diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -1,112 +1,116 @@ Makefile$ Makefile\.in$ \.deps$ \.libs$ \.l[ao]$ \.so$ \.so\. \.o$ ~$ \.pyc$ \.codereplace$ \.orig$ \.tar\.(gz|bz2)$ ^autom4te.cache$ ^config.herwig$ ^config.log$ ^config.status$ ^configure$ ^include/Herwig$ ^Config/config.guess$ ^Config/config.h$ ^Config/config.h.in$ ^Config/config.sub$ ^Config/depcomp$ ^Config/compile$ ^Config/install-sh$ ^Config/missing$ ^Config/stamp-h1$ ^Config/ar-lib$ ^Contrib/make_makefiles.sh$ ^Contrib/.*/.*\.(log|out|tex|run)$ ^Utilities/hgstamp.inc$ ^Doc/HerwigDefaults.in$ ^Doc/refman-html$ ^Doc/fixinterfaces.pl$ ^Doc/refman.conf$ ^Doc/refman.h$ ^Doc/AllInterfaces.h$ ^Doc/HerwigDefaults.rpo$ ^Doc/Herwig-refman.tag$ ^Doc/tagfileThePEG.tag$ ^Doc/.*\.log$ ^INSTALL$ ^aclocal.m4$ ^confdefs.h$ ^conftest.c$ ^conftest.err$ ^include/done-all-links$ ^libtool$ \.dirstamp$ ^src/hgstamp.inc$ ^src/herwigopts.h$ ^src/herwigopts.c$ ^src/defaults/Analysis.in$ ^src/defaults/Decays.in$ ^src/defaults/decayers.in$ ^src/herwig-config$ ^src/.*\.(run|tex|out|log|rpo|spc|top|dump|dot|aux|pdf|ps|png|svg|hepmc|dvi)$ ^src/Makefile-UserModules$ ^lib/done-all-links$ ^lib/apple-fixes$ ^src/defaults/PDF.in$ ^src/defaults/done-all-links$ ^src/tune$ ^src/Herwig$ ^src/Herwig-cache$ ^src/tests/.*\.(time|mult|Bmult|chisq)$ ^src/Merging/test/*yoda ^src/Merging/test/Herwig* ^src/Merging/test/L* ^src/Merging/test/done-all-links ^src/Merging/done-all-links ^Tests/.*/.*\.(top|ps|pyc|info|dat|pdf|png)$ ^Tests/.*\.(top|ps|pyc|info|dat|pdf|png|log|out)$ ^Tests/.*\.(top|run|tex|mult|Bmult|aida|yoda)$ ^Tests/Rivet-.*$ ^Tests/.cache$ ^Tests/Rivet/(LEP|DIS|LHC|TVT|Star|BFactory|ISR|SppS)-.*\.in$ ^Tests/plots$ ^Tests/Herwig$ ^Tests/.*index.html$ +PDF/SaSPhotonPDF.cc ^Herwig\- ^Models/Feynrules/python/Makefile-FR$ ^MatrixElement/Matchbox/External/MadGraph/mg2herwig$ ^MatrixElement/Matchbox/Scales/MatchboxScale.cc$ ^Utilities/Statistics/herwig-combinedistributions$ ^Utilities/Statistics/herwig-combineruns$ ^Utilities/Statistics/herwig-makedistributions$ ^src/defaults/MatchboxDefaults.in$ ^src/defaults/setup.gosam.in$ ^src/Matchbox/LO-DefaultShower.in$ ^src/Matchbox/LO-DipoleShower.in$ ^src/Matchbox/LO-NoShower.in$ ^src/Matchbox/MCatLO-DefaultShower.in$ ^src/Matchbox/MCatLO-DipoleShower.in$ ^src/Matchbox/MCatNLO-DefaultShower.in$ ^src/Matchbox/MCatNLO-DipoleShower.in$ ^src/Matchbox/NLO-NoShower.in$ ^src/Matchbox/Powheg-DefaultShower.in$ ^src/Matchbox/Powheg-DipoleShower.in$ ^src/defaults/MatchboxMergingDefaults.in ^src/Matchbox/done-all-links$ ^src/snippets/done-all-links$ ^Utilities/XML/xml_test$ ^Utilities/utilities_test$ ^Utilities/versionstring.h$ +^MatrixElement/Matchbox/External/MadGraph/mg2herwig.py$ test\.(log|trs)$ test-suite\.log$ ^Config/test-driver$ param_card\.dat$ __all.cc$ .ccR$ +^tmp/* +PDF/stamp-h2 diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -1,26 +1,27 @@ 168ae2110e964d62fbc1331a1c2e095952a67748 release-2-5-2 3abb4fa42e20e332796c2572334c2d77204cd0e0 release-2-4-2 4796ca080aafd5daa3b7349b015cb1df944428a2 release-2-5-0 76da042f056eb153981b4d005d5474ffb90a5e88 release-2-4-1 81a684a558413c69df314365eabf09893ffd43d8 release-2-6-0 bd75cd00d99f4bdbaed992daf98f0a73c0f91e9b release-2-4-0 ff6ecc8d49ce10299303b050394bd5cb5837f1c3 release-2-5-1 d0389f5453b2c210923e1adc7b872b18269de668 release-2-6-1 f8998033021185942533b824607285feb3fbd2dc release-2-6-1a cead23e428b9aacaf2d709e722624e54f844498b release-2-6-1b 191db4655439045f912cb21bd905e729d59ec7bc release-2-6-2 edb538156e9c3d64bb842934b4cebf0126aeb9ea release-2-6-3 eb4a104591859ecac18746b1ad54d6aa0c2a5d1a release-2-7-0 568971ac5b3c1d044c9259f2280a8304fc5a62e9 trunk-before-QED 6e3edb6cfeb4ee48687eb4eb3d016026fc59d602 trunk-after-QED 633abb80b571aa23088957df60e9b0000bbb8a22 release-2-7-1 1bdde095d2346c15ee548e5406a96f0fc6d6e0f1 beforeHQ a0f9fb821396092bdbeee532bcb0bd624f58335b before_MB_merge 270c1e6b34aa7f758f1d9868c4d3e1ec4bf4e709 herwig-7-0-0 6e0f198c1c2603ecd1a0b6cfe40105cda4bd58c5 herwig-7-0-1 566c1de845a8070559cda45b1bdb40afa18cb2cc herwig-7-0-2 f5c4aa956880f2def763ebd57de7b5bfa55cb1db herwig-7-0-3 65282dedfc2e4bec184e68678dbf4c553c968f38 herwig-7-0-4 541e7790b65ed423c86780bf66ec30e6b99b5a18 herwig-7-1-0 dd35a1c12d57c047169e8c5fb18644972d49c6ac herwig-7-1-1 0d651b079756b63713e32a1341d81e4dfc7eeb7b herwig-7-1-2 +4b97934bc41c861c4be04f563ffa68a94a982560 herwig-7-1-3 diff --git a/AUTHORS b/AUTHORS --- a/AUTHORS +++ b/AUTHORS @@ -1,56 +1,56 @@ ================================================================================ -Herwig 7.1.2 +Herwig 7.1.3 ================================================================================ Please contact for any queries. -------------------------------------------------------------------------------- Herwig is actively developed by: -------------------------------------------------------------------------------- Johannes Bellm Stefan Gieseke David Grellscheid Patrick Kirchgaeßer -Frashër Loshaj Graeme Nail Andreas Papaefstathiou Simon Plätzer Radek Podskubka Michael Rauch Christian Reuschle Peter Richardson -Peter Schichtel Mike Seymour Andrzej Siödmok Stephen Webster -------------------------------------------------------------------------------- Former authors are: -------------------------------------------------------------------------------- Ken Arnold Manuel Bähr Luca d'Errico Martyn Gigg Nadine Fischer Keith Hamilton Marco A. Harrendorf Seyi Latunde-Dada +Frashër Loshaj Daniel Rauch Alberto Ribon Christian Röhr Pavel Růžička +Peter Schichtel Alex Schofield Thomas Schuh Alexander Sherstnev Philip Stephens Martin Stoll Louise Suter Jon Tully Bryan Webber Alix Wilcock David Winn Benedikt Zimmermann diff --git a/Decay/DecayPhaseSpaceChannel.cc b/Decay/DecayPhaseSpaceChannel.cc --- a/Decay/DecayPhaseSpaceChannel.cc +++ b/Decay/DecayPhaseSpaceChannel.cc @@ -1,603 +1,603 @@ // -*- C++ -*- // // DecayPhaseSpaceChannel.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 DecayPhaseSpaceChannel class. // // Author: Peter Richardson // #include "DecayPhaseSpaceChannel.h" #include "ThePEG/Utilities/DescribeClass.h" #include "DecayPhaseSpaceMode.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Repository/CurrentGenerator.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/ParVector.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Switch.h" #include using namespace Herwig; DecayPhaseSpaceChannel::DecayPhaseSpaceChannel(tcDecayPhaseSpaceModePtr in) : _mode(in) {} void DecayPhaseSpaceChannel::persistentOutput(PersistentOStream & os) const { os << _intpart << _jactype << ounit(_intmass,GeV) << ounit(_intwidth,GeV) << ounit(_intmass2,GeV2) << ounit(_intmwidth,GeV2) << _intpower << _intdau1 << _intdau2 << _intext << _mode; } void DecayPhaseSpaceChannel::persistentInput(PersistentIStream & is, int) { is >> _intpart >> _jactype >> iunit(_intmass,GeV) >> iunit(_intwidth,GeV) >> iunit(_intmass2,GeV2) >> iunit(_intmwidth,GeV2) >> _intpower >> _intdau1 >> _intdau2 >> _intext >> _mode; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigDecayPhaseSpaceChannel("Herwig::DecayPhaseSpaceChannel", "Herwig.so"); void DecayPhaseSpaceChannel::Init() { static RefVector interfaceIntermediateParticles ("IntermediateParticles", "The intermediate particles in the decay chain.", &DecayPhaseSpaceChannel::_intpart, 0, false, false, true, false); static ParVector interfacejactype ("Jacobian", "The type of Jacobian to use for the intermediate particle", &DecayPhaseSpaceChannel::_jactype, 0, 0, 0, 0, 1, false, false, true); static ParVector interfaceIntermediatePower ("IntermediatePower", "The power to use in the Jacobian", &DecayPhaseSpaceChannel::_intpower, 0, 0, 0, -10, 10, false, false, true); static ParVector interfaceIntermediateDau1 ("IntermediateDaughter1", "First Daughter of the intermediate", &DecayPhaseSpaceChannel::_intdau1, 0, 0, 0, -10, 10, false, false, true); static ParVector interfaceIntermediateDau2 ("IntermediateDaughter2", "Second Daughter of the intermediate", &DecayPhaseSpaceChannel::_intdau2, 0, 0, 0, -10, 10, false, false, true); static ClassDocumentation documentation ("The DecayPhaseSpaceChannel class defines a channel" " for the multichannel integration of the phase space for a decay."); } // generate the momenta of the external particles vector DecayPhaseSpaceChannel::generateMomenta(const Lorentz5Momentum & pin, const vector & massext) { // integers for loops unsigned int ix,iy,idau[2],iz; // storage of the momenta of the external particles vector pexternal; // and the internal particles vector pinter; // copy the momentum of the incoming particle pexternal.push_back(pin); pinter.push_back(pin); pexternal.resize(_mode->numberofParticles()); pinter.resize(_intpart.size()); // masses of the intermediate particles vector massint(_intpart.size()); massint[0]=pin.mass(); // generate all the decays in the chain Energy lower,upper,lowerb[2]; for(ix=0;ix<_intpart.size();++ix) { idau[0] = abs(_intdau1[ix]); idau[1] = abs(_intdau2[ix]); // if both decay products off-shell if(_intdau1[ix]<0&&_intdau2[ix]<0) { // lower limits on the masses of the two resonances for(iy=0;iy<2;++iy) { lowerb[iy]=ZERO; for(iz=0;iz<_intext[idau[iy]].size();++iz) { lowerb[iy]+=massext[_intext[idau[iy]][iz]]; } } // randomize the order if(UseRandom::rnd()<0.5) { // mass of the first resonance upper = massint[ix]-lowerb[1]; lower = lowerb[0]; massint[idau[0]]=generateMass(idau[0],lower,upper); // mass of the second resonance upper = massint[ix]-massint[idau[0]]; lower = lowerb[1]; massint[idau[1]]=generateMass(idau[1],lower,upper); } else { // mass of the second resonance upper = massint[ix]-lowerb[0]; lower = lowerb[1]; massint[idau[1]]=generateMass(idau[1],lower,upper); // mass of the first resonance upper = massint[ix]-massint[idau[1]]; lower = lowerb[0]; massint[idau[0]]=generateMass(idau[0],lower,upper); } // generate the momenta of the decay products twoBodyDecay(pinter[ix],massint[idau[0]],massint[idau[1]], pinter[idau[0]],pinter[idau[1]]); } // only first off-shell else if(_intdau1[ix]<0) { // compute the limits of integration upper = massint[ix]-massext[idau[1]]; lower = ZERO; for(iy=0;iy<_intext[idau[0]].size();++iy) { lower+=massext[_intext[idau[0]][iy]]; } massint[idau[0]]=generateMass(idau[0],lower,upper); // generate the momenta of the decay products twoBodyDecay(pinter[ix],massint[idau[0]],massext[idau[1]], pinter[idau[0]],pexternal[idau[1]]); } // only second off-shell else if(_intdau2[ix]<0) { // compute the limits of integration upper = massint[ix]-massext[idau[0]]; lower = ZERO; for(iy=0;iy<_intext[idau[1]].size();++iy) { lower+=massext[_intext[idau[1]][iy]]; } massint[idau[1]]=generateMass(idau[1],lower,upper); // generate the momenta of the decay products twoBodyDecay(pinter[ix],massext[idau[0]],massint[idau[1]], pexternal[idau[0]],pinter[idau[1]]); } // both on-shell else { // generate the momenta of the decay products twoBodyDecay(pinter[ix],massext[idau[0]],massext[idau[1]], pexternal[idau[0]],pexternal[idau[1]]); } } // return the external momenta return pexternal; } // generate the weight for this channel given a phase space configuration double DecayPhaseSpaceChannel::generateWeight(const vector & output) { using Constants::pi; // integers for loops unsigned int ix,iy,idau[2],iz; // include the prefactor due to the weight of the channel double wgt=1.; // work out the masses of the intermediate particles static vector intmass; intmass.clear(); Lorentz5Momentum pinter; for(ix=0;ix<_intpart.size();++ix) { pinter=output[_intext[ix][0]]; for(iz=1;iz<_intext[ix].size();++iz) pinter+=output[_intext[ix][iz]]; pinter.rescaleMass(); intmass.push_back( pinter.mass() ); } Energy2 scale(sqr(intmass[0])); // calculate the terms for each of the decays Energy lower,upper,lowerb[2]; for(ix=0;ix<_intpart.size();++ix) { idau[0] = abs(_intdau1[ix]); idau[1] = abs(_intdau2[ix]); // if both decay products off-shell Energy pcm; if(_intdau1[ix]<0&&_intdau2[ix]<0) { // lower limits on the masses of the two resonances for(iy=0;iy<2;++iy) { lowerb[iy]=ZERO; for(iz=0;iz<_intext[idau[iy]].size();++iz) lowerb[iy]+=output[_intext[idau[iy]][iz]].mass(); } // undo effect of randomising // weight for the first order // contribution of first resonance upper = intmass[ix]-lowerb[1]; lower = lowerb[0]; InvEnergy2 wgta=massWeight(idau[0],intmass[idau[0]],lower,upper); // contribution of second resonance upper = intmass[ix]-intmass[idau[0]]; lower = lowerb[1]; InvEnergy4 wgta2 = wgta*massWeight(idau[1],intmass[idau[1]],lower,upper); // weight for the second order upper = intmass[ix]-lowerb[0]; lower = lowerb[1]; InvEnergy2 wgtb=massWeight(idau[1],intmass[idau[1]],lower,upper); upper = intmass[ix]-intmass[idau[1]]; lower = lowerb[0]; InvEnergy4 wgtb2=wgtb*massWeight(idau[0],intmass[idau[0]],lower,upper); // weight factor wgt *=0.5*sqr(scale)*(wgta2+wgtb2); // factor for the kinematics pcm = Kinematics::pstarTwoBodyDecay(intmass[ix],intmass[idau[0]], intmass[idau[1]]); - if(pcm!=ZERO) + if(pcm>ZERO) wgt *= intmass[ix]*8.*pi*pi/pcm; else wgt = 0.; } // only first off-shell else if(_intdau1[ix]<0) { // compute the limits of integration upper = intmass[ix]-output[idau[1]].mass(); lower = ZERO; for(iy=0;iy<_intext[idau[0]].size();++iy) lower+=output[_intext[idau[0]][iy]].mass(); wgt *=scale*massWeight(idau[0],intmass[idau[0]],lower,upper); pcm = Kinematics::pstarTwoBodyDecay(intmass[ix],intmass[idau[0]], - output[idau[1]].mass()); - if(pcm!=ZERO) + output[idau[1]].mass()); + if(pcm>ZERO) wgt *= intmass[ix]*8.*pi*pi/pcm; else wgt = 0.; } // only second off-shell else if(_intdau2[ix]<0) { // compute the limits of integration upper = intmass[ix]-output[idau[0]].mass(); lower = ZERO; for(iy=0;iy<_intext[idau[1]].size();++iy) lower+=output[_intext[idau[1]][iy]].mass(); wgt *=scale*massWeight(idau[1],intmass[idau[1]],lower,upper); pcm = Kinematics::pstarTwoBodyDecay(intmass[ix],intmass[idau[1]], - output[idau[0]].mass()); - if(pcm!=ZERO) + output[idau[0]].mass()); + if(pcm>ZERO) wgt *=intmass[ix]*8.*pi*pi/pcm; else - wgt = 0.; + wgt=0.; } // both on-shell else { pcm = Kinematics::pstarTwoBodyDecay(intmass[ix],output[idau[1]].mass(), output[idau[0]].mass()); - if(pcm!=ZERO) + if(pcm>ZERO) wgt *=intmass[ix]*8.*pi*pi/pcm; else wgt = 0.; } } // finally the overall factor wgt /= pi; // return the answer return wgt; } // output the information to a stream ostream & Herwig::operator<<(ostream & os, const DecayPhaseSpaceChannel & channel) { // output of the external particles os << "Channel for the decay of " << channel._mode->externalParticles(0)->PDGName() << " -> "; for(unsigned int ix=1;ixnumberofParticles();++ix) os << channel._mode->externalParticles(ix)->PDGName() << " "; os << endl; os << "Decay proceeds in following steps "; for(unsigned int ix=0;ixPDGName() << " -> "; if(channel._intdau1[ix]>0) { os << channel._mode->externalParticles(channel._intdau1[ix])->PDGName() << "(" << channel._intdau1[ix]<< ") "; } else { os << channel._intpart[-channel._intdau1[ix]]->PDGName() << "(" << channel._intdau1[ix]<< ") "; } if(channel._intdau2[ix]>0) { os << channel._mode->externalParticles(channel._intdau2[ix])->PDGName() << "(" <PDGName() << "(" <mass()); _intwidth.push_back(_intpart[ix]->width()); _intmass2.push_back(_intpart[ix]->mass()*_intpart[ix]->mass()); _intmwidth.push_back(_intpart[ix]->mass()*_intpart[ix]->width()); } // external particles for each intermediate particle vector temp; _intext.resize(_intpart.size()); // loop over the intermediate particles for(int ix=_intpart.size()-1;ix>=0;--ix) { temp.clear(); // add the first daughter if(_intdau1[ix]>=0) { temp.push_back(_intdau1[ix]); } else { int iy = -_intdau1[ix]; vector::iterator istart=_intext[iy].begin(); vector::iterator iend=_intext[iy].end(); for(;istart!=iend;++istart) temp.push_back(*istart); } // add the second daughter if(_intdau2[ix]>=0) { temp.push_back(_intdau2[ix]); } else { int iy = -_intdau2[ix]; vector::iterator istart=_intext[iy].begin(); vector::iterator iend=_intext[iy].end(); for(;istart!=iend;++istart) temp.push_back(*istart); } _intext[ix]=temp; } // ensure intermediates either have the width set, or // can't possibly be on-shell Energy massmax; if(_mode->testOnShell()) { massmax = _mode->externalParticles(0)->mass(); for(unsigned int ix=1;ix<_mode->numberofParticles();++ix) massmax -= _mode->externalParticles(ix)->mass(); } else { massmax = _mode->externalParticles(0)->massMax(); for(unsigned int ix=1;ix<_mode->numberofParticles();++ix) massmax -= _mode->externalParticles(ix)->massMin(); } for(unsigned int ix=0;ix<_intpart.size();++ix) { if(_intwidth[ix]==ZERO && ix>0 && _jactype[ix]==0 ) { Energy massmin(ZERO); for(unsigned int iy=0;iy<_intext[ix].size();++iy) massmin += _mode->testOnShell() ? _mode->externalParticles(_intext[ix][iy])->mass() : _mode->externalParticles(_intext[ix][iy])->massMin(); // check if can be on-shell if(_intmass[ix]>=massmin&&_intmass[ix]<=massmax+massmin) { string modeout; for(unsigned int iy=0;iy<_mode->numberofParticles();++iy) { modeout += _mode->externalParticles(iy)->PDGName() + " "; } throw InitException() << "Width zero for " << _intpart[ix]->PDGName() << " in DecayPhaseSpaceChannel::doinit() " << modeout << Exception::runerror; } } } } void DecayPhaseSpaceChannel::doinitrun() { Interfaced::doinitrun(); if(!_mode->testOnShell()) return; _intmass.clear(); _intwidth.clear(); _intmass2.clear(); _intmwidth.clear(); // masses and widths of the intermediate particles for(unsigned int ix=0;ix<_intpart.size();++ix) { _intmass.push_back(_intpart[ix]->mass()); _intwidth.push_back(_intpart[ix]->width()); _intmass2.push_back(_intpart[ix]->mass()*_intpart[ix]->mass()); _intmwidth.push_back(_intpart[ix]->mass()*_intpart[ix]->width()); } // ensure intermediates either have the width set, or // can't possibly be on-shell Energy massmax = _mode->externalParticles(0)->massMax(); for(unsigned int ix=1;ix<_mode->numberofParticles();++ix) massmax -= _mode->externalParticles(ix)->massMin(); for(unsigned int ix=0;ix<_intpart.size();++ix) { if(_intwidth[ix]==0.*MeV && ix>0 && _jactype[ix]==0 ) { Energy massmin(0.*GeV); for(unsigned int iy=0;iy<_intext[ix].size();++iy) massmin += _mode->externalParticles(_intext[ix][iy])->massMin(); // check if can be on-shell if(_intmass[ix]>=massmin&&_intmass[ix]<=massmax+massmin) { string modeout; for(unsigned int iy=0;iy<_mode->numberofParticles();++iy) { modeout += _mode->externalParticles(iy)->PDGName() + " "; } throw Exception() << "Width zero for " << _intpart[ix]->PDGName() << " in DecayPhaseSpaceChannel::doinitrun() " << modeout << Exception::runerror; } } } } // generate the final-state particles including the intermediate resonances void DecayPhaseSpaceChannel::generateIntermediates(bool cc, const Particle & in, ParticleVector & out) { // integers for the loops unsigned int ix,iz; // create the particles // incoming particle ParticleVector external; external.push_back(const_ptr_cast(&in)); // outgoing for(ix=0;ixmomentum(); for(iz=1;iz<_intext[ix].size();++iz) pinter+=external[_intext[ix][iz]]->momentum(); pinter.rescaleMass(); respart = (cc&&_intpart[ix]->CC()) ? _intpart[ix]->CC()->produceParticle(pinter) : _intpart[ix] ->produceParticle(pinter); resonance.push_back(respart); } // set up the mother daughter relations for(ix=1;ix<_intpart.size();++ix) { resonance[ix]->addChild( _intdau1[ix]<0 ? resonance[-_intdau1[ix]] : external[_intdau1[ix]]); resonance[ix]->addChild( _intdau2[ix]<0 ? resonance[-_intdau2[ix]] : external[_intdau2[ix]]); if(resonance[ix]->dataPtr()->stable()) resonance[ix]->setLifeLength(Lorentz5Distance()); } // construct the output with the particles in the first step out.push_back( _intdau1[0]>0 ? external[_intdau1[0]] : resonance[-_intdau1[0]]); out.push_back( _intdau2[0]>0 ? external[_intdau2[0]] : resonance[-_intdau2[0]]); } double DecayPhaseSpaceChannel::atanhelper_(int ires, Energy limit) { return atan2( limit*limit-_intmass2[ires], _intmwidth[ires] ); } // return the weight for a given resonance InvEnergy2 DecayPhaseSpaceChannel::massWeight(int ires, Energy moff, Energy lower,Energy upper) { InvEnergy2 wgt = ZERO; if(lower>upper) { throw DecayPhaseSpaceError() << "DecayPhaseSpaceChannel::massWeight not allowed " << ires << " " << _intpart[ires]->id() << " " << moff/GeV << " " << lower/GeV << " " << upper/GeV << Exception::eventerror; } // use a Breit-Wigner if ( _jactype[ires] == 0 ) { double rhomin = atanhelper_(ires,lower); double rhomax = atanhelper_(ires,upper) - rhomin; if ( rhomax != 0.0 ) { Energy2 moff2=moff*moff-_intmass2[ires]; wgt = _intmwidth[ires]/rhomax/(moff2*moff2+_intmwidth[ires]*_intmwidth[ires]); } else { wgt = 1./((sqr(upper)-sqr(lower))*sqr(sqr(moff)-_intmass2[ires])/ (sqr(lower)-_intmass2[ires])/(sqr(upper)-_intmass2[ires])); } } // power law else if(_jactype[ires]==1) { double rhomin = pow(sqr(lower/MeV),_intpower[ires]+1.); double rhomax = pow(sqr(upper/MeV),_intpower[ires]+1.)-rhomin; wgt = (_intpower[ires]+1.)/rhomax*pow(sqr(moff/MeV),_intpower[ires]) /MeV/MeV; } else if(_jactype[ires]==2) { wgt = 1./Constants::pi/_intmwidth[ires]; } else { throw DecayPhaseSpaceError() << "Unknown type of Jacobian in " << "DecayPhaseSpaceChannel::massWeight" << Exception::eventerror; } return wgt; } Energy DecayPhaseSpaceChannel::generateMass(int ires,Energy lower,Energy upper) { static const Energy eps=1e-9*MeV; if(lowerupper) throw DecayPhaseSpaceError() << "DecayPhaseSpaceChannel::generateMass" << " not allowed" << Exception::eventerror; if(abs(lower-upper)/(lower+upper)>2e-10) { lower +=1e-10*(lower+upper); upper -=1e-10*(lower+upper); } else return 0.5*(lower+upper); // use a Breit-Wigner if(_jactype[ires]==0) { if(_intmwidth[ires]!=ZERO) { Energy2 lower2 = sqr(lower); Energy2 upper2 = sqr(upper); double rhomin = atan2((lower2 - _intmass2[ires]),_intmwidth[ires]); double rhomax = atan2((upper2 - _intmass2[ires]),_intmwidth[ires])-rhomin; double rho = rhomin+rhomax*UseRandom::rnd(); Energy2 mass2 = max(lower2,min(upper2,_intmass2[ires]+_intmwidth[ires]*tan(rho))); if(mass2upper-1e-10*(lower+upper)) mass=upper-1e-10*(lower+upper); return mass; } void DecayPhaseSpaceChannel::twoBodyDecay(const Lorentz5Momentum & p, const Energy m1, const Energy m2, Lorentz5Momentum & p1, Lorentz5Momentum & p2 ) { static const double eps=1e-6; double ctheta,phi; Kinematics::generateAngles(ctheta,phi); Axis unitDir1=Kinematics::unitDirection(ctheta,phi); Momentum3 pstarVector; Energy min=p.mass(); if ( min >= m1 + m2 && m1 >= ZERO && m2 >= ZERO ) { pstarVector = unitDir1 * Kinematics::pstarTwoBodyDecay(min,m1,m2); } else if( m1 >= ZERO && m2 >= ZERO && (m1+m2-min)/(min+m1+m2) " << m1/GeV << ' ' << m2/GeV << Exception::eventerror; } p1 = Lorentz5Momentum(m1, pstarVector); p2 = Lorentz5Momentum(m2,-pstarVector); // boost from CM to LAB Boost bv = p.boostVector(); double gammarest = p.e()/p.mass(); p1.boost( bv , gammarest ); p2.boost( bv , gammarest ); } diff --git a/Decay/DecayPhaseSpaceMode.cc b/Decay/DecayPhaseSpaceMode.cc --- a/Decay/DecayPhaseSpaceMode.cc +++ b/Decay/DecayPhaseSpaceMode.cc @@ -1,529 +1,531 @@ // -*- C++ -*- // // DecayPhaseSpaceMode.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 DecayPhaseSpaceMode class. // #include "DecayPhaseSpaceMode.h" #include "ThePEG/Utilities/DescribeClass.h" #include "Herwig/PDT/GenericWidthGenerator.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/RefVector.h" #include "DecayIntegrator.h" #include "Herwig/Utilities/Kinematics.h" #include "ThePEG/EventRecord/HelicityVertex.h" #include "Herwig/Decay/DecayVertex.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/EventRecord/Event.h" #include "ThePEG/Utilities/Debug.h" using namespace Herwig; using namespace ThePEG::Helicity; void DecayPhaseSpaceMode::persistentOutput(PersistentOStream & os) const { os << _integrator << _channels << _channelwgts << _maxweight << _niter << _npoint << _ntry << _extpart << _partial << _widthgen << _massgen << _testOnShell; } void DecayPhaseSpaceMode::persistentInput(PersistentIStream & is, int) { is >> _integrator >> _channels >> _channelwgts >> _maxweight >> _niter >> _npoint >> _ntry >> _extpart >> _partial >> _widthgen >> _massgen >> _testOnShell; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigDecayPhaseSpaceMode("Herwig::DecayPhaseSpaceMode", "Herwig.so"); void DecayPhaseSpaceMode::Init() { static ClassDocumentation documentation ("The DecayPhaseSpaceMode class contains a number of phase space" " channels for the integration of a particular decay mode"); static RefVector interfaceChannels ("Channels", "The phase space integration channels.", &DecayPhaseSpaceMode::_channels, 0, false, false, true, true); } // flat phase space generation and weight Energy DecayPhaseSpaceMode::flatPhaseSpace(bool cc, const Particle & inpart, ParticleVector & outpart, bool onShell) const { double wgt(1.); if(outpart.empty()) { outpart.reserve(_extpart.size()-1); for(unsigned int ix=1;ix<_extpart.size();++ix) { if(cc&&_extpart[ix]->CC()) { outpart.push_back((_extpart[ix]->CC())->produceParticle()); } else { outpart.push_back(_extpart[ix]->produceParticle()); } } } // masses of the particles Energy inmass(inpart.mass()); vector mass = externalMasses(inmass,wgt,onShell); // momenta of the particles vector part(outpart.size()); // two body decay assert(outpart.size()==2); double ctheta,phi; Kinematics::generateAngles(ctheta,phi); if(! Kinematics::twoBodyDecay(inpart.momentum(), mass[1], mass[2], ctheta, phi,part[0],part[1])) throw Exception() << "Incoming mass - Outgoing mass negative in " << "DecayPhaseSpaceMode::flatPhaseSpace()" << Exception::eventerror; wgt *= Kinematics::pstarTwoBodyDecay(inmass,mass[1],mass[2])/8./Constants::pi/inmass; outpart[0]->set5Momentum(part[0]); outpart[1]->set5Momentum(part[1]); return wgt*inmass; } // initialise the phase space Energy DecayPhaseSpaceMode::initializePhaseSpace(bool init, bool onShell) { Energy output(ZERO); // ensure that the weights add up to one if(!_channels.empty()) { double temp=0.; for(unsigned int ix=0;ix<_channels.size();++ix) temp+=_channelwgts[ix]; for(unsigned int ix=0;ix<_channels.size();++ix) _channelwgts[ix]/=temp; } if(!init) return ZERO; // create a particle vector from the particle data one ThePEG::PPtr inpart=_extpart[0]->produceParticle(); ParticleVector particles; // now if using flat phase space _maxweight=0.; double totsum(0.),totsq(0.); InvEnergy pre=1./MeV; Energy prewid; if(_channels.empty()) { double wsum=0.,wsqsum=0.; Energy m0,mmin(ZERO); for(unsigned int ix=1;ix<_extpart.size();++ix) { mmin+=_extpart[ix]->massMin(); } for(int ix=0;ix<_npoint;++ix) { // set the mass of the decaying particle m0 = !onShell ? inpart->dataPtr()->generateMass() : inpart->dataPtr()->mass(); double wgt=0.; if(m0>mmin) { inpart->set5Momentum(Lorentz5Momentum(m0)); // compute the prefactor prewid = (_widthgen&&_partial>=0) ? _widthgen->partialWidth(_partial,inpart->mass()) : inpart->dataPtr()->width(); pre = prewid>ZERO ? 1./prewid : 1./MeV; // generate the weight for this point try { int dummy; wgt = pre*weight(false,dummy,*inpart,particles,true,onShell); } catch (Veto) { wgt=0.; } } if(wgt>_maxweight) _maxweight=wgt; wsum += wgt; wsqsum += sqr(wgt); } wsum=wsum/_npoint; wsqsum=wsqsum/_npoint-sqr(wsum); if(wsqsum<0.) wsqsum=0.; wsqsum=sqrt(wsqsum/_npoint); Energy fact = (_widthgen&&_partial>=0) ? _widthgen->partialWidth(_partial,inpart->nominalMass()) : inpart->dataPtr()->width(); if(fact==ZERO) fact=MeV; // factor for the weight with spin correlations _maxweight *= inpart->dataPtr()->iSpin()==1 ? 1.1 : 1.6; if ( Debug::level > 1 ) { // ouptut the information on the initialisation CurrentGenerator::log() << "Initialized the phase space for the decay " << _extpart[0]->PDGName() << " -> "; for(unsigned int ix=1,N=_extpart.size();ixPDGName() << " "; CurrentGenerator::log() << "\n"; if(fact!=MeV) CurrentGenerator::log() << "The branching ratio is " << wsum << " +/- " << wsqsum << "\n"; CurrentGenerator::log() << "The partial width is " << wsum*fact/MeV << " +/- " << wsqsum*fact/MeV << " MeV\n"; CurrentGenerator::log() << "The partial width is " << wsum*fact/6.58212E-22/MeV << " +/- " << wsqsum*fact/6.58212E-22/MeV<< " s-1\n"; CurrentGenerator::log() << "The maximum weight is " << _maxweight << endl; } output=wsum*fact; } else { for(int iy=0;iy<_niter;++iy) { // zero the maximum weight _maxweight=0.; vector wsum(_channels.size(),0.),wsqsum(_channels.size(),0.); vector nchan(_channels.size(),0); totsum = 0.; totsq = 0.; Energy m0,mmin(ZERO); for(unsigned int ix=1;ix<_extpart.size();++ix) { mmin+=_extpart[ix]->massMin(); } for(int ix=0;ix<_npoint;++ix) { m0 = !onShell ? inpart->dataPtr()->generateMass() : inpart->dataPtr()->mass(); double wgt=0.; int ichan(-1); if(m0>mmin) { inpart->set5Momentum(Lorentz5Momentum(m0)); // compute the prefactor prewid= (_widthgen&&_partial>=0) ? _widthgen->partialWidth(_partial,inpart->mass()) : inpart->dataPtr()->width(); pre = prewid>ZERO ? 1./prewid : 1./MeV; // generate the weight for this point try { wgt = pre*weight(false,ichan,*inpart,particles,true,onShell); } catch (Veto) { wgt=0.; } } if(wgt>_maxweight) _maxweight=wgt; if(ichan>=0) { wsum[ichan] += wgt; wsqsum[ichan] += sqr(wgt); ++nchan[ichan]; } totsum+=wgt; totsq+=wgt*wgt; } totsum=totsum/_npoint; totsq=totsq/_npoint-sqr(totsum); if(totsq<0.) totsq=0.; totsq=sqrt(totsq/_npoint); if ( Debug::level > 1 ) CurrentGenerator::log() << "The branching ratio is " << iy << " " << totsum << " +/- " << totsq << _maxweight << "\n"; // compute the individual terms double total(0.); for(unsigned int ix=0;ix<_channels.size();++ix) { if(nchan[ix]!=0) { wsum[ix]=wsum[ix]/nchan[ix]; wsqsum[ix]=wsqsum[ix]/nchan[ix]; if(wsqsum[ix]<0.) wsqsum[ix]=0.; wsqsum[ix]=sqrt(wsqsum[ix]/nchan[ix]); } else { wsum[ix]=0; wsqsum[ix]=0; } total+=sqrt(wsqsum[ix])*_channelwgts[ix]; } if(total>0.) { double temp; for(unsigned int ix=0;ix<_channels.size();++ix) { temp=sqrt(wsqsum[ix])*_channelwgts[ix]/total; _channelwgts[ix]=temp; } } } // factor for the weight with spin correlations _maxweight*= inpart->dataPtr()->iSpin()==1 ? 1.1 : 1.6; // ouptut the information on the initialisation Energy fact = (_widthgen&&_partial>=0) ? _widthgen->partialWidth(_partial,inpart->nominalMass()) : inpart->dataPtr()->width(); if(fact==ZERO) fact=MeV; if ( Debug::level > 1 ) { CurrentGenerator::log() << "Initialized the phase space for the decay " << _extpart[0]->PDGName() << " -> "; for(unsigned int ix=1,N=_extpart.size();ixPDGName() << " "; CurrentGenerator::log() << "\n"; if(fact!=MeV) CurrentGenerator::log() << "The branching ratio is " << totsum << " +/- " << totsq << "\n"; CurrentGenerator::log() << "The partial width is " << totsum*fact/MeV << " +/- " << totsq*fact/MeV << " MeV\n"; CurrentGenerator::log() << "The partial width is " << totsum*fact/6.58212E-22/MeV << " +/- " << totsq*fact/6.58212E-22/MeV << " s-1\n"; CurrentGenerator::log() << "The maximum weight is " << _maxweight << "\n"; CurrentGenerator::log() << "The weights for the different phase" << " space channels are \n"; for(unsigned int ix=0,N=_channels.size();ix momenta; double wgt(UseRandom::rnd()); // select a channel ichan=-1; do{++ichan;wgt-=_channelwgts[ichan];} while(ichan0.); // generate the momenta if(ichan==int(_channels.size())) { throw DecayIntegratorError() << "DecayPhaseSpaceMode::channelPhaseSpace()" << " failed to select a channel" << Exception::abortnow; } // generate the masses of the external particles double masswgt(1.); vector mass(externalMasses(inpart.mass(),masswgt,onShell)); momenta=_channels[ichan]->generateMomenta(inpart.momentum(),mass); // compute the denominator of the weight wgt=0.; unsigned int ix; for(ix=0;ix<_channels.size();++ix) { wgt+=_channelwgts[ix]*_channels[ix]->generateWeight(momenta); } // now we need to set the momenta of the particles // create the particles if they don't exist if(outpart.empty()) { for(ix=1;ix<_extpart.size();++ix) { if(cc&&_extpart[ix]->CC()) { outpart.push_back((_extpart[ix]->CC())->produceParticle()); } else { outpart.push_back(_extpart[ix]->produceParticle()); } } } // set up the momenta for(ix=0;ixset5Momentum(momenta[ix+1]); // return the weight return wgt!=0. ? inpart.mass()*masswgt/wgt : ZERO; } // generate the decay ParticleVector DecayPhaseSpaceMode::generate(bool intermediates,bool cc, const Particle & inpart) const { _integrator->ME(DecayMEPtr()); // compute the prefactor InvEnergy pre(1./MeV); Energy prewid; if(_widthgen&&_partial>=0) prewid=_widthgen->partialWidth(_partial,inpart.mass()); else prewid=(inpart.dataPtr()->width()); pre = prewid>ZERO ? 1./prewid : 1./MeV; // Particle vector for the output ParticleVector particles; // boosts to/from rest Boost bv =-inpart.momentum().boostVector(); double gammarest = inpart.momentum().e()/inpart.momentum().mass(); LorentzRotation boostToRest( bv,gammarest); LorentzRotation boostFromRest(-bv,gammarest); // construct a new particle which is at rest Particle inrest(inpart); inrest.transform(boostToRest); int ncount(0),ichan; double wgt(0.); unsigned int ix; try { do { wgt=pre*weight(cc,ichan,inrest,particles,ncount==0); ++ncount; if(wgt>_maxweight) { CurrentGenerator::log() << "Resetting max weight for decay " << inrest.PDGName() << " -> "; for(ix=0;ixPDGName(); CurrentGenerator::log() << " " << _maxweight << " " << wgt << " " << inrest.mass()/MeV << "\n"; _maxweight=wgt; } } while(_maxweight*UseRandom::rnd()>wgt&&ncount<_ntry); if(ncount>=_ntry) { CurrentGenerator::log() << "The decay " << inrest.PDGName() << " -> "; for(ix=0;ixPDGName(); CurrentGenerator::log() << " " << _maxweight << " " << _ntry << " is too inefficient for the particle " << inpart << "vetoing the decay \n"; particles.clear(); throw Veto(); } } catch (Veto) { // restore the incoming particle to its original state inrest.transform(boostFromRest); throw Veto(); } // set up the vertex for spin correlations me2(-1,inrest,particles,DecayIntegrator::Terminate); const_ptr_cast(&inpart)->spinInfo(inrest.spinInfo()); constructVertex(inpart,particles); // return if intermediate particles not required if(_channelwgts.empty()||!intermediates) { for(ix=0;ixtransform(boostFromRest); } // find the intermediate particles else { // select the channel _ichannel = selectChannel(inpart,particles); for(ix=0;ixtransform(boostFromRest); // generate the particle vector _channels[_ichannel]->generateIntermediates(cc,inpart,particles); } _integrator->ME(DecayMEPtr()); return particles; } // construct the vertex for spin corrections void DecayPhaseSpaceMode::constructVertex(const Particle & inpart, const ParticleVector & decay) const { // construct the decay vertex VertexPtr vertex(new_ptr(DecayVertex())); DVertexPtr Dvertex(dynamic_ptr_cast(vertex)); // set the incoming particle for the decay vertex (inpart.spinInfo())->decayVertex(vertex); for(unsigned int ix=0;ixspinInfo())->productionVertex(vertex); } // set the matrix element Dvertex->ME(_integrator->ME()); _integrator->ME(DecayMEPtr()); } // output info on the mode ostream & Herwig::operator<<(ostream & os, const DecayPhaseSpaceMode & decay) { os << "The mode has " << decay._channels.size() << " channels\n"; os << "This is a mode for the decay of " << decay._extpart[0]->PDGName() << " to "; for(unsigned int iz=1,N=decay._extpart.size();izPDGName() << " "; } os << "\n"; for(unsigned int ix=0;ix(_extpart[0]->widthGenerator()); for(unsigned int ix=0;ix<_extpart.size();++ix) { assert(_extpart[ix]); _massgen[ix]= dynamic_ptr_cast(_extpart[ix]->massGenerator()); } for(unsigned int ix=0;ix<_channels.size();++ix) { _channels[ix]->init(); } } void DecayPhaseSpaceMode::doinitrun() { // update the mass and width generators if(_extpart[0]->widthGenerator()!=_widthgen) { _widthgen= dynamic_ptr_cast(_extpart[0]->widthGenerator()); } for(unsigned int ix=0;ix<_extpart.size();++ix) { if(_massgen[ix]!=_extpart[ix]->massGenerator()) _massgen[ix] = dynamic_ptr_cast(_extpart[ix]->massGenerator()); } // check the size of the weight vector is the same as the number of channels if(_channelwgts.size()!=numberChannels()) { throw Exception() << "Inconsistent number of channel weights and channels" << " in DecayPhaseSpaceMode " << Exception::abortnow; } for(unsigned int ix=0;ix<_channels.size();++ix) { _channels[ix]->initrun(); } if(_widthgen) const_ptr_cast(_widthgen)->initrun(); tcGenericWidthGeneratorPtr wtemp; for(unsigned int ix=1;ix<_extpart.size();++ix) { wtemp= dynamic_ptr_cast(_extpart[ix]->widthGenerator()); if(wtemp) const_ptr_cast(wtemp)->initrun(); } Interfaced::doinitrun(); } // generate the masses of the external particles vector DecayPhaseSpaceMode::externalMasses(Energy inmass,double & wgt, bool onShell) const { vector mass(1,inmass); mass.reserve(_extpart.size()); vector notdone; Energy mlow(ZERO); // set masses of stable particles and limits for(unsigned int ix=1;ix<_extpart.size();++ix) { // get the mass of the particle if can't use weight if(onShell) { mass.push_back(_extpart[ix]->mass()); } else if(!_massgen[ix] || _extpart[ix]->stable()) { mass.push_back(_extpart[ix]->generateMass()); mlow+=mass[ix]; } else { mass.push_back(ZERO); notdone.push_back(ix); mlow+=max(_extpart[ix]->mass()-_extpart[ix]->widthLoCut(),ZERO); } } if(mlow>inmass) { - CurrentGenerator::log() << "Decay mode " << _extpart[0]->PDGName() << " -> "; - for(unsigned int ix=1;ix<_extpart.size();++ix) { - CurrentGenerator::log() << _extpart[ix]->PDGName() << " "; + if(_integrator->state()==runready) { + CurrentGenerator::log() << "Decay mode " << _extpart[0]->PDGName() << " -> "; + for(unsigned int ix=1;ix<_extpart.size();++ix) { + CurrentGenerator::log() << _extpart[ix]->PDGName() << " "; + } + CurrentGenerator::log() << "is below threshold in DecayPhaseMode::externalMasses()" + << "the threshold is " << mlow/GeV + << "GeV and the parent mass is " << inmass/GeV + << " GeV\n"; } - CurrentGenerator::log() << "is below threshold in DecayPhaseMode::externalMasses()" - << "the threshold is " << mlow/GeV - << "GeV and the parent mass is " << inmass/GeV - << " GeV\n"; throw Veto(); } // now we need to generate the masses for the particles we haven't unsigned int iloc; double wgttemp; Energy low=ZERO; for( ;!notdone.empty();) { iloc=long(UseRandom::rnd()*(notdone.size()-1)); low=max(_extpart[notdone[iloc]]->mass()-_extpart[notdone[iloc]]->widthLoCut(),ZERO); mlow-=low; mass[notdone[iloc]]= _massgen[notdone[iloc]]->mass(wgttemp,*_extpart[notdone[iloc]],low,inmass-mlow); assert(mass[notdone[iloc]]>=low&&mass[notdone[iloc]]<=inmass-mlow); wgt *= wgttemp; mlow += mass[notdone[iloc]]; notdone.erase(notdone.begin()+iloc); } return mass; } diff --git a/Decay/General/FFSDecayer.cc b/Decay/General/FFSDecayer.cc --- a/Decay/General/FFSDecayer.cc +++ b/Decay/General/FFSDecayer.cc @@ -1,444 +1,463 @@ // -*- C++ -*- // // FFSDecayer.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 FFSDecayer class. // #include "FFSDecayer.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" #include "Herwig/Utilities/Kinematics.h" #include "Herwig/Decay/GeneralDecayMatrixElement.h" using namespace Herwig; using namespace ThePEG::Helicity; IBPtr FFSDecayer::clone() const { return new_ptr(*this); } IBPtr FFSDecayer::fullclone() const { return new_ptr(*this); } void FFSDecayer::setDecayInfo(PDPtr incoming, PDPair outgoing, - VertexBasePtr vertex, + vector vertex, map & inV, const vector > & outV, map ) { decayInfo(incoming,outgoing); - vertex_ = dynamic_ptr_cast(vertex); - perturbativeVertex_ = dynamic_ptr_cast (vertex); + for(auto vert : vertex) { + vertex_ .push_back(dynamic_ptr_cast(vert)); + perturbativeVertex_ .push_back(dynamic_ptr_cast (vert)); + } vector itemp={ShowerInteraction::QCD,ShowerInteraction::QED}; for(auto & inter : itemp) { incomingVertex_[inter] = dynamic_ptr_cast(inV.at(inter)); outgoingVertexF_[inter] = AbstractFFVVertexPtr(); outgoingVertexS_[inter] = AbstractVSSVertexPtr(); if(outV[0].at(inter)) { if (outV[0].at(inter)->getName()==VertexType::FFV) outgoingVertexF_[inter] = dynamic_ptr_cast(outV[0].at(inter)); else outgoingVertexS_[inter] = dynamic_ptr_cast(outV[0].at(inter)); } if(outV[1].at(inter)) { if (outV[1].at(inter)->getName()==VertexType::FFV) outgoingVertexF_[inter] = dynamic_ptr_cast(outV[1].at(inter)); else outgoingVertexS_[inter] = dynamic_ptr_cast(outV[1].at(inter)); } } } void FFSDecayer::persistentOutput(PersistentOStream & os) const { os << perturbativeVertex_ << vertex_ << incomingVertex_ << outgoingVertexF_ << outgoingVertexS_; } void FFSDecayer::persistentInput(PersistentIStream & is, int) { is >> perturbativeVertex_ >> vertex_ >> incomingVertex_ >> outgoingVertexF_ >> outgoingVertexS_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigFFSDecayer("Herwig::FFSDecayer", "Herwig.so"); void FFSDecayer::Init() { static ClassDocumentation documentation ("The FFSDecayer class implements the decay of a fermion to " "a fermion and a scalar."); } double FFSDecayer::me2(const int , const Particle & inpart, const ParticleVector & decay, MEOption meopt) const { if(!ME()) ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin1Half,PDT::Spin1Half,PDT::Spin0))); //Need to use different barred or unbarred spinors depending on //whether particle is cc or not. int itype[2]; if(inpart.dataPtr()->CC()) itype[0] = inpart.id() > 0? 0:1; else itype[0] = 2; if(decay[0]->dataPtr()->CC()) itype[1] = decay[0]->id() > 0? 0:1; else itype[1] = 2; bool ferm(itype[0] == 0 || itype[1] == 0 || (itype[0] == 2 && itype[1] == 2)); if(meopt==Initialize) { // spinors and rho if(ferm) { SpinorWaveFunction ::calculateWaveFunctions(wave_,rho_, const_ptr_cast(&inpart), incoming); if(wave_[0].wave().Type() != SpinorType::u) for(unsigned int ix = 0; ix < 2; ++ix) wave_ [ix].conjugate(); } else { SpinorBarWaveFunction::calculateWaveFunctions(wavebar_,rho_, const_ptr_cast(&inpart), incoming); if(wavebar_[0].wave().Type() != SpinorType::v) for(unsigned int ix = 0; ix < 2; ++ix) wavebar_[ix].conjugate(); } } // setup spin info when needed if(meopt==Terminate) { // for the decaying particle if(ferm) { SpinorWaveFunction:: constructSpinInfo(wave_,const_ptr_cast(&inpart),incoming,true); SpinorBarWaveFunction::constructSpinInfo(wavebar_,decay[0],outgoing,true); } else { SpinorBarWaveFunction:: constructSpinInfo(wavebar_,const_ptr_cast(&inpart),incoming,true); SpinorWaveFunction::constructSpinInfo(wave_,decay[0],outgoing,true); } ScalarWaveFunction::constructSpinInfo(decay[1],outgoing,true); } if(ferm) SpinorBarWaveFunction:: calculateWaveFunctions(wavebar_,decay[0],outgoing); else SpinorWaveFunction:: calculateWaveFunctions(wave_ ,decay[0],outgoing); ScalarWaveFunction scal(decay[1]->momentum(),decay[1]->dataPtr(),outgoing); Energy2 scale(sqr(inpart.mass())); for(unsigned int if1 = 0; if1 < 2; ++if1) { for(unsigned int if2 = 0; if2 < 2; ++if2) { - if(ferm) (*ME())(if1, if2, 0) = - vertex_->evaluate(scale,wave_[if1],wavebar_[if2],scal); - else (*ME())(if2, if1, 0) = - vertex_->evaluate(scale,wave_[if1],wavebar_[if2],scal); + if(ferm) (*ME())(if1, if2, 0) = 0.; + else (*ME())(if2, if1, 0) = 0.; + for(auto vert : vertex_) { + if(ferm) (*ME())(if1, if2, 0) += + vert->evaluate(scale,wave_[if1],wavebar_[if2],scal); + else (*ME())(if2, if1, 0) += + vert->evaluate(scale,wave_[if1],wavebar_[if2],scal); + } } } double output = (ME()->contract(rho_)).real()/scale*UnitRemoval::E2; // colour and identical particle factors output *= colourFactor(inpart.dataPtr(),decay[0]->dataPtr(), decay[1]->dataPtr()); // return the answer return output; } Energy FFSDecayer::partialWidth(PMPair inpart, PMPair outa, PMPair outb) const { if( inpart.second < outa.second + outb.second ) return ZERO; - if(perturbativeVertex_) { + if(perturbativeVertex_.size()==1 && + perturbativeVertex_[0]) { double mu1(0.),mu2(0.); tcPDPtr in = inpart.first->CC() ? tcPDPtr(inpart.first->CC()) : inpart.first; if(outa.first->iSpin() == PDT::Spin1Half) { mu1 = outa.second/inpart.second; mu2 = outb.second/inpart.second; - perturbativeVertex_->setCoupling(sqr(inpart.second), in, outa.first, outb.first); + perturbativeVertex_[0]->setCoupling(sqr(inpart.second), in, outa.first, outb.first); } else { mu1 = outb.second/inpart.second; mu2 = outa.second/inpart.second; - perturbativeVertex_->setCoupling(sqr(inpart.second), in, outb.first, outa.first); + perturbativeVertex_[0]->setCoupling(sqr(inpart.second), in, outb.first, outa.first); } - double c2 = norm(perturbativeVertex_->norm()); - Complex cl = perturbativeVertex_->left(); - Complex cr = perturbativeVertex_->right(); + double c2 = norm(perturbativeVertex_[0]->norm()); + Complex cl = perturbativeVertex_[0]->left(); + Complex cr = perturbativeVertex_[0]->right(); double me2 = c2*( (norm(cl) + norm(cr))*(1. + sqr(mu1) - sqr(mu2)) + 2.*mu1*(conj(cl)*cr + conj(cr)*cl).real() ); Energy pcm = Kinematics::pstarTwoBodyDecay(inpart.second, outa.second, outb.second); Energy output = me2*pcm/16./Constants::pi; // colour factor output *= colourFactor(inpart.first,outa.first,outb.first); // return the answer return output; } else { return GeneralTwoBodyDecayer::partialWidth(inpart,outa,outb); } } double FFSDecayer::threeBodyME(const int , const Particle & inpart, const ParticleVector & decay, ShowerInteraction inter, MEOption meopt) { int iscal (0), iferm (1), iglu (2); // get location of outgoing fermion/scalar if(decay[1]->dataPtr()->iSpin()==PDT::Spin0) swap(iscal,iferm); // work out whether inpart is a fermion or antifermion int itype[2]; if(inpart.dataPtr()->CC()) itype[0] = inpart.id() > 0 ? 0 : 1; else itype[0] = 2; if(decay[iferm]->dataPtr()->CC()) itype[1] = decay[iferm]->id() > 0 ? 0 : 1; else itype[1] = 2; bool ferm(false); if(itype[0] == itype[1] ) { ferm = itype[0]==0 || (itype[0]==2 && decay[iscal]->id() < 0); } else if(itype[0] == 2) { ferm = itype[1]==0; } else if(itype[1] == 2) { ferm = itype[0]==0; } else if((itype[0] == 1 && itype[1] == 0) || (itype[0] == 0 && itype[1] == 1)) { if(abs(inpart.id())<=16) { ferm = itype[0]==0; } else if(abs(decay[iferm]->id())<=16) { ferm = itype[1]==0; } else { ferm = true; } } else assert(false); if(meopt==Initialize) { // create spinor (bar) for decaying particle if(ferm) { SpinorWaveFunction::calculateWaveFunctions(wave3_, rho3_, const_ptr_cast(&inpart), incoming); if(wave3_[0].wave().Type() != SpinorType::u) for(unsigned int ix = 0; ix < 2; ++ix) wave3_[ix].conjugate(); } else { SpinorBarWaveFunction::calculateWaveFunctions(wavebar3_,rho3_, const_ptr_cast(&inpart), incoming); if(wavebar3_[0].wave().Type() != SpinorType::v) for(unsigned int ix = 0; ix < 2; ++ix) wavebar3_[ix].conjugate(); } } // setup spin information when needed if(meopt==Terminate) { if(ferm) { SpinorWaveFunction:: constructSpinInfo(wave3_,const_ptr_cast(&inpart),incoming,true); SpinorBarWaveFunction::constructSpinInfo(wavebar3_,decay[iferm],outgoing,true); } else { SpinorBarWaveFunction:: constructSpinInfo(wavebar3_,const_ptr_cast(&inpart),incoming,true); SpinorWaveFunction::constructSpinInfo(wave3_,decay[iferm],outgoing,true); } ScalarWaveFunction::constructSpinInfo( decay[iscal],outgoing,true); VectorWaveFunction::constructSpinInfo(gluon_, decay[iglu ],outgoing,true,false); return 0.; } // calulate colour factors and number of colour flows unsigned int nflow; vector cfactors = getColourFactors(inpart, decay, nflow); vector ME(nflow,new_ptr(GeneralDecayMatrixElement(PDT::Spin1Half, PDT::Spin0, PDT::Spin1Half, PDT::Spin1))); // create wavefunctions if (ferm) SpinorBarWaveFunction::calculateWaveFunctions(wavebar3_, decay[iferm],outgoing); else SpinorWaveFunction:: calculateWaveFunctions(wave3_ , decay[iferm],outgoing); ScalarWaveFunction swave3_(decay[iscal]->momentum(), decay[iscal]->dataPtr(),outgoing); VectorWaveFunction::calculateWaveFunctions(gluon_, decay[iglu ],outgoing,true); // gauge invariance test #ifdef GAUGE_CHECK gluon_.clear(); for(unsigned int ix=0;ix<3;++ix) { if(ix==1) gluon_.push_back(VectorWaveFunction()); else { gluon_.push_back(VectorWaveFunction(decay[iglu ]->momentum(),decay[iglu ]->dataPtr(),10, outgoing)); } } #endif if (! ((incomingVertex_[inter] && (outgoingVertexF_[inter] || outgoingVertexS_[inter])) || (outgoingVertexF_[inter] && outgoingVertexS_[inter]))) throw Exception() << "Invalid vertices for radiation in FFS decay in FFSDecayer::threeBodyME" << Exception::runerror; // sort out colour flows int F(1), S(2); if (decay[iscal]->dataPtr()->iColour()==PDT::Colour3 && decay[iferm]->dataPtr()->iColour()==PDT::Colour8) swap(F,S); else if (decay[iferm]->dataPtr()->iColour()==PDT::Colour3bar && decay[iscal]->dataPtr()->iColour()==PDT::Colour8) swap(F,S); Complex diag; Energy2 scale(sqr(inpart.mass())); const GeneralTwoBodyDecayer::CFlow & colourFlow = colourFlows(inpart, decay); double gs(0.); bool couplingSet(false); #ifdef GAUGE_CHECK double total=0.; #endif for(unsigned int ifi = 0; ifi < 2; ++ifi) { for(unsigned int ifo = 0; ifo < 2; ++ifo) { for(unsigned int ig = 0; ig < 2; ++ig) { // radiation from the incoming fermion if((inpart.dataPtr()->coloured() && inter==ShowerInteraction::QCD) || (inpart.dataPtr()->charged() && inter==ShowerInteraction::QED) ) { assert(incomingVertex_[inter]); if (ferm) { SpinorWaveFunction spinorInter = incomingVertex_[inter]->evaluate(scale,3,inpart.dataPtr(),wave3_[ifi], gluon_[2*ig],inpart.mass()); assert(wave3_[ifi].particle()->id()==spinorInter.particle()->id()); - diag = vertex_->evaluate(scale,spinorInter,wavebar3_[ifo],swave3_); + diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,spinorInter,wavebar3_[ifo],swave3_); } else { SpinorBarWaveFunction spinorBarInter = incomingVertex_[inter]->evaluate(scale,3,inpart.dataPtr(),wavebar3_[ifi], gluon_[2*ig],inpart.mass()); assert(wavebar3_[ifi].particle()->id()==spinorBarInter.particle()->id()); - diag = vertex_->evaluate(scale,wave3_[ifo], spinorBarInter,swave3_); + diag = 0.; + for(auto vertex :vertex_) + diag+= vertex->evaluate(scale,wave3_[ifo], spinorBarInter,swave3_); } if(!couplingSet) { gs = abs(incomingVertex_[inter]->norm()); couplingSet = true; } for(unsigned int ix=0;ixdataPtr()->coloured() && inter==ShowerInteraction::QCD) || (decay[iferm]->dataPtr()->charged() && inter==ShowerInteraction::QED) ) { assert(outgoingVertexF_[inter]); // ensure you get correct outgoing particle from first vertex tcPDPtr off = decay[iferm]->dataPtr(); if(off->CC()) off = off->CC(); if (ferm) { SpinorBarWaveFunction spinorBarInter = outgoingVertexF_[inter]->evaluate(scale,3,off,wavebar3_[ifo], gluon_[2*ig],decay[iferm]->mass()); assert(wavebar3_[ifo].particle()->id()==spinorBarInter.particle()->id()); - diag = vertex_->evaluate(scale,wave3_[ifi],spinorBarInter,swave3_); + diag = 0.; + for(auto vertex :vertex_) + diag+= vertex->evaluate(scale,wave3_[ifi],spinorBarInter,swave3_); } else { SpinorWaveFunction spinorInter = outgoingVertexF_[inter]->evaluate(scale,3,off,wave3_[ifo], gluon_[2*ig],decay[iferm]->mass()); assert(wave3_[ifo].particle()->id()==spinorInter.particle()->id()); - diag = vertex_->evaluate(scale,spinorInter,wavebar3_[ifi],swave3_); + diag = 0.; + for(auto vertex :vertex_) + diag+= vertex->evaluate(scale,spinorInter,wavebar3_[ifi],swave3_); } if(!couplingSet) { gs = abs(outgoingVertexF_[inter]->norm()); couplingSet = true; } for(unsigned int ix=0;ixdataPtr()->coloured() && inter==ShowerInteraction::QCD) || (decay[iscal]->dataPtr()->charged() && inter==ShowerInteraction::QED) ) { assert(outgoingVertexS_[inter]); // ensure you get correct ougoing particle from first vertex tcPDPtr off = decay[iscal]->dataPtr(); if(off->CC()) off = off->CC(); ScalarWaveFunction scalarInter = outgoingVertexS_[inter]->evaluate(scale,3,off,gluon_[2*ig], swave3_,decay[iscal]->mass()); assert(swave3_.particle()->id()==scalarInter.particle()->id()); if (ferm){ - diag = vertex_->evaluate(scale,wave3_[ifi],wavebar3_[ifo],scalarInter); + diag = 0.; + for(auto vertex :vertex_) + diag += vertex->evaluate(scale,wave3_[ifi],wavebar3_[ifo],scalarInter); } else { - diag = vertex_->evaluate(scale,wave3_[ifo],wavebar3_[ifi],scalarInter); + diag = 0.; + for(auto vertex :vertex_) + diag += vertex->evaluate(scale,wave3_[ifo],wavebar3_[ifi],scalarInter); } if(!couplingSet) { gs = abs(outgoingVertexS_[inter]->norm()); couplingSet = true; } for(unsigned int ix=0;ixcontract(*ME[iy],rho3_)).real(); } } // divide by alpha(S,EM) output*=(4.*Constants::pi)/sqr(gs); #ifdef GAUGE_CHECK double ratio = output/total; if(abs(ratio)>1e-20) { generator()->log() << "Test of gauge invariance in decay\n" << inpart << "\n"; for(unsigned int ix=0;ixlog() << *decay[ix] << "\n"; generator()->log() << "Test of gauge invariance " << ratio << "\n"; } #endif // return the answer return output; } diff --git a/Decay/General/FFSDecayer.h b/Decay/General/FFSDecayer.h --- a/Decay/General/FFSDecayer.h +++ b/Decay/General/FFSDecayer.h @@ -1,210 +1,218 @@ // -*- C++ -*- // // FFSDecayer.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_FFSDecayer_H #define HERWIG_FFSDecayer_H // // This is the declaration of the FFSDecayer class. // #include "GeneralTwoBodyDecayer.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Helicity/Vertex/Scalar/FFSVertex.h" #include "ThePEG/Helicity/Vertex/Scalar/VSSVertex.h" #include "ThePEG/Helicity/Vertex/Vector/FFVVertex.h" namespace Herwig { using namespace ThePEG; using Helicity::FFSVertexPtr; /** \ingroup Decay * The FFSDecayer class implements the decay of a fermion * to a fermion and a vector in a general model. It holds an FFVVertex * pointer that must be typecast from the VertexBase pointer held in * GeneralTwoBodyDecayer. It implents the virtual functions me2() and * partialWidth(). * * @see GeneralTwoBodyDecayer */ class FFSDecayer: public GeneralTwoBodyDecayer { public: /** * The default constructor. */ FFSDecayer() {} /** @name Virtual functions required by the Decayer class. */ //@{ /** * Return the matrix element squared for a given mode and phase-space channel. * @param ichan The channel we are calculating the matrix element for. * @param part The decaying Particle. * @param decay The particles produced in the decay. * @param meopt Option for the calculation of the matrix element * @return The matrix element squared for the phase-space configuration. */ virtual double me2(const int ichan, const Particle & part, const ParticleVector & decay, MEOption meopt) const; /** * Function to return partial Width * @param inpart The decaying particle. * @param outa One of the decay products. * @param outb The other decay product. */ virtual Energy partialWidth(PMPair inpart, PMPair outa, PMPair outb) const; /** * Has a POWHEG style correction */ virtual POWHEGType hasPOWHEGCorrection() { - return (vertex_->orderInGem()+vertex_->orderInGs())==1 ? FSR : No; + POWHEGType output = FSR; + for(auto vertex : vertex_) { + if(vertex->orderInAllCouplings()!=1) { + output = No; + break; + } + } + return output; } /** * Three-body matrix element including additional QCD radiation */ virtual double threeBodyME(const int , const Particle & inpart, const ParticleVector & decay, ShowerInteraction inter, MEOption meopt); /** * Set the information on the decay */ - virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, VertexBasePtr, + virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, + vector, map &, const vector > &, map); //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FFSDecayer & operator=(const FFSDecayer &); private: /** * Abstract pointer to AbstractFFSVertex */ - AbstractFFSVertexPtr vertex_; + vector vertex_; /** * Pointer to the perturbative vertex */ - FFSVertexPtr perturbativeVertex_; + vector perturbativeVertex_; /** * Abstract pointer to AbstractFFVVertex for QCD radiation from incoming (anti)fermion */ map incomingVertex_; /** * Abstract pointer to AbstractFFVVertex for QCD radiation from outgoing (anti)fermion */ map outgoingVertexF_; /** * Abstract pointer to AbstractVSSVertex for QCD radiation from outgoing scalar */ map outgoingVertexS_; /** * Spin density matrix */ mutable RhoDMatrix rho_; /** * Spinor wavefunctions */ mutable vector wave_ ; /** * Barred spinor wavefunctions */ mutable vector wavebar_; /** * Spin density matrix for 3 body decay */ mutable RhoDMatrix rho3_; /** * Scalar wavefunction for 3 body decay */ mutable ScalarWaveFunction swave3_; /** * Spinor wavefunction for 3 body decay */ mutable vector wave3_; /** * Barred spinor wavefunction for 3 body decay */ mutable vector wavebar3_; /** * Vector wavefunction for 3 body decay */ mutable vector gluon_; }; } #endif /* HERWIG_FFSDecayer_H */ diff --git a/Decay/General/FFVDecayer.cc b/Decay/General/FFVDecayer.cc --- a/Decay/General/FFVDecayer.cc +++ b/Decay/General/FFVDecayer.cc @@ -1,433 +1,456 @@ // -*- C++ -*- // // FFVDecayer.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 FFVDecayer class. // #include "FFVDecayer.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" #include "Herwig/Utilities/Kinematics.h" #include "Herwig/Decay/GeneralDecayMatrixElement.h" using namespace Herwig; using namespace ThePEG::Helicity; IBPtr FFVDecayer::clone() const { return new_ptr(*this); } IBPtr FFVDecayer::fullclone() const { return new_ptr(*this); } void FFVDecayer::setDecayInfo(PDPtr incoming, PDPair outgoing, - VertexBasePtr vertex, + vector vertex, map & inV, const vector > & outV, map ) { decayInfo(incoming,outgoing); - vertex_ = dynamic_ptr_cast(vertex); - perturbativeVertex_ = dynamic_ptr_cast (vertex); + for(auto vert : vertex) { + vertex_ .push_back(dynamic_ptr_cast(vert)); + perturbativeVertex_ .push_back(dynamic_ptr_cast (vert)); + } vector itemp={ShowerInteraction::QCD,ShowerInteraction::QED}; for(auto & inter : itemp) { incomingVertex_[inter] = dynamic_ptr_cast(inV.at(inter)); if(outV[0].at(inter)) { if (outV[0].at(inter)->getName()==VertexType::FFV) outgoingVertexF_[inter] = dynamic_ptr_cast(outV[0].at(inter)); else outgoingVertexV_[inter] = dynamic_ptr_cast(outV[0].at(inter)); } if(outV[1].at(inter)) { if (outV[1].at(inter)->getName()==VertexType::FFV) outgoingVertexF_[inter] = dynamic_ptr_cast(outV[1].at(inter)); else outgoingVertexV_[inter] = dynamic_ptr_cast(outV[1].at(inter)); } } } void FFVDecayer::persistentOutput(PersistentOStream & os) const { os << vertex_ << perturbativeVertex_ << incomingVertex_ << outgoingVertexF_ << outgoingVertexV_; } void FFVDecayer::persistentInput(PersistentIStream & is, int) { is >> vertex_ >> perturbativeVertex_ >> incomingVertex_ >> outgoingVertexF_ >> outgoingVertexV_; } double FFVDecayer::me2(const int , const Particle & inpart, const ParticleVector & decay, MEOption meopt) const { if(!ME()) ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin1Half,PDT::Spin1Half,PDT::Spin1))); // type of process int itype[2]; if(inpart.dataPtr()->CC()) itype[0] = inpart.id() > 0 ? 0 : 1; else itype[0] = 2; if(decay[0]->dataPtr()->CC()) itype[1] = decay[0]->id() > 0 ? 0 : 1; else itype[1] = 2; //Need to use different barred or unbarred spinors depending on //whether particle is cc or not. bool ferm(itype[0] == 0 || itype[1] == 0 || (itype[0] == 2 && itype[1] == 2)); if(meopt==Initialize) { // spinors and rho if(ferm) { SpinorWaveFunction ::calculateWaveFunctions(wave_,rho_, const_ptr_cast(&inpart), incoming); if(wave_[0].wave().Type() != SpinorType::u) for(unsigned int ix = 0; ix < 2; ++ix) wave_ [ix].conjugate(); } else { SpinorBarWaveFunction::calculateWaveFunctions(wavebar_,rho_, const_ptr_cast(&inpart), incoming); if(wavebar_[0].wave().Type() != SpinorType::v) for(unsigned int ix = 0; ix < 2; ++ix) wavebar_[ix].conjugate(); } } // setup spin info when needed if(meopt==Terminate) { // for the decaying particle if(ferm) { SpinorWaveFunction:: constructSpinInfo(wave_,const_ptr_cast(&inpart),incoming,true); SpinorBarWaveFunction::constructSpinInfo(wavebar_,decay[0],outgoing,true); } else { SpinorBarWaveFunction:: constructSpinInfo(wavebar_,const_ptr_cast(&inpart),incoming,true); SpinorWaveFunction::constructSpinInfo(wave_,decay[0],outgoing,true); } VectorWaveFunction:: constructSpinInfo(vector_,decay[1],outgoing,true,false); } Energy2 scale(sqr(inpart.mass())); if(ferm) SpinorBarWaveFunction:: calculateWaveFunctions(wavebar_,decay[0],outgoing); else SpinorWaveFunction:: calculateWaveFunctions(wave_ ,decay[0],outgoing); bool massless = decay[1]->dataPtr()->mass()==ZERO; VectorWaveFunction:: calculateWaveFunctions(vector_,decay[1],outgoing,massless); for(unsigned int if1 = 0; if1 < 2; ++if1) { for(unsigned int if2 = 0; if2 < 2; ++if2) { for(unsigned int vhel = 0; vhel < 3; ++vhel) { if(massless && vhel == 1) ++vhel; if(ferm) - (*ME())(if1, if2,vhel) = - vertex_->evaluate(scale,wave_[if1],wavebar_[if2],vector_[vhel]); + (*ME())(if1, if2,vhel) = 0.; else - (*ME())(if2, if1, vhel) = - vertex_->evaluate(scale,wave_[if1],wavebar_[if2],vector_[vhel]); + (*ME())(if2, if1, vhel) = 0.; + for(auto vertex : vertex_) { + if(ferm) + (*ME())(if1, if2,vhel) += + vertex->evaluate(scale,wave_[if1],wavebar_[if2],vector_[vhel]); + else + (*ME())(if2, if1, vhel) += + vertex->evaluate(scale,wave_[if1],wavebar_[if2],vector_[vhel]); + } } } } double output=(ME()->contract(rho_)).real()/scale*UnitRemoval::E2; // colour and identical particle factors output *= colourFactor(inpart.dataPtr(),decay[0]->dataPtr(),decay[1]->dataPtr()); // return the answer return output; } Energy FFVDecayer::partialWidth(PMPair inpart, PMPair outa, PMPair outb) const { if( inpart.second < outa.second + outb.second ) return ZERO; - if(perturbativeVertex_) { + if(perturbativeVertex_.size()==1 && + perturbativeVertex_[0]) { double mu1(outa.second/inpart.second),mu2(outb.second/inpart.second); tcPDPtr in = inpart.first->CC() ? tcPDPtr(inpart.first->CC()) : inpart.first; if( outa.first->iSpin() == PDT::Spin1Half) - perturbativeVertex_->setCoupling(sqr(inpart.second), in, + perturbativeVertex_[0]->setCoupling(sqr(inpart.second), in, outa.first, outb.first); else { swap(mu1,mu2); - perturbativeVertex_->setCoupling(sqr(inpart.second),in, + perturbativeVertex_[0]->setCoupling(sqr(inpart.second),in, outb.first,outa.first); } - Complex cl(perturbativeVertex_->left()),cr(perturbativeVertex_->right()); + Complex cl(perturbativeVertex_[0]->left()),cr(perturbativeVertex_[0]->right()); double me2(0.); if( mu2 > 0. ) { me2 = (norm(cl) + norm(cr))*(1. + sqr(mu1*mu2) + sqr(mu2) - 2.*sqr(mu1) - 2.*sqr(mu2*mu2) + sqr(mu1*mu1)) - 6.*mu1*sqr(mu2)*(conj(cl)*cr + conj(cr)*cl).real(); me2 /= sqr(mu2); } else me2 = 2.*( (norm(cl) + norm(cr))*(sqr(mu1) + 1.) - 4.*mu1*(conj(cl)*cr + conj(cr)*cl).real() ); Energy pcm = Kinematics::pstarTwoBodyDecay(inpart.second, outa.second, outb.second); - Energy output = norm(perturbativeVertex_->norm())*me2*pcm/16./Constants::pi; + Energy output = norm(perturbativeVertex_[0]->norm())*me2*pcm/16./Constants::pi; // colour factor output *= colourFactor(inpart.first,outa.first,outb.first); // return the answer return output; } else { return GeneralTwoBodyDecayer::partialWidth(inpart,outa,outb); } } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigFFVDecayer("Herwig::FFVDecayer", "Herwig.so"); void FFVDecayer::Init() { static ClassDocumentation documentation ("The FFVDecayer class implements the decay of a fermion to a fermion and a vector boson"); } double FFVDecayer::threeBodyME(const int , const Particle & inpart, const ParticleVector & decay, ShowerInteraction inter, MEOption meopt) { int iferm (0), ivect (1), iglu (2); // get location of outgoing lepton/vector if(decay[1]->dataPtr()->iSpin()==PDT::Spin1Half) swap(iferm,ivect); // work out whether inpart is a fermion or antifermion int itype[2]; if(inpart.dataPtr()->CC()) itype[0] = inpart.id() > 0 ? 0 : 1; else itype[0] = 2; if(decay[iferm]->dataPtr()->CC()) itype[1] = decay[iferm]->id() > 0 ? 0 : 1; else itype[1] = 2; bool ferm(itype[0] == 0 || itype[1] == 0 || (itype[0] == 2 && itype[1] == 2 && decay[ivect]->id() < 0)); // no emissions from massive vectors bool massless = decay[ivect]->dataPtr()->mass()==ZERO; if(meopt==Initialize) { // create spinor (bar) for decaying particle if(ferm) { SpinorWaveFunction::calculateWaveFunctions(wave3_, rho3_, const_ptr_cast(&inpart), incoming); if(wave3_[0].wave().Type() != SpinorType::u) for(unsigned int ix = 0; ix < 2; ++ix) wave3_[ix].conjugate(); } else { SpinorBarWaveFunction::calculateWaveFunctions(wavebar3_,rho3_, const_ptr_cast(&inpart), incoming); if(wavebar3_[0].wave().Type() != SpinorType::v) for(unsigned int ix = 0; ix < 2; ++ix) wavebar3_[ix].conjugate(); } } // setup spin information when needed if(meopt==Terminate) { if(ferm) { SpinorWaveFunction:: constructSpinInfo(wave3_,const_ptr_cast(&inpart),incoming,true); SpinorBarWaveFunction::constructSpinInfo(wavebar3_,decay[iferm],outgoing,true); } else { SpinorBarWaveFunction:: constructSpinInfo(wavebar3_,const_ptr_cast(&inpart),incoming,true); SpinorWaveFunction::constructSpinInfo(wave3_,decay[iferm],outgoing,true); } VectorWaveFunction::constructSpinInfo(vector3_, decay[ivect],outgoing,true,massless); VectorWaveFunction::constructSpinInfo(gluon_, decay[iglu ],outgoing,true,false); return 0.; } // calulate colour factors and number of colour flows unsigned int nflow; vector cfactors = getColourFactors(inpart, decay, nflow); vector ME(nflow,new_ptr(GeneralDecayMatrixElement(PDT::Spin1Half, PDT::Spin1Half, PDT::Spin1, PDT::Spin1))); // create wavefunctions if (ferm) SpinorBarWaveFunction::calculateWaveFunctions(wavebar3_, decay[iferm],outgoing); else SpinorWaveFunction:: calculateWaveFunctions(wave3_ , decay[iferm],outgoing); VectorWaveFunction::calculateWaveFunctions(vector3_, decay[ivect],outgoing,massless); VectorWaveFunction::calculateWaveFunctions(gluon_, decay[iglu ],outgoing,true ); // gauge invariance test #ifdef GAUGE_CHECK gluon_.clear(); for(unsigned int ix=0;ix<3;++ix) { if(ix==1) gluon_.push_back(VectorWaveFunction()); else { gluon_.push_back(VectorWaveFunction(decay[iglu ]->momentum(), decay[iglu ]->dataPtr(),10, outgoing)); } } #endif if (! ((incomingVertex_[inter] && (outgoingVertexF_[inter] || outgoingVertexV_[inter])) || (outgoingVertexF_[inter] && outgoingVertexV_[inter]))) throw Exception() << "Invalid vertices for QCD radiation in FFV decay in FFVDecayer::threeBodyME" << Exception::runerror; // sort out colour flows int F(1), V(2); if (decay[iferm]->dataPtr()->iColour()==PDT::Colour3bar && decay[ivect]->dataPtr()->iColour()==PDT::Colour8) swap(F,V); else if (decay[ivect]->dataPtr()->iColour()==PDT::Colour3 && decay[iferm]->dataPtr()->iColour()==PDT::Colour8) swap(F,V); Complex diag; Energy2 scale(sqr(inpart.mass())); const GeneralTwoBodyDecayer::CFlow & colourFlow = colourFlows(inpart, decay); double gs(0.); bool couplingSet(false); #ifdef GAUGE_CHECK double total=0.; #endif for(unsigned int ifi = 0; ifi < 2; ++ifi) { for(unsigned int ifo = 0; ifo < 2; ++ifo) { for(unsigned int iv = 0; iv < 3; ++iv) { for(unsigned int ig = 0; ig < 2; ++ig) { // radiation from the incoming fermion if((inpart.dataPtr()->coloured() && inter==ShowerInteraction::QCD) || (inpart.dataPtr()->charged() && inter==ShowerInteraction::QED) ) { assert(incomingVertex_[inter]); if (ferm){ SpinorWaveFunction spinorInter = incomingVertex_[inter]->evaluate(scale,3,inpart.dataPtr(),wave3_[ifi], gluon_[2*ig],inpart.mass()); assert(wave3_[ifi].particle()->id()==spinorInter.particle()->id()); - diag = vertex_->evaluate(scale,spinorInter,wavebar3_[ifo],vector3_[iv]); + diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,spinorInter,wavebar3_[ifo],vector3_[iv]); } else { SpinorBarWaveFunction spinorBarInter = incomingVertex_[inter]->evaluate(scale,3,inpart.dataPtr(),wavebar3_[ifi], gluon_[2*ig],inpart.mass()); assert(wavebar3_[ifi].particle()->id()==spinorBarInter.particle()->id()); - diag = vertex_->evaluate(scale,wave3_[ifo], spinorBarInter,vector3_[iv]); + diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,wave3_[ifo], spinorBarInter,vector3_[iv]); } if(!couplingSet) { gs = abs(incomingVertex_[inter]->norm()); couplingSet = true; } for(unsigned int ix=0;ixdataPtr()->coloured() && inter==ShowerInteraction::QCD) || (decay[iferm]->dataPtr()->charged() && inter==ShowerInteraction::QED) ) { assert(outgoingVertexF_[inter]); // ensure you get correct outgoing particle from first vertex tcPDPtr off = decay[iferm]->dataPtr(); if(off->CC()) off = off->CC(); if (ferm) { SpinorBarWaveFunction spinorBarInter = outgoingVertexF_[inter]->evaluate(scale,3,off,wavebar3_[ifo], gluon_[2*ig],decay[iferm]->mass()); assert(wavebar3_[ifo].particle()->id()==spinorBarInter.particle()->id()); - diag = vertex_->evaluate(scale,wave3_[ifi],spinorBarInter,vector3_[iv]); + diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,wave3_[ifi],spinorBarInter,vector3_[iv]); } else { SpinorWaveFunction spinorInter = outgoingVertexF_[inter]->evaluate(scale,3,off,wave3_[ifo], gluon_[2*ig],decay[iferm]->mass()); assert(wave3_[ifo].particle()->id()==spinorInter.particle()->id()); - diag = vertex_->evaluate(scale,spinorInter,wavebar3_[ifi],vector3_[iv]); + diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,spinorInter,wavebar3_[ifi],vector3_[iv]); } if(!couplingSet) { gs = abs(outgoingVertexF_[inter]->norm()); couplingSet = true; } for(unsigned int ix=0;ixdataPtr()->coloured() && inter==ShowerInteraction::QCD) || (decay[ivect]->dataPtr()->charged() && inter==ShowerInteraction::QED) ) { assert(outgoingVertexV_[inter]); // ensure you get correct ougoing particle from first vertex tcPDPtr off = decay[ivect]->dataPtr(); if(off->CC()) off = off->CC(); VectorWaveFunction vectorInter = outgoingVertexV_[inter]->evaluate(scale,3,off,gluon_[2*ig], vector3_[iv],decay[ivect]->mass()); - assert(vector3_[iv].particle()->id()==vectorInter.particle()->id()); - if (ferm) - diag = vertex_->evaluate(scale,wave3_[ifi],wavebar3_[ifo],vectorInter); - else - diag = vertex_->evaluate(scale,wave3_[ifo],wavebar3_[ifi],vectorInter); + assert(vector3_[iv].particle()->id()==vectorInter.particle()->id()); + if (ferm) { + diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,wave3_[ifi],wavebar3_[ifo],vectorInter); + } + else { + diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,wave3_[ifo],wavebar3_[ifi],vectorInter); + } if(!couplingSet) { gs = abs(outgoingVertexV_[inter]->norm()); couplingSet = true; } for(unsigned int ix=0;ixcontract(*ME[iy],rho3_)).real(); } } // divide by alpha(S,eM) output *= (4.*Constants::pi)/sqr(gs); #ifdef GAUGE_CHECK double ratio = output/total; if(abs(ratio)>1e-20) { generator()->log() << "Test of gauge invariance in decay\n" << inpart << "\n"; for(unsigned int ix=0;ixlog() << *decay[ix] << "\n"; generator()->log() << "Test of gauge invariance " << ratio << "\n"; } #endif // return the answer return output; } diff --git a/Decay/General/FFVDecayer.h b/Decay/General/FFVDecayer.h --- a/Decay/General/FFVDecayer.h +++ b/Decay/General/FFVDecayer.h @@ -1,216 +1,223 @@ // -*- C++ -*- // // FFVDecayer.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_FFVDecayer_H #define HERWIG_FFVDecayer_H // // This is the declaration of the FFVDecayer class. // #include "GeneralTwoBodyDecayer.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Helicity/Vertex/Vector/FFVVertex.h" #include "ThePEG/Helicity/Vertex/Vector/VVVVertex.h" namespace Herwig { using namespace ThePEG; using Helicity::FFVVertexPtr; /** \ingroup Decay * The FFVDecayer class implements the decay of a fermion * to a fermion and a vector in a general model. It holds an FFVVertex * pointer that must be typecast from the VertexBase pointer held in * GeneralTwoBodyDecayer. It implents the virtual functions me2() and * partialWidth(). * * @see GeneralTwoBodyDecayer */ class FFVDecayer: public GeneralTwoBodyDecayer { public: /** * The default constructor. */ FFVDecayer() {} public: /** @name Virtual functions required by the Decayer class. */ //@{ /** * Return the matrix element squared for a given mode and phase-space channel. * @param ichan The channel we are calculating the matrix element for. * @param part The decaying Particle. * @param decay The particles produced in the decay. * @param meopt Option for the matrix element * @return The matrix element squared for the phase-space configuration. */ virtual double me2(const int ichan, const Particle & part, const ParticleVector & decay, MEOption meopt) const; /** * Function to return partial Width * @param inpart The decaying particle. * @param outa One of the decay products. * @param outb The other decay product. */ virtual Energy partialWidth(PMPair inpart, PMPair outa, PMPair outb) const; /** * Has a POWHEG style correction */ virtual POWHEGType hasPOWHEGCorrection() { - return (vertex_->orderInGem()+vertex_->orderInGs())==1 ? FSR : No; + POWHEGType output = FSR; + for(auto vertex : vertex_) { + if(vertex->orderInAllCouplings()!=1) { + output = No; + break; + } + } + return output; } /** * Three-body matrix element including additional QCD radiation */ virtual double threeBodyME(const int , const Particle & inpart, const ParticleVector & decay, ShowerInteraction inter, MEOption meopt); /** * Set the information on the decay */ - virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, VertexBasePtr, + virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, vector, map &, const vector > &, map); //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FFVDecayer & operator=(const FFVDecayer &); private: /** * Abstract pointer to AbstractFFVVertex */ - AbstractFFVVertexPtr vertex_; + vector vertex_; /** * Pointer to the perturbative vertex */ - FFVVertexPtr perturbativeVertex_; + vector perturbativeVertex_; /** * Abstract pointer to AbstractFFVVertex for QCD radiation from incoming (anti)fermion */ map incomingVertex_; /** * Abstract pointer to AbstractFFVVertex for QCD radiation from outgoing (anti)fermion */ map outgoingVertexF_; /** * Abstract pointer to AbstractVVVVertex for QCD radiation from outgoing vector */ map outgoingVertexV_; /** * Spin density matrix */ mutable RhoDMatrix rho_; /** * Spinor wavefunction */ mutable vector wave_ ; /** * Barred spinor wavefunction */ mutable vector wavebar_; /** * Polarization vectors */ mutable vector vector_; /** * Spin density matrix for 3 body decay */ mutable RhoDMatrix rho3_; /** * vector wavefunction for 3 body decay */ mutable vector vector3_; /** * Spinor wavefunction for 3 body decay */ mutable vector wave3_; /** * Barred spinor wavefunction for 3 body decay */ mutable vector wavebar3_; /** * Vector wavefunction for gluon in 3 body decay */ mutable vector gluon_; }; } #endif /* HERWIG_FFVDecayer_H */ diff --git a/Decay/General/FRSDecayer.cc b/Decay/General/FRSDecayer.cc --- a/Decay/General/FRSDecayer.cc +++ b/Decay/General/FRSDecayer.cc @@ -1,183 +1,189 @@ // -*- C++ -*- // // FRSDecayer.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 FRSDecayer class. // #include "FRSDecayer.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" #include "Herwig/Utilities/Kinematics.h" #include "Herwig/Decay/GeneralDecayMatrixElement.h" using namespace Herwig; using namespace ThePEG::Helicity; IBPtr FRSDecayer::clone() const { return new_ptr(*this); } IBPtr FRSDecayer::fullclone() const { return new_ptr(*this); } void FRSDecayer::setDecayInfo(PDPtr incoming, PDPair outgoing, - VertexBasePtr vertex, + vector vertex, map &, const vector > &, map) { decayInfo(incoming,outgoing); - vertex_ = dynamic_ptr_cast(vertex); - perturbativeVertex_ = dynamic_ptr_cast (vertex); + for(auto vert : vertex) { + vertex_ .push_back(dynamic_ptr_cast(vert)); + perturbativeVertex_.push_back(dynamic_ptr_cast (vert)); + } } void FRSDecayer::persistentOutput(PersistentOStream & os) const { os << perturbativeVertex_ << vertex_; } void FRSDecayer::persistentInput(PersistentIStream & is, int) { is >> perturbativeVertex_ >> vertex_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigFRSDecayer("Herwig::FRSDecayer", "Herwig.so"); void FRSDecayer::Init() { static ClassDocumentation documentation ("The FRSDecayer class implements the decay of a fermion to " "a spin-3/2 fermion and a scalar."); } double FRSDecayer::me2(const int , const Particle & inpart, const ParticleVector & decay, MEOption meopt) const { bool ferm = inpart.id() > 0; if(!ME()) ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin1Half,PDT::Spin3Half,PDT::Spin0))); if(meopt==Initialize) { // spinors and rho if(ferm) { SpinorWaveFunction ::calculateWaveFunctions(wave_,rho_, const_ptr_cast(&inpart), incoming); if(wave_[0].wave().Type() != SpinorType::u) for(unsigned int ix = 0; ix < 2; ++ix) wave_ [ix].conjugate(); } else { SpinorBarWaveFunction::calculateWaveFunctions(wavebar_,rho_, const_ptr_cast(&inpart), incoming); if(wavebar_[0].wave().Type() != SpinorType::v) for(unsigned int ix = 0; ix < 2; ++ix) wavebar_[ix].conjugate(); } } // setup spin info when needed if(meopt==Terminate) { // for the decaying particle if(ferm) { SpinorWaveFunction:: constructSpinInfo(wave_,const_ptr_cast(&inpart),incoming,true); RSSpinorBarWaveFunction::constructSpinInfo(RSwavebar_,decay[0],outgoing,true); } else { SpinorBarWaveFunction:: constructSpinInfo(wavebar_,const_ptr_cast(&inpart),incoming,true); RSSpinorWaveFunction::constructSpinInfo(RSwave_,decay[0],outgoing,true); } ScalarWaveFunction::constructSpinInfo(decay[1],outgoing,true); } if(ferm) RSSpinorBarWaveFunction:: calculateWaveFunctions(RSwavebar_,decay[0],outgoing); else RSSpinorWaveFunction:: calculateWaveFunctions(RSwave_ ,decay[0],outgoing); ScalarWaveFunction scal(decay[1]->momentum(),decay[1]->dataPtr(),outgoing); Energy2 scale(sqr(inpart.mass())); for(unsigned int if1 = 0; if1 < 2; ++if1) { for(unsigned int if2 = 0; if2 < 4; ++if2) { - if(ferm) (*ME())(if1, if2, 0) = - vertex_->evaluate(scale,wave_[if1],RSwavebar_[if2],scal); - else (*ME())(if1, if2, 0) = - vertex_->evaluate(scale,RSwave_[if2],wavebar_[if1],scal); + (*ME())(if1, if2, 0) = 0.; + for(auto vert : vertex_) { + if(ferm) (*ME())(if1, if2, 0) += + vert->evaluate(scale,wave_[if1],RSwavebar_[if2],scal); + else (*ME())(if1, if2, 0) += + vert->evaluate(scale,RSwave_[if2],wavebar_[if1],scal); + } } } double output = (ME()->contract(rho_)).real()/scale*UnitRemoval::E2; // colour and identical particle factors output *= colourFactor(inpart.dataPtr(),decay[0]->dataPtr(), decay[1]->dataPtr()); // test code // Energy q = inpart.mass(); // Energy m1 = decay[0]->mass(); // Energy m2 = decay[1]->mass(); // Energy2 q2(q*q),m12(m1*m1),m22(m2*m2); // Energy2 pcm2(0.25*(q2*(q2-2.*m12-2.*m22)+(m12-m22)*(m12-m22))/q2); // Energy pcm(sqrt(pcm2)); // Energy Qp(sqrt((q+m1)*(q+m1)-m22)),Qm(sqrt((q-m1)*(q-m1)-m22)); // double r23(sqrt(2./3.)); // // couplings // Complex left = perturbativeVertex_-> left()*perturbativeVertex_-> norm(); // Complex right = perturbativeVertex_->right()*perturbativeVertex_-> norm(); // complex A1 = 0.5*(left+right)*UnitRemoval::InvE; // complex B1 = 0.5*(right-left)*UnitRemoval::InvE; // complex h1(-2.*r23*pcm*q/m1*Qm*B1); // complex h2( 2.*r23*pcm*q/m1*Qp*A1); // cout << "testing 1/2->3/2 0 " // << output*scale/GeV2 << " " // << real(h1*conj(h1)+h2*conj(h2))/4./GeV2 << " " // << real(h1*conj(h1)+h2*conj(h2))/4./(output*scale) << endl; // return the answer return output; } Energy FRSDecayer::partialWidth(PMPair inpart, PMPair outa, PMPair outb) const { if( inpart.second < outa.second + outb.second ) return ZERO; - if(perturbativeVertex_) { + if(perturbativeVertex_.size()==1 && + perturbativeVertex_[0]) { Energy q = inpart.second; Energy m1 = outa.second; Energy m2 = outb.second; Energy2 q2(q*q),m12(m1*m1),m22(m2*m2); Energy2 pcm2(0.25*(q2*(q2-2.*m12-2.*m22)+(m12-m22)*(m12-m22))/q2); Energy pcm(sqrt(pcm2)); Energy Qp(sqrt((q+m1)*(q+m1)-m22)),Qm(sqrt((q-m1)*(q-m1)-m22)); double r23(sqrt(2./3.)); // couplings tcPDPtr in = inpart.first->CC() ? tcPDPtr(inpart.first->CC()) : inpart.first; - perturbativeVertex_->setCoupling(sqr(inpart.second), outa.first, + perturbativeVertex_[0]->setCoupling(sqr(inpart.second), outa.first, in, outb.first); - Complex left = perturbativeVertex_-> left()*perturbativeVertex_-> norm(); - Complex right = perturbativeVertex_->right()*perturbativeVertex_-> norm(); + Complex left = perturbativeVertex_[0]-> left()*perturbativeVertex_[0]-> norm(); + Complex right = perturbativeVertex_[0]->right()*perturbativeVertex_[0]-> norm(); complex A1 = 0.5*(left+right)*UnitRemoval::InvE; complex B1 = 0.5*(right-left)*UnitRemoval::InvE; complex h1(-2.*r23*pcm*q/m1*Qm*B1); complex h2( 2.*r23*pcm*q/m1*Qp*A1); double me2 = real(h1*conj(h1)+h2*conj(h2))/4./sqr(inpart.second); Energy output = me2*pcm/8./Constants::pi; // colour factor output *= colourFactor(inpart.first,outa.first,outb.first); // return the answer return output; } else { return GeneralTwoBodyDecayer::partialWidth(inpart,outa,outb); } } diff --git a/Decay/General/FRSDecayer.h b/Decay/General/FRSDecayer.h --- a/Decay/General/FRSDecayer.h +++ b/Decay/General/FRSDecayer.h @@ -1,163 +1,164 @@ // -*- C++ -*- // // FRSDecayer.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_FRSDecayer_H #define HERWIG_FRSDecayer_H // // This is the declaration of the FRSDecayer class. // #include "GeneralTwoBodyDecayer.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Helicity/Vertex/Scalar/RFSVertex.h" namespace Herwig { using namespace ThePEG; using Helicity::RFSVertexPtr; /** \ingroup Decay * The FRSDecayer class implements the decay of a fermion * to a spin-3/2 fermion and a vector in a general model. It holds an RFVVertex * pointer that must be typecast from the VertexBase pointer held in * GeneralTwoBodyDecayer. It implents the virtual functions me2() and * partialWidth(). * * @see GeneralTwoBodyDecayer */ class FRSDecayer: public GeneralTwoBodyDecayer { public: /** * The default constructor. */ FRSDecayer() {} /** @name Virtual functions required by the Decayer class. */ //@{ /** * Return the matrix element squared for a given mode and phase-space channel. * @param ichan The channel we are calculating the matrix element for. * @param part The decaying Particle. * @param decay The particles produced in the decay. * @param meopt Option for the calculation of the matrix element * @return The matrix element squared for the phase-space configuration. */ virtual double me2(const int ichan, const Particle & part, const ParticleVector & decay, MEOption meopt) const; /** * Function to return partial Width * @param inpart The decaying particle. * @param outa One of the decay products. * @param outb The other decay product. */ virtual Energy partialWidth(PMPair inpart, PMPair outa, PMPair outb) const; /** * Set the information on the decay */ - virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, VertexBasePtr, + virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, + vector, map &, const vector > &, map); //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FRSDecayer & operator=(const FRSDecayer &); private: /** * Abstract pointer to AbstractFRSVertex */ - AbstractRFSVertexPtr vertex_; + vector vertex_; /** * Pointer to the perturbative vertex */ - RFSVertexPtr perturbativeVertex_; + vector perturbativeVertex_; /** * Spin density matrix */ mutable RhoDMatrix rho_; /** * Spinor wavefunctions */ mutable vector wave_ ; /** * Barred spinor wavefunctions */ mutable vector wavebar_; /** * RS Spinor wavefunctions */ mutable vector RSwave_ ; /** * Barred RS spinor wavefunctions */ mutable vector RSwavebar_; }; } #endif /* HERWIG_FRSDecayer_H */ diff --git a/Decay/General/FRVDecayer.cc b/Decay/General/FRVDecayer.cc --- a/Decay/General/FRVDecayer.cc +++ b/Decay/General/FRVDecayer.cc @@ -1,213 +1,219 @@ // -*- C++ -*- // // FRVDecayer.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 FRVDecayer class. // #include "FRVDecayer.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" #include "Herwig/Utilities/Kinematics.h" #include "Herwig/Decay/GeneralDecayMatrixElement.h" using namespace Herwig; using namespace ThePEG::Helicity; IBPtr FRVDecayer::clone() const { return new_ptr(*this); } IBPtr FRVDecayer::fullclone() const { return new_ptr(*this); } void FRVDecayer::setDecayInfo(PDPtr incoming, PDPair outgoing, - VertexBasePtr vertex, + vector vertex, map &, const vector > &, map) { decayInfo(incoming,outgoing); - vertex_ = dynamic_ptr_cast(vertex); - perturbativeVertex_ = dynamic_ptr_cast (vertex); + for(auto vert : vertex) { + vertex_ .push_back(dynamic_ptr_cast(vert)); + perturbativeVertex_.push_back(dynamic_ptr_cast (vert)); + } } void FRVDecayer::persistentOutput(PersistentOStream & os) const { os << vertex_ << perturbativeVertex_; } void FRVDecayer::persistentInput(PersistentIStream & is, int) { is >> vertex_ >> perturbativeVertex_; } double FRVDecayer::me2(const int , const Particle & inpart, const ParticleVector & decay, MEOption meopt) const { if(!ME()) ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin1Half,PDT::Spin3Half,PDT::Spin1))); // decaying fermion or antifermion bool ferm = inpart.id() > 0; // initialize if(meopt==Initialize) { // spinors and rho if(ferm) { SpinorWaveFunction ::calculateWaveFunctions(wave_,rho_, const_ptr_cast(&inpart), incoming); if(wave_[0].wave().Type() != SpinorType::u) for(unsigned int ix = 0; ix < 2; ++ix) wave_ [ix].conjugate(); } else { SpinorBarWaveFunction::calculateWaveFunctions(wavebar_,rho_, const_ptr_cast(&inpart), incoming); if(wavebar_[0].wave().Type() != SpinorType::v) for(unsigned int ix = 0; ix < 2; ++ix) wavebar_[ix].conjugate(); } } // setup spin info when needed if(meopt==Terminate) { // for the decaying particle if(ferm) { SpinorWaveFunction:: constructSpinInfo(wave_,const_ptr_cast(&inpart),incoming,true); RSSpinorBarWaveFunction::constructSpinInfo(RSwavebar_,decay[0],outgoing,true); } else { SpinorBarWaveFunction:: constructSpinInfo(wavebar_,const_ptr_cast(&inpart),incoming,true); RSSpinorWaveFunction::constructSpinInfo(RSwave_,decay[0],outgoing,true); } VectorWaveFunction:: constructSpinInfo(vector_,decay[1],outgoing,true,false); } Energy2 scale(sqr(inpart.mass())); if(ferm) RSSpinorBarWaveFunction:: calculateWaveFunctions(RSwavebar_,decay[0],outgoing); else RSSpinorWaveFunction:: calculateWaveFunctions(RSwave_ ,decay[0],outgoing); bool massless = decay[1]->dataPtr()->mass()==ZERO; VectorWaveFunction:: calculateWaveFunctions(vector_,decay[1],outgoing,massless); // loop over helicities for(unsigned int if1 = 0; if1 < 2; ++if1) { for(unsigned int if2 = 0; if2 < 4; ++if2) { for(unsigned int vhel = 0; vhel < 3; ++vhel) { if(massless && vhel == 1) ++vhel; - if(ferm) - (*ME())(if1, if2,vhel) = - vertex_->evaluate(scale,wave_[if1], - RSwavebar_[if2],vector_[vhel]); - else - (*ME())(if1, if2, vhel) = - vertex_->evaluate(scale,RSwave_[if2], - wavebar_[if1],vector_[vhel]); + (*ME())(if1, if2,vhel) = 0.; + for(auto vert : vertex_) { + if(ferm) + (*ME())(if1, if2,vhel) += + vert->evaluate(scale,wave_[if1], + RSwavebar_[if2],vector_[vhel]); + else + (*ME())(if1, if2, vhel) += + vert->evaluate(scale,RSwave_[if2], + wavebar_[if1],vector_[vhel]); + } } } } double output=(ME()->contract(rho_)).real()/scale*UnitRemoval::E2; // test // Energy m1(inpart.mass()),m2(decay[0]->mass()),m3(decay[1]->mass()); // Energy2 m12(m1*m1),m22(m2*m2),m32(m3*m3); // Energy Qp(sqrt(sqr(m1+m2)-sqr(m3))),Qm(sqrt(sqr(m1-m2)-sqr(m3))); // double r2(sqrt(2.)),r3(sqrt(3.)); // Energy pcm(Kinematics::pstarTwoBodyDecay(m1,m2,m3)); // vector left = perturbativeVertex_-> left(); // vector right = perturbativeVertex_->right(); // Complex A1 = 0.5*(left [0]+right[0])*perturbativeVertex_-> norm(); // Complex B1 = 0.5*(right[0]- left[0])*perturbativeVertex_-> norm(); // complex A2 = 0.5*(left [1]+right[1])*perturbativeVertex_-> norm()*UnitRemoval::InvE; // complex B2 = 0.5*(right[1]- left[1])*perturbativeVertex_-> norm()*UnitRemoval::InvE; // complex A3 = 0.5*(left [2]+right[2])*perturbativeVertex_-> norm()*UnitRemoval::InvE2; // complex B3 = 0.5*(right[2]- left[2])*perturbativeVertex_-> norm()*UnitRemoval::InvE2; // complex h1(-2.*Qp*A1),h2(2.*Qm*B1); // complex h3(-2./r3*Qp*(A1-Qm*Qm/m2*A2)); // complex h4( 2./r3*Qm*(B1-Qp*Qp/m2*B2)); // complex h5(ZERO),h6(ZERO); // if(decay[1]->mass()>ZERO) { // h5 = -2.*r2/r3/m2/m3*Qp*(0.5*(m12-m22-m32)*A1+0.5*Qm*Qm*(m1+m2)*A2 // +m12*pcm*pcm*A3); // h6 = 2.*r2/r3/m2/m3*Qm*(0.5*(m12-m22-m32)*B1-0.5*Qp*Qp*(m1-m2)*B2 // +m12*pcm*pcm*B3); // } // cout << "testing 1/2->3/2 1 " << inpart.id() << " " // << output << " " // << 0.25*(h1*conj(h1)+h2*conj(h2)+h3*conj(h3)+ // h4*conj(h4)+h5*conj(h5)+h6*conj(h6))/sqr(inpart.mass()) << " " // << 0.25*(h1*conj(h1)+h2*conj(h2)+h3*conj(h3)+ // h4*conj(h4)+h5*conj(h5)+h6*conj(h6))/sqr(inpart.mass())/output << endl; // colour and identical particle factors output *= colourFactor(inpart.dataPtr(),decay[0]->dataPtr(),decay[1]->dataPtr()); // return the answer return output; } Energy FRVDecayer::partialWidth(PMPair inpart, PMPair outa, PMPair outb) const { if( inpart.second < outa.second + outb.second ) return ZERO; - if(perturbativeVertex_) { + if(perturbativeVertex_.size()==1 && + perturbativeVertex_[0]) { Energy m1(inpart.second),m2(outa.second),m3(outb.second); Energy2 m12(m1*m1),m22(m2*m2),m32(m3*m3); Energy Qp(sqrt(sqr(m1+m2)-sqr(m3))),Qm(sqrt(sqr(m1-m2)-sqr(m3))); double r2(sqrt(2.)),r3(sqrt(3.)); Energy pcm(Kinematics::pstarTwoBodyDecay(m1,m2,m3)); // couplings tcPDPtr in = inpart.first->CC() ? tcPDPtr(inpart.first->CC()) : inpart.first; - perturbativeVertex_->setCoupling(sqr(inpart.second), outa.first, + perturbativeVertex_[0]->setCoupling(sqr(inpart.second), outa.first, in, outb.first); - vector left = perturbativeVertex_-> left(); - vector right = perturbativeVertex_->right(); - Complex A1 = 0.5*(left [0]+right[0])*perturbativeVertex_-> norm(); - Complex B1 = 0.5*(right[0]- left[0])*perturbativeVertex_-> norm(); - complex A2 = 0.5*(left [1]+right[1])*perturbativeVertex_-> norm()*UnitRemoval::InvE; - complex B2 = 0.5*(right[1]- left[1])*perturbativeVertex_-> norm()*UnitRemoval::InvE; - complex A3 = 0.5*(left [2]+right[2])*perturbativeVertex_-> norm()*UnitRemoval::InvE2; - complex B3 = 0.5*(right[2]- left[2])*perturbativeVertex_-> norm()*UnitRemoval::InvE2; + vector left = perturbativeVertex_[0]-> left(); + vector right = perturbativeVertex_[0]->right(); + Complex A1 = 0.5*(left [0]+right[0])*perturbativeVertex_[0]-> norm(); + Complex B1 = 0.5*(right[0]- left[0])*perturbativeVertex_[0]-> norm(); + complex A2 = 0.5*(left [1]+right[1])*perturbativeVertex_[0]-> norm()*UnitRemoval::InvE; + complex B2 = 0.5*(right[1]- left[1])*perturbativeVertex_[0]-> norm()*UnitRemoval::InvE; + complex A3 = 0.5*(left [2]+right[2])*perturbativeVertex_[0]-> norm()*UnitRemoval::InvE2; + complex B3 = 0.5*(right[2]- left[2])*perturbativeVertex_[0]-> norm()*UnitRemoval::InvE2; complex h1(-2.*Qp*A1),h2(2.*Qm*B1); complex h3(-2./r3*Qp*(A1-Qm*Qm/m2*A2)); complex h4( 2./r3*Qm*(B1-Qp*Qp/m2*B2)); complex h5(ZERO),h6(ZERO); if(outb.second>ZERO) { h5 = -2.*r2/r3/m2/m3*Qp*(0.5*(m12-m22-m32)*A1+0.5*Qm*Qm*(m1+m2)*A2 +m12*pcm*pcm*A3); h6 = 2.*r2/r3/m2/m3*Qm*(0.5*(m12-m22-m32)*B1-0.5*Qp*Qp*(m1-m2)*B2 +m12*pcm*pcm*B3); } double me2 = 0.25*real(h1*conj(h1)+h2*conj(h2)+h3*conj(h3)+ h4*conj(h4)+h5*conj(h5)+h6*conj(h6))/sqr(inpart.second); Energy output = me2*pcm/8./Constants::pi; // colour factor output *= colourFactor(inpart.first,outa.first,outb.first); return output; } else { return GeneralTwoBodyDecayer::partialWidth(inpart,outa,outb); } } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigFRVDecayer("Herwig::FRVDecayer", "Herwig.so"); void FRVDecayer::Init() { static ClassDocumentation documentation ("The FRVDecayer class handles the decay of a fermion to " "a spin-3/2 particle and a vector boson."); } diff --git a/Decay/General/FRVDecayer.h b/Decay/General/FRVDecayer.h --- a/Decay/General/FRVDecayer.h +++ b/Decay/General/FRVDecayer.h @@ -1,170 +1,171 @@ // -*- C++ -*- // // FRVDecayer.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_FRVDecayer_H #define HERWIG_FRVDecayer_H // // This is the declaration of the FRVDecayer class. // #include "GeneralTwoBodyDecayer.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Helicity/Vertex/Vector/RFVVertex.h" namespace Herwig { using namespace ThePEG; using Helicity::RFVVertexPtr; /** \ingroup Decay * The FRVDecayer class implements the decay of a fermion * to a spin-3/2 fermion and a vector in a general model. It holds an RFVVertex * pointer that must be typecast from the VertexBase pointer held in * GeneralTwoBodyDecayer. It implents the virtual functions me2() and * partialWidth(). * * @see GeneralTwoBodyDecayer */ class FRVDecayer: public GeneralTwoBodyDecayer { public: /** * The default constructor. */ FRVDecayer() {} public: /** @name Virtual functions required by the Decayer class. */ //@{ /** * Return the matrix element squared for a given mode and phase-space channel. * @param ichan The channel we are calculating the matrix element for. * @param part The decaying Particle. * @param decay The particles produced in the decay. * @param meopt Option for the matrix element * @return The matrix element squared for the phase-space configuration. */ virtual double me2(const int ichan, const Particle & part, const ParticleVector & decay, MEOption meopt) const; /** * Function to return partial Width * @param inpart The decaying particle. * @param outa One of the decay products. * @param outb The other decay product. */ virtual Energy partialWidth(PMPair inpart, PMPair outa, PMPair outb) const; /** * Set the information on the decay */ - virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, VertexBasePtr, + virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, + vector, map &, const vector > &, map); //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FRVDecayer & operator=(const FRVDecayer &); private: /** * Abstract pointer to AbstractFRVVertex */ - AbstractRFVVertexPtr vertex_; + vector vertex_; /** * Pointer to the perturbative vertex */ - RFVVertexPtr perturbativeVertex_; + vector perturbativeVertex_; /** * Spin density matrix */ mutable RhoDMatrix rho_; /** * Spinor wavefunction */ mutable vector wave_ ; /** * Barred spinor wavefunction */ mutable vector wavebar_; /** * RS Spinor wavefunction */ mutable vector RSwave_ ; /** * Barred RS spinor wavefunction */ mutable vector RSwavebar_; /** * Polarization vectors */ mutable vector vector_; }; } #endif /* HERWIG_FRVDecayer_H */ diff --git a/Decay/General/FtoFFFDecayer.cc b/Decay/General/FtoFFFDecayer.cc --- a/Decay/General/FtoFFFDecayer.cc +++ b/Decay/General/FtoFFFDecayer.cc @@ -1,308 +1,309 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the FtoFFFDecayer class. // #include "FtoFFFDecayer.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/Decay/DecayPhaseSpaceMode.h" #include "Herwig/PDT/ThreeBodyAllOnCalculator.h" #include "Herwig/Decay/GeneralDecayMatrixElement.h" #include using namespace Herwig; IBPtr FtoFFFDecayer::clone() const { return new_ptr(*this); } IBPtr FtoFFFDecayer::fullclone() const { return new_ptr(*this); } void FtoFFFDecayer::persistentOutput(PersistentOStream & os) const { os << sca_ << vec_ << ten_; } void FtoFFFDecayer::persistentInput(PersistentIStream & is, int) { is >> sca_ >> vec_ >> ten_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigFtoFFFDecayer("Herwig::FtoFFFDecayer", "Herwig.so"); void FtoFFFDecayer::Init() { static ClassDocumentation documentation ("The FtoFFFDecayer class implements the general decay of a fermion to " "three fermions."); } void FtoFFFDecayer::doinit() { GeneralThreeBodyDecayer::doinit(); + if(outgoing().empty()) return; unsigned int ndiags = getProcessInfo().size(); sca_.resize(ndiags); vec_.resize(ndiags); ten_.resize(ndiags); for(unsigned int ix = 0;ix < ndiags; ++ix) { TBDiagram current = getProcessInfo()[ix]; tcPDPtr offshell = current.intermediate; if( offshell->CC() ) offshell = offshell->CC(); if(offshell->iSpin() == PDT::Spin0) { AbstractFFSVertexPtr vert1 = dynamic_ptr_cast (current.vertices.first); AbstractFFSVertexPtr vert2 = dynamic_ptr_cast (current.vertices.second); if(!vert1||!vert2) throw Exception() << "Invalid vertices for a scalar diagram in FtoFFFDecayer::doinit()" << Exception::runerror; sca_[ix] = make_pair(vert1, vert2); } else if(offshell->iSpin() == PDT::Spin1) { AbstractFFVVertexPtr vert1 = dynamic_ptr_cast (current.vertices.first); AbstractFFVVertexPtr vert2 = dynamic_ptr_cast (current.vertices.second); if(!vert1||!vert2) throw Exception() << "Invalid vertices for a vector diagram in FtoFFFDecayer::doinit()" << Exception::runerror; vec_[ix] = make_pair(vert1, vert2); } else if(offshell->iSpin() == PDT::Spin2) { AbstractFFTVertexPtr vert1 = dynamic_ptr_cast (current.vertices.first); AbstractFFTVertexPtr vert2 = dynamic_ptr_cast (current.vertices.second); if(!vert1||!vert2) throw Exception() << "Invalid vertices for a tensor diagram in FtoFFFDecayer::doinit()" << Exception::runerror; ten_[ix] = make_pair(vert1, vert2); } } } double FtoFFFDecayer::me2(const int ichan, const Particle & inpart, const ParticleVector & decay, MEOption meopt) const { // particle or CC of particle bool cc = (*getProcessInfo().begin()).incoming != inpart.id(); // special handling or first/last call const vector > cfactors(getColourFactors()); const vector > nfactors(getLargeNcColourFactors()); const size_t ncf(numberOfFlows()); Energy2 scale(sqr(inpart.mass())); if(meopt==Initialize) { SpinorWaveFunction:: calculateWaveFunctions(inwave_.first,rho_,const_ptr_cast(&inpart), Helicity::incoming); inwave_.second.resize(2); if(inwave_.first[0].wave().Type() == SpinorType::u) { for(unsigned int ix = 0; ix < 2; ++ix) { inwave_.second[ix] = inwave_.first[ix].bar(); inwave_.second[ix].conjugate(); } } else { for(unsigned int ix = 0; ix < 2; ++ix) { inwave_.second[ix] = inwave_.first[ix].bar(); inwave_.first[ix].conjugate(); } } } // setup spin info when needed if(meopt==Terminate) { // for the decaying particle if(inpart.id()<0) SpinorWaveFunction::constructSpinInfo(inwave_.first, const_ptr_cast(&inpart), Helicity::incoming,true); else SpinorBarWaveFunction::constructSpinInfo(inwave_.second, const_ptr_cast(&inpart), Helicity::incoming,true); // outgoing particles for(unsigned int ix = 0; ix < 3; ++ix) { SpinorWaveFunction:: constructSpinInfo(outwave_[ix].first,decay[ix],Helicity::outgoing,true); } } // outgoing particles for(unsigned int ix = 0; ix < 3; ++ix) { SpinorWaveFunction:: calculateWaveFunctions(outwave_[ix].first,decay[ix],Helicity::outgoing); outwave_[ix].second.resize(2); if(outwave_[ix].first[0].wave().Type() == SpinorType::u) { for(unsigned int iy = 0; iy < 2; ++iy) { outwave_[ix].second[iy] = outwave_[ix].first[iy].bar(); outwave_[ix].first[iy].conjugate(); } } else { for(unsigned int iy = 0; iy < 2; ++iy) { outwave_[ix].second[iy] = outwave_[ix].first[iy].bar(); outwave_[ix].second[iy].conjugate(); } } } bool ferm = inpart.id()>0; vector flows(ncf, Complex(0.)),largeflows(ncf, Complex(0.)); static const unsigned int out2[3]={1,0,0},out3[3]={2,2,1}; vector mes(ncf,new_ptr(GeneralDecayMatrixElement(PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1Half,PDT::Spin1Half))); vector mel(ncf,new_ptr(GeneralDecayMatrixElement(PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1Half,PDT::Spin1Half))); unsigned int ihel[4]; for(ihel[0] = 0; ihel[0] < 2; ++ihel[0]) { for(ihel[1] = 0; ihel[1] < 2; ++ihel[1]) { for(ihel[2] = 0; ihel[2] < 2; ++ihel[2]) { for(ihel[3] = 0; ihel[3] < 2; ++ihel[3]) { flows = vector(ncf, Complex(0.)); largeflows = vector(ncf, Complex(0.)); unsigned int idiag=0; for(vector::const_iterator dit=getProcessInfo().begin(); dit!=getProcessInfo().end();++dit) { if(ichan>=0&&diagramMap()[ichan]!=idiag) { ++idiag; continue; } // the sign from normal ordering double sign = ferm ? 1. : -1; // outgoing wavefunction and NO sign if (dit->channelType==TBDiagram::channel23) sign *= -1.; else if(dit->channelType==TBDiagram::channel13) sign *= 1.; else if(dit->channelType==TBDiagram::channel12) sign *= -1.; else throw Exception() << "Unknown diagram type in FtoFFFDecayer::me2()" << Exception::runerror; // wavefunctions SpinorWaveFunction w0,w3; SpinorBarWaveFunction w1,w2; // incoming wavefunction if(ferm) { w0 = inwave_.first [ihel[0]]; w1 = outwave_[dit->channelType].second[ihel[dit->channelType+1]]; } else { w0 = outwave_[dit->channelType].first [ihel[dit->channelType+1]]; w1 = inwave_.second[ihel[0]]; } if(decay[out2[dit->channelType]]->id()<0&& decay[out3[dit->channelType]]->id()>0) { w2 = outwave_[out3[dit->channelType]].second[ihel[out3[dit->channelType]+1]]; w3 = outwave_[out2[dit->channelType]].first [ihel[out2[dit->channelType]+1]]; sign *= -1.; } else { w2 = outwave_[out2[dit->channelType]].second[ihel[out2[dit->channelType]+1]]; w3 = outwave_[out3[dit->channelType]].first [ihel[out3[dit->channelType]+1]]; } tcPDPtr offshell = dit->intermediate; if(cc&&offshell->CC()) offshell=offshell->CC(); Complex diag(0.); // intermediate scalar if (offshell->iSpin() == PDT::Spin0) { ScalarWaveFunction inters = sca_[idiag].first-> evaluate(scale, widthOption(), offshell, w0, w1); diag = sca_[idiag].second->evaluate(scale,w3,w2,inters); } // intermediate vector else if(offshell->iSpin() == PDT::Spin1) { VectorWaveFunction interv = vec_[idiag].first-> evaluate(scale, widthOption(), offshell, w0, w1); diag = vec_[idiag].second->evaluate(scale,w3,w2,interv); } // intermediate tensor else if(offshell->iSpin() == PDT::Spin2) { TensorWaveFunction intert = ten_[idiag].first-> evaluate(scale, widthOption(), offshell, w0, w1); diag = ten_[idiag].second->evaluate(scale,w3,w2,intert); } // unknown else throw Exception() << "Unknown intermediate in FtoFFFDecayer::me2()" << Exception::runerror; // apply NO sign diag *= sign; // matrix element for the different colour flows if(ichan<0) { for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) { flows[dit->colourFlow[iy].first - 1] += dit->colourFlow[iy].second * diag; } for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) { largeflows[dit->largeNcColourFlow[iy].first - 1] += dit->largeNcColourFlow[iy].second * diag; } } else { for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) { if(dit->colourFlow[iy].first - 1!=colourFlow()) continue; flows[dit->colourFlow[iy].first - 1] += dit->colourFlow[iy].second * diag; } for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) { if(dit->colourFlow[iy].first - 1!=colourFlow()) continue; largeflows[dit->largeNcColourFlow[iy].first - 1] += dit->largeNcColourFlow[iy].second * diag; } } ++idiag; } // now add the flows to the me2 with appropriate colour factors for(unsigned int ix = 0; ix < ncf; ++ix) { (*mes[ix])(ihel[0],ihel[1],ihel[2],ihel[3]) = flows[ix]; (*mel[ix])(ihel[0],ihel[1],ihel[2],ihel[3]) = largeflows[ix]; } } } } } double me2(0.); if(ichan<0) { vector pflows(ncf,0.); for(unsigned int ix = 0; ix < ncf; ++ix) { for(unsigned int iy = 0; iy < ncf; ++ iy) { double con = cfactors[ix][iy]*(mes[ix]->contract(*mes[iy],rho_)).real(); me2 += con; if(ix==iy) { con = nfactors[ix][iy]*(mel[ix]->contract(*mel[iy],rho_)).real(); pflows[ix] += con; } } } double ptotal(std::accumulate(pflows.begin(),pflows.end(),0.)); ptotal *=UseRandom::rnd(); for(unsigned int ix=0;ixcontract(*mel[iflow],rho_)).real(); } // return the matrix element squared return me2; } WidthCalculatorBasePtr FtoFFFDecayer:: threeBodyMEIntegrator(const DecayMode & ) const { vector intype; vector inmass,inwidth; vector inpow,inweights; constructIntegratorChannels(intype,inmass,inwidth,inpow,inweights); return new_ptr(ThreeBodyAllOnCalculator (inweights,intype,inmass,inwidth,inpow,*this,0, outgoing()[0]->mass(),outgoing()[1]->mass(),outgoing()[2]->mass(), relativeError())); } diff --git a/Decay/General/FtoFVVDecayer.cc b/Decay/General/FtoFVVDecayer.cc --- a/Decay/General/FtoFVVDecayer.cc +++ b/Decay/General/FtoFVVDecayer.cc @@ -1,400 +1,401 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the FtoFVVDecayer class. // #include "FtoFVVDecayer.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/Decay/DecayPhaseSpaceMode.h" #include "Herwig/PDT/ThreeBodyAllOnCalculator.h" #include "Herwig/Decay/GeneralDecayMatrixElement.h" #include using namespace Herwig; IBPtr FtoFVVDecayer::clone() const { return new_ptr(*this); } IBPtr FtoFVVDecayer::fullclone() const { return new_ptr(*this); } void FtoFVVDecayer::persistentOutput(PersistentOStream & os) const { os << sca_ << fer_ << vec_ << ten_; } void FtoFVVDecayer::persistentInput(PersistentIStream & is, int) { is >> sca_ >> fer_ >> vec_ >> ten_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigFtoFVVDecayer("Herwig::FtoFVVDecayer", "Herwig.so"); void FtoFVVDecayer::Init() { static ClassDocumentation documentation ("The FtoFVVDecayer class implements the general decay of a fermion to " "a fermion and a pair of vectors."); } void FtoFVVDecayer::doinit() { GeneralThreeBodyDecayer::doinit(); + if(outgoing().empty()) return; unsigned int ndiags = getProcessInfo().size(); sca_.resize(ndiags); fer_.resize(ndiags); vec_.resize(ndiags); ten_.resize(ndiags); for(unsigned int ix = 0;ix < ndiags; ++ix) { TBDiagram current = getProcessInfo()[ix]; tcPDPtr offshell = current.intermediate; if(offshell->iSpin() == PDT::Spin0) { AbstractFFSVertexPtr vert1 = dynamic_ptr_cast (current.vertices.first); AbstractVVSVertexPtr vert2 = dynamic_ptr_cast (current.vertices.second); if(!vert1||!vert2) throw Exception() << "Invalid vertices for a scalar diagram in FtoFVVDecayer::doinit()" << Exception::runerror; sca_[ix] = make_pair(vert1, vert2); } else if(offshell->iSpin() == PDT::Spin1Half) { AbstractFFVVertexPtr vert1 = dynamic_ptr_cast (current.vertices.first); AbstractFFVVertexPtr vert2 = dynamic_ptr_cast (current.vertices.second); if(!vert1||!vert2) throw Exception() << "Invalid vertices for a scalar diagram in FtoFVVDecayer::doinit()" << Exception::runerror; fer_[ix] = make_pair(vert1, vert2); } else if(offshell->iSpin() == PDT::Spin1) { AbstractFFVVertexPtr vert1 = dynamic_ptr_cast (current.vertices.first); AbstractVVVVertexPtr vert2 = dynamic_ptr_cast (current.vertices.second); if(!vert1||!vert2) throw Exception() << "Invalid vertices for a vector diagram in FtoFVVDecayer::doinit()" << Exception::runerror; vec_[ix] = make_pair(vert1, vert2); } else if(offshell->iSpin() == PDT::Spin2) { AbstractFFTVertexPtr vert1 = dynamic_ptr_cast (current.vertices.first); AbstractVVTVertexPtr vert2 = dynamic_ptr_cast (current.vertices.second); if(!vert1||!vert2) throw Exception() << "Invalid vertices for a tensor diagram in FtoFVVDecayer::doinit()" << Exception::runerror; ten_[ix] = make_pair(vert1, vert2); } } } double FtoFVVDecayer::me2(const int ichan, const Particle & inpart, const ParticleVector & decay, MEOption meopt) const { // particle or CC of particle bool cc = (*getProcessInfo().begin()).incoming != inpart.id(); // special handling or first/last call //Set up wave-functions bool ferm( inpart.id() > 0 ); if(meopt==Initialize) { if( ferm ) { SpinorWaveFunction:: calculateWaveFunctions(fwave_,rho_,const_ptr_cast(&inpart), Helicity::incoming); if( fwave_[0].wave().Type() != SpinorType::u ) fwave_[0].conjugate(); if( fwave_[1].wave().Type() != SpinorType::u ) fwave_[1].conjugate(); } else { SpinorBarWaveFunction:: calculateWaveFunctions(fbwave_, rho_, const_ptr_cast(&inpart), Helicity::incoming); if( fbwave_[0].wave().Type() != SpinorType::v ) fbwave_[0].conjugate(); if( fbwave_[1].wave().Type() != SpinorType::v ) fbwave_[1].conjugate(); } } // setup spin info when needed if(meopt==Terminate) { // for the decaying particle if(ferm) SpinorWaveFunction::constructSpinInfo(fwave_, const_ptr_cast(&inpart), Helicity::incoming,true); else SpinorBarWaveFunction::constructSpinInfo(fbwave_, const_ptr_cast(&inpart), Helicity::incoming,true); int ivec(-1); // outgoing particles for(int ix = 0; ix < 3; ++ix) { tPPtr p = decay[ix]; if( p->dataPtr()->iSpin() == PDT::Spin1Half ) { if( ferm ) { SpinorBarWaveFunction:: constructSpinInfo(fbwave_, p, Helicity::outgoing,true); } else { SpinorWaveFunction:: constructSpinInfo(fwave_ , p, Helicity::outgoing,true); } } else if( p->dataPtr()->iSpin() == PDT::Spin1 ) { if( ivec < 0 ) { ivec = ix; VectorWaveFunction:: constructSpinInfo(vwave_.first , p, Helicity::outgoing, true, false); } else { VectorWaveFunction:: constructSpinInfo(vwave_.second, p, Helicity::outgoing, true, false); } } } return 0.; } // outgoing, keep track of fermion and first occurrence of vector positions int isp(-1), ivec(-1); // outgoing particles pair mass = make_pair(false,false); for(int ix = 0; ix < 3; ++ix) { tPPtr p = decay[ix]; if( p->dataPtr()->iSpin() == PDT::Spin1Half ) { isp = ix; if( ferm ) { SpinorBarWaveFunction:: calculateWaveFunctions(fbwave_, p, Helicity::outgoing); if( fbwave_[0].wave().Type() != SpinorType::u ) fbwave_[0].conjugate(); if( fbwave_[1].wave().Type() != SpinorType::u ) fbwave_[1].conjugate(); } else { SpinorWaveFunction:: calculateWaveFunctions(fwave_, p, Helicity::outgoing); if( fwave_[0].wave().Type() != SpinorType::v ) fwave_[0].conjugate(); if( fwave_[1].wave().Type() != SpinorType::v ) fwave_[1].conjugate(); } } else if( p->dataPtr()->iSpin() == PDT::Spin1 ) { bool massless = p->id() == ParticleID::gamma || p->id() == ParticleID::g; if( ivec < 0 ) { ivec = ix; VectorWaveFunction:: calculateWaveFunctions(vwave_.first , p, Helicity::outgoing, massless); mass.first = massless; } else { VectorWaveFunction:: calculateWaveFunctions(vwave_.second, p, Helicity::outgoing, massless); mass.second = massless; } } } assert(isp >= 0 && ivec >= 0); Energy2 scale(sqr(inpart.mass())); const vector > cfactors(getColourFactors()); const vector > nfactors(getLargeNcColourFactors()); const size_t ncf(numberOfFlows()); vector flows(ncf, Complex(0.)), largeflows(ncf, Complex(0.)); vector mes(ncf,new_ptr(GeneralDecayMatrixElement(PDT::Spin1Half, (isp == 0) ? PDT::Spin1Half : PDT::Spin1, (isp == 1) ? PDT::Spin1Half : PDT::Spin1, (isp == 2) ? PDT::Spin1Half : PDT::Spin1))); vector mel(ncf,new_ptr(GeneralDecayMatrixElement(PDT::Spin1Half, (isp == 0) ? PDT::Spin1Half : PDT::Spin1, (isp == 1) ? PDT::Spin1Half : PDT::Spin1, (isp == 2) ? PDT::Spin1Half : PDT::Spin1))); //Helicity calculation for( unsigned int if1 = 0; if1 < 2; ++if1 ) { for( unsigned int if2 = 0; if2 < 2; ++if2 ) { for( unsigned int iv1 = 0; iv1 < 3; ++iv1 ) { if ( mass.first && iv1 == 1 ) continue; for( unsigned int iv2 = 0; iv2 < 3; ++iv2 ) { if ( mass.second && iv2 == 1 ) continue; flows = vector(ncf, Complex(0.)); largeflows = vector(ncf, Complex(0.)); unsigned int idiag(0); for(vector::const_iterator dit = getProcessInfo().begin(); dit != getProcessInfo().end(); ++dit) { // If we are selecting a particular channel if( ichan >= 0 && diagramMap()[ichan] != idiag ) { ++idiag; continue; } tcPDPtr offshell = (*dit).intermediate; if(cc&&offshell->CC()) offshell=offshell->CC(); Complex diag; if( offshell->iSpin() == PDT::Spin1Half ) { // Make sure we connect the correct particles VectorWaveFunction vw1, vw2; if( (*dit).channelType == TBDiagram::channel23 ) { vw1 = vwave_.first[iv1]; vw2 = vwave_.second[iv2]; } else if( (*dit).channelType == TBDiagram::channel12 ) { vw1 = vwave_.second[iv2]; vw2 = vwave_.first[iv1]; } else { if( ivec < isp ) { vw1 = vwave_.second[iv2]; vw2 = vwave_.first[iv1]; } else { vw1 = vwave_.first[iv1]; vw2 = vwave_.second[iv2]; } } if( ferm ) { SpinorWaveFunction inters = fer_[idiag].first->evaluate(scale, widthOption(), offshell, fwave_[if1], vw1); diag = fer_[idiag].second->evaluate(scale, inters, fbwave_[if2], vw2); } else { SpinorBarWaveFunction inters = fer_[idiag].first->evaluate(scale, widthOption(), offshell, fbwave_[if2], vw1); diag = fer_[idiag].second->evaluate(scale, fwave_[if1], inters, vw2); } } else if( offshell->iSpin() == PDT::Spin0 ) { ScalarWaveFunction inters = sca_[idiag].first->evaluate(scale, widthOption(), offshell, fwave_[if1], fbwave_[if2]); diag = sca_[idiag].second->evaluate(scale, vwave_.first[iv1], vwave_.second[iv2], inters); } else if( offshell->iSpin() == PDT::Spin1 ) { VectorWaveFunction interv = vec_[idiag].first->evaluate(scale, widthOption(), offshell, fwave_[if1], fbwave_[if2]); diag = vec_[idiag].second->evaluate(scale, vwave_.first[iv1], vwave_.second[iv2], interv); } else if( offshell->iSpin() == PDT::Spin2 ) { TensorWaveFunction intert = ten_[idiag].first->evaluate(scale, widthOption(), offshell, fwave_[if1], fbwave_[if2]); diag = ten_[idiag].second->evaluate(scale, vwave_.first[iv1], vwave_.second[iv2], intert); } else throw Exception() << "Unknown intermediate in FtoFVVDecayer::me2()" << Exception::runerror; //NO sign if( !ferm ) diag *= -1; if(ichan<0) { for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) { flows[dit->colourFlow[iy].first - 1] += dit->colourFlow[iy].second * diag; } for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) { largeflows[dit->largeNcColourFlow[iy].first - 1] += dit->largeNcColourFlow[iy].second * diag; } } else { for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) { if(dit->colourFlow[iy].first - 1!=colourFlow()) continue; flows[dit->colourFlow[iy].first - 1] += dit->colourFlow[iy].second * diag; } for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) { if(dit->colourFlow[iy].first - 1!=colourFlow()) continue; largeflows[dit->largeNcColourFlow[iy].first - 1] += dit->largeNcColourFlow[iy].second * diag; } } ++idiag; }// end diagram loop // now add the flows to the me2 unsigned int h1(if1), h2(if2); if( !ferm ) swap(h1,h2); for(unsigned int ix = 0; ix < ncf; ++ix) { if(isp == 0) { (*mes[ix])(h1, h2, iv1, iv2) = flows[ix]; (*mel[ix])(h1, h2, iv1, iv2) = largeflows[ix]; } else if(isp == 1) { (*mes[ix])(h1, iv1, h2, iv2) = flows[ix]; (*mel[ix])(h1, iv1, h2, iv2) = largeflows[ix]; } else if(isp == 2) { (*mes[ix])(h1, iv1, iv2, h2) = flows[ix]; (*mel[ix])(h1, iv1, h2, iv2) = largeflows[ix]; } } }//v2 }//v1 }//f2 }//f1 //Finally, work out me2. This depends on whether we are selecting channels //or not double me2(0.); if(ichan<0) { vector pflows(ncf,0.); for(unsigned int ix = 0; ix < ncf; ++ix) { for(unsigned int iy = 0; iy < ncf; ++ iy) { double con = cfactors[ix][iy]*(mes[ix]->contract(*mes[iy],rho_)).real(); me2 += con; if(ix==iy) { con = nfactors[ix][iy]*(mel[ix]->contract(*mel[iy],rho_)).real(); pflows[ix] += con; } } } double ptotal(std::accumulate(pflows.begin(),pflows.end(),0.)); ptotal *= UseRandom::rnd(); for(unsigned int ix=0;ixcontract(*mel[iflow],rho_)).real(); } // return the matrix element squared return me2; } WidthCalculatorBasePtr FtoFVVDecayer:: threeBodyMEIntegrator(const DecayMode & ) const { vector intype; vector inmass,inwidth; vector inpow,inweights; constructIntegratorChannels(intype,inmass,inwidth,inpow,inweights); return new_ptr(ThreeBodyAllOnCalculator (inweights,intype,inmass,inwidth,inpow,*this,0, outgoing()[0]->mass(),outgoing()[1]->mass(), outgoing()[2]->mass(),relativeError())); } diff --git a/Decay/General/GeneralThreeBodyDecayer.cc b/Decay/General/GeneralThreeBodyDecayer.cc --- a/Decay/General/GeneralThreeBodyDecayer.cc +++ b/Decay/General/GeneralThreeBodyDecayer.cc @@ -1,1033 +1,1028 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the GeneralThreeBodyDecayer class. // #include "GeneralThreeBodyDecayer.h" #include "ThePEG/Utilities/DescribeClass.h" #include "Herwig/Decay/DecayPhaseSpaceMode.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/PDT/ThreeBodyAllOnCalculator.h" using namespace Herwig; void GeneralThreeBodyDecayer::persistentOutput(PersistentOStream & os) const { os << incoming_ << outgoing_ << diagrams_ << diagmap_ << colour_ << colourLargeNC_ << nflow_ << widthOpt_ << refTag_ << refTagCC_ << intOpt_ << relerr_; } void GeneralThreeBodyDecayer::persistentInput(PersistentIStream & is, int) { is >> incoming_ >> outgoing_ >> diagrams_ >> diagmap_ >> colour_ >> colourLargeNC_ >> nflow_ >> widthOpt_ >> refTag_ >> refTagCC_ >> intOpt_ >> relerr_; } // The following static variable is needed for the type // description system in ThePEG. DescribeAbstractClass describeHerwigGeneralThreeBodyDecayer("Herwig::GeneralThreeBodyDecayer", "Herwig.so"); void GeneralThreeBodyDecayer::Init() { static ClassDocumentation documentation ("The GeneralThreeBodyDecayer class is the base class for the implementation of" " all three body decays based on spin structures in Herwig."); static Switch interfaceWidthOption ("WidthOption", "Option for the treatment of the widths of the intermediates", &GeneralThreeBodyDecayer::widthOpt_, 1, false, false); static SwitchOption interfaceWidthOptionFixed (interfaceWidthOption, "Fixed", "Use fixed widths", 1); static SwitchOption interfaceWidthOptionRunning (interfaceWidthOption, "Running", "Use running widths", 2); static SwitchOption interfaceWidthOptionZero (interfaceWidthOption, "Zero", "Set the widths to zero", 3); static Switch interfacePartialWidthIntegration ("PartialWidthIntegration", "Switch to control the partial width integration", &GeneralThreeBodyDecayer::intOpt_, 0, false, false); static SwitchOption interfacePartialWidthIntegrationAllPoles (interfacePartialWidthIntegration, "AllPoles", "Include all potential poles", 0); static SwitchOption interfacePartialWidthIntegrationShallowestPole (interfacePartialWidthIntegration, "ShallowestPole", "Only include the shallowest pole", 1); static Parameter interfaceRelativeError ("RelativeError", "The relative error for the GQ integration of the partial width", &GeneralThreeBodyDecayer::relerr_, 1e-2, 1e-10, 1., false, false, Interface::limited); } ParticleVector GeneralThreeBodyDecayer::decay(const Particle & parent, const tPDVector & children) const { // return empty vector if products heavier than parent Energy mout(ZERO); for(tPDVector::const_iterator it=children.begin(); it!=children.end();++it) mout+=(**it).massMin(); if(mout>parent.mass()) return ParticleVector(); // generate the decay bool cc; int imode=modeNumber(cc,parent.dataPtr(),children); // generate the kinematics ParticleVector decay=generate(generateIntermediates(),cc,imode,parent); // make the colour connections colourConnections(parent, decay); // return the answer return decay; } int GeneralThreeBodyDecayer:: modeNumber(bool & cc, tcPDPtr in, const tPDVector & outin) const { assert( !refTag_.empty() && !refTagCC_.empty() ); // check number of outgoing particles if( outin.size() != 3 || abs(in->id()) != abs(incoming_->id()) ) return -1; OrderedParticles testmode(outin.begin(), outin.end()); OrderedParticles::const_iterator dit = testmode.begin(); string testtag(in->name() + "->"); for( unsigned int i = 1; dit != testmode.end(); ++dit, ++i) { testtag += (**dit).name(); if( i != 3 ) testtag += string(","); } if( testtag == refTag_ ) { cc = false; return 0; } else if ( testtag == refTagCC_ ) { cc = true; return 0; } else return -1; } bool GeneralThreeBodyDecayer::setDecayInfo(PDPtr incoming, vector outgoing, const vector & process, double symfac) { // set the member variables from the info supplied incoming_ = incoming; outgoing_ = outgoing; diagrams_ = process; assert( outgoing_.size() == 3 ); // Construct reference tags for testing in modeNumber function OrderedParticles refmode(outgoing_.begin(), outgoing_.end()); OrderedParticles::const_iterator dit = refmode.begin(); refTag_ = incoming_->name() + "->"; for( unsigned int i = 1; dit != refmode.end(); ++dit, ++i) { refTag_ += (**dit).name(); if( i != 3 ) refTag_ += string(","); } //CC-mode refmode.clear(); refTagCC_ = incoming_->CC() ? incoming_->CC()->name() : incoming_->name(); refTagCC_ += "->"; for( unsigned int i = 0; i < 3; ++i ) { if( outgoing_[i]->CC() ) refmode.insert( outgoing_[i]->CC() ); else refmode.insert( outgoing_[i] ); } dit = refmode.begin(); for( unsigned int i = 1; dit != refmode.end(); ++dit , ++i) { refTagCC_ += (**dit).name(); if( i != 3 ) refTagCC_ += string(","); } + // check if intermeidates or only four point diagrams + bool intermediates(false); + for(auto diagram : diagrams_) { + if(diagram.intermediate) { + intermediates=true; + break; + } + } + if(!intermediates) { + incoming_= PDPtr(); + outgoing_.clear(); + generator()->log() << "Only four body diagrams for decay " + << refTag_ << " in GeneralThreeBodyDecayer::" + << "setDecayInfo(), omitting decay\n"; + return false; + } // set the colour factors and return the answer - return setColourFactors(symfac); + if(setColourFactors(symfac)) return true; + incoming_= PDPtr(); + outgoing_.clear(); + return false; } void GeneralThreeBodyDecayer::doinit() { DecayIntegrator::doinit(); + if(outgoing_.empty()) return; // create the phase space integrator tPDVector extpart(1,incoming_); extpart.insert(extpart.end(),outgoing_.begin(),outgoing_.end()); // create the integration channels for the decay DecayPhaseSpaceModePtr mode(new_ptr(DecayPhaseSpaceMode(extpart,this,true))); DecayPhaseSpaceChannelPtr newchannel; // create the phase-space channels for the integration unsigned int nmode(0); for(unsigned int ix=0;ixmass() == ZERO || diagrams_[ix].intermediate->width() == ZERO ) { jac = 1; power = -2.0; } if(diagrams_[ix].channelType==TBDiagram::channel23) { newchannel->addIntermediate(extpart[0],0,0.0,-1,1); newchannel->addIntermediate(diagrams_[ix].intermediate,jac,power, 2,3); } else if(diagrams_[ix].channelType==TBDiagram::channel13) { newchannel->addIntermediate(extpart[0],0,0.0,-1,2); newchannel->addIntermediate(diagrams_[ix].intermediate,jac,power, 1,3); } else if(diagrams_[ix].channelType==TBDiagram::channel12) { newchannel->addIntermediate(extpart[0],0,0.0,-1,3); newchannel->addIntermediate(diagrams_[ix].intermediate,jac,power, 1,2); } diagmap_.push_back(ix); mode->addChannel(newchannel); ++nmode; } if(nmode==0) { string mode = extpart[0]->PDGName() + "->"; for(unsigned int ix=1;ixPDGName() + " "; throw Exception() << "No decay channels in GeneralThreeBodyDecayer::" << "doinit() for " << mode << "\n" << Exception::runerror; } // add the mode vector wgt(nmode,1./double(nmode)); addMode(mode,1.,wgt); } double GeneralThreeBodyDecayer:: threeBodyMatrixElement(const int imode, const Energy2 q2, const Energy2 s3, const Energy2 s2, const Energy2 s1, const Energy m1, const Energy m2, const Energy m3) const { // calculate the momenta of the outgoing particles Energy m0=sqrt(q2); // energies Energy eout[3] = {0.5*(q2+sqr(m1)-s1)/m0, 0.5*(q2+sqr(m2)-s2)/m0, 0.5*(q2+sqr(m3)-s3)/m0}; // magnitudes of the momenta Energy pout[3] = {sqrt(sqr(eout[0])-sqr(m1)), sqrt(sqr(eout[1])-sqr(m2)), sqrt(sqr(eout[2])-sqr(m3))}; double cos2 = 0.5*(sqr(pout[0])+sqr(pout[1])-sqr(pout[2]))/pout[0]/pout[1]; double cos3 = 0.5*(sqr(pout[0])-sqr(pout[1])+sqr(pout[2]))/pout[0]/pout[2]; double sin2 = sqrt(1.-sqr(cos2)), sin3 = sqrt(1.-sqr(cos3)); Lorentz5Momentum out[3]= {Lorentz5Momentum( ZERO , ZERO , pout[0] , eout[0] , m1), Lorentz5Momentum( pout[1]*sin2 , ZERO , -pout[1]*cos2 , eout[1] , m2), Lorentz5Momentum( -pout[2]*sin3 , ZERO , -pout[2]*cos3 , eout[2] , m3)}; // create the incoming PPtr inpart=mode(imode)->externalParticles(0)-> produceParticle(Lorentz5Momentum(sqrt(q2))); // and outgoing particles ParticleVector decay; for(unsigned int ix=1;ix<4;++ix) decay.push_back(mode(imode)->externalParticles(ix)->produceParticle(out[ix-1])); // return the matrix element return me2(-1,*inpart,decay,Initialize); } double GeneralThreeBodyDecayer::brat(const DecayMode &, const Particle & p, double oldbrat) const { ParticleVector children = p.children(); if( children.size() != 3 || !p.data().widthGenerator() ) return oldbrat; // partial width for this mode Energy scale = p.mass(); Energy pwidth = partialWidth( make_pair(p.dataPtr(), scale), make_pair(children[0]->dataPtr(), children[0]->mass()), make_pair(children[1]->dataPtr(), children[1]->mass()), make_pair(children[2]->dataPtr(), children[2]->mass()) ); Energy width = p.data().widthGenerator()->width(p.data(), scale); return pwidth/width; } Energy GeneralThreeBodyDecayer::partialWidth(PMPair inpart, PMPair outa, PMPair outb, PMPair outc) const { if(inpart.secondname() + "->"; tag += outgoing_[0]->name() + "," + outgoing_[1]->name() + "," + outgoing_[2]->name() + ";"; DMPtr dm = generator()->findDecayMode(tag); widthCalc_ = threeBodyMEIntegrator(*dm); } return widthCalc_->partialWidth(sqr(inpart.second)); } void GeneralThreeBodyDecayer:: colourConnections(const Particle & parent, const ParticleVector & out) const { // first extract the outgoing particles and intermediate PPtr inter; ParticleVector outgoing; if(!generateIntermediates()) { outgoing=out; } else { // find the diagram unsigned int idiag = diagramMap()[mode(imode())->selectedChannel()]; PPtr child; for(unsigned int ix=0;ixchildren().empty()) child = out[ix]; else inter = out[ix]; } outgoing.resize(3); switch(diagrams_[idiag].channelType) { case TBDiagram::channel23: outgoing[0] = child; outgoing[1] = inter->children()[0]; outgoing[2] = inter->children()[1]; break; case TBDiagram::channel13: outgoing[0] = inter->children()[0]; outgoing[1] = child; outgoing[2] = inter->children()[1]; break; case TBDiagram::channel12: outgoing[0] = inter->children()[0]; outgoing[1] = inter->children()[1]; outgoing[2] = child; break; default: throw Exception() << "unknown diagram type in GeneralThreeBodyDecayer::" << "colourConnections()" << Exception::runerror; } } // extract colour of the incoming and outgoing particles PDT::Colour inColour(parent.data().iColour()); vector outColour; vector singlet,octet,triplet,antitriplet; for(unsigned int ix=0;ixdata().iColour()); switch(outColour.back()) { case PDT::Colour0 : singlet.push_back(ix); break; case PDT::Colour3 : triplet.push_back(ix); break; case PDT::Colour3bar: antitriplet.push_back(ix); break; case PDT::Colour8 : octet.push_back(ix); break; default: throw Exception() << "Unknown colour for particle in GeneralThreeBodyDecayer::" << "colourConnections()" << Exception::runerror; } } // colour neutral decaying particle if ( inColour == PDT::Colour0) { // options are all neutral or triplet/antitriplet+ neutral if(singlet.size()==3) return; else if(singlet.size()==1&&triplet.size()==1&&antitriplet.size()==1) { outgoing[triplet[0]]->antiColourNeighbour(outgoing[antitriplet[0]]); // add intermediate if needed if(inter&&inter->coloured()) { if(inter->dataPtr()->iColour()==PDT::Colour3) outgoing[triplet[0]]->colourLine()->addColoured(inter); else if(inter->dataPtr()->iColour()==PDT::Colour3bar) outgoing[triplet[0]]->colourLine()->addAntiColoured(inter); } } else if(octet.size()==1&&triplet.size()==1&&antitriplet.size()==1) { outgoing[ triplet[0]]->antiColourNeighbour(outgoing[octet[0]]); outgoing[antitriplet[0]]-> colourNeighbour(outgoing[octet[0]]); if(inter&&inter->coloured()) { if(inter->dataPtr()->iColour()==PDT::Colour3) outgoing[antitriplet[0]]->antiColourLine()->addColoured(inter); else if(inter->dataPtr()->iColour()==PDT::Colour3bar) outgoing[ triplet[0]]-> colourLine()->addAntiColoured(inter); else if(inter->dataPtr()->iColour()==PDT::Colour8) { outgoing[antitriplet[0]]->antiColourLine()->addAntiColoured(inter); outgoing[ triplet[0]]-> colourLine()->addColoured(inter); } } } else if(triplet.size()==3) { tColinePtr col[3] = {ColourLine::create(outgoing[0]), ColourLine::create(outgoing[1]), ColourLine::create(outgoing[2])}; col[0]->setSourceNeighbours(col[1],col[2]); } else if(antitriplet.size()==3) { tColinePtr col[3] = {ColourLine::create(outgoing[0],true), ColourLine::create(outgoing[1],true), ColourLine::create(outgoing[2],true)}; col[0]->setSinkNeighbours(col[1],col[2]); } else { string mode = parent.PDGName() + " -> " + out[0]->PDGName() + " " + out[1]->PDGName() + " " + out[2]->PDGName(); throw Exception() << "Unknown colour structure in GeneralThreeBodyDecayer::" << "colourConnections() for singlet decaying particle " << mode << Exception::runerror; } } // colour triplet decaying particle else if( inColour == PDT::Colour3) { if(singlet.size()==2&&triplet.size()==1) { outgoing[triplet[0]]->incomingColour(const_ptr_cast(&parent)); if(inter&&inter->coloured()) outgoing[triplet[0]]->colourLine()->addColoured(inter); } else if(antitriplet.size()==1&&triplet.size()==2) { if(colourFlow()==0) { outgoing[triplet[0]]->incomingColour(const_ptr_cast(&parent)); outgoing[antitriplet[0]]->colourNeighbour(outgoing[triplet[1]]); if(inter&&inter->coloured()) { switch (inter->dataPtr()->iColour()) { case PDT::Colour8: inter->incomingColour(const_ptr_cast(&parent)); outgoing[triplet[1]]->colourLine()->addAntiColoured(inter); break; default: string mode = parent.PDGName() + " -> " + out[0]->PDGName() + " " + out[1]->PDGName() + " " + out[2]->PDGName(); throw Exception() << "Unknown colour for intermediate in " << "GeneralThreeBodyDecayer::" << "colourConnections() for " << "decaying colour triplet " << mode << Exception::runerror; } } } else { outgoing[triplet[1]]->incomingColour(const_ptr_cast(&parent)); outgoing[antitriplet[0]]->colourNeighbour(outgoing[triplet[0]]); if(inter&&inter->coloured()) { switch (inter->dataPtr()->iColour()) { case PDT::Colour8: inter->incomingColour(const_ptr_cast(&parent)); outgoing[triplet[0]]->colourLine()->addAntiColoured(inter); break; default: string mode = parent.PDGName() + " -> " + out[0]->PDGName() + " " + out[1]->PDGName() + " " + out[2]->PDGName(); throw Exception() << "Unknown colour for intermediate in " << "GeneralThreeBodyDecayer::" << "colourConnections() for " << "decaying colour triplet " << mode << Exception::runerror; } } } } else if (singlet.size()==1&&triplet.size()==1&&octet.size()==1) { if(inter) { if(inter->children()[0]->dataPtr()->iColour()==PDT::Colour8 || inter->children()[1]->dataPtr()->iColour()==PDT::Colour8) { inter->incomingColour(const_ptr_cast(&parent)); outgoing[octet[0]]->incomingColour(inter); outgoing[octet[0]]->colourNeighbour(outgoing[triplet[0]]); } else { outgoing[octet[0]]->incomingColour(inter); outgoing[octet[0]]->colourNeighbour(inter); outgoing[triplet[0]]->incomingColour(inter); } } else { outgoing[octet[0]]->incomingColour(const_ptr_cast(&parent)); outgoing[octet[0]]->colourNeighbour(outgoing[triplet[0]]); } } else if (singlet.size()==1&&antitriplet.size()==2) { tColinePtr col[2] = {ColourLine::create(outgoing[antitriplet[0]],true), ColourLine::create(outgoing[antitriplet[1]],true)}; parent.colourLine()->setSinkNeighbours(col[0],col[1]); } else { string mode = parent.PDGName() + " -> " + out[0]->PDGName() + " " + out[1]->PDGName() + " " + out[2]->PDGName(); throw Exception() << "Unknown colour structure in GeneralThreeBodyDecayer::" << "colourConnections() for triplet decaying particle " << mode << Exception::runerror; } } else if( inColour == PDT::Colour3bar) { if(singlet.size()==2&&antitriplet.size()==1) { outgoing[antitriplet[0]]->incomingAntiColour(const_ptr_cast(&parent)); } else if(antitriplet.size()==2&&triplet.size()==1) { if(colourFlow()==0) { outgoing[antitriplet[0]]->incomingAntiColour(const_ptr_cast(&parent)); outgoing[triplet[0]]->antiColourNeighbour(outgoing[antitriplet[1]]); if(inter&&inter->coloured()) { switch (inter->dataPtr()->iColour()) { case PDT::Colour8: inter->incomingAntiColour(const_ptr_cast(&parent)); outgoing[antitriplet[1]]->antiColourLine()->addAntiColoured(inter); break; default: string mode = parent.PDGName() + " -> " + out[0]->PDGName() + " " + out[1]->PDGName() + " " + out[2]->PDGName(); throw Exception() << "Unknown colour for intermediate in" << " GeneralThreeBodyDecayer::" << "colourConnections() for " << "decaying colour antitriplet " << mode << Exception::runerror; } } } else { outgoing[antitriplet[1]]->incomingAntiColour(const_ptr_cast(&parent)); outgoing[triplet[0]]->antiColourNeighbour(outgoing[antitriplet[0]]); if(inter&&inter->coloured()) { switch (inter->dataPtr()->iColour()) { case PDT::Colour8: inter->incomingAntiColour(const_ptr_cast(&parent)); outgoing[antitriplet[0]]->antiColourLine()->addAntiColoured(inter); break; default: string mode = parent.PDGName() + " -> " + out[0]->PDGName() + " " + out[1]->PDGName() + " " + out[2]->PDGName(); throw Exception() << "Unknown colour for intermediate in " << "GeneralThreeBodyDecayer::" << "colourConnections() for " << "decaying colour antitriplet " << mode << Exception::runerror; } } } } else if (singlet.size()==1&&antitriplet.size()==1&&octet.size()==1) { if(inter) { if(inter->children()[0]->dataPtr()->iColour()==PDT::Colour8 || inter->children()[1]->dataPtr()->iColour()==PDT::Colour8) { inter->incomingColour(const_ptr_cast(&parent)); outgoing[octet[0]]->incomingAntiColour(inter); outgoing[octet[0]]->antiColourNeighbour(outgoing[antitriplet[0]]); } else { outgoing[octet[0]]->incomingAntiColour(inter); outgoing[octet[0]]->antiColourNeighbour(inter); outgoing[antitriplet[0]]->incomingAntiColour(inter); } } else { outgoing[octet[0]]->incomingAntiColour(const_ptr_cast(&parent)); outgoing[octet[0]]->antiColourNeighbour(outgoing[antitriplet[0]]); } } else if (singlet.size()==1&&triplet.size()==2) { tColinePtr col[2] = {ColourLine::create(outgoing[triplet[0]]), ColourLine::create(outgoing[triplet[1]])}; parent.antiColourLine()->setSourceNeighbours(col[0],col[1]); } else { string mode = parent.PDGName() + " -> " + out[0]->PDGName() + " " + out[1]->PDGName() + " " + out[2]->PDGName(); throw Exception() << "Unknown colour structure in GeneralThreeBodyDecayer::" << "colourConnections() for anti-triplet decaying particle" << mode << Exception::runerror; } } else if( inColour == PDT::Colour8) { if(triplet.size()==1&&antitriplet.size()==1&&singlet.size()==1) { outgoing[ triplet[0]]->incomingColour (const_ptr_cast(&parent)); outgoing[antitriplet[0]]->incomingAntiColour(const_ptr_cast(&parent)); if(inter&&inter->coloured()) { switch (inter->dataPtr()->iColour()) { case PDT::Colour3: outgoing[triplet[0]]->colourLine()->addColoured(inter); break; case PDT::Colour3bar: outgoing[antitriplet[0]]->antiColourLine()->addAntiColoured(inter); break; default: string mode = parent.PDGName() + " -> " + out[0]->PDGName() + " " + out[1]->PDGName() + " " + out[2]->PDGName(); throw Exception() << "Unknown colour for intermediate" << " in GeneralThreeBodyDecayer::" << "colourConnections() for " << "decaying colour octet " << mode << Exception::runerror; } } } else if(triplet.size()==3) { tColinePtr col[2]; if(colourFlow()==0) { outgoing[0]->incomingColour (const_ptr_cast(&parent)); col[0] = ColourLine::create(outgoing[1]); col[1] = ColourLine::create(outgoing[2]); } else if(colourFlow()==1) { outgoing[1]->incomingColour (const_ptr_cast(&parent)); col[0] = ColourLine::create(outgoing[0]); col[1] = ColourLine::create(outgoing[2]); } else if(colourFlow()==2) { outgoing[2]->incomingColour (const_ptr_cast(&parent)); col[0] = ColourLine::create(outgoing[0]); col[1] = ColourLine::create(outgoing[1]); } else assert(false); parent.antiColourLine()->setSourceNeighbours(col[0],col[1]); } else if(antitriplet.size()==3) { tColinePtr col[2]; if(colourFlow()==0) { outgoing[0]->incomingAntiColour(const_ptr_cast(&parent)); col[0] = ColourLine::create(outgoing[1],true); col[1] = ColourLine::create(outgoing[2],true); } else if(colourFlow()==1) { outgoing[1]->incomingAntiColour(const_ptr_cast(&parent)); col[0] = ColourLine::create(outgoing[0],true); col[1] = ColourLine::create(outgoing[2],true); } else if(colourFlow()==2) { outgoing[2]->incomingAntiColour(const_ptr_cast(&parent)); col[0] = ColourLine::create(outgoing[0],true); col[1] = ColourLine::create(outgoing[1],true); } else assert(false); parent.colourLine()->setSinkNeighbours(col[0],col[1]); } else { string mode = parent.PDGName() + " -> " + out[0]->PDGName() + " " + out[1]->PDGName() + " " + out[2]->PDGName(); throw Exception() << "Unknown colour structure in GeneralThreeBodyDecayer::" << "colourConnections() for octet decaying particle" << mode << Exception::runerror; } } } void GeneralThreeBodyDecayer:: constructIntegratorChannels(vector & intype, vector & inmass, vector & inwidth, vector & inpow, vector & inweights) const { // check if any intermediate photons bool hasPhoton=false; for(unsigned int iy=0;iyid()==ParticleID::gamma) hasPhoton = true; } // loop over channels Energy min = incoming()->mass(); int nchannel(0); pair imin[4]={make_pair(-1,-1.*GeV),make_pair(-1,-1.*GeV), make_pair(-1,-1.*GeV),make_pair(-1,-1.*GeV)}; Energy absmin = -1e20*GeV; int minType = -1; for(unsigned int iy=0;iymass()); Energy dm2(getProcessInfo()[ix].intermediate->mass()); int itype(0); if (getProcessInfo()[ix].channelType==TBDiagram::channel23) { dm1 -= outgoing()[0]->mass(); dm2 -= outgoing()[1]->mass()+outgoing()[2]->mass(); itype = 3; } else if(getProcessInfo()[ix].channelType==TBDiagram::channel13) { dm1 -= outgoing()[1]->mass(); dm2 -= outgoing()[0]->mass()+outgoing()[2]->mass(); itype = 2; } else if(getProcessInfo()[ix].channelType==TBDiagram::channel12) { dm1 -= outgoing()[2]->mass(); dm2 -= outgoing()[0]->mass()+outgoing()[1]->mass(); itype = 1; } if((dm1id()!=ParticleID::gamma) { intype.push_back(itype); inpow.push_back(0.); inmass.push_back(getProcessInfo()[ix].intermediate->mass()); inwidth.push_back(widthOption() ==3 ? ZERO : getProcessInfo()[ix].intermediate->width()); ++nchannel; } else if(getProcessInfo()[ix].intermediate->id()==ParticleID::gamma) { intype.push_back(itype); inpow.push_back(-2.); inmass.push_back(-1.*GeV); inwidth.push_back(-1.*GeV); ++nchannel; } } // physical poles, use them and return if(nchannel>0) { inweights = vector(nchannel,1./double(nchannel)); return; } // use shallowest pole else if(intOpt_==1&&minType>0&&getProcessInfo()[imin[minType].first].intermediate->id()!=ParticleID::gamma) { intype.push_back(minType); inpow.push_back(0.); inmass.push_back(getProcessInfo()[imin[minType].first].intermediate->mass()); inwidth.push_back(widthOption() ==3 ? ZERO : getProcessInfo()[imin[minType].first].intermediate->width()); inweights = vector(1,1.); return; } for(unsigned int ix=1;ix<4;++ix) { if(imin[ix].first>=0) { intype.push_back(ix); if(getProcessInfo()[imin[ix].first].intermediate->id()!=ParticleID::gamma) { inpow.push_back(0.); inmass.push_back(getProcessInfo()[imin[ix].first].intermediate->mass()); inwidth.push_back(widthOption() ==3 ? ZERO : getProcessInfo()[imin[ix].first].intermediate->width()); } else { inpow.push_back(-2.); inmass.push_back(-1.*GeV); inwidth.push_back(-1.*GeV); } ++nchannel; } } inweights = vector(nchannel,1./double(nchannel)); } bool GeneralThreeBodyDecayer::setColourFactors(double symfac) { string name = incoming_->PDGName() + "->"; vector sng,trip,atrip,oct; unsigned int iloc(0); + for(vector::const_iterator it = outgoing_.begin(); it != outgoing_.end();++it) { name += (**it).PDGName() + " "; if ((**it).iColour() == PDT::Colour0 ) sng.push_back(iloc) ; else if((**it).iColour() == PDT::Colour3 ) trip.push_back(iloc) ; else if((**it).iColour() == PDT::Colour3bar ) atrip.push_back(iloc); else if((**it).iColour() == PDT::Colour8 ) oct.push_back(iloc) ; ++iloc; } // colour neutral decaying particle if ( incoming_->iColour() == PDT::Colour0) { // options are all neutral or triplet/antitriplet+ neutral if(sng.size()==3) { nflow_ = 1; colour_ = vector(1,DVector(1,1.)); colourLargeNC_ = vector(1,DVector(1,1.)); } else if(sng.size()==1&&trip.size()==1&&atrip.size()==1) { nflow_ = 1; colour_ = vector(1,DVector(1,3.)); colourLargeNC_ = vector(1,DVector(1,3.)); } else if(trip.size()==1&&atrip.size()==1&&oct.size()==1) { nflow_ = 1; colour_ = vector(1,DVector(1,4.)); colourLargeNC_ = vector(1,DVector(1,4.)); } else if( trip.size() == 3 || atrip.size() == 3 ) { nflow_ = 1; colour_ = vector(1,DVector(1,6.)); colourLargeNC_ = vector(1,DVector(1,6.)); for(unsigned int ix=0;ixCC()) inter = inter->CC(); - unsigned int io[2]={1,2}; double sign = diagrams_[ix].channelType == TBDiagram::channel13 ? -1. : 1.; - for(unsigned int iy=0;iy<3;++iy) { - if (iy==1) io[0]=0; - else if(iy==2) io[1]=1; - tPDVector decaylist = diagrams_[ix].vertices.second->search(iy, inter); - if(decaylist.empty()) continue; - bool found=false; - for(unsigned int iz=0;izid()==diagrams_[ix].outgoingPair.first && - decaylist[iz+io[1]]->id()==diagrams_[ix].outgoingPair.second) { - sign *= 1.; - found = true; - } - else if(decaylist[iz+io[0]]->id()==diagrams_[ix].outgoingPair.second && - decaylist[iz+io[1]]->id()==diagrams_[ix].outgoingPair.first ) { - sign *= -1.; - found = true; - } - } - if(found) { - if(iy==1) sign *=-1.; - break; - } - } diagrams_[ix]. colourFlow = vector(1,make_pair(1,sign)); diagrams_[ix].largeNcColourFlow = vector(1,make_pair(1,sign)); } } else { generator()->log() << "Unknown colour flow structure for " << "colour neutral decay " << name << " in GeneralThreeBodyDecayer::" << "setColourFactors(), omitting decay\n"; return false; } } // colour triplet decaying particle else if( incoming_->iColour() == PDT::Colour3) { if(sng.size()==2&&trip.size()==1) { nflow_ = 1; colour_ = vector(1,DVector(1,1.)); colourLargeNC_ = vector(1,DVector(1,1.)); } else if(trip.size()==2&&atrip.size()==1) { nflow_ = 2; colour_.clear(); colour_.resize(2,DVector(2,0.)); colour_[0][0] = 3.; colour_[0][1] = 1.; colour_[1][0] = 1.; colour_[1][1] = 3.; colourLargeNC_.clear(); colourLargeNC_.resize(2,DVector(2,0.)); colourLargeNC_[0][0] = 3.; colourLargeNC_[1][1] = 3.; // sort out the contribution of the different diagrams to the colour // flows for(unsigned int ix=0;ixiColour()==PDT::Colour0) { if(diagrams_[ix].channelType==trip[0]) { diagrams_[ix]. colourFlow = vector(1,make_pair(1,1.)); diagrams_[ix].largeNcColourFlow = vector(1,make_pair(1,1.)); } else { diagrams_[ix].colourFlow = vector(1,make_pair(2,1.)); diagrams_[ix].largeNcColourFlow = vector(1,make_pair(2,1.)); } } // colour octet intermediate else if(diagrams_[ix].intermediate->iColour()==PDT::Colour8) { if(diagrams_[ix].channelType==trip[0]) { vector flow(1,make_pair(2, 0.5 )); diagrams_[ix].largeNcColourFlow = flow; flow.push_back( make_pair(1,-1./6.)); diagrams_[ix].colourFlow=flow; } else { vector flow(1,make_pair(1, 0.5 )); diagrams_[ix].largeNcColourFlow = flow; flow.push_back( make_pair(2,-1./6.)); diagrams_[ix].colourFlow=flow; } } else { generator()->log() << "Unknown colour for the intermediate in " << "triplet -> triplet triplet antitriplet in " << "GeneralThreeBodyDecayer::setColourFactors()" << " for " << name << " omitting decay\n"; return false; } } } else if(trip.size()==1&&oct.size()==1&&sng.size()==1) { nflow_ = 1; colour_ = vector(1,DVector(1,4./3.)); colourLargeNC_ = vector(1,DVector(1,4./3.)); } else if(sng.size()==1&&atrip.size()==2) { nflow_ = 1; colour_ = vector(1,DVector(1,2.)); colourLargeNC_ = vector(1,DVector(1,2.)); } else { generator()->log() << "Unknown colour structure for " << "triplet decay in " << "GeneralThreeBodyDecayer::setColourFactors()" << " for " << name << " omitting decay\n"; return false; } } // colour antitriplet decaying particle else if( incoming_->iColour() == PDT::Colour3bar) { if(sng.size()==2&&atrip.size()==1) { nflow_ = 1; colour_ = vector(1,DVector(1,1.)); colourLargeNC_ = vector(1,DVector(1,1.)); } else if(atrip.size()==2&&trip.size()==1) { nflow_ = 2; colour_.clear(); colour_.resize(2,DVector(2,0.)); colour_[0][0] = 3.; colour_[0][1] = 1.; colour_[1][0] = 1.; colour_[1][1] = 3.; colourLargeNC_.clear(); colourLargeNC_.resize(2,DVector(2,0.)); colourLargeNC_[0][0] = 3.; colourLargeNC_[1][1] = 3.; // sort out the contribution of the different diagrams to the colour // flows for(unsigned int ix=0;ixiColour()==PDT::Colour0) { if(diagrams_[ix].channelType==atrip[0]) { diagrams_[ix]. colourFlow = vector(1,make_pair(1,1.)); diagrams_[ix].largeNcColourFlow = vector(1,make_pair(1,1.)); } else { diagrams_[ix].colourFlow = vector(1,make_pair(2,1.)); diagrams_[ix].largeNcColourFlow = vector(1,make_pair(2,1.)); } } // colour octet intermediate else if(diagrams_[ix].intermediate->iColour()==PDT::Colour8) { if(diagrams_[ix].channelType==atrip[0]) { vector flow(1,make_pair(2, 0.5 )); diagrams_[ix].largeNcColourFlow = flow; flow.push_back( make_pair(1,-1./6.)); diagrams_[ix].colourFlow=flow; } else { vector flow(1,make_pair(1, 0.5 )); diagrams_[ix].largeNcColourFlow = flow; flow.push_back( make_pair(2,-1./6.)); diagrams_[ix].colourFlow=flow; } } else { generator()->log() << "Unknown colour for the intermediate in " << "antitriplet -> antitriplet antitriplet triplet in " << "GeneralThreeBodyDecayer::setColourFactors()" << " for " << name << " omitting decay\n"; return false; } } } else if(atrip.size()==1&&oct.size()==1&&sng.size()==1) { nflow_ = 1; colour_ = vector(1,DVector(1,4./3.)); colourLargeNC_ = vector(1,DVector(1,4./3.)); } else if(sng.size()==1&&trip.size()==2) { nflow_ = 1; colour_ = vector(1,DVector(1,2.)); colourLargeNC_ = vector(1,DVector(1,2.)); } else { generator()->log() << "Unknown colour antitriplet decay in " << "GeneralThreeBodyDecayer::setColourFactors()" << " for " << name << " omitting decay\n"; return false; } } // colour octet particle else if( incoming_->iColour() == PDT::Colour8) { // triplet antitriplet if(trip.size() == 1 && atrip.size() == 1 && sng.size() == 1) { nflow_ = 1; colour_ = vector(1,DVector(1,0.5)); colourLargeNC_ = vector(1,DVector(1,0.5)); } // three (anti)triplets else if(trip.size()==3||atrip.size()==3) { nflow_ = 3; colour_ = vector(3,DVector(3,0.)); colourLargeNC_ = vector(3,DVector(3,0.)); colour_[0][0] = 1.; colour_[1][1] = 1.; colour_[2][2] = 1.; colour_[0][1] = -0.5; colour_[1][0] = -0.5; colour_[0][2] = -0.5; colour_[2][0] = -0.5; colour_[1][2] = -0.5; colour_[2][1] = -0.5; colourLargeNC_ = vector(3,DVector(3,0.)); colourLargeNC_[0][0] = 1.; colourLargeNC_[1][1] = 1.; colourLargeNC_[2][2] = 1.; // sett the factors for the diagrams for(unsigned int ix=0;ixCC()) inter = inter->CC(); unsigned int io[2]={1,2}; double sign = diagrams_[ix].channelType == TBDiagram::channel13 ? -1. : 1.; for(unsigned int iy=0;iy<3;++iy) { if (iy==1) io[0]=0; else if(iy==2) io[1]=1; tPDVector decaylist = diagrams_[ix].vertices.second->search(iy, inter); if(decaylist.empty()) continue; bool found=false; for(unsigned int iz=0;izid()==diagrams_[ix].outgoingPair.first && decaylist[iz+io[1]]->id()==diagrams_[ix].outgoingPair.second) { sign *= 1.; found = true; } else if(decaylist[iz+io[0]]->id()==diagrams_[ix].outgoingPair.second && decaylist[iz+io[1]]->id()==diagrams_[ix].outgoingPair.first ) { sign *= -1.; found = true; } } if(found) { if(iy==1) sign *=-1.; break; } } diagrams_[ix]. colourFlow = vector(1,make_pair(diagrams_[ix].channelType+1,sign)); diagrams_[ix].largeNcColourFlow = vector(1,make_pair(diagrams_[ix].channelType+1,sign)); } } // unknown else { generator()->log() << "Unknown colour octet decay in " << "GeneralThreeBodyDecayer::setColourFactors()" << " for " << name << " omitting decay\n"; return false; } } else if (incoming_->iColour() == PDT::Colour6 ) { generator()->log() << "Unknown colour sextet decay in " << "GeneralThreeBodyDecayer::setColourFactors()" << " for " << name << " omitting decay\n"; return false; } else if (incoming_->iColour() == PDT::Colour6bar ) { generator()->log() << "Unknown colour anti-sextet decay in " << "GeneralThreeBodyDecayer::setColourFactors()" << " for " << name << " omitting decay\n"; return false; } assert(nflow_ != 999); for(unsigned int ix=0;ix 1 ) { generator()->log() << "Mode: " << name << " has colour factors\n"; for(unsigned int ix=0;ixlog() << colour_[ix][iy] << " "; } generator()->log() << "\n"; } for(unsigned int ix=0;ixlog() << "colour flow for diagram : " << ix; for(unsigned int iy=0;iylog() << "(" << diagrams_[ix].colourFlow[iy].first << "," << diagrams_[ix].colourFlow[iy].second << "); "; generator()->log() << "\n"; } } return true; } diff --git a/Decay/General/GeneralTwoBodyDecayer.h b/Decay/General/GeneralTwoBodyDecayer.h --- a/Decay/General/GeneralTwoBodyDecayer.h +++ b/Decay/General/GeneralTwoBodyDecayer.h @@ -1,305 +1,306 @@ // -*- C++ -*- // // GeneralTwoBodyDecayer.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_GeneralTwoBodyDecayer_H #define HERWIG_GeneralTwoBodyDecayer_H // // This is the declaration of the GeneralTwoBodyDecayer class. // #include "Herwig/Decay/PerturbativeDecayer.h" #include "Herwig/Decay/DecayPhaseSpaceMode.h" #include "ThePEG/Helicity/Vertex/VertexBase.h" #include "GeneralTwoBodyDecayer.fh" namespace Herwig { using namespace ThePEG; using Helicity::VertexBasePtr; /** \ingroup Decay * The GeneralTwoBodyDecayer class is designed to be the base class * for 2 body decays for some general model. It inherits from * PerturbativeDecayer and implements the modeNumber() virtual function * that is the same for all of the decays. A decayer for * a specific spin configuration should inherit from this and implement * the me2() and partialWidth() member functions. The colourConnections() * member should be called from inside me2() in the inheriting decayer * to set up the colour lines. * * @see \ref GeneralTwoBodyDecayerInterfaces "The interfaces" * defined for GeneralTwoBodyDecayer. * @see PerturbativeDecayer */ class GeneralTwoBodyDecayer: public PerturbativeDecayer { public: /** A ParticleData ptr and (possible) mass pair.*/ typedef pair PMPair; public: /** * The default constructor. */ GeneralTwoBodyDecayer() : maxWeight_(1.), colour_(1,DVector(1,1.)) {} /** @name Virtual functions required by the Decayer class. */ //@{ /** * For a given decay mode and a given particle instance, perform the * decay and return the decay products. As this is the base class this * is not implemented. * @return The vector of particles produced in the decay. */ virtual ParticleVector decay(const Particle & parent, const tPDVector & children) const; /** * Which of the possible decays is required * @param cc Is this mode the charge conjugate * @param parent The decaying particle * @param children The decay products */ virtual int modeNumber(bool & cc, tcPDPtr parent,const tPDVector & children) const; /** * Return the matrix element squared for a given mode and phase-space channel * @param ichan The channel we are calculating the matrix element for. * @param part The decaying Particle. * @param decay The particles produced in the decay. * @param meopt Option for the calculation of the matrix element * @return The matrix element squared for the phase-space configuration. */ virtual double me2(const int , const Particle & part, const ParticleVector & decay, MEOption meopt) const = 0; /** * Function to return partial Width * @param inpart The decaying particle. * @param outa One of the decay products. * @param outb The other decay product. */ virtual Energy partialWidth(PMPair inpart, PMPair outa, PMPair outb) const; /** * Specify the \f$1\to2\f$ matrix element to be used in the running width * calculation. * @param dm The DecayMode * @param mecode The code for the matrix element as described * in the GenericWidthGenerator class. * @param coupling The coupling for the matrix element. * @return True if the the order of the particles in the * decayer is the same as the DecayMode tag. */ virtual bool twoBodyMEcode(const DecayMode & dm, int & mecode, double & coupling) const; /** * An overidden member to calculate a branching ratio for a certain * particle instance. * @param dm The DecayMode of the particle * @param p The particle object * @param oldbrat The branching fraction given in the DecayMode object */ virtual double brat(const DecayMode & dm, const Particle & p, double oldbrat) const; //@} /** * Set the information on the decay */ - virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, VertexBasePtr, + virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, + vector, map &, const vector > &, map) =0; protected: /** @name Functions used by inheriting decayers. */ //@{ /** * Set integration weight * @param wgt Maximum integration weight */ void setWeight(double wgt) { maxWeight_ = wgt; } /** * Set colour connections * @param parent Parent particle * @param out Particle vector containing particles to * connect colour lines */ void colourConnections(const Particle & parent, const ParticleVector & out) const; /** * Compute the spin and colour factor */ double colourFactor(tcPDPtr in, tcPDPtr out1, tcPDPtr out2) const; /** * Calculate matrix element ratio R/B */ double matrixElementRatio(const Particle & inpart, const ParticleVector & decay2, const ParticleVector & decay3, MEOption meopt, ShowerInteraction inter); /** * Set the information on the decay */ void decayInfo(PDPtr incoming, PDPair outgoing); //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} protected: /** * Member for the generation of additional hard radiation */ //@{ /** * Return the matrix of colour factors */ typedef vector > CFlowPairVec; typedef vector CFlow; const vector & getColourFactors(const Particle & inpart, const ParticleVector & decay, unsigned int & nflow); const CFlow & colourFlows(const Particle & inpart, const ParticleVector & decay); /** * Three-body matrix element including additional QCD radiation */ virtual double threeBodyME(const int , const Particle & inpart, const ParticleVector & decay, ShowerInteraction inter, MEOption meopt); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ GeneralTwoBodyDecayer & operator=(const GeneralTwoBodyDecayer &); private: /** * Store the incoming particle */ PDPtr incoming_; /** * Outgoing particles */ vector outgoing_; /** * Maximum weight for integration */ double maxWeight_; /** * Store colour factors for ME calc. */ vector colour_; }; /** * Write a map with ShowerInteraction as the key */ template inline PersistentOStream & operator<<(PersistentOStream & os, const map & m) { os << m.size(); if(m.find(ShowerInteraction::QCD)!=m.end()) { os << 0 << m.at(ShowerInteraction::QCD); } if(m.find(ShowerInteraction::QED)!=m.end()) { os << 1 << m.at(ShowerInteraction::QED); } return os; } /** * Read a map with ShowerInteraction as the key */ template inline PersistentIStream & operator>>(PersistentIStream & is, map & m) { m.clear(); long size; int k; is >> size; while ( size-- && is ) { is >> k; if(k==0) is >> m[ShowerInteraction::QCD]; else if(k==1) is >> m[ShowerInteraction::QED]; else assert(false); } return is; } } #endif /* HERWIG_GeneralTwoBodyDecayer_H */ diff --git a/Decay/General/SFFDecayer.cc b/Decay/General/SFFDecayer.cc --- a/Decay/General/SFFDecayer.cc +++ b/Decay/General/SFFDecayer.cc @@ -1,478 +1,491 @@ // -*- C++ -*- // // SFFDecayer.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SFFDecayer class. // #include "SFFDecayer.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" #include "Herwig/Utilities/Kinematics.h" #include "Herwig/Decay/GeneralDecayMatrixElement.h" using namespace Herwig; using namespace ThePEG::Helicity; IBPtr SFFDecayer::clone() const { return new_ptr(*this); } IBPtr SFFDecayer::fullclone() const { return new_ptr(*this); } void SFFDecayer::setDecayInfo(PDPtr incoming, PDPair outgoing, - VertexBasePtr vertex, + vector vertex, map & inV, const vector > & outV, map ) { decayInfo(incoming,outgoing); - vertex_ = dynamic_ptr_cast(vertex); - perturbativeVertex_ = dynamic_ptr_cast (vertex); + for(auto vert : vertex) { + vertex_ .push_back(dynamic_ptr_cast(vert)); + perturbativeVertex_ .push_back(dynamic_ptr_cast (vert)); + } vector itemp={ShowerInteraction::QCD,ShowerInteraction::QED}; for(auto & inter : itemp) { incomingVertex_[inter] = dynamic_ptr_cast(inV.at(inter)); outgoingVertex1_[inter] = dynamic_ptr_cast(outV[0].at(inter)); outgoingVertex2_[inter] = dynamic_ptr_cast(outV[1].at(inter)); } } void SFFDecayer::persistentOutput(PersistentOStream & os) const { os << vertex_ << perturbativeVertex_ << incomingVertex_ << outgoingVertex1_ << outgoingVertex2_; } void SFFDecayer::persistentInput(PersistentIStream & is, int) { is >> vertex_ >> perturbativeVertex_ >> incomingVertex_ >> outgoingVertex1_ >> outgoingVertex2_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigSFFDecayer("Herwig::SFFDecayer", "Herwig.so"); void SFFDecayer::Init() { static ClassDocumentation documentation ("This class implements to decay of a scalar to 2 fermions"); } double SFFDecayer::me2(const int , const Particle & inpart, const ParticleVector & decay,MEOption meopt) const { if(!ME()) ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin0,PDT::Spin1Half,PDT::Spin1Half))); // work out which is the fermion and antifermion int iferm(1),ianti(0); int itype[2]; for(unsigned int ix=0;ix<2;++ix) { if(decay[ix]->dataPtr()->CC()) itype[ix] = decay[ix]->id()>0 ? 0:1; else itype[ix] = 2; } if(itype[0]==0||itype[1]==1||(itype[0]==2&&itype[1]==2)) swap(iferm,ianti); if(meopt==Initialize) { ScalarWaveFunction:: calculateWaveFunctions(rho_,const_ptr_cast(&inpart),incoming); swave_ = ScalarWaveFunction(inpart.momentum(),inpart.dataPtr(),incoming); } if(meopt==Terminate) { ScalarWaveFunction:: constructSpinInfo(const_ptr_cast(&inpart),incoming,true); SpinorBarWaveFunction:: constructSpinInfo(wavebar_,decay[iferm],outgoing,true); SpinorWaveFunction:: constructSpinInfo(wave_ ,decay[ianti],outgoing,true); return 0.; } SpinorBarWaveFunction:: calculateWaveFunctions(wavebar_,decay[iferm],outgoing); SpinorWaveFunction:: calculateWaveFunctions(wave_ ,decay[ianti],outgoing); Energy2 scale(sqr(inpart.mass())); for(unsigned int ifm = 0; ifm < 2; ++ifm){ for(unsigned int ia = 0; ia < 2; ++ia) { - if(iferm > ianti){ - (*ME())(0, ia, ifm) = vertex_->evaluate(scale,wave_[ia], - wavebar_[ifm],swave_); - } - else { - (*ME())(0, ifm, ia) = vertex_->evaluate(scale,wave_[ia], - wavebar_[ifm],swave_); + if(iferm > ianti) (*ME())(0, ia, ifm) = 0.; + else (*ME())(0, ifm, ia) = 0.; + for(auto vert : vertex_) { + if(iferm > ianti){ + (*ME())(0, ia, ifm) += vert->evaluate(scale,wave_[ia], + wavebar_[ifm],swave_); + } + else { + (*ME())(0, ifm, ia) += vert->evaluate(scale,wave_[ia], + wavebar_[ifm],swave_); + } } } } double output = (ME()->contract(rho_)).real()/scale*UnitRemoval::E2; // colour and identical particle factors output *= colourFactor(inpart.dataPtr(),decay[0]->dataPtr(), decay[1]->dataPtr()); // return the answer return output; } Energy SFFDecayer::partialWidth(PMPair inpart, PMPair outa, PMPair outb) const { if( inpart.second < outa.second + outb.second ) return ZERO; - if(perturbativeVertex_) { + if(perturbativeVertex_.size()==1 && + perturbativeVertex_[0]) { tcPDPtr in = inpart.first->CC() ? tcPDPtr(inpart.first->CC()) : inpart.first; - perturbativeVertex_->setCoupling(sqr(inpart.second), outb.first, outa.first, + perturbativeVertex_[0]->setCoupling(sqr(inpart.second), outb.first, outa.first, in); double mu1(outa.second/inpart.second),mu2(outb.second/inpart.second); - double c2 = norm(perturbativeVertex_->norm()); - Complex al(perturbativeVertex_->left()), ar(perturbativeVertex_->right()); + double c2 = norm(perturbativeVertex_[0]->norm()); + Complex al(perturbativeVertex_[0]->left()), ar(perturbativeVertex_[0]->right()); double me2 = -c2*( (norm(al) + norm(ar))*( sqr(mu1) + sqr(mu2) - 1.) + 2.*(ar*conj(al) + al*conj(ar)).real()*mu1*mu2 ); Energy pcm = Kinematics::pstarTwoBodyDecay(inpart.second, outa.second, outb.second); Energy output = me2*pcm/(8*Constants::pi); // colour factor output *= colourFactor(inpart.first,outa.first,outb.first); return output; } else { return GeneralTwoBodyDecayer::partialWidth(inpart,outa,outb); } } double SFFDecayer::threeBodyME(const int , const Particle & inpart, const ParticleVector & decay, ShowerInteraction inter, MEOption meopt) { // work out which is the fermion and antifermion int ianti(0), iferm(1), iglu(2); int itype[2]; for(unsigned int ix=0;ix<2;++ix) { if(decay[ix]->dataPtr()->CC()) itype[ix] = decay[ix]->id()>0 ? 0:1; else itype[ix] = 2; } if(itype[0]==0 && itype[1]!=0) swap(iferm, ianti); if(itype[0]==2 && itype[1]==1) swap(iferm, ianti); if(itype[0]==0 && itype[1]==0 && decay[0]->dataPtr()->id()dataPtr()->id()) swap(iferm, ianti); if(itype[0]==1 && itype[1]==1 && decay[0]->dataPtr()->id()dataPtr()->id()) swap(iferm, ianti); if(meopt==Initialize) { // create scalar wavefunction for decaying particle ScalarWaveFunction:: calculateWaveFunctions(rho3_,const_ptr_cast(&inpart),incoming); swave3_ = ScalarWaveFunction(inpart.momentum(),inpart.dataPtr(),incoming); } // setup spin information when needed if(meopt==Terminate) { ScalarWaveFunction:: constructSpinInfo(const_ptr_cast(&inpart),incoming,true); SpinorBarWaveFunction:: constructSpinInfo(wavebar3_ ,decay[iferm],outgoing,true); SpinorWaveFunction:: constructSpinInfo(wave3_ ,decay[ianti],outgoing,true); VectorWaveFunction:: constructSpinInfo(gluon_ ,decay[iglu ],outgoing,true,false); return 0.; } // calculate colour factors and number of colour flows unsigned int nflow; vector cfactors = getColourFactors(inpart, decay, nflow); vector ME(nflow,new_ptr(GeneralDecayMatrixElement(PDT::Spin0, PDT::Spin1Half, PDT::Spin1Half, PDT::Spin1))); // create wavefunctions SpinorBarWaveFunction:: calculateWaveFunctions(wavebar3_, decay[iferm],outgoing); SpinorWaveFunction:: calculateWaveFunctions(wave3_ , decay[ianti],outgoing); VectorWaveFunction:: calculateWaveFunctions(gluon_ , decay[iglu ],outgoing,true); // gauge invariance test #ifdef GAUGE_CHECK gluon_.clear(); for(unsigned int ix=0;ix<3;++ix) { if(ix==1) gluon_.push_back(VectorWaveFunction()); else { gluon_.push_back(VectorWaveFunction(decay[iglu ]->momentum(), decay[iglu ]->dataPtr(),10, outgoing)); } } #endif // identify fermion and/or anti-fermion vertex AbstractFFVVertexPtr outgoingVertexF; AbstractFFVVertexPtr outgoingVertexA; identifyVertices(iferm, ianti, inpart, decay, outgoingVertexF, outgoingVertexA, inter); const GeneralTwoBodyDecayer::CFlow & colourFlow = colourFlows(inpart, decay); Energy2 scale(sqr(inpart.mass())); double gs(0.); bool couplingSet(false); #ifdef GAUGE_CHECK double total=0.; #endif for(unsigned int ifm = 0; ifm < 2; ++ifm) { for(unsigned int ia = 0; ia < 2; ++ia) { for(unsigned int ig = 0; ig < 2; ++ig) { // radiation from the incoming scalar if((inpart.dataPtr()->coloured() && inter==ShowerInteraction::QCD) || (inpart.dataPtr()->charged() && inter==ShowerInteraction::QED) ) { assert(incomingVertex_[inter]); ScalarWaveFunction scalarInter = incomingVertex_[inter]->evaluate(scale,3,inpart.dataPtr(), gluon_[2*ig],swave3_,inpart.mass()); assert(swave3_.particle()->id()==scalarInter.particle()->id()); if(!couplingSet) { gs = abs(incomingVertex_[inter]->norm()); couplingSet = true; } - Complex diag = vertex_->evaluate(scale,wave3_[ia], - wavebar3_[ifm],scalarInter); + Complex diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,wave3_[ia], + wavebar3_[ifm],scalarInter); for(unsigned int ix=0;ixdataPtr()->coloured() && inter==ShowerInteraction::QCD) || (decay[iferm]->dataPtr()->charged() && inter==ShowerInteraction::QED)) { assert(outgoingVertexF); // ensure you get correct outgoing particle from first vertex tcPDPtr off = decay[iferm]->dataPtr(); if(off->CC()) off = off->CC(); SpinorBarWaveFunction interS = outgoingVertexF->evaluate(scale,3,off,wavebar3_[ifm], gluon_[2*ig],decay[iferm]->mass()); assert(wavebar3_[ifm].particle()->id()==interS.particle()->id()); if(!couplingSet) { gs = abs(outgoingVertexF->norm()); couplingSet = true; } - Complex diag = vertex_->evaluate(scale,wave3_[ia], interS,swave3_); + Complex diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,wave3_[ia], interS,swave3_); for(unsigned int ix=0;ixdataPtr()->coloured() && inter==ShowerInteraction::QCD) || (decay[ianti]->dataPtr()->charged() && inter==ShowerInteraction::QED)) { assert(outgoingVertexA); // ensure you get correct outgoing particle from first vertex tcPDPtr off = decay[ianti]->dataPtr(); if(off->CC()) off = off->CC(); SpinorWaveFunction interS = outgoingVertexA->evaluate(scale,3,off,wave3_[ia], gluon_[2*ig],decay[ianti]->mass()); assert(wave3_[ia].particle()->id()==interS.particle()->id()); if(!couplingSet) { gs = abs(outgoingVertexA->norm()); couplingSet = true; } - Complex diag = vertex_->evaluate(scale,interS,wavebar3_[ifm],swave3_); + Complex diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,interS,wavebar3_[ifm],swave3_); for(unsigned int ix=0;ixcontract(*ME[iy],rho3_)).real(); } } // divide by alpha(S,EM) output *= (4.*Constants::pi)/sqr(gs); #ifdef GAUGE_CHECK double ratio = output/total; if(abs(ratio)>1e-20) { generator()->log() << "Test of gauge invariance in decay\n" << inpart << "\n"; for(unsigned int ix=0;ixlog() << *decay[ix] << "\n"; generator()->log() << "Test of gauge invariance " << ratio << "\n"; } #endif // return the answer return output; } void SFFDecayer::identifyVertices(const int iferm, const int ianti, const Particle & inpart, const ParticleVector & decay, AbstractFFVVertexPtr & outgoingVertexF, AbstractFFVVertexPtr & outgoingVertexA, ShowerInteraction inter) { // QCD if(inter==ShowerInteraction::QCD) { // work out which fermion each outgoing vertex corresponds to // two outgoing vertices if( inpart.dataPtr() ->iColour()==PDT::Colour0 && ((decay[iferm]->dataPtr()->iColour()==PDT::Colour3 && decay[ianti]->dataPtr()->iColour()==PDT::Colour3bar) || (decay[iferm]->dataPtr()->iColour()==PDT::Colour8 && decay[ianti]->dataPtr()->iColour()==PDT::Colour8))) { if(outgoingVertex1_[inter]==outgoingVertex2_[inter]) { outgoingVertexF = outgoingVertex1_[inter]; outgoingVertexA = outgoingVertex2_[inter]; } else if (outgoingVertex1_[inter]->isIncoming(const_ptr_cast(decay[iferm]->dataPtr()))) { outgoingVertexF = outgoingVertex1_[inter]; outgoingVertexA = outgoingVertex2_[inter]; } else if (outgoingVertex2_[inter]->isIncoming(const_ptr_cast(decay[iferm]->dataPtr()))) { outgoingVertexF = outgoingVertex2_[inter]; outgoingVertexA = outgoingVertex1_[inter]; } } else if(inpart.dataPtr() ->iColour()==PDT::Colour8 && decay[iferm]->dataPtr()->iColour()==PDT::Colour3 && decay[ianti]->dataPtr()->iColour()==PDT::Colour3bar) { if(outgoingVertex1_[inter]==outgoingVertex2_[inter]) { outgoingVertexF = outgoingVertex1_[inter]; outgoingVertexA = outgoingVertex2_[inter]; } else if (outgoingVertex1_[inter]->isIncoming(const_ptr_cast(decay[iferm]->dataPtr()))) { outgoingVertexF = outgoingVertex1_[inter]; outgoingVertexA = outgoingVertex2_[inter]; } else if (outgoingVertex2_[inter]->isIncoming(const_ptr_cast(decay[iferm]->dataPtr()))) { outgoingVertexF = outgoingVertex2_[inter]; outgoingVertexA = outgoingVertex1_[inter]; } } // one outgoing vertex else if(inpart.dataPtr()->iColour()==PDT::Colour3){ if(decay[iferm]->dataPtr()->iColour()==PDT::Colour3 && decay[ianti]->dataPtr()->iColour()==PDT::Colour0){ if (outgoingVertex1_[inter]) outgoingVertexF = outgoingVertex1_[inter]; else if(outgoingVertex2_[inter]) outgoingVertexF = outgoingVertex2_[inter]; } else if (decay[iferm]->dataPtr()->iColour()==PDT::Colour3 && decay[ianti]->dataPtr()->iColour()==PDT::Colour8) { if (outgoingVertex1_[inter]->isIncoming(const_ptr_cast(decay[ianti]->dataPtr()))) { outgoingVertexF = outgoingVertex2_[inter]; outgoingVertexA = outgoingVertex1_[inter]; } else { outgoingVertexF = outgoingVertex1_[inter]; outgoingVertexA = outgoingVertex2_[inter]; } } else if(decay[iferm]->dataPtr()->iColour()==PDT::Colour3bar && decay[ianti]->dataPtr()->iColour()==PDT::Colour3bar) { if (outgoingVertex1_[inter]->isIncoming(const_ptr_cast(decay[iferm]->dataPtr()))) { outgoingVertexF = outgoingVertex1_[inter]; outgoingVertexA = outgoingVertex2_[inter]; } else { outgoingVertexF = outgoingVertex2_[inter]; outgoingVertexA = outgoingVertex1_[inter]; } } } else if(inpart.dataPtr()->iColour()==PDT::Colour3bar){ if(decay[ianti]->dataPtr()->iColour()==PDT::Colour3bar && decay[iferm]->dataPtr()->iColour()==PDT::Colour0){ if (outgoingVertex1_[inter]) outgoingVertexA = outgoingVertex1_[inter]; else if(outgoingVertex2_[inter]) outgoingVertexA = outgoingVertex2_[inter]; } else if (decay[iferm]->dataPtr()->iColour()==PDT::Colour8 && decay[ianti]->dataPtr()->iColour()==PDT::Colour3bar){ if (outgoingVertex1_[inter]->isIncoming(const_ptr_cast(decay[iferm]->dataPtr()))) { outgoingVertexF = outgoingVertex1_[inter]; outgoingVertexA = outgoingVertex2_[inter]; } else { outgoingVertexF = outgoingVertex2_[inter]; outgoingVertexA = outgoingVertex1_[inter]; } } else if(decay[iferm]->dataPtr()->iColour()==PDT::Colour3 && decay[ianti]->dataPtr()->iColour()==PDT::Colour3) { if (outgoingVertex1_[inter]->isIncoming(const_ptr_cast(decay[iferm]->dataPtr()))) { outgoingVertexF = outgoingVertex1_[inter]; outgoingVertexA = outgoingVertex2_[inter]; } else { outgoingVertexF = outgoingVertex2_[inter]; outgoingVertexA = outgoingVertex1_[inter]; } } } else if(inpart.dataPtr()->iColour()==PDT::Colour6 || inpart.dataPtr()->iColour()==PDT::Colour6bar) { if (outgoingVertex1_[inter]->isIncoming(const_ptr_cast(decay[iferm]->dataPtr()))) { outgoingVertexF = outgoingVertex1_[inter]; outgoingVertexA = outgoingVertex2_[inter]; } else { outgoingVertexF = outgoingVertex2_[inter]; outgoingVertexA = outgoingVertex1_[inter]; } } if (! ((incomingVertex_[inter] && (outgoingVertexF || outgoingVertexA)) || ( outgoingVertexF && outgoingVertexA))) { throw Exception() << "Invalid vertices for QCD radiation in SFF decay in SFFDecayer::identifyVertices" << Exception::runerror; } } // QED else { if(decay[iferm]->dataPtr()->charged()) { if (outgoingVertex1_[inter] && outgoingVertex1_[inter]->isIncoming(const_ptr_cast(decay[iferm]->dataPtr()))) outgoingVertexF = outgoingVertex1_[inter]; else outgoingVertexF = outgoingVertex2_[inter]; } if(decay[ianti]->dataPtr()->charged()) { if (outgoingVertex1_[inter] && outgoingVertex1_[inter]->isIncoming(const_ptr_cast(decay[ianti]->dataPtr()))) outgoingVertexA = outgoingVertex1_[inter]; else outgoingVertexA = outgoingVertex2_[inter]; } } } diff --git a/Decay/General/SFFDecayer.h b/Decay/General/SFFDecayer.h --- a/Decay/General/SFFDecayer.h +++ b/Decay/General/SFFDecayer.h @@ -1,226 +1,234 @@ // -*- C++ -*- // // SFFDecayer.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_SFFDecayer_H #define HERWIG_SFFDecayer_H // // This is the declaration of the SFFDecayer class. // #include "GeneralTwoBodyDecayer.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Helicity/Vertex/Scalar/FFSVertex.h" #include "ThePEG/Helicity/Vertex/Scalar/VSSVertex.h" #include "ThePEG/Helicity/Vertex/Vector/FFVVertex.h" namespace Herwig { using namespace ThePEG; using Helicity::FFSVertexPtr; /** \ingroup Decay * The SFFDecayer class implements the decay of a scalar to 2 * fermions in a general model. It holds an FFSVertex pointer that * must be typecast from the VertexBase pointer held in * GeneralTwoBodyDecayer. It implents the virtual functions me2() and * partialWidth(). * * @see GeneralTwoBodyDecayer */ class SFFDecayer: public GeneralTwoBodyDecayer { public: /** * The default constructor. */ SFFDecayer() {} /** @name Virtual functions required by the Decayer class. */ //@{ /** * Return the matrix element squared for a given mode and phase-space channel. * @param ichan The channel we are calculating the matrix element for. * @param part The decaying Particle. * @param decay The particles produced in the decay. * @param meopt Option for the calculation of the matrix element * @return The matrix element squared for the phase-space configuration. */ virtual double me2(const int ichan, const Particle & part, const ParticleVector & decay, MEOption meopt) const; /** * Function to return partial Width * @param inpart The decaying particle. * @param outa One of the decay products. * @param outb The other decay product. */ virtual Energy partialWidth(PMPair inpart, PMPair outa, PMPair outb) const; /** * Has a POWHEG style correction */ virtual POWHEGType hasPOWHEGCorrection() { - return (vertex_->orderInGem()+vertex_->orderInGs())==1 ? FSR : No; + POWHEGType output = FSR; + for(auto vertex : vertex_) { + if(vertex->orderInAllCouplings()!=1) { + output = No; + break; + } + } + return output; } /** * Three-body matrix element including additional QCD radiation */ virtual double threeBodyME(const int , const Particle & inpart, const ParticleVector & decay, ShowerInteraction inter, MEOption meopt); /** * Indentify outgoing vertices for the fermion and antifermion */ void identifyVertices(const int iferm, const int ianti, const Particle & inpart, const ParticleVector & decay, AbstractFFVVertexPtr & outgoingVertexF, AbstractFFVVertexPtr & outgoingVertexA, ShowerInteraction inter); /** * Set the information on the decay */ - virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, VertexBasePtr, + virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, + vector, map &, const vector > &, map); //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ SFFDecayer & operator=(const SFFDecayer &); private: /** * Abstract pointer to AbstractFFSVertex */ - AbstractFFSVertexPtr vertex_; + vector vertex_; /** * Pointer to the perturbative vertex */ - FFSVertexPtr perturbativeVertex_; + vector perturbativeVertex_; /** * Abstract pointer to AbstractVSSVertex for QCD radiation from incoming scalar */ map incomingVertex_; /** * Abstract pointer to AbstractFFVVertex for QCD radiation from outgoing (anti)fermion */ map outgoingVertex1_; /** * Abstract pointer to AbstractFFVVertex for QCD radiation from outgoing (anti)fermion */ map outgoingVertex2_; /** * Spin density matrix */ mutable RhoDMatrix rho_; /** * Scalar wavefunction */ mutable ScalarWaveFunction swave_; /** * Spinor wavefunction */ mutable vector wave_; /** * Barred spinor wavefunction */ mutable vector wavebar_; /** * Spin density matrix for 3 body decay */ mutable RhoDMatrix rho3_; /** * Scalar wavefunction for 3 body decay */ mutable ScalarWaveFunction swave3_; /** * Spinor wavefunction for 3 body decay */ mutable vector wave3_; /** * Barred spinor wavefunction for 3 body decay */ mutable vector wavebar3_; /** * Vector wavefunction for 3 body decay */ mutable vector gluon_; }; } #endif /* HERWIG_SFFDecayer_H */ diff --git a/Decay/General/SRFDecayer.cc b/Decay/General/SRFDecayer.cc --- a/Decay/General/SRFDecayer.cc +++ b/Decay/General/SRFDecayer.cc @@ -1,181 +1,196 @@ // -*- C++ -*- // // SRFDecayer.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SRFDecayer class. // #include "SRFDecayer.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" #include "Herwig/Utilities/Kinematics.h" #include "Herwig/Decay/GeneralDecayMatrixElement.h" using namespace Herwig; using namespace ThePEG::Helicity; IBPtr SRFDecayer::clone() const { return new_ptr(*this); } IBPtr SRFDecayer::fullclone() const { return new_ptr(*this); } void SRFDecayer::setDecayInfo(PDPtr incoming, PDPair outgoing, - VertexBasePtr vertex, + vector vertex, map &, const vector > &, map) { decayInfo(incoming,outgoing); - vertex_ = dynamic_ptr_cast(vertex); - perturbativeVertex_ = dynamic_ptr_cast (vertex); + for(auto vert : vertex) { + vertex_ .push_back(dynamic_ptr_cast(vert)); + perturbativeVertex_ .push_back(dynamic_ptr_cast (vert)); + } } void SRFDecayer::persistentOutput(PersistentOStream & os) const { os << vertex_ << perturbativeVertex_; } void SRFDecayer::persistentInput(PersistentIStream & is, int) { is >> vertex_ >> perturbativeVertex_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigSRFDecayer("Herwig::SRFDecayer", "Herwig.so"); void SRFDecayer::Init() { static ClassDocumentation documentation ("This class implements to decay of a scalar to a spin-3/2 and" " spin-1/2 fermion"); } double SRFDecayer::me2(const int , const Particle & inpart, const ParticleVector & decay,MEOption meopt) const { unsigned int irs=0,ifm=1; if(decay[0]->dataPtr()->iSpin()==PDT::Spin1Half) swap(irs,ifm); if(!ME()) { if(irs==0) ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin0,PDT::Spin3Half,PDT::Spin1Half))); else ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin0,PDT::Spin1Half,PDT::Spin3Half))); } bool ferm = decay[ifm]->id()<0; if(meopt==Initialize) { ScalarWaveFunction:: calculateWaveFunctions(rho_,const_ptr_cast(&inpart),incoming); swave_ = ScalarWaveFunction(inpart.momentum(),inpart.dataPtr(),incoming); } if(meopt==Terminate) { ScalarWaveFunction:: constructSpinInfo(const_ptr_cast(&inpart),incoming,true); if(ferm) { RSSpinorBarWaveFunction:: constructSpinInfo(RSwavebar_,decay[irs],outgoing,true); SpinorWaveFunction:: constructSpinInfo(wave_ ,decay[ifm],outgoing,true); } else { RSSpinorWaveFunction:: constructSpinInfo(RSwave_ ,decay[irs],outgoing,true); SpinorBarWaveFunction:: constructSpinInfo(wavebar_,decay[ifm],outgoing,true); } return 0.; } if(ferm) { RSSpinorBarWaveFunction:: calculateWaveFunctions(RSwavebar_,decay[irs],outgoing); SpinorWaveFunction:: calculateWaveFunctions(wave_ ,decay[ifm],outgoing); } else { RSSpinorWaveFunction:: calculateWaveFunctions(RSwave_ ,decay[irs],outgoing); SpinorBarWaveFunction:: calculateWaveFunctions(wavebar_,decay[ifm],outgoing); } Energy2 scale(sqr(inpart.mass())); for(unsigned int ifm = 0; ifm < 4; ++ifm){ for(unsigned int ia = 0; ia < 2; ++ia) { if(irs==0) { - if(ferm) - (*ME())(0, ifm, ia) = vertex_->evaluate(scale,wave_[ia], - RSwavebar_[ifm],swave_); - else - (*ME())(0, ifm, ia) = vertex_->evaluate(scale,RSwave_[ifm], - wavebar_[ia],swave_); + if(ferm) { + (*ME())(0, ifm, ia) = 0.; + for(auto vert : vertex_) + (*ME())(0, ifm, ia) += vert->evaluate(scale,wave_[ia], + RSwavebar_[ifm],swave_); + } + else { + (*ME())(0, ifm, ia) = 0.; + for(auto vert : vertex_) + (*ME())(0, ifm, ia) += vert->evaluate(scale,RSwave_[ifm], + wavebar_[ia],swave_); + } } else { - if(ferm) - (*ME())(0, ia, ifm) = vertex_->evaluate(scale,wave_[ia], - RSwavebar_[ifm],swave_); - else - (*ME())(0, ia, ifm) = vertex_->evaluate(scale,RSwave_[ifm], - wavebar_[ia],swave_); + if(ferm) { + (*ME())(0, ia, ifm) = 0.; + for(auto vert : vertex_) + (*ME())(0, ia, ifm) += vert->evaluate(scale,wave_[ia], + RSwavebar_[ifm],swave_); + } + else { + (*ME())(0, ia, ifm) = 0.; + for(auto vert : vertex_) + (*ME())(0, ia, ifm) += vert->evaluate(scale,RSwave_[ifm], + wavebar_[ia],swave_); + } } } } double output = (ME()->contract(rho_)).real()/scale*UnitRemoval::E2; // colour and identical particle factors output *= colourFactor(inpart.dataPtr(),decay[irs]->dataPtr(), decay[ifm]->dataPtr()); // return the answer return output; } Energy SRFDecayer::partialWidth(PMPair inpart, PMPair outa, PMPair outb) const { if( inpart.second < outa.second + outb.second ) return ZERO; - if(perturbativeVertex_) { + if(perturbativeVertex_.size()==1 && + perturbativeVertex_[0]) { Energy q = inpart.second; Energy m1 = outa.second, m2 = outb.second; // couplings tcPDPtr in = inpart.first->CC() ? tcPDPtr(inpart.first->CC()) : inpart.first; if(outa.first->iSpin()==PDT::Spin1Half) { swap(m1,m2); - perturbativeVertex_->setCoupling(sqr(inpart.second),outb.first, + perturbativeVertex_[0]->setCoupling(sqr(inpart.second),outb.first, outa.first, in); } else { - perturbativeVertex_->setCoupling(sqr(inpart.second),outa.first, + perturbativeVertex_[0]->setCoupling(sqr(inpart.second),outa.first, outb.first, in); } - Complex left = perturbativeVertex_-> left()*perturbativeVertex_-> norm(); - Complex right = perturbativeVertex_->right()*perturbativeVertex_-> norm(); + Complex left = perturbativeVertex_[0]-> left()*perturbativeVertex_[0]-> norm(); + Complex right = perturbativeVertex_[0]->right()*perturbativeVertex_[0]-> norm(); complex A1 = 0.5*(left+right)*UnitRemoval::InvE; complex B1 = 0.5*(right-left)*UnitRemoval::InvE; Energy2 q2(q*q),m12(m1*m1),m22(m2*m2); Energy2 pcm2(0.25*(q2*(q2-2.*m12-2.*m22)+(m12-m22)*(m12-m22))/q2); Energy pcm(sqrt(pcm2)); Energy Qp(sqrt(-sqr(m2+m1)+q2)),Qm(sqrt(-sqr(m2-m1)+q2)); double r23(sqrt(2./3.)); complex h1(-2.*r23*pcm*q/m1*Qm*B1); complex h2( 2.*r23*pcm*q/m1*Qp*A1); double me2 = real(h1*conj(h1)+h2*conj(h2))/2./sqr(inpart.second); Energy output = me2*pcm/8./Constants::pi; // colour factor output *= colourFactor(inpart.first,outa.first,outb.first); // return the answer return output; } else { return GeneralTwoBodyDecayer::partialWidth(inpart,outa,outb); } } diff --git a/Decay/General/SRFDecayer.h b/Decay/General/SRFDecayer.h --- a/Decay/General/SRFDecayer.h +++ b/Decay/General/SRFDecayer.h @@ -1,170 +1,171 @@ // -*- C++ -*- // // SRFDecayer.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_SRFDecayer_H #define HERWIG_SRFDecayer_H // // This is the declaration of the SRFDecayer class. // #include "GeneralTwoBodyDecayer.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Helicity/Vertex/Scalar/RFSVertex.h" namespace Herwig { using namespace ThePEG; using Helicity::RFSVertexPtr; /** \ingroup Decay * The SRFDecayer class implements the decay of a scalar to spin-3/2 * and spin-1/2 fermion in a general model. It holds an RFSVertex pointer that * must be typecast from the VertexBase pointer held in * GeneralTwoBodyDecayer. It implents the virtual functions me2() and * partialWidth(). * * @see GeneralTwoBodyDecayer */ class SRFDecayer: public GeneralTwoBodyDecayer { public: /** * The default constructor. */ SRFDecayer() {} /** @name Virtual functions required by the Decayer class. */ //@{ /** * Return the matrix element squared for a given mode and phase-space channel. * @param ichan The channel we are calculating the matrix element for. * @param part The decaying Particle. * @param decay The particles produced in the decay. * @param meopt Option for the calculation of the matrix element * @return The matrix element squared for the phase-space configuration. */ virtual double me2(const int ichan, const Particle & part, const ParticleVector & decay, MEOption meopt) const; /** * Function to return partial Width * @param inpart The decaying particle. * @param outa One of the decay products. * @param outb The other decay product. */ virtual Energy partialWidth(PMPair inpart, PMPair outa, PMPair outb) const; /** * Set the information on the decay */ - virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, VertexBasePtr, + virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, + vector, map &, const vector > &, map); //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ SRFDecayer & operator=(const SRFDecayer &); private: /** * Abstract pointer to AbstractFFSVertex */ - AbstractRFSVertexPtr vertex_; + vector vertex_; /** * Pointer to the perturbative vertex */ - RFSVertexPtr perturbativeVertex_; + vector perturbativeVertex_; /** * Spin density matrix */ mutable RhoDMatrix rho_; /** * Scalar wavefunction */ mutable ScalarWaveFunction swave_; /** * Spinor wavefunction */ mutable vector wave_; /** * Barred spinor wavefunction */ mutable vector wavebar_; /** * RS Spinor wavefunction */ mutable vector RSwave_; /** * Barred RS spinor wavefunction */ mutable vector RSwavebar_; }; } #endif /* HERWIG_SRFDecayer_H */ diff --git a/Decay/General/SSSDecayer.cc b/Decay/General/SSSDecayer.cc --- a/Decay/General/SSSDecayer.cc +++ b/Decay/General/SSSDecayer.cc @@ -1,398 +1,410 @@ // -*- C++ -*- // // SSSDecayer.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SSSDecayer class. // #include "SSSDecayer.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h" #include "Herwig/Utilities/Kinematics.h" #include "Herwig/Decay/GeneralDecayMatrixElement.h" using namespace Herwig; using namespace ThePEG::Helicity; IBPtr SSSDecayer::clone() const { return new_ptr(*this); } IBPtr SSSDecayer::fullclone() const { return new_ptr(*this); } void SSSDecayer::setDecayInfo(PDPtr incoming, PDPair outgoing, - VertexBasePtr vertex, + vector vertex, map & inV, const vector > & outV, map ) { decayInfo(incoming,outgoing); - vertex_ = dynamic_ptr_cast(vertex); - perturbativeVertex_ = dynamic_ptr_cast (vertex); + for(auto vert : vertex) { + vertex_ .push_back(dynamic_ptr_cast(vert)); + perturbativeVertex_.push_back(dynamic_ptr_cast (vert)); + } vector itemp={ShowerInteraction::QCD,ShowerInteraction::QED}; for(auto & inter : itemp) { incomingVertex_[inter] = dynamic_ptr_cast(inV.at(inter)); outgoingVertex1_[inter] = dynamic_ptr_cast(outV[0].at(inter)); outgoingVertex2_[inter] = dynamic_ptr_cast(outV[1].at(inter)); } } void SSSDecayer::persistentOutput(PersistentOStream & os) const { os << vertex_ << perturbativeVertex_ << incomingVertex_ << outgoingVertex1_ << outgoingVertex2_; } void SSSDecayer::persistentInput(PersistentIStream & is, int) { is >> vertex_ >> perturbativeVertex_ >> incomingVertex_ >> outgoingVertex1_ >> outgoingVertex2_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigSSSDecayer("Herwig::SSSDecayer", "Herwig.so"); void SSSDecayer::Init() { static ClassDocumentation documentation ("This class implements the decay of a scalar to 2 scalars."); } double SSSDecayer::me2(const int , const Particle & inpart, const ParticleVector & decay, MEOption meopt) const { if(!ME()) ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin0,PDT::Spin0,PDT::Spin0))); if(meopt==Initialize) { ScalarWaveFunction:: calculateWaveFunctions(rho_,const_ptr_cast(&inpart),incoming); swave_ = ScalarWaveFunction(inpart.momentum(),inpart.dataPtr(),incoming); } if(meopt==Terminate) { ScalarWaveFunction:: constructSpinInfo(const_ptr_cast(&inpart),incoming,true); for(unsigned int ix=0;ix<2;++ix) ScalarWaveFunction:: constructSpinInfo(decay[ix],outgoing,true); } ScalarWaveFunction s1(decay[0]->momentum(),decay[0]->dataPtr(),outgoing); ScalarWaveFunction s2(decay[1]->momentum(),decay[1]->dataPtr(),outgoing); Energy2 scale(sqr(inpart.mass())); - (*ME())(0,0,0) = vertex_->evaluate(scale,s1,s2,swave_); + (*ME())(0,0,0) = 0.; + for(auto vert : vertex_) { + (*ME())(0,0,0) += vert->evaluate(scale,s1,s2,swave_); + } double output = (ME()->contract(rho_)).real()/scale*UnitRemoval::E2; // colour and identical particle factors output *= colourFactor(inpart.dataPtr(),decay[0]->dataPtr(), decay[1]->dataPtr()); // return the answer return output; } Energy SSSDecayer::partialWidth(PMPair inpart, PMPair outa, PMPair outb) const { if( inpart.second < outa.second + outb.second ) return ZERO; - if(perturbativeVertex_ && !perturbativeVertex_->kinematics()) { + if(perturbativeVertex_.size()==1 && + perturbativeVertex_[0] && !perturbativeVertex_[0]->kinematics()) { Energy2 scale(sqr(inpart.second)); tcPDPtr in = inpart.first->CC() ? tcPDPtr(inpart.first->CC()) : inpart.first; - perturbativeVertex_->setCoupling(scale, in, outa.first, outb.first); + perturbativeVertex_[0]->setCoupling(scale, in, outa.first, outb.first); Energy pcm = Kinematics::pstarTwoBodyDecay(inpart.second, outa.second, outb.second); - double c2 = norm(perturbativeVertex_->norm()); + double c2 = norm(perturbativeVertex_[0]->norm()); Energy pWidth = c2*pcm/8./Constants::pi/scale*UnitRemoval::E2; // colour factor pWidth *= colourFactor(inpart.first,outa.first,outb.first); return pWidth; } else { return GeneralTwoBodyDecayer::partialWidth(inpart,outa,outb); } } double SSSDecayer::threeBodyME(const int , const Particle & inpart, const ParticleVector & decay, ShowerInteraction inter, MEOption meopt) { // work out which is the scalar and anti scalar int ianti(0), iscal(1), iglu(2); int itype[2]; for(unsigned int ix=0;ix<2;++ix) { if(decay[ix]->dataPtr()->CC()) itype[ix] = decay[ix]->id()>0 ? 0:1; else itype[ix] = 2; } if(itype[0]==0 && itype[1]!=0) swap(ianti, iscal); if(itype[0]==2 && itype[1]==1) swap(ianti, iscal); if(itype[0]==0 && itype[1]==0 && abs(decay[0]->dataPtr()->id())>abs(decay[1]->dataPtr()->id())) swap(iscal, ianti); if(itype[0]==1 && itype[1]==1 && abs(decay[0]->dataPtr()->id())dataPtr()->id())) swap(iscal, ianti); if(meopt==Initialize) { // create scalar wavefunction for decaying particle ScalarWaveFunction::calculateWaveFunctions(rho3_,const_ptr_cast(&inpart),incoming); swave3_ = ScalarWaveFunction(inpart.momentum(),inpart.dataPtr(),incoming); } // setup spin information when needed if(meopt==Terminate) { ScalarWaveFunction:: constructSpinInfo(const_ptr_cast(&inpart),incoming,true); ScalarWaveFunction:: constructSpinInfo(decay[iscal],outgoing,true); ScalarWaveFunction:: constructSpinInfo(decay[ianti],outgoing,true); VectorWaveFunction:: constructSpinInfo(gluon_,decay[iglu ],outgoing,true,false); return 0.; } // calculate colour factors and number of colour flows unsigned int nflow; vector cfactors = getColourFactors(inpart, decay, nflow); vector ME(nflow,new_ptr(GeneralDecayMatrixElement(PDT::Spin0, PDT::Spin0, PDT::Spin0, PDT::Spin1))); // create wavefunctions ScalarWaveFunction scal(decay[iscal]->momentum(), decay[iscal]->dataPtr(),outgoing); ScalarWaveFunction anti(decay[ianti]->momentum(), decay[ianti]->dataPtr(),outgoing); VectorWaveFunction::calculateWaveFunctions(gluon_,decay[iglu ],outgoing,true); // gauge invariance test #ifdef GAUGE_CHECK gluon_.clear(); for(unsigned int ix=0;ix<3;++ix) { if(ix==1) gluon_.push_back(VectorWaveFunction()); else { gluon_.push_back(VectorWaveFunction(decay[iglu ]->momentum(), decay[iglu ]->dataPtr(),10, outgoing)); } } #endif AbstractVSSVertexPtr outgoingVertexS; AbstractVSSVertexPtr outgoingVertexA; identifyVertices(iscal, ianti, inpart, decay, outgoingVertexS, outgoingVertexA,inter); Energy2 scale(sqr(inpart.mass())); const GeneralTwoBodyDecayer::CFlow & colourFlow = colourFlows(inpart, decay); double gs(0.); bool couplingSet(false); #ifdef GAUGE_CHECK double total=0.; #endif for(unsigned int ig = 0; ig < 2; ++ig) { // radiation from the incoming scalar if((inpart.dataPtr()->coloured() && inter==ShowerInteraction::QCD) || (inpart.dataPtr()->charged() && inter==ShowerInteraction::QED) ) { assert(incomingVertex_[inter]); ScalarWaveFunction scalarInter = incomingVertex_[inter]->evaluate(scale,3,inpart.dataPtr(), gluon_[2*ig],swave3_,inpart.mass()); assert(swave3_.particle()->id()==scalarInter.particle()->id()); - Complex diag = vertex_->evaluate(scale,scal,anti,scalarInter); + Complex diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,scal,anti,scalarInter); if(!couplingSet) { gs = abs(incomingVertex_[inter]->norm()); couplingSet = true; } for(unsigned int ix=0;ixdataPtr()->coloured() && inter==ShowerInteraction::QCD) || (decay[iscal]->dataPtr()->charged() && inter==ShowerInteraction::QED) ) { assert(outgoingVertexS); // ensure you get correct outgoing particle from first vertex tcPDPtr off = decay[iscal]->dataPtr(); if(off->CC()) off = off->CC(); ScalarWaveFunction scalarInter = outgoingVertexS->evaluate(scale,3,off,gluon_[2*ig],scal,decay[iscal]->mass()); assert(scal.particle()->id()==scalarInter.particle()->id()); - Complex diag = vertex_->evaluate(scale,swave3_,anti,scalarInter); + Complex diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,swave3_,anti,scalarInter); if(!couplingSet) { gs = abs(outgoingVertexS->norm()); couplingSet = true; } for(unsigned int ix=0;ixdataPtr()->coloured() && inter==ShowerInteraction::QCD) || (decay[ianti]->dataPtr()->charged() && inter==ShowerInteraction::QED) ) { assert(outgoingVertexA); // ensure you get correct outgoing particle from first vertex tcPDPtr off = decay[ianti]->dataPtr(); if(off->CC()) off = off->CC(); ScalarWaveFunction scalarInter = outgoingVertexA->evaluate(scale,3,off, gluon_[2*ig],anti,decay[ianti]->mass()); assert(anti.particle()->id()==scalarInter.particle()->id()); - Complex diag = vertex_->evaluate(scale,swave3_,scal,scalarInter); + Complex diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,swave3_,scal,scalarInter); if(!couplingSet) { gs = abs(outgoingVertexA->norm()); couplingSet = true; } for(unsigned int ix=0;ixcontract(*ME[iy],rho3_)).real(); } } // divide by alpha_(S,EM) output*=(4.*Constants::pi)/sqr(gs); #ifdef GAUGE_CHECK double ratio = output/total; if(abs(ratio)>1e-20) { generator()->log() << "Test of gauge invariance in decay\n" << inpart << "\n"; for(unsigned int ix=0;ixlog() << *decay[ix] << "\n"; generator()->log() << "Test of gauge invariance " << ratio << "\n"; } #endif // return the answer return output; } void SSSDecayer::identifyVertices(const int iscal, const int ianti, const Particle & inpart, const ParticleVector & decay, AbstractVSSVertexPtr & outgoingVertexS, AbstractVSSVertexPtr & outgoingVertexA, ShowerInteraction inter){ // QCD if(inter==ShowerInteraction::QCD) { // work out which scalar each outgoing vertex corresponds to // two outgoing vertices if( inpart.dataPtr() ->iColour()==PDT::Colour0 && ((decay[iscal]->dataPtr()->iColour()==PDT::Colour3 && decay[ianti]->dataPtr()->iColour()==PDT::Colour3bar) || (decay[iscal]->dataPtr()->iColour()==PDT::Colour8 && decay[ianti]->dataPtr()->iColour()==PDT::Colour8))){ if(outgoingVertex1_[inter]==outgoingVertex2_[inter]){ outgoingVertexS = outgoingVertex1_[inter]; outgoingVertexA = outgoingVertex2_[inter]; } else if (outgoingVertex1_[inter]->isIncoming(getParticleData(decay[iscal]->id()))){ outgoingVertexS = outgoingVertex1_[inter]; outgoingVertexA = outgoingVertex2_[inter]; } else if (outgoingVertex2_[inter]->isIncoming(getParticleData(decay[iscal]->id()))){ outgoingVertexS = outgoingVertex2_[inter]; outgoingVertexA = outgoingVertex1_[inter]; } } else if(inpart.dataPtr() ->iColour()==PDT::Colour8 && decay[iscal]->dataPtr()->iColour()==PDT::Colour3 && decay[ianti]->dataPtr()->iColour()==PDT::Colour3bar){ if(outgoingVertex1_[inter]==outgoingVertex2_[inter]){ outgoingVertexS = outgoingVertex1_[inter]; outgoingVertexA = outgoingVertex2_[inter]; } else if (outgoingVertex1_[inter]->isIncoming(getParticleData(decay[iscal]->id()))){ outgoingVertexS = outgoingVertex1_[inter]; outgoingVertexA = outgoingVertex2_[inter]; } else if (outgoingVertex2_[inter]->isIncoming(getParticleData(decay[iscal]->id()))){ outgoingVertexS = outgoingVertex2_[inter]; outgoingVertexA = outgoingVertex1_[inter]; } } // one outgoing vertex else if(inpart.dataPtr() ->iColour()==PDT::Colour3){ if(decay[iscal]->dataPtr()->iColour()==PDT::Colour3 && decay[ianti]->dataPtr()->iColour()==PDT::Colour0){ if (outgoingVertex1_[inter]) outgoingVertexS = outgoingVertex1_[inter]; else if(outgoingVertex2_[inter]) outgoingVertexS = outgoingVertex2_[inter]; } else if (decay[iscal]->dataPtr()->iColour()==PDT::Colour3 && decay[ianti]->dataPtr()->iColour()==PDT::Colour8){ if (outgoingVertex1_[inter]->isIncoming(getParticleData(decay[ianti]->dataPtr()->id()))){ outgoingVertexS = outgoingVertex2_[inter]; outgoingVertexA = outgoingVertex1_[inter]; } else { outgoingVertexS = outgoingVertex1_[inter]; outgoingVertexA = outgoingVertex2_[inter]; } } } else if(inpart.dataPtr() ->iColour()==PDT::Colour3bar){ if(decay[ianti]->dataPtr()->iColour()==PDT::Colour3bar && decay[iscal]->dataPtr()->iColour()==PDT::Colour0){ if (outgoingVertex1_[inter]) outgoingVertexA = outgoingVertex1_[inter]; else if(outgoingVertex2_[inter]) outgoingVertexA = outgoingVertex2_[inter]; } else if (decay[ianti]->dataPtr()->iColour()==PDT::Colour3bar && decay[iscal]->dataPtr()->iColour()==PDT::Colour8){ if (outgoingVertex1_[inter]->isIncoming(getParticleData(decay[iscal]->dataPtr()->id()))){ outgoingVertexS = outgoingVertex1_[inter]; outgoingVertexA = outgoingVertex2_[inter]; } else { outgoingVertexS = outgoingVertex2_[inter]; outgoingVertexA = outgoingVertex1_[inter]; } } } if (! ((incomingVertex_[inter] && (outgoingVertexS || outgoingVertexA)) || ( outgoingVertexS && outgoingVertexA))) throw Exception() << "Invalid vertices for QCD radiation in SSS decay in SSSDecayer::identifyVertices" << Exception::runerror; } // QED else { if(decay[iscal]->dataPtr()->charged()) { if (outgoingVertex1_[inter] && outgoingVertex1_[inter]->isIncoming(const_ptr_cast(decay[iscal]->dataPtr()))) outgoingVertexS = outgoingVertex1_[inter]; else outgoingVertexS = outgoingVertex2_[inter]; } if(decay[ianti]->dataPtr()->charged()) { if (outgoingVertex1_[inter] && outgoingVertex1_[inter]->isIncoming(const_ptr_cast(decay[ianti]->dataPtr()))) outgoingVertexA = outgoingVertex1_[inter]; else outgoingVertexA = outgoingVertex2_[inter]; } } } diff --git a/Decay/General/SSSDecayer.h b/Decay/General/SSSDecayer.h --- a/Decay/General/SSSDecayer.h +++ b/Decay/General/SSSDecayer.h @@ -1,203 +1,211 @@ // -*- C++ -*- // // SSSDecayer.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_SSSDecayer_H #define HERWIG_SSSDecayer_H // // This is the declaration of the SSSDecayer class. // #include "GeneralTwoBodyDecayer.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Helicity/Vertex/Scalar/SSSVertex.h" #include "ThePEG/Helicity/Vertex/Scalar/VSSVertex.h" namespace Herwig { using namespace ThePEG; using Helicity::SSSVertexPtr; /** \ingroup Decay * The SSDecayer class implements the decay of a scalar * to 2 scalars in a general model. It holds a SSSVertex * pointer that must be typecast from the VertexBase pointer held in * GeneralTwoBodyDecayer. It implents the virtual functions me2() and * partialWidth(). * * @see GeneralTwoBodyDecayer */ class SSSDecayer: public GeneralTwoBodyDecayer { public: /** * The default constructor. */ SSSDecayer() {} /** @name Virtual functions required by the Decayer class. */ //@{ /** * Return the matrix element squared for a given mode and phase-space channel. * @param ichan The channel we are calculating the matrix element for. * @param part The decaying Particle. * @param decay The particles produced in the decay. * @param meopt Option for the calculation of the matrix element * @return The matrix element squared for the phase-space configuration. */ virtual double me2(const int ichan, const Particle & part, const ParticleVector & decay, MEOption meopt) const; /** * Function to return partial Width * @param inpart The decaying particle. * @param outa One of the decay products. * @param outb The other decay product. */ virtual Energy partialWidth(PMPair inpart, PMPair outa, PMPair outb) const; /** * Has a POWHEG style correction */ virtual POWHEGType hasPOWHEGCorrection() { - return (vertex_->orderInGem()+vertex_->orderInGs())==1 ? FSR : No; + POWHEGType output = FSR; + for(auto vertex : vertex_) { + if(vertex->orderInAllCouplings()!=1) { + output = No; + break; + } + } + return output; } /** * Three-body matrix element including additional QCD radiation */ virtual double threeBodyME(const int , const Particle & inpart, const ParticleVector & decay, ShowerInteraction inter, MEOption meopt); /** * Indentify outgoing vertices for the scalar and anti scalar */ void identifyVertices(const int iscal, const int ianti, const Particle & inpart, const ParticleVector & decay, AbstractVSSVertexPtr & abstractOutgoingVertexS, AbstractVSSVertexPtr & abstractOutgoingVertexA, ShowerInteraction inter); /** * Set the information on the decay */ - virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, VertexBasePtr, + virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, + vector, map &, const vector > &, map); //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ SSSDecayer & operator=(const SSSDecayer &); private: /** * Abstract pointer to AbstractSSSVertex */ - AbstractSSSVertexPtr vertex_; + vector vertex_; /** * Pointer to the perturbative vertex */ - SSSVertexPtr perturbativeVertex_; + vector perturbativeVertex_; /** * Abstract pointer to AbstractVSSVertex for QCD radiation from incoming scalar */ map incomingVertex_; /** * Abstract pointer to AbstractVSSVertex for QCD radiation from outgoing scalar */ map outgoingVertex1_; /** * Abstract pointer to AbstractVSSVertex for QCD radiation from outgoing scalar */ map outgoingVertex2_; /** * Spin density matrix */ mutable RhoDMatrix rho_; /** * Scalar wavefunctions */ mutable Helicity::ScalarWaveFunction swave_; /** * Spin density matrix for 3 body decay */ mutable RhoDMatrix rho3_; /** * Scalar wavefunction for 3 body decay */ mutable Helicity::ScalarWaveFunction swave3_; /** * Vector wavefunction for 3 body decay */ mutable vector gluon_; }; } #endif /* HERWIG_SSSDecayer_H */ diff --git a/Decay/General/SSVDecayer.cc b/Decay/General/SSVDecayer.cc --- a/Decay/General/SSVDecayer.cc +++ b/Decay/General/SSVDecayer.cc @@ -1,351 +1,366 @@ // -*- C++ -*- // // SSVDecayer.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SSVDecayer class. // #include "SSVDecayer.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/DecayMode.h" #include "Herwig/Utilities/Kinematics.h" #include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "Herwig/Decay/GeneralDecayMatrixElement.h" using namespace Herwig; using namespace ThePEG::Helicity; IBPtr SSVDecayer::clone() const { return new_ptr(*this); } IBPtr SSVDecayer::fullclone() const { return new_ptr(*this); } void SSVDecayer::setDecayInfo(PDPtr incoming, PDPair outgoing, - VertexBasePtr vertex, + vector vertex, map & inV, const vector > & outV, map fourV) { decayInfo(incoming,outgoing); - vertex_ = dynamic_ptr_cast(vertex); - perturbativeVertex_ = dynamic_ptr_cast (vertex); + for(auto vert : vertex) { + vertex_ .push_back(dynamic_ptr_cast(vert)); + perturbativeVertex_.push_back(dynamic_ptr_cast (vert)); + } vector itemp={ShowerInteraction::QCD,ShowerInteraction::QED}; for(auto & inter : itemp) { incomingVertex_[inter] = dynamic_ptr_cast(inV.at(inter)); fourPointVertex_[inter] = dynamic_ptr_cast(fourV.at(inter)); outgoingVertexS_[inter] = AbstractVSSVertexPtr(); outgoingVertexV_[inter] = AbstractVVVVertexPtr(); if(outV[0].at(inter)) { if (outV[0].at(inter)->getName()==VertexType::VSS) outgoingVertexS_[inter] = dynamic_ptr_cast(outV[0].at(inter)); else outgoingVertexV_[inter] = dynamic_ptr_cast(outV[0].at(inter)); } if(outV[1].at(inter)) { if (outV[1].at(inter)->getName()==VertexType::VSS) outgoingVertexS_[inter] = dynamic_ptr_cast(outV[1].at(inter)); else outgoingVertexV_[inter] = dynamic_ptr_cast(outV[1].at(inter)); } } } void SSVDecayer::persistentOutput(PersistentOStream & os) const { os << vertex_ << perturbativeVertex_ << incomingVertex_ << outgoingVertexS_ << outgoingVertexV_ << fourPointVertex_; } void SSVDecayer::persistentInput(PersistentIStream & is, int) { is >> vertex_ >> perturbativeVertex_ >> incomingVertex_ >> outgoingVertexS_ >> outgoingVertexV_ >> fourPointVertex_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigSSVDecayer("Herwig::SSVDecayer", "Herwig.so"); void SSVDecayer::Init() { static ClassDocumentation documentation ("This implements the decay of a scalar to a vector and a scalar"); } double SSVDecayer::me2(const int , const Particle & inpart, const ParticleVector & decay, MEOption meopt) const { unsigned int isc(0),ivec(1); if(decay[0]->dataPtr()->iSpin() != PDT::Spin0) swap(isc,ivec); if(!ME()) { if(ivec==1) ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin0,PDT::Spin0,PDT::Spin1))); else ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin0,PDT::Spin1,PDT::Spin0))); } if(meopt==Initialize) { ScalarWaveFunction:: calculateWaveFunctions(rho_,const_ptr_cast(&inpart),incoming); swave_ = ScalarWaveFunction(inpart.momentum(),inpart.dataPtr(),incoming); } if(meopt==Terminate) { ScalarWaveFunction:: constructSpinInfo(const_ptr_cast(&inpart),incoming,true); ScalarWaveFunction:: constructSpinInfo(decay[isc],outgoing,true); VectorWaveFunction:: constructSpinInfo(vector_,decay[ivec],outgoing,true,false); } VectorWaveFunction:: calculateWaveFunctions(vector_,decay[ivec],outgoing,false); ScalarWaveFunction sca(decay[isc]->momentum(),decay[isc]->dataPtr(),outgoing); Energy2 scale(sqr(inpart.mass())); //make sure decay matrix element is in the correct order double output(0.); if(ivec == 0) { - for(unsigned int ix = 0; ix < 3; ++ix) - (*ME())(0, ix, 0) = vertex_->evaluate(scale,vector_[ix],sca, swave_); + for(unsigned int ix = 0; ix < 3; ++ix) { + (*ME())(0, ix, 0) = 0.; + for(auto vert : vertex_) + (*ME())(0, ix, 0) += vert->evaluate(scale,vector_[ix],sca, swave_); + } } else { - for(unsigned int ix = 0; ix < 3; ++ix) - (*ME())(0, 0, ix) = vertex_->evaluate(scale,vector_[ix],sca,swave_); + for(unsigned int ix = 0; ix < 3; ++ix) { + (*ME())(0, 0, ix) = 0.; + for(auto vert : vertex_) + (*ME())(0, 0, ix) += vert->evaluate(scale,vector_[ix],sca,swave_); + } } output = (ME()->contract(rho_)).real()/scale*UnitRemoval::E2; // colour and identical particle factors output *= colourFactor(inpart.dataPtr(),decay[0]->dataPtr(), decay[1]->dataPtr()); // return the answer return output; } Energy SSVDecayer:: partialWidth(PMPair inpart, PMPair outa, PMPair outb) const { if( inpart.second < outa.second + outb.second ) return ZERO; - if(perturbativeVertex_) { + if(perturbativeVertex_.size()==1 && + perturbativeVertex_[0]) { double mu1sq(sqr(outa.second/inpart.second)), mu2sq(sqr(outb.second/inpart.second)); tcPDPtr in = inpart.first->CC() ? tcPDPtr(inpart.first->CC()) : inpart.first; if(outa.first->iSpin() == PDT::Spin0) { - perturbativeVertex_->setCoupling(sqr(inpart.second), outb.first, outa.first,in); + perturbativeVertex_[0]->setCoupling(sqr(inpart.second), outb.first, outa.first,in); } else { swap(mu1sq,mu2sq); - perturbativeVertex_->setCoupling(sqr(inpart.second), outa.first, outb.first,in); + perturbativeVertex_[0]->setCoupling(sqr(inpart.second), outa.first, outb.first,in); } double me2(0.); if(mu2sq == 0.) me2 = -2.*mu1sq - 2.; else me2 = ( sqr(mu2sq - mu1sq) - 2.*(mu2sq + mu1sq) + 1. )/mu2sq; Energy pcm = Kinematics::pstarTwoBodyDecay(inpart.second, outa.second, outb.second); - Energy output = pcm*me2*norm(perturbativeVertex_->norm())/8./Constants::pi; + Energy output = pcm*me2*norm(perturbativeVertex_[0]->norm())/8./Constants::pi; // colour factor output *= colourFactor(inpart.first,outa.first,outb.first); // return the answer return output; } else { return GeneralTwoBodyDecayer::partialWidth(inpart,outa,outb); } } double SSVDecayer::threeBodyME(const int , const Particle & inpart, const ParticleVector & decay, ShowerInteraction inter, MEOption meopt) { int iscal (0), ivect (1), iglu (2); // get location of outgoing scalar/vector if(decay[1]->dataPtr()->iSpin()==PDT::Spin0) swap(iscal,ivect); if(meopt==Initialize) { // create scalar wavefunction for decaying particle ScalarWaveFunction::calculateWaveFunctions(rho3_,const_ptr_cast(&inpart),incoming); swave3_ = ScalarWaveFunction(inpart.momentum(),inpart.dataPtr(),incoming); } // setup spin information when needed if(meopt==Terminate) { ScalarWaveFunction:: constructSpinInfo(const_ptr_cast(&inpart),incoming,true); ScalarWaveFunction:: constructSpinInfo(decay[iscal],outgoing,true); VectorWaveFunction:: constructSpinInfo(vector3_,decay[ivect],outgoing,true,false); VectorWaveFunction:: constructSpinInfo(gluon_, decay[iglu ],outgoing,true,false); return 0.; } // calculate colour factors and number of colour flows unsigned int nflow; vector cfactors = getColourFactors(inpart, decay, nflow); vector ME(nflow,new_ptr(GeneralDecayMatrixElement(PDT::Spin0, PDT::Spin0, PDT::Spin1, PDT::Spin1))); // create wavefunctions ScalarWaveFunction scal(decay[iscal]->momentum(), decay[iscal]->dataPtr(),outgoing); VectorWaveFunction::calculateWaveFunctions(vector3_,decay[ivect],outgoing,false); VectorWaveFunction::calculateWaveFunctions(gluon_, decay[iglu ],outgoing,true ); // gauge invariance test #ifdef GAUGE_CHECK gluon_.clear(); for(unsigned int ix=0;ix<3;++ix) { if(ix==1) gluon_.push_back(VectorWaveFunction()); else { gluon_.push_back(VectorWaveFunction(decay[iglu ]->momentum(), decay[iglu ]->dataPtr(),10, outgoing)); } } #endif if (! ((incomingVertex_[inter] && (outgoingVertexS_[inter] || outgoingVertexV_[inter])) || (outgoingVertexS_[inter] && outgoingVertexV_[inter]))) throw Exception() << "Invalid vertices for radiation in SSV decay in SSVDecayer::threeBodyME" << Exception::runerror; // sort out colour flows int S(1), V(2); if (decay[iscal]->dataPtr()->iColour()==PDT::Colour3bar && decay[ivect]->dataPtr()->iColour()==PDT::Colour8) swap(S,V); else if (decay[ivect]->dataPtr()->iColour()==PDT::Colour3 && decay[iscal]->dataPtr()->iColour()==PDT::Colour8) swap(S,V); Energy2 scale(sqr(inpart.mass())); const GeneralTwoBodyDecayer::CFlow & colourFlow = colourFlows(inpart, decay); double gs(0.); bool couplingSet(false); #ifdef GAUGE_CHECK double total=0.; #endif for(unsigned int iv = 0; iv < 3; ++iv) { for(unsigned int ig = 0; ig < 2; ++ig) { // radiation from the incoming scalar if((inpart.dataPtr()->coloured() && inter==ShowerInteraction::QCD) || (inpart.dataPtr()->charged() && inter==ShowerInteraction::QED) ) { assert(incomingVertex_[inter]); ScalarWaveFunction scalarInter = incomingVertex_[inter]->evaluate(scale,3,inpart.dataPtr(), gluon_[2*ig],swave3_,inpart.mass()); assert(swave3_.particle()->id()==scalarInter.particle()->id()); - Complex diag = vertex_->evaluate(scale,vector3_[iv],scal,scalarInter); + Complex diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,vector3_[iv],scal,scalarInter); if(!couplingSet) { gs = abs(incomingVertex_[inter]->norm()); couplingSet = true; } for(unsigned int ix=0;ixdataPtr()->coloured() && inter==ShowerInteraction::QCD) || (decay[iscal]->dataPtr()->charged() && inter==ShowerInteraction::QED) ) { assert(outgoingVertexS_[inter]); // ensure you get correct outgoing particle from first vertex tcPDPtr off = decay[iscal]->dataPtr(); if(off->CC()) off = off->CC(); ScalarWaveFunction scalarInter = outgoingVertexS_[inter]->evaluate(scale,3,off,gluon_[2*ig],scal,decay[iscal]->mass()); assert(scal.particle()->id()==scalarInter.particle()->id()); if(!couplingSet) { gs = abs(outgoingVertexS_[inter]->norm()); couplingSet = true; } - Complex diag = vertex_->evaluate(scale,vector3_[iv],scalarInter,swave3_); + Complex diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,vector3_[iv],scalarInter,swave3_); for(unsigned int ix=0;ixdataPtr()->coloured() && inter==ShowerInteraction::QCD) || (decay[ivect]->dataPtr()->charged() && inter==ShowerInteraction::QED) ) { assert(outgoingVertexV_[inter]); // ensure you get correct outgoing particle from first vertex tcPDPtr off = decay[ivect]->dataPtr(); if(off->CC()) off = off->CC(); VectorWaveFunction vectorInter = outgoingVertexV_[inter]->evaluate(scale,3,off,gluon_[2*ig], vector3_[iv],decay[ivect]->mass()); assert(vector3_[iv].particle()->id()==vectorInter.particle()->id()); if(!couplingSet) { gs = abs(outgoingVertexV_[inter]->norm()); couplingSet = true; } - Complex diag = vertex_->evaluate(scale,vectorInter,scal,swave3_); + Complex diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,vectorInter,scal,swave3_); for(unsigned int ix=0;ixevaluate(scale, gluon_[2*ig], vector3_[iv], scal, swave3_); for(unsigned int ix=0;ixcontract(*ME[iy],rho3_)).real(); } } // divide by alpha_(S,EM) output*=(4.*Constants::pi)/sqr(gs); #ifdef GAUGE_CHECK double ratio = output/total; if(abs(ratio)>1e-20) { generator()->log() << "Test of gauge invariance in decay\n" << inpart << "\n"; for(unsigned int ix=0;ixlog() << *decay[ix] << "\n"; generator()->log() << "Test of gauge invariance " << ratio << "\n"; } #endif // return the answer return output; } diff --git a/Decay/General/SSVDecayer.h b/Decay/General/SSVDecayer.h --- a/Decay/General/SSVDecayer.h +++ b/Decay/General/SSVDecayer.h @@ -1,216 +1,224 @@ // -*- C++ -*- // // SSVDecayer.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_SSVDecayer_H #define HERWIG_SSVDecayer_H // // This is the declaration of the SSVDecayer class. // #include "GeneralTwoBodyDecayer.h" #include "ThePEG/Helicity/Vertex/Scalar/VSSVertex.h" #include "ThePEG/Helicity/Vertex/Vector/VVVVertex.h" #include "ThePEG/Helicity/Vertex/Scalar/VVSSVertex.h" #include "ThePEG/Repository/EventGenerator.h" namespace Herwig { using namespace ThePEG; using Helicity::VSSVertexPtr; /** \ingroup Decay * The SSVDecayer class implements the decay of a scalar to a vector * and a scalar in a general model. It holds an VSSVertex pointer * that must be typecast from the VertexBase pointer held in * GeneralTwoBodyDecayer. It implents the virtual functions me2() and * partialWidth(). * * @see GeneralTwoBodyDecayer */ class SSVDecayer: public GeneralTwoBodyDecayer { public: /** * The default constructor. */ SSVDecayer() {} /** @name Virtual functions required by the Decayer class. */ //@{ /** * Return the matrix element squared for a given mode and phase-space channel * @param ichan The channel we are calculating the matrix element for. * @param part The decaying Particle. * @param decay The particles produced in the decay. * @param meopt Option for the calculation of the matrix element * @return The matrix element squared for the phase-space configuration. */ virtual double me2(const int ichan, const Particle & part, const ParticleVector & decay, MEOption meopt) const; /** * Function to return partial Width * @param inpart The decaying particle. * @param outa One of the decay products. * @param outb The other decay product. */ virtual Energy partialWidth(PMPair inpart, PMPair outa, PMPair outb) const; /** * Has a POWHEG style correction */ virtual POWHEGType hasPOWHEGCorrection() { - return (vertex_->orderInGem()+vertex_->orderInGs())==1 ? FSR : No; + POWHEGType output = FSR; + for(auto vertex : vertex_) { + if(vertex->orderInAllCouplings()!=1) { + output = No; + break; + } + } + return output; } /** * Three-body matrix element including additional QCD radiation */ virtual double threeBodyME(const int , const Particle & inpart, const ParticleVector & decay, ShowerInteraction inter, MEOption meopt); /** * Set the information on the decay */ - virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, VertexBasePtr, + virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, + vector, map &, const vector > &, map); //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ SSVDecayer & operator=(const SSVDecayer &); private: /** * Abstract pointer to AbstractFFVVertex */ - AbstractVSSVertexPtr vertex_; + vector vertex_; /** * Pointer to the perturbative vertex */ - VSSVertexPtr perturbativeVertex_; + vector perturbativeVertex_; /** * Abstract pointer to AbstractVSSVertex for QCD radiation from incoming scalar */ map incomingVertex_; /** * Abstract pointer to AbstractVSSVertex for QCD radiation from outgoing scalar */ map outgoingVertexS_; /** * Abstract pointer to AbstractVVVVertex for QCD radiation from outgoing vector */ map outgoingVertexV_; /** * Abstract pointer to AbstractVVSSVertex for QCD radiation from 4 point vertex */ map fourPointVertex_; /** * Spinor density matrix */ mutable RhoDMatrix rho_; /** * Scalar wavefunction */ mutable Helicity::ScalarWaveFunction swave_; /** * Vector wavefunction */ mutable vector vector_; /** * Spin density matrix for 3 body decay */ mutable RhoDMatrix rho3_; /** * Scalar wavefunction for 3 body decay */ mutable Helicity::ScalarWaveFunction swave3_; /** * Scalar wavefunction for 3 body decay */ mutable Helicity::ScalarWaveFunction scal_; /** * Vector wavefunction for 3 body decay */ mutable vector vector3_; /** * Vector wavefunction for 3 body decay */ mutable vector gluon_; }; } #endif /* HERWIG_SSVDecayer_H */ diff --git a/Decay/General/SVVDecayer.cc b/Decay/General/SVVDecayer.cc --- a/Decay/General/SVVDecayer.cc +++ b/Decay/General/SVVDecayer.cc @@ -1,421 +1,432 @@ // -*- C++ -*- // // SVVDecayer.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SVVDecayer class. // #include "SVVDecayer.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/Helicity/Vertex/Scalar/VVSVertex.h" #include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "Herwig/Utilities/Kinematics.h" #include "Herwig/Decay/GeneralDecayMatrixElement.h" using namespace Herwig; using namespace ThePEG::Helicity; IBPtr SVVDecayer::clone() const { return new_ptr(*this); } IBPtr SVVDecayer::fullclone() const { return new_ptr(*this); } void SVVDecayer::setDecayInfo(PDPtr incoming, PDPair outgoing, - VertexBasePtr vertex, + vector vertex, map & inV, const vector > & outV, map ) { decayInfo(incoming,outgoing); - vertex_ = dynamic_ptr_cast(vertex); - perturbativeVertex_ = dynamic_ptr_cast (vertex); + for(auto vert : vertex) { + vertex_ .push_back(dynamic_ptr_cast(vert)); + perturbativeVertex_.push_back(dynamic_ptr_cast (vert)); + } vector itemp={ShowerInteraction::QCD,ShowerInteraction::QED}; for(auto & inter : itemp) { incomingVertex_[inter] = dynamic_ptr_cast(inV.at(inter)); outgoingVertex1_[inter] = dynamic_ptr_cast(outV[0].at(inter)); outgoingVertex2_[inter] = dynamic_ptr_cast(outV[1].at(inter)); } } void SVVDecayer::persistentOutput(PersistentOStream & os) const { os << vertex_ << perturbativeVertex_ << incomingVertex_ << outgoingVertex1_ << outgoingVertex2_; } void SVVDecayer::persistentInput(PersistentIStream & is, int) { is >> vertex_ >> perturbativeVertex_ >> incomingVertex_ >> outgoingVertex1_ >> outgoingVertex2_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigSVVDecayer("Herwig::SVVDecayer", "Herwig.so"); void SVVDecayer::Init() { static ClassDocumentation documentation ("This implements the decay of a scalar to 2 vector bosons."); } double SVVDecayer::me2(const int , const Particle & inpart, const ParticleVector& decay, MEOption meopt) const { if(!ME()) ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin0,PDT::Spin1,PDT::Spin1))); bool photon[2]; for(unsigned int ix=0;ix<2;++ix) photon[ix] = decay[ix]->mass()==ZERO; if(meopt==Initialize) { ScalarWaveFunction:: calculateWaveFunctions(rho_,const_ptr_cast(&inpart),incoming); swave_ = ScalarWaveFunction(inpart.momentum(),inpart.dataPtr(),incoming); } if(meopt==Terminate) { ScalarWaveFunction:: constructSpinInfo(const_ptr_cast(&inpart),incoming,true); for(unsigned int ix=0;ix<2;++ix) VectorWaveFunction:: constructSpinInfo(vectors_[ix],decay[ix],outgoing,true,photon[ix]); } for(unsigned int ix=0;ix<2;++ix) VectorWaveFunction:: calculateWaveFunctions(vectors_[ix],decay[ix],outgoing,photon[ix]); Energy2 scale(sqr(inpart.mass())); unsigned int iv1,iv2; for(iv2 = 0; iv2 < 3; ++iv2) { if( photon[1] && iv2 == 1 ) ++iv2; for(iv1=0;iv1<3;++iv1) { if( photon[0] && iv1 == 1) ++iv1; - (*ME())(0, iv1, iv2) = vertex_->evaluate(scale,vectors_[0][iv1], + (*ME())(0, iv1, iv2) = 0.; + for(auto vert : vertex_) + (*ME())(0, iv1, iv2) += vert->evaluate(scale,vectors_[0][iv1], vectors_[1][iv2],swave_); } } double output = ME()->contract(rho_).real()/scale*UnitRemoval::E2; // colour and identical particle factors output *= colourFactor(inpart.dataPtr(),decay[0]->dataPtr(), decay[1]->dataPtr()); // return the answer return output; } Energy SVVDecayer::partialWidth(PMPair inpart, PMPair outa, PMPair outb) const { if( inpart.second < outa.second + outb.second ) return ZERO; - if(perturbativeVertex_) { + if(perturbativeVertex_.size()==1 && + perturbativeVertex_[0]) { Energy2 scale(sqr(inpart.second)); tcPDPtr in = inpart.first->CC() ? tcPDPtr(inpart.first->CC()) : inpart.first; - perturbativeVertex_->setCoupling(scale, outa.first , + perturbativeVertex_[0]->setCoupling(scale, outa.first , outb.first, in); double mu1sq = sqr(outa.second/inpart.second); double mu2sq = sqr(outb.second/inpart.second); double m1pm2 = mu1sq + mu2sq; double me2(0.); if( mu1sq > 0. && mu2sq > 0.) me2 = ( m1pm2*(m1pm2 - 2.) + 8.*mu1sq*mu2sq + 1.)/4./mu1sq/mu2sq; else if( mu1sq == 0. || mu2sq == 0. ) me2 = 3.; else me2 = 4.; Energy pcm = Kinematics::pstarTwoBodyDecay(inpart.second,outa.second, outb.second); - Energy output = norm(perturbativeVertex_->norm())* + Energy output = norm(perturbativeVertex_[0]->norm())* me2*pcm/(8*Constants::pi)/scale*UnitRemoval::E2; // colour factor output *= colourFactor(inpart.first,outa.first,outb.first); // return the answer return output; } else { return GeneralTwoBodyDecayer::partialWidth(inpart,outa,outb); } } double SVVDecayer::threeBodyME(const int , const Particle & inpart, const ParticleVector & decay, ShowerInteraction inter, MEOption meopt) { if(meopt==Initialize) { // create scalar wavefunction for decaying particle ScalarWaveFunction:: calculateWaveFunctions(rho3_,const_ptr_cast(&inpart),incoming); swave3_ = ScalarWaveFunction(inpart.momentum(),inpart.dataPtr(),incoming); } if(meopt==Terminate) { ScalarWaveFunction:: constructSpinInfo(const_ptr_cast(&inpart),incoming,true); VectorWaveFunction:: constructSpinInfo(vectors3_[0],decay[0],outgoing,true,false); VectorWaveFunction:: constructSpinInfo(vectors3_[1],decay[1],outgoing,true,false); VectorWaveFunction:: constructSpinInfo(gluon_ ,decay[2],outgoing,true,false); return 0.; } // calculate colour factors and number of colour flows unsigned int nflow; vector cfactors = getColourFactors(inpart, decay, nflow); vector ME(nflow,new_ptr(GeneralDecayMatrixElement(PDT::Spin0, PDT::Spin1, PDT::Spin1, PDT::Spin1))); bool massless[2]; for(unsigned int ix=0;ix<2;++ix) massless[ix] = decay[ix]->mass()!=ZERO; // create wavefunctions VectorWaveFunction::calculateWaveFunctions(vectors3_[0],decay[0],outgoing,massless[0]); VectorWaveFunction::calculateWaveFunctions(vectors3_[1],decay[1],outgoing,massless[1]); VectorWaveFunction::calculateWaveFunctions(gluon_ ,decay[2],outgoing,true); // gauge test #ifdef GAUGE_CHECK gluon_.clear(); for(unsigned int ix=0;ix<3;++ix) { if(ix==1) gluon_.push_back(VectorWaveFunction()); else { gluon_.push_back(VectorWaveFunction(decay[2]->momentum(), decay[2]->dataPtr(),10, outgoing)); } } #endif // get the outgoing vertices AbstractVVVVertexPtr outgoingVertex1; AbstractVVVVertexPtr outgoingVertex2; identifyVertices(inpart,decay, outgoingVertex1, outgoingVertex2,inter); Energy2 scale(sqr(inpart.mass())); const GeneralTwoBodyDecayer::CFlow & colourFlow = colourFlows(inpart, decay); double gs(0.); bool couplingSet(false); #ifdef GAUGE_CHECK double total=0.; #endif for(unsigned int iv1 = 0; iv1 < 3; ++iv1) { if(massless[0] && iv1==1) continue; for(unsigned int iv2 = 0; iv2 < 3; ++iv2) { if(massless[1] && iv2==1) continue; for(unsigned int ig = 0; ig < 2; ++ig) { // radiation from the incoming vector if((inpart.dataPtr()->coloured() && inter==ShowerInteraction::QCD) || (inpart.dataPtr()->charged() && inter==ShowerInteraction::QED) ) { assert(incomingVertex_[inter]); ScalarWaveFunction scalarInter = incomingVertex_[inter]->evaluate(scale,3,inpart.dataPtr(),gluon_[2*ig], swave3_,inpart.mass()); assert(swave3_.particle()->id()==scalarInter.particle()->id()); - Complex diag = vertex_->evaluate(scale,vectors3_[0][iv1], - vectors3_[1][iv2],scalarInter); + Complex diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,vectors3_[0][iv1], + vectors3_[1][iv2],scalarInter); if(!couplingSet) { gs = abs(incomingVertex_[inter]->norm()); couplingSet = true; } for(unsigned int ix=0;ixdataPtr()->coloured() && inter==ShowerInteraction::QCD) || (decay[0]->dataPtr()->charged() && inter==ShowerInteraction::QED) ) { assert(outgoingVertex1); // ensure you get correct outgoing particle from first vertex tcPDPtr off = decay[0]->dataPtr(); if(off->CC()) off = off->CC(); VectorWaveFunction vectorInter = outgoingVertex1->evaluate(scale,3,off,gluon_[2*ig],vectors3_[0][iv1],decay[0]->mass()); assert(vectors3_[0][iv1].particle()->id()==vectorInter.particle()->id()); - Complex diag =vertex_->evaluate(scale,vectorInter,vectors3_[1][iv2],swave3_); + Complex diag =0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,vectorInter,vectors3_[1][iv2],swave3_); if(!couplingSet) { gs = abs(outgoingVertex1->norm()); couplingSet = true; } for(unsigned int ix=0;ixdataPtr()->coloured() && inter==ShowerInteraction::QCD) || (decay[1]->dataPtr()->charged() && inter==ShowerInteraction::QED) ) { assert(outgoingVertex2); // ensure you get correct outgoing particle from first vertex tcPDPtr off = decay[1]->dataPtr(); if(off->CC()) off = off->CC(); VectorWaveFunction vectorInter = outgoingVertex2->evaluate(scale,3,off, gluon_[2*ig],vectors3_[1][iv2],decay[1]->mass()); assert(vectors3_[1][iv2].particle()->id()==vectorInter.particle()->id()); - Complex diag = vertex_->evaluate(scale,vectors3_[0][iv1],vectorInter,swave3_); + Complex diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,vectors3_[0][iv1],vectorInter,swave3_); if(!couplingSet) { gs = abs(outgoingVertex2->norm()); couplingSet = true; } for(unsigned int ix=0;ixcontract(*ME[iy],rho3_)).real(); } } // divide by alpha_(S,EM) output*=(4.*Constants::pi)/sqr(gs); #ifdef GAUGE_CHECK double ratio = output/total; if(abs(ratio)>1e-20) { generator()->log() << "Test of gauge invariance in decay\n" << inpart << "\n"; for(unsigned int ix=0;ixlog() << *decay[ix] << "\n"; generator()->log() << "Test of gauge invariance " << ratio << "\n"; } #endif // return the answer return output; } void SVVDecayer::identifyVertices(const Particle & inpart, const ParticleVector & decay, AbstractVVVVertexPtr & outgoingVertex1, AbstractVVVVertexPtr & outgoingVertex2, ShowerInteraction inter) { if(inter==ShowerInteraction::QCD) { // work out which scalar each outgoing vertex corresponds to // two outgoing vertices if( inpart.dataPtr() ->iColour()==PDT::Colour0 && ((decay[0]->dataPtr()->iColour()==PDT::Colour3 && decay[1]->dataPtr()->iColour()==PDT::Colour3bar) || (decay[0]->dataPtr()->iColour()==PDT::Colour8 && decay[1]->dataPtr()->iColour()==PDT::Colour8))){ if(outgoingVertex1_[inter]==outgoingVertex2_[inter]){ outgoingVertex1 = outgoingVertex1_[inter]; outgoingVertex2 = outgoingVertex2_[inter]; } else if (outgoingVertex1_[inter]->isIncoming(getParticleData(decay[0]->id()))){ outgoingVertex1 = outgoingVertex1_[inter]; outgoingVertex2 = outgoingVertex2_[inter]; } else if (outgoingVertex2_[inter]->isIncoming(getParticleData(decay[0]->id()))){ outgoingVertex1 = outgoingVertex2_[inter]; outgoingVertex2 = outgoingVertex1_[inter]; } } else if(inpart.dataPtr() ->iColour()==PDT::Colour8 && decay[0]->dataPtr()->iColour()==PDT::Colour3 && decay[1]->dataPtr()->iColour()==PDT::Colour3bar){ if(outgoingVertex1_[inter]==outgoingVertex2_[inter]){ outgoingVertex1 = outgoingVertex1_[inter]; outgoingVertex2 = outgoingVertex2_[inter]; } else if (outgoingVertex1_[inter]->isIncoming(getParticleData(decay[0]->id()))){ outgoingVertex1 = outgoingVertex1_[inter]; outgoingVertex2 = outgoingVertex2_[inter]; } else if (outgoingVertex2_[inter]->isIncoming(getParticleData(decay[0]->id()))){ outgoingVertex1 = outgoingVertex2_[inter]; outgoingVertex2 = outgoingVertex1_[inter]; } } // one outgoing vertex else if(inpart.dataPtr()->iColour()==PDT::Colour3){ if(decay[0]->dataPtr()->iColour()==PDT::Colour3 && decay[1]->dataPtr()->iColour()==PDT::Colour0){ if (outgoingVertex1_[inter]) outgoingVertex1 = outgoingVertex1_[inter]; else if(outgoingVertex2_[inter]) outgoingVertex1 = outgoingVertex2_[inter]; } else if (decay[0]->dataPtr()->iColour()==PDT::Colour3 && decay[1]->dataPtr()->iColour()==PDT::Colour8){ if (outgoingVertex1_[inter]->isIncoming(getParticleData(decay[1]->dataPtr()->id()))){ outgoingVertex1 = outgoingVertex2_[inter]; outgoingVertex2 = outgoingVertex1_[inter]; } else { outgoingVertex1 = outgoingVertex1_[inter]; outgoingVertex2 = outgoingVertex2_[inter]; } } } else if(inpart.dataPtr()->iColour()==PDT::Colour3bar){ if(decay[1]->dataPtr()->iColour()==PDT::Colour3bar && decay[0]->dataPtr()->iColour()==PDT::Colour0){ if (outgoingVertex1_[inter]) outgoingVertex2 = outgoingVertex1_[inter]; else if(outgoingVertex2_[inter]) outgoingVertex2 = outgoingVertex2_[inter]; } else if (decay[0]->dataPtr()->iColour()==PDT::Colour8 && decay[1]->dataPtr()->iColour()==PDT::Colour3bar){ if (outgoingVertex1_[inter]->isIncoming(getParticleData(decay[0]->dataPtr()->id()))){ outgoingVertex1 = outgoingVertex1_[inter]; outgoingVertex2 = outgoingVertex2_[inter]; } else { outgoingVertex1 = outgoingVertex2_[inter]; outgoingVertex2 = outgoingVertex1_[inter]; } } } if (! ((incomingVertex_[inter] && (outgoingVertex1 || outgoingVertex2)) || ( outgoingVertex1 && outgoingVertex2))) throw Exception() << "Invalid vertices for QCD radiation in SVV decay in SVVDecayer::identifyVertices" << Exception::runerror; } else { if(decay[0]->dataPtr()->charged()) { if (outgoingVertex1_[inter] && outgoingVertex1_[inter]->isIncoming(const_ptr_cast(decay[0]->dataPtr()))) outgoingVertex1 = outgoingVertex1_[inter]; else outgoingVertex1 = outgoingVertex2_[inter]; } if(decay[1]->dataPtr()->charged()) { if (outgoingVertex1_[inter] && outgoingVertex1_[inter]->isIncoming(const_ptr_cast(decay[1]->dataPtr()))) outgoingVertex2 = outgoingVertex1_[inter]; else outgoingVertex2 = outgoingVertex2_[inter]; } } } diff --git a/Decay/General/SVVDecayer.h b/Decay/General/SVVDecayer.h --- a/Decay/General/SVVDecayer.h +++ b/Decay/General/SVVDecayer.h @@ -1,222 +1,230 @@ // -*- C++ -*- // // SVVDecayer.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_SVVDecayer_H #define HERWIG_SVVDecayer_H // // This is the declaration of the SVVDecayer class. // #include "GeneralTwoBodyDecayer.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Helicity/Vertex/Scalar/VVSVertex.h" #include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" namespace Herwig { using namespace ThePEG; using Helicity::VVSVertexPtr; /** \ingroup Decay * This SVVDecayer class implements the decay of a scalar to * 2 vector bosons using either the tree level VVSVertex or the loop vertex. * It inherits from * GeneralTwoBodyDecayer and implements the virtual member functions me2() * and partialWidth(). It also stores a pointer to the VVSVertex. * * @see GeneralTwoBodyDecayer * */ class SVVDecayer: public GeneralTwoBodyDecayer { public: /** * The default constructor. */ SVVDecayer() {} /** @name Virtual functions required by the Decayer class. */ //@{ /** * Return the matrix element squared for a given mode and phase-space channel. * @param ichan The channel we are calculating the matrix element for. * @param part The decaying Particle. * @param decay The particles produced in the decay. * @param meopt Option for the calculation of the matrix element * @return The matrix element squared for the phase-space configuration. */ virtual double me2(const int ichan, const Particle & part, const ParticleVector & decay, MEOption meopt) const; /** * Function to return partial Width * @param inpart The decaying particle. * @param outa One of the decay products. * @param outb The other decay product. */ virtual Energy partialWidth(PMPair inpart, PMPair outa, PMPair outb) const; /** * Set the information on the decay */ - virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, VertexBasePtr, + virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, + vector, map &, const vector > &, map); /** * Has a POWHEG style correction */ virtual POWHEGType hasPOWHEGCorrection() { - return (vertex_->orderInGem()+vertex_->orderInGs())==1 ? FSR : No; + POWHEGType output = FSR; + for(auto vertex : vertex_) { + if(vertex->orderInAllCouplings()!=1) { + output = No; + break; + } + } + return output; } /** * Three-body matrix element including additional QCD radiation */ virtual double threeBodyME(const int , const Particle & inpart, const ParticleVector & decay, ShowerInteraction inter, MEOption meopt); //@} 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: /** * Find the vertices for the decay */ void identifyVertices(const Particle & inpart, const ParticleVector & decay, AbstractVVVVertexPtr & outgoingVertex1, AbstractVVVVertexPtr & outgoingVertex2, ShowerInteraction inter); private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ SVVDecayer & operator=(const SVVDecayer &); private: /** * Abstract pointer to general VVS vertex */ - AbstractVVSVertexPtr vertex_; + vector vertex_; /** * Pointer to the perturbative form */ - VVSVertexPtr perturbativeVertex_; + vector perturbativeVertex_; /** * Abstract pointer to AbstractVSSVertex for QCD radiation from incoming scalar */ map incomingVertex_; /** * Abstract pointer to AbstractFFVVertex for QCD radiation from the 1st outgoing vector */ map outgoingVertex1_; /** * Abstract pointer to AbstractFFVVertex for QCD radiation from the 2nd outgoing vector */ map outgoingVertex2_; /** * Spin density matrix */ mutable RhoDMatrix rho_; /** * Scalar wavefunction */ mutable Helicity::ScalarWaveFunction swave_; /** * Vector wavefunctions */ mutable vector vectors_[2]; private: /** * Member for the POWHEG correction */ //@{ /** * Spin density matrix for 3 body decay */ mutable RhoDMatrix rho3_; /** * Scalar wavefunction for 3 body decay */ mutable ScalarWaveFunction swave3_; /** * Vector wavefunctions */ mutable vector vectors3_[2]; /** * Vector wavefunction for 3 body decay */ mutable vector gluon_; //@} }; } #endif /* HERWIG_SVVDecayer_H */ diff --git a/Decay/General/StoFFVDecayer.cc b/Decay/General/StoFFVDecayer.cc --- a/Decay/General/StoFFVDecayer.cc +++ b/Decay/General/StoFFVDecayer.cc @@ -1,331 +1,387 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the StoFFVDecayer class. // #include "StoFFVDecayer.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/PDT/ThreeBodyAllOnCalculator.h" #include "Herwig/Decay/GeneralDecayMatrixElement.h" #include using namespace Herwig; using namespace ThePEG; using namespace ThePEG::Helicity; IBPtr StoFFVDecayer::clone() const { return new_ptr(*this); } IBPtr StoFFVDecayer::fullclone() const { return new_ptr(*this); } void StoFFVDecayer::persistentOutput(PersistentOStream & os) const { - os << sca_ << fer_ << vec_; + os << sca_ << fer_ << vec_ << RSfer_ << four_; } void StoFFVDecayer::persistentInput(PersistentIStream & is, int) { - is >> sca_ >> fer_ >> vec_; + is >> sca_ >> fer_ >> vec_ >> RSfer_ >> four_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigStoFFVDecayer("Herwig::StoFFVDecayer", "Herwig.so"); void StoFFVDecayer::Init() { static ClassDocumentation documentation ("The StoFFVDecayer class implements the general decay of a scalar to " "a two fermions and a vector."); } WidthCalculatorBasePtr StoFFVDecayer:: threeBodyMEIntegrator(const DecayMode & ) const { vector intype; vector inmass,inwidth; vector inpow,inweights; constructIntegratorChannels(intype,inmass,inwidth,inpow,inweights); return new_ptr(ThreeBodyAllOnCalculator (inweights,intype,inmass,inwidth,inpow,*this,0, outgoing()[0]->mass(),outgoing()[1]->mass(), outgoing()[2]->mass(),relativeError())); } void StoFFVDecayer::doinit() { - GeneralThreeBodyDecayer::doinit(); + GeneralThreeBodyDecayer::doinit(); + if(outgoing().empty()) return; unsigned int ndiags = getProcessInfo().size(); sca_.resize(ndiags); fer_.resize(ndiags); + RSfer_.resize(ndiags); vec_.resize(ndiags); + four_.resize(ndiags); for(unsigned int ix = 0;ix < ndiags; ++ix) { TBDiagram current = getProcessInfo()[ix]; tcPDPtr offshell = current.intermediate; + // four point vertex + if(!offshell) { + four_[ix] = dynamic_ptr_cast(current.vertices.first); + continue; + } if( offshell->CC() ) offshell = offshell->CC(); if(offshell->iSpin() == PDT::Spin0) { AbstractVSSVertexPtr vert1 = dynamic_ptr_cast (current.vertices.first); AbstractFFSVertexPtr vert2 = dynamic_ptr_cast (current.vertices.second); if(!vert1||!vert2) throw Exception() << "Invalid vertices for a scalar diagram in StoFFVDecayer::doinit()" << Exception::runerror; sca_[ix] = make_pair(vert1, vert2); } else if(offshell->iSpin() == PDT::Spin1Half) { AbstractFFSVertexPtr vert1 = dynamic_ptr_cast (current.vertices.first); AbstractFFVVertexPtr vert2 = dynamic_ptr_cast (current.vertices.second); if(!vert1||!vert2) throw Exception() << "Invalid vertices for a fermion diagram in StoFFVDecayer::doinit()" << Exception::runerror; fer_[ix] = make_pair(vert1, vert2); } else if(offshell->iSpin() == PDT::Spin1) { AbstractVVSVertexPtr vert1 = dynamic_ptr_cast (current.vertices.first); AbstractFFVVertexPtr vert2 = dynamic_ptr_cast (current.vertices.second); if(!vert1||!vert2) throw Exception() << "Invalid vertices for a vector diagram in StoFFVDecayer::doinit()" << Exception::runerror; vec_[ix] = make_pair(vert1, vert2); } + else if(offshell->iSpin() == PDT::Spin3Half) { + AbstractRFSVertexPtr vert1 = dynamic_ptr_cast + (current.vertices.first); + AbstractRFVVertexPtr vert2 = dynamic_ptr_cast + (current.vertices.second); + if(!vert1||!vert2) throw Exception() + << "Invalid vertices for a RS fermion diagram in StoFFVDecayer::doinit()" + << Exception::runerror; + RSfer_[ix] = make_pair(vert1, vert2); + } } } double StoFFVDecayer::me2(const int ichan, const Particle & inpart, const ParticleVector & decay, MEOption meopt) const { // particle or CC of particle bool cc = (*getProcessInfo().begin()).incoming != inpart.id(); // special handling or first/last call if(meopt==Initialize) { ScalarWaveFunction:: calculateWaveFunctions(rho_,const_ptr_cast(&inpart), Helicity::incoming); swave_ = ScalarWaveFunction(inpart.momentum(),inpart.dataPtr(), Helicity::incoming); } if(meopt==Terminate) { ScalarWaveFunction:: constructSpinInfo(const_ptr_cast(&inpart), Helicity::incoming,true); for(unsigned int ix=0;ixdataPtr()->iSpin()==PDT::Spin1) { VectorWaveFunction::constructSpinInfo(outVector_,decay[ix], Helicity::outgoing,true,false); } else { SpinorWaveFunction:: constructSpinInfo(outspin_[ix].first,decay[ix],Helicity::outgoing,true); } } } unsigned int ivec(0); bool massless(false); for(unsigned int ix = 0; ix < decay.size();++ix) { if(decay[ix]->dataPtr()->iSpin() == PDT::Spin1) { ivec = ix; massless = decay[ivec]->mass()==ZERO; VectorWaveFunction:: calculateWaveFunctions(outVector_, decay[ix], Helicity::outgoing,massless); } else { SpinorWaveFunction:: calculateWaveFunctions(outspin_[ix].first,decay[ix],Helicity::outgoing); outspin_[ix].second.resize(2); // Need a ubar and a v spinor if(outspin_[ix].first[0].wave().Type() == SpinorType::u) { for(unsigned int iy = 0; iy < 2; ++iy) { outspin_[ix].second[iy] = outspin_[ix].first[iy].bar(); outspin_[ix].first[iy].conjugate(); } } else { for(unsigned int iy = 0; iy < 2; ++iy) { outspin_[ix].second[iy] = outspin_[ix].first[iy].bar(); outspin_[ix].second[iy].conjugate(); } } } } const vector > cfactors(getColourFactors()); const vector > nfactors(getLargeNcColourFactors()); Energy2 scale(sqr(inpart.mass())); const size_t ncf(numberOfFlows()); vector flows(ncf, Complex(0.)), largeflows(ncf, Complex(0.)); // setup the DecayMatrixElement vector mes(ncf,new_ptr(GeneralDecayMatrixElement(PDT::Spin0, ivec == 0 ? PDT::Spin1 : PDT::Spin1Half, ivec == 1 ? PDT::Spin1 : PDT::Spin1Half, ivec == 2 ? PDT::Spin1 : PDT::Spin1Half))); vector mel(ncf,new_ptr(GeneralDecayMatrixElement(PDT::Spin0, ivec == 0 ? PDT::Spin1 : PDT::Spin1Half, ivec == 1 ? PDT::Spin1 : PDT::Spin1Half, ivec == 2 ? PDT::Spin1 : PDT::Spin1Half))); //the channel possiblities static const unsigned int out2[3] = {1,0,0}, out3[3] = {2,2,1}; for(unsigned int s1 = 0; s1 < 2; ++s1) { for(unsigned int s2 = 0; s2 < 2; ++s2) { for(unsigned int v1 = 0; v1 < 3; ++v1) { if(massless&&v1==1) ++v1; flows = vector(ncf, Complex(0.)); largeflows = vector(ncf, Complex(0.)); unsigned int idiag(0); + Complex diag; for(vector::const_iterator dit=getProcessInfo().begin(); dit!=getProcessInfo().end();++dit) { // channels if selecting if( ichan >= 0 && diagramMap()[ichan] != idiag ) { ++idiag; continue; } tcPDPtr offshell = dit->intermediate; - if(cc&&offshell->CC()) offshell=offshell->CC(); - Complex diag; - unsigned int o2(out2[dit->channelType]), o3(out3[dit->channelType]); - double sign = (o3 < o2) ? 1. : -1.; - // intermediate scalar - if(offshell->iSpin() == PDT::Spin0) { - ScalarWaveFunction inters = sca_[idiag].first-> - evaluate(scale, widthOption(), offshell, outVector_[v1], swave_); - unsigned int h1(s1),h2(s2); - if(o2 > o3) swap(h1, h2); - if(decay[o2]->id() < 0 && decay[o3]->id() > 0) { - diag = -sign*sca_[idiag].second-> - evaluate(scale,outspin_[o2].first[h1], - outspin_[o3].second[h2],inters); + if(offshell) { + if(cc&&offshell->CC()) offshell=offshell->CC(); + unsigned int o2(out2[dit->channelType]), o3(out3[dit->channelType]); + double sign = (o3 < o2) ? 1. : -1.; + // intermediate scalar + if(offshell->iSpin() == PDT::Spin0) { + ScalarWaveFunction inters = sca_[idiag].first-> + evaluate(scale, widthOption(), offshell, outVector_[v1], swave_); + unsigned int h1(s1),h2(s2); + if(o2 > o3) swap(h1, h2); + if(decay[o2]->id() < 0 && decay[o3]->id() > 0) { + diag = -sign*sca_[idiag].second-> + evaluate(scale,outspin_[o2].first[h1], + outspin_[o3].second[h2],inters); + } + else { + diag = sign*sca_[idiag].second-> + evaluate(scale, outspin_[o3].first [h2], + outspin_[o2].second[h1],inters); + } + } + // intermediate fermion + else if(offshell->iSpin() == PDT::Spin1Half) { + int iferm = (decay[o2]->dataPtr()->iSpin() == PDT::Spin1Half) + ? o2 : o3; + unsigned int h1(s1),h2(s2); + if(dit->channelType > iferm) swap(h1, h2); + sign = iferm < dit->channelType ? 1. : -1.; + if((decay[dit->channelType]->id() < 0 && decay[iferm]->id() > 0 ) || + (decay[dit->channelType]->id()*offshell->id()>0)) { + SpinorWaveFunction inters = fer_[idiag].first-> + evaluate(scale,widthOption(),offshell, + outspin_[dit->channelType].first[h1], swave_); + diag = -sign*fer_[idiag].second-> + evaluate(scale,inters,outspin_[iferm].second[h2], outVector_[v1]); + } + else { + SpinorBarWaveFunction inters = fer_[idiag].first-> + evaluate(scale,widthOption(),offshell, + outspin_[dit->channelType].second[h1],swave_); + diag = sign*fer_[idiag].second-> + evaluate(scale,outspin_[iferm].first [h2],inters, outVector_[v1]); + } + } + // intermediate vector + else if(offshell->iSpin() == PDT::Spin1) { + VectorWaveFunction interv = vec_[idiag].first-> + evaluate(scale, widthOption(), offshell, outVector_[v1], swave_); + unsigned int h1(s1),h2(s2); + if(o2 > o3) swap(h1,h2); + if(decay[o2]->id() < 0 && decay[o3]->id() > 0) { + diag =-sign*vec_[idiag].second-> + evaluate(scale, outspin_[o2].first[h1], + outspin_[o3].second[h2], interv); + } + else { + diag = sign*vec_[idiag].second-> + evaluate(scale, outspin_[o3].first[h2], + outspin_[o2].second[h1], interv); + } + } + // intermediate RS fermion + else if(offshell->iSpin() == PDT::Spin3Half) { + int iferm = (decay[o2]->dataPtr()->iSpin() == PDT::Spin1Half) + ? o2 : o3; + unsigned int h1(s1),h2(s2); + if(dit->channelType > iferm) swap(h1, h2); + sign = iferm < dit->channelType ? 1. : -1.; + if((decay[dit->channelType]->id() < 0 && decay[iferm]->id() > 0 ) || + (decay[dit->channelType]->id()*offshell->id()>0)) { + RSSpinorWaveFunction inters = RSfer_[idiag].first-> + evaluate(scale,widthOption(),offshell, + outspin_[dit->channelType].first[h1], swave_); + diag = -sign*RSfer_[idiag].second-> + evaluate(scale,inters,outspin_[iferm].second[h2], outVector_[v1]); + } + else { + RSSpinorBarWaveFunction inters = RSfer_[idiag].first-> + evaluate(scale,widthOption(),offshell, + outspin_[dit->channelType].second[h1],swave_); + diag = sign*RSfer_[idiag].second-> + evaluate(scale,outspin_[iferm].first [h2],inters, outVector_[v1]); + } + } + // unknown + else throw Exception() + << "Unknown intermediate in StoFFVDecayer::me2()" + << Exception::runerror; + } + else { + unsigned int o2 = ivec > 0 ? 0 : 1; + unsigned int o3 = ivec < 2 ? 2 : 1; + if(decay[o2]->id() < 0 && decay[o3]->id() > 0) { + diag =-four_[idiag]-> + evaluate(scale, outspin_[o2].first[s1], + outspin_[o3].second[s2], outVector_[v1], swave_); } else { - diag = sign*sca_[idiag].second-> - evaluate(scale, outspin_[o3].first [h2], - outspin_[o2].second[h1],inters); + diag = four_[idiag]-> + evaluate(scale, outspin_[o3].first[s2], + outspin_[o2].second[s1], outVector_[v1], swave_); } } - // intermediate fermion - else if(offshell->iSpin() == PDT::Spin1Half) { - int iferm = (decay[o2]->dataPtr()->iSpin() == PDT::Spin1Half) - ? o2 : o3; - unsigned int h1(s1),h2(s2); - if(dit->channelType > iferm) swap(h1, h2); - sign = iferm < dit->channelType ? 1. : -1.; - if((decay[dit->channelType]->id() < 0 && decay[iferm]->id() > 0 ) || - (decay[dit->channelType]->id()*offshell->id()>0)) { - SpinorWaveFunction inters = fer_[idiag].first-> - evaluate(scale,widthOption(),offshell, - outspin_[dit->channelType].first[h1], swave_); - diag = -sign*fer_[idiag].second-> - evaluate(scale,inters,outspin_[iferm].second[h2], outVector_[v1]); - } - else { - SpinorBarWaveFunction inters = fer_[idiag].first-> - evaluate(scale,widthOption(),offshell, - outspin_[dit->channelType].second[h1],swave_); - diag = sign*fer_[idiag].second-> - evaluate(scale,outspin_[iferm].first [h2],inters, outVector_[v1]); - } - } - // intermediate vector - else if(offshell->iSpin() == PDT::Spin1) { - VectorWaveFunction interv = vec_[idiag].first-> - evaluate(scale, widthOption(), offshell, outVector_[v1], swave_); - unsigned int h1(s1),h2(s2); - if(o2 > o3) swap(h1,h2); - if(decay[o2]->id() < 0 && decay[o3]->id() > 0) { - diag =-sign*vec_[idiag].second-> - evaluate(scale, outspin_[o2].first[h1], - outspin_[o3].second[h2], interv); - } - else { - diag = sign*vec_[idiag].second-> - evaluate(scale, outspin_[o3].first[h2], - outspin_[o2].second[h1], interv); - } - } - // unknown - else throw Exception() - << "Unknown intermediate in StoFFVDecayer::me2()" - << Exception::runerror; - // matrix element for the different colour flows if(ichan < 0) { for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) { flows[dit->colourFlow[iy].first - 1] += dit->colourFlow[iy].second * diag; } for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) { largeflows[dit->largeNcColourFlow[iy].first - 1] += dit->largeNcColourFlow[iy].second * diag; } } else { for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) { if(dit->colourFlow[iy].first - 1 != colourFlow()) continue; flows[dit->colourFlow[iy].first - 1] += dit->colourFlow[iy].second * diag; } for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) { if(dit->colourFlow[iy].first - 1!=colourFlow()) continue; largeflows[dit->largeNcColourFlow[iy].first - 1] += dit->largeNcColourFlow[iy].second * diag; } } ++idiag; } //end of diagrams // now add the flows to the me2 with appropriate colour factors for(unsigned int ix = 0; ix < ncf; ++ix) { if ( ivec == 0 ) { (*mes[ix])(0, v1, s1, s2) = flows[ix]; (*mel[ix])(0, v1, s1, s2) = largeflows[ix]; } else if( ivec == 1 ) { (*mes[ix])(0, s1, v1, s2) = flows[ix]; (*mel[ix])(0, s1, v1, s2) = largeflows[ix]; } else if( ivec == 2 ) { (*mes[ix])(0, s1, s2, v1) = flows[ix]; (*mel[ix])(0, s1, s2, v1) = largeflows[ix]; } } } } } double me2(0.); if(ichan < 0) { vector pflows(ncf,0.); for(unsigned int ix = 0; ix < ncf; ++ix) { for(unsigned int iy = 0; iy < ncf; ++ iy) { double con = cfactors[ix][iy]*(mes[ix]->contract(*mes[iy],rho_)).real(); me2 += con; if(ix == iy) { con = nfactors[ix][iy]*(mel[ix]->contract(*mel[iy],rho_)).real(); pflows[ix] += con; } } } double ptotal(std::accumulate(pflows.begin(),pflows.end(),0.)); ptotal *= UseRandom::rnd(); for(unsigned int ix = 0;ix < pflows.size(); ++ix) { if(ptotal <= pflows[ix]) { colourFlow(ix); ME(mes[ix]); break; } ptotal -= pflows[ix]; } } else { unsigned int iflow = colourFlow(); me2 = nfactors[iflow][iflow]*(mel[iflow]->contract(*mel[iflow],rho_)).real(); } // return the matrix element squared return me2; } diff --git a/Decay/General/StoFFVDecayer.h b/Decay/General/StoFFVDecayer.h --- a/Decay/General/StoFFVDecayer.h +++ b/Decay/General/StoFFVDecayer.h @@ -1,149 +1,162 @@ // -*- C++ -*- #ifndef THEPEG_StoFFVDecayer_H #define THEPEG_StoFFVDecayer_H // // This is the declaration of the StoFFVDecayer class. // #include "GeneralThreeBodyDecayer.h" #include "ThePEG/Helicity/Vertex/AbstractFFSVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVSSVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVVSVertex.h" #include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractRFVVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractRFSVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractFFVSVertex.h" namespace Herwig { using namespace ThePEG; /** * Here is the documentation of the StoFFVDecayer class. * * @see \ref StoFFVDecayerInterfaces "The interfaces" * defined for StoFFVDecayer. */ class StoFFVDecayer: public GeneralThreeBodyDecayer { public: /** * Return the matrix element squared for a given mode and phase-space channel * @param ichan The channel we are calculating the matrix element for. * @param part The decaying Particle. * @param decay The particles produced in the decay. * @param meopt Option for the calculation of the matrix element * @return The matrix element squared for the phase-space configuration. */ virtual double me2(const int ichan, const Particle & part, const ParticleVector & decay, MEOption meopt) const; /** * Method to return an object to calculate the 3 (or higher body) partial width * @param dm The DecayMode * @return A pointer to a WidthCalculatorBase object capable of * calculating the width */ virtual WidthCalculatorBasePtr threeBodyMEIntegrator(const DecayMode & dm) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ StoFFVDecayer & operator=(const StoFFVDecayer &); private: /** * Store the vertices for fermion intrermediate */ vector > fer_; + + /** + * Store the vertices for fermion intrermediate + */ + vector > RSfer_; /** * Store the vertices for scalar intrermediate */ vector > sca_; /** * Store the vertices for vector intrermediate */ vector > vec_; /** + * Store the vertices for 4-point diagrams + */ + vector four_; + + /** * Spin density matrix */ mutable RhoDMatrix rho_; /** * Scalar wavefunction */ mutable ScalarWaveFunction swave_; /** * Vector wavefunction */ mutable vector outVector_; /** * Spinor wavefunctions */ mutable pair,vector > outspin_[3]; }; } #endif /* THEPEG_StoFFVDecayer_H */ diff --git a/Decay/General/StoSFFDecayer.cc b/Decay/General/StoSFFDecayer.cc --- a/Decay/General/StoSFFDecayer.cc +++ b/Decay/General/StoSFFDecayer.cc @@ -1,363 +1,422 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the StoSFFDecayer class. // #include "StoSFFDecayer.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/PDT/ThreeBodyAllOnCalculator.h" #include "Herwig/Decay/GeneralDecayMatrixElement.h" #include using namespace Herwig; using namespace ThePEG; using namespace ThePEG::Helicity; IBPtr StoSFFDecayer::clone() const { return new_ptr(*this); } IBPtr StoSFFDecayer::fullclone() const { return new_ptr(*this); } void StoSFFDecayer::persistentOutput(PersistentOStream & os) const { - os << sca_ << fer_ << vec_ << ten_; + os << sca_ << fer_ << vec_ << ten_ << RSfer_ << four_; } void StoSFFDecayer::persistentInput(PersistentIStream & is, int) { - is >> sca_ >> fer_ >> vec_ >> ten_; + is >> sca_ >> fer_ >> vec_ >> ten_ >> RSfer_ >> four_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigStoSFFDecayer("Herwig::StoSFFDecayer", "Herwig.so"); void StoSFFDecayer::Init() { static ClassDocumentation documentation ("The StoSFFDecayer class implements the general decay of a scalar to " "a scalar and two fermions."); } WidthCalculatorBasePtr StoSFFDecayer:: threeBodyMEIntegrator(const DecayMode & ) const { vector intype; vector inmass,inwidth; vector inpow,inweights; constructIntegratorChannels(intype,inmass,inwidth,inpow,inweights); return new_ptr(ThreeBodyAllOnCalculator (inweights,intype,inmass,inwidth,inpow,*this,0, outgoing()[0]->mass(),outgoing()[1]->mass(),outgoing()[2]->mass(), relativeError())); } void StoSFFDecayer::doinit() { - GeneralThreeBodyDecayer::doinit(); + GeneralThreeBodyDecayer::doinit(); + if(outgoing().empty()) return; unsigned int ndiags = getProcessInfo().size(); sca_.resize(ndiags); fer_.resize(ndiags); + RSfer_.resize(ndiags); vec_.resize(ndiags); ten_.resize(ndiags); + four_.resize(ndiags); for(unsigned int ix = 0;ix < ndiags; ++ix) { TBDiagram current = getProcessInfo()[ix]; tcPDPtr offshell = current.intermediate; + // four point vertex + if(!offshell) { + four_[ix] = dynamic_ptr_cast(current.vertices.first); + continue; + } if( offshell->CC() ) offshell = offshell->CC(); if(offshell->iSpin() == PDT::Spin0) { AbstractSSSVertexPtr vert1 = dynamic_ptr_cast (current.vertices.first); AbstractFFSVertexPtr vert2 = dynamic_ptr_cast (current.vertices.second); if(!vert1||!vert2) throw Exception() << "Invalid vertices for a scalar diagram in StoSFFDecayer::doinit()" << Exception::runerror; sca_[ix] = make_pair(vert1, vert2); } else if(offshell->iSpin() == PDT::Spin1Half) { AbstractFFSVertexPtr vert1 = dynamic_ptr_cast (current.vertices.first); AbstractFFSVertexPtr vert2 = dynamic_ptr_cast (current.vertices.second); if(!vert1||!vert2) throw Exception() << "Invalid vertices for a fermion diagram in StoSFFDecayer::doinit()" << Exception::runerror; fer_[ix] = make_pair(vert1, vert2); } else if(offshell->iSpin() == PDT::Spin1) { AbstractVSSVertexPtr vert1 = dynamic_ptr_cast (current.vertices.first); AbstractFFVVertexPtr vert2 = dynamic_ptr_cast (current.vertices.second); if(!vert1||!vert2) throw Exception() << "Invalid vertices for a vector diagram in StoSFFDecayer::doinit()" << Exception::runerror; vec_[ix] = make_pair(vert1, vert2); } else if(offshell->iSpin() == PDT::Spin2) { AbstractSSTVertexPtr vert1 = dynamic_ptr_cast (current.vertices.first); AbstractFFTVertexPtr vert2 = dynamic_ptr_cast (current.vertices.second); if(!vert1||!vert2) throw Exception() << "Invalid vertices for a tensor diagram in StoSFFDecayer::doinit()" << Exception::runerror; ten_[ix] = make_pair(vert1, vert2); } + else if(offshell->iSpin() == PDT::Spin3Half) { + AbstractRFSVertexPtr vert1 = dynamic_ptr_cast + (current.vertices.first); + AbstractRFSVertexPtr vert2 = dynamic_ptr_cast + (current.vertices.second); + if(!vert1||!vert2) throw Exception() + << "Invalid vertices for a RS fermion diagram in StoSFFDecayer::doinit()" + << Exception::runerror; + RSfer_[ix] = make_pair(vert1, vert2); + } } } double StoSFFDecayer::me2(const int ichan, const Particle & inpart, const ParticleVector & decay, MEOption meopt) const { // particle or CC of particle bool cc = (*getProcessInfo().begin()).incoming != inpart.id(); // special handling or first/last call if(meopt==Initialize) { ScalarWaveFunction:: calculateWaveFunctions(rho_,const_ptr_cast(&inpart), Helicity::incoming); swave_ = ScalarWaveFunction(inpart.momentum(),inpart.dataPtr(), Helicity::incoming); } if(meopt==Terminate) { ScalarWaveFunction:: constructSpinInfo(const_ptr_cast(&inpart), Helicity::incoming,true); for(unsigned int ix=0;ixdataPtr()->iSpin()==PDT::Spin0) { ScalarWaveFunction::constructSpinInfo(decay[ix],Helicity::outgoing,true); } else { SpinorWaveFunction:: constructSpinInfo(outspin_[ix].first,decay[ix],Helicity::outgoing,true); } } return 0.; } // get the wavefunctions for all the particles ScalarWaveFunction outScalar; unsigned int isca(0); for(unsigned int ix=0;ixdataPtr()->iSpin()==PDT::Spin0) { isca = ix; outScalar = ScalarWaveFunction(decay[ix]->momentum(), decay[ix]->dataPtr(),Helicity::outgoing); } else { SpinorWaveFunction:: calculateWaveFunctions(outspin_[ix].first,decay[ix],Helicity::outgoing); outspin_[ix].second.resize(2); if(outspin_[ix].first[0].wave().Type() == SpinorType::u) { for(unsigned int iy = 0; iy < 2; ++iy) { outspin_[ix].second[iy] = outspin_[ix].first[iy].bar(); outspin_[ix].first[iy].conjugate(); } } else { for(unsigned int iy = 0; iy < 2; ++iy) { outspin_[ix].second[iy] = outspin_[ix].first[iy].bar(); outspin_[ix].second[iy].conjugate(); } } } } const vector > cfactors(getColourFactors()); const vector > nfactors(getLargeNcColourFactors()); Energy2 scale(sqr(inpart.mass())); const size_t ncf(numberOfFlows()); vector flows(ncf, Complex(0.)), largeflows(ncf, Complex(0.)); vector mes(ncf,new_ptr(GeneralDecayMatrixElement(PDT::Spin0, isca==0 ? PDT::Spin0 : PDT::Spin1Half, isca==1 ? PDT::Spin0 : PDT::Spin1Half, isca==2 ? PDT::Spin0 : PDT::Spin1Half))); vector mel(ncf,new_ptr(GeneralDecayMatrixElement(PDT::Spin0, isca == 0 ? PDT::Spin0 : PDT::Spin1Half, isca == 1 ? PDT::Spin0 : PDT::Spin1Half, isca == 2 ? PDT::Spin0 : PDT::Spin1Half))); static const unsigned int out2[3]={1,0,0},out3[3]={2,2,1}; for(unsigned int s1 = 0;s1 < 2; ++s1) { for(unsigned int s2 = 0;s2 < 2; ++s2) { flows = vector(ncf, Complex(0.)); largeflows = vector(ncf, Complex(0.)); unsigned int idiag(0); for(vector::const_iterator dit = getProcessInfo().begin(); dit != getProcessInfo().end(); ++dit) { // channels if selecting if( ichan >= 0 && diagramMap()[ichan] != idiag ) { ++idiag; continue; } tcPDPtr offshell = dit->intermediate; - if(cc&&offshell->CC()) offshell=offshell->CC(); Complex diag; - double sign = out3[dit->channelType] < out2[dit->channelType] ? 1. : -1.; - // intermediate scalar - if (offshell->iSpin() == PDT::Spin0) { - ScalarWaveFunction inters = sca_[idiag].first-> - evaluate(scale, widthOption(), offshell, swave_, outScalar); - unsigned int h1(s1),h2(s2); - if(out2[dit->channelType]>out3[dit->channelType]) swap(h1,h2); - if(decay[out2[dit->channelType]]->id()<0&& - decay[out3[dit->channelType]]->id()>0) { - diag =-sign*sca_[idiag].second-> - evaluate(scale, - outspin_[out2[dit->channelType]].first [h1], - outspin_[out3[dit->channelType]].second[h2],inters); + if(offshell) { + if(cc&&offshell->CC()) offshell=offshell->CC(); + double sign = out3[dit->channelType] < out2[dit->channelType] ? 1. : -1.; + // intermediate scalar + if (offshell->iSpin() == PDT::Spin0) { + ScalarWaveFunction inters = sca_[idiag].first-> + evaluate(scale, widthOption(), offshell, swave_, outScalar); + unsigned int h1(s1),h2(s2); + if(out2[dit->channelType]>out3[dit->channelType]) swap(h1,h2); + if(decay[out2[dit->channelType]]->id()<0&& + decay[out3[dit->channelType]]->id()>0) { + diag =-sign*sca_[idiag].second-> + evaluate(scale, + outspin_[out2[dit->channelType]].first [h1], + outspin_[out3[dit->channelType]].second[h2],inters); + } + else { + diag = sign*sca_[idiag].second-> + evaluate(scale, + outspin_[out3[dit->channelType]].first [h2], + outspin_[out2[dit->channelType]].second[h1],inters); + } } - else { - diag = sign*sca_[idiag].second-> - evaluate(scale, - outspin_[out3[dit->channelType]].first [h2], - outspin_[out2[dit->channelType]].second[h1],inters); - } - } - // intermediate fermion - else if(offshell->iSpin() == PDT::Spin1Half) { - int iferm = - decay[out2[dit->channelType]]->dataPtr()->iSpin()==PDT::Spin1Half - ? out2[dit->channelType] : out3[dit->channelType]; - unsigned int h1(s1),h2(s2); - if(dit->channelType>iferm) swap(h1,h2); - sign = ifermchannelType ? 1. : -1.; - - - if((decay[dit->channelType]->id() < 0 &&decay[iferm]->id() > 0 ) || - (decay[dit->channelType]->id()*offshell->id()>0)) { - SpinorWaveFunction inters = fer_[idiag].first-> - evaluate(scale,widthOption(),offshell, - outspin_[dit->channelType].first [h1],swave_); - diag = -sign*fer_[idiag].second-> - evaluate(scale,inters,outspin_[iferm].second[h2],outScalar); - } - else { + // intermediate fermion + else if(offshell->iSpin() == PDT::Spin1Half) { + int iferm = + decay[out2[dit->channelType]]->dataPtr()->iSpin()==PDT::Spin1Half + ? out2[dit->channelType] : out3[dit->channelType]; + unsigned int h1(s1),h2(s2); + if(dit->channelType>iferm) swap(h1,h2); + sign = ifermchannelType ? 1. : -1.; + + + if((decay[dit->channelType]->id() < 0 &&decay[iferm]->id() > 0 ) || + (decay[dit->channelType]->id()*offshell->id()>0)) { + SpinorWaveFunction inters = fer_[idiag].first-> + evaluate(scale,widthOption(),offshell, + outspin_[dit->channelType].first [h1],swave_); + diag = -sign*fer_[idiag].second-> + evaluate(scale,inters,outspin_[iferm].second[h2],outScalar); + } + else { SpinorBarWaveFunction inters = fer_[idiag].first-> evaluate(scale,widthOption(),offshell, outspin_[dit->channelType].second[h1],swave_); diag = sign*fer_[idiag].second-> evaluate(scale,outspin_[iferm].first [h2],inters,outScalar); + } } - } - // intermediate vector - else if(offshell->iSpin() == PDT::Spin1) { - VectorWaveFunction interv = vec_[idiag].first-> - evaluate(scale, widthOption(), offshell, swave_, outScalar); - unsigned int h1(s1),h2(s2); - if(out2[dit->channelType]>out3[dit->channelType]) swap(h1,h2); + // intermediate vector + else if(offshell->iSpin() == PDT::Spin1) { + VectorWaveFunction interv = vec_[idiag].first-> + evaluate(scale, widthOption(), offshell, swave_, outScalar); + unsigned int h1(s1),h2(s2); + if(out2[dit->channelType]>out3[dit->channelType]) swap(h1,h2); if(decay[out2[dit->channelType]]->id()<0&& decay[out3[dit->channelType]]->id()>0) { diag =-sign*vec_[idiag].second-> evaluate(scale, outspin_[out2[dit->channelType]].first [h1], outspin_[out3[dit->channelType]].second[h2],interv); } else { diag = sign*vec_[idiag].second-> evaluate(scale, outspin_[out3[dit->channelType]].first [h2], outspin_[out2[dit->channelType]].second[h1],interv); } + } + // intermediate tensor + else if(offshell->iSpin() == PDT::Spin2) { + TensorWaveFunction intert = ten_[idiag].first-> + evaluate(scale, widthOption(), offshell, swave_, outScalar); + unsigned int h1(s1),h2(s2); + if(out2[dit->channelType]>out3[dit->channelType]) swap(h1,h2); + if(decay[out2[dit->channelType]]->id()<0&& + decay[out3[dit->channelType]]->id()>0) { + diag =-sign*ten_[idiag].second-> + evaluate(scale, + outspin_[out2[dit->channelType]].first [h1], + outspin_[out3[dit->channelType]].second[h2],intert); + } + else { + diag = sign*ten_[idiag].second-> + evaluate(scale, + outspin_[out3[dit->channelType]].first [h2], + outspin_[out2[dit->channelType]].second[h1],intert); + } + } + // intermediate RS fermion + else if(offshell->iSpin() == PDT::Spin3Half) { + int iferm = + decay[out2[dit->channelType]]->dataPtr()->iSpin()==PDT::Spin1Half + ? out2[dit->channelType] : out3[dit->channelType]; + unsigned int h1(s1),h2(s2); + if(dit->channelType>iferm) swap(h1,h2); + sign = ifermchannelType ? 1. : -1.; + if((decay[dit->channelType]->id() < 0 &&decay[iferm]->id() > 0 ) || + (decay[dit->channelType]->id()*offshell->id()>0)) { + RSSpinorWaveFunction inters = RSfer_[idiag].first-> + evaluate(scale,widthOption(),offshell, + outspin_[dit->channelType].first [h1],swave_); + diag = -sign*RSfer_[idiag].second-> + evaluate(scale,inters,outspin_[iferm].second[h2],outScalar); + } + else { + RSSpinorBarWaveFunction inters = RSfer_[idiag].first-> + evaluate(scale,widthOption(),offshell, + outspin_[dit->channelType].second[h1],swave_); + diag = sign*RSfer_[idiag].second-> + evaluate(scale,outspin_[iferm].first [h2],inters,outScalar); + } + } + // unknown + else throw Exception() + << "Unknown intermediate in StoSFFDecayer::me2()" + << Exception::runerror; } - // intermediate tensor - else if(offshell->iSpin() == PDT::Spin2) { - TensorWaveFunction intert = ten_[idiag].first-> - evaluate(scale, widthOption(), offshell, swave_, outScalar); - unsigned int h1(s1),h2(s2); - if(out2[dit->channelType]>out3[dit->channelType]) swap(h1,h2); - if(decay[out2[dit->channelType]]->id()<0&& - decay[out3[dit->channelType]]->id()>0) { - diag =-sign*ten_[idiag].second-> - evaluate(scale, - outspin_[out2[dit->channelType]].first [h1], - outspin_[out3[dit->channelType]].second[h2],intert); - } - else { - diag = sign*ten_[idiag].second-> - evaluate(scale, - outspin_[out3[dit->channelType]].first [h2], - outspin_[out2[dit->channelType]].second[h1],intert); - } + // four point diagram + else { + unsigned int o2 = isca > 0 ? 0 : 1; + unsigned int o3 = isca < 2 ? 2 : 1; + if(decay[o2]->id() < 0 && decay[o3]->id() > 0) { + diag =-four_[idiag]-> + evaluate(scale, outspin_[o2].first[s1], + outspin_[o3].second[s2], outScalar, swave_); + } + else { + diag = four_[idiag]-> + evaluate(scale, outspin_[o3].first[s2], + outspin_[o2].second[s1], outScalar, swave_); + } } - // unknown - else throw Exception() - << "Unknown intermediate in StoSFFDecayer::me2()" - << Exception::runerror; // matrix element for the different colour flows if(ichan < 0) { for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) { flows[dit->colourFlow[iy].first - 1] += dit->colourFlow[iy].second * diag; } for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) { largeflows[dit->largeNcColourFlow[iy].first - 1] += dit->largeNcColourFlow[iy].second * diag; } } else { for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) { if(dit->colourFlow[iy].first - 1 != colourFlow()) continue; flows[dit->colourFlow[iy].first - 1] += dit->colourFlow[iy].second * diag; } for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) { if(dit->colourFlow[iy].first - 1!=colourFlow()) continue; largeflows[dit->largeNcColourFlow[iy].first - 1] += dit->largeNcColourFlow[iy].second * diag; } } ++idiag; } for(unsigned int ix = 0; ix < ncf; ++ix) { if(isca == 0) { (*mes[ix])(0, 0, s1, s2) = flows[ix]; (*mel[ix])(0, 0, s1, s2) = largeflows[ix]; } else if(isca == 1 ) { (*mes[ix])(0, s1, 0, s2) = flows[ix]; (*mel[ix])(0, s1, 0, s2) = largeflows[ix]; } else if(isca == 2) { (*mes[ix])(0, s1,s2, 0) = flows[ix]; (*mel[ix])(0, s1,s2, 0) = largeflows[ix] ; } } } } double me2(0.); if(ichan < 0) { vector pflows(ncf,0.); for(unsigned int ix = 0; ix < ncf; ++ix) { for(unsigned int iy = 0; iy < ncf; ++ iy) { double con = cfactors[ix][iy]*(mes[ix]->contract(*mes[iy],rho_)).real(); me2 += con; if(ix == iy) { con = nfactors[ix][iy]*(mel[ix]->contract(*mel[iy],rho_)).real(); pflows[ix] += con; } } } double ptotal(std::accumulate(pflows.begin(),pflows.end(),0.)); ptotal *= UseRandom::rnd(); for(unsigned int ix = 0;ix < pflows.size(); ++ix) { if(ptotal <= pflows[ix]) { colourFlow(ix); ME(mes[ix]); break; } ptotal -= pflows[ix]; } } else { unsigned int iflow = colourFlow(); me2 = nfactors[iflow][iflow]*(mel[iflow]->contract(*mel[iflow],rho_)).real(); } // return the matrix element squared return me2; } diff --git a/Decay/General/StoSFFDecayer.h b/Decay/General/StoSFFDecayer.h --- a/Decay/General/StoSFFDecayer.h +++ b/Decay/General/StoSFFDecayer.h @@ -1,151 +1,163 @@ // -*- C++ -*- #ifndef THEPEG_StoSFFDecayer_H #define THEPEG_StoSFFDecayer_H // // This is the declaration of the StoSFFDecayer class. // #include "GeneralThreeBodyDecayer.h" #include "ThePEG/Helicity/Vertex/AbstractSSSVertex.h" #include "ThePEG/Helicity/Vertex/AbstractFFSVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractRFSVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVSSVertex.h" #include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h" #include "ThePEG/Helicity/Vertex/AbstractSSTVertex.h" #include "ThePEG/Helicity/Vertex/AbstractFFTVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractFFSSVertex.h" namespace Herwig { using namespace ThePEG; /** * The StoSFFDecayer class provides the general matrix element for * scalar decays into another scalar and a fermion-antifermion pair. * * @see \ref StoSFFDecayerInterfaces "The interfaces" * defined for StoSFFDecayer. */ class StoSFFDecayer: public GeneralThreeBodyDecayer { public: /** * Return the matrix element squared for a given mode and phase-space channel * @param ichan The channel we are calculating the matrix element for. * @param part The decaying Particle. * @param decay The particles produced in the decay. * @param meopt Option for the calculation of the matrix element * @return The matrix element squared for the phase-space configuration. */ virtual double me2(const int ichan, const Particle & part, const ParticleVector & decay, MEOption meopt) const; /** * Method to return an object to calculate the 3 (or higher body) partial width * @param dm The DecayMode * @return A pointer to a WidthCalculatorBase object capable of calculating the width */ virtual WidthCalculatorBasePtr threeBodyMEIntegrator(const DecayMode & dm) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ StoSFFDecayer & operator=(const StoSFFDecayer &); private: /** - * Store the vertices for scalar intrermediate + * Store the vertices for scalar intermediate */ vector > sca_; /** - * Store the vertices for fermion intrermediate + * Store the vertices for spin-\f$\frac12\f$ fermion intermediate */ vector > fer_; /** - * Store the vertices for vector intrermediate + * Store the vertices for spin-\f$\frac32\f$ fermion intermediate + */ + vector > RSfer_; + + /** + * Store the vertices for vector intermediate */ vector > vec_; /** - * Store the vertices for tensor intrermediate + * Store the vertices for tensor intermediate */ vector > ten_; /** + * Store the vertices for four point diagrams + */ + vector four_; + + /** * Spin density matrix */ mutable RhoDMatrix rho_; /** * Scalar wavefunction */ mutable ScalarWaveFunction swave_; /** * Spinor wavefunctions */ mutable pair,vector > outspin_[3]; }; } #endif /* THEPEG_StoSFFDecayer_H */ diff --git a/Decay/General/TFFDecayer.cc b/Decay/General/TFFDecayer.cc --- a/Decay/General/TFFDecayer.cc +++ b/Decay/General/TFFDecayer.cc @@ -1,340 +1,351 @@ // -*- C++ -*- // // TFFDecayer.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 TFFDecayer class. // #include "TFFDecayer.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/Helicity/WaveFunction/TensorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" #include "Herwig/Utilities/Kinematics.h" #include "Herwig/Decay/GeneralDecayMatrixElement.h" using namespace Herwig; using namespace ThePEG::Helicity; IBPtr TFFDecayer::clone() const { return new_ptr(*this); } IBPtr TFFDecayer::fullclone() const { return new_ptr(*this); } void TFFDecayer::setDecayInfo(PDPtr incoming, PDPair outgoing, - VertexBasePtr vertex, + vector vertex, map &, const vector > & outV, map fourV) { decayInfo(incoming,outgoing); - vertex_ = dynamic_ptr_cast(vertex); - perturbativeVertex_ = dynamic_ptr_cast (vertex); + for(auto vert : vertex) { + vertex_ .push_back(dynamic_ptr_cast(vert)); + perturbativeVertex_.push_back(dynamic_ptr_cast (vert)); + } vector itemp={ShowerInteraction::QCD,ShowerInteraction::QED}; for(auto & inter : itemp) { fourPointVertex_[inter] = dynamic_ptr_cast(fourV.at(inter)); outgoingVertex1_[inter] = dynamic_ptr_cast (outV[0].at(inter)); outgoingVertex2_[inter] = dynamic_ptr_cast (outV[1].at(inter)); } } void TFFDecayer::persistentOutput(PersistentOStream & os) const { os << vertex_ << perturbativeVertex_ << outgoingVertex1_ << outgoingVertex2_ << fourPointVertex_; } void TFFDecayer::persistentInput(PersistentIStream & is, int) { is >> vertex_ >> perturbativeVertex_ >> outgoingVertex1_ >> outgoingVertex2_ >> fourPointVertex_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigTFFDecayer("Herwig::TFFDecayer", "Herwig.so"); void TFFDecayer::Init() { static ClassDocumentation documentation ("The TFFDecayer class implements the decay of a tensor particle " "to 2 fermions "); } double TFFDecayer::me2(const int , const Particle & inpart, const ParticleVector & decay, MEOption meopt) const { unsigned int iferm(0),ianti(1); if(!ME()) ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin2,PDT::Spin1Half,PDT::Spin1Half))); if(decay[0]->id()>=0) swap(iferm,ianti); if(meopt==Initialize) { TensorWaveFunction:: calculateWaveFunctions(tensors_,rho_,const_ptr_cast(&inpart), incoming,false); } if(meopt==Terminate) { TensorWaveFunction:: constructSpinInfo(tensors_,const_ptr_cast(&inpart), incoming,true,false); SpinorBarWaveFunction:: constructSpinInfo(wavebar_,decay[iferm],outgoing,true); SpinorWaveFunction:: constructSpinInfo(wave_ ,decay[ianti],outgoing,true); return 0.; } SpinorBarWaveFunction:: calculateWaveFunctions(wavebar_,decay[iferm],outgoing); SpinorWaveFunction:: calculateWaveFunctions(wave_ ,decay[ianti],outgoing); Energy2 scale(sqr(inpart.mass())); unsigned int thel,fhel,ahel; for(thel=0;thel<5;++thel) { for(fhel=0;fhel<2;++fhel) { for(ahel=0;ahel<2;++ahel) { if(iferm > ianti) { - (*ME())(thel,fhel,ahel) = - vertex_->evaluate(scale,wave_[ahel], - wavebar_[fhel],tensors_[thel]); + (*ME())(thel,fhel,ahel) = 0.; + for(auto vert : vertex_) + (*ME())(thel,fhel,ahel) += + vert->evaluate(scale,wave_[ahel], + wavebar_[fhel],tensors_[thel]); } else { - (*ME())(thel,ahel,fhel) = - vertex_->evaluate(scale,wave_[ahel], - wavebar_[fhel],tensors_[thel]); + (*ME())(thel,ahel,fhel) = 0.; + for(auto vert : vertex_) + (*ME())(thel,ahel,fhel) += + vert->evaluate(scale,wave_[ahel], + wavebar_[fhel],tensors_[thel]); } } } } double output = (ME()->contract(rho_)).real()/scale*UnitRemoval::E2; // colour and identical particle factors output *= colourFactor(inpart.dataPtr(),decay[0]->dataPtr(), decay[1]->dataPtr()); // return the answer return output; } Energy TFFDecayer::partialWidth(PMPair inpart, PMPair outa, PMPair outb) const { if( inpart.second < outa.second + outb.second ) return ZERO; - if(perturbativeVertex_) { + if(perturbativeVertex_.size()==1 && + perturbativeVertex_[0]) { Energy2 scale = sqr(inpart.second); tcPDPtr in = inpart.first->CC() ? tcPDPtr(inpart.first->CC()) : inpart.first; - perturbativeVertex_->setCoupling(scale, in, outa.first, outb.first); + perturbativeVertex_[0]->setCoupling(scale, in, outa.first, outb.first); double musq = sqr(outa.second/inpart.second); double b = sqrt(1- 4.*musq); double me2 = b*b*(5-2*b*b)*scale/120.*UnitRemoval::InvE2; Energy pcm = Kinematics::pstarTwoBodyDecay(inpart.second,outa.second, outb.second); - Energy output = norm(perturbativeVertex_->norm())*me2*pcm/(8.*Constants::pi); + Energy output = norm(perturbativeVertex_[0]->norm())*me2*pcm/(8.*Constants::pi); // colour factor output *= colourFactor(inpart.first,outa.first,outb.first); // return the answer return output; } else { return GeneralTwoBodyDecayer::partialWidth(inpart,outa,outb); } } double TFFDecayer::threeBodyME(const int , const Particle & inpart, const ParticleVector & decay, ShowerInteraction inter, MEOption meopt) { // work out which is the fermion and antifermion int ianti(0), iferm(1), iglu(2); int itype[2]; for(unsigned int ix=0;ix<2;++ix) { if(decay[ix]->dataPtr()->CC()) itype[ix] = decay[ix]->id()>0 ? 0:1; else itype[ix] = 2; } if(itype[0]==0 && itype[1]!=0) swap(iferm, ianti); if(itype[0]==2 && itype[1]==1) swap(iferm, ianti); if(itype[0]==0 && itype[1]==0 && decay[0]->dataPtr()->id()dataPtr()->id()) swap(iferm, ianti); if(itype[0]==1 && itype[1]==1 && decay[0]->dataPtr()->id()dataPtr()->id()) swap(iferm, ianti); if(meopt==Initialize) { // create tensor wavefunction for decaying particle TensorWaveFunction:: calculateWaveFunctions(tensors3_, rho3_, const_ptr_cast(&inpart), incoming, false); } // setup spin information when needed if(meopt==Terminate) { TensorWaveFunction:: constructSpinInfo(tensors3_, const_ptr_cast(&inpart),incoming,true, false); SpinorBarWaveFunction:: constructSpinInfo(wavebar3_ ,decay[iferm],outgoing,true); SpinorWaveFunction:: constructSpinInfo(wave3_ ,decay[ianti],outgoing,true); VectorWaveFunction:: constructSpinInfo(gluon_ ,decay[iglu ],outgoing,true,false); return 0.; } // calculate colour factors and number of colour flows unsigned int nflow; vector cfactors = getColourFactors(inpart, decay, nflow); vector ME(nflow,new_ptr(GeneralDecayMatrixElement(PDT::Spin2, PDT::Spin1Half, PDT::Spin1Half, PDT::Spin1))); // create wavefunctions SpinorBarWaveFunction:: calculateWaveFunctions(wavebar3_, decay[iferm],outgoing); SpinorWaveFunction:: calculateWaveFunctions(wave3_ , decay[ianti],outgoing); VectorWaveFunction:: calculateWaveFunctions(gluon_ , decay[iglu ],outgoing,true); // gauge invariance test #ifdef GAUGE_CHECK gluon_.clear(); for(unsigned int ix=0;ix<3;++ix) { if(ix==1) gluon_.push_back(VectorWaveFunction()); else { gluon_.push_back(VectorWaveFunction(decay[iglu ]->momentum(), decay[iglu ]->dataPtr(),10, outgoing)); } } #endif if (! (outgoingVertex1_[inter] && outgoingVertex2_[inter])) throw Exception() << "Invalid vertices for QCD radiation in TFF decay in TFFDecayer::threeBodyME" << Exception::runerror; // identify fermion and/or anti-fermion vertex AbstractFFVVertexPtr outgoingVertexF = outgoingVertex1_[inter]; AbstractFFVVertexPtr outgoingVertexA = outgoingVertex2_[inter]; if(outgoingVertex1_[inter]!=outgoingVertex2_[inter] && outgoingVertex1_[inter]->isIncoming(getParticleData(decay[ianti]->id()))) swap (outgoingVertexF, outgoingVertexA); if(! (inpart.dataPtr()->iColour()==PDT::Colour0)){ throw Exception() << "Invalid vertices for QCD radiation in TFF decay in TFFDecayer::threeBodyME" << Exception::runerror; } Energy2 scale(sqr(inpart.mass())); const GeneralTwoBodyDecayer::CFlow & colourFlow = colourFlows(inpart, decay); double gs(0.); bool couplingSet(false); #ifdef GAUGE_CHECK double total=0.; #endif for(unsigned int it = 0; it < 5; ++it) { for(unsigned int ifm = 0; ifm < 2; ++ifm) { for(unsigned int ia = 0; ia < 2; ++ia) { for(unsigned int ig = 0; ig < 2; ++ig) { // radiation from outgoing fermion if((decay[iferm]->dataPtr()->coloured() && inter==ShowerInteraction::QCD) || (decay[iferm]->dataPtr()->charged() && inter==ShowerInteraction::QED) ) { assert(outgoingVertexF); // ensure you get correct outgoing particle from first vertex tcPDPtr off = decay[iferm]->dataPtr(); if(off->CC()) off = off->CC(); SpinorBarWaveFunction interS = outgoingVertexF->evaluate(scale,3,off,wavebar3_[ifm], gluon_[2*ig],decay[iferm]->mass()); assert(wavebar3_[ifm].particle()->id()==interS.particle()->id()); - Complex diag = vertex_->evaluate(scale,wave3_[ia], interS,tensors3_[it]); + Complex diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,wave3_[ia], interS,tensors3_[it]); if(!couplingSet) { gs = abs(outgoingVertexF->norm()); couplingSet = true; } for(unsigned int ix=0;ixdataPtr()->coloured() && inter==ShowerInteraction::QCD) || (decay[ianti]->dataPtr()->charged() && inter==ShowerInteraction::QED) ) { assert(outgoingVertexA); // ensure you get correct outgoing particle from first vertex tcPDPtr off = decay[ianti]->dataPtr(); if(off->CC()) off = off->CC(); SpinorWaveFunction interS = outgoingVertexA->evaluate(scale,3,off,wave3_[ia], gluon_[2*ig],decay[ianti]->mass()); assert(wave3_[ia].particle()->id()==interS.particle()->id()); - Complex diag = vertex_->evaluate(scale,interS,wavebar3_[ifm],tensors3_[it]); + Complex diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,interS,wavebar3_[ifm],tensors3_[it]); if(!couplingSet) { gs = abs(outgoingVertexA->norm()); couplingSet = true; } for(unsigned int ix=0;ixevaluate(scale, wave3_[ia], wavebar3_[ifm], gluon_[2*ig], tensors3_[it]); for(unsigned int ix=0;ixcontract(*ME[iy],rho3_)).real(); } } // divide by alpha_(s,em) output *= (4.*Constants::pi)/sqr(gs); #ifdef GAUGE_CHECK double ratio = output/total; if(abs(ratio)>1e-20) { generator()->log() << "Test of gauge invariance in decay\n" << inpart << "\n"; for(unsigned int ix=0;ixlog() << *decay[ix] << "\n"; generator()->log() << "Test of gauge invariance " << ratio << "\n"; } #endif // return the answer return output; } diff --git a/Decay/General/TFFDecayer.h b/Decay/General/TFFDecayer.h --- a/Decay/General/TFFDecayer.h +++ b/Decay/General/TFFDecayer.h @@ -1,215 +1,223 @@ // -*- C++ -*- // // TFFDecayer.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_TFFDecayer_H #define HERWIG_TFFDecayer_H // // This is the declaration of the TFFDecayer class. // #include "GeneralTwoBodyDecayer.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Helicity/Vertex/Tensor/FFTVertex.h" #include "ThePEG/Helicity/Vertex/Vector/FFVVertex.h" #include "ThePEG/Helicity/Vertex/Tensor/FFVTVertex.h" namespace Herwig { using namespace ThePEG; using Helicity::FFTVertexPtr; /** \ingroup Decay * The TFFDecayer class implements the decay of a tensor * to 2 fermions in a general model. It holds an FFTVertex pointer * that must be typecast from the VertexBase pointer held in * GeneralTwoBodyDecayer. It implents the virtual functions me2() and * partialWidth(). * * @see GeneralTwoBodyDecayer */ class TFFDecayer: public GeneralTwoBodyDecayer { public: /** * The default constructor. */ TFFDecayer() {} /** @name Virtual functions required by the Decayer class. */ //@{ /** * Return the matrix element squared for a given mode and phase-space channel. * @param ichan The channel we are calculating the matrix element for. * @param part The decaying Particle. * @param decay The particles produced in the decay. * @param meopt Option for the matrix element * @return The matrix element squared for the phase-space configuration. */ virtual double me2(const int ichan, const Particle & part, const ParticleVector & decay, MEOption meopt) const; /** * Function to return partial Width * @param inpart The decaying particle. * @param outa One of the decay products. * @param outb The other decay product. */ virtual Energy partialWidth(PMPair inpart, PMPair outa, PMPair outb) const; /** * Has a POWHEG style correction */ virtual POWHEGType hasPOWHEGCorrection() { - return (vertex_->orderInGem()+vertex_->orderInGs())==1 ? FSR : No; + POWHEGType output = FSR; + for(auto vertex : vertex_) { + if(vertex->orderInAllCouplings()!=1) { + output = No; + break; + } + } + return output; } /** * Three-body matrix element including additional QCD radiation */ virtual double threeBodyME(const int , const Particle & inpart, const ParticleVector & decay, ShowerInteraction inter, MEOption meopt); /** * Set the information on the decay */ - virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, VertexBasePtr, + virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, + vector, map &, const vector > &, map); //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ TFFDecayer & operator=(const TFFDecayer &); private: /** * Abstract pointer to AbstractFFTVertex */ - AbstractFFTVertexPtr vertex_; + vector vertex_; /** * Pointer to the perturbative vertex */ - FFTVertexPtr perturbativeVertex_; + vector perturbativeVertex_; /** * Abstract pointer to AbstractFFVVertex for QCD radiation from outgoing (anti)fermion */ map outgoingVertex1_; /** * Abstract pointer to AbstractFFVVertex for QCD radiation from outgoing (anti)fermion */ map outgoingVertex2_; /** * Abstract pointer to AbstractFFVTVertex for QCD radiation from 4 point vertex */ map fourPointVertex_; /** * Spin density matrix */ mutable RhoDMatrix rho_; /** * Polarization tensors for the decaying particle */ mutable vector tensors_; /** * Spinors for the decay products */ mutable vector wave_; /** * Barred spinors for the decay products */ mutable vector wavebar_; /** * Spin density matrix for 3 body decay */ mutable RhoDMatrix rho3_; /** * Tensor wavefunction for 3 body decay */ mutable vector tensors3_; /** * Spinor wavefunction for 3 body decay */ mutable vector wave3_; /** * Barred spinor wavefunction for 3 body decay */ mutable vector wavebar3_; /** * Vector wavefunction for 3 body decay */ mutable vector gluon_; }; } #endif /* HERWIG_TFFDecayer_H */ diff --git a/Decay/General/TSSDecayer.cc b/Decay/General/TSSDecayer.cc --- a/Decay/General/TSSDecayer.cc +++ b/Decay/General/TSSDecayer.cc @@ -1,125 +1,130 @@ // -*- C++ -*- // // TSSDecayer.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 TSSDecayer class. // #include "TSSDecayer.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.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/TensorWaveFunction.h" #include "Herwig/Decay/GeneralDecayMatrixElement.h" using namespace Herwig; using namespace ThePEG::Helicity; IBPtr TSSDecayer::clone() const { return new_ptr(*this); } IBPtr TSSDecayer::fullclone() const { return new_ptr(*this); } void TSSDecayer::setDecayInfo(PDPtr incoming, PDPair outgoing, - VertexBasePtr vertex, + vector vertex, map & , const vector > & , map ) { decayInfo(incoming,outgoing); - vertex_ = dynamic_ptr_cast(vertex); - perturbativeVertex_ = dynamic_ptr_cast (vertex); + for(auto vert : vertex) { + vertex_ .push_back(dynamic_ptr_cast(vert)); + perturbativeVertex_.push_back(dynamic_ptr_cast (vert)); + } } void TSSDecayer::persistentOutput(PersistentOStream & os) const { os << vertex_ << perturbativeVertex_; } void TSSDecayer::persistentInput(PersistentIStream & is, int) { is >> vertex_ >> perturbativeVertex_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigTSSDecayer("Herwig::TSSDecayer", "Herwig.so"); void TSSDecayer::Init() { static ClassDocumentation documentation ("This class implements the decay of a tensor particle into " "2 scalars."); } double TSSDecayer::me2(const int , const Particle & inpart, const ParticleVector & decay, MEOption meopt) const { if(!ME()) ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin2,PDT::Spin0,PDT::Spin0))); if(meopt==Initialize) { TensorWaveFunction:: calculateWaveFunctions(tensors_,rho_,const_ptr_cast(&inpart), incoming,false); } if(meopt==Terminate) { TensorWaveFunction:: constructSpinInfo(tensors_,const_ptr_cast(&inpart), incoming,true,false); for(unsigned int ix=0;ix<2;++ix) ScalarWaveFunction:: constructSpinInfo(decay[ix],outgoing,true); return 0.; } ScalarWaveFunction sca1(decay[0]->momentum(),decay[0]->dataPtr(),outgoing); ScalarWaveFunction sca2(decay[1]->momentum(),decay[1]->dataPtr(),outgoing); Energy2 scale(sqr(inpart.mass())); for(unsigned int thel=0;thel<5;++thel) { - (*ME())(thel,0,0) = vertex_->evaluate(scale,sca1,sca2,tensors_[thel]); + (*ME())(thel,0,0) =0.; + for(auto vert : vertex_) + (*ME())(thel,0,0) += vert->evaluate(scale,sca1,sca2,tensors_[thel]); } double output = (ME()->contract(rho_)).real()/scale*UnitRemoval::E2; // colour and identical particle factors output *= colourFactor(inpart.dataPtr(),decay[0]->dataPtr(), decay[1]->dataPtr()); // return the answer return output; } Energy TSSDecayer::partialWidth(PMPair inpart, PMPair outa, PMPair outb) const { if( inpart.second < outa.second + outb.second ) return ZERO; - if(perturbativeVertex_) { + if(perturbativeVertex_.size()==1 && + perturbativeVertex_[0]) { Energy2 scale(sqr(inpart.second)); tcPDPtr in = inpart.first->CC() ? tcPDPtr(inpart.first->CC()) : inpart.first; - perturbativeVertex_->setCoupling(scale, outa.first, outb.first, in); + perturbativeVertex_[0]->setCoupling(scale, outa.first, outb.first, in); double musq = sqr(outa.second/inpart.second); double b = sqrt(1. - 4.*musq); double me2 = scale*pow(b,4)/120*UnitRemoval::InvE2; Energy pcm = Kinematics::pstarTwoBodyDecay(inpart.second,outa.second, outb.second); - Energy output = norm(perturbativeVertex_->norm())*me2*pcm/(8.*Constants::pi); + Energy output = norm(perturbativeVertex_[0]->norm())*me2*pcm/(8.*Constants::pi); // colour factor output *= colourFactor(inpart.first,outa.first,outb.first); // return the answer return output; } else { return GeneralTwoBodyDecayer::partialWidth(inpart,outa,outb); } } diff --git a/Decay/General/TSSDecayer.h b/Decay/General/TSSDecayer.h --- a/Decay/General/TSSDecayer.h +++ b/Decay/General/TSSDecayer.h @@ -1,150 +1,151 @@ // -*- C++ -*- // // TSSDecayer.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_TSSDecayer_H #define HERWIG_TSSDecayer_H // // This is the declaration of the TSSDecayer class. // #include "GeneralTwoBodyDecayer.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Helicity/Vertex/Tensor/SSTVertex.h" namespace Herwig { using namespace ThePEG; using Helicity::SSTVertexPtr; /** \ingroup Decay * The TSSDecayer class implements the decay of a tensor * to 2 scalars in a general model. It holds an SSTVertex pointer * that must be typecast from the VertexBase pointer held in * GeneralTwoBodyDecayer. It implents the virtual functions me2() and * partialWidth(). * * @see GeneralTwoBodyDecayer */ class TSSDecayer: public GeneralTwoBodyDecayer { public: /** * The default constructor. */ TSSDecayer() {} public: /** @name Virtual functions required by the Decayer class. */ //@{ /** * Return the matrix element squared for a given mode and phase-space channel. * @param ichan The channel we are calculating the matrix element for. * @param part The decaying Particle. * @param decay The particles produced in the decay. * @param meopt Option for the matrix element * @return The matrix element squared for the phase-space configuration. */ virtual double me2(const int ichan, const Particle & part, const ParticleVector & decay, MEOption meopt) const; /** * Function to return partial Width * @param inpart The decaying particle. * @param outa One of the decay products. * @param outb The other decay product. */ virtual Energy partialWidth(PMPair inpart, PMPair outa, PMPair outb) const; /** * Set the information on the decay */ - virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, VertexBasePtr, + virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, + vector, map &, const vector > &, map); //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ TSSDecayer & operator=(const TSSDecayer &); private: /** * Abstract pointer to AbstractSSTVertex */ - AbstractSSTVertexPtr vertex_; + vector vertex_; /** * Pointer to the perturbative vertex */ - SSTVertexPtr perturbativeVertex_; + vector perturbativeVertex_; /** * Spin density matrix */ mutable RhoDMatrix rho_; /** * Polarization tensors of the decaying particle */ mutable vector tensors_; }; } #endif /* HERWIG_TSSDecayer_H */ diff --git a/Decay/General/TVVDecayer.cc b/Decay/General/TVVDecayer.cc --- a/Decay/General/TVVDecayer.cc +++ b/Decay/General/TVVDecayer.cc @@ -1,329 +1,338 @@ // -*- C++ -*- // // TVVDecayer.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 TVVDecayer class. // #include "TVVDecayer.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/TensorWaveFunction.h" #include "Herwig/Utilities/Kinematics.h" #include "ThePEG/Helicity/LorentzTensor.h" #include "Herwig/Decay/GeneralDecayMatrixElement.h" using namespace Herwig; using namespace ThePEG::Helicity; IBPtr TVVDecayer::clone() const { return new_ptr(*this); } IBPtr TVVDecayer::fullclone() const { return new_ptr(*this); } void TVVDecayer::setDecayInfo(PDPtr incoming, PDPair outgoing, - VertexBasePtr vertex, + vector vertex, map &, const vector > & outV, map fourV) { decayInfo(incoming,outgoing); - vertex_ = dynamic_ptr_cast(vertex); - perturbativeVertex_ = dynamic_ptr_cast (vertex); + for(auto vert : vertex) { + vertex_ .push_back(dynamic_ptr_cast(vert)); + perturbativeVertex_.push_back(dynamic_ptr_cast (vert)); + } vector itemp={ShowerInteraction::QCD,ShowerInteraction::QED}; for(auto & inter : itemp) { fourPointVertex_[inter] = dynamic_ptr_cast(fourV.at(inter)); outgoingVertex1_[inter] = dynamic_ptr_cast (outV[0].at(inter)); outgoingVertex2_[inter] = dynamic_ptr_cast (outV[1].at(inter)); } } void TVVDecayer::persistentOutput(PersistentOStream & os) const { os << vertex_ << perturbativeVertex_ << outgoingVertex1_ << outgoingVertex2_ << fourPointVertex_; } void TVVDecayer::persistentInput(PersistentIStream & is, int) { is >> vertex_ >> perturbativeVertex_ >> outgoingVertex1_ >> outgoingVertex2_ >> fourPointVertex_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigTVVDecayer("Herwig::TVVDecayer", "Herwig.so"); void TVVDecayer::Init() { static ClassDocumentation documentation ("This class implements the decay of a tensor to 2 vector bosons"); } double TVVDecayer::me2(const int , const Particle & inpart, const ParticleVector & decay, MEOption meopt) const { if(!ME()) ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin2,PDT::Spin1,PDT::Spin1))); bool photon[2]; for(unsigned int ix=0;ix<2;++ix) photon[ix] = decay[ix]->mass()==ZERO; if(meopt==Initialize) { TensorWaveFunction:: calculateWaveFunctions(tensors_,rho_,const_ptr_cast(&inpart), incoming,false); } if(meopt==Terminate) { TensorWaveFunction:: constructSpinInfo(tensors_,const_ptr_cast(&inpart), incoming,true,false); for(unsigned int ix=0;ix<2;++ix) VectorWaveFunction:: constructSpinInfo(vectors_[ix],decay[ix],outgoing,true,photon[ix]); return 0.; } for(unsigned int ix=0;ix<2;++ix) VectorWaveFunction:: calculateWaveFunctions(vectors_[ix],decay[ix],outgoing,photon[ix]); Energy2 scale(sqr(inpart.mass())); unsigned int thel,v1hel,v2hel; for(thel=0;thel<5;++thel) { for(v1hel=0;v1hel<3;++v1hel) { for(v2hel=0;v2hel<3;++v2hel) { - (*ME())(thel,v1hel,v2hel) = vertex_->evaluate(scale, - vectors_[0][v1hel], - vectors_[1][v2hel], - tensors_[thel]); + (*ME())(thel,v1hel,v2hel) = 0.; + for(auto vert : vertex_) + (*ME())(thel,v1hel,v2hel) += vert->evaluate(scale, + vectors_[0][v1hel], + vectors_[1][v2hel], + tensors_[thel]); if(photon[1]) ++v2hel; } if(photon[0]) ++v1hel; } } double output = (ME()->contract(rho_)).real()/scale*UnitRemoval::E2; // colour and identical particle factors output *= colourFactor(inpart.dataPtr(),decay[0]->dataPtr(), decay[1]->dataPtr()); // return the answer return output; } Energy TVVDecayer::partialWidth(PMPair inpart, PMPair outa, PMPair outb) const { if( inpart.second < outa.second + outb.second ) return ZERO; - if(perturbativeVertex_) { + if(perturbativeVertex_.size()==1 && + perturbativeVertex_[0]) { Energy2 scale(sqr(inpart.second)); tcPDPtr in = inpart.first->CC() ? tcPDPtr(inpart.first->CC()) : inpart.first; - perturbativeVertex_->setCoupling(scale, outa.first, outb.first, in); + perturbativeVertex_[0]->setCoupling(scale, outa.first, outb.first, in); double mu2 = sqr(outa.second/inpart.second); double b = sqrt(1 - 4.*mu2); Energy pcm = Kinematics::pstarTwoBodyDecay(inpart.second,outa.second, outb.second); Energy2 me2; if(outa.second > ZERO && outb.second > ZERO) me2 = scale*(30 - 20.*b*b + 3.*pow(b,4))/120.; else me2 = scale/10.; - Energy output = norm(perturbativeVertex_->norm())*me2*pcm + Energy output = norm(perturbativeVertex_[0]->norm())*me2*pcm /(8.*Constants::pi)*UnitRemoval::InvE2; // colour factor output *= colourFactor(inpart.first,outa.first,outb.first); // return the answer return output; } else { return GeneralTwoBodyDecayer::partialWidth(inpart,outa,outb); } } double TVVDecayer::threeBodyME(const int , const Particle & inpart, const ParticleVector & decay, ShowerInteraction inter, MEOption meopt) { bool massless[2]; for(unsigned int ix=0;ix<2;++ix) massless[ix] = decay[ix]->mass()==ZERO; int iglu(2); if(meopt==Initialize) { // create tensor wavefunction for decaying particle TensorWaveFunction:: calculateWaveFunctions(tensors3_, rho3_, const_ptr_cast(&inpart), incoming, false); } // setup spin information when needed if(meopt==Terminate) { TensorWaveFunction:: constructSpinInfo(tensors3_, const_ptr_cast(&inpart),incoming,true, false); for(unsigned int ix=0;ix<2;++ix) VectorWaveFunction:: constructSpinInfo(vectors3_[ix],decay[ix ],outgoing,true, massless[ix]); VectorWaveFunction:: constructSpinInfo(gluon_ ,decay[iglu ],outgoing,true,false); return 0.; } // calculate colour factors and number of colour flows unsigned int nflow; vector cfactors = getColourFactors(inpart, decay, nflow); vector ME(nflow,new_ptr(GeneralDecayMatrixElement(PDT::Spin2, PDT::Spin1, PDT::Spin1, PDT::Spin1))); // create wavefunctions for(unsigned int ix=0;ix<2;++ix) VectorWaveFunction:: calculateWaveFunctions(vectors3_[ix],decay[ix ],outgoing,massless[ix]); VectorWaveFunction:: calculateWaveFunctions(gluon_ ,decay[iglu ],outgoing,true); // gauge test #ifdef GAUGE_CHECK gluon_.clear(); for(unsigned int ix=0;ix<3;++ix) { if(ix==1) gluon_.push_back(VectorWaveFunction()); else { gluon_.push_back(VectorWaveFunction(decay[iglu ]->momentum(), decay[iglu ]->dataPtr(),10, outgoing)); } } #endif // work out which vector each outgoing vertex corresponds to if(outgoingVertex1_[inter]!=outgoingVertex2_[inter] && outgoingVertex1_[inter]->isIncoming(getParticleData(decay[1]->id()))) swap(outgoingVertex1_[inter], outgoingVertex2_[inter]); if (! (outgoingVertex1_[inter] && outgoingVertex2_[inter])) throw Exception() << "Invalid vertices for radiation in TVV decay in TVVDecayer::threeBodyME" << Exception::runerror; if( !(!inpart.dataPtr()->coloured() && inter ==ShowerInteraction::QCD) && !(!inpart.dataPtr()->charged() && inter ==ShowerInteraction::QED)) throw Exception() << "Invalid vertices for radiation in TVV decay in TVVDecayer::threeBodyME" << Exception::runerror; Energy2 scale(sqr(inpart.mass())); const GeneralTwoBodyDecayer::CFlow & colourFlow = colourFlows(inpart, decay); double gs(0.); bool couplingSet(false); #ifdef GAUGE_CHECK double total=0.; #endif for(unsigned int it = 0; it < 5; ++it) { for(unsigned int iv0 = 0; iv0 < 3; ++iv0) { for(unsigned int iv1 = 0; iv1 < 3; ++iv1) { for(unsigned int ig = 0; ig < 2; ++ig) { // radiation from first outgoing vector if((decay[0]->dataPtr()->coloured() && inter==ShowerInteraction::QCD) || (decay[0]->dataPtr()->charged() && inter==ShowerInteraction::QED) ) { assert(outgoingVertex1_[inter]); // ensure you get correct outgoing particle from first vertex tcPDPtr off = decay[0]->dataPtr(); if(off->CC()) off = off->CC(); VectorWaveFunction vectInter = outgoingVertex1_[inter]->evaluate(scale,3,off,gluon_[2*ig], vectors3_[0][iv0],decay[0]->mass()); assert(vectors3_[0][iv0].particle()->PDGName()==vectInter.particle()->PDGName()); - Complex diag = vertex_->evaluate(scale,vectors3_[1][iv1], - vectInter,tensors3_[it]); + Complex diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,vectors3_[1][iv1], + vectInter,tensors3_[it]); if(!couplingSet) { gs = abs(outgoingVertex1_[inter]->norm()); couplingSet = true; } for(unsigned int ix=0;ixdataPtr()->coloured() && inter==ShowerInteraction::QCD) || (decay[1]->dataPtr()->charged() && inter==ShowerInteraction::QED) ) { assert(outgoingVertex2_[inter]); // ensure you get correct outgoing particle from first vertex tcPDPtr off = decay[1]->dataPtr(); if(off->CC()) off = off->CC(); VectorWaveFunction vectInter = outgoingVertex2_[inter]->evaluate(scale,3,off,vectors3_[1][iv1], gluon_[2*ig],decay[1]->mass()); assert(vectors3_[1][iv1].particle()->PDGName()==vectInter.particle()->PDGName()); - Complex diag = vertex_->evaluate(scale,vectInter,vectors3_[0][iv0], - tensors3_[it]); + Complex diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,vectInter,vectors3_[0][iv0], + tensors3_[it]); if(!couplingSet) { gs = abs(outgoingVertex2_[inter]->norm()); couplingSet = true; } for(unsigned int ix=0;ixevaluate(scale, vectors3_[0][iv0], vectors3_[1][iv1],gluon_[2*ig], tensors3_[it]); for(unsigned int ix=0;ixcontract(*ME[iy],rho3_)).real(); } } // divide by alpha_(s,em) output *= (4.*Constants::pi)/sqr(gs); #ifdef GAUGE_CHECK double ratio = output/total; if(abs(ratio)>1e-20) { generator()->log() << "Test of gauge invariance in decay\n" << inpart << "\n"; for(unsigned int ix=0;ixlog() << *decay[ix] << "\n"; generator()->log() << "Test of gauge invariance " << ratio << "\n"; } #endif // return the answer return output; } diff --git a/Decay/General/TVVDecayer.h b/Decay/General/TVVDecayer.h --- a/Decay/General/TVVDecayer.h +++ b/Decay/General/TVVDecayer.h @@ -1,205 +1,213 @@ // -*- C++ -*- // // TVVDecayer.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_TVVDecayer_H #define HERWIG_TVVDecayer_H // // This is the declaration of the TVVDecayer class. // #include "GeneralTwoBodyDecayer.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Helicity/Vertex/Vector/VVVVertex.h" #include "ThePEG/Helicity/Vertex/Tensor/VVTVertex.h" #include "ThePEG/Helicity/Vertex/Tensor/VVVTVertex.h" namespace Herwig { using namespace ThePEG; using Helicity::VVTVertexPtr; /** \ingroup Decay * The TVVDecayer class implements the decay of a tensor * to 2 vector bosons in a general model. It holds a VVTVertex pointer * that must be typecast from the VertexBase pointer held in * GeneralTwoBodyDecayer. It implents the virtual functions me2() and * partialWidth(). * * @see GeneralTwoBodyDecayer */ class TVVDecayer: public GeneralTwoBodyDecayer { public: /** * The default constructor. */ TVVDecayer() {} /** @name Virtual functions required by the Decayer class. */ //@{ /** * Return the matrix element squared for a given mode and phase-space channel. * @param ichan The channel we are calculating the matrix element for. * @param part The decaying Particle. * @param decay The particles produced in the decay. * @param meopt Option for the matrix element * @return The matrix element squared for the phase-space configuration. */ virtual double me2(const int ichan, const Particle & part, const ParticleVector & decay, MEOption meopt) const; /** * Function to return partial Width * @param inpart The decaying particle. * @param outa One of the decay products. * @param outb The other decay product. */ virtual Energy partialWidth(PMPair inpart, PMPair outa, PMPair outb) const; /** * Has a POWHEG style correction */ virtual POWHEGType hasPOWHEGCorrection() { - return (vertex_->orderInGem()+vertex_->orderInGs())==1 ? FSR : No; + POWHEGType output = FSR; + for(auto vertex : vertex_) { + if(vertex->orderInAllCouplings()!=1) { + output = No; + break; + } + } + return output; } /** * Three-body matrix element including additional QCD radiation */ virtual double threeBodyME(const int , const Particle & inpart, const ParticleVector & decay, ShowerInteraction inter, MEOption meopt); /** * Set the information on the decay */ - virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, VertexBasePtr, + virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, + vector, map &, const vector > &, map); //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ TVVDecayer & operator=(const TVVDecayer &); private: /** * Abstract pointer to AbstractVVTVertex */ - AbstractVVTVertexPtr vertex_; + vector vertex_; /** * Pointer to the perturbative vertex */ - VVTVertexPtr perturbativeVertex_; + vector perturbativeVertex_; /** * Abstract pointer to AbstractVVVVertex for QCD radiation from outgoing vector */ map outgoingVertex1_; /** * Abstract pointer to AbstractVVVVertex for QCD radiation from outgoing vector */ map outgoingVertex2_; /** * Abstract pointer to AbstractVVVTVertex for QCD radiation from 4 point vertex */ map fourPointVertex_; /** * Spin density matrix */ mutable RhoDMatrix rho_; /** * Polarization tensors of decaying particle */ mutable vector tensors_; /** * Polarization vectors of outgoing vector bosons */ mutable vector vectors_[2]; /** * Spin density matrix for 3 body decay */ mutable RhoDMatrix rho3_; /** * Tensor wavefunction for 3 body decay */ mutable vector tensors3_; /** * Polarization vectors of outgoing vector bosons */ mutable vector vectors3_[2]; /** * Vector wavefunction for 3 body decay */ mutable vector gluon_; }; } #endif /* HERWIG_TVVDecayer_H */ diff --git a/Decay/General/VFFDecayer.cc b/Decay/General/VFFDecayer.cc --- a/Decay/General/VFFDecayer.cc +++ b/Decay/General/VFFDecayer.cc @@ -1,456 +1,470 @@ // -*- C++ -*- // // VFFDecayer.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 VFFDecayer class. // #include "VFFDecayer.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" #include "Herwig/Utilities/Kinematics.h" #include "ThePEG/Helicity/Vertex/Vector/FFVVertex.h" #include "Herwig/Decay/GeneralDecayMatrixElement.h" using namespace Herwig; using namespace ThePEG::Helicity; IBPtr VFFDecayer::clone() const { return new_ptr(*this); } IBPtr VFFDecayer::fullclone() const { return new_ptr(*this); } void VFFDecayer::setDecayInfo(PDPtr incoming, PDPair outgoing, - VertexBasePtr vertex, + vector vertex, map & inV, const vector > & outV, map ) { decayInfo(incoming,outgoing); - vertex_ = dynamic_ptr_cast(vertex); - perturbativeVertex_ = dynamic_ptr_cast (vertex); + for(auto vert : vertex) { + vertex_ .push_back(dynamic_ptr_cast(vert)); + perturbativeVertex_.push_back(dynamic_ptr_cast (vert)); + } vector itemp={ShowerInteraction::QCD,ShowerInteraction::QED}; for(auto & inter : itemp) { incomingVertex_[inter] = dynamic_ptr_cast(inV.at(inter)); outgoingVertex1_[inter] = dynamic_ptr_cast(outV[0].at(inter)); outgoingVertex2_[inter] = dynamic_ptr_cast(outV[1].at(inter)); } } void VFFDecayer::persistentOutput(PersistentOStream & os) const { os << vertex_ << perturbativeVertex_ << incomingVertex_ << outgoingVertex1_ << outgoingVertex2_; } void VFFDecayer::persistentInput(PersistentIStream & is, int) { is >> vertex_ >> perturbativeVertex_ >> incomingVertex_ >> outgoingVertex1_ >> outgoingVertex2_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigVFFDecayer("Herwig::VFFDecayer", "Herwig.so"); void VFFDecayer::Init() { static ClassDocumentation documentation ("The VFFDecayer implements the matrix element for the" " decay of a vector to fermion-antifermion pair"); } double VFFDecayer::me2(const int , const Particle & inpart, const ParticleVector & decay, MEOption meopt) const { int iferm(1),ianti(0); if(decay[0]->id()>0) swap(iferm,ianti); if(!ME()) ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin1,PDT::Spin1Half,PDT::Spin1Half))); if(meopt==Initialize) { VectorWaveFunction::calculateWaveFunctions(vectors_,rho_, const_ptr_cast(&inpart), incoming,false); } if(meopt==Terminate) { VectorWaveFunction::constructSpinInfo(vectors_,const_ptr_cast(&inpart), incoming,true,false); SpinorBarWaveFunction:: constructSpinInfo(wavebar_,decay[iferm],outgoing,true); SpinorWaveFunction:: constructSpinInfo(wave_ ,decay[ianti],outgoing,true); return 0.; } SpinorBarWaveFunction:: calculateWaveFunctions(wavebar_,decay[iferm],outgoing); SpinorWaveFunction:: calculateWaveFunctions(wave_ ,decay[ianti],outgoing); // compute the matrix element Energy2 scale(inpart.mass()*inpart.mass()); for(unsigned int ifm = 0; ifm < 2; ++ifm) { //loop over fermion helicities for(unsigned int ia = 0; ia < 2; ++ia) {// loop over antifermion helicities for(unsigned int vhel = 0; vhel < 3; ++vhel) {//loop over vector helicities if(iferm > ianti) { - (*ME())(vhel, ia, ifm) = - vertex_->evaluate(scale,wave_[ia], - wavebar_[ifm],vectors_[vhel]); + (*ME())(vhel, ia, ifm) = 0.; + for(auto vert : vertex_) + (*ME())(vhel, ia, ifm) += + vert->evaluate(scale,wave_[ia], + wavebar_[ifm],vectors_[vhel]); } - else - (*ME())(vhel,ifm,ia)= - vertex_->evaluate(scale,wave_[ia], - wavebar_[ifm],vectors_[vhel]); + else { + (*ME())(vhel,ifm,ia)= 0.; + for(auto vert : vertex_) + (*ME())(vhel,ifm,ia) += + vert->evaluate(scale,wave_[ia], + wavebar_[ifm],vectors_[vhel]); + } } } } double output=(ME()->contract(rho_)).real()/scale*UnitRemoval::E2; // colour and identical particle factors output *= colourFactor(inpart.dataPtr(),decay[0]->dataPtr(), decay[1]->dataPtr()); // return the answer return output; } Energy VFFDecayer::partialWidth(PMPair inpart, PMPair outa, PMPair outb) const { if( inpart.second < outa.second + outb.second ) return ZERO; - if(perturbativeVertex_) { + if(perturbativeVertex_.size()==1 && + perturbativeVertex_[0]) { double mu1(outa.second/inpart.second), mu2(outb.second/inpart.second); tcPDPtr in = inpart.first->CC() ? tcPDPtr(inpart.first->CC()) : inpart.first; - perturbativeVertex_->setCoupling(sqr(inpart.second), outa.first, outb.first,in); - Complex cl(perturbativeVertex_->left()), cr(perturbativeVertex_->right()); + perturbativeVertex_[0]->setCoupling(sqr(inpart.second), outa.first, outb.first,in); + Complex cl(perturbativeVertex_[0]->left()), cr(perturbativeVertex_[0]->right()); double me2 = (norm(cl) + norm(cr))*( sqr(sqr(mu1) - sqr(mu2)) + sqr(mu1) + sqr(mu2) - 2.) - 6.*(cl*conj(cr) + cr*conj(cl)).real()*mu1*mu2; Energy pcm = Kinematics::pstarTwoBodyDecay(inpart.second,outa.second, outb.second); - Energy output = -norm(perturbativeVertex_->norm())*me2*pcm / + Energy output = -norm(perturbativeVertex_[0]->norm())*me2*pcm / (24.*Constants::pi); // colour factor output *= colourFactor(inpart.first,outa.first,outb.first); // return the answer return output; } else { return GeneralTwoBodyDecayer::partialWidth(inpart,outa,outb); } } double VFFDecayer::threeBodyME(const int , const Particle & inpart, const ParticleVector & decay, ShowerInteraction inter, MEOption meopt) { // work out which is the fermion and antifermion int ianti(0), iferm(1), iglu(2); int itype[2]; for(unsigned int ix=0;ix<2;++ix) { if(decay[ix]->dataPtr()->CC()) itype[ix] = decay[ix]->id()>0 ? 0:1; else itype[ix] = 2; } if(itype[0]==0 && itype[1]!=0) swap(iferm, ianti); if(itype[0]==2 && itype[1]==1) swap(iferm, ianti); if(itype[0]==0 && itype[1]==0 && decay[0]->dataPtr()->id()dataPtr()->id()) swap(iferm, ianti); if(itype[0]==1 && itype[1]==1 && decay[0]->dataPtr()->id()dataPtr()->id()) swap(iferm, ianti); if(meopt==Initialize) { // create vector wavefunction for decaying particle VectorWaveFunction::calculateWaveFunctions(vector3_, rho3_, const_ptr_cast(&inpart), incoming, false); } // setup spin information when needed if(meopt==Terminate) { VectorWaveFunction:: constructSpinInfo(vector3_ ,const_ptr_cast(&inpart),outgoing,true,false); SpinorBarWaveFunction:: constructSpinInfo(wavebar3_,decay[iferm],outgoing,true); SpinorWaveFunction:: constructSpinInfo(wave3_ ,decay[ianti],outgoing,true); VectorWaveFunction:: constructSpinInfo(gluon_ ,decay[iglu ],outgoing,true,false); return 0.; } // calculate colour factors and number of colour flows unsigned int nflow; vector cfactors = getColourFactors(inpart, decay, nflow); vector ME(nflow,new_ptr(GeneralDecayMatrixElement(PDT::Spin1, PDT::Spin1Half, PDT::Spin1Half, PDT::Spin1))); // create wavefunctions SpinorBarWaveFunction:: calculateWaveFunctions(wavebar3_, decay[iferm],outgoing); SpinorWaveFunction:: calculateWaveFunctions(wave3_ , decay[ianti],outgoing); VectorWaveFunction:: calculateWaveFunctions(gluon_ , decay[iglu ],outgoing,true); // gauge invariance test #ifdef GAUGE_CHECK gluon_.clear(); for(unsigned int ix=0;ix<3;++ix) { if(ix==1) gluon_.push_back(VectorWaveFunction()); else { gluon_.push_back(VectorWaveFunction(decay[iglu ]->momentum(), decay[iglu ]->dataPtr(),10, outgoing)); } } #endif // identify fermion and/or anti-fermion vertex AbstractFFVVertexPtr outgoingVertexF; AbstractFFVVertexPtr outgoingVertexA; identifyVertices(iferm, ianti, inpart, decay, outgoingVertexF, outgoingVertexA,inter); Energy2 scale(sqr(inpart.mass())); const GeneralTwoBodyDecayer::CFlow & colourFlow = colourFlows(inpart, decay); double gs(0.); bool couplingSet(false); #ifdef GAUGE_CHECK double total=0.; #endif for(unsigned int iv = 0; iv < 3; ++iv) { for(unsigned int ifm = 0; ifm < 2; ++ifm) { for(unsigned int ia = 0; ia < 2; ++ia) { for(unsigned int ig = 0; ig < 2; ++ig) { // radiation from the incoming vector if((inpart.dataPtr()->coloured() && inter==ShowerInteraction::QCD) || (inpart.dataPtr()->charged() && inter==ShowerInteraction::QED) ) { assert(incomingVertex_[inter]); VectorWaveFunction vectorInter = incomingVertex_[inter]->evaluate(scale,3,inpart.dataPtr(),vector3_[iv], gluon_[2*ig],inpart.mass()); assert(vector3_[iv].particle()->id()==vectorInter.particle()->id()); - Complex diag = vertex_->evaluate(scale,wave3_[ia],wavebar3_[ifm],vectorInter); + Complex diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,wave3_[ia],wavebar3_[ifm],vectorInter); if(!couplingSet) { gs = abs(incomingVertex_[inter]->norm()); couplingSet = true; } for(unsigned int ix=0;ixdataPtr()->coloured() && inter==ShowerInteraction::QCD) || (decay[iferm]->dataPtr()->charged() && inter==ShowerInteraction::QED) ) { assert(outgoingVertexF); // ensure you get correct outgoing particle from first vertex tcPDPtr off = decay[iferm]->dataPtr(); if(off->CC()) off = off->CC(); SpinorBarWaveFunction interS = outgoingVertexF->evaluate(scale,3,off,wavebar3_[ifm], gluon_[2*ig],decay[iferm]->mass()); assert(wavebar3_[ifm].particle()->id()==interS.particle()->id()); - Complex diag = vertex_->evaluate(scale,wave3_[ia], interS,vector3_[iv]); + Complex diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,wave3_[ia], interS,vector3_[iv]); if(!couplingSet) { gs = abs(outgoingVertexF->norm()); couplingSet = true; } for(unsigned int ix=0;ixdataPtr()->coloured() && inter==ShowerInteraction::QCD) || (decay[ianti]->dataPtr()->charged() && inter==ShowerInteraction::QED) ) { assert(outgoingVertexA); // ensure you get correct outgoing particle from first vertex tcPDPtr off = decay[ianti]->dataPtr(); if(off->CC()) off = off->CC(); SpinorWaveFunction interS = outgoingVertexA->evaluate(scale,3,off,wave3_[ia], gluon_[2*ig],decay[ianti]->mass()); assert(wave3_[ia].particle()->id()==interS.particle()->id()); - Complex diag = vertex_->evaluate(scale,interS,wavebar3_[ifm],vector3_[iv]); + Complex diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,interS,wavebar3_[ifm],vector3_[iv]); if(!couplingSet) { gs = abs(outgoingVertexA->norm()); couplingSet = true; } for(unsigned int ix=0;ixcontract(*ME[iy],rho3_)).real(); } } // divide by alpha_(S,EM) output*=(4.*Constants::pi)/sqr(gs); #ifdef GAUGE_CHECK double ratio = output/total; if(abs(ratio)>1e-20) { generator()->log() << "Test of gauge invariance in decay\n" << inpart << "\n"; for(unsigned int ix=0;ixlog() << *decay[ix] << "\n"; generator()->log() << "Test of gauge invariance " << ratio << "\n"; } #endif //return output return output; } void VFFDecayer::identifyVertices(const int iferm, const int ianti, const Particle & inpart, const ParticleVector & decay, AbstractFFVVertexPtr & outgoingVertexF, AbstractFFVVertexPtr & outgoingVertexA, ShowerInteraction inter){ // QCD vertices if(inter==ShowerInteraction::QCD) { // work out which fermion each outgoing vertex corresponds to // two outgoing vertices if( inpart.dataPtr() ->iColour()==PDT::Colour0 && ((decay[iferm]->dataPtr()->iColour()==PDT::Colour3 && decay[ianti]->dataPtr()->iColour()==PDT::Colour3bar) || (decay[iferm]->dataPtr()->iColour()==PDT::Colour8 && decay[ianti]->dataPtr()->iColour()==PDT::Colour8))){ if(outgoingVertex1_[inter]==outgoingVertex2_[inter]){ outgoingVertexF = outgoingVertex1_[inter]; outgoingVertexA = outgoingVertex2_[inter]; } else if (outgoingVertex1_[inter]->isIncoming(const_ptr_cast(decay[iferm]->dataPtr()))){ outgoingVertexF = outgoingVertex1_[inter]; outgoingVertexA = outgoingVertex2_[inter]; } else if (outgoingVertex2_[inter]->isIncoming(const_ptr_cast(decay[iferm]->dataPtr()))){ outgoingVertexF = outgoingVertex2_[inter]; outgoingVertexA = outgoingVertex1_[inter]; } } else if(inpart.dataPtr() ->iColour()==PDT::Colour8 && decay[iferm]->dataPtr()->iColour()==PDT::Colour3 && decay[ianti]->dataPtr()->iColour()==PDT::Colour3bar){ if(outgoingVertex1_[inter]==outgoingVertex2_[inter]){ outgoingVertexF = outgoingVertex1_[inter]; outgoingVertexA = outgoingVertex2_[inter]; } else if (outgoingVertex1_[inter]->isIncoming(const_ptr_cast(decay[iferm]->dataPtr()))){ outgoingVertexF = outgoingVertex1_[inter]; outgoingVertexA = outgoingVertex2_[inter]; } else if (outgoingVertex2_[inter]->isIncoming(const_ptr_cast(decay[iferm]->dataPtr()))){ outgoingVertexF = outgoingVertex2_[inter]; outgoingVertexA = outgoingVertex1_[inter]; } } // one outgoing vertex else if(inpart.dataPtr()->iColour()==PDT::Colour3){ if(decay[iferm]->dataPtr()->iColour()==PDT::Colour3 && decay[ianti]->dataPtr()->iColour()==PDT::Colour0){ if (outgoingVertex1_[inter]) outgoingVertexF = outgoingVertex1_[inter]; else if(outgoingVertex2_[inter]) outgoingVertexF = outgoingVertex2_[inter]; } else if (decay[iferm]->dataPtr()->iColour()==PDT::Colour3 && decay[ianti]->dataPtr()->iColour()==PDT::Colour8){ if (outgoingVertex1_[inter]->isIncoming(const_ptr_cast(decay[ianti]->dataPtr()))){ outgoingVertexF = outgoingVertex2_[inter]; outgoingVertexA = outgoingVertex1_[inter]; } else { outgoingVertexF = outgoingVertex1_[inter]; outgoingVertexA = outgoingVertex2_[inter]; } } } else if(inpart.dataPtr()->iColour()==PDT::Colour3bar){ if(decay[ianti]->dataPtr()->iColour()==PDT::Colour3bar && decay[iferm]->dataPtr()->iColour()==PDT::Colour0){ if (outgoingVertex1_[inter]) outgoingVertexA = outgoingVertex1_[inter]; else if(outgoingVertex2_[inter]) outgoingVertexA = outgoingVertex2_[inter]; } else if (decay[iferm]->dataPtr()->iColour()==PDT::Colour8 && decay[ianti]->dataPtr()->iColour()==PDT::Colour3bar){ if (outgoingVertex1_[inter]->isIncoming(const_ptr_cast(decay[iferm]->dataPtr()))){ outgoingVertexF = outgoingVertex1_[inter]; outgoingVertexA = outgoingVertex2_[inter]; } else { outgoingVertexF = outgoingVertex2_[inter]; outgoingVertexA = outgoingVertex1_[inter]; } } } else if(inpart.dataPtr()->iColour()==PDT::Colour6 || inpart.dataPtr()->iColour()==PDT::Colour6bar) { if (outgoingVertex1_[inter]->isIncoming(const_ptr_cast(decay[iferm]->dataPtr()))) { outgoingVertexF = outgoingVertex1_[inter]; outgoingVertexA = outgoingVertex2_[inter]; } else { outgoingVertexF = outgoingVertex2_[inter]; outgoingVertexA = outgoingVertex1_[inter]; } } if (! ((incomingVertex_[inter] && (outgoingVertexF || outgoingVertexA)) || ( outgoingVertexF && outgoingVertexA))) throw Exception() << "Invalid vertices for QCD radiation in VFF decay in VFFDecayer::identifyVertices" << Exception::runerror; } // QED else { if(decay[iferm]->dataPtr()->charged()) { if (outgoingVertex1_[inter] && outgoingVertex1_[inter]->isIncoming(const_ptr_cast(decay[iferm]->dataPtr()))) outgoingVertexF = outgoingVertex1_[inter]; else outgoingVertexF = outgoingVertex2_[inter]; } if(decay[ianti]->dataPtr()->charged()) { if (outgoingVertex1_[inter] && outgoingVertex1_[inter]->isIncoming(const_ptr_cast(decay[ianti]->dataPtr()))) outgoingVertexA = outgoingVertex1_[inter]; else outgoingVertexA = outgoingVertex2_[inter]; } } } diff --git a/Decay/General/VFFDecayer.h b/Decay/General/VFFDecayer.h --- a/Decay/General/VFFDecayer.h +++ b/Decay/General/VFFDecayer.h @@ -1,224 +1,232 @@ // -*- C++ -*- // // VFFDecayer.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_VFFDecayer_H #define HERWIG_VFFDecayer_H // // This is the declaration of the VFFDecayer class. // #include "GeneralTwoBodyDecayer.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Helicity/Vertex/Vector/FFVVertex.h" #include "ThePEG/Helicity/Vertex/Vector/VVVVertex.h" namespace Herwig { using namespace ThePEG; using Helicity::FFVVertexPtr; /** \ingroup Decay * The VFFDecayer class implements the decay of a vector * to 2 fermions in a general model. It holds an FFVVertex pointer * that must be typecast from the VertexBase pointer held in * GeneralTwoBodyDecayer. It implents the virtual functions me2() and * partialWidth(). * * @see GeneralTwoBodyDecayer */ class VFFDecayer: public GeneralTwoBodyDecayer { public: /** * The default constructor. */ VFFDecayer() {} public: /** @name Virtual functions required by the Decayer class. */ //@{ /** * Return the matrix element squared for a given mode and phase-space channel. * @param ichan The channel we are calculating the matrix element for. * @param part The decaying Particle. * @param decay The particles produced in the decay. * @param meopt Option for the matrix element * @return The matrix element squared for the phase-space configuration. */ virtual double me2(const int ichan, const Particle & part, const ParticleVector & decay, MEOption meopt) const; /** * Function to return partial Width * @param inpart The decaying particle. * @param outa One of the decay products. * @param outb The other decay product. */ virtual Energy partialWidth(PMPair inpart, PMPair outa, PMPair outb) const; /** * Has a POWHEG style correction */ virtual POWHEGType hasPOWHEGCorrection() { - return (vertex_->orderInGem()+vertex_->orderInGs())==1 ? FSR : No; + POWHEGType output = FSR; + for(auto vertex : vertex_) { + if(vertex->orderInAllCouplings()!=1) { + output = No; + break; + } + } + return output; } /** * Three-body matrix element including additional QCD radiation */ virtual double threeBodyME(const int , const Particle & inpart, const ParticleVector & decay, ShowerInteraction inter, MEOption meopt); /** * Indentify outgoing vertices for the fermion and antifermion */ void identifyVertices(const int iferm, const int ianti, const Particle & inpart, const ParticleVector & decay, AbstractFFVVertexPtr & abstractOutgoingVertexF, AbstractFFVVertexPtr & abstractOutgoingVertexA, ShowerInteraction inter); /** * Set the information on the decay */ - virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, VertexBasePtr, + virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, + vector, map &, const vector > &, map); //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ VFFDecayer & operator=(const VFFDecayer &); private: /** * Abstract pointer to AbstractFFVVertex */ - AbstractFFVVertexPtr vertex_; + vector vertex_; /** * Pointer to the perturbative vertex */ - FFVVertexPtr perturbativeVertex_; + vector perturbativeVertex_; /** * Abstract pointer to AbstractVVVVertex for QCD radiation from incoming vector */ map incomingVertex_; /** * Abstract pointer to AbstractFFVVertex for QCD radiation from outgoing (anti)fermion */ map outgoingVertex1_; /** * Abstract pointer to AbstractFFVVertex for QCD radiation from outgoing (anti)fermion */ map outgoingVertex2_; /** * Spin density matrix */ mutable RhoDMatrix rho_; /** * Polarization vectors for the decaying particle */ mutable vector vectors_; /** * Spinors for the decay products */ mutable vector wave_; /** * Barred spinors for the decay products */ mutable vector wavebar_; /** * Spin density matrix for 3 body decay */ mutable RhoDMatrix rho3_; /** * Scalar wavefunction for 3 body decay */ mutable vector vector3_; /** * Spinor wavefunction for 3 body decay */ mutable vector wave3_; /** * Barred spinor wavefunction for 3 body decay */ mutable vector wavebar3_; /** * Vector wavefunction for 3 body decay */ mutable vector gluon_; }; } #endif /* HERWIG_VFFDecayer_H */ diff --git a/Decay/General/VSSDecayer.cc b/Decay/General/VSSDecayer.cc --- a/Decay/General/VSSDecayer.cc +++ b/Decay/General/VSSDecayer.cc @@ -1,405 +1,416 @@ // -*- C++ -*- // // VSSDecayer.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 VSSDecayer class. // #include "VSSDecayer.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/DecayMode.h" #include "Herwig/Utilities/Kinematics.h" #include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "Herwig/Decay/GeneralDecayMatrixElement.h" using namespace Herwig; using namespace ThePEG::Helicity; IBPtr VSSDecayer::clone() const { return new_ptr(*this); } IBPtr VSSDecayer::fullclone() const { return new_ptr(*this); } void VSSDecayer::setDecayInfo(PDPtr incoming, PDPair outgoing, - VertexBasePtr vertex, + vector vertex, map & inV, const vector > & outV, map ) { decayInfo(incoming,outgoing); - vertex_ = dynamic_ptr_cast(vertex); - perturbativeVertex_ = dynamic_ptr_cast (vertex); + for(auto vert : vertex) { + vertex_ .push_back(dynamic_ptr_cast(vert)); + perturbativeVertex_.push_back(dynamic_ptr_cast (vert)); + } vector itemp={ShowerInteraction::QCD,ShowerInteraction::QED}; for(auto & inter : itemp) { incomingVertex_[inter] = dynamic_ptr_cast(inV.at(inter)); outgoingVertex1_[inter] = dynamic_ptr_cast(outV[0].at(inter)); outgoingVertex2_[inter] = dynamic_ptr_cast(outV[1].at(inter)); } } void VSSDecayer::persistentOutput(PersistentOStream & os) const { os << vertex_ << perturbativeVertex_ << incomingVertex_ << outgoingVertex1_ << outgoingVertex2_; } void VSSDecayer::persistentInput(PersistentIStream & is, int) { is >> vertex_ >> perturbativeVertex_ >> incomingVertex_ >> outgoingVertex1_ >> outgoingVertex2_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigVSSDecayer("Herwig::VSSDecayer", "Herwig.so"); void VSSDecayer::Init() { static ClassDocumentation documentation ("This implements the decay of a vector to 2 scalars"); } double VSSDecayer::me2(const int , const Particle & inpart, const ParticleVector & decay, MEOption meopt) const { if(!ME()) ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin1,PDT::Spin0,PDT::Spin0))); if(meopt==Initialize) { VectorWaveFunction::calculateWaveFunctions(vectors_,rho_, const_ptr_cast(&inpart), incoming,false); } if(meopt==Terminate) { VectorWaveFunction::constructSpinInfo(vectors_,const_ptr_cast(&inpart), incoming,true,false); for(unsigned int ix=0;ix<2;++ix) ScalarWaveFunction:: constructSpinInfo(decay[ix],outgoing,true); return 0.; } ScalarWaveFunction sca1(decay[0]->momentum(),decay[0]->dataPtr(),outgoing); ScalarWaveFunction sca2(decay[1]->momentum(),decay[1]->dataPtr(),outgoing); Energy2 scale(sqr(inpart.mass())); for(unsigned int ix=0;ix<3;++ix) { - (*ME())(ix,0,0) = vertex_->evaluate(scale,vectors_[ix],sca1,sca2); + (*ME())(ix,0,0) = 0.; + for(auto vert : vertex_) + (*ME())(ix,0,0) += vert->evaluate(scale,vectors_[ix],sca1,sca2); } double output=(ME()->contract(rho_)).real()/scale*UnitRemoval::E2; // colour and identical particle factors output *= colourFactor(inpart.dataPtr(),decay[0]->dataPtr(), decay[1]->dataPtr()); // return the answer return output; } Energy VSSDecayer::partialWidth(PMPair inpart, PMPair outa, PMPair outb) const { if( inpart.second < outa.second + outb.second ) return ZERO; - if(perturbativeVertex_) { + if(perturbativeVertex_.size()==1 && + perturbativeVertex_[0]) { tcPDPtr in = inpart.first->CC() ? tcPDPtr(inpart.first->CC()) : inpart.first; - perturbativeVertex_->setCoupling(sqr(inpart.second), in, outa.first, + perturbativeVertex_[0]->setCoupling(sqr(inpart.second), in, outa.first, outb.first); double mu1sq = sqr(outa.second/inpart.second); double mu2sq = sqr(outb.second/inpart.second); double me2 = sqr(mu1sq - mu2sq) - 2.*(mu1sq + mu2sq); Energy pcm = Kinematics::pstarTwoBodyDecay(inpart.second,outa.second, outb.second); - Energy output = -norm(perturbativeVertex_->norm())*me2*pcm / + Energy output = -norm(perturbativeVertex_[0]->norm())*me2*pcm / (24.*Constants::pi); // colour factor output *= colourFactor(inpart.first,outa.first,outb.first); // return the answer return output; } else { return GeneralTwoBodyDecayer::partialWidth(inpart,outa,outb); } } double VSSDecayer::threeBodyME(const int , const Particle & inpart, const ParticleVector & decay, ShowerInteraction inter, MEOption meopt) { // work out which is the scalar and anti-scalar int ianti(0), iscal(1), iglu(2); int itype[2]; for(unsigned int ix=0;ix<2;++ix) { if(decay[ix]->dataPtr()->CC()) itype[ix] = decay[ix]->id()>0 ? 0:1; else itype[ix] = 2; } if(itype[0]==0 && itype[1]!=0) swap(ianti, iscal); if(itype[0]==2 && itype[1]==1) swap(ianti, iscal); if(itype[0]==0 && itype[1]==0 && abs(decay[0]->dataPtr()->id())>abs(decay[1]->dataPtr()->id())) swap(iscal, ianti); if(itype[0]==1 && itype[1]==1 && abs(decay[0]->dataPtr()->id())dataPtr()->id())) swap(iscal, ianti); if(meopt==Initialize) { // create vector wavefunction for decaying particle VectorWaveFunction::calculateWaveFunctions(vector3_, rho3_, const_ptr_cast(&inpart), incoming, false); } // setup spin information when needed if(meopt==Terminate) { VectorWaveFunction:: constructSpinInfo(vector3_ ,const_ptr_cast(&inpart),outgoing,true,false); ScalarWaveFunction::constructSpinInfo( decay[iscal],outgoing,true); ScalarWaveFunction::constructSpinInfo( decay[ianti],outgoing,true); VectorWaveFunction::constructSpinInfo(gluon_,decay[iglu ],outgoing,true,false); return 0.; } // calculate colour factors and number of colour flows unsigned int nflow; vector cfactors = getColourFactors(inpart, decay, nflow); vector ME(nflow,new_ptr(GeneralDecayMatrixElement(PDT::Spin1, PDT::Spin0, PDT::Spin0, PDT::Spin1))); // create wavefunctions ScalarWaveFunction scal(decay[iscal]->momentum(), decay[iscal]->dataPtr(),outgoing); ScalarWaveFunction anti(decay[ianti]->momentum(), decay[ianti]->dataPtr(),outgoing); VectorWaveFunction::calculateWaveFunctions(gluon_,decay[iglu ],outgoing,true); // gauge test #ifdef GAUGE_CHECK gluon_.clear(); for(unsigned int ix=0;ix<3;++ix) { if(ix==1) gluon_.push_back(VectorWaveFunction()); else { gluon_.push_back(VectorWaveFunction(decay[iglu ]->momentum(), decay[iglu ]->dataPtr(),10, outgoing)); } } #endif // identify scalar and/or anti-scalar vertex AbstractVSSVertexPtr outgoingVertexS; AbstractVSSVertexPtr outgoingVertexA; identifyVertices(iscal, ianti, inpart, decay, outgoingVertexS, outgoingVertexA,inter); Energy2 scale(sqr(inpart.mass())); const GeneralTwoBodyDecayer::CFlow & colourFlow = colourFlows(inpart, decay); double gs(0.); bool couplingSet(false); #ifdef GAUGE_CHECK double total=0.; #endif for(unsigned int iv = 0; iv < 3; ++iv) { for(unsigned int ig = 0; ig < 2; ++ig) { // radiation from the incoming vector if((inpart.dataPtr()->coloured() && inter==ShowerInteraction::QCD) || (inpart.dataPtr()->charged() && inter==ShowerInteraction::QED) ) { assert(incomingVertex_[inter]); VectorWaveFunction vectorInter = incomingVertex_[inter]->evaluate(scale,3,inpart.dataPtr(),vector3_[iv], gluon_[2*ig],inpart.mass()); assert(vector3_[iv].particle()->id()==vectorInter.particle()->id()); - Complex diag = vertex_->evaluate(scale,vectorInter,scal,anti); + Complex diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,vectorInter,scal,anti); if(!couplingSet) { gs = abs(incomingVertex_[inter]->norm()); couplingSet = true; } for(unsigned int ix=0;ixdataPtr()->coloured() && inter==ShowerInteraction::QCD) || (decay[iscal]->dataPtr()->charged() && inter==ShowerInteraction::QED) ) { assert(outgoingVertexS); // ensure you get correct outgoing particle from first vertex tcPDPtr off = decay[iscal]->dataPtr(); if(off->CC()) off = off->CC(); ScalarWaveFunction scalarInter = outgoingVertexS->evaluate(scale,3,off,gluon_[2*ig],scal,decay[iscal]->mass()); assert(scal.particle()->id()==scalarInter.particle()->id()); - Complex diag =vertex_->evaluate(scale,vector3_[iv],anti,scalarInter); + Complex diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,vector3_[iv],anti,scalarInter); if(!couplingSet) { gs = abs(outgoingVertexS->norm()); couplingSet = true; } for(unsigned int ix=0;ixdataPtr()->coloured() && inter==ShowerInteraction::QCD) || (decay[ianti]->dataPtr()->charged() && inter==ShowerInteraction::QED) ) { assert(outgoingVertexA); // ensure you get correct outgoing particle from first vertex tcPDPtr off = decay[ianti]->dataPtr(); if(off->CC()) off = off->CC(); ScalarWaveFunction scalarInter = outgoingVertexA->evaluate(scale,3,off, gluon_[2*ig],anti,decay[ianti]->mass()); assert(anti.particle()->id()==scalarInter.particle()->id()); - Complex diag = vertex_->evaluate(scale,vector3_[iv],scal,scalarInter); + Complex diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,vector3_[iv],scal,scalarInter); if(!couplingSet) { gs = abs(outgoingVertexA->norm()); couplingSet = true; } for(unsigned int ix=0;ixcontract(*ME[iy],rho3_)).real(); } } // divide by alpha_(S,EM) output*=(4.*Constants::pi)/sqr(gs); #ifdef GAUGE_CHECK double ratio = output/total; if(abs(ratio)>1e-20) { generator()->log() << "Test of gauge invariance in decay\n" << inpart << "\n"; for(unsigned int ix=0;ixlog() << *decay[ix] << "\n"; generator()->log() << "Test of gauge invariance " << ratio << "\n"; } #endif // return the answer return output; } void VSSDecayer::identifyVertices(const int iscal, const int ianti, const Particle & inpart, const ParticleVector & decay, AbstractVSSVertexPtr & outgoingVertexS, AbstractVSSVertexPtr & outgoingVertexA, ShowerInteraction inter){ if(inter==ShowerInteraction::QCD) { // work out which scalar each outgoing vertex corresponds to // two outgoing vertices if( inpart.dataPtr() ->iColour()==PDT::Colour0 && ((decay[iscal]->dataPtr()->iColour()==PDT::Colour3 && decay[ianti]->dataPtr()->iColour()==PDT::Colour3bar) || (decay[iscal]->dataPtr()->iColour()==PDT::Colour8 && decay[ianti]->dataPtr()->iColour()==PDT::Colour8))){ if(outgoingVertex1_[inter]==outgoingVertex2_[inter]){ outgoingVertexS = outgoingVertex1_[inter]; outgoingVertexA = outgoingVertex2_[inter]; } else if (outgoingVertex1_[inter]->isIncoming(getParticleData(decay[iscal]->id()))){ outgoingVertexS = outgoingVertex1_[inter]; outgoingVertexA = outgoingVertex2_[inter]; } else if (outgoingVertex2_[inter]->isIncoming(getParticleData(decay[iscal]->id()))){ outgoingVertexS = outgoingVertex2_[inter]; outgoingVertexA = outgoingVertex1_[inter]; } } else if(inpart.dataPtr() ->iColour()==PDT::Colour8 && decay[iscal]->dataPtr()->iColour()==PDT::Colour3 && decay[ianti]->dataPtr()->iColour()==PDT::Colour3bar){ if(outgoingVertex1_[inter]==outgoingVertex2_[inter]){ outgoingVertexS = outgoingVertex1_[inter]; outgoingVertexA = outgoingVertex2_[inter]; } else if (outgoingVertex1_[inter]->isIncoming(getParticleData(decay[iscal]->id()))){ outgoingVertexS = outgoingVertex1_[inter]; outgoingVertexA = outgoingVertex2_[inter]; } else if (outgoingVertex2_[inter]->isIncoming(getParticleData(decay[iscal]->id()))){ outgoingVertexS = outgoingVertex2_[inter]; outgoingVertexA = outgoingVertex1_[inter]; } } // one outgoing vertex else if(inpart.dataPtr()->iColour()==PDT::Colour3){ if(decay[iscal]->dataPtr()->iColour()==PDT::Colour3 && decay[ianti]->dataPtr()->iColour()==PDT::Colour0){ if (outgoingVertex1_[inter]) outgoingVertexS = outgoingVertex1_[inter]; else if(outgoingVertex2_[inter]) outgoingVertexS = outgoingVertex2_[inter]; } else if (decay[iscal]->dataPtr()->iColour()==PDT::Colour3 && decay[ianti]->dataPtr()->iColour()==PDT::Colour8){ if (outgoingVertex1_[inter]->isIncoming(getParticleData(decay[ianti]->dataPtr()->id()))){ outgoingVertexS = outgoingVertex2_[inter]; outgoingVertexA = outgoingVertex1_[inter]; } else { outgoingVertexS = outgoingVertex1_[inter]; outgoingVertexA = outgoingVertex2_[inter]; } } } else if(inpart.dataPtr()->iColour()==PDT::Colour3bar){ if(decay[ianti]->dataPtr()->iColour()==PDT::Colour3bar && decay[iscal]->dataPtr()->iColour()==PDT::Colour0){ if (outgoingVertex1_[inter]) outgoingVertexA = outgoingVertex1_[inter]; else if(outgoingVertex2_[inter]) outgoingVertexA = outgoingVertex2_[inter]; } else if (decay[iscal]->dataPtr()->iColour()==PDT::Colour8 && decay[ianti]->dataPtr()->iColour()==PDT::Colour3bar){ if (outgoingVertex1_[inter]->isIncoming(getParticleData(decay[iscal]->dataPtr()->id()))){ outgoingVertexS = outgoingVertex1_[inter]; outgoingVertexA = outgoingVertex2_[inter]; } else { outgoingVertexS = outgoingVertex2_[inter]; outgoingVertexA = outgoingVertex1_[inter]; } } } if (! ((incomingVertex_[inter] && (outgoingVertexS || outgoingVertexA)) || ( outgoingVertexS && outgoingVertexA))) throw Exception() << "Invalid vertices for QCD radiation in VSS decay in VSSDecayer::identifyVertices" << Exception::runerror; } else { if(decay[iscal]->dataPtr()->charged()) { if (outgoingVertex1_[inter] && outgoingVertex1_[inter]->isIncoming(const_ptr_cast(decay[iscal]->dataPtr()))) outgoingVertexS = outgoingVertex1_[inter]; else outgoingVertexS = outgoingVertex2_[inter]; } if(decay[ianti]->dataPtr()->charged()) { if (outgoingVertex1_[inter] && outgoingVertex1_[inter]->isIncoming(const_ptr_cast(decay[ianti]->dataPtr()))) outgoingVertexA = outgoingVertex1_[inter]; else outgoingVertexA = outgoingVertex2_[inter]; } } } diff --git a/Decay/General/VSSDecayer.h b/Decay/General/VSSDecayer.h --- a/Decay/General/VSSDecayer.h +++ b/Decay/General/VSSDecayer.h @@ -1,203 +1,211 @@ // -*- C++ -*- // // VSSDecayer.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_VSSDecayer_H #define HERWIG_VSSDecayer_H // // This is the declaration of the VSSDecayer class. // #include "GeneralTwoBodyDecayer.h" #include "ThePEG/Helicity/Vertex/Scalar/VSSVertex.h" #include "ThePEG/Helicity/Vertex/Vector/VVVVertex.h" #include "ThePEG/Repository/EventGenerator.h" namespace Herwig { using namespace ThePEG; using Helicity::VSSVertexPtr; /** \ingroup Decay * The VSSDecayer class implements the decay of a vector * to 2 scalars in a general model. It holds an VSSVertex pointer * that must be typecast from the VertexBase pointer held in * GeneralTwoBodyDecayer. It implents the virtual functions me2() and * partialWidth(). * * @see GeneralTwoBodyDecayer */ class VSSDecayer: public GeneralTwoBodyDecayer { public: /** * The default constructor. */ VSSDecayer() {} /** @name Virtual functions required by the Decayer class. */ //@{ /** * Return the matrix element squared for a given mode and phase-space channel * @param ichan The channel we are calculating the matrix element for. * @param part The decaying Particle. * @param decay The particles produced in the decay. * @param meopt Option for the matrix element * @return The matrix element squared for the phase-space configuration. */ virtual double me2(const int ichan, const Particle & part, const ParticleVector & decay, MEOption meopt) const; /** * Function to return partial Width * @param inpart The decaying particle. * @param outa One of the decay products. * @param outb The other decay product. */ virtual Energy partialWidth(PMPair inpart, PMPair outa, PMPair outb) const; /** * Has a POWHEG style correction */ virtual POWHEGType hasPOWHEGCorrection() { - return (vertex_->orderInGem()+vertex_->orderInGs())==1 ? FSR : No; + POWHEGType output = FSR; + for(auto vertex : vertex_) { + if(vertex->orderInAllCouplings()!=1) { + output = No; + break; + } + } + return output; } /** * Three-body matrix element including additional QCD radiation */ virtual double threeBodyME(const int , const Particle & inpart, const ParticleVector & decay, ShowerInteraction inter, MEOption meopt); /** * Indentify outgoing vertices for the scalar and antiscalar */ void identifyVertices(const int iscal, const int ianti, const Particle & inpart, const ParticleVector & decay, AbstractVSSVertexPtr & abstractOutgoingVertexS, AbstractVSSVertexPtr & abstractOutgoingVertexA, ShowerInteraction inter); /** * Set the information on the decay */ - virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, VertexBasePtr, + virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, + vector, map &, const vector > &, map); //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ VSSDecayer & operator=(const VSSDecayer &); private: /** * Abstract pointer to AbstractVSSVertex */ - AbstractVSSVertexPtr vertex_; + vector vertex_; /** * Pointer to the perturbative vertex */ - VSSVertexPtr perturbativeVertex_; + vector perturbativeVertex_; /** * Abstract pointer to AbstractVVVVertex for QCD radiation from incoming vector */ map incomingVertex_; /** * Abstract pointer to AbstractFFVVertex for QCD radiation from outgoing scalar */ map outgoingVertex1_; /** * Abstract pointer to AbstractFFVVertex for QCD radiation from outgoing scalar */ map outgoingVertex2_; /** * Spin density matrix */ mutable RhoDMatrix rho_; /** * Polarization vectors for the decaying particle */ mutable vector vectors_; /** * Spin density matrix for 3 body decay */ mutable RhoDMatrix rho3_; /** * Vector wavefunction for 3 body decay */ mutable vector vector3_; /** * Vector wavefunction for 3 body decay */ mutable vector gluon_; }; } #endif /* HERWIG_VSSDecayer_H */ diff --git a/Decay/General/VVSDecayer.cc b/Decay/General/VVSDecayer.cc --- a/Decay/General/VVSDecayer.cc +++ b/Decay/General/VVSDecayer.cc @@ -1,302 +1,313 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the VVSDecayer class. // #include "VVSDecayer.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/Decay/GeneralDecayMatrixElement.h" using namespace Herwig; using namespace ThePEG::Helicity; IBPtr VVSDecayer::clone() const { return new_ptr(*this); } IBPtr VVSDecayer::fullclone() const { return new_ptr(*this); } void VVSDecayer::setDecayInfo(PDPtr incoming, PDPair outgoing, - VertexBasePtr vertex, + vector vertex, map & inV, const vector > & outV, map) { decayInfo(incoming,outgoing); - vertex_ = dynamic_ptr_cast(vertex); - perturbativeVertex_ = dynamic_ptr_cast (vertex); + for(auto vert : vertex) { + vertex_ .push_back(dynamic_ptr_cast(vert)); + perturbativeVertex_.push_back(dynamic_ptr_cast (vert)); + } vector itemp={ShowerInteraction::QCD,ShowerInteraction::QED}; for(auto & inter : itemp) { incomingVertex_[inter] = dynamic_ptr_cast(inV.at(inter)); outgoingVertexS_[inter] = AbstractVSSVertexPtr(); outgoingVertexV_[inter] = AbstractVVVVertexPtr(); if(outV[0].at(inter)) { if (outV[0].at(inter)->getName()==VertexType::VSS) outgoingVertexS_[inter] = dynamic_ptr_cast(outV[0].at(inter)); else outgoingVertexV_[inter] = dynamic_ptr_cast(outV[0].at(inter)); } if(outV[1].at(inter)) { if (outV[1].at(inter)->getName()==VertexType::VSS) outgoingVertexS_[inter] = dynamic_ptr_cast(outV[1].at(inter)); else outgoingVertexV_[inter] = dynamic_ptr_cast(outV[1].at(inter)); } } } void VVSDecayer::persistentOutput(PersistentOStream & os) const { os << vertex_ << perturbativeVertex_ << incomingVertex_ << outgoingVertexS_ << outgoingVertexV_; } void VVSDecayer::persistentInput(PersistentIStream & is, int) { is >> vertex_ >> perturbativeVertex_ >> incomingVertex_ >> outgoingVertexS_ >> outgoingVertexV_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigVVSDecayer("Herwig::VVSDecayer", "Herwig.so"); void VVSDecayer::Init() { static ClassDocumentation documentation ("The VVSDecayer class implements the decay of a vector" " to a vector and a scalar"); } double VVSDecayer::me2(const int , const Particle & inpart, const ParticleVector & decay, MEOption meopt) const { bool massless = ( decay[0]->id()==ParticleID::gamma || decay[0]->id()==ParticleID::g ); if(!ME()) ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin1,PDT::Spin1,PDT::Spin0))); if(meopt==Initialize) { VectorWaveFunction::calculateWaveFunctions(vectors_[0],rho_, const_ptr_cast(&inpart), incoming,false); } if(meopt==Terminate) { VectorWaveFunction::constructSpinInfo(vectors_[0],const_ptr_cast(&inpart), incoming,true,false); VectorWaveFunction:: constructSpinInfo(vectors_[1],decay[0],outgoing,true,massless); ScalarWaveFunction:: constructSpinInfo(decay[1],outgoing,true); return 0.; } VectorWaveFunction:: calculateWaveFunctions(vectors_[1],decay[0],outgoing,massless); ScalarWaveFunction sca(decay[1]->momentum(),decay[1]->dataPtr(),outgoing); Energy2 scale(sqr(inpart.mass())); for(unsigned int in=0;in<3;++in) { for(unsigned int out=0;out<3;++out) { if(massless&&out==1) ++out; - (*ME())(in,out,0) = - vertex_->evaluate(scale,vectors_[0][in],vectors_[1][out],sca); + (*ME())(in,out,0) = 0.; + for(auto vert : vertex_) + (*ME())(in,out,0) += + vert->evaluate(scale,vectors_[0][in],vectors_[1][out],sca); } } double output=(ME()->contract(rho_)).real()/scale*UnitRemoval::E2; // colour and identical particle factors output *= colourFactor(inpart.dataPtr(),decay[0]->dataPtr(), decay[1]->dataPtr()); // return the answer return output; } Energy VVSDecayer::partialWidth(PMPair inpart, PMPair outa, PMPair outb) const { if( inpart.second < outa.second + outb.second ) return ZERO; - if(perturbativeVertex_) { + if(perturbativeVertex_.size()==1 && + perturbativeVertex_[0]) { Energy2 scale(sqr(inpart.second)); double mu1sq = sqr(outa.second/inpart.second); double mu2sq = sqr(outb.second/inpart.second); tcPDPtr in = inpart.first->CC() ? tcPDPtr(inpart.first->CC()) : inpart.first; if( outb.first->iSpin() == PDT::Spin0 ) - perturbativeVertex_->setCoupling(sqr(inpart.second), in, + perturbativeVertex_[0]->setCoupling(sqr(inpart.second), in, outa.first, outb.first); else { - perturbativeVertex_->setCoupling(sqr(inpart.second), in, + perturbativeVertex_[0]->setCoupling(sqr(inpart.second), in, outb.first, outa.first); swap(mu1sq, mu2sq); } - double vn = norm(perturbativeVertex_->norm()); + double vn = norm(perturbativeVertex_[0]->norm()); if(vn == ZERO || mu1sq == ZERO) return ZERO; double me2 = 2. + 0.25*sqr(1. + mu1sq - mu2sq)/mu1sq; Energy pcm = Kinematics::pstarTwoBodyDecay(inpart.second,outa.second, outb.second); Energy output = vn*me2*pcm/(24.*Constants::pi)/scale*UnitRemoval::E2; // colour factor output *= colourFactor(inpart.first,outa.first,outb.first); // return the answer return output; } else { return GeneralTwoBodyDecayer::partialWidth(inpart,outa,outb); } } double VVSDecayer::threeBodyME(const int , const Particle & inpart, const ParticleVector & decay, ShowerInteraction inter, MEOption meopt) { unsigned int ivec(0),isca(1); if(decay[ivec]->dataPtr()->iSpin()!=PDT::Spin1) swap(ivec,isca); if(meopt==Initialize) { // create vector wavefunction for decaying particle VectorWaveFunction::calculateWaveFunctions(vectors3_[0], rho3_, const_ptr_cast(&inpart), incoming, false); } if(meopt==Terminate) { VectorWaveFunction:: constructSpinInfo(vectors3_[0] ,const_ptr_cast(&inpart),outgoing,true,false); VectorWaveFunction:: constructSpinInfo(vectors3_[1],decay[ivec],outgoing,true,false); ScalarWaveFunction:: constructSpinInfo(decay[isca],outgoing,true); VectorWaveFunction:: constructSpinInfo(gluon_ ,decay[2],outgoing,true,false); return 0.; } // calculate colour factors and number of colour flows unsigned int nflow; vector cfactors = getColourFactors(inpart, decay, nflow); vector ME(nflow,new_ptr(GeneralDecayMatrixElement(PDT::Spin1, PDT::Spin1, PDT::Spin0, PDT::Spin1))); bool massless= decay[ivec]->mass()!=ZERO; // create wavefunctions VectorWaveFunction::calculateWaveFunctions(vectors3_[1],decay[0],outgoing,massless); ScalarWaveFunction scal(decay[isca]->momentum(), decay[isca]->dataPtr(),outgoing); VectorWaveFunction::calculateWaveFunctions(gluon_ ,decay[2],outgoing,true); // gauge test #ifdef GAUGE_CHECK gluon_.clear(); for(unsigned int ix=0;ix<3;++ix) { if(ix==1) gluon_.push_back(VectorWaveFunction()); else { gluon_.push_back(VectorWaveFunction(decay[2]->momentum(), decay[2]->dataPtr(),10, outgoing)); } } #endif Energy2 scale(sqr(inpart.mass())); const GeneralTwoBodyDecayer::CFlow & colourFlow = colourFlows(inpart, decay); double gs(0.); bool couplingSet(false); #ifdef GAUGE_CHECK double total=0.; #endif for(unsigned int iv0 = 0; iv0 < 3; ++iv0) { for(unsigned int iv1 = 0; iv1 < 3; ++iv1) { if(massless && iv1==1) continue; for(unsigned int ig = 0; ig < 2; ++ig) { // radiation from the incoming vector if((inpart.dataPtr()->coloured() && inter==ShowerInteraction::QCD) || (inpart.dataPtr()->charged() && inter==ShowerInteraction::QED) ) { assert(incomingVertex_[inter]); VectorWaveFunction vectorInter = incomingVertex_[inter]->evaluate(scale,3,inpart.dataPtr(),vectors3_[0][iv0], gluon_[2*ig],inpart.mass()); assert(vectors3_[0][iv0].particle()->id()==vectorInter.particle()->id()); - Complex diag = vertex_->evaluate(scale,vectorInter,vectors3_[1][iv1],scal); + Complex diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,vectorInter,vectors3_[1][iv1],scal); if(!couplingSet) { gs = abs(incomingVertex_[inter]->norm()); couplingSet = true; } for(unsigned int ix=0;ixdataPtr()->coloured() && inter==ShowerInteraction::QCD) || (decay[ivec]->dataPtr()->charged() && inter==ShowerInteraction::QED) ) { assert(outgoingVertexV_[inter]); // ensure you get correct outgoing particle from first vertex tcPDPtr off = decay[ivec]->dataPtr(); if(off->CC()) off = off->CC(); VectorWaveFunction vectorInter = outgoingVertexV_[inter]->evaluate(scale,3,off,gluon_[2*ig],vectors3_[1][iv1],decay[ivec]->mass()); assert(vectors3_[1][iv1].particle()->id()==vectorInter.particle()->id()); - Complex diag =vertex_->evaluate(scale,vectors3_[0][iv0],vectorInter,scal); + Complex diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,vectors3_[0][iv0],vectorInter,scal); if(!couplingSet) { gs = abs(outgoingVertexV_[inter]->norm()); couplingSet = true; } for(unsigned int ix=0;ixdataPtr()->coloured() && inter==ShowerInteraction::QCD) || (decay[isca]->dataPtr()->charged() && inter==ShowerInteraction::QED) ) { assert(outgoingVertexS_[inter]); // ensure you get correct outgoing particle from first vertex tcPDPtr off = decay[isca]->dataPtr(); if(off->CC()) off = off->CC(); ScalarWaveFunction scalarInter = outgoingVertexS_[inter]->evaluate(scale,3,off,gluon_[2*ig],scal,decay[isca]->mass()); assert(scal.particle()->id()==scalarInter.particle()->id()); - Complex diag = vertex_->evaluate(scale,vectors3_[0][iv0],vectors3_[1][iv1],scalarInter); + Complex diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,vectors3_[0][iv0],vectors3_[1][iv1],scalarInter); if(!couplingSet) { gs = abs(outgoingVertexS_[inter]->norm()); couplingSet = true; } for(unsigned int ix=0;ixcontract(*ME[iy],rho3_)).real(); } } // divide by alpha_(S,EM) output*=(4.*Constants::pi)/sqr(gs); #ifdef GAUGE_CHECK double ratio = output/total; if(abs(ratio)>1e-20) { generator()->log() << "Test of gauge invariance in decay\n" << inpart << "\n"; for(unsigned int ix=0;ixlog() << *decay[ix] << "\n"; generator()->log() << "Test of gauge invariance " << ratio << "\n"; } #endif // return the answer return output; } diff --git a/Decay/General/VVSDecayer.h b/Decay/General/VVSDecayer.h --- a/Decay/General/VVSDecayer.h +++ b/Decay/General/VVSDecayer.h @@ -1,193 +1,201 @@ // -*- C++ -*- #ifndef THEPEG_VVSDecayer_H #define THEPEG_VVSDecayer_H // // This is the declaration of the VVSDecayer class. // #include "GeneralTwoBodyDecayer.h" #include "ThePEG/Helicity/Vertex/Scalar/VVSVertex.h" #include "ThePEG/Repository/EventGenerator.h" namespace Herwig { using namespace ThePEG; using Helicity::VVSVertexPtr; /** \ingroup Decay * The VVSDecayer class implements the decay of a vector to a * vector and a scalar in a general model. It holds an VVSVertex pointer * that must be typecast from the VertexBase pointer helid in the * GeneralTwoBodyDecayer. It implents the virtual functions me2() and * partialWidth(). * * @see \ref VVSDecayerInterfaces "The interfaces" * defined for VVSDecayer. */ class VVSDecayer: public GeneralTwoBodyDecayer { public: /** * The default constructor. */ VVSDecayer() {} /** @name Virtual functions required by the Decayer class. */ //@{ /** * Return the matrix element squared for a given mode and phase-space channel * @param ichan The channel we are calculating the matrix element for. * @param part The decaying Particle. * @param decay The particles produced in the decay. * @param meopt Option for the calculation of the matrix element * @return The matrix element squared for the phase-space configuration. */ virtual double me2(const int ichan, const Particle & part, const ParticleVector & decay, MEOption meopt) const; /** * Function to return partial Width * @param inpart The decaying particle. * @param outa One of the decay products. * @param outb The other decay product. */ virtual Energy partialWidth(PMPair inpart, PMPair outa, PMPair outb) const; /** * Set the information on the decay */ - virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, VertexBasePtr, + virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, + vector, map &, const vector > &, map); /** * Has a POWHEG style correction */ virtual POWHEGType hasPOWHEGCorrection() { - return (vertex_->orderInGem()+vertex_->orderInGs())==1 ? FSR : No; + POWHEGType output = FSR; + for(auto vertex : vertex_) { + if(vertex->orderInAllCouplings()!=1) { + output = No; + break; + } + } + return output; } /** * Three-body matrix element including additional QCD radiation */ virtual double threeBodyME(const int , const Particle & inpart, const ParticleVector & decay, ShowerInteraction inter, MEOption meopt); //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ VVSDecayer & operator=(const VVSDecayer &); private: /** * Abstract pointer to AbstractVVSVertex */ - AbstractVVSVertexPtr vertex_; + vector vertex_; /** * Pointer to the perturbative vertex */ - VVSVertexPtr perturbativeVertex_; + vector perturbativeVertex_; /** * Abstract pointer to AbstractVVVVertex for QCD radiation from incoming vector */ map incomingVertex_; /** * Abstract pointer to AbstractVVVVertex for QCD radiation from the first outgoing vector */ map outgoingVertexV_; /** * Abstract pointer to AbstractVVVVertex for QCD radiation from the second outgoing vector */ map outgoingVertexS_; /** * Spin density matrix */ mutable RhoDMatrix rho_; /** * Vector wavefunctions */ mutable vector vectors_[2]; private: /** * Members for the POWHEG correction */ //@{ /** * Spin density matrix for 3 body decay */ mutable RhoDMatrix rho3_; /** * Vector wavefunctions */ mutable vector vectors3_[2]; /** * Vector wavefunction for 3 body decay */ mutable vector gluon_; //@} }; } #endif /* THEPEG_VVSDecayer_H */ diff --git a/Decay/General/VVVDecayer.cc b/Decay/General/VVVDecayer.cc --- a/Decay/General/VVVDecayer.cc +++ b/Decay/General/VVVDecayer.cc @@ -1,429 +1,441 @@ // -*- C++ -*- // // VVVDecayer.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 VVVDecayer class. // #include "VVVDecayer.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "Herwig/Utilities/Kinematics.h" #include "Herwig/Decay/GeneralDecayMatrixElement.h" using namespace Herwig; using namespace ThePEG::Helicity; IBPtr VVVDecayer::clone() const { return new_ptr(*this); } IBPtr VVVDecayer::fullclone() const { return new_ptr(*this); } void VVVDecayer::setDecayInfo(PDPtr incoming, PDPair outgoing, - VertexBasePtr vertex, + vector vertex, map & inV, const vector > & outV, map fourV) { decayInfo(incoming,outgoing); - vertex_ = dynamic_ptr_cast(vertex); - perturbativeVertex_ = dynamic_ptr_cast (vertex); + for(auto vert : vertex) { + vertex_ .push_back(dynamic_ptr_cast(vert)); + perturbativeVertex_ .push_back(dynamic_ptr_cast (vert)); + } vector itemp={ShowerInteraction::QCD,ShowerInteraction::QED}; for(auto & inter : itemp) { incomingVertex_[inter] = dynamic_ptr_cast(inV.at(inter)); outgoingVertex1_[inter] = dynamic_ptr_cast(outV[0].at(inter)); outgoingVertex2_[inter] = dynamic_ptr_cast(outV[1].at(inter)); fourPointVertex_[inter] = dynamic_ptr_cast(fourV.at(inter)); } } void VVVDecayer::persistentOutput(PersistentOStream & os) const { os << vertex_ << perturbativeVertex_ << incomingVertex_ << outgoingVertex1_ << outgoingVertex2_ << fourPointVertex_; } void VVVDecayer::persistentInput(PersistentIStream & is, int) { is >> vertex_ >> perturbativeVertex_ >> incomingVertex_ >> outgoingVertex1_ >> outgoingVertex2_ >> fourPointVertex_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigVVVDecayer("Herwig::VVVDecayer", "Herwig.so"); void VVVDecayer::Init() { static ClassDocumentation documentation ("The VVVDecayer class implements the decay of a vector boson " "into 2 vector bosons"); } double VVVDecayer::me2(const int , const Particle & inpart, const ParticleVector & decay, MEOption meopt) const { if(!ME()) ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin1,PDT::Spin1,PDT::Spin1))); bool massless[2]; for(unsigned int ix=0;ix<2;++ix) massless[ix] = (decay[ix]->id()==ParticleID::gamma || decay[ix]->id()==ParticleID::g); if(meopt==Initialize) { VectorWaveFunction::calculateWaveFunctions(vectors_[0],rho_, const_ptr_cast(&inpart), incoming,false); } if(meopt==Terminate) { VectorWaveFunction::constructSpinInfo(vectors_[0],const_ptr_cast(&inpart), incoming,true,false); for(unsigned int ix=0;ix<2;++ix) VectorWaveFunction:: constructSpinInfo(vectors_[ix+1],decay[ix],outgoing,true,massless[ix]); return 0.; } for(unsigned int ix=0;ix<2;++ix) VectorWaveFunction:: calculateWaveFunctions(vectors_[ix+1],decay[ix],outgoing,massless[ix]); Energy2 scale(sqr(inpart.mass())); for(unsigned int iv3=0;iv3<3;++iv3) { for(unsigned int iv2=0;iv2<3;++iv2) { for(unsigned int iv1=0;iv1<3;++iv1) { - (*ME())(iv1,iv2,iv3) = vertex_-> - evaluate(scale,vectors_[1][iv2],vectors_[2][iv3],vectors_[0][iv1]); + (*ME())(iv1,iv2,iv3) = 0.; + for(auto vert : vertex_) { + (*ME())(iv1,iv2,iv3) += vert-> + evaluate(scale,vectors_[1][iv2],vectors_[2][iv3],vectors_[0][iv1]); + } } } } double output = (ME()->contract(rho_)).real()/scale*UnitRemoval::E2; // colour and identical particle factors output *= colourFactor(inpart.dataPtr(),decay[0]->dataPtr(), decay[1]->dataPtr()); // return the answer return output; } Energy VVVDecayer::partialWidth(PMPair inpart, PMPair outa, PMPair outb) const { if( inpart.second < outa.second + outb.second ) return ZERO; - if(perturbativeVertex_) { + if(perturbativeVertex_.size()==1 && + perturbativeVertex_[0]) { tcPDPtr in = inpart.first->CC() ? tcPDPtr(inpart.first->CC()) : inpart.first; - perturbativeVertex_->setCoupling(sqr(inpart.second), in, - outa.first, outb.first); + perturbativeVertex_[0]->setCoupling(sqr(inpart.second), in, + outa.first, outb.first); double mu1(outa.second/inpart.second), mu1sq(sqr(mu1)), mu2(outb.second/inpart.second), mu2sq(sqr(mu2)); - double vn = norm(perturbativeVertex_->norm()); + double vn = norm(perturbativeVertex_[0]->norm()); if(vn == ZERO || mu1sq == ZERO || mu2sq == ZERO) return ZERO; double me2 = (mu1 - mu2 - 1.)*(mu1 - mu2 + 1.)*(mu1 + mu2 - 1.)*(mu1 + mu2 + 1.) * (sqr(mu1sq) + sqr(mu2sq) + 10.*(mu1sq*mu2sq + mu1sq + mu2sq) + 1.) /4./mu1sq/mu2sq; Energy pcm = Kinematics::pstarTwoBodyDecay(inpart.second,outa.second, outb.second); Energy pWidth = vn*me2*pcm/24./Constants::pi; // colour factor pWidth *= colourFactor(inpart.first,outa.first,outb.first); // return the answer return pWidth; } else { return GeneralTwoBodyDecayer::partialWidth(inpart,outa,outb); } } double VVVDecayer::threeBodyME(const int , const Particle & inpart, const ParticleVector & decay, ShowerInteraction inter, MEOption meopt) { if(meopt==Initialize) { // create vector wavefunction for decaying particle VectorWaveFunction::calculateWaveFunctions(vector3_, rho3_, const_ptr_cast(&inpart), incoming, false); } if(meopt==Terminate) { VectorWaveFunction:: constructSpinInfo(vector3_ ,const_ptr_cast(&inpart),outgoing,true,false); VectorWaveFunction:: constructSpinInfo(vectors3_[0],decay[0],outgoing,true,false); VectorWaveFunction:: constructSpinInfo(vectors3_[1],decay[1],outgoing,true,false); VectorWaveFunction:: constructSpinInfo(gluon_ ,decay[2],outgoing,true,false); return 0.; } // calculate colour factors and number of colour flows unsigned int nflow; vector cfactors = getColourFactors(inpart, decay, nflow); vector ME(nflow,new_ptr(GeneralDecayMatrixElement(PDT::Spin1, PDT::Spin1, PDT::Spin1, PDT::Spin1))); bool massless[2]; for(unsigned int ix=0;ix<2;++ix) massless[ix] = decay[ix]->mass()!=ZERO; // create wavefunctions VectorWaveFunction::calculateWaveFunctions(vectors3_[0],decay[0],outgoing,massless[0]); VectorWaveFunction::calculateWaveFunctions(vectors3_[1],decay[1],outgoing,massless[1]); VectorWaveFunction::calculateWaveFunctions(gluon_ ,decay[2],outgoing,true); // gauge test #ifdef GAUGE_CHECK gluon_.clear(); for(unsigned int ix=0;ix<3;++ix) { if(ix==1) gluon_.push_back(VectorWaveFunction()); else { gluon_.push_back(VectorWaveFunction(decay[2]->momentum(), decay[2]->dataPtr(),10, outgoing)); } } #endif // get the outgoing vertices AbstractVVVVertexPtr outgoingVertex1; AbstractVVVVertexPtr outgoingVertex2; identifyVertices(inpart,decay, outgoingVertex1, outgoingVertex2,inter); Energy2 scale(sqr(inpart.mass())); const GeneralTwoBodyDecayer::CFlow & colourFlow = colourFlows(inpart, decay); double gs(0.); bool couplingSet(false); #ifdef GAUGE_CHECK double total=0.; #endif for(unsigned int iv0 = 0; iv0 < 3; ++iv0) { for(unsigned int iv1 = 0; iv1 < 3; ++iv1) { if(massless[0] && iv1==1) continue; for(unsigned int iv2 = 0; iv2 < 3; ++iv2) { if(massless[1] && iv2==1) continue; for(unsigned int ig = 0; ig < 2; ++ig) { // radiation from the incoming vector if((inpart.dataPtr()->coloured() && inter==ShowerInteraction::QCD) || (inpart.dataPtr()->charged() && inter==ShowerInteraction::QED) ) { assert(incomingVertex_[inter]); VectorWaveFunction vectorInter = incomingVertex_[inter]->evaluate(scale,3,inpart.dataPtr(),vector3_[iv0], gluon_[2*ig],inpart.mass()); assert(vector3_[iv0].particle()->id()==vectorInter.particle()->id()); - Complex diag = vertex_->evaluate(scale,vectorInter,vectors3_[0][iv1], - vectors3_[1][iv2]); + Complex diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,vectorInter,vectors3_[0][iv1], + vectors3_[1][iv2]); if(!couplingSet) { gs = abs(incomingVertex_[inter]->norm()); couplingSet = true; } for(unsigned int ix=0;ixdataPtr()->coloured() && inter==ShowerInteraction::QCD) || (decay[0]->dataPtr()->charged() && inter==ShowerInteraction::QED) ) { assert(outgoingVertex1); // ensure you get correct outgoing particle from first vertex tcPDPtr off = decay[0]->dataPtr(); if(off->CC()) off = off->CC(); VectorWaveFunction vectorInter = outgoingVertex1->evaluate(scale,3,off,gluon_[2*ig],vectors3_[0][iv1],decay[0]->mass()); assert(vectors3_[0][iv1].particle()->id()==vectorInter.particle()->id()); - Complex diag =vertex_->evaluate(scale,vector3_[iv0],vectorInter,vectors3_[1][iv2]); + Complex diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,vector3_[iv0],vectorInter,vectors3_[1][iv2]); if(!couplingSet) { gs = abs(outgoingVertex1->norm()); couplingSet = true; } for(unsigned int ix=0;ixdataPtr()->coloured() && inter==ShowerInteraction::QCD) || (decay[1]->dataPtr()->charged() && inter==ShowerInteraction::QED) ) { assert(outgoingVertex2); // ensure you get correct outgoing particle from first vertex tcPDPtr off = decay[1]->dataPtr(); if(off->CC()) off = off->CC(); VectorWaveFunction vectorInter = outgoingVertex2->evaluate(scale,3,off, gluon_[2*ig],vectors3_[1][iv2],decay[1]->mass()); assert(vectors3_[1][iv2].particle()->id()==vectorInter.particle()->id()); - Complex diag = vertex_->evaluate(scale,vector3_[iv0],vectors3_[0][iv1],vectorInter); + Complex diag = 0.; + for(auto vertex : vertex_) + diag += vertex->evaluate(scale,vector3_[iv0],vectors3_[0][iv1],vectorInter); if(!couplingSet) { gs = abs(outgoingVertex2->norm()); couplingSet = true; } for(unsigned int ix=0;ixevaluate(scale,0, vector3_[iv0], vectors3_[0][iv1], vectors3_[1][iv2],gluon_[2*ig]); for(unsigned int ix=0;ixcontract(*ME[iy],rho3_)).real(); } } // divide by alpha_(S,EM) output*=(4.*Constants::pi)/sqr(gs); #ifdef GAUGE_CHECK double ratio = output/total; if(abs(ratio)>1e-20) { generator()->log() << "Test of gauge invariance in decay\n" << inpart << "\n"; for(unsigned int ix=0;ixlog() << *decay[ix] << "\n"; generator()->log() << "Test of gauge invariance " << ratio << "\n"; } #endif // return the answer return output; } void VVVDecayer::identifyVertices(const Particle & inpart, const ParticleVector & decay, AbstractVVVVertexPtr & outgoingVertex1, AbstractVVVVertexPtr & outgoingVertex2, ShowerInteraction inter) { if(inter==ShowerInteraction::QCD) { // work out which scalar each outgoing vertex corresponds to // two outgoing vertices if( inpart.dataPtr() ->iColour()==PDT::Colour0 && ((decay[0]->dataPtr()->iColour()==PDT::Colour3 && decay[1]->dataPtr()->iColour()==PDT::Colour3bar) || (decay[0]->dataPtr()->iColour()==PDT::Colour8 && decay[1]->dataPtr()->iColour()==PDT::Colour8))){ if(outgoingVertex1_[inter]==outgoingVertex2_[inter]){ outgoingVertex1 = outgoingVertex1_[inter]; outgoingVertex2 = outgoingVertex2_[inter]; } else if (outgoingVertex1_[inter]->isIncoming(getParticleData(decay[0]->id()))){ outgoingVertex1 = outgoingVertex1_[inter]; outgoingVertex2 = outgoingVertex2_[inter]; } else if (outgoingVertex2_[inter]->isIncoming(getParticleData(decay[0]->id()))){ outgoingVertex1 = outgoingVertex2_[inter]; outgoingVertex2 = outgoingVertex1_[inter]; } } else if(inpart.dataPtr() ->iColour()==PDT::Colour8 && decay[0]->dataPtr()->iColour()==PDT::Colour3 && decay[1]->dataPtr()->iColour()==PDT::Colour3bar){ if(outgoingVertex1_[inter]==outgoingVertex2_[inter]){ outgoingVertex1 = outgoingVertex1_[inter]; outgoingVertex2 = outgoingVertex2_[inter]; } else if (outgoingVertex1_[inter]->isIncoming(getParticleData(decay[0]->id()))){ outgoingVertex1 = outgoingVertex1_[inter]; outgoingVertex2 = outgoingVertex2_[inter]; } else if (outgoingVertex2_[inter]->isIncoming(getParticleData(decay[0]->id()))){ outgoingVertex1 = outgoingVertex2_[inter]; outgoingVertex2 = outgoingVertex1_[inter]; } } // one outgoing vertex else if(inpart.dataPtr()->iColour()==PDT::Colour3){ if(decay[0]->dataPtr()->iColour()==PDT::Colour3 && decay[1]->dataPtr()->iColour()==PDT::Colour0){ if (outgoingVertex1_[inter]) outgoingVertex1 = outgoingVertex1_[inter]; else if(outgoingVertex2_[inter]) outgoingVertex1 = outgoingVertex2_[inter]; } else if (decay[0]->dataPtr()->iColour()==PDT::Colour3 && decay[1]->dataPtr()->iColour()==PDT::Colour8){ if (outgoingVertex1_[inter]->isIncoming(getParticleData(decay[1]->dataPtr()->id()))){ outgoingVertex1 = outgoingVertex2_[inter]; outgoingVertex2 = outgoingVertex1_[inter]; } else { outgoingVertex1 = outgoingVertex1_[inter]; outgoingVertex2 = outgoingVertex2_[inter]; } } } else if(inpart.dataPtr()->iColour()==PDT::Colour3bar){ if(decay[1]->dataPtr()->iColour()==PDT::Colour3bar && decay[0]->dataPtr()->iColour()==PDT::Colour0){ if (outgoingVertex1_[inter]) outgoingVertex2 = outgoingVertex1_[inter]; else if(outgoingVertex2_[inter]) outgoingVertex2 = outgoingVertex2_[inter]; } else if (decay[0]->dataPtr()->iColour()==PDT::Colour8 && decay[1]->dataPtr()->iColour()==PDT::Colour3bar){ if (outgoingVertex1_[inter]->isIncoming(getParticleData(decay[0]->dataPtr()->id()))){ outgoingVertex1 = outgoingVertex1_[inter]; outgoingVertex2 = outgoingVertex2_[inter]; } else { outgoingVertex1 = outgoingVertex2_[inter]; outgoingVertex2 = outgoingVertex1_[inter]; } } } if (! ((incomingVertex_[inter] && (outgoingVertex1 || outgoingVertex2)) || ( outgoingVertex1 && outgoingVertex2))) throw Exception() << "Invalid vertices for QCD radiation in VVV decay in VVVDecayer::identifyVertices" << Exception::runerror; } else { if(decay[0]->dataPtr()->charged()) { if (outgoingVertex1_[inter] && outgoingVertex1_[inter]->isIncoming(const_ptr_cast(decay[0]->dataPtr()))) outgoingVertex1 = outgoingVertex1_[inter]; else outgoingVertex1 = outgoingVertex2_[inter]; } if(decay[1]->dataPtr()->charged()) { if (outgoingVertex1_[inter] && outgoingVertex1_[inter]->isIncoming(const_ptr_cast(decay[1]->dataPtr()))) outgoingVertex2 = outgoingVertex1_[inter]; else outgoingVertex2 = outgoingVertex2_[inter]; } } } diff --git a/Decay/General/VVVDecayer.h b/Decay/General/VVVDecayer.h --- a/Decay/General/VVVDecayer.h +++ b/Decay/General/VVVDecayer.h @@ -1,220 +1,228 @@ // -*- C++ -*- // // VVVDecayer.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_VVVDecayer_H #define HERWIG_VVVDecayer_H // // This is the declaration of the VVVDecayer class. // #include "GeneralTwoBodyDecayer.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Helicity/Vertex/Vector/VVVVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVVVVVertex.h" namespace Herwig { using namespace ThePEG; using Helicity::VVVVertexPtr; /** \ingroup Decay * The VVVDecayer class implements the decay of a vector * to 2 vectors in a general model. It holds an VVVVertex pointer * that must be typecast from the VertexBase pointer held in * GeneralTwoBodyDecayer. It implents the virtual functions me2() and * partialWidth(). * * @see GeneralTwoBodyDecayer */ class VVVDecayer: public GeneralTwoBodyDecayer { public: /** * The default constructor. */ VVVDecayer() {} /** @name Virtual functions required by the Decayer class. */ //@{ /** * Return the matrix element squared for a given mode and phase-space channel. * @param ichan The channel we are calculating the matrix element for. * @param part The decaying Particle. * @param decay The particles produced in the decay. * @param meopt Option for the calculation of the matrix element * @return The matrix element squared for the phase-space configuration. */ virtual double me2(const int ichan, const Particle & part, const ParticleVector & decay, MEOption meopt) const; /** * Function to return partial Width * @param inpart The decaying particle. * @param outa One of the decay products. * @param outb The other decay product. */ virtual Energy partialWidth(PMPair inpart, PMPair outa, PMPair outb) const; /** * Set the information on the decay */ - virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, VertexBasePtr, + virtual void setDecayInfo(PDPtr incoming, PDPair outgoing, + vector, map &, const vector > &, map); /** * Has a POWHEG style correction */ virtual POWHEGType hasPOWHEGCorrection() { - return (vertex_->orderInGem()+vertex_->orderInGs())==1 ? FSR : No; + POWHEGType output = FSR; + for(auto vertex : vertex_) { + if(vertex->orderInAllCouplings()!=1) { + output = No; + break; + } + } + return output; } /** * Three-body matrix element including additional QCD radiation */ virtual double threeBodyME(const int , const Particle & inpart, const ParticleVector & decay, ShowerInteraction inter, MEOption meopt); //@} 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: /** * Find the vertices for the decay */ void identifyVertices(const Particle & inpart, const ParticleVector & decay, AbstractVVVVertexPtr & outgoingVertex1, AbstractVVVVertexPtr & outgoingVertex2, ShowerInteraction inter); private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ VVVDecayer & operator=(const VVVDecayer &); private: /** * Abstract pointer to AbstractVVVVertex */ - AbstractVVVVertexPtr vertex_; + vector vertex_; /** * Pointer to the perturbative vertex */ - VVVVertexPtr perturbativeVertex_; + vector perturbativeVertex_; /** * Abstract pointer to AbstractVVVVertex for QCD radiation from incoming vector */ map incomingVertex_; /** * Abstract pointer to AbstractVVVVertex for QCD radiation from the first outgoing vector */ map outgoingVertex1_; /** * Abstract pointer to AbstractVVVVertex for QCD radiation from the second outgoing vector */ map outgoingVertex2_; /** * Abstract pointer to AbstractVVVVertex for QCD radiation from the 4-point vertex */ map fourPointVertex_; /** * Spin density matrix */ mutable RhoDMatrix rho_; /** * Vector wavefunctions */ mutable vector vectors_[3]; private: /** * Members for the POWHEG correction */ //@{ /** * Spin density matrix for 3 body decay */ mutable RhoDMatrix rho3_; /** * Vector wavefunction for 3 body decay */ mutable vector vector3_; /** * Vector wavefunctions */ mutable vector vectors3_[2]; /** * Vector wavefunction for 3 body decay */ mutable vector gluon_; //@} }; } #endif /* HERWIG_VVVDecayer_H */ diff --git a/Decay/General/VtoFFVDecayer.cc b/Decay/General/VtoFFVDecayer.cc --- a/Decay/General/VtoFFVDecayer.cc +++ b/Decay/General/VtoFFVDecayer.cc @@ -1,368 +1,369 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the VtoFFVDecayer class. // #include "VtoFFVDecayer.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/PDT/ThreeBodyAllOnCalculator.h" #include "Herwig/Decay/GeneralDecayMatrixElement.h" #include using namespace Herwig; using namespace ThePEG; using namespace ThePEG::Helicity; IBPtr VtoFFVDecayer::clone() const { return new_ptr(*this); } IBPtr VtoFFVDecayer::fullclone() const { return new_ptr(*this); } void VtoFFVDecayer::persistentOutput(PersistentOStream & os) const { os << sca_ << fer_ << vec_ << ten_; } void VtoFFVDecayer::persistentInput(PersistentIStream & is, int) { is >> sca_ >> fer_ >> vec_ >> ten_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigVtoFFVDecayer("Herwig::VtoFFVDecayer", "Herwig.so"); void VtoFFVDecayer::Init() { static ClassDocumentation documentation ("The VtoFFVDecayer class implements the general three-body " "decay of a vector to a two fermions and a vector."); } WidthCalculatorBasePtr VtoFFVDecayer:: threeBodyMEIntegrator(const DecayMode & ) const { vector intype; vector inmass,inwidth; vector inpow,inweights; constructIntegratorChannels(intype,inmass,inwidth,inpow,inweights); return new_ptr(ThreeBodyAllOnCalculator (inweights,intype,inmass,inwidth,inpow,*this,0, outgoing()[0]->mass(),outgoing()[1]->mass(), outgoing()[2]->mass(),relativeError())); } void VtoFFVDecayer::doinit() { - GeneralThreeBodyDecayer::doinit(); + GeneralThreeBodyDecayer::doinit(); + if(outgoing().empty()) return; unsigned int ndiags = getProcessInfo().size(); sca_.resize(ndiags); fer_.resize(ndiags); vec_.resize(ndiags); ten_.resize(ndiags); for(unsigned int ix = 0;ix < ndiags; ++ix) { TBDiagram current = getProcessInfo()[ix]; tcPDPtr offshell = current.intermediate; if( offshell->CC() ) offshell = offshell->CC(); if(offshell->iSpin() == PDT::Spin0) { AbstractVVSVertexPtr vert1 = dynamic_ptr_cast (current.vertices.first); AbstractFFSVertexPtr vert2 = dynamic_ptr_cast (current.vertices.second); if(!vert1||!vert2) throw Exception() << "Invalid vertices for a scalar diagram in VtoFFVDecayer::doinit()" << Exception::runerror; sca_[ix] = make_pair(vert1, vert2); } else if(offshell->iSpin() == PDT::Spin1Half) { AbstractFFVVertexPtr vert1 = dynamic_ptr_cast (current.vertices.first); AbstractFFVVertexPtr vert2 = dynamic_ptr_cast (current.vertices.second); if(!vert1||!vert2) throw Exception() << "Invalid vertices for a fermion diagram in VtoFFVDecayer::doinit()" << Exception::runerror; fer_[ix] = make_pair(vert1, vert2); } else if(offshell->iSpin() == PDT::Spin1) { AbstractVVVVertexPtr vert1 = dynamic_ptr_cast (current.vertices.first); AbstractFFVVertexPtr vert2 = dynamic_ptr_cast (current.vertices.second); if(!vert1||!vert2) throw Exception() << "Invalid vertices for a vector diagram in VtoFFVDecayer::doinit()" << Exception::runerror; vec_[ix] = make_pair(vert1, vert2); } else if(offshell->iSpin() == PDT::Spin2) { AbstractVVTVertexPtr vert1 = dynamic_ptr_cast (current.vertices.first); AbstractFFTVertexPtr vert2 = dynamic_ptr_cast (current.vertices.second); if(!vert1||!vert2) throw Exception() << "Invalid vertices for a tensor diagram in VtoFFVDecayer::doinit()" << Exception::runerror; ten_[ix] = make_pair(vert1, vert2); } } } double VtoFFVDecayer::me2(const int ichan, const Particle & inpart, const ParticleVector & decay, MEOption meopt) const { // particle or CC of particle bool cc = (*getProcessInfo().begin()).incoming != inpart.id(); // special handling or first/last call if(meopt==Initialize) { VectorWaveFunction:: calculateWaveFunctions(inVector_,rho_,const_ptr_cast(&inpart), Helicity::incoming,false); } if(meopt==Terminate) { VectorWaveFunction:: constructSpinInfo(inVector_,const_ptr_cast(&inpart), Helicity::incoming,true,false); for(unsigned int ix=0;ixdataPtr()->iSpin()==PDT::Spin1) { VectorWaveFunction::constructSpinInfo(outVector_,decay[ix], Helicity::outgoing,true,false); } else { SpinorWaveFunction:: constructSpinInfo(outspin_[ix].first,decay[ix],Helicity::outgoing,true); } } } unsigned int ivec(0); bool massless = false; for(unsigned int ix = 0; ix < decay.size();++ix) { if(decay[ix]->dataPtr()->iSpin() == PDT::Spin1) { massless = decay[ix]->id()==ParticleID::g || decay[ix]->id()==ParticleID::gamma; ivec = ix; VectorWaveFunction:: calculateWaveFunctions(outVector_, decay[ix], Helicity::outgoing, massless ); } else { SpinorWaveFunction:: calculateWaveFunctions(outspin_[ix].first,decay[ix],Helicity::outgoing); outspin_[ix].second.resize(2); // Need a ubar and a v spinor if(outspin_[ix].first[0].wave().Type() == SpinorType::u) { for(unsigned int iy = 0; iy < 2; ++iy) { outspin_[ix].second[iy] = outspin_[ix].first[iy].bar(); outspin_[ix].first[iy].conjugate(); } } else { for(unsigned int iy = 0; iy < 2; ++iy) { outspin_[ix].second[iy] = outspin_[ix].first[iy].bar(); outspin_[ix].second[iy].conjugate(); } } } } const vector > cfactors(getColourFactors()); const vector > nfactors(getLargeNcColourFactors()); Energy2 scale(sqr(inpart.mass())); const size_t ncf(numberOfFlows()); vector flows(ncf, Complex(0.)), largeflows(ncf, Complex(0.)); // setup the DecayMatrixElement vector mes(ncf,new_ptr(GeneralDecayMatrixElement(PDT::Spin1, ivec == 0 ? PDT::Spin1 : PDT::Spin1Half, ivec == 1 ? PDT::Spin1 : PDT::Spin1Half, ivec == 2 ? PDT::Spin1 : PDT::Spin1Half))); vector mel(ncf,new_ptr(GeneralDecayMatrixElement(PDT::Spin1, ivec == 0 ? PDT::Spin1 : PDT::Spin1Half, ivec == 1 ? PDT::Spin1 : PDT::Spin1Half, ivec == 2 ? PDT::Spin1 : PDT::Spin1Half))); //the channel possiblities static const unsigned int out2[3] = {1,0,0}, out3[3] = {2,2,1}; for(unsigned int vi = 0; vi < 3; ++vi) { for(unsigned int s1 = 0; s1 < 2; ++s1) { for(unsigned int s2 = 0; s2 < 2; ++s2) { for(unsigned int v1 = 0; v1 < 3; ++v1) { if ( massless && v1 == 1 ) continue; flows = vector(ncf, Complex(0.)); largeflows = vector(ncf, Complex(0.)); unsigned int idiag(0); for(vector::const_iterator dit=getProcessInfo().begin(); dit!=getProcessInfo().end();++dit) { // channels if selecting if( ichan >=0 && diagramMap()[ichan] != idiag ) { ++idiag; continue; } tcPDPtr offshell = dit->intermediate; if(cc&&offshell->CC()) offshell=offshell->CC(); Complex diag; unsigned int o2(out2[dit->channelType]), o3(out3[dit->channelType]); double sign = (o3 < o2) ? 1. : -1.; // intermediate scalar if(offshell->iSpin() == PDT::Spin0) { ScalarWaveFunction inters = sca_[idiag].first-> evaluate(scale, widthOption(), offshell, outVector_[v1], inVector_[vi]); unsigned int h1(s1),h2(s2); if(o2 > o3) swap(h1, h2); if(decay[o2]->id() < 0 && decay[o3]->id() > 0) { diag = -sign*sca_[idiag].second-> evaluate(scale,outspin_[o2].first[h1], outspin_[o3].second[h2],inters); } else { diag = sign*sca_[idiag].second-> evaluate(scale, outspin_[o3].first [h2], outspin_[o2].second[h1],inters); } } // intermediate fermion else if(offshell->iSpin() == PDT::Spin1Half) { int iferm = (decay[o2]->dataPtr()->iSpin() == PDT::Spin1Half) ? o2 : o3; unsigned int h1(s1),h2(s2); if(dit->channelType > iferm) swap(h1, h2); sign = iferm < dit->channelType ? 1. : -1.; if(decay[dit->channelType]->id() < 0 && decay[iferm]->id() > 0 ) { SpinorWaveFunction inters = fer_[idiag].first-> evaluate(scale,widthOption(),offshell, outspin_[dit->channelType].first[h1], inVector_[vi]); diag = -sign*fer_[idiag].second-> evaluate(scale,inters,outspin_[iferm].second[h2], outVector_[v1]); } else { SpinorBarWaveFunction inters = fer_[idiag].first-> evaluate(scale,widthOption(),offshell, outspin_[dit->channelType].second[h1],inVector_[vi]); diag = sign*fer_[idiag].second-> evaluate(scale,outspin_[iferm].first [h2],inters, outVector_[v1]); } } // intermediate vector else if(offshell->iSpin() == PDT::Spin1) { VectorWaveFunction interv = vec_[idiag].first-> evaluate(scale, widthOption(), offshell, outVector_[v1], inVector_[vi]); unsigned int h1(s1),h2(s2); if(o2 > o3) swap(h1,h2); if(decay[o2]->id() < 0 && decay[o3]->id() > 0) { diag =-sign*vec_[idiag].second-> evaluate(scale, outspin_[o2].first[h1], outspin_[o3].second[h2], interv); } else { diag = sign*vec_[idiag].second-> evaluate(scale, outspin_[o3].first[h2], outspin_[o2].second[h1], interv); } } else if(offshell->iSpin() == PDT::Spin2) { TensorWaveFunction intert = ten_[idiag].first-> evaluate(scale, widthOption(), offshell, inVector_[vi], outVector_[v1]); unsigned int h1(s1),h2(s2); if(out2[dit->channelType]>out3[dit->channelType]) swap(h1,h2); if(decay[out2[dit->channelType]]->id()<0&& decay[out3[dit->channelType]]->id()>0) { diag =-sign*ten_[idiag].second-> evaluate(scale, outspin_[out2[dit->channelType]].first [h1], outspin_[out3[dit->channelType]].second[h2],intert); } else { diag = sign*ten_[idiag].second-> evaluate(scale, outspin_[out3[dit->channelType]].first [h2], outspin_[out2[dit->channelType]].second[h1],intert); } } // unknown else throw Exception() << "Unknown intermediate in VtoFFVDecayer::me2()" << Exception::runerror; // matrix element for the different colour flows if(ichan < 0) { for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) { flows[dit->colourFlow[iy].first - 1] += dit->colourFlow[iy].second * diag; } for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) { largeflows[dit->largeNcColourFlow[iy].first - 1] += dit->largeNcColourFlow[iy].second * diag; } } else { for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) { if(dit->colourFlow[iy].first - 1 != colourFlow()) continue; flows[dit->colourFlow[iy].first - 1] += dit->colourFlow[iy].second * diag; } for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) { if(dit->colourFlow[iy].first - 1!=colourFlow()) continue; largeflows[dit->largeNcColourFlow[iy].first - 1] += dit->largeNcColourFlow[iy].second * diag; } } ++idiag; } //end of diagrams // now add the flows to the me2 with appropriate colour factors for(unsigned int ix = 0; ix < ncf; ++ix) { if (ivec == 0) { (*mes[ix])(vi, v1, s1, s2) = flows[ix]; (*mel[ix])(vi, v1, s1, s2) = largeflows[ix]; } else if(ivec == 1) { (*mes[ix])(vi, s1, v1, s2) = flows[ix]; (*mel[ix])(vi, s1, v1, s2) = largeflows[ix]; } else if(ivec == 2) { (*mes[ix])(vi, s1, s2, v1) = flows[ix]; (*mel[ix])(vi, s1, s2, v1) = largeflows[ix]; } } } } } } double me2(0.); if(ichan < 0) { vector pflows(ncf,0.); for(unsigned int ix = 0; ix < ncf; ++ix) { for(unsigned int iy = 0; iy < ncf; ++ iy) { double con = cfactors[ix][iy]*(mes[ix]->contract(*mes[iy],rho_)).real(); me2 += con; if(ix == iy) { con = nfactors[ix][iy]*(mel[ix]->contract(*mel[iy],rho_)).real(); pflows[ix] += con; } } } double ptotal(std::accumulate(pflows.begin(),pflows.end(),0.)); ptotal *= UseRandom::rnd(); for(unsigned int ix = 0;ix < pflows.size(); ++ix) { if(ptotal <= pflows[ix]) { colourFlow(ix); ME(mes[ix]); break; } ptotal -= pflows[ix]; } } else { unsigned int iflow = colourFlow(); me2 = nfactors[iflow][iflow]*(mel[iflow]->contract(*mel[iflow],rho_)).real(); } // return the matrix element squared return me2; } diff --git a/Hadronization/ClusterHadronizationHandler.cc b/Hadronization/ClusterHadronizationHandler.cc --- a/Hadronization/ClusterHadronizationHandler.cc +++ b/Hadronization/ClusterHadronizationHandler.cc @@ -1,303 +1,307 @@ // -*- C++ -*- // // ClusterHadronizationHandler.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 ClusterHadronizationHandler class. // #include "ClusterHadronizationHandler.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "Herwig/Utilities/EnumParticles.h" #include "CluHadConfig.h" #include "Cluster.h" #include using namespace Herwig; ClusterHadronizationHandler * ClusterHadronizationHandler::currentHandler_ = 0; DescribeClass describeClusterHadronizationHandler("Herwig::ClusterHadronizationHandler",""); IBPtr ClusterHadronizationHandler::clone() const { return new_ptr(*this); } IBPtr ClusterHadronizationHandler::fullclone() const { return new_ptr(*this); } void ClusterHadronizationHandler::persistentOutput(PersistentOStream & os) const { os << _partonSplitter << _clusterFinder << _colourReconnector << _clusterFissioner << _lightClusterDecayer << _clusterDecayer << ounit(_minVirtuality2,GeV2) << ounit(_maxDisplacement,mm) << _underlyingEventHandler << _reduceToTwoComponents; } void ClusterHadronizationHandler::persistentInput(PersistentIStream & is, int) { is >> _partonSplitter >> _clusterFinder >> _colourReconnector >> _clusterFissioner >> _lightClusterDecayer >> _clusterDecayer >> iunit(_minVirtuality2,GeV2) >> iunit(_maxDisplacement,mm) >> _underlyingEventHandler >> _reduceToTwoComponents; } void ClusterHadronizationHandler::Init() { static ClassDocumentation documentation ("This is the main handler class for the Cluster Hadronization", "The hadronization was performed using the cluster model of \\cite{Webber:1983if}.", "%\\cite{Webber:1983if}\n" "\\bibitem{Webber:1983if}\n" " B.~R.~Webber,\n" " ``A QCD Model For Jet Fragmentation Including Soft Gluon Interference,''\n" " Nucl.\\ Phys.\\ B {\\bf 238}, 492 (1984).\n" " %%CITATION = NUPHA,B238,492;%%\n" // main manual ); static Reference interfacePartonSplitter("PartonSplitter", "A reference to the PartonSplitter object", &Herwig::ClusterHadronizationHandler::_partonSplitter, false, false, true, false); static Reference interfaceClusterFinder("ClusterFinder", "A reference to the ClusterFinder object", &Herwig::ClusterHadronizationHandler::_clusterFinder, false, false, true, false); static Reference interfaceColourReconnector("ColourReconnector", "A reference to the ColourReconnector object", &Herwig::ClusterHadronizationHandler::_colourReconnector, false, false, true, false); static Reference interfaceClusterFissioner("ClusterFissioner", "A reference to the ClusterFissioner object", &Herwig::ClusterHadronizationHandler::_clusterFissioner, false, false, true, false); static Reference interfaceLightClusterDecayer("LightClusterDecayer", "A reference to the LightClusterDecayer object", &Herwig::ClusterHadronizationHandler::_lightClusterDecayer, false, false, true, false); static Reference interfaceClusterDecayer("ClusterDecayer", "A reference to the ClusterDecayer object", &Herwig::ClusterHadronizationHandler::_clusterDecayer, false, false, true, false); static Parameter interfaceMinVirtuality2 ("MinVirtuality2", "Minimum virtuality^2 of partons to use in calculating distances (unit [GeV2]).", &ClusterHadronizationHandler::_minVirtuality2, GeV2, 0.1*GeV2, ZERO, 10.0*GeV2,false,false,false); static Parameter interfaceMaxDisplacement ("MaxDisplacement", "Maximum displacement that is allowed for a particle (unit [millimeter]).", &ClusterHadronizationHandler::_maxDisplacement, mm, 1.0e-10*mm, 0.0*mm, 1.0e-9*mm,false,false,false); static Reference interfaceUnderlyingEventHandler ("UnderlyingEventHandler", "Pointer to the handler for the Underlying Event. " "Set to NULL to disable.", &ClusterHadronizationHandler::_underlyingEventHandler, false, false, true, true, false); static Switch interfaceReduceToTwoComponents ("ReduceToTwoComponents", "Whether or not to reduce three component baryon-number violating clusters to two components before cluster splitting or leave" " this till after the cluster splitting", &ClusterHadronizationHandler::_reduceToTwoComponents, true, false, false); static SwitchOption interfaceReduceToTwoComponentsYes (interfaceReduceToTwoComponents, "BeforeSplitting", "Reduce to two components", true); static SwitchOption interfaceReduceToTwoComponentsNo (interfaceReduceToTwoComponents, "AfterSplitting", "Treat as three components", false); } namespace { void extractChildren(tPPtr p, set & all) { if (p->children().empty()) return; for (PVector::const_iterator child = p->children().begin(); child != p->children().end(); ++child) { all.insert(*child); extractChildren(*child, all); } } } void ClusterHadronizationHandler:: handle(EventHandler & ch, const tPVector & tagged, const Hint &) { useMe(); currentHandler_ = this; PVector currentlist(tagged.begin(),tagged.end()); // set the scale for coloured particles to just above the gluon mass squared // if less than this so they are classed as perturbative Energy2 Q02 = 1.01*sqr(getParticleData(ParticleID::g)->constituentMass()); for(unsigned int ix=0;ixscale()scale(Q02); } // split the gluons _partonSplitter->split(currentlist); // form the clusters ClusterVector clusters = _clusterFinder->formClusters(currentlist); // reduce BV clusters to two components now if needed if(_reduceToTwoComponents) _clusterFinder->reduceToTwoComponents(clusters); // perform colour reconnection if needed and then // decay the clusters into one hadron bool lightOK = false; short tried = 0; const ClusterVector savedclusters = clusters; tPVector finalHadrons; // only needed for partonic decayer while (!lightOK && tried++ < 10) { // no colour reconnection with baryon-number-violating (BV) clusters ClusterVector CRclusters, BVclusters; CRclusters.reserve( clusters.size() ); BVclusters.reserve( clusters.size() ); for (size_t ic = 0; ic < clusters.size(); ++ic) { ClusterPtr cl = clusters.at(ic); bool hasClusterParent = false; for (unsigned int ix=0; ix < cl->parents().size(); ++ix) { if (cl->parents()[ix]->id() == ParticleID::Cluster) { hasClusterParent = true; break; } } if (cl->numComponents() > 2 || hasClusterParent) BVclusters.push_back(cl); else CRclusters.push_back(cl); } // colour reconnection _colourReconnector->rearrange(CRclusters); // tag new clusters as children of the partons to hadronize _setChildren(CRclusters); + // forms diquarks + _clusterFinder->reduceToTwoComponents(CRclusters); + // recombine vectors of (possibly) reconnected and BV clusters clusters.clear(); clusters.insert( clusters.end(), CRclusters.begin(), CRclusters.end() ); clusters.insert( clusters.end(), BVclusters.begin(), BVclusters.end() ); // fission of heavy clusters // NB: during cluster fission, light hadrons might be produced straight away finalHadrons = _clusterFissioner->fission(clusters,isSoftUnderlyingEventON()); // if clusters not previously reduced to two components do it now if(!_reduceToTwoComponents) _clusterFinder->reduceToTwoComponents(clusters); lightOK = _lightClusterDecayer->decay(clusters,finalHadrons); // if the decay of the light clusters was not successful, undo the cluster // fission and decay steps and revert to the original state of the event // record if (!lightOK) { clusters = savedclusters; for_each(clusters.begin(), clusters.end(), mem_fun(&Particle::undecay)); } } if (!lightOK) { - // currentHandler_ = 0; throw Exception("CluHad::handle(): tried LightClusterDecayer 10 times!", Exception::eventerror); } // decay the remaining clusters _clusterDecayer->decay(clusters,finalHadrons); // ***************************************** // ***************************************** // ***************************************** StepPtr pstep = newStep(); set allDecendants; for (tPVector::const_iterator it = tagged.begin(); it != tagged.end(); ++it) { extractChildren(*it, allDecendants); } for(set::const_iterator it = allDecendants.begin(); it != allDecendants.end(); ++it) { // this is a workaround because the set sometimes // re-orders parents after their children if ((*it)->children().empty()) pstep->addDecayProduct(*it); else { pstep->addDecayProduct(*it); pstep->addIntermediate(*it); } } // ***************************************** // ***************************************** // ***************************************** // soft underlying event if needed if (isSoftUnderlyingEventON()) { assert(_underlyingEventHandler); ch.performStep(_underlyingEventHandler,Hint::Default()); } } -void ClusterHadronizationHandler::_setChildren(ClusterVector clusters) const { +// Sets parent child relationship of all clusters with two components +// Relationships for clusters with more than two components are set elsewhere in the Colour Reconnector +void ClusterHadronizationHandler::_setChildren(const ClusterVector & clusters) const { // erase existing information about the partons' children tPVector partons; - for (ClusterVector::const_iterator cl = clusters.begin(); - cl != clusters.end(); cl++) { - partons.push_back( (*cl)->colParticle() ); - partons.push_back( (*cl)->antiColParticle() ); + for ( const auto & cl : clusters ) { + if ( cl->numComponents() > 2 ) continue; + partons.push_back( cl->colParticle() ); + partons.push_back( cl->antiColParticle() ); } + // erase all previous information about parent child relationship for_each(partons.begin(), partons.end(), mem_fun(&Particle::undecay)); // give new parents to the clusters: their constituents - for (ClusterVector::iterator cl = clusters.begin(); - cl != clusters.end(); cl++) { - (*cl)->colParticle()->addChild(*cl); - (*cl)->antiColParticle()->addChild(*cl); + for ( const auto & cl : clusters ) { + if ( cl->numComponents() > 2 ) continue; + cl->colParticle()->addChild(cl); + cl->antiColParticle()->addChild(cl); } - } diff --git a/Hadronization/ClusterHadronizationHandler.h b/Hadronization/ClusterHadronizationHandler.h --- a/Hadronization/ClusterHadronizationHandler.h +++ b/Hadronization/ClusterHadronizationHandler.h @@ -1,223 +1,209 @@ // -*- C++ -*- // // ClusterHadronizationHandler.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_ClusterHadronizationHandler_H #define HERWIG_ClusterHadronizationHandler_H #include #include "PartonSplitter.h" #include "ClusterFinder.h" #include "ColourReconnector.h" #include "ClusterFissioner.h" #include "LightClusterDecayer.h" #include "ClusterDecayer.h" #include "ClusterHadronizationHandler.fh" namespace Herwig { using namespace ThePEG; /** \ingroup Hadronization * \class ClusterHadronizationHandler * \brief Class that controls the cluster hadronization algorithm. * \author Philip Stephens // cerr << *ch.currentEvent() << '\n'; cerr << finalHadrons.size() << '\n'; cerr << "Finished hadronizing \n"; * \author Alberto Ribon * * This class is the main driver of the cluster hadronization: it is * responsible for the proper handling of all other specific collaborating * classes PartonSplitter, ClusterFinder, ColourReconnector, ClusterFissioner, * LightClusterDecayer, ClusterDecayer; * and for the storing of the produced particles in the Event record. * * @see PartonSplitter * @see ClusterFinder * @see ColourReconnector * @see ClusterFissioner * @see LightClusterDecayer * @see ClusterDecayer * @see Cluster * @see \ref ClusterHadronizationHandlerInterfaces "The interfaces" * defined for ClusterHadronizationHandler. */ class ClusterHadronizationHandler: public HadronizationHandler { public: - /** @name Standard constructors and destructors. */ - //@{ - /** - * The default constructor. - */ - ClusterHadronizationHandler() - : _minVirtuality2( 0.1*GeV2 ), _maxDisplacement( 1.0e-10*mm ), - _reduceToTwoComponents(true) - {} - - //@} - -public: - /** * The main method which manages the all cluster hadronization. * * This routine directs "traffic". It determines which function is called * and on which particles/clusters. This function also handles the * situation of vetos on the hadronization. */ virtual void handle(EventHandler & ch, const tPVector & tagged, const Hint & hint); /** * It returns minimum virtuality^2 of partons to use in calculating * distances. It is used both in the Showering and Hadronization. */ Energy2 minVirtuality2() const { return _minVirtuality2; } /** * It returns the maximum displacement that is allowed for a particle * (used to determine the position of a cluster with two components). */ Length maxDisplacement() const { return _maxDisplacement; } /** * It returns true/false according if the soft underlying model * is switched on/off. */ bool isSoftUnderlyingEventON() const { return _underlyingEventHandler; } /** * pointer to "this", the current HadronizationHandler. */ static const ClusterHadronizationHandler * currentHandler() { assert(currentHandler_); return currentHandler_; } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interfaces. */ static void Init(); protected: /** @name 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: /** * Private and non-existent assignment operator. */ - ClusterHadronizationHandler & operator=(const ClusterHadronizationHandler &); + ClusterHadronizationHandler & operator=(const ClusterHadronizationHandler &) = delete; /** * This is a pointer to a Herwig::PartonSplitter object. */ PartonSplitterPtr _partonSplitter; /** * This is a pointer to a Herwig::ClusterFinder object. */ ClusterFinderPtr _clusterFinder; /** * This is a pointer to a Herwig::ColourReconnector object. */ ColourReconnectorPtr _colourReconnector; /** * This is a pointer to a Herwig::ClusterFissioner object. */ ClusterFissionerPtr _clusterFissioner; /** * This is a pointer to a Herwig::LightClusterDecayer object. */ LightClusterDecayerPtr _lightClusterDecayer; /** * This is a pointer to a Herwig::ClusterDecayer object. */ ClusterDecayerPtr _clusterDecayer; /** * The minimum virtuality^2 of partons to use in calculating * distances. */ - Energy2 _minVirtuality2; + Energy2 _minVirtuality2 = 0.1_GeV2; /** * The maximum displacement that is allowed for a particle * (used to determine the position of a cluster with two components). */ - Length _maxDisplacement; + Length _maxDisplacement = 1.0e-10_mm; /** * The pointer to the Underlying Event handler. */ StepHdlPtr _underlyingEventHandler; /** * How to handle baryon-number clusters */ - bool _reduceToTwoComponents; + bool _reduceToTwoComponents = true; /** * Tag the constituents of the clusters as their parents */ - void _setChildren(ClusterVector clusters) const; + void _setChildren(const ClusterVector & clusters) const; /** * pointer to "this", the current HadronizationHandler. */ static ClusterHadronizationHandler * currentHandler_; }; } #endif /* HERWIG_ClusterHadronizationHandler_H */ diff --git a/Hadronization/ColourReconnector.cc b/Hadronization/ColourReconnector.cc --- a/Hadronization/ColourReconnector.cc +++ b/Hadronization/ColourReconnector.cc @@ -1,488 +1,821 @@ // -*- C++ -*- // // ColourReconnector.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 ColourReconnector class. // #include "ColourReconnector.h" #include "Cluster.h" -#include "Herwig/Utilities/Maths.h" -#include -#include "ThePEG/Interface/Parameter.h" + +#include +#include +#include #include #include -#include -#include -#include -#include +#include +#include + +#include "Herwig/Utilities/Maths.h" using namespace Herwig; -typedef ClusterVector::iterator CluVecIt; +using CluVecIt = ColourReconnector::CluVecIt; +using Constants::pi; +using Constants::twopi; + DescribeClass describeColourReconnector("Herwig::ColourReconnector",""); IBPtr ColourReconnector::clone() const { return new_ptr(*this); } IBPtr ColourReconnector::fullclone() const { return new_ptr(*this); } void ColourReconnector::rearrange(ClusterVector & clusters) { if (_clreco == 0) return; // need at least two clusters if (clusters.size() < 2) return; // do the colour reconnection switch (_algorithm) { - case 0: _doRecoPlain(clusters); - break; - case 1: _doRecoStatistical(clusters); - break; + case 0: _doRecoPlain(clusters); break; + case 1: _doRecoStatistical(clusters); break; + case 2: _doRecoBaryonic(clusters); break; } - - return; } Energy2 ColourReconnector::_clusterMassSum(const PVector & q, const PVector & aq) const { const size_t nclusters = q.size(); assert (aq.size() == nclusters); Energy2 sum = ZERO; for (size_t i = 0; i < nclusters; i++) sum += ( q[i]->momentum() + aq[i]->momentum() ).m2(); return sum; } bool ColourReconnector::_containsColour8(const ClusterVector & cv, const vector & P) const { assert (P.size() == cv.size()); for (size_t i = 0; i < cv.size(); i++) { tcPPtr p = cv[i]->colParticle(); tcPPtr q = cv[P[i]]->antiColParticle(); - if (isColour8(p, q)) return true; + if (_isColour8(p, q)) return true; } return false; } void ColourReconnector::_doRecoStatistical(ClusterVector & cv) const { const size_t nclusters = cv.size(); // initially, enumerate (anti)quarks as given in the cluster vector ParticleVector q, aq; for (size_t i = 0; i < nclusters; i++) { q.push_back( cv[i]->colParticle() ); aq.push_back( cv[i]->antiColParticle() ); } // annealing scheme Energy2 t, delta; Energy2 lambda = _clusterMassSum(q,aq); const unsigned _ntries = _triesPerStepFactor * nclusters; // find appropriate starting temperature by measuring the largest lambda // difference in some dry-run random rearrangements { vector typical; for (int i = 0; i < 10; i++) { const pair toswap = _shuffle(q,aq,5); ParticleVector newaq = aq; swap (newaq[toswap.first], newaq[toswap.second]); Energy2 newlambda = _clusterMassSum(q,newaq); typical.push_back( abs(newlambda - lambda) ); } t = _initTemp * Math::median(typical); } // anneal in up to _annealingSteps temperature steps for (unsigned step = 0; step < _annealingSteps; step++) { // For this temperature step, try to reconnect _ntries times. Stop the // algorithm if no successful reconnection happens. unsigned nSuccess = 0; for (unsigned it = 0; it < _ntries; it++) { // make a random rearrangement const unsigned maxtries = 10; const pair toswap = _shuffle(q,aq,maxtries); const int i = toswap.first; const int j = toswap.second; // stop here if we cannot find any allowed reconfiguration if (i == -1) break; // create a new antiquark vector with the two partons swapped ParticleVector newaq = aq; swap (newaq[i], newaq[j]); // Check if lambda would decrease. If yes, accept the reconnection. If no, // accept it only with a probability given by the current Boltzmann // factor. In the latter case we set p = 0 if the temperature is close to // 0, to avoid division by 0. Energy2 newlambda = _clusterMassSum(q,newaq); delta = newlambda - lambda; double prob = 1.0; if (delta > ZERO) prob = ( abs(t) < 1e-8*MeV2 ) ? 0.0 : exp(-delta/t); if (UseRandom::rnd() < prob) { lambda = newlambda; swap (newaq, aq); nSuccess++; } } if (nSuccess == 0) break; // reduce temperature t *= _annealingFactor; } // construct the new cluster vector ClusterVector newclusters; for (size_t i = 0; i < nclusters; i++) { ClusterPtr cl = new_ptr( Cluster( q[i], aq[i] ) ); newclusters.push_back(cl); } swap(newclusters,cv); return; } void ColourReconnector::_doRecoPlain(ClusterVector & cv) const { ClusterVector newcv = cv; // try to avoid systematic errors by randomising the reconnection order long (*p_irnd)(long) = UseRandom::irnd; random_shuffle( newcv.begin(), newcv.end(), p_irnd ); // iterate over all clusters for (CluVecIt cit = newcv.begin(); cit != newcv.end(); cit++) { - // find the cluster which, if reconnected with *cit, would result in the // smallest sum of cluster masses // NB this method returns *cit if no reconnection partner can be found CluVecIt candidate = _findRecoPartner(cit, newcv); // skip this cluster if no possible reshuffling partner can be found if (candidate == cit) continue; // accept the reconnection with probability _preco. if (UseRandom::rnd() < _preco) { pair reconnected = _reconnect(*cit, *candidate); // Replace the clusters in the ClusterVector. The order of the // colour-triplet partons in the cluster vector is retained here. // replace *cit by reconnected.first *cit = reconnected.first; // replace candidate by reconnected.second *candidate = reconnected.second; } } swap(cv,newcv); return; } +namespace { + inline bool hasDiquark(CluVecIt cit) { + for(int i = 0; i<(*cit)->numComponents(); i++) { + if (DiquarkMatcher::Check(*((*cit)->particle(i)->dataPtr()))) + return true; + } + return false; + } +} + + +// Implementation of the baryonic reconnection algorithm +void ColourReconnector::_doRecoBaryonic(ClusterVector & cv) const { + + ClusterVector newcv = cv; + + ClusterVector deleted; deleted.reserve(cv.size()); + + // try to avoid systematic errors by randomising the reconnection order + long (*p_irnd)(long) = UseRandom::irnd; + random_shuffle( newcv.begin(), newcv.end(), p_irnd ); + + // iterate over all clusters + for (CluVecIt cit = newcv.begin(); cit != newcv.end(); ++cit) { + //avoid clusters already containing diuarks + if (hasDiquark(cit)) continue; + + //skip the cluster to be deleted later 3->2 cluster + if (find(deleted.begin(), deleted.end(), *cit) != deleted.end()) + continue; + + // Skip all found baryonic clusters, this biases the algorithm but implementing + // something like re-reconnection is ongoing work + if ((*cit)->numComponents()==3) continue; + + // Find a candidate suitable for reconnection + CluVecIt baryonic1, baryonic2; + bool isBaryonicCandidate = false; + CluVecIt candidate = _findPartnerBaryonic(cit, newcv, + isBaryonicCandidate, + deleted, + baryonic1, baryonic2); + + // skip this cluster if no possible reconnection partner can be found + if ( !isBaryonicCandidate && candidate==cit ) + continue; + + if ( isBaryonicCandidate + && UseRandom::rnd() < _precoBaryonic ) { + deleted.push_back(*baryonic2); + + // Function that does the reconnection from 3 -> 2 clusters + ClusterPtr b1, b2; + _makeBaryonicClusters(*cit,*baryonic1,*baryonic2, b1, b2); + + *cit = b1; + *baryonic1 = b2; + + // Baryonic2 is easily skipped in the next loop + } + + // Normal 2->2 Colour reconnection + if ( !isBaryonicCandidate + && UseRandom::rnd() < _preco ) { + auto reconnected = _reconnectBaryonic(*cit, *candidate); + *cit = reconnected.first; + *candidate = reconnected.second; + } + } + + // create a new vector of clusters except for the ones which are "deleted" during + // baryonic reconnection + ClusterVector clustervector; + for ( const auto & cluster : newcv ) + if ( find(deleted.begin(), + deleted.end(), cluster) == deleted.end() ) + clustervector.push_back(cluster); + + swap(cv,clustervector); +} + + + +namespace { + +double calculateRapidityRF(const Lorentz5Momentum & q1, + const Lorentz5Momentum & p2) { + //calculate rapidity wrt the direction of q1 + //angle between the particles in the RF of cluster of q1 + + // calculate the z component of p2 w.r.t the direction of q1 + const Energy pz = p2.vect() * q1.vect().unit(); + if ( pz == ZERO ) return 0.; + + // Transverse momentum of p2 w.r.t the direction of q1 + const Energy pt = sqrt(p2.vect().mag2() - sqr(pz)); + + // Transverse mass pf p2 w.r.t to the direction of q1 + const Energy mtrans = sqrt(p2.mass()*p2.mass() + (pt*pt)); + + // Correct formula + const double y2 = log((p2.t() + abs(pz))/mtrans); + + return ( pz < ZERO ) ? -y2 : y2; +} + +} + + +CluVecIt ColourReconnector::_findPartnerBaryonic( + CluVecIt cl, ClusterVector & cv, + bool & baryonicCand, + const ClusterVector& deleted, + CluVecIt &baryonic1, + CluVecIt &baryonic2 ) const { + + using Constants::pi; + using Constants::twopi; + + // Returns a candidate for possible reconnection + CluVecIt candidate = cl; + + bool bcand = false; + + double maxrap = 0.0; + double minrap = 0.0; + double maxrapNormal = 0.0; + double minrapNormal = 0.0; + double maxsumnormal = 0.0; + + double maxsum = 0.0; + double secondsum = 0.0; + + + // boost into RF of cl + Lorentz5Momentum cl1 = (*cl)->momentum(); + const Boost boostv(-cl1.boostVector()); + cl1.boost(boostv); + // boost constituents of cl into RF of cl + Lorentz5Momentum p1col = (*cl)->colParticle()->momentum(); + Lorentz5Momentum p1anticol = (*cl)->antiColParticle()->momentum(); + p1col.boost(boostv); + p1anticol.boost(boostv); + + + for (CluVecIt cit=cv.begin(); cit != cv.end(); ++cit) { + //avoid looping over clusters containing diquarks + if ( hasDiquark(cit) ) continue; + if ( (*cit)->numComponents()==3 ) continue; + if ( cit==cl ) continue; + + //skip the cluster to be deleted later 3->2 cluster + if ( find(deleted.begin(), deleted.end(), *cit) != deleted.end() ) + continue; + + if ( (*cl)->isBeamCluster() && (*cit)->isBeamCluster() ) + continue; + + // stop it putting far apart clusters together + if ( ( (**cl).vertex()-(**cit).vertex() ).m() >_maxDistance ) + continue; + + const bool Colour8 = + _isColour8( (*cl)->colParticle(), (*cit)->antiColParticle() ) + || + _isColour8( (*cit)->colParticle(), (*cl)->antiColParticle() ) ; + if ( Colour8 ) continue; + + + // boost constituents of cit into RF of cl + Lorentz5Momentum p2col = (*cit)->colParticle()->momentum(); + Lorentz5Momentum p2anticol = (*cit)->antiColParticle()->momentum(); + + p2col.boost(boostv); + p2anticol.boost(boostv); + + // calculate the rapidity of the other constituents of the clusters + // w.r.t axis of p1anticol.vect.unit + const double rapq = calculateRapidityRF(p1anticol,p2col); + const double rapqbar = calculateRapidityRF(p1anticol,p2anticol); + + // configuration for normal CR + if ( rapq > 0.0 && rapqbar < 0.0 + && rapq > maxrap + && rapqbar < minrap ) { + maxrap = rapq; + minrap = rapqbar; + //sum of rapidities of quarks + const double normalsum = abs(rapq) + abs(rapqbar); + if ( normalsum > maxsumnormal ) { + maxsumnormal = normalsum; + maxrapNormal = rapq; + minrapNormal = rapqbar; + bcand = false; + candidate = cit; + } + } + + if ( rapq < 0.0 && rapqbar >0.0 + && rapqbar > maxrapNormal + && rapq < minrapNormal ) { + maxrap = rapqbar; + minrap = rapq; + const double sumrap = abs(rapqbar) + abs(rapq); + // first candidate gets here. If second baryonic candidate has higher Ysum than the first + // one, the second candidate becomes the first one and the first the second. + if (sumrap > maxsum) { + if(maxsum != 0){ + baryonic2 = baryonic1; + baryonic1 = cit; + bcand = true; + } else { + baryonic1 = cit; + } + maxsum = sumrap; + } else { + if (sumrap > secondsum && sumrap != maxsum) { + secondsum = sumrap; + bcand = true; + baryonic2 = cit; + } + } + } + + } + + if(bcand == true){ + baryonicCand = true; + } + + return candidate; +} + CluVecIt ColourReconnector::_findRecoPartner(CluVecIt cl, ClusterVector & cv) const { CluVecIt candidate = cl; Energy minMass = 1*TeV; for (CluVecIt cit=cv.begin(); cit != cv.end(); ++cit) { // don't even look at original cluster if(cit==cl) continue; // don't allow colour octet clusters - if ( isColour8( (*cl)->colParticle(), - (*cit)->antiColParticle() ) || - isColour8( (*cit)->colParticle(), - (*cl)->antiColParticle() ) ) { + if ( _isColour8( (*cl)->colParticle(), + (*cit)->antiColParticle() ) || + _isColour8( (*cit)->colParticle(), + (*cl)->antiColParticle() ) ) { continue; } // stop it putting beam remnants together if((*cl)->isBeamCluster() && (*cit)->isBeamCluster()) continue; // stop it putting far apart clusters together if(((**cl).vertex()-(**cit).vertex()).m()>_maxDistance) continue; // momenta of the old clusters Lorentz5Momentum p1 = (*cl)->colParticle()->momentum() + (*cl)->antiColParticle()->momentum(); Lorentz5Momentum p2 = (*cit)->colParticle()->momentum() + (*cit)->antiColParticle()->momentum(); // momenta of the new clusters Lorentz5Momentum p3 = (*cl)->colParticle()->momentum() + (*cit)->antiColParticle()->momentum(); Lorentz5Momentum p4 = (*cit)->colParticle()->momentum() + (*cl)->antiColParticle()->momentum(); Energy oldMass = abs( p1.m() ) + abs( p2.m() ); Energy newMass = abs( p3.m() ) + abs( p4.m() ); + if ( newMass < oldMass && newMass < minMass ) { minMass = newMass; candidate = cit; } } + return candidate; } +// forms two baryonic clusters from three clusters +void ColourReconnector::_makeBaryonicClusters( + ClusterPtr &c1, ClusterPtr &c2, + ClusterPtr &c3, + ClusterPtr &newcluster1, + ClusterPtr &newcluster2) const{ + + //make sure they all have 2 components + assert(c1->numComponents()==2); + assert(c2->numComponents()==2); + assert(c3->numComponents()==2); + //abandon childs + c1->colParticle()->abandonChild(c1); + c1->antiColParticle()->abandonChild(c1); + c2->colParticle()->abandonChild(c2); + c2->antiColParticle()->abandonChild(c2); + c3->colParticle()->abandonChild(c3); + c3->antiColParticle()->abandonChild(c3); + + newcluster1 = new_ptr(Cluster(c1->colParticle(),c2->colParticle(), c3->colParticle())); + c1->colParticle()->addChild(newcluster1); + c2->colParticle()->addChild(newcluster1); + c3->colParticle()->addChild(newcluster1); + newcluster1->setVertex(LorentzPoint()); + newcluster2 = new_ptr(Cluster(c1->antiColParticle(), c2->antiColParticle(), + c3->antiColParticle())); + c1->antiColParticle()->addChild(newcluster2); + c2->antiColParticle()->addChild(newcluster2); + c3->antiColParticle()->addChild(newcluster2); + newcluster2->setVertex(LorentzPoint()); +} pair -ColourReconnector::_reconnect(ClusterPtr c1, ClusterPtr c2) const { +ColourReconnector::_reconnect(ClusterPtr &c1, ClusterPtr &c2) const { // choose the other possibility to form two clusters from the given // constituents + assert(c1->numComponents()==2); assert(c2->numComponents()==2); int c1_col(-1),c1_anti(-1),c2_col(-1),c2_anti(-1); for(unsigned int ix=0;ix<2;++ix) { if (c1->particle(ix)->hasColour(false)) c1_col = ix; else if(c1->particle(ix)->hasColour(true )) c1_anti = ix; if (c2->particle(ix)->hasColour(false)) c2_col = ix; else if(c2->particle(ix)->hasColour(true )) c2_anti = ix; } assert(c1_col>=0&&c2_col>=0&&c1_anti>=0&&c2_anti>=0); ClusterPtr newCluster1 = new_ptr( Cluster( c1->colParticle(), c2->antiColParticle() ) ); newCluster1->setVertex(0.5*( c1->colParticle()->vertex() + - c2->antiColParticle()->vertex() )); + c2->antiColParticle()->vertex() )); if(c1->isBeamRemnant(c1_col )) newCluster1->setBeamRemnant(0,true); if(c2->isBeamRemnant(c2_anti)) newCluster1->setBeamRemnant(1,true); - + ClusterPtr newCluster2 = new_ptr( Cluster( c2->colParticle(), c1->antiColParticle() ) ); newCluster2->setVertex(0.5*( c2->colParticle()->vertex() + - c1->antiColParticle()->vertex() )); + c1->antiColParticle()->vertex() )); + + if(c2->isBeamRemnant(c2_col )) newCluster2->setBeamRemnant(0,true); + if(c1->isBeamRemnant(c1_anti)) newCluster2->setBeamRemnant(1,true); + + return pair (newCluster1, newCluster2); +} + + + + + +pair +ColourReconnector::_reconnectBaryonic(ClusterPtr &c1, ClusterPtr &c2) const { + + // choose the other possibility to form two clusters from the given + // constituents + + assert(c1->numComponents()==2); + assert(c2->numComponents()==2); + int c1_col(-1),c1_anti(-1),c2_col(-1),c2_anti(-1); + for(unsigned int ix=0;ix<2;++ix) { + if (c1->particle(ix)->hasColour(false)) c1_col = ix; + else if(c1->particle(ix)->hasColour(true )) c1_anti = ix; + if (c2->particle(ix)->hasColour(false)) c2_col = ix; + else if(c2->particle(ix)->hasColour(true )) c2_anti = ix; + } + assert(c1_col>=0&&c2_col>=0&&c1_anti>=0&&c2_anti>=0); + +c1->colParticle()->abandonChild(c1); +c2->antiColParticle()->abandonChild(c2); + + ClusterPtr newCluster1 + = new_ptr( Cluster( c1->colParticle(), c2->antiColParticle() ) ); + + c1->colParticle()->addChild(newCluster1); + c2->antiColParticle()->addChild(newCluster1); + + newCluster1->setVertex(0.5*( c1->colParticle()->vertex() + + c2->antiColParticle()->vertex() )); + + if(c1->isBeamRemnant(c1_col )) newCluster1->setBeamRemnant(0,true); + if(c2->isBeamRemnant(c2_anti)) newCluster1->setBeamRemnant(1,true); + + c1->antiColParticle()->abandonChild(c1); + c2->colParticle()->abandonChild(c2); + + ClusterPtr newCluster2 + = new_ptr( Cluster( c2->colParticle(), c1->antiColParticle() ) ); + + c1->antiColParticle()->addChild(newCluster2); + c2->colParticle()->addChild(newCluster2); + + newCluster2->setVertex(0.5*( c2->colParticle()->vertex() + + c1->antiColParticle()->vertex() )); if(c2->isBeamRemnant(c2_col )) newCluster2->setBeamRemnant(0,true); if(c1->isBeamRemnant(c1_anti)) newCluster2->setBeamRemnant(1,true); return pair (newCluster1, newCluster2); } pair ColourReconnector::_shuffle (const PVector & q, const PVector & aq, unsigned maxtries) const { const size_t nclusters = q.size(); assert (nclusters > 1); assert (aq.size() == nclusters); int i, j; unsigned tries = 0; bool octet; do { // find two different random integers in the range [0, nclusters) i = UseRandom::irnd( nclusters ); do { j = UseRandom::irnd( nclusters ); } while (i == j); // check if one of the two potential clusters would be a colour octet state - octet = isColour8( q[i], aq[j] ) || isColour8( q[j], aq[i] ) ; + octet = _isColour8( q[i], aq[j] ) || _isColour8( q[j], aq[i] ) ; tries++; } while (octet && tries < maxtries); if (octet) i = j = -1; return make_pair(i,j); } -bool ColourReconnector::isColour8(cPPtr p, cPPtr q) const { + +bool ColourReconnector::_isColour8(tcPPtr p, tcPPtr q) const { bool octet = false; // make sure we have a triplet and an anti-triplet if ( ( p->hasColour() && q->hasAntiColour() ) || ( p->hasAntiColour() && q->hasColour() ) ) { // true if p and q are originated from a colour octet if ( !p->parents().empty() && !q->parents().empty() ) { octet = ( p->parents()[0] == q->parents()[0] ) && ( p->parents()[0]->data().iColour() == PDT::Colour8 ); } // (Final) option: check if same colour8 parent // or already found an octet. if(_octetOption==0||octet) return octet; // (All) option handling more octets // by browsing particle history/colour lines. tColinePtr cline,aline; // Get colourlines form final states. if(p->hasColour() && q->hasAntiColour()) { cline = p-> colourLine(); aline = q->antiColourLine(); } else { cline = q-> colourLine(); aline = p->antiColourLine(); } // Follow the colourline of p. if ( !p->parents().empty() ) { tPPtr parent = p->parents()[0]; while (parent) { if(parent->data().iColour() == PDT::Colour8) { // Coulour8 particles should have a colour // and an anticolour line. Currently the // remnant has none of those. Since the children // of the remnant are not allowed to emit currently, // the colour octet remnant is handled by the return // statement above. The assert also catches other // colour octets without clines. If the children of // a remnant should be allowed to emit, the remnant // should get appropriate colour lines and // colour states. // See Ticket: #407 - // assert(parent->colourLine()&&parent->antiColourLine()); + // assert(parent->colourLine()&&parent->antiColourLine()); octet = (parent-> colourLine()==cline && parent->antiColourLine()==aline); } if(octet||parent->parents().empty()) break; parent = parent->parents()[0]; } } } return octet; } void ColourReconnector::persistentOutput(PersistentOStream & os) const { - os << _clreco << _preco << _algorithm << _initTemp << _annealingFactor + os << _clreco << _preco << _precoBaryonic << _algorithm << _initTemp << _annealingFactor << _annealingSteps << _triesPerStepFactor << ounit(_maxDistance,femtometer) << _octetOption; } void ColourReconnector::persistentInput(PersistentIStream & is, int) { - is >> _clreco >> _preco >> _algorithm >> _initTemp >> _annealingFactor + is >> _clreco >> _preco >> _precoBaryonic >> _algorithm >> _initTemp >> _annealingFactor >> _annealingSteps >> _triesPerStepFactor >> iunit(_maxDistance,femtometer) >> _octetOption; } void ColourReconnector::Init() { static ClassDocumentation documentation ("This class is responsible of the colour reconnection."); static Switch interfaceColourReconnection ("ColourReconnection", "Colour reconnections", &ColourReconnector::_clreco, 0, true, false); static SwitchOption interfaceColourReconnectionNo (interfaceColourReconnection, "No", "Colour reconnections off", 0); static SwitchOption interfaceColourReconnectionYes (interfaceColourReconnection, "Yes", "Colour reconnections on", 1); static Parameter interfaceMtrpAnnealingFactor ("AnnealingFactor", "The annealing factor is the ratio of the temperatures in two successive " "temperature steps.", &ColourReconnector::_annealingFactor, 0.9, 0.0, 1.0, false, false, Interface::limited); static Parameter interfaceMtrpAnnealingSteps ("AnnealingSteps", "Number of temperature steps in the statistical annealing algorithm", &ColourReconnector::_annealingSteps, 50, 1, 10000, false, false, Interface::limited); static Parameter interfaceMtrpTriesPerStepFactor ("TriesPerStepFactor", "The number of reconnection tries per temperature steps is the number of " "clusters times this factor.", &ColourReconnector::_triesPerStepFactor, 5.0, 0.0, 100.0, false, false, Interface::limited); static Parameter interfaceMtrpInitialTemp ("InitialTemperature", "Factor used to determine the initial temperature from the median of the " "energy change in a few random rearrangements.", &ColourReconnector::_initTemp, 0.1, 0.00001, 100.0, false, false, Interface::limited); static Parameter interfaceRecoProb ("ReconnectionProbability", "Probability that a found reconnection possibility is actually accepted", &ColourReconnector::_preco, 0.5, 0.0, 1.0, false, false, Interface::limited); + static Parameter interfaceRecoProbBaryonic + ("ReconnectionProbabilityBaryonic", + "Probability that a found reconnection possibility is actually accepted", + &ColourReconnector::_precoBaryonic, 0.5, 0.0, 1.0, + false, false, Interface::limited); + static Switch interfaceAlgorithm ("Algorithm", "Specifies the colour reconnection algorithm", &ColourReconnector::_algorithm, 0, true, false); static SwitchOption interfaceAlgorithmPlain (interfaceAlgorithm, "Plain", "Plain colour reconnection as in Herwig 2.5.0", 0); static SwitchOption interfaceAlgorithmStatistical (interfaceAlgorithm, "Statistical", "Statistical colour reconnection using simulated annealing", 1); - + static SwitchOption interfaceAlgorithmBaryonic + (interfaceAlgorithm, + "BaryonicReco", + "Baryonic cluster reconnection", + 2); static Parameter interfaceMaxDistance ("MaxDistance", "Maximum distance between the clusters at which to consider rearrangement" " to avoid colour reconneections of displaced vertices", &ColourReconnector::_maxDistance, femtometer, 1000.*femtometer, 0.0*femtometer, 1e100*femtometer, false, false, Interface::limited); + static Switch interfaceOctetTreatment ("OctetTreatment", "Which octets are not allowed to be reconnected", &ColourReconnector::_octetOption, 0, false, false); static SwitchOption interfaceOctetTreatmentFinal (interfaceOctetTreatment, "Final", "Only prevent for the final (usuaslly non-perturbative) g -> q qbar splitting", 0); static SwitchOption interfaceOctetTreatmentAll (interfaceOctetTreatment, "All", "Prevent for all octets", 1); +} -} diff --git a/Hadronization/ColourReconnector.h b/Hadronization/ColourReconnector.h --- a/Hadronization/ColourReconnector.h +++ b/Hadronization/ColourReconnector.h @@ -1,247 +1,265 @@ // -*- C++ -*- // // ColourReconnector.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_ColourReconnector_H #define HERWIG_ColourReconnector_H #include #include "CluHadConfig.h" #include "ColourReconnector.fh" namespace Herwig { using namespace ThePEG; /** \ingroup Hadronization * \class ColourReconnector * \brief Class for changing colour reconnections of partons. * \author Alberto Ribon, Christian Roehr * * This class does the nonperturbative colour rearrangement, after the * nonperturbative gluon splitting and the "normal" cluster formation. * It uses the list of particles in the event record, and the collections of * "usual" clusters which is passed to the main method. If the colour * reconnection is actually accepted, then the previous collections of "usual" * clusters is first deleted and then the new one is created. * * * @see \ref ColourReconnectorInterfaces "The interfaces" * defined for ColourReconnector. */ class ColourReconnector: public Interfaced { public: - /** @name Standard constructors and destructors. */ - //@{ - /** - * Default constructor. - */ - ColourReconnector() : - _algorithm(0), - _annealingFactor(0.9), - _annealingSteps(50), - _clreco(0), - _initTemp(0.1), - _preco(0.5), - _triesPerStepFactor(5.0), - _maxDistance(1000.*femtometer), - _octetOption(0) - {} - //@} - /** * Does the colour rearrangement, starting out from the list of particles in * the event record and the collection of "usual" clusters passed as * arguments. If the actual rearrangement is accepted, the initial collection of * clusters is overridden by the old ones. */ void rearrange(ClusterVector & clusters); + using CluVecIt = ClusterVector::iterator; private: /** PRIVATE MEMBER FUNCTIONS */ /** * @brief Calculates the sum of the squared cluster masses. * @arguments q, aq vectors containing the quarks and antiquarks respectively * @return Sum of cluster squared masses M^2_{q[i],aq[i]}. */ Energy2 _clusterMassSum(const PVector & q, const PVector & aq) const; /** * @brief Examines whether the cluster vector (under the given permutation of * the antiquarks) contains colour-octet clusters * @param cv Cluster vector * @param P Permutation, a vector of permutated indices from 0 to * cv.size()-1 */ bool _containsColour8(const ClusterVector & cv, const vector & P) const; /** * @brief A Metropolis-type algorithm which finds a local minimum in the * total sum of cluster masses * @arguments cv cluster vector */ void _doRecoStatistical(ClusterVector & cv) const; /** * @brief Plain colour reconnection as used in Herwig 2.5.0 * @arguments cv cluster vector */ void _doRecoPlain(ClusterVector & cv) const; + + /** + * Baryonic Colour Reconnection model + */ + void _doRecoBaryonic(ClusterVector & cv) const; + + + void _makeBaryonicClusters(ClusterPtr &c1, ClusterPtr &c2, ClusterPtr &c3, + ClusterPtr &newcluster1, ClusterPtr &newcluster2) const; + + /** * @brief Finds the cluster in cv which, if reconnected with the given * cluster cl, would result in the smallest sum of cluster masses. * If no reconnection partner can be found, a pointer to the * original Cluster cl is returned. * @arguments cv cluster vector * cl cluster iterator (must be from cv) which wants to have a reconnection partner * @return iterator to the found cluster, or the original cluster pointer if * no mass-reducing combination can be found */ - ClusterVector::iterator _findRecoPartner(ClusterVector::iterator cl, - ClusterVector & cv) const; + + + CluVecIt _findRecoPartner(CluVecIt cl, ClusterVector & cv) const; + + CluVecIt _findPartnerRapidity(CluVecIt cl, ClusterVector & cv) const; + + CluVecIt _findPartnerBaryonic(CluVecIt cl, ClusterVector & cv, + bool & tetraCand, + const ClusterVector& a, + CluVecIt &baryonic1, + CluVecIt &baryonic2 ) const; + + + /** * @brief Reconnects the constituents of the given clusters to the (only) * other possible cluster combination. * @return pair of pointers to the two new clusters */ - pair _reconnect(ClusterPtr c1, ClusterPtr c2) const; + pair _reconnect(ClusterPtr &c1, ClusterPtr &c2) const; + + /** + * Reconnection method for baryonic reconenction model + */ + pair _reconnectBaryonic(ClusterPtr &c1, ClusterPtr &c2) const; + /** * @brief At random, swap two antiquarks, if not excluded by the * constraint that there must not be any colour-octet clusters. * @arguments q, aq vectors containing the quarks and antiquarks respectively * maxtries maximal number of tries to find a non-colour-octet * reconfiguration * @return Pair of ints indicating the indices of the antiquarks to be * swapped. Returns (-1,-1) if no valid reconfiguration could be * found after maxtries trials */ pair _shuffle(const PVector & q, const PVector & aq, unsigned maxtries = 10) const; + + /** DATA MEMBERS */ + + /** + * Specifies the colour reconnection algorithm to be used. + */ + int _algorithm = 0; + + /** + * The annealing factor is the ratio of two successive temperature steps: + * T_n = _annealingFactor * T_(n-1) + */ + double _annealingFactor = 0.9; + + /** + * Number of temperature steps in the statistical annealing algorithm + */ + unsigned int _annealingSteps = 50; + + /** + * Do we do colour reconnections? + */ + int _clreco = 0; + + /** + * Factor used to determine the initial temperature according to + * InitialTemperature = _initTemp * median {energy changes in a few random + * rearrangements} + */ + double _initTemp = 0.1; + + /** + * Probability that a found reconnection possibility is actually accepted. + */ + double _preco = 0.5; + + + double _precoBaryonic = 0.5; + + /** + * The number of tries per temperature steps is the number of clusters times + * this factor. + */ + double _triesPerStepFactor = 5.0; + /** + * maximum allowed distance in the eta phi space for reconnection to occur + */ + + /** + * Maximium distance for reconnections + */ + Length _maxDistance = picometer; + /** * @return true, if the two partons are splitting products of the same * gluon */ - bool isColour8(cPPtr p, cPPtr q) const; - + bool _isColour8(tcPPtr p, tcPPtr q) const; + + /** + * Option for handling octets + */ + unsigned int _octetOption = 0; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interfaces. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * Private and non-existent assignment operator. */ - ColourReconnector & operator=(const ColourReconnector &); + ColourReconnector & operator=(const ColourReconnector &) = delete; -private: - - /** DATA MEMBERS */ - - /** - * Specifies the colour reconnection algorithm to be used. - */ - int _algorithm; - - /** - * The annealing factor is the ratio of two successive temperature steps: - * T_n = _annealingFactor * T_(n-1) - */ - double _annealingFactor; - - /** - * Number of temperature steps in the statistical annealing algorithm - */ - unsigned _annealingSteps; - - /** - * Do we do colour reconnections? - */ - int _clreco; - - /** - * Factor used to determine the initial temperature according to - * InitialTemperature = _initTemp * median {energy changes in a few random - * rearrangements} - */ - double _initTemp; - - /** - * Probability that a found reconnection possibility is actually accepted. - */ - double _preco; - - /** - * The number of tries per temperature steps is the number of clusters times - * this factor. - */ - double _triesPerStepFactor; - - /** - * Maximium distance for reconnections - */ - Length _maxDistance; - - /** - * Option for handling octets - */ - unsigned int _octetOption; }; } #endif /* HERWIG_ColourReconnector_H */ + diff --git a/Hadronization/PartonSplitter.cc b/Hadronization/PartonSplitter.cc --- a/Hadronization/PartonSplitter.cc +++ b/Hadronization/PartonSplitter.cc @@ -1,149 +1,223 @@ // -*- C++ -*- // // PartonSplitter.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 PartonSplitter class. // #include "PartonSplitter.h" #include #include +#include #include #include #include #include +#include "ThePEG/Interface/Parameter.h" #include #include +#include "ThePEG/Repository/UseRandom.h" #include "Herwig/Utilities/Kinematics.h" #include #include "ClusterHadronizationHandler.h" +#include "CheckId.h" using namespace Herwig; IBPtr PartonSplitter::clone() const { return new_ptr(*this); } IBPtr PartonSplitter::fullclone() const { return new_ptr(*this); } void PartonSplitter::persistentOutput(PersistentOStream & os) const { - os << _quarkSelector << ounit(_gluonDistance,femtometer); + os << _quarkSelector << ounit(_gluonDistance,femtometer) + << _splitGluon << _splitPwtUquark << _splitPwtDquark << _splitPwtSquark; } void PartonSplitter::persistentInput(PersistentIStream & is, int) { - is >> _quarkSelector >> iunit(_gluonDistance,femtometer); + is >> _quarkSelector >> iunit(_gluonDistance,femtometer) + >> _splitGluon >> _splitPwtUquark >> _splitPwtDquark >> _splitPwtSquark; } DescribeClass describePartonSplitter("Herwig::PartonSplitter",""); + void PartonSplitter::Init() { static ClassDocumentation documentation ("This class is reponsible of the nonperturbative splitting of partons"); - + + static Switch interfaceSplit + ("Split", + "Option for different splitting options", + &PartonSplitter::_splitGluon, 1, false, false); + static SwitchOption interfaceSplitDefault + (interfaceSplit, + "ud", + "Normal cluster splitting where only u and d quarks are drawn is used.", + 0); + static SwitchOption interfaceSplitAll + (interfaceSplit, + "uds", + "Alternative cluster splitting where all light quark pairs (u, d, s) can be drawn.", + 1); + + static Parameter interfaceSplitPwtUquark + ("SplitPwtUquark", + "Weight for splitting in U quarks", + &PartonSplitter::_splitPwtUquark, 1, 0.0, 1.0, + false, false, Interface::limited); + static Parameter interfaceSplitPwtDquark + ("SplitPwtDquark", + "Weight for splitting in D quarks", + &PartonSplitter::_splitPwtDquark, 1, 0.0, 1.0, + false, false, Interface::limited); + static Parameter interfaceSplitPwtSquark + ("SplitPwtSquark", + "Weight for splitting in S quarks", + &PartonSplitter::_splitPwtSquark, 0.5, 0.0, 1.0, + false, false, Interface::limited); + } void PartonSplitter::split(PVector & tagged) { // set the gluon c tau once and for all static bool first = true; if(first) { _gluonDistance = hbarc*getParticleData(ParticleID::g)->constituentMass()/ ClusterHadronizationHandler::currentHandler()->minVirtuality2(); first = false; } PVector newtag; Energy2 Q02 = 0.99*sqr(getParticleData(ParticleID::g)->constituentMass()); // Loop over all of the particles in the event. for(PVector::iterator pit = tagged.begin(); pit!=tagged.end(); ++pit) { // only considering gluons so add other particles to list of particles if( (**pit).data().id() != ParticleID::g ) { newtag.push_back(*pit); continue; } // should not have been called for massless or space-like gluons if((**pit).momentum().m2() <= 0.0*sqr(MeV) ) { throw Exception() << "Spacelike or massless gluon m2= " << (**pit).momentum().m2()/GeV2 << "GeV2 in PartonSplitter::split()" << Exception::eventerror; } // time like gluon gets split PPtr ptrQ = PPtr(); PPtr ptrQbar = PPtr(); splitTimeLikeGluon(*pit,ptrQ,ptrQbar); ptrQ->scale(Q02); ptrQbar->scale(Q02); (*pit)->colourLine()->addColoured(ptrQ); (*pit)->addChild(ptrQ); newtag.push_back(ptrQ); (*pit)->antiColourLine()->addAntiColoured(ptrQbar); (*pit)->addChild(ptrQbar); newtag.push_back(ptrQbar); // set the life length of gluon Length distance = UseRandom::rndExp(_gluonDistance); (**pit).setLifeLength((distance/(**pit).mass())*(**pit).momentum()); // assume quarks same position as gluon ptrQ ->setVertex((**pit).decayVertex()); ptrQ ->setLifeLength(Lorentz5Distance()); ptrQbar->setVertex((**pit).decayVertex()); ptrQbar->setLifeLength(Lorentz5Distance()); } swap(tagged,newtag); } void PartonSplitter::splitTimeLikeGluon(tcPPtr ptrGluon, PPtr & ptrQ, PPtr & ptrQbar){ // select the quark flavour - tPDPtr quark = _quarkSelector.select(UseRandom::rnd()); + tPDPtr quark; + long idNew=0; + + switch(_splitGluon){ + case 0: + quark = _quarkSelector.select(UseRandom::rnd()); + break; + case 1: + if ( ptrGluon->momentum().m() < + 2.0 *getParticle(ThePEG::ParticleID::s)->data().constituentMass() ) { + throw Exception() << "Impossible Kinematics in PartonSplitter::splitTimeLikeGluon()" + << Exception::runerror; + } + // Only allow light quarks u,d,s with the probabilities + double prob_d = _splitPwtDquark; + double prob_u = _splitPwtUquark; + double prob_s = _splitPwtSquark; + + int choice = UseRandom::rnd3(prob_u, prob_d, prob_s); + switch(choice) { + case 0: idNew = ThePEG::ParticleID::u; break; + case 1: idNew = ThePEG::ParticleID::d; break; + case 2: idNew = ThePEG::ParticleID::s; break; + } + ptrQ = getParticle(idNew); + ptrQbar = getParticle(-idNew); + break; + } // Solve the kinematics of the two body decay G --> Q + Qbar Lorentz5Momentum momentumQ; Lorentz5Momentum momentumQbar; double cosThetaStar = UseRandom::rnd( -1.0 , 1.0 ); using Constants::pi; double phiStar = UseRandom::rnd( -pi , pi ); - Energy constituentQmass = quark->constituentMass(); - if (ptrGluon->momentum().m() < 2.0*constituentQmass) { + Energy constituentQmass; + if(_splitGluon==0) { + constituentQmass = quark->constituentMass(); + }else{ + constituentQmass = ptrQ->data().constituentMass(); + } + + if (ptrGluon->momentum().m() < 2.0*constituentQmass) { throw Exception() << "Impossible Kinematics in PartonSplitter::splitTimeLikeGluon()" << Exception::eventerror; } Kinematics::twoBodyDecay(ptrGluon->momentum(), constituentQmass, constituentQmass, cosThetaStar, phiStar, momentumQ, momentumQbar ); // Create quark and anti-quark particles of the chosen flavour // and set they 5-momentum (the mass is the constituent one). - ptrQ = new_ptr(Particle(quark )); - ptrQbar = new_ptr(Particle(quark->CC())); + if(_splitGluon==0) { + ptrQ = new_ptr(Particle(quark )); + ptrQbar = new_ptr(Particle(quark->CC())); + } + ptrQ ->set5Momentum( momentumQ ); ptrQbar ->set5Momentum( momentumQbar ); } void PartonSplitter::doinit() { Interfaced::doinit(); // calculate the probabilties for the gluon to branch into each quark type // based on the available phase-space, as in fortran. Energy mg=getParticleData(ParticleID::g)->constituentMass(); for( int ix=1; ix<6; ++ix ) { PDPtr quark = getParticleData(ix); Energy pcm = Kinematics::pstarTwoBodyDecay(mg,quark->constituentMass(), quark->constituentMass()); if(pcm>ZERO) _quarkSelector.insert(pcm/GeV,quark); } if(_quarkSelector.empty()) throw InitException() << "At least one quark must have constituent mass less " << "then the constituent mass of the gluon in " << "PartonSplitter::doinit()" << Exception::runerror; } diff --git a/Hadronization/PartonSplitter.h b/Hadronization/PartonSplitter.h --- a/Hadronization/PartonSplitter.h +++ b/Hadronization/PartonSplitter.h @@ -1,144 +1,172 @@ // -*- C++ -*- // // PartonSplitter.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_PartonSplitter_H #define HERWIG_PartonSplitter_H #include "CluHadConfig.h" #include #include #include "PartonSplitter.fh" namespace Herwig { using namespace ThePEG; /** \ingroup Hadronization * \class PartonSplitter * \brief This class splits the gluons from the end of the shower. * \author Philip Stephens * \author Alberto Ribon * * This class does all of the nonperturbative parton splittings needed * immediately after the end of the showering (both initial and final), * as very first step of the cluster hadronization. * - * \todo change so quark weights can be varied and quarks other - * than u and d can be produced + * the quarks are attributed with different weights for the splitting + * by default only the splitting in u and d quarks is allowed + * the option "set /Herwig/Hadronization/PartonSplitter:Split 1" + * allows for additional splitting into s quarks based on some weight + * in order for that to work the mass of the strange quark has to be changed + * from the default value s.t. m_g > 2m_s + * * * * @see \ref PartonSplitterInterfaces "The interfaces" * defined for PartonSplitter. */ class PartonSplitter: public Interfaced { public: /** * Default constructor */ - PartonSplitter() : _gluonDistance(ZERO) + PartonSplitter() : + _splitPwtUquark(1), + _splitPwtDquark(1), + _splitPwtSquark(0.5), + _gluonDistance(ZERO), + _splitGluon(0) {} /** * This method does the nonperturbative splitting of: * time-like gluons. At the end of the shower the gluons should be * on a "physical" mass shell and should therefore be time-like. * @param tagged The tagged particles to be split * @return The particles which were not split and the products of splitting. */ void split(PVector & tagged); 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: /** * Private and non-existent assignment operator. */ PartonSplitter & operator=(const PartonSplitter &); /** * Non-perturbatively split a time-like gluon, * if something goes wrong null pointers are returned. * @param gluon The gluon to be split * @param quark The quark produced in the splitting * @param anti The antiquark produced in the splitting */ void splitTimeLikeGluon(tcPPtr gluon, PPtr & quark, PPtr & anti); + // probabilities for the different quark types + double _splitPwtUquark; + double _splitPwtDquark; + double _splitPwtSquark; + + private: /** * The selector to pick the type of quark */ Selector _quarkSelector; /** + * A pointer to a Herwig::HadronSelector object for generating hadrons. + */ + + /** * c tau for gluon decays */ Length _gluonDistance; + + /** + * Flag used to determine between normal gluon splitting and alternative gluon splitting + */ + int _splitGluon; + + }; } #endif /* HERWIG_PartonSplitter_H */ diff --git a/MatrixElement/DIS/MEChargedCurrentDIS.cc b/MatrixElement/DIS/MEChargedCurrentDIS.cc --- a/MatrixElement/DIS/MEChargedCurrentDIS.cc +++ b/MatrixElement/DIS/MEChargedCurrentDIS.cc @@ -1,307 +1,312 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the MEChargedCurrentDIS class. // #include "MEChargedCurrentDIS.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Utilities/SimplePhaseSpace.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "Herwig/MatrixElement/HardVertex.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "Herwig/Models/StandardModel/StandardModel.h" #include "ThePEG/Cuts/Cuts.h" #include "ThePEG/Handlers/StandardXComb.h" #include "ThePEG/PDF/PolarizedBeamParticleData.h" using namespace Herwig; MEChargedCurrentDIS::MEChargedCurrentDIS() : _maxflavour(5), _massopt(0) { vector mopt(2,1); mopt[1] = _massopt; massOption(mopt); } void MEChargedCurrentDIS::doinit() { DISBase::doinit(); _wp = getParticleData(ThePEG::ParticleID::Wplus ); _wm = getParticleData(ThePEG::ParticleID::Wminus); // cast the SM pointer to the Herwig SM pointer tcHwSMPtr hwsm=ThePEG::dynamic_ptr_cast(standardModel()); if(!hwsm) throw InitException() << "Must be the Herwig StandardModel class in " << "MEChargedCurrentDIS::doinit" << Exception::abortnow; // vertices _theFFWVertex = hwsm->vertexFFW(); } void MEChargedCurrentDIS::getDiagrams() const { // possible quarks typedef std::vector > Pairvector; Pairvector quarkpair; quarkpair.reserve(6); // don't even think of putting 'break' in here! switch(_maxflavour) { case 6: quarkpair.push_back(make_pair(ParticleID::s, ParticleID::t)); quarkpair.push_back(make_pair(ParticleID::d, ParticleID::t)); quarkpair.push_back(make_pair(ParticleID::b, ParticleID::t)); + [[fallthrough]]; case 5: quarkpair.push_back(make_pair(ParticleID::b, ParticleID::c)); quarkpair.push_back(make_pair(ParticleID::b, ParticleID::u)); + [[fallthrough]]; case 4: quarkpair.push_back(make_pair(ParticleID::s, ParticleID::c)); quarkpair.push_back(make_pair(ParticleID::d, ParticleID::c)); + [[fallthrough]]; case 3: quarkpair.push_back(make_pair(ParticleID::s, ParticleID::u)); + [[fallthrough]]; case 2: quarkpair.push_back(make_pair(ParticleID::d, ParticleID::u)); + [[fallthrough]]; default: ; } // create the diagrams for(int il1=11;il1<=14;++il1) { int il2 = il1%2==0 ? il1-1 : il1+1; for(unsigned int iz=0;iz<2;++iz) { tcPDPtr lepin = iz==1 ? getParticleData(il1) : getParticleData(-il1); tcPDPtr lepout = iz==1 ? getParticleData(il2) : getParticleData(-il2); tcPDPtr inter = lepin->iCharge()-lepout->iCharge()==3 ? _wp : _wm; for(unsigned int iq=0;iqCC(), 1, lepout, 2, first->CC(), -2))); } else { add(new_ptr((Tree2toNDiagram(3), lepin, inter, second , 1, lepout, 2, first , -1))); add(new_ptr((Tree2toNDiagram(3), lepin, inter, first->CC(), 1, lepout, 2, second->CC(), -2))); } } } } } unsigned int MEChargedCurrentDIS::orderInAlphaS() const { return 0; } unsigned int MEChargedCurrentDIS::orderInAlphaEW() const { return 2; } Selector MEChargedCurrentDIS::colourGeometries(tcDiagPtr diag) const { static ColourLines c1("3 5"); static ColourLines c2("-3 -5"); Selector sel; if ( diag->id() == -1 ) sel.insert(1.0, &c1); else sel.insert(1.0, &c2); return sel; } void MEChargedCurrentDIS::persistentOutput(PersistentOStream & os) const { os << _theFFWVertex << _maxflavour << _wp << _wm << _massopt; } void MEChargedCurrentDIS::persistentInput(PersistentIStream & is, int) { is >> _theFFWVertex >> _maxflavour >> _wp >> _wm >> _massopt; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigMEChargedCurrentDIS("Herwig::MEChargedCurrentDIS", "HwMEDIS.so"); void MEChargedCurrentDIS::Init() { static ClassDocumentation documentation ("The MEChargedCurrentDIS class implements the matrix elements " "for leading-order charged current deep inelastic scattering"); static Parameter interfaceMaxFlavour ( "MaxFlavour", "The heaviest incoming quark flavour this matrix element is allowed to handle " "(if applicable).", &MEChargedCurrentDIS::_maxflavour, 5, 2, 6, false, false, true); static Switch interfaceMassOption ("MassOption", "Option for the treatment of the mass of the outgoing quarks", &MEChargedCurrentDIS::_massopt, 0, false, false); static SwitchOption interfaceMassOptionMassless (interfaceMassOption, "Massless", "Treat the outgoing quarks as massless", 0); static SwitchOption interfaceMassOptionMassive (interfaceMassOption, "Massive", "Treat the outgoing quarks as massive", 1); } Selector MEChargedCurrentDIS::diagrams(const DiagramVector & diags) const { Selector sel; for ( DiagramIndex i = 0; i < diags.size(); ++i ) sel.insert(1., i); return sel; } double MEChargedCurrentDIS::helicityME(vector & f1, vector & f2, vector & a1, vector & a2, bool lorder, bool qorder, bool calc) const { // scale Energy2 mb2(scale()); // matrix element to be stored ProductionMatrixElement menew(PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1Half,PDT::Spin1Half); // pick a W boson tcPDPtr ipart = (mePartonData()[0]->iCharge()-mePartonData()[1]->iCharge())==3 ? _wp : _wm; // declare the variables we need VectorWaveFunction inter; double me(0.); Complex diag; // sum over helicities to get the matrix element unsigned int hel[4]; unsigned int lhel1,lhel2,qhel1,qhel2; for(lhel1=0;lhel1<2;++lhel1) { for(lhel2=0;lhel2<2;++lhel2) { // intermediate W inter = _theFFWVertex->evaluate(mb2,3,ipart,f1[lhel1],a1[lhel2]); for(qhel1=0;qhel1<2;++qhel1) { for(qhel2=0;qhel2<2;++qhel2) { hel[0] = lhel1; hel[1] = qhel1; hel[2] = lhel2; hel[3] = qhel2; if(!lorder) swap(hel[0],hel[2]); if(!qorder) swap(hel[1],hel[3]); diag = _theFFWVertex->evaluate(mb2,f2[qhel1],a2[qhel2],inter); me += norm(diag); menew(hel[0],hel[1],hel[2],hel[3]) = diag; } } } } // spin and colour factor me *= 0.25; tcPolarizedBeamPDPtr beam[2] = {dynamic_ptr_cast(mePartonData()[0]), dynamic_ptr_cast(mePartonData()[1])}; if( beam[0] || beam[1] ) { RhoDMatrix rho[2] = {beam[0] ? beam[0]->rhoMatrix() : RhoDMatrix(mePartonData()[0]->iSpin()), beam[1] ? beam[1]->rhoMatrix() : RhoDMatrix(mePartonData()[1]->iSpin())}; me = menew.average(rho[0],rho[1]); } if(calc) _me.reset(menew); return me; } double MEChargedCurrentDIS::me2() const { vector f1,f2; vector a1,a2; bool lorder,qorder; SpinorWaveFunction l1,q1; SpinorBarWaveFunction l2,q2; // lepton wave functions if(mePartonData()[0]->id()>0) { lorder=true; l1 = SpinorWaveFunction (meMomenta()[0],mePartonData()[0],incoming); l2 = SpinorBarWaveFunction(meMomenta()[2],mePartonData()[2],outgoing); } else { lorder=false; l1 = SpinorWaveFunction (meMomenta()[2],mePartonData()[2],outgoing); l2 = SpinorBarWaveFunction(meMomenta()[0],mePartonData()[0],incoming); } // quark wave functions if(mePartonData()[1]->id()>0) { qorder = true; q1 = SpinorWaveFunction (meMomenta()[1],mePartonData()[1],incoming); q2 = SpinorBarWaveFunction(meMomenta()[3],mePartonData()[3],outgoing); } else { qorder = false; q1 = SpinorWaveFunction (meMomenta()[3],mePartonData()[3],outgoing); q2 = SpinorBarWaveFunction(meMomenta()[1],mePartonData()[1],incoming); } // wavefunctions for various helicities for(unsigned int ix=0;ix<2;++ix) { l1.reset(ix); f1.push_back(l1); l2.reset(ix); a1.push_back(l2); q1.reset(ix); f2.push_back(q1); q2.reset(ix); a2.push_back(q2); } return helicityME(f1,f2,a1,a2,lorder,qorder,false); } void MEChargedCurrentDIS::constructVertex(tSubProPtr sub) { // extract the particles in the hard process ParticleVector hard; hard.push_back(sub->incoming().first); hard.push_back(sub->incoming().second); hard.push_back(sub->outgoing()[0]); hard.push_back(sub->outgoing()[1]); // sort out the ordering unsigned int order[4]={0,1,2,3}; bool lorder(true),qorder(true); if(abs(hard[0]->id())<6) swap(hard[0],hard[1]); if(abs(hard[2]->id())<6) swap(hard[2],hard[3]); if(hard[0]->id()<0) { swap(order[0],order[2]); lorder = false; } if(hard[1]->id()<0) { swap(order[1],order[3]); qorder = false; } vector f1,f2; vector a1,a2; SpinorWaveFunction (f1,hard[order[0]], lorder ? incoming : outgoing, !lorder,true); SpinorWaveFunction (f2,hard[order[1]], qorder ? incoming : outgoing, !qorder,true); SpinorBarWaveFunction(a1,hard[order[2]], lorder ? outgoing : incoming, lorder,true); SpinorBarWaveFunction(a2,hard[order[3]], qorder ? outgoing : incoming, qorder,true); helicityME(f1,f2,a1,a2,lorder,qorder,true); // construct the vertex HardVertexPtr hardvertex=new_ptr(HardVertex()); // set the matrix element for the vertex hardvertex->ME(_me); // set the pointers and to and from the vertex for(unsigned int ix=0;ix<4;++ix) { tSpinPtr spin = hard[ix]->spinInfo(); if(ix<2) { tcPolarizedBeamPDPtr beam = dynamic_ptr_cast(hard[ix]->dataPtr()); if(beam) spin->rhoMatrix() = beam->rhoMatrix(); } spin->productionVertex(hardvertex); } } double MEChargedCurrentDIS::A(tcPDPtr lin, tcPDPtr, tcPDPtr qin, tcPDPtr, Energy2) const { double output = 2.; if(qin->id()<0) output *= -1.; if(lin->id()<0) output *= -1; return output; } diff --git a/MatrixElement/DrellYanBase.cc b/MatrixElement/DrellYanBase.cc --- a/MatrixElement/DrellYanBase.cc +++ b/MatrixElement/DrellYanBase.cc @@ -1,911 +1,909 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the DrellYanBase class. // #include "DrellYanBase.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include "Herwig/Shower/RealEmissionProcess.h" using namespace Herwig; DrellYanBase::DrellYanBase() : _channelwgtA(0.12), _channelwgtB(2.00), _nover(0), _maxwgt(0.), _power(2.0),_preqqbar(6.5),_preqg(4.0),_pregqbar(4.0), _min_pt(2.*GeV) {} void DrellYanBase::persistentOutput(PersistentOStream & os) const { os << _channelwgtA << _channelwgtB << _channelweights << _alpha << _power << _preqqbar << _preqg << _pregqbar << ounit( _min_pt, GeV ) << _prefactor; } void DrellYanBase::persistentInput(PersistentIStream & is, int) { is >> _channelwgtA >> _channelwgtB >> _channelweights >> _alpha >> _power >> _preqqbar >> _preqg >> _pregqbar >> iunit( _min_pt, GeV ) >> _prefactor; } // The following static variable is needed for the type // description system in ThePEG. DescribeAbstractClass describeHerwigDrellYanBase("Herwig::DrellYanBase", "Herwig.so"); void DrellYanBase::Init() { static ClassDocumentation documentation ("The DrellYanBase class provides a base class for the" " corrections to Drell-Yan type processes"); static Parameter interfaceQQbarChannelWeight ("QQbarChannelWeight", "The relative weights of the q qbar abd q g channels for selection." " This is a technical parameter for the phase-space generation and " "should not affect the results only the efficiency and fraction" " of events with weight > 1.", &DrellYanBase::_channelwgtA, 0.12, 0.01, 100., false, false, Interface::limited); static Parameter interfaceQGChannelWeight ("QGChannelWeight", "The relative weights of the qg abd qbar g channels for selection." " This is a technical parameter for the phase-space generation and " "should not affect the results only the efficiency and fraction", &DrellYanBase::_channelwgtB, 2., 0.01, 100., false, false, Interface::limited); static Reference interfaceCoupling ("Coupling", "Pointer to the object to calculate the coupling for the correction", &DrellYanBase::_alpha, false, false, true, false, false); static Parameter interfacePower ("Power", "The power for the sampling of the matrix elements", &DrellYanBase::_power, 2.0, 1.0, 10.0, false, false, Interface::limited); static Parameter interfacePrefactorqqbar ("Prefactorqqbar", "The prefactor for the sampling of the q qbar channel", &DrellYanBase::_preqqbar, 5.0, 0.0, 1000.0, false, false, Interface::limited); static Parameter interfacePrefactorqg ("Prefactorqg", "The prefactor for the sampling of the q g channel", &DrellYanBase::_preqg, 3.0, 0.0, 1000.0, false, false, Interface::limited); static Parameter interfacePrefactorgqbar ("Prefactorgqbar", "The prefactor for the sampling of the g qbar channel", &DrellYanBase::_pregqbar, 3.0, 0.0, 1000.0, false, false, Interface::limited); static Parameter interfacePtMin ("minPt", "The pt cut on hardest emision generation" "2*(1-Beta)*exp(-sqr(intrinsicpT/RMS))/sqr(RMS)", &DrellYanBase::_min_pt, GeV, 2.*GeV, ZERO, 100000.0*GeV, false, false, Interface::limited); } void DrellYanBase::doinit() { HwMEBase::doinit(); _channelweights.push_back(_channelwgtA/(1.+_channelwgtA)); _channelweights.push_back(_channelweights[0]+1./(1.+_channelwgtA)/(1+_channelwgtB)); _channelweights.push_back(1.0); _prefactor.push_back(_preqqbar); _prefactor.push_back(_preqg); _prefactor.push_back(_pregqbar); } void DrellYanBase::dofinish() { HwMEBase::dofinish(); if(_nover==0) return; generator()->log() << "DrellYanBase when applying the hard correction " << _nover << " weights larger than one were generated of which" << " the largest was " << _maxwgt << "\n"; } RealEmissionProcessPtr DrellYanBase::applyHardMatrixElementCorrection(RealEmissionProcessPtr born) { // get the quark,antiquark ParticleVector incoming; vector beams; + Lorentz5Momentum phadron; for(unsigned int ix=0;ixbornIncoming().size();++ix) { incoming.push_back(born->bornIncoming()[ix]); tPPtr beam = born->hadrons()[ix]; + phadron+=beam->momentum(); beams.push_back(dynamic_ptr_cast(beam->dataPtr())); } + Energy2 shad = phadron.m2(); pair xnew = born->x(); // ensure that the quark is first if(incoming[0]->id()id()) { swap(incoming[0],incoming[1]); swap(beams[0],beams[1]); swap(xnew.first,xnew.second); } // and the gauge boson Lorentz5Momentum pboson; for(unsigned int ix=0;ixbornOutgoing().size();++ix) { pboson += born->bornOutgoing()[ix]->momentum(); } pboson.rescaleMass(); // calculate the momenta unsigned int iemit,itype; vector pnew; LorentzRotation trans; // if not accepted return - if(!applyHard(incoming,beams,pboson,iemit,itype,pnew,trans,xnew)) return RealEmissionProcessPtr(); + if(!applyHard(incoming,beams,pboson,iemit,itype,pnew,trans,xnew,shad)) + return RealEmissionProcessPtr(); // if applying ME correction create the new particles // first the final-state particles Boost boostv=pboson.findBoostToCM(); trans *=LorentzRotation(boostv); born->transformation(trans); for(unsigned int ix=0;ixbornOutgoing().size();++ix) { Lorentz5Momentum pnew = trans*(born->bornOutgoing()[ix]->momentum()); born->outgoing().push_back(born->bornOutgoing()[ix]->dataPtr()->produceParticle(pnew)); } // then emitter, spectator and emitted // emission of a final-state gluon if(itype==0) { // get the momenta of the new particles Lorentz5Momentum pquark(pnew[0]),panti(pnew[1]),pgluon(pnew[2]); if(iemit==2) swap(pquark,panti); // ensure gluon can be put on shell Lorentz5Momentum ptest(pgluon); if(ptest.boost(-(pquark+panti).boostVector()).e() < getParticleData(ParticleID::g)->constituentMass()) return RealEmissionProcessPtr(); // outgoing gluon born->outgoing().push_back(getParticleData(ParticleID::g)->produceParticle(pgluon)); // incoming particles if(born->bornIncoming()[0]->id()>0) { if(iemit==1) { born->emitter(0); born->spectator(1); } else { born->emitter(1); born->spectator(0); } born->incoming().push_back(born->bornIncoming()[0]->dataPtr()->produceParticle(pquark)); born->incoming().push_back(born->bornIncoming()[1]->dataPtr()->produceParticle(panti)); born->outgoing().back()->incomingColour(born->incoming()[0]); born->outgoing().back()->incomingAntiColour(born->incoming()[1]); } else { if(iemit==1) { born->emitter(1); born->spectator(0); } else { born->emitter(0); born->spectator(1); } born->incoming().push_back(born->bornIncoming()[0]->dataPtr()->produceParticle(panti)); born->incoming().push_back(born->bornIncoming()[1]->dataPtr()->produceParticle(pquark)); born->outgoing().back()->incomingColour(born->incoming()[1]); born->outgoing().back()->incomingAntiColour(born->incoming()[0]); } } else if(itype==1) { Lorentz5Momentum pin(pnew[0]),pout(pnew[1]),pgluon(pnew[2]); if(iemit==2) swap(pin,pout); // ensure outgoing quark can be put on-shell Lorentz5Momentum ptest(pout); if(ptest.boost(-(pin+pgluon).boostVector()).e() < incoming[1]->dataPtr()->constituentMass()) return RealEmissionProcessPtr(); // create the new gluon PPtr newg = getParticleData(ParticleID::g)->produceParticle(pgluon); // create the new outgoing quark PPtr newout= incoming[1]->dataPtr()->CC()->produceParticle(pout); // create the new incoming quark PPtr newin = incoming[0]->dataPtr()->produceParticle(pin); // colours newout->incomingColour(newg); newin->antiColourNeighbour(newg); if(born->bornIncoming()[0]->id()>0) { born->emitter (1); born->spectator(0); born->incoming().push_back(newin); born->incoming().push_back(newg ); } else { born->emitter (0); born->spectator(1); born->incoming().push_back(newg ); born->incoming().push_back(newin); } born->outgoing().push_back(newout); } else if(itype==2) { Lorentz5Momentum pin(pnew[0]),pout(pnew[1]),pgluon(pnew[2]); if(iemit==2) swap(pin,pout); // ensure outgoing antiquark can be put on-shell Lorentz5Momentum ptest(pout); if(ptest.boost(-(pin+pgluon).boostVector()).e() < incoming[0]->dataPtr()->constituentMass()) return RealEmissionProcessPtr(); // create the new gluon PPtr newg = getParticleData(ParticleID::g)->produceParticle(pgluon); // create the new outgoing antiquark PPtr newout= incoming[0]->dataPtr()->CC()->produceParticle(pout); // create the new incoming antiquark PPtr newin = incoming[1]->dataPtr()->produceParticle(pin); // colours newout->incomingAntiColour(newg); newin->colourNeighbour(newg); if(born->bornIncoming()[0]->id()>0) { born->emitter (0); born->spectator(1); born->incoming().push_back(newg ); born->incoming().push_back(newin); } else { born->emitter (1); born->spectator(0); born->incoming().push_back(newin); born->incoming().push_back(newg ); } born->outgoing().push_back(newout); } else assert(false); born->emitted(born->outgoing().size()+1); if(born->bornIncoming()[0]->id()<0) { swap(xnew.first,xnew.second); } born->x(xnew); born->interaction(ShowerInteraction::QCD); return born; } bool DrellYanBase::applyHard(ParticleVector & quarks, vector beams, Lorentz5Momentum boson, unsigned int & iemit,unsigned int & itype, vector & pnew, LorentzRotation & trans, - pair & xout) { + pair & xout, + Energy2 shad) { // check that quark along +z and qbar along -z bool quarkplus=quarks[0]->momentum().z()>quarks[1]->momentum().z(); // calculate the limits on s Energy mb = sqrt(mb2_); Energy2 smin=mb2_; - Energy2 s= - (generator()->currentEvent()->incoming().first ->momentum()+ - generator()->currentEvent()->incoming().second->momentum()).m2(); - Energy2 smax(s); + Energy2 smax(shad); // calculate the rapidity of the boson double yB=0.5*log((boson.e()+boson.z())/ (boson.e()-boson.z())); if(!quarkplus) yB=-yB; // if no phase-space return if(smaxpdf(); assert(pdf[ix]); fx[ix]=pdf[ix]->xfx(beams[ix],quarks[ix]->dataPtr(),mb2_,x[ix]); } // select the type of process and generate the kinematics double rn(UseRandom::rnd()); Energy2 shat(ZERO),uhat(ZERO),that(ZERO); double weight(0.),xnew[2]={1.,1.}; // generate the value of s according to 1/s^2 shat = smax*smin/(smin+UseRandom::rnd()*(smax-smin)); Energy2 jacobian = sqr(shat)*(1./smin-1./smax); double sbar=shat/mb2_; // calculate limits on that Energy2 tmax=mb2_*kappa[0]*(1.-sbar)/(kappa[0]+sbar); Energy2 tmin=shat*(1.-sbar)/(kappa[1]+sbar); // calculate the limits on uhat Energy2 umax(mb2_-shat-tmin),umin(mb2_-shat-tmax); // check inside phase space if(tmax g V if(rn<_channelweights[0]) { // generate t and u according to 1/t+1/u // generate in 1/t if(UseRandom::rndbool(0.5)) { that=tmax*pow(tmin/tmax,UseRandom::rnd()); uhat=mb2_-shat-that; jacobian *=log(tmin/tmax); } // generate in 1/u else { uhat=umax*pow(umin/umax,UseRandom::rnd()); that=mb2_-shat-uhat; jacobian *=log(umin/umax); } Energy4 jacobian2 = jacobian * 2.*uhat*that/(shat-mb2_); // new scale (this is mt^2=pt^2+mb^2) Energy2 scale(uhat*that/shat+mb2_); // the PDF's with the emitted gluon double fxnew[2]; - xnew[0]=exp(yB)/sqrt(s)*sqrt(shat*(mb2_-uhat)/(mb2_-that)); - xnew[1]=shat/(s*xnew[0]); - for(unsigned int ix=0;ix<2;++ix) - {fxnew[ix]=pdf[ix]->xfx(beams[ix],quarks[ix]->dataPtr(),scale,xnew[ix]);} + xnew[0]=exp(yB)/sqrt(shad)*sqrt(shat*(mb2_-uhat)/(mb2_-that)); + xnew[1]=shat/(shad*xnew[0]); + for(unsigned int ix=0;ix<2;++ix) { + fxnew[ix] = xnew[ix]<=1. ? pdf[ix]->xfx(beams[ix],quarks[ix]->dataPtr(),scale,xnew[ix]) : 0.; + } // jacobian and me parts of the weight weight=jacobian2*(sqr(mb2_-that)+sqr(mb2_-uhat))/(sqr(shat)*that*uhat); // pdf part of the weight weight *=fxnew[0]*fxnew[1]*x[0]*x[1]/(fx[0]*fx[1]*xnew[0]*xnew[1]); // finally coupling, colour factor and different channel pieces weight *= 2./3./Constants::pi/_channelweights[0]*_alpha->value(scale); // select the emiting particle iemit=1; if(UseRandom::rnd()_channelweights[1]) { swap(tmax,tmin); tmax=mb2_-shat-tmax; tmin=mb2_-shat-tmin; } that=tmax*pow(tmin/tmax,UseRandom::rnd()); uhat=mb2_-shat-that; Energy4 jacobian2 = jacobian * that*log(tmax/tmin); // new scale (this is mt^2=pt^2+mb^2) Energy2 scale(uhat*that/shat+mb2_); // g qbar -> qbar V double fxnew[2]; if(rn<_channelweights[1]) { itype=2; - xnew[0]=exp(yB)/sqrt(s)*sqrt(shat*(mb2_-uhat)/(mb2_-that)); - xnew[1]=shat/(s*xnew[0]); - fxnew[0]=pdf[0]->xfx(beams[0],getParticleData(ParticleID::g),scale,xnew[0]); - fxnew[1]=pdf[1]->xfx(beams[1],quarks[1]->dataPtr(),scale,xnew[1]); + xnew[0]=exp(yB)/sqrt(shad)*sqrt(shat*(mb2_-uhat)/(mb2_-that)); + xnew[1]=shat/(shad*xnew[0]); + fxnew[0] = xnew[0] <=1. ? pdf[0]->xfx(beams[0],getParticleData(ParticleID::g),scale,xnew[0]) : 0.; + fxnew[1] = xnew[1] <=1. ? pdf[1]->xfx(beams[1],quarks[1]->dataPtr() ,scale,xnew[1]) : 0.; jacobian2/=(_channelweights[1]-_channelweights[0]); } // q g -> q V else { itype=1; - xnew[0]=exp(yB)/sqrt(s)*sqrt(shat*(mb2_-that)/(mb2_-uhat)); - xnew[1]=shat/(s*xnew[0]); - fxnew[0]=pdf[0]->xfx(beams[0],quarks[0]->dataPtr(),scale,xnew[0]); - fxnew[1]=pdf[1]->xfx(beams[1],getParticleData(ParticleID::g),scale,xnew[1]); + xnew[0]=exp(yB)/sqrt(shad)*sqrt(shat*(mb2_-that)/(mb2_-uhat)); + xnew[1]=shat/(shad*xnew[0]); + fxnew[0] = xnew[0] <=1. ? pdf[0]->xfx(beams[0],quarks[0]->dataPtr(),scale,xnew[0]) : 0.; + fxnew[1] = xnew[1] <=1. ? pdf[1]->xfx(beams[1],getParticleData(ParticleID::g),scale,xnew[1]) : 0.; jacobian2/=(_channelweights[2]-_channelweights[1]); } // jacobian and me parts of the weight weight=-jacobian2*(sqr(mb2_-that)+sqr(mb2_-shat))/(sqr(shat)*shat*that); // pdf part of the weight weight *=fxnew[0]*fxnew[1]*x[0]*x[1]/(fx[0]*fx[1]*xnew[0]*xnew[1]); // finally coupling, colour factor and different channel pieces weight *= 0.25/Constants::pi*_alpha->value(scale); // select the emiting particle iemit=1; if(UseRandom::rnd()1.) { ++_nover; _maxwgt=max(_maxwgt,weight); weight=1.; } if(UseRandom::rnd()>weight) return false; // construct the momenta in the rest frame of the boson Lorentz5Momentum pb(ZERO,ZERO,ZERO,mb,mb),pspect,pg,pemit; double cos3 = 0.0; - if(itype==0) - { - pg = Lorentz5Momentum(ZERO,ZERO,ZERO,0.5*(shat-mb2_)/mb,ZERO); - Energy2 tp(that),up(uhat); - double zsign(quarkplus ? -1. : 1.); - if(iemit==2) - { - tp=uhat; - up=that; - zsign *= -1.; - } - pspect = Lorentz5Momentum(ZERO,ZERO,zsign*0.5*(mb2_-tp)/mb, - 0.5*(mb2_-tp)/mb,ZERO); - Energy eemit=0.5*(mb2_-up)/mb; + if(itype==0) { + pg = Lorentz5Momentum(ZERO,ZERO,ZERO,0.5*(shat-mb2_)/mb,ZERO); + Energy2 tp(that),up(uhat); + double zsign(quarkplus ? -1. : 1.); + if(iemit==2) { + tp=uhat; + up=that; + zsign *= -1.; + } + pspect = Lorentz5Momentum(ZERO,ZERO,zsign*0.5*(mb2_-tp)/mb, + 0.5*(mb2_-tp)/mb,ZERO); + Energy eemit=0.5*(mb2_-up)/mb; + cos3 = 0.5/pspect.z()/pg.e()*(sqr(pspect.e())+sqr(pg.e())-sqr(eemit)); + } + else { + pg=Lorentz5Momentum(ZERO,ZERO,ZERO,0.5*(mb2_-uhat)/mb,ZERO); + double zsign(quarkplus ? 1. : -1.); + if(iemit==1) { + if(itype==1) zsign *= -1.; + pspect=Lorentz5Momentum(ZERO,ZERO,0.5*zsign*(shat-mb2_)/mb, + 0.5*(shat-mb2_)/mb); + Energy eemit=0.5*(mb2_-that)/mb; cos3 = 0.5/pspect.z()/pg.e()*(sqr(pspect.e())+sqr(pg.e())-sqr(eemit)); } - else - { - pg=Lorentz5Momentum(ZERO,ZERO,ZERO,0.5*(mb2_-uhat)/mb,ZERO); - double zsign(quarkplus ? 1. : -1.); - if(iemit==1) - { - if(itype==1) zsign *= -1.; - pspect=Lorentz5Momentum(ZERO,ZERO,0.5*zsign*(shat-mb2_)/mb, - 0.5*(shat-mb2_)/mb); - Energy eemit=0.5*(mb2_-that)/mb; - cos3 = 0.5/pspect.z()/pg.e()*(sqr(pspect.e())+sqr(pg.e())-sqr(eemit)); - } - else - { - if(itype==2) zsign *= -1.; - pspect=Lorentz5Momentum(ZERO,ZERO,0.5*zsign*(mb2_-that)/mb, - 0.5*(mb2_-that)/mb); - Energy eemit=0.5*(shat-mb2_)/mb; - cos3 = 0.5/pspect.z()/pg.e()*(-sqr(pspect.e())-sqr(pg.e())+sqr(eemit)); - } + else { + if(itype==2) zsign *= -1.; + pspect=Lorentz5Momentum(ZERO,ZERO,0.5*zsign*(mb2_-that)/mb, + 0.5*(mb2_-that)/mb); + Energy eemit=0.5*(shat-mb2_)/mb; + cos3 = 0.5/pspect.z()/pg.e()*(-sqr(pspect.e())-sqr(pg.e())+sqr(eemit)); } + } // rotate the gluon double sin3(sqrt(1.-sqr(cos3))); double phi(Constants::twopi*UseRandom::rnd()); pg.setX(pg.e()*sin3*cos(phi)); pg.setY(pg.e()*sin3*sin(phi)); pg.setZ(pg.e()*cos3); if(itype==0) { pemit=pb+pg-pspect; } else { if(iemit==1) pemit=pb+pspect-pg; else pemit=pspect+pg-pb; } pemit.rescaleMass(); // find the new CMF Lorentz5Momentum pp[2]; if(itype==0) { if(iemit==1) { pp[0]=pemit; pp[1]=pspect; } else { pp[0]=pspect; pp[1]=pemit; } } else if(itype==1) { pp[1]=pg; if(iemit==1) pp[0]=pemit; else pp[0]=pspect; } else { pp[0]=pg; if(iemit==1) pp[1]=pemit; else pp[1]=pspect; } Lorentz5Momentum pz= quarkplus ? pp[0] : pp[1]; pp[0]/=xnew[0]; pp[1]/=xnew[1]; Lorentz5Momentum plab(pp[0]+pp[1]); plab.rescaleMass(); // construct the boost to rest frame of plab trans=LorentzRotation(plab.findBoostToCM()); pz.transform(trans); // rotate so emitting particle along z axis // rotate so in x-z plane trans.rotateZ(-atan2(pz.y(),pz.x())); // rotate so along trans.rotateY(-acos(pz.z()/pz.vect().mag())); // undo azimuthal rotation trans.rotateZ(atan2(pz.y(),pz.x())); // perform the transforms pb .transform(trans); pspect.transform(trans); pg .transform(trans); pemit .transform(trans); // momenta to be returned pnew.push_back(pemit); pnew.push_back(pspect); pnew.push_back(pg); pnew.push_back(pb); xout.first=xnew[0]; xout.second=xnew[1]; return true; } bool DrellYanBase::softMatrixElementVeto(PPtr parent, PPtr progenitor, const bool & fs, const Energy & highestpT, const vector & ids, const double & z, const Energy & scale, const Energy & pT) { if(fs) return false; // check if me correction should be applied long id[2]={progenitor->id(),parent->id()}; if(id[0]!=id[1]||id[1]==ParticleID::g) return false; // check if hardest so far if(pT0&&ids[0]->id()==ParticleID::g) wgt=mb2_/(shat+uhat)*(sqr(mb2_-that)+sqr(mb2_-shat))/(sqr(shat+uhat)+sqr(uhat)); else if(id[0]>0&&ids[0]->id()==id[0]) wgt=mb2_/(shat+uhat)*(sqr(mb2_-uhat)+sqr(mb2_-that))/(sqr(shat)+sqr(shat+uhat)); else if(id[0]<0&&ids[0]->id()==ParticleID::g) wgt=mb2_/(shat+uhat)*(sqr(mb2_-that)+sqr(mb2_-shat))/(sqr(shat+uhat)+sqr(uhat)); else if(id[0]<0&&ids[0]->id()==id[0]) wgt=mb2_/(shat+uhat)*(sqr(mb2_-uhat)+sqr(mb2_-that))/(sqr(shat)+sqr(shat+uhat)); else return false; if(wgt<.0||wgt>1.) generator()->log() << "Soft ME correction weight too large or " << "negative in DrellYanBase::" << "softMatrixElementVeto()soft weight " << " sbar = " << shat/mb2_ << " tbar = " << that/mb2_ << "weight = " << wgt << "\n"; // return whether or not vetoed return !UseRandom::rndbool(wgt); } RealEmissionProcessPtr DrellYanBase::generateHardest(RealEmissionProcessPtr born, ShowerInteraction inter) { if(inter==ShowerInteraction::QED) return RealEmissionProcessPtr(); useMe(); // get the particles to be showered _beams.clear(); _partons.clear(); // find the incoming particles ParticleVector incoming; _quarkplus = true; ParticleVector particlesToShower; // progenitor particles are produced in z direction. for(unsigned int ix=0;ixbornIncoming().size();++ix) { incoming.push_back(born->bornIncoming()[ix]); tPPtr beam = born->hadrons()[ix]; _beams.push_back(dynamic_ptr_cast(beam->dataPtr())); _partons.push_back( born->bornIncoming()[ix]->dataPtr() ); // check that quark is along +ve z direction if(born->bornIncoming()[ix]->id() > 0 && born->bornIncoming()[ix]->momentum().z() < ZERO ) _quarkplus = false; particlesToShower.push_back( born->bornIncoming()[ix] ); } Lorentz5Momentum pboson; for(unsigned int ix=0;ixbornOutgoing().size();++ix) { pboson += born->bornOutgoing()[ix]->momentum(); } pboson.rescaleMass(); // calculate the rapidity of the boson _yb = 0.5 * log((pboson.e()+pboson.z())/(pboson.e()-pboson.z())); _yb *= _quarkplus ? 1. : -1.; _mass = pboson.mass(); // we are assuming quark first, swap order to ensure this // if antiquark first bool order = _partons[0]->id()<_partons[1]->id(); if(order) { swap(_partons[0],_partons[1]); swap(_beams[0],_beams[1]); } vector pnew; int emission_type(-1); // generate the hard emission and return if no emission if(!getEvent(pnew,emission_type)) { born->pT()[ShowerInteraction::QCD] = _min_pt; return born; } // construct the HardTree object needed to perform the showers ParticleVector newparticles; // make the particles for the HardTree tcPDPtr gluon=getParticleData(ParticleID::g); // create the partons int iemit; // q qbar -> g V ColinePtr newline[2]={new_ptr(ColourLine()),new_ptr(ColourLine())}; if(emission_type==0) { newparticles.push_back(_partons[0]->produceParticle(pnew[0])); newparticles.push_back(_partons[1]->produceParticle(pnew[1])); newparticles.push_back(gluon ->produceParticle(pnew[2])); newline[1]->addColoured(newparticles[0]); newline[1]->addColoured(newparticles[2]); newline[0]->addAntiColoured(newparticles[1]); newline[0]->addAntiColoured(newparticles[2]); iemit = (pnew[0]-pnew[2]).m2()>(pnew[1]-pnew[2]).m2() ? 0 : 1; } // q g -> q V else if(emission_type==1) { iemit =1; newparticles.push_back(_partons[0]->produceParticle(pnew[0])); newparticles.push_back(gluon ->produceParticle(pnew[1])); newparticles.push_back(_partons[1]->CC()->produceParticle(pnew[2])); newline[1]->addColoured(newparticles[0]); newline[1]->addAntiColoured(newparticles[1]); newline[0]->addColoured(newparticles[1]); newline[0]->addColoured(newparticles[2]); } // g qbar -> qbar V else { iemit =0; newparticles.push_back(gluon ->produceParticle(pnew[0])); newparticles.push_back(_partons[1]->produceParticle(pnew[1])); newparticles.push_back(_partons[0]->CC()->produceParticle(pnew[2])); newline[0]->addAntiColoured(newparticles[1]); newline[0]->addColoured(newparticles[0]); newline[1]->addAntiColoured(newparticles[0]); newline[1]->addAntiColoured(newparticles[2]); } int ispect = iemit == 0 ? 1 : 0; if(iemit==0) newline[0]->addColoured(newparticles.back()); else newline[1]->addAntiColoured(newparticles.back()); // compute the boost for the bosons LorentzRotation boost(pboson.findBoostToCM()); boost.boost(pnew[3].boostVector()); born->transformation(boost); for(unsigned int ix=0;ixbornOutgoing().size();++ix) { born->outgoing().push_back(born->bornOutgoing()[ix]->dataPtr()-> produceParticle(born->bornOutgoing()[ix]->momentum())); born->outgoing().back()->transform(boost); } if(!order) { born->incoming().push_back(newparticles[0]); born->incoming().push_back(newparticles[1]); } else { born->incoming().push_back(newparticles[1]); born->incoming().push_back(newparticles[0]); swap(iemit,ispect); } born->outgoing().push_back(newparticles[2]); born->emitter (iemit ); born->spectator(ispect); born->emitted(born->bornOutgoing().size()+2); pair xnew; for(unsigned int ix=0;ix<2;++ix) { double x = born->incoming()[ix]->momentum().rho()/born->hadrons()[ix]->momentum().rho(); if(ix==0) xnew.first = x; else xnew.second = x; } born->x(xnew); born->pT()[ShowerInteraction::QCD] = _pt; born->interaction(ShowerInteraction::QCD); return born; } double DrellYanBase::getResult(int emis_type, Energy pt, double yj) { Energy2 s=sqr(generator()->maximumCMEnergy()); Energy2 m2(sqr(_mass)); Energy2 scale = m2+sqr(pt); Energy et=sqrt(scale); // longitudinal real correction fractions double x = pt*exp( yj)/sqrt(s)+et*exp( _yb)/sqrt(s); double y = pt*exp(-yj)/sqrt(s)+et*exp(-_yb)/sqrt(s); // reject if outside region if(x<0.||x>1.||y<0.||y>1.||x*ypdf()->xfx(_beams[0],_partons[0],m2,x1); pdf[1]=_beams[1]->pdf()->xfx(_beams[1],_partons[1],m2,y1); //qqbar2Zg using Constants::pi; if(emis_type==0) { pdf[2]=_beams[0]->pdf()->xfx(_beams[0],_partons[0],scale,x); pdf[3]=_beams[1]->pdf()->xfx(_beams[1],_partons[1],scale,y); res = 4./3./pi*(sqr(th-m2)+sqr(uh-m2))*pt/(sh*uh*th)*GeV; } //qg2Zq else if(emis_type==1) { pdf[2]=_beams[0]->pdf()->xfx(_beams[0],_partons[0],scale,x); pdf[3]=_beams[1]->pdf()->xfx(_beams[1],getParticleData(ParticleID::g),scale,y); res = -1./2./pi*(sqr(uh-m2)+sqr(sh-m2))*pt/(sh*sh*uh)*GeV; } //qbarg2Zqbar else { pdf[2]=_beams[0]->pdf()->xfx(_beams[0],getParticleData(ParticleID::g),scale,x); pdf[3]=_beams[1]->pdf()->xfx(_beams[1],_partons[1],scale,y); res =- 1./2./pi*(sqr(th-m2)+sqr(sh-m2))*pt/(sh*sh*th)*GeV; } //deals with pdf zero issue at large x if(pdf[0]<=0.||pdf[1]<=0.||pdf[2]<=0.||pdf[3]<=0.) { res=0.; } else { res*=pdf[2]*pdf[3]/pdf[0]/pdf[1]*m2/sh; } res*=_alpha->ratio(sqr(pt)); return res; } bool DrellYanBase::getEvent(vector & pnew, int & emis_type){ // pt cut-off // Energy minp = 0.1*GeV; // maximum pt (half of centre-of-mass energy) Energy maxp = 0.5*generator()->maximumCMEnergy(); // set pt of emission to zero _pt=ZERO; //Working Variables Energy pt; double yj; // limits on the rapidity of the jet double minyj = -8.0,maxyj = 8.0; bool reject; double wgt; emis_type=-1; for(int j=0;j<3;j++) { pt=maxp; double a = _alpha->overestimateValue()*_prefactor[j]*(maxyj-minyj)/(_power-1.); do { // generate next pt pt=GeV/pow(pow(GeV/pt,_power-1)-log(UseRandom::rnd())/a,1./(_power-1.)); // generate rapidity of the jet yj=UseRandom::rnd()*(maxyj-minyj)+ minyj; // calculate rejection weight wgt=getResult(j,pt,yj); wgt/= _prefactor[j]*pow(GeV/pt,_power); reject = UseRandom::rnd()>wgt; //no emission event if p goes past p min - basically set to outside //of the histogram bounds (hopefully hist object just ignores it) if(pt<_min_pt){ pt=ZERO; reject = false; } if(wgt>1.0) { ostringstream s; s << "DrellYanBase::getEvent weight for channel " << j << "is " << wgt << " which is greater than 1"; generator()->logWarning( Exception(s.str(), Exception::warning) ); } } while(reject); // set pt of emission etc if(pt>_pt){ emis_type = j; _pt=pt; _yj=yj; } } //was this an (overall) no emission event? if(_pt<_min_pt){ _pt=ZERO; emis_type = 3; } if(emis_type==3) return false; // generate the momenta of the particles // hadron-hadron cmf Energy2 s=sqr(generator()->maximumCMEnergy()); // transverse energy Energy2 m2(sqr(_mass)); Energy et=sqrt(m2+sqr(_pt)); // first calculate all the kinematic variables // longitudinal real correction fractions double x = _pt*exp( _yj)/sqrt(s)+et*exp( _yb)/sqrt(s); double y = _pt*exp(-_yj)/sqrt(s)+et*exp(-_yb)/sqrt(s); // that and uhat Energy2 th = -sqrt(s)*x*_pt*exp(-_yj); Energy2 uh = -sqrt(s)*y*_pt*exp( _yj); Energy2 sh = x*y*s; if(emis_type==1) swap(th,uh); // decide which was the emitting particle unsigned int iemit=1; // from q qbar if(emis_type==0) { if(UseRandom::rnd() & ids, const double & z, const Energy & scale, const Energy & pT); /** * Apply the POWHEG style correction */ virtual RealEmissionProcessPtr generateHardest(RealEmissionProcessPtr, ShowerInteraction); /** * Set the typed and momenta of the incoming and outgoing partons to * be used in subsequent calls to me() and colourGeometries() * according to the associated XComb object. */ virtual void setKinematics() { HwMEBase::setKinematics(); mb2_ = sHat(); } protected: /** * Return the momenta and type of hard matrix element correction * @param quarks The original incoming particles. * @param beams The BeamParticleData objects * @param boson The momentum of the original outgoing gauge boson * @param iemit Whether the first (0) or second (1) particle emitted * the radiation * @param itype The type of radiated particle (0 is gluon, 1 is quark * and 2 is antiquark) * @param pnew The momenta of the new particles * @param trans The LorentzRotation from the boson rest frame to the new lab * @param xnew The new values of the momentuym fractions * @return Whether or not the matrix element correction needs to be applied */ bool applyHard(ParticleVector & quarks, vector beams, Lorentz5Momentum boson,unsigned int & iemit, unsigned int & itype,vector & pnew, - LorentzRotation & trans, pair & xnew); + LorentzRotation & trans, pair & xnew, + Energy2 shad); /** * Returns the matrix element for a given type of process, * rapidity of the jet \f$y_j\f$ and transverse momentum \f$p_T\f$ * @param emis_type the type of emission, * (0 is \f$q\bar{q}\to Vg\f$, 1 is \f$qg\to Vq\f$ and 2 is \f$g\bar{q}\to V\bar{q}\f$) * @param pt The transverse momentum of the jet * @param yj The rapidity of the jet */ double getResult(int emis_type, Energy pt, double yj); /** * generates the hardest emission (yj,p) * @param pnew The momenta of the new particles * @param emissiontype The type of emission, as for getResult * @return Whether not an emission was generated */ bool getEvent(vector & pnew,int & emissiontype); public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Finalize this object. Called in the run phase just after a * run has ended. Used eg. to write out statistics. */ virtual void dofinish(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ DrellYanBase & operator=(const DrellYanBase &); private: /** * Mass squared of the vector boson */ Energy2 mb2_; /** * Parameters for the old-style ME correction */ //@{ /** * Relative weight for the \f$q\bar{q}\f$ and \f$q/\bar{q}g\f$ channels */ double _channelwgtA; /** * Relative weight for the \f$qg\f$ and \f$\bar{q}g\f$ channels */ double _channelwgtB; /** * Weights for the channels as a vector */ vector _channelweights; /** * Number of weights greater than 1 */ unsigned int _nover; /** * Maximum weight */ double _maxwgt; //@} /** * Constants for the sampling. The distribution is assumed to have the * form \f$\frac{c}{{\rm GeV}}\times\left(\frac{{\rm GeV}}{p_T}\right)^n\f$ */ //@{ /** * The power, \f$n\f$, for the sampling */ double _power; /** * The prefactor, \f$c\f$ for the \f$q\bar{q}\f$ channel */ double _preqqbar; /** * The prefactor, \f$c\f$ for the \f$qg\f$ channel */ double _preqg; /** * The prefactor, \f$c\f$ for the \f$g\bar{q}\f$ channel */ double _pregqbar; /** * The prefactors as a vector for easy use */ vector _prefactor; //@} /** * Properties of the incoming particles */ //@{ /** * Pointers to the BeamParticleData objects */ vector _beams; /** * Pointers to the ParticleDataObjects for the partons */ vector _partons; //@} /** * Properties of the boson and jets */ //@{ /** * The rapidity of the gauge boson */ double _yb; /** * The mass of the gauge boson */ Energy _mass; /** * Whether the quark is in the + or - z direction */ bool _quarkplus; /** * the rapidity of the jet */ double _yj; /** * The transverse momentum of the jet */ Energy _pt; //@} /** * The transverse momentum of the jet */ Energy _min_pt; /** * Pointer to the object calculating the strong coupling */ ShowerAlphaPtr _alpha; }; } #endif /* HERWIG_DrellYanBase_H */ diff --git a/MatrixElement/General/GeneralHardME.cc b/MatrixElement/General/GeneralHardME.cc --- a/MatrixElement/General/GeneralHardME.cc +++ b/MatrixElement/General/GeneralHardME.cc @@ -1,1185 +1,1209 @@ // -*- C++ -*- // // GeneralHardME.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 GeneralHardME class. // #include "GeneralHardME.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/Utilities/EnumIO.h" #include "ThePEG/PDF/PolarizedBeamParticleData.h" #include "ThePEG/Utilities/Debug.h" #include using namespace Herwig; GeneralHardME::GeneralHardME() : incoming_(0, 0), outgoing_(0, 0), diagrams_(0), numberOfDiagrams_(0), colour_(0), numberOfFlows_(0) , debug_(false), scaleChoice_(0), scaleFactor_(1.) { massOption(vector(2,1)); } void GeneralHardME::setProcessInfo(const vector & alldiagrams, ColourStructure colour, bool debug, unsigned int scaleOption, double scaleFactor) { // external particles incoming_ = alldiagrams.at(0).incoming; outgoing_ = alldiagrams.at(0).outgoing; diagrams_ = alldiagrams; numberOfDiagrams_ = alldiagrams.size(); // debug option debug_ = debug; // scale choice scaleChoice_ = scaleOption; scaleFactor_ = scaleFactor; // OffShell options pair offshell(make_pair(false, false)); vector mopt(2,1); if( getParticleData(outgoing_.first )->widthGenerator() || getParticleData(outgoing_.first )-> massGenerator()) { offshell.first = true; mopt[0] = 2; } if( getParticleData(outgoing_.second)->widthGenerator() || getParticleData(outgoing_.second)-> massGenerator() ) { offshell.second = true; mopt[1] = 2; } if(outgoing_.first == incoming_.first || outgoing_.first == incoming_.second ) mopt[0] = 0; if(outgoing_.second == incoming_.first || outgoing_.second == incoming_.second ) mopt[1] = 0; massOption(mopt); if( offshell.first == true && offshell.second == true && abs(outgoing_.first) == abs(outgoing_.second) ) rescalingOption(3); // colour structure colourStructure_ = colour; switch (colour) { // colour neutral process case Colour11to11: colour_ = vector(1,DVector(1,1.)); numberOfFlows_ = 1; break; // colour neutral -> 3 3bar or swap process case Colour11to33bar: case Colour33barto11: colour_ = vector(1,DVector(1,3.)); numberOfFlows_ = 1; break; // colour neutral -> 8 8 process or swap case Colour11to88: case Colour88to11 : colour_ = vector(1,DVector(1,8.)); numberOfFlows_ = 1; break; // colour 33 -> 33 or 3bar3bar -> 3bar3bar process // or colour 33bar -> 33bar case Colour33to33: case Colour3bar3barto3bar3bar: case Colour33barto33bar: colour_ = vector(4, DVector(4, 0.)); colour_[0][0] = colour_[1][1] = 2.; colour_[2][2] = colour_[3][3] = 9.; colour_[0][1] = colour_[1][0] = -2./3.; colour_[0][2] = colour_[2][0] = 0.; colour_[0][3] = colour_[3][0] = 4.; colour_[1][2] = colour_[2][1] = 4.; colour_[1][3] = colour_[3][1] = 0.; colour_[2][3] = colour_[3][2] = 3.; numberOfFlows_ = 4; break; // colour 3 3bar -> 6 6bar case Colour33barto66bar: case Colour33barto6bar6: colour_ = vector(10, DVector(10, 0.)); // diagonals for(unsigned int ix=0;ix<4;++ix){ colour_[ix][ix] = 1.5; colour_[ix+4][ix+4] = 27./16.; } colour_[8][8]=colour_[9][9]=27./4.; // 0 colour_[0][1] = colour_[1][0] = 0.5; colour_[0][2] = colour_[2][0] = 0.5; colour_[0][3] = colour_[3][0] = 0.; colour_[0][4] = colour_[4][0] = 3./2.; colour_[0][5] = colour_[5][0] = 1./2.; colour_[0][6] = colour_[6][0] = 1./2.; colour_[0][7] = colour_[7][0] = 0.; // 1 colour_[1][2] = colour_[2][1] = 0.; colour_[1][3] = colour_[3][1] = 0.5; colour_[1][4] = colour_[4][1] = 1./2.; colour_[1][5] = colour_[5][1] = 3./2.; colour_[1][6] = colour_[6][1] = 0.; colour_[1][7] = colour_[7][1] = 1./2.; // 2 colour_[2][3] = colour_[3][2] = 0.5; colour_[2][4] = colour_[4][2] = 1./2.; colour_[2][5] = colour_[5][2] = 0.; colour_[2][6] = colour_[6][2] = 3./2.; colour_[2][7] = colour_[7][2] = 1./2.; // 3 colour_[3][4] = colour_[4][3] = 0.; colour_[3][5] = colour_[5][3] = 1./2.; colour_[3][6] = colour_[6][3] = 1./2.; colour_[3][7] = colour_[7][3] = 3./2.; // 4 colour_[4][5] = colour_[5][4] = 9./16.; colour_[4][6] = colour_[6][4] = 9./16.; colour_[4][7] = colour_[7][4] = 3./16.; colour_[4][8] = colour_[8][4] = 9./8.; colour_[4][9] = colour_[9][4] = 3./8.; // 5 colour_[5][6] = colour_[6][5] = 3./16.; colour_[5][7] = colour_[7][5] = 9./16.; colour_[5][8] = colour_[8][5] = 3./8.; colour_[5][9] = colour_[9][5] = 9./8.; //6 colour_[6][7] = colour_[7][6] = 9./16.; colour_[6][8] = colour_[8][6] = 3./8.; colour_[6][9] = colour_[9][6] = 9./8.; // 7 colour_[7][8] = colour_[8][7] = 9./8.; colour_[7][9] = colour_[9][7] = 3./8.; // 8 colour_[8][9] = colour_[9][8] = 9./4.; numberOfFlows_ = 10; break; // colour 33bar -> 88, 88 -> 33bar case Colour33barto88: case Colour88to33bar: case Colour38to83: case Colour38to38: case Colour3bar8to83bar: case Colour3bar8to3bar8: colour_ = vector(3, DVector(3, 0.)); colour_[0][0] = colour_[1][1] = 16./3.; colour_[0][1] = colour_[1][0] = -2./3.; colour_[2][2]=24.; colour_[0][2] = colour_[2][0] = 4.; colour_[1][2] = colour_[2][1] = 4.; numberOfFlows_ = 3; break; case Colour88to88: { colour_ = vector(9, DVector(9, 0.)); double on1=19./6.,on2=64.; double off1=-1./3.,off2=2./3.,off3=8.,off4=16./3.,off5=-2./3.; // octet exchange colour_[0][0] = colour_[1][1] = colour_[2][2]=on1; colour_[3][3] = colour_[4][4] = colour_[5][5]=on1; colour_[0][1] = colour_[1][0] = off1; colour_[0][2] = colour_[2][0] = off1; colour_[0][3] = colour_[3][0] = off1; colour_[0][4] = colour_[4][0] = off1; colour_[0][5] = colour_[5][0] = off2; colour_[1][2] = colour_[2][1] = off1; colour_[1][3] = colour_[3][1] = off2; colour_[1][4] = colour_[4][1] = off1; colour_[1][5] = colour_[5][1] = off1; colour_[2][3] = colour_[3][2] = off1; colour_[2][4] = colour_[4][2] = off2; colour_[2][5] = colour_[5][2] = off1; colour_[3][4] = colour_[4][3] = off1; colour_[3][5] = colour_[5][3] = off1; colour_[4][5] = colour_[5][4] = off1; // singlet exchange colour_[6][6] = colour_[7][7] = colour_[8][8] = on2; colour_[6][7] = colour_[7][6] = off3; colour_[6][8] = colour_[8][6] = off3; colour_[7][8] = colour_[8][7] = off3; // octet singlet interference colour_[0][6] = colour_[6][0] = off4; colour_[1][6] = colour_[6][1] = off4; colour_[2][6] = colour_[6][2] = off5; colour_[3][6] = colour_[6][3] = off4; colour_[4][6] = colour_[6][4] = off5; colour_[5][6] = colour_[6][5] = off4; colour_[0][7] = colour_[7][0] = off5; colour_[1][7] = colour_[7][1] = off4; colour_[2][7] = colour_[7][2] = off4; colour_[3][7] = colour_[7][3] = off4; colour_[4][7] = colour_[7][4] = off4; colour_[5][7] = colour_[7][5] = off5; colour_[0][8] = colour_[8][0] = off4; colour_[1][8] = colour_[8][1] = off5; colour_[2][8] = colour_[8][2] = off4; colour_[3][8] = colour_[8][3] = off5; colour_[4][8] = colour_[8][4] = off4; colour_[5][8] = colour_[8][5] = off4; numberOfFlows_ = 9; break; } case Colour33barto18 : case Colour33barto81 : case Colour38to13 : case Colour38to31 : case Colour3bar8to13bar: case Colour3bar8to3bar1: colour_ = vector(1,DVector(1,4.)); numberOfFlows_ = 1; break; case Colour88to18 : case Colour88to81: colour_ = vector(1,DVector(1,24.)); numberOfFlows_ = 1; break; case Colour88to66bar: colour_ = vector(12, DVector(12, 0.)); // diagonals for(unsigned int ix=0;ix<12;++ix) colour_[ix][ix] = 4.; // 1 1 block colour_[ 0][ 1] = colour_[ 1][ 0] = 4./3.; colour_[ 0][ 2] = colour_[ 2][ 0] = 4./3.; colour_[ 0][ 3] = colour_[ 3][ 0] = 0.5 ; colour_[ 1][ 2] = colour_[ 2][ 1] = 0.5 ; colour_[ 1][ 3] = colour_[ 3][ 1] = 4./3.; colour_[ 2][ 3] = colour_[ 3][2] = 4./3.; // 1 2 and 2 1 blocks colour_[ 0][ 4] = colour_[ 4][ 0] = 4./3.; colour_[ 1][ 5] = colour_[ 5][ 1] = 4./3.; colour_[ 2][ 6] = colour_[ 6][ 2] = 4./3.; colour_[ 3][ 7] = colour_[ 7][ 3] = 4./3.; colour_[ 0][ 7] = colour_[ 7][ 0] = -1./6.; colour_[ 1][ 6] = colour_[ 6][ 1] = -1./6.; colour_[ 2][ 5] = colour_[ 5][ 2] = -1./6.; colour_[ 3][ 4] = colour_[ 4][ 3] = -1./6.; // 1 3 and 3 1 blocks colour_[ 0][11] = colour_[11][ 0] = 4./3.; colour_[ 1][10] = colour_[10][ 1] = 4./3.; colour_[ 2][ 9] = colour_[ 9][ 2] = 4./3.; colour_[ 3][ 8] = colour_[ 8][ 3] = 4./3.; colour_[ 0][ 8] = colour_[ 8][ 0] = -1./6.; colour_[ 1][ 9] = colour_[ 9][ 1] = -1./6.; colour_[ 2][10] = colour_[10][ 2] = -1./6.; colour_[ 3][11] = colour_[11][ 3] = -1./6.; // 2 2 block colour_[ 4][ 5] = colour_[ 5][ 4] = 4./3.; colour_[ 4][ 6] = colour_[ 6][ 4] = 4./3.; colour_[ 4][ 7] = colour_[ 7][ 4] = 0.5 ; colour_[ 5][ 6] = colour_[ 6][ 5] = 0.5 ; colour_[ 5][ 7] = colour_[ 7][ 5] = 4./3.; colour_[ 6][ 7] = colour_[ 7][ 6] = 4./3.; // 2 3 and 3 2 blocks colour_[ 4][ 8] = colour_[ 8][ 4] = -0.5 ; colour_[ 4][ 9] = colour_[ 9][ 4] = -1./6.; colour_[ 4][10] = colour_[10][ 4] = -1./6.; colour_[ 4][11] = colour_[11][ 4] = 0.5 ; colour_[ 5][ 8] = colour_[ 8][ 5] = -1./6.; colour_[ 5][ 9] = colour_[ 9][ 5] = -0.5 ; colour_[ 5][10] = colour_[10][ 5] = 0.5 ; colour_[ 5][11] = colour_[11][ 5] = -1./6.; colour_[ 6][ 8] = colour_[ 8][ 6] = -1./6.; colour_[ 6][ 9] = colour_[ 9][ 6] = 0.5 ; colour_[ 6][10] = colour_[10][ 6] = -0.5 ; colour_[ 6][11] = colour_[11][ 6] = -1./6.; colour_[ 7][ 8] = colour_[ 8][ 7] = 0.5 ; colour_[ 7][ 9] = colour_[ 9][ 7] = -1./6.; colour_[ 7][10] = colour_[10][ 7] = -1./6.; colour_[ 7][11] = colour_[11][ 7] = -0.5 ; // 3 3 block colour_[ 8][ 9] = colour_[ 9][ 8] = 4./3.; colour_[ 8][10] = colour_[10][ 8] = 4./3.; colour_[ 8][11] = colour_[11][ 8] = 0.5 ; colour_[ 9][10] = colour_[10][ 9] = 0.5 ; colour_[ 9][11] = colour_[11][ 9] = 4./3.; colour_[10][11] = colour_[11][10] = 4./3.; numberOfFlows_ = 12; break; case Colour33to61: case Colour33to16: case Colour3bar3barto6bar1: case Colour3bar3barto16bar: colour_ = vector(2, DVector(2, 0.)); colour_[1][1] = colour_[0][0] = 9./4.; colour_[0][1] = colour_[1][0] = 3./4.; numberOfFlows_ = 2; break; case Colour38to3bar6: case Colour38to63bar: colour_ = vector(8, DVector(8, 0.)); // diagonals for(unsigned int ix=0;ix<8;++ix) colour_[ix][ix] = 3.; colour_[0][1] = colour_[1][0] = 1.; colour_[0][2] = colour_[2][0] = 1.; colour_[0][3] = colour_[3][0] = 0.; colour_[0][4] = colour_[4][0] = 1.; colour_[0][5] = colour_[5][0] = 3.; colour_[0][6] = colour_[6][0] = 1.; colour_[0][7] = colour_[7][0] = 0.; // 1 colour_[1][2] = colour_[2][1] = 0.; colour_[1][3] = colour_[3][1] = 1.; colour_[1][4] = colour_[4][1] = 3.; colour_[1][5] = colour_[5][1] = 1.; colour_[1][6] = colour_[6][1] = 0.; colour_[1][7] = colour_[7][1] = 1.; // 2 colour_[2][3] = colour_[3][2] = 1.; colour_[2][4] = colour_[4][2] = 0.; colour_[2][5] = colour_[5][2] = 1.; colour_[2][6] = colour_[6][2] = 3.; colour_[2][7] = colour_[7][2] = 1.; // 3 colour_[3][4] = colour_[4][3] = 1.; colour_[3][5] = colour_[5][3] = 0.; colour_[3][6] = colour_[6][3] = 1.; colour_[3][7] = colour_[7][3] = 3.; // 4 colour_[4][5] = colour_[5][4] = 1.; colour_[4][6] = colour_[6][4] = 0.; colour_[4][7] = colour_[7][4] = 1.; // 5 colour_[5][6] = colour_[6][5] = 1.; colour_[5][7] = colour_[7][5] = 0.; //6 colour_[6][7] = colour_[7][6] = 1.; numberOfFlows_ = 8; break; case Colour33to13bar: case Colour33to3bar1: case Colour3bar3barto13: case Colour3bar3barto31: colour_ = vector(1, DVector(1, 6.)); numberOfFlows_ = 1; break; case Colour33to83bar: case Colour33to3bar8: case Colour3bar3barto83: case Colour3bar3barto38: case Colour38to3bar3bar: case Colour3bar8to33: colour_ = vector(3, DVector(3, 0.)); colour_[0][0]=colour_[1][1]=colour_[2][2]=8.; colour_[0][1]=colour_[1][0]=-4.; colour_[0][2]=colour_[2][0]=-4.; colour_[1][2]=colour_[2][1]=-4.; numberOfFlows_ = 3; break; default: assert(false); } if(Debug::level > 1 ) { generator()->log() << "Set up 2->2 ME for " << getParticleData(incoming_.first )->PDGName() << " " << getParticleData(incoming_.second)->PDGName() << " -> " << getParticleData(outgoing_.first )->PDGName() << " " << getParticleData(outgoing_.second)->PDGName() << "\n"; for(unsigned int ix=0;ixlog() << "Diagram " << ix << " has " << alldiagrams[ix].incoming.first << " " << alldiagrams[ix].incoming.second << " -> " << alldiagrams[ix].outgoing.first << " " << alldiagrams[ix].outgoing.second << "\n"; generator()->log() << "Type " << alldiagrams[ix].channelType << " " << alldiagrams[ix].ordered.first << " " << alldiagrams[ix].ordered.second << "\n"; if(alldiagrams[ix].intermediate) generator()->log() << "Intermediate " << alldiagrams[ix].intermediate->PDGName() << "\n"; generator()->log() << "vertices " << alldiagrams[ix].vertices.first ->fullName() << " " << alldiagrams[ix].vertices.second->fullName() << "\n"; } } } void GeneralHardME::getDiagrams() const { //get ParticleData pointers for external particles tcPDPtr ina = getParticleData(getIncoming().first); tcPDPtr inb = getParticleData(getIncoming().second); tcPDPtr outa = getParticleData(getOutgoing().first); tcPDPtr outb = getParticleData(getOutgoing().second); - + + bool hasThreePoints = false; for(HPCount idx = 0; idx < numberOfDiagrams_; ++idx) { const HPDiagram & current = getProcessInfo()[idx]; tcPDPtr offshell = current.intermediate; if(!offshell) continue; //t-channel if(current.channelType == HPDiagram::tChannel) { + hasThreePoints = true; if(offshell->id() < 0) offshell = offshell->CC(); if(current.ordered.second) add(new_ptr((Tree2toNDiagram(3), ina, offshell, inb, 1, outa, 2, outb, -(idx+1)))); else add(new_ptr((Tree2toNDiagram(3), ina, offshell, inb, 2, outa, 1, outb, -(idx+1)))); } //s-channel - else if(current.channelType == HPDiagram::sChannel) + else if(current.channelType == HPDiagram::sChannel) { + hasThreePoints = true; add(new_ptr((Tree2toNDiagram(2), ina, inb, 1, offshell, 3, outa, 3, outb, -(idx+1)))); + } else throw MEException() << "getDiagrams() - Unknown diagram in matrix element " << fullName() << Exception::runerror; } + if(!hasThreePoints) { + add(new_ptr((Tree2toNDiagram(2), ina, inb, 1, outa, + 3, outa, 3, outb, -1))); + } } unsigned int GeneralHardME::orderInAlphaS() const { unsigned int order(0); for(HPCount idx = 0; idx < numberOfDiagrams_; ++idx) { unsigned int tOrder = diagrams_[idx].vertices.first->orderInGs() + diagrams_[idx].vertices.second->orderInGs(); if(tOrder > order) order = tOrder; } return order; } unsigned int GeneralHardME::orderInAlphaEW() const { unsigned int order(0); for(HPCount idx = 0; idx < numberOfDiagrams_; ++idx) { unsigned int tOrder = diagrams_[idx].vertices.first->orderInGem() + diagrams_[idx].vertices.second->orderInGem(); if(tOrder > order) order = tOrder; } return order; } Selector GeneralHardME::diagrams(const DiagramVector & diags) const { Selector sel; for ( DiagramIndex i = 0; i < diags.size(); ++i ) { if(abs(diags[i]->id()) == int(diagram_+1)) sel.insert(1., i); } return sel; } void GeneralHardME::persistentOutput(PersistentOStream & os) const { os << incoming_ << outgoing_ << diagrams_ << colour_ << oenum(colourStructure_) << numberOfDiagrams_ << numberOfFlows_ << debug_ << scaleChoice_ << scaleFactor_; } void GeneralHardME::persistentInput(PersistentIStream & is, int) { is >> incoming_ >> outgoing_ >> diagrams_ >> colour_ >> ienum(colourStructure_) >> numberOfDiagrams_ >> numberOfFlows_ >> debug_ >> scaleChoice_ >> scaleFactor_; } // The following static variable is needed for the type // description system in ThePEG. DescribeAbstractClass describeHerwigGeneralHardME("Herwig::GeneralHardME", "Herwig.so"); void GeneralHardME::Init() { static ClassDocumentation documentation ("This class is designed to be a base class for a specific spin " "configuration where no matrix element exists, i.e. when processes " "are created automaticlly for a different model."); } Selector GeneralHardME::colourGeometries(tcDiagPtr diag) const { // get the current diagram const HPDiagram & current = getProcessInfo()[abs(diag->id()) - 1]; Selector sel; switch(colourStructure_) { case Colour11to11: static ColourLines f11to11(""); sel.insert(1.,&f11to11); break; case Colour11to33bar: static ColourLines f11to33bar[2]={ColourLines("4 -5"), ColourLines("4 2 -5")}; if(current.channelType == HPDiagram::tChannel) sel.insert(1.,&f11to33bar[1]); else sel.insert(1.,&f11to33bar[0]); break; case Colour11to88: static ColourLines f11to88[2]={ColourLines("4 -5, 5 -4"), ColourLines("4 2 -5,5 -2 4")}; if(current.channelType == HPDiagram::tChannel) sel.insert(1.,&f11to88[1]); else sel.insert(1.,&f11to88[0]); break; case Colour33to33: static ColourLines f33to33[4]={ColourLines("1 2 5, 3 -2 4"), ColourLines("1 2 4, 3 -2 5"), ColourLines("1 4, 3 5"), ColourLines("1 5, 3 4")}; static ColourLines f33to33s[4]={ColourLines("1 3:1 4, 2 3:2 5"), ColourLines("1 3:2 4, 2 3:1 5"), ColourLines("1 3:1 5, 2 3:2 4"), ColourLines("1 3:2 5, 2 3:1 4")}; static ColourLines f33to33t[2]={ColourLines("1 4, 2 5"), ColourLines("1 5, 2 4")}; if(current.intermediate->iColour() == PDT::Colour8) sel.insert(1.,current.ordered.second ? &f33to33[0] : &f33to33[1]); else if(current.intermediate->iColour() == PDT::Colour6) { sel.insert(1., &f33to33s[2*(flow_-2)+UseRandom::irnd(0,2)]); } else if(current.intermediate->iColour() == PDT::Colour3bar) { sel.insert(1., &f33to33t[flow_-2]); } else sel.insert(1.,current.ordered.second ? &f33to33[2] : &f33to33[3]); break; case Colour3bar3barto3bar3bar: static ColourLines f3bar3barto3bar3bar[4]={ColourLines("-1 -2 -5, -3 2 -4"), ColourLines("-1 -2 -4, -3 2 -5"), ColourLines("-1 -4, -3 -5"), ColourLines("-1 -5, -3 -4")}; static ColourLines f3bar3barto3bar3bars[4]= {ColourLines("-1 -3:1 -4, -2 -3:2 -5"), ColourLines("-1 -3:2 -4, -2 -3:1 -5"), ColourLines("-1 -3:1 -5, -2 -3:2 -4"), ColourLines("-1 -3:2 -5, -2 -3:1 -4")}; static ColourLines f3bar3barto3bar3bart[2]= {ColourLines("-1 -4, -2 -5"), ColourLines("-1 -5, -2 -4")}; if(current.intermediate->iColour() == PDT::Colour8) { sel.insert(1.,current.ordered.second ? &f3bar3barto3bar3bar[0] : &f3bar3barto3bar3bar[1]); } else if(current.intermediate->iColour() == PDT::Colour6bar) { sel.insert(1., &f3bar3barto3bar3bars[2*(flow_-2)+UseRandom::irnd(0,2)]); } else if(current.intermediate->iColour() == PDT::Colour3) { sel.insert(1., &f3bar3barto3bar3bart[flow_-2]); } else sel.insert(1.,current.ordered.second ? &f3bar3barto3bar3bar[2] : &f3bar3barto3bar3bar[3]); break; case Colour33barto33bar: static ColourLines - f33barto33bar[4]={ColourLines("1 2 -3, 4 -2 -5"), + f33barto33bar[5]={ColourLines("1 2 -3, 4 -2 -5"), ColourLines("1 3 4, -2 -3 -5"), ColourLines("1 4, -3 -5"), - ColourLines("1 -2, 4 -5")}; - if(current.channelType == HPDiagram::tChannel) - sel.insert(1.,current.intermediate->iColour() == PDT::Colour8 ? - &f33barto33bar[0] : &f33barto33bar[2]); + ColourLines("1 -2, 4 -5"), + ColourLines("1 -3, 4 -5")}; + if(current.channelType == HPDiagram::tChannel) { + if(current.ordered.second) { + sel.insert(1.,current.intermediate->iColour() == PDT::Colour8 ? + &f33barto33bar[0] : &f33barto33bar[2]); + } + else { + sel.insert(1.,&f33barto33bar[2*(flow_-2)+2]); + } + } else sel.insert(1.,current.intermediate->iColour() == PDT::Colour8 ? &f33barto33bar[1] : &f33barto33bar[3]); break; case Colour33barto11: static ColourLines f33barto11[2]={ColourLines("1 -2"), ColourLines("1 2 -3")}; if(current.channelType == HPDiagram::tChannel) sel.insert(1.,&f33barto11[1]); else sel.insert(1.,&f33barto11[0]); break; case Colour33barto88: static ColourLines f33barto88[5]={ColourLines("1 4, -4 2 5, -5 -3"), ColourLines("1 5, -5 2 4, -4 -3"), ColourLines("1 3 4, -5 -3 -2, -4 5"), ColourLines("1 3 5, -4 -3 -2, -5 4"), ColourLines("1 -2,4 -5, 5 -4")}; if(current.channelType == HPDiagram::tChannel) sel.insert(1.,current.ordered.second ? &f33barto88[0] : &f33barto88[1]); else if(current.intermediate->iColour() == PDT::Colour8) sel.insert(1.,&f33barto88[flow_+2]); else sel.insert(1.,&f33barto88[4]); break; case Colour33barto18: static ColourLines f33barto18[3]={ColourLines("1 2 5, -3 -5"), ColourLines("1 5, -5 2 -3"), ColourLines("1 3 5,-2 -3 -5")}; if(current.channelType == HPDiagram::tChannel) sel.insert(1.,current.ordered.second ? &f33barto18[0] : &f33barto18[1]); else sel.insert(1.,&f33barto18[2]); break; case Colour33barto81: static ColourLines f33barto81[3]={ColourLines("1 4, -4 2 -3"), ColourLines("-3 -4, 1 2 4"), ColourLines("1 3 4,-2 -3 -4")}; if(current.channelType == HPDiagram::tChannel) sel.insert(1.,current.ordered.second ? &f33barto81[0] : &f33barto81[1]); else sel.insert(1.,&f33barto81[2]); break; case Colour88to11: static ColourLines f88barto11[2]={ColourLines("1 -2, 2 -1"), ColourLines("1 -2 -3, 3 2 -1")}; if(current.channelType == HPDiagram::tChannel) sel.insert(1.,&f88barto11[1]); else sel.insert(1.,&f88barto11[0]); break; case Colour88to33bar: static ColourLines f88to33bar[5]={ColourLines("1 4, -3 -5, 3 2 -1"), ColourLines("-1 -5, 1 2 -3, 3 4"), ColourLines("2 -1, 1 3 4, -2 -3 -5"), ColourLines("1 -2, -1 -3 -5, 2 3 4"), ColourLines("1 -2, 2 -1, 4 -5")}; if(current.channelType == HPDiagram::tChannel) sel.insert(1.,current.ordered.second ? &f88to33bar[0] : &f88to33bar[1]); else if(current.intermediate->iColour() == PDT::Colour8 ) sel.insert(1.,&f88to33bar[flow_+2]); else sel.insert(1.,&f88to33bar[4]); break; case Colour88to88: static ColourLines f88to88s[9]={ColourLines("-1 2, 1 3 5, -5 4, -2 -3 -4"), ColourLines("-1 2, 1 3 4, -4 5, -2 -3 -5"), ColourLines(""), ColourLines("1 -2, -1 -3 -4, 4 -5, 2 3 5"), ColourLines(""), ColourLines("1 -2, -1 -3 -5, 5 -4, 2 3 4"), ColourLines("1 -2, 2 -1, 4 -5, 5 -4"), ColourLines(""), ColourLines("")}; static ColourLines f88to88t[9]={ColourLines(""), ColourLines("1 4, -1 -2 3, -2 -5, -3 2 5"), ColourLines("-1 -4, 1 2 5, -3 -5, 3 -2 4"), ColourLines("-1 -4, 1 2 -3, 3 5, 4 -2 -5"), ColourLines("1 4, -1 -2 -5, 3 5, -3 2 -4"), ColourLines(""), ColourLines(""), ColourLines("1 4, -1 -4, 3 5, -5 -3"), ColourLines("")}; static ColourLines f88to88u[9]={ColourLines("1 4, -1 -2 3, -3 -5, -4 2 5"), ColourLines(""), ColourLines("1 5, -1 -2 -4, 3 4, -3 2 -5"), ColourLines(""), ColourLines("-1 -5, 1 2 4, -3 -4, 3 -2 5"), ColourLines("-1 -5, 1 2 -3, 3 4, 5 -2 -4"), ColourLines(""), ColourLines(""), ColourLines("1 5, -1 -5, 3 4, -3 -4")}; if(current.channelType == HPDiagram::sChannel) { sel.insert(1., &f88to88s[flow_]); } else if(current.channelType == HPDiagram::tChannel) { if(current.ordered.second) { sel.insert(1., &f88to88t[flow_]); } else { sel.insert(1., &f88to88u[flow_]); } } break; case Colour38to13: static ColourLines f38to13[2]={ColourLines("1 2 -3, 3 5"), ColourLines("1 -2, 2 3 5")}; if(current.channelType == HPDiagram::tChannel) { sel.insert(1.,&f38to13[0]); } else { sel.insert(1.,&f38to13[1]); } break; case Colour38to31: static ColourLines f38to31[2]={ColourLines("1 2 -3, 3 4"), ColourLines("1 -2, 2 3 4 ")}; if(current.channelType == HPDiagram::tChannel) sel.insert(1.,&f38to31[0]); else sel.insert(1.,&f38to31[1]); break; case Colour3bar8to13bar: static ColourLines f3bar8to13bar[2]={ColourLines("-1 2 3, -3 -5 "), ColourLines("-1 2, -5 -3 -2")}; if(current.channelType == HPDiagram::tChannel) sel.insert(1.,&f3bar8to13bar[0]); else sel.insert(1.,&f3bar8to13bar[1]); break; case Colour3bar8to3bar1: static ColourLines f3bar8to3bar1[2]={ColourLines("-1 2 3, -3 -4 "), ColourLines("-1 2, -4 -3 -2")}; if(current.channelType == HPDiagram::tChannel) sel.insert(1.,&f3bar8to3bar1[0]); else sel.insert(1.,&f3bar8to3bar1[1]); break; case Colour38to83: - static ColourLines f38to83[4]={ColourLines("1 4, -4 2 -3, 3 5"), + static ColourLines f38to83[5]={ColourLines("1 4, -4 2 -3, 3 5"), ColourLines("1 -2, 2 3 4, 5 -4"), ColourLines("1 2 4, -4 -3, 3 -2 5"), - ColourLines("1 2 -3, -4 -2 5, 3 4")}; + ColourLines("1 2 -3, -4 -2 5, 3 4"), + ColourLines("1 5, 3 4, -3 -4")}; if(current.channelType == HPDiagram::sChannel) sel.insert(1.,&f38to83[1]); else { if(current.intermediate->iColour() == PDT::Colour8) sel.insert(1.,&f38to83[flow_+2]); + else if(current.intermediate->iColour() == PDT::Colour0) + sel.insert(1.,&f38to83[4]); else sel.insert(1.,&f38to83[0]); } break; case Colour38to38: - static ColourLines f38to38[4]={ColourLines("1 5, -5 2 -3, 3 4"), + static ColourLines f38to38[5]={ColourLines("1 5, -5 2 -3, 3 4"), ColourLines("1 -2, 2 3 5, 4 -5"), ColourLines("1 2 5, -5 -3, 3 -2 4"), - ColourLines("1 2 -3, -5 -2 4, 3 5")}; + ColourLines("1 2 -3, -5 -2 4, 3 5"), + ColourLines("1 4, 3 5, -3 -5")}; if(current.channelType == HPDiagram::sChannel) sel.insert(1.,&f38to38[1]); else { if(current.intermediate->iColour() == PDT::Colour8) sel.insert(1.,&f38to38[flow_+2]); + else if(current.intermediate->iColour() == PDT::Colour0) + sel.insert(1.,&f38to38[4]); else sel.insert(1.,&f38to38[0]); } break; case Colour3bar8to83bar: - static ColourLines f3bar8to83bar[4]={ColourLines("-1 -4, 3 2 4, -3 -5"), + static ColourLines f3bar8to83bar[5]={ColourLines("-1 -4, 3 2 4, -3 -5"), ColourLines("-1 2, -4 -3 -2, 4 -5"), ColourLines("-1 -2 -4,-3 2 -5,3 4"), - ColourLines("-1 -2 3, -5 2 4, -3 -4")}; + ColourLines("-1 -2 3, -5 2 4, -3 -4"), + ColourLines("-1 -5, -3 -4, 3 4")}; if(current.channelType == HPDiagram::sChannel) sel.insert(1.,&f3bar8to83bar[1]); else { if(current.intermediate->iColour() == PDT::Colour8) sel.insert(1.,&f3bar8to83bar[flow_+2]); + else if(current.intermediate->iColour() == PDT::Colour0) + sel.insert(1.,&f3bar8to83bar[4]); else sel.insert(1.,&f3bar8to83bar[0]); } break; case Colour3bar8to3bar8: static ColourLines f3bar8to3bar8[4]={ColourLines("-1 -5, 3 2 5, -3 -4"), ColourLines("-1 2, -5 -3 -2, 5 -4"), ColourLines("-1 -2 -5,-3 2 -4,3 5"), ColourLines("-1 -2 3, -4 2 5, -3 -5")}; if(current.channelType == HPDiagram::sChannel) sel.insert(1.,&f3bar8to3bar8[1]); else { if(current.intermediate->iColour() == PDT::Colour8) sel.insert(1.,&f3bar8to3bar8[flow_+2]); else sel.insert(1.,&f3bar8to3bar8[0]); } break; case Colour88to18: static ColourLines f88to18[6]={ColourLines(" 1 3 5, -1 2, -2 -3 -5"), ColourLines(" -1 -3 -5, 1 -2, 2 3 5"), ColourLines(" 1 2 -3, -1 -2 -5, 3 5"), ColourLines("-1 -2 3, 1 2 5, -3 -5"), ColourLines(" 1 5, -1 2 3, -3 -2 -5"), ColourLines("-1 -5, 1 -2 -3, 3 2 5")}; if(current.channelType == HPDiagram::sChannel) sel.insert(1.,&f88to18[UseRandom::irnd(0,2)]); else if(current.channelType == HPDiagram::tChannel) { if(current.ordered.second) sel.insert(1.,&f88to18[UseRandom::irnd(2,4)]); else sel.insert(1.,&f88to18[UseRandom::irnd(4,6)]); } break; case Colour88to81: static ColourLines f88to81[6]={ColourLines(" 1 3 4, -1 2, -2 -3 -4"), ColourLines(" -1 -3 -4, 1 -2, 2 3 4"), ColourLines(" 1 4, -1 2 3, -3 -2 -4"), ColourLines(" -1 -4, 1 -2 -3, 3 2 4"), ColourLines(" 1 2 -3, -1 -2 -4, 3 4"), ColourLines(" -1 -2 3, 1 2 4, -3 -4")}; if(current.channelType == HPDiagram::sChannel) sel.insert(1.,&f88to81[UseRandom::irnd(0,2)]); else if(current.channelType == HPDiagram::tChannel) { if(current.ordered.second) sel.insert(1.,&f88to81[UseRandom::irnd(2,4)]); else sel.insert(1.,&f88to81[UseRandom::irnd(4,6)]); } break; case Colour33barto66bar: static ColourLines f33barto66bars[10] ={ColourLines("1 3 4:1, -2 -3 -5:1, 4:2 -5:2"), ColourLines("1 3 4:1, -2 -3 -5:2, 4:2 -5:1"), ColourLines("1 3 4:2, -2 -3 -5:1, 4:1 -5:2"), ColourLines("1 3 4:2, -2 -3 -5:2, 4:1 -5:1"), ColourLines(""), ColourLines(""), ColourLines(""), ColourLines(""), ColourLines("1 -2, 4:1 -5:1, 4:2 -5:2"), ColourLines("1 -2, 4:1 -5:2, 4:2 -5:1")}; static ColourLines f33barto66bart[10] ={ColourLines(""), ColourLines(""), ColourLines(""), ColourLines(""), ColourLines("1 4:1, 4:2 2 -5:2, -3 -5:1"), ColourLines("1 4:1, 4:2 2 -5:1, -3 -5:2"), ColourLines("1 4:2, 4:1 2 -5:2, -3 -5:1"), ColourLines("1 4:2, 4:1 2 -5:1, -3 -5:2"), ColourLines(""), ColourLines("")}; if(current.channelType == HPDiagram::sChannel) sel.insert(1.,&f33barto66bars[flow_]); else if(current.channelType == HPDiagram::tChannel) { if(current.ordered.second) sel.insert(1.,&f33barto66bart[flow_]); else assert(false); } break; case Colour33barto6bar6: static ColourLines f33barto6bar6s[8] ={ColourLines("1 3 5:1, -2 -3 -4:1, -4:2 5:2"), ColourLines("1 3 5:1, -2 -3 -4:2, -4:1 5:2"), ColourLines("1 3 5:2, -2 -3 -4:1, -4:2 5:1"), ColourLines("1 3 5:2, -2 -3 -4:2, -4:1 5:1"), ColourLines(""), ColourLines(""), ColourLines(""), ColourLines("")}; static ColourLines f33barto6bar6u[8] ={ColourLines(""), ColourLines(""), ColourLines(""), ColourLines(""), ColourLines("1 5:1, 5:2 2 -4:1, -3 -4:2"), ColourLines("1 5:1, 5:2 2 -4:2, -3 -4:1"), ColourLines("1 5:2, 5:1 2 -4:1, -3 -4:2"), ColourLines("1 5:2, 5:1 2 -4:2, -3 -4:1")}; if(current.channelType == HPDiagram::sChannel) sel.insert(1.,&f33barto6bar6s[flow_]); else if(current.channelType == HPDiagram::tChannel) { if(current.ordered.second) assert(false); else sel.insert(1.,&f33barto6bar6u[flow_]); } break; case Colour88to66bar: static ColourLines f88to66t[12]= {ColourLines("1 4:2, 4:1 2:1 3, -1 2:2 -5:2, -3 -5:1"), ColourLines("1 4:1, 4:2 2:2 3, -1 2:1 -5:2, -3 -5:1"), ColourLines("1 4:2, 4:1 2:1 3, -1 2:2 -5:1, -3 -5:2"), ColourLines("1 4:1, 4:2 2:2 3, -1 2:1 -5:1, -3 -5:2"), ColourLines("1 4:2, 4:1 2:2 -5:2, -1 2:1 3, -3 -5:1"), ColourLines("1 4:1, 4:2 2:2 -5:2, -1 2:1 3, -3 -5:1"), ColourLines("1 4:2, 4:1 2:2 -5:1, -1 2:1 3, -3 -5:2"), ColourLines("1 4:1, 4:2 2:2 -5:1, -1 2:1 3, -3 -5:2"), ColourLines(""),ColourLines(""), ColourLines(""),ColourLines("")}; static ColourLines f88to66u[12]= {ColourLines("1 2:2 4:2, 4:1 3, -1 -5:2, -3 2:1 -5:1"), ColourLines("1 2:1 4:1, 4:2 3, -1 -5:2, -3 2:2 -5:1"), ColourLines("1 2:2 4:2, 4:1 3, -1 -5:1, -3 2:1 -5:2"), ColourLines("1 2:1 4:1, 4:2 3, -1 -5:1, -3 2:2 -5:2"), ColourLines(""),ColourLines(""), ColourLines(""),ColourLines(""), ColourLines("-1 -5:1, -5:2 2:2 4:1, 1 2:1 -3, 3 4:2"), ColourLines("-1 -5:1, -5:2 2:2 4:2, 1 2:1 -3, 3 4:1"), ColourLines("-1 -5:2, -5:1 2:2 4:1, 1 2:1 -3, 3 4:2"), ColourLines("-1 -5:2, -5:1 2:2 4:2, 1 2:1 -3, 3 4:1")}; static ColourLines f88to66s[12]= {ColourLines(""),ColourLines(""), ColourLines(""),ColourLines(""), ColourLines("1 3 4:2, 4:1 -5:2, -1 2, -2 -3 -5:1"), ColourLines("1 3 4:1, 4:2 -5:2, -1 2, -2 -3 -5:1"), ColourLines("1 3 4:2, 4:1 -5:1, -1 2, -2 -3 -5:2"), ColourLines("1 3 4:1, 4:2 -5:1, -1 2, -2 -3 -5:2"), ColourLines("-1 -3 -5:1, -5:2 4:1, 1 -2, 2 3 4:2"), ColourLines("-1 -3 -5:1, -5:2 4:2, 1 -2, 2 3 4:1"), ColourLines("-1 -3 -5:2, -5:1 4:1, 1 -2, 2 3 4:2"), ColourLines("-1 -3 -5:2, -5:1 4:2, 1 -2, 2 3 4:1")}; if(current.channelType == HPDiagram::sChannel) sel.insert(1., &f88to66s[flow_]); else if(current.channelType == HPDiagram::tChannel) { if(current.ordered.second) { sel.insert(1., &f88to66t[flow_]); } else { sel.insert(1., &f88to66u[flow_]); } } break; case Colour33to61: static ColourLines f33to61t[2] ={ColourLines("1 4:1, 3 2 4:2"), ColourLines("1 4:2, 3 2 4:1")}; static ColourLines f33to61u[2] ={ColourLines("1 2 4:1, 3 4:2"), ColourLines("1 2 4:2, 3 4:1")}; static ColourLines f33to61s[2] ={ColourLines("1 3:1 4:1, 2 3:2 4:2"), ColourLines("1 3:2 4:2, 2 3:1 4:1")}; if(current.channelType == HPDiagram::tChannel) { if(current.ordered.second) sel.insert(1., &f33to61t[flow_]); else sel.insert(1., &f33to61u[flow_]); } else { sel.insert(1., &f33to61s[flow_]); } break; case Colour33to16: static ColourLines f33to16t[2] ={ColourLines("1 2 5:1, 3 5:2"), ColourLines("1 2 5:2, 3 5:1")}; static ColourLines f33to16u[2] ={ColourLines("1 5:1, 3 2 5:2"), ColourLines("1 5:2, 3 2 5:1")}; static ColourLines f33to16s[2] ={ColourLines("1 3:1 5:1, 2 3:2 5:2"), ColourLines("1 3:2 5:2, 2 3:1 5:1")}; if(current.channelType == HPDiagram::tChannel) { if(current.ordered.second) sel.insert(1., &f33to16t[flow_]); else sel.insert(1., &f33to16u[flow_]); } else { sel.insert(1., &f33to16s[flow_]); } break; case Colour3bar3barto6bar1: static ColourLines f3bar3barto6bar1t[2] ={ColourLines("-1 -4:1, -3 -2 -4:2"), ColourLines("-1 -4:2, -3 -2 -4:1")}; static ColourLines f3bar3barto6bar1u[2] ={ColourLines("-1 -2 -4:1, -3 -4:2"), ColourLines("-1 -2 -4:2, -3 -4:1")}; static ColourLines f3bar3barto6bar1s[2] ={ColourLines("-1 -3:1 -4:1, -2 -3:2 -4:2"), ColourLines("-1 -3:2 -4:2, -2 -3:1 -4:1")}; if(current.channelType == HPDiagram::tChannel) { if(current.ordered.second) sel.insert(1., &f3bar3barto6bar1t[flow_]); else sel.insert(1., &f3bar3barto6bar1u[flow_]); } else { sel.insert(1., &f3bar3barto6bar1s[flow_]); } break; case Colour3bar3barto16bar: static ColourLines f3bar3barto16bart[2] ={ColourLines("-1 -2 -5:1, -3 -5:2"), ColourLines("-1 -2 -5:2, -3 -5:1")}; static ColourLines f3bar3barto16baru[2] ={ColourLines("-1 -5:1, -3 -2 -5:2"), ColourLines("-1 -5:2, -3 -2 -5:1")}; static ColourLines f3bar3barto16bars[2] ={ColourLines("-1 -3:1 -5:1, -2 -3:2 -5:2"), ColourLines("-1 -3:2 -5:2, -2 -3:1 -5:1")}; if(current.channelType == HPDiagram::tChannel) { if(current.ordered.second) sel.insert(1., &f3bar3barto16bart[flow_]); else sel.insert(1., &f3bar3barto16baru[flow_]); } else { sel.insert(1., &f3bar3barto16bars[flow_]); } break; case Colour38to3bar6: static ColourLines f38to3bar6t[8] ={ColourLines("1 2:1 -3, -4 2:2 5:1, 3 5:2"), ColourLines("1 2:1 -3, -4 2:2 5:2, 3 5:1"), ColourLines("1 2:1 5:1, -4 2:2 -3, 3 5:2"), ColourLines("1 2:1 5:2, -4 2:2 -3, 3 5:1"), ColourLines(""),ColourLines(""), ColourLines(""),ColourLines("")}; static ColourLines f38to3bar6u[8] ={ColourLines(""),ColourLines(""), ColourLines(""),ColourLines(""), ColourLines("1 5:1, 3 2 5:2, -4 -3"), ColourLines("1 5:2, 3 2 5:1, -4 -3"), ColourLines(""),ColourLines("")}; static ColourLines f38to3bar6s[8] ={ColourLines(""),ColourLines(""), ColourLines(""),ColourLines(""), ColourLines(""),ColourLines(""), ColourLines("1 -2, 2 3 5:1, -4 5:2"), ColourLines("1 -2, 2 3 5:2, -4 5:1")}; if(current.channelType == HPDiagram::sChannel) sel.insert(1., &f38to3bar6s[flow_]); else if(current.channelType == HPDiagram::tChannel) { if(current.ordered.second) sel.insert(1., &f38to3bar6t[flow_]); else sel.insert(1., &f38to3bar6u[flow_]); } break; case Colour38to63bar: static ColourLines f38to63baru[8] ={ColourLines("1 2:1 -3, -5 2:2 4:1, 3 4:2"), ColourLines("1 2:1 -3, -5 2:2 4:2, 3 4:1"), ColourLines("1 2:1 4:1, -5 2:2 -3, 3 4:2"), ColourLines("1 2:1 4:2, -5 2:2 -3, 3 4:1"), ColourLines(""),ColourLines(""), ColourLines(""),ColourLines("")}; static ColourLines f38to63bart[8] ={ColourLines(""),ColourLines(""), ColourLines(""),ColourLines(""), ColourLines("1 4:1, 3 2 4:2, -5 -3"), ColourLines("1 4:2, 3 2 4:1, -5 -3"), ColourLines(""),ColourLines("")}; static ColourLines f38to63bars[8] ={ColourLines(""),ColourLines(""), ColourLines(""),ColourLines(""), ColourLines(""),ColourLines(""), ColourLines("1 -2, 2 3 4:1, -5 4:2"), ColourLines("1 -2, 2 3 4:2, -5 4:1")}; if(current.channelType == HPDiagram::sChannel) sel.insert(1., &f38to63bars[flow_]); else if(current.channelType == HPDiagram::tChannel) { if(current.ordered.second) sel.insert(1., &f38to63bart[flow_]); else sel.insert(1., &f38to63baru[flow_]); } break; case Colour33to13bar: static ColourLines f33to13bar[3]={ColourLines("1 -6, 2 -6, -5 -3 -6"), ColourLines("1 2 -6, 3 -6, -5 -6"), ColourLines("1 -6, 3 2 -6, -5 -6")}; if(current.channelType == HPDiagram::sChannel) sel.insert(1., &f33to13bar[0]); else if(current.channelType == HPDiagram::tChannel) { if(current.ordered.second) sel.insert(1., &f33to13bar[1]); else sel.insert(1., &f33to13bar[2]); } break; case Colour33to3bar1: static ColourLines f33to3bar1[3]={ColourLines("1 -6, 2 -6, -4 -3 -6"), ColourLines("1 -6, 3 2 -6, -4 -6"), ColourLines("1 2 -6, 3 -6, -4 -6")}; if(current.channelType == HPDiagram::sChannel) sel.insert(1., &f33to3bar1[0]); else if(current.channelType == HPDiagram::tChannel) { if(current.ordered.second) sel.insert(1., &f33to3bar1[1]); else sel.insert(1., &f33to3bar1[2]); } break; case Colour3bar3barto13: static ColourLines f3bar3barto13[3]={ColourLines("-1 6, -2 6, 5 3 6"), ColourLines("-1 2 6, -3 6, 5 6"), ColourLines("-1 6, -3 2 6, 5 6")}; if(current.channelType == HPDiagram::sChannel) { sel.insert(1., &f3bar3barto13[0]); } else if(current.channelType == HPDiagram::tChannel) { if(current.ordered.second) { sel.insert(1., &f3bar3barto13[1]); } else { sel.insert(1., &f3bar3barto13[2]); } } break; case Colour3bar3barto31: static ColourLines f3bar3barto31[3]={ColourLines("-1 6, -2 6, 4 3 6"), - ColourLines("-1 6, -3 -2 6, 4 6"), - ColourLines("-1 -2 6, -3 6, 4 6")}; + ColourLines("-1 6, -3 2 6, 4 6"), + ColourLines("-1 2 6, -3 6, 4 6")}; if(current.channelType == HPDiagram::sChannel) sel.insert(1., &f3bar3barto31[0]); else if(current.channelType == HPDiagram::tChannel) { if(current.ordered.second) sel.insert(1., &f3bar3barto31[1]); else sel.insert(1., &f3bar3barto31[2]); } break; case Colour33to83bar: static ColourLines f33to83bar[3]={ColourLines("1 -6, 2 -6, -5 4, -4 -3 -6"), ColourLines("1 4, -4 2 -6, 3 -6, -5 -6"), ColourLines("1 -6, 3 4, -4 2 -6, -5 -6")}; sel.insert(1., &f33to83bar[flow_]); break; case Colour33to3bar8: static ColourLines f33to3bar8[3]={ColourLines("1 -6, 2 -6, -4 5, -5 -3 -6"), ColourLines("1 -6, 3 5, -5 2 -6, -4 -6"), ColourLines("1 5, -5 2 -6, 3 -6, -4 -6")}; sel.insert(1., &f33to3bar8[flow_]); break; case Colour3bar3barto83: static ColourLines f3bar3barto83[3]={ColourLines("-1 6, -2 6, 5 -4, 4 3 6"), ColourLines("-1 -4, 4 2 6, -3 6, 5 6"), ColourLines("-1 6, -3 -4, 4 2 6, 5 6")}; sel.insert(1., &f3bar3barto83[flow_]); break; case Colour3bar3barto38: static ColourLines f3bar3barto38[3]={ColourLines("-1 6, -2 6, 4 -5, 5 3 6"), ColourLines("-1 6, -3 -5, 5 -2 6, 4 6"), ColourLines("-1 -5, 5 -2 6, -3 6, 4 6")}; sel.insert(1., &f3bar3barto38[flow_]); break; case Colour38to3bar3bar: static ColourLines f38to3bar3bar[3]={ColourLines("1 -2, 2 3 -6, -4 -6, -5 -6"), ColourLines("1 -6, 3 2 -6, -3 -5, -4 -6"), ColourLines("1 -6, 3 2 -6, -3 -4, -5 -6")}; sel.insert(1., &f38to3bar3bar[flow_]); break; case Colour3bar8to33: static ColourLines f3bar8to33[3]={ColourLines("-1 2, -2 -3 6, 4 6, 5 6"), ColourLines("-1 6, -3 2 6, 3 5, 4 6"), ColourLines("-1 6, -3 2 6, 3 4, 5 6")}; sel.insert(1., &f3bar8to33[flow_]); break; default: assert(false); } return sel; } double GeneralHardME:: selectColourFlow(vector & flow,vector & me, double average) const { // spin average double output = 0.25*average; // special for beam polarization tcPolarizedBeamPDPtr beam[2] = {dynamic_ptr_cast(mePartonData()[0]), dynamic_ptr_cast(mePartonData()[1])}; if( beam[0] || beam[1] ) { RhoDMatrix rho[2] = {beam[0] ? beam[0]->rhoMatrix() : RhoDMatrix(mePartonData()[0]->iSpin()), beam[1] ? beam[1]->rhoMatrix() : RhoDMatrix(mePartonData()[1]->iSpin())}; for(unsigned int ix = 0;ixid()==ParticleID::g || mePartonData()[0]->id()==ParticleID::gamma) output *= 1.5; if(mePartonData()[1]->id()==ParticleID::g || mePartonData()[1]->id()==ParticleID::gamma) output *= 1.5; } // select the colour flow double maxWgt = UseRandom::rnd()*std::accumulate(flow.begin(),flow.end(),0.); flow_ = flow.size(); for(unsigned int ix=0;ix=maxWgt) { flow_=ix; break; } maxWgt -= flow[ix]; } assert(flow_maxWgt) { diagram_=ix; break; } maxWgt -= me[ix]; } // colour factors output /= max(1,abs(int(mePartonData()[0]->iColour()))); output /= max(1,abs(int(mePartonData()[1]->iColour()))); // identical particle factor output *= mePartonData()[2]->id() == mePartonData()[3]->id() ? 0.5 : 1; // return the answer return output; } void GeneralHardME::doinitrun() { HwMEBase::doinitrun(); for(unsigned int ix=0;ixinitrun(); diagrams_[ix].vertices.second->initrun(); } } diff --git a/MatrixElement/General/GeneralfftoffH.cc b/MatrixElement/General/GeneralfftoffH.cc --- a/MatrixElement/General/GeneralfftoffH.cc +++ b/MatrixElement/General/GeneralfftoffH.cc @@ -1,174 +1,178 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the GeneralfftoffH class. // #include "GeneralfftoffH.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include"ThePEG/Utilities/EnumIO.h" using namespace Herwig; GeneralfftoffH::GeneralfftoffH() {} IBPtr GeneralfftoffH::clone() const { return new_ptr(*this); } IBPtr GeneralfftoffH::fullclone() const { return new_ptr(*this); } void GeneralfftoffH::persistentOutput(PersistentOStream & os) const { os << oenum(_proc); } void GeneralfftoffH::persistentInput(PersistentIStream & is, int) { is >> ienum(_proc); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigGeneralfftoffH("Herwig::GeneralfftoffH", "Herwig.so"); void GeneralfftoffH::Init() { static ClassDocumentation documentation ("There is no documentation for the GeneralfftoffH class"); } void GeneralfftoffH::getDiagrams() const { if(_proc==Lepton) { for(long ix=11;ix<=13;ix+=1) { tcPDPtr em(getParticleData(ix)); tcPDPtr ep(em->CC()); // WW processes if(process()==0||process()==1) { tcPDPtr nue(getParticleData(ix+1)); tcPDPtr nueb(nue->CC()); add(new_ptr((Tree2toNDiagram(4), em, WMinus(), WPlus(), ep, 1, nue, 4, nueb, 2, higgs(),-1))); } // ZZ processes if(process()==0||process()==2) { add(new_ptr((Tree2toNDiagram(4), em, Z0(), Z0(), ep, 1, em, 4, ep, 2, higgs(),-2))); } } } else { // WW processes if(process()==0||process()==1) { std::vector > parentpair; parentpair.reserve(6); // don't even think of putting 'break' in here! switch(maxFlavour()) { case 5: if (minFlavour()<=4) parentpair.push_back(make_pair(getParticleData(ParticleID::b), getParticleData(ParticleID::c))); if (minFlavour()<=2) parentpair.push_back(make_pair(getParticleData(ParticleID::b), getParticleData(ParticleID::u))); + [[fallthrough]]; case 4: if (minFlavour()<=3) parentpair.push_back(make_pair(getParticleData(ParticleID::s), getParticleData(ParticleID::c))); if (minFlavour()<=1) parentpair.push_back(make_pair(getParticleData(ParticleID::d), getParticleData(ParticleID::c))); + [[fallthrough]]; case 3: if (minFlavour()<=2) parentpair.push_back(make_pair(getParticleData(ParticleID::s), getParticleData(ParticleID::u))); + [[fallthrough]]; case 2: if (minFlavour()<=1) parentpair.push_back(make_pair(getParticleData(ParticleID::d), getParticleData(ParticleID::u))); + [[fallthrough]]; default: ; } for(unsigned int ix=0;ix q1' q2' h if(parentpair[ix].first->id()id()) { add(new_ptr((Tree2toNDiagram(4), parentpair[ix].first, WMinus(), WPlus(), parentpair[iy].second, 1, parentpair[ix].second, 4, parentpair[iy].first, 2, higgs(),-1))); } else { add(new_ptr((Tree2toNDiagram(4), parentpair[iy].second, WPlus(), WMinus(), parentpair[ix].first, 1, parentpair[iy].first, 4, parentpair[ix].second, 2, higgs(),-1))); } // q1 qbar2 -> q1' qbar2' h add(new_ptr((Tree2toNDiagram(4), parentpair[ix].first, WMinus(), WPlus(), parentpair[iy].first->CC(), 1, parentpair[ix].second, 4, parentpair[iy].second->CC(), 2, higgs(),-1))); add(new_ptr((Tree2toNDiagram(4),parentpair[iy].second, WPlus(), WMinus(), parentpair[ix].second->CC(), 1, parentpair[iy].first, 4, parentpair[ix].first->CC(), 2, higgs(),-1))); // qbar1 qbar2 -> qbar1' qbar2' h if(parentpair[ix].first->id()id()) { add(new_ptr((Tree2toNDiagram(4), parentpair[ix].first->CC(), WPlus(), WMinus(), parentpair[iy].second->CC(), 1, parentpair[ix].second->CC(), 4, parentpair[iy].first->CC(), 2, higgs(),-1))); } else { add(new_ptr((Tree2toNDiagram(4), parentpair[iy].second->CC(), WMinus(), WPlus(), parentpair[ix].first->CC(), 1, parentpair[iy].first->CC(), 4, parentpair[ix].second->CC(), 2, higgs(),-1))); } } } } // ZZ processes if(process()==0||process()==2) { // get the quark particle data objects as we'll be using them tcPDPtr q[6],qbar[6]; for ( int ix=0; ix<5; ++ix ) { q [ix] = getParticleData(ix+1); qbar[ix] = q[ix]->CC(); } for(unsigned int ix=minFlavour()-1;ix q q H add(new_ptr((Tree2toNDiagram(4), q[ix], Z0(), Z0(), q[iy], 1, q[ix], 4, q[iy], 2, higgs(),-2))); // qbar qbar -> qbar qbar H add(new_ptr((Tree2toNDiagram(4), qbar[ix], Z0(), Z0(), qbar[iy], 1, qbar[ix], 4, qbar[iy], 2, higgs(),-2))); } // q qbar -> q qbar H for(unsigned int iy=minFlavour()-1;iyiSpin() == PDT::Spin0) { + if(!offshell) { + four_[ix] = dynamic_ptr_cast + (current.vertices.first); + } + else if(offshell->iSpin() == PDT::Spin0) { AbstractFFSVertexPtr vert1 = dynamic_ptr_cast (current.vertices.first); AbstractFFSVertexPtr vert2 = dynamic_ptr_cast (current.vertices.second); scalar_[ix] = make_pair(vert1, vert2); } else if(offshell->iSpin() == PDT::Spin1) { AbstractFFVVertexPtr vert1 = dynamic_ptr_cast (current.vertices.first); AbstractFFVVertexPtr vert2 = dynamic_ptr_cast (current.vertices.second); vector_[ix] = make_pair(vert1, vert2); } else if(offshell->iSpin() == PDT::Spin2) { AbstractFFTVertexPtr vert1 = dynamic_ptr_cast (current.vertices.first); AbstractFFTVertexPtr vert2 = dynamic_ptr_cast (current.vertices.second); tensor_[ix] = make_pair(vert1, vert2); } } } double MEff2ff::me2() const { - tcPDPtr ina (mePartonData()[0]), inb (mePartonData()[1]); - tcPDPtr outa(mePartonData()[2]), outb(mePartonData()[3]); for(unsigned int ix=0;ix<4;++ix) { spin_[ix].clear(); sbar_[ix].clear(); for(unsigned int ih=0;ih<2;++ih) { spin_[ix].push_back(SpinorWaveFunction (rescaledMomenta()[ix], mePartonData()[ix], ih, ix<2 ? incoming : outgoing)); sbar_[ix].push_back(SpinorBarWaveFunction(rescaledMomenta()[ix], mePartonData()[ix], ih, ix<2 ? incoming : outgoing)); } } double full_me(0.); - if( ina->id() > 0 && inb->id() < 0) { + if( mePartonData()[0]->id() > 0 && mePartonData()[1]->id() < 0) { ffb2ffbHeME (full_me,true); } - else if( ina->id() > 0 && inb->id() > 0 ) + else if( mePartonData()[0]->id() > 0 && mePartonData()[1]->id() > 0 ) ff2ffHeME(full_me,true); - else if( ina->id() < 0 && inb->id() < 0 ) + else if( mePartonData()[0]->id() < 0 && mePartonData()[1]->id() < 0 ) fbfb2fbfbHeME(full_me,true); - else - throw MEException() - << "MEff2ff::me2() - Cannot find correct function to deal with process " - << ina->PDGName() << "," << inb->PDGName() << "->" << outa->PDGName() - << "," << outb->PDGName() << "\n"; + else + assert(false); #ifndef NDEBUG if( debugME() ) debug(full_me); #endif return full_me; } ProductionMatrixElement MEff2ff::ffb2ffbHeME(double & me2, bool first) const { const Energy2 q2(scale()); // weights for the selection of the diagram vector me(numberOfDiags(), 0.); // weights for the selection of the colour flow vector flow(numberOfFlows(),0.); // flow over the helicities and diagrams for(unsigned int ifhel1 = 0; ifhel1 < 2; ++ifhel1) { for(unsigned int ifhel2 = 0; ifhel2 < 2; ++ifhel2) { for(unsigned int ofhel1 = 0; ofhel1 < 2; ++ofhel1) { for(unsigned int ofhel2 = 0; ofhel2 < 2; ++ofhel2) { vector flows(numberOfFlows(),0.); for(HPCount ix = 0; ix < numberOfDiags(); ++ix) { Complex diag(0.); const HPDiagram & current = getProcessInfo()[ix]; tcPDPtr offshell = current.intermediate; if(current.channelType == HPDiagram::tChannel) { + if(offshell->CC()) offshell=offshell->CC(); if(offshell->iSpin() == PDT::Spin0) { if(current.ordered.second) { ScalarWaveFunction interS = scalar_[ix].second-> evaluate(q2, 3, offshell,spin_[3][ofhel2],sbar_[1][ifhel2]); diag = -scalar_[ix].first-> evaluate(q2, spin_[0][ifhel1],sbar_[2][ofhel1],interS); } else { ScalarWaveFunction interS = scalar_[ix].second-> evaluate(q2, 3, offshell,spin_[2][ofhel1],sbar_[1][ifhel2]); diag = scalar_[ix].first-> evaluate(q2, spin_[0][ifhel1],sbar_[3][ofhel2],interS); } } else if(offshell->iSpin() == PDT::Spin1) { if(current.ordered.second) { VectorWaveFunction interV = vector_[ix].second-> evaluate(q2, 3, offshell,spin_[3][ofhel2],sbar_[1][ifhel2]); diag = -vector_[ix].first-> evaluate(q2, spin_[0][ifhel1], sbar_[2][ofhel1], interV); } else { VectorWaveFunction interV = vector_[ix].second-> evaluate(q2, 3, offshell,spin_[2][ofhel1],sbar_[1][ifhel2]); diag = vector_[ix].first-> evaluate(q2, spin_[0][ifhel1], sbar_[3][ofhel2], interV); } } else if(offshell->iSpin() == PDT::Spin2) { if(current.ordered.second) { TensorWaveFunction interT = tensor_[ix].second-> evaluate(q2, 3, offshell,spin_[3][ofhel2],sbar_[1][ifhel2]); diag = -tensor_[ix].first-> evaluate(q2, spin_[0][ifhel1], sbar_[2][ofhel1], interT); } else { TensorWaveFunction interT = tensor_[ix].second-> evaluate(q2, 3, offshell,spin_[2][ofhel1],sbar_[1][ifhel2]); diag = tensor_[ix].first-> evaluate(q2, spin_[0][ifhel1], sbar_[3][ofhel2], interT); } } } else if(current.channelType == HPDiagram::sChannel) { if(offshell->iSpin() == PDT::Spin0) { ScalarWaveFunction interS = scalar_[ix].second-> evaluate(q2, 1, offshell,spin_[3][ofhel2],sbar_[2][ofhel1]); diag = scalar_[ix].first-> evaluate(q2, spin_[0][ifhel1], sbar_[1][ifhel2], interS); } else if(offshell->iSpin() == PDT::Spin1) { VectorWaveFunction interV = vector_[ix].second-> evaluate(q2, 1, offshell,spin_[3][ofhel2],sbar_[2][ofhel1]); diag = vector_[ix].first-> evaluate(q2, spin_[0][ifhel1], sbar_[1][ifhel2], interV); } else if(offshell->iSpin() == PDT::Spin2) { TensorWaveFunction interT = tensor_[ix].second-> evaluate(q2, 1, offshell,spin_[3][ofhel2],sbar_[2][ofhel1]); diag = tensor_[ix].first-> evaluate(q2, spin_[0][ifhel1], sbar_[1][ifhel2], interT); } } - else assert(false); + else { + diag = four_[ix]->evaluate(q2,spin_[0][ifhel1], sbar_[1][ifhel2], + spin_[3][ofhel2],sbar_[2][ofhel1]); + } me[ix] += norm(diag); diagramME()[ix](ifhel1, ifhel2, ofhel1, ofhel2) = diag; //Compute flows for(size_t iy = 0; iy < current.colourFlow.size(); ++iy) { assert(current.colourFlow[iy].first me(numberOfDiags(), 0.); // weights for the selection of the colour flow vector flow(numberOfFlows(),0.); // flow over the helicities and diagrams for(unsigned int ifhel1 = 0; ifhel1 < 2; ++ifhel1) { for(unsigned int ifhel2 = 0; ifhel2 < 2; ++ifhel2) { for(unsigned int ofhel1 = 0; ofhel1 < 2; ++ofhel1) { for(unsigned int ofhel2 = 0; ofhel2 < 2; ++ofhel2) { vector flows(numberOfFlows(),0.); for(HPCount ix = 0; ix < numberOfDiags(); ++ix) { Complex diag(0.); const HPDiagram & current = getProcessInfo()[ix]; tcPDPtr offshell = current.intermediate; + if(offshell->CC()) offshell=offshell->CC(); if(current.channelType == HPDiagram::tChannel) { if(offshell->iSpin() == PDT::Spin0) { if(current.ordered.second) { ScalarWaveFunction interS = scalar_[ix].second-> evaluate(q2, 3, offshell,spin_[1][ifhel2],sbar_[3][ofhel2]); diag = scalar_[ix].first-> evaluate(q2, spin_[0][ifhel1], sbar_[2][ofhel1], interS); } else { ScalarWaveFunction interS = scalar_[ix].second-> evaluate(q2, 3, offshell,spin_[1][ifhel2],sbar_[2][ofhel1]); diag = -scalar_[ix].first-> evaluate(q2, spin_[0][ifhel1], sbar_[3][ofhel2], interS); } } else if(offshell->iSpin() == PDT::Spin1) { if(current.ordered.second) { VectorWaveFunction interV = vector_[ix].second-> evaluate(q2, 3, offshell,spin_[1][ifhel2],sbar_[3][ofhel2]); diag = vector_[ix].first-> evaluate(q2, spin_[0][ifhel1], sbar_[2][ofhel1], interV); } else { VectorWaveFunction interV = vector_[ix].second-> evaluate(q2, 3, offshell,spin_[1][ifhel2],sbar_[2][ofhel1]); diag = -vector_[ix].first-> evaluate(q2, spin_[0][ifhel1], sbar_[3][ofhel2], interV); } } else if(offshell->iSpin() == PDT::Spin2) { if(current.ordered.second) { TensorWaveFunction interT = tensor_[ix].second-> evaluate(q2, 3, offshell,spin_[1][ifhel2],sbar_[3][ofhel2]); diag = tensor_[ix].first-> evaluate(q2, spin_[0][ifhel1], sbar_[2][ofhel1], interT); } else { TensorWaveFunction interT = tensor_[ix].second-> evaluate(q2, 3, offshell,spin_[1][ifhel2],sbar_[2][ofhel1]); diag = -tensor_[ix].first-> evaluate(q2, spin_[0][ifhel1], sbar_[3][ofhel2], interT); } } } else if(current.channelType == HPDiagram::sChannel) { - if(offshell->CC()) offshell=offshell->CC(); if(offshell->iSpin() == PDT::Spin0) { ScalarWaveFunction interS = scalar_[ix].second-> evaluate(q2, 1, offshell,spin_[3][ofhel2],sbar_[2][ofhel1]); diag = scalar_[ix].first-> evaluate(q2, spin_[0][ifhel1], sbar_[1][ifhel2], interS); } else if(offshell->iSpin() == PDT::Spin1) { VectorWaveFunction interV = vector_[ix].second-> evaluate(q2, 1, offshell,spin_[3][ofhel2],sbar_[2][ofhel1]); diag = vector_[ix].first-> evaluate(q2, spin_[0][ifhel1], sbar_[1][ifhel2], interV); } else if(offshell->iSpin() == PDT::Spin2) { TensorWaveFunction interT = tensor_[ix].second-> evaluate(q2, 1, offshell,spin_[3][ofhel2],sbar_[2][ofhel1]); diag = tensor_[ix].first-> evaluate(q2, spin_[0][ifhel1], sbar_[1][ifhel2], interT); } } - else - assert(false); + else if(current.channelType == HPDiagram::fourPoint) { + diag= four_[ix]->evaluate(q2,spin_[0][ifhel1],sbar_[2][ofhel1], + spin_[1][ifhel2],sbar_[3][ofhel2]); + } me[ix] += norm(diag); diagramME()[ix](ifhel1, ifhel2, ofhel1, ofhel2) = diag; //Compute flows for(size_t iy = 0; iy < current.colourFlow.size(); ++iy) { assert(current.colourFlow[iy].first me(numberOfDiags(), 0.); // weights for the selection of the colour flow vector flow(numberOfFlows(),0.); // flow over the helicities and diagrams for(unsigned int ifhel1 = 0; ifhel1 < 2; ++ifhel1) { for(unsigned int ifhel2 = 0; ifhel2 < 2; ++ifhel2) { for(unsigned int ofhel1 = 0; ofhel1 < 2; ++ofhel1) { for(unsigned int ofhel2 = 0; ofhel2 < 2; ++ofhel2) { vector flows(numberOfFlows(),0.); for(HPCount ix = 0; ix < numberOfDiags(); ++ix) { Complex diag(0.); const HPDiagram & current = getProcessInfo()[ix]; tcPDPtr offshell = current.intermediate; + if(offshell->CC()) offshell=offshell->CC(); if(current.channelType == HPDiagram::tChannel) { if(offshell->iSpin() == PDT::Spin0) { if(current.ordered.second) { ScalarWaveFunction interS = scalar_[ix].second-> evaluate(q2, 3, offshell,spin_[3][ofhel2],sbar_[1][ifhel2]); diag = scalar_[ix].first-> evaluate(q2, spin_[2][ofhel1], sbar_[0][ifhel1], interS); } else { ScalarWaveFunction interS = scalar_[ix].second-> evaluate(q2, 3, offshell,spin_[2][ofhel1],sbar_[1][ifhel2]); diag = -scalar_[ix].first-> evaluate(q2, spin_[3][ofhel2], sbar_[0][ifhel1], interS); } } else if(offshell->iSpin() == PDT::Spin1) { if(current.ordered.second) { VectorWaveFunction interV = vector_[ix].second-> evaluate(q2, 3, offshell,spin_[3][ofhel2],sbar_[1][ifhel2]); diag = vector_[ix].first-> evaluate(q2, spin_[2][ofhel1], sbar_[0][ifhel1], interV); } else { VectorWaveFunction interV = vector_[ix].second-> evaluate(q2, 3, offshell,spin_[2][ofhel1],sbar_[1][ifhel2]); diag = -vector_[ix].first-> evaluate(q2, spin_[3][ofhel2], sbar_[0][ifhel1], interV); } } else if(offshell->iSpin() == PDT::Spin2) { if(current.ordered.second) { TensorWaveFunction interT = tensor_[ix].second-> evaluate(q2, 3, offshell,spin_[3][ofhel2],sbar_[1][ifhel2]); diag = tensor_[ix].first-> evaluate(q2, spin_[2][ofhel1], sbar_[0][ifhel1], interT); } else { TensorWaveFunction interT = tensor_[ix].second-> evaluate(q2, 3, offshell,spin_[2][ofhel1],sbar_[1][ifhel2]); diag = -tensor_[ix].first-> evaluate(q2, spin_[3][ofhel2], sbar_[0][ifhel1], interT); } } } else if(current.channelType == HPDiagram::sChannel) { - if(offshell->CC()) offshell=offshell->CC(); if(offshell->iSpin() == PDT::Spin0) { ScalarWaveFunction interS = scalar_[ix].second-> evaluate(q2, 1, offshell,spin_[3][ofhel2],sbar_[2][ofhel1]); diag = scalar_[ix].first-> evaluate(q2, spin_[0][ifhel1], sbar_[1][ifhel2], interS); } else if(offshell->iSpin() == PDT::Spin1) { VectorWaveFunction interV = vector_[ix].second-> evaluate(q2, 1, offshell,spin_[3][ofhel2],sbar_[2][ofhel1]); diag = vector_[ix].first-> evaluate(q2, spin_[0][ifhel1], sbar_[1][ifhel2], interV); } else if(offshell->iSpin() == PDT::Spin2) { TensorWaveFunction interT = tensor_[ix].second-> evaluate(q2, 1, offshell,spin_[3][ofhel2],sbar_[2][ofhel1]); diag = tensor_[ix].first-> evaluate(q2, spin_[0][ifhel1], sbar_[1][ifhel2], interT); } } - else { - assert(false); + else if(current.channelType == HPDiagram::fourPoint) { + diag= four_[ix]->evaluate(q2,spin_[2][ofhel1],sbar_[0][ifhel1], + spin_[3][ofhel2],sbar_[1][ifhel2]); } me[ix] += norm(diag); diagramME()[ix](ifhel1, ifhel2, ofhel1, ofhel2) = diag; //Compute flows for(size_t iy = 0; iy < current.colourFlow.size(); ++iy) { assert(current.colourFlow[iy].first1); - SpinorBarWaveFunction(sbar_[ix],hardpro[ix], - ix<2 ? incoming : outgoing,ix>1); - } + SpinorWaveFunction (spin_[ix],hardpro[ix], + ix<2 ? incoming : outgoing,ix>1); + SpinorBarWaveFunction(sbar_[ix],hardpro[ix], + ix<2 ? incoming : outgoing,ix>1); } double dummy(0.); //pick which process we are doing if( hardpro[0]->id() > 0) { //ffbar->ffbar if( hardpro[1]->id() < 0 ) { ProductionMatrixElement prodME = ffb2ffbHeME(dummy,false); createVertex(prodME,hardpro); } //ff2ff else { ProductionMatrixElement prodME = ff2ffHeME(dummy,false); createVertex(prodME,hardpro); } } //fbarfbar->fbarfbar else { ProductionMatrixElement prodME = fbfb2fbfbHeME(dummy,false); createVertex(prodME,hardpro); } #ifndef NDEBUG if( debugME() ) debug(dummy); #endif } void MEff2ff::persistentOutput(PersistentOStream & os) const { - os << scalar_ << vector_ << tensor_; + os << scalar_ << vector_ << tensor_ << four_; } void MEff2ff::persistentInput(PersistentIStream & is, int) { - is >> scalar_ >> vector_ >> tensor_; + is >> scalar_ >> vector_ >> tensor_ >> four_; initializeMatrixElements(PDT::Spin1Half, PDT::Spin1Half, PDT::Spin1Half, PDT::Spin1Half); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigMEff2ff("Herwig::MEff2ff", "Herwig.so"); void MEff2ff::Init() { static ClassDocumentation documentation ("This is the implementation of the matrix element for fermion-" "antifermion -> fermion-antifermion."); } void MEff2ff::debug(double me2) const { if( !generator()->logfile().is_open() ) return; long id1 = mePartonData()[0]->id(); long id2 = mePartonData()[1]->id(); long id3 = mePartonData()[2]->id(); long id4 = mePartonData()[3]->id(); long aid1 = abs(mePartonData()[0]->id()); long aid2 = abs(mePartonData()[1]->id()); long aid3 = abs(mePartonData()[2]->id()); long aid4 = abs(mePartonData()[3]->id()); if( (aid1 != 1 && aid1 != 2) || (aid2 != 1 && aid2 != 2) ) return; double analytic(0.); if( id3 == id4 && id3 == 1000021 ) { tcSMPtr sm = generator()->standardModel(); double gs4 = sqr( 4.*Constants::pi*sm->alphaS(scale()) ); int Nc = sm->Nc(); double Cf = (sqr(Nc) - 1.)/2./Nc; Energy2 mgo2 = meMomenta()[3].m2(); long squark = (aid1 == 1) ? 1000001 : 1000002; Energy2 muL2 = sqr(getParticleData(squark)->mass()); Energy2 deltaL = muL2 - mgo2; Energy2 muR2 = sqr(getParticleData(squark + 1000000)->mass()); Energy2 deltaR = muR2 - mgo2; Energy2 s(sHat()); Energy2 m3s = meMomenta()[2].m2(); Energy2 m4s = meMomenta()[3].m2(); Energy4 spt2 = uHat()*tHat() - m3s*m4s; Energy2 t3(tHat() - m3s), u4(uHat() - m4s); double Cl = 2.*spt2*( (u4*u4 - deltaL*deltaL) + (t3*t3 - deltaL*deltaL) - (s*s/Nc/Nc) )/s/s/(u4 - deltaL)/(t3 - deltaL); Cl += deltaL*deltaL*( (1./sqr(t3 - deltaL)) + (1./sqr(u4 - deltaL)) - ( sqr( (1./(t3 - deltaL)) - (1./(u4 - deltaL)) )/Nc/Nc ) ); double Cr = 2.*spt2*( (u4*u4 - deltaR*deltaR) + (t3*t3 - deltaR*deltaR) - (s*s/Nc/Nc) )/s/s/(u4 - deltaR)/(t3 - deltaR); Cr += deltaR*deltaR*( (1./sqr(t3 - deltaR)) + (1./sqr(u4 - deltaR)) - ( sqr( (1./(t3 - deltaR)) - (1./(u4 - deltaR)) )/Nc/Nc ) ); analytic = gs4*Cf*(Cl + Cr)/4.; } else if( (aid3 == 5100001 || aid3 == 5100002 || aid3 == 6100001 || aid3 == 6100002) && (aid4 == 5100001 || aid4 == 5100002 || aid4 == 6100001 || aid4 == 6100002) ) { tcSMPtr sm = generator()->standardModel(); double gs4 = sqr( 4.*Constants::pi*sm->alphaS(scale()) ); Energy2 s(sHat()); Energy2 mf2 = meMomenta()[2].m2(); Energy2 t3(tHat() - mf2), u4(uHat() - mf2); Energy4 s2(sqr(s)), t3s(sqr(t3)), u4s(sqr(u4)); bool iflav = (aid2 - aid1 == 0); int alpha(aid3/1000000), beta(aid4/1000000); bool oflav = ((aid3 - aid1) % 10 == 0); if( alpha != beta ) { if( ( id1 > 0 && id2 > 0) || ( id1 < 0 && id2 < 0) ) { if( iflav ) analytic = gs4*( mf2*(2.*s2*s/t3s/u4s - 4.*s/t3/u4) + 2.*sqr(s2)/t3s/u4s - 8.*s2/t3/u4 + 5. )/9.; else analytic = gs4*( -2.*mf2*(1./t3 + u4/t3s) + 0.5 + 2.*u4s/t3s)/9.; } else analytic = gs4*( 2.*mf2*(1./t3 + u4/t3s) + 5./2. + 4.*u4/t3 + 2.*u4s/t3s)/9.; } else { if( ( id1 > 0 && id2 > 0) || ( id1 < 0 && id2 < 0) ) { if( iflav ) { analytic = gs4*( mf2*(6.*t3/u4s + 6.*u4/t3s - s/t3/u4) + 2.*(3.*t3s/u4s + 3.*u4s/t3s + 4.*s2/t3/u4 - 5.) )/27.; } else analytic = 2.*gs4*( -mf2*s/t3s + 0.25 + s2/t3s )/9.; } else { if( iflav ) { if( oflav ) analytic = gs4*( 2.*mf2*(4./s + s/t3s - 1./t3) + 23./6.+ 2.*s2/t3s + 8.*s/3./t3 + 6.*t3/s + 8.*t3s/s2 )/9.; else analytic = 4.*gs4*( 2.*mf2/s + (t3s + u4s)/s2)/9.; } else analytic = gs4*(4.*mf2*s/t3s + 5. + 4.*s2/t3s + 8.*s/t3 )/18.; } } if( id3 == id4 ) analytic /= 2.; } else return; double diff = abs(analytic - me2); if( diff > 1e-4 ) { generator()->log() << mePartonData()[0]->PDGName() << "," << mePartonData()[1]->PDGName() << "->" << mePartonData()[2]->PDGName() << "," << mePartonData()[3]->PDGName() << " difference: " << setprecision(10) << diff << " ratio: " << analytic/me2 << '\n'; } } diff --git a/MatrixElement/General/MEff2ff.h b/MatrixElement/General/MEff2ff.h --- a/MatrixElement/General/MEff2ff.h +++ b/MatrixElement/General/MEff2ff.h @@ -1,224 +1,220 @@ // -*- C++ -*- // // MEff2ff.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_MEff2ff_H #define HERWIG_MEff2ff_H // // This is the declaration of the MEff2ff class. // #include "GeneralHardME.h" #include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" #include "Herwig/MatrixElement/ProductionMatrixElement.h" #include "ThePEG/Helicity/Vertex/AbstractFFSVertex.h" #include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h" #include "ThePEG/Helicity/Vertex/AbstractFFTVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractFFFFVertex.h" namespace Herwig { using namespace ThePEG; using Helicity::SpinorWaveFunction; using Helicity::SpinorBarWaveFunction; /** * This is the implementation of the \f$ 2\to 2\f$ matrix element for * a \f$ \Psi \Psi \to \Psi \Psi\f$ process. It inherits from * GeneralHardME and implements the appropriate virtual functions. * - * @see \ref MEff2ffInterfaces "The Interfaces" - * defined for MEff2ff. * @see GeneralHardME */ class MEff2ff: public GeneralHardME { public: /** Vector of SpinorWaveFunctions. */ typedef vector SpinorVector; /** Vector of SpinorBarWaveFunctions. */ typedef vector SpinorBarVector; public: - /** - * The default constructor. - */ - MEff2ff() : scalar_(0), vector_(0), tensor_(0), spin_(4), sbar_(4) - {} - -public: - /** @name Virtual functions required by the MEBase class. */ //@{ /** * The matrix element for the kinematical configuration * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. * @return the matrix element scaled with sHat() to give a * dimensionless number. */ virtual double me2() const; //@} private: /** @name Functions to compute the ProductionMatrixElement. */ //@{ /** * Compute the matrix element for \f$\Psi\bar{\Psi}\to\Psi\bar{\Psi}\f$ * @param me2 colour averaged, spin summed ME * @param first Whether or not first call to decide if colour decomposition etc * should be calculated * @return ProductionMatrixElement containing results of * helicity calculations */ ProductionMatrixElement ffb2ffbHeME(double & me2, bool first) const; /** * Compute the matrix element for \f$\Psi\Psi\to\Psi\Psi\f$ * @param first Whether or not first call to decide if colour decomposition etc * should be calculated * @return ProductionMatrixElement containing results of * helicity calculations */ ProductionMatrixElement ff2ffHeME(double & me2, bool first) const; /** * Compute the matrix element for * \f$\bar{\Psi}\bar{\Psi}\to\bar{\Psi}\bar{\Psi}\f$ * @param me2 colour averaged, spin summed ME * @param first Whether or not first call to decide if colour decomposition etc * should be calculated * @return ProductionMatrixElement containing results of * helicity calculations */ ProductionMatrixElement fbfb2fbfbHeME(double & me2, bool first) const; /** * Compute the matrix element for \f$\Psi\bar{\Psi}\to\lambda\lambda\f$ * @param me2 colour averaged, spin summed ME * @param first Whether or not first call to decide if colour decomposition etc * should be calculated * @return ProductionMatrixElement containing results of * helicity calculations */ ProductionMatrixElement ffb2mfmfHeME(double & me2, bool first) const; //@} /** * Construct the vertex information for the spin correlations * @param sub Pointer to the relevent SubProcess */ virtual void constructVertex(tSubProPtr sub); protected: /** * A debugging function to test the value of me2 against an * analytic function. * @param me2 The value of the \f$ |\bar{\mathcal{M}}|^2 \f$ */ virtual void debug(double me2) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const {return new_ptr(*this);} /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const {return new_ptr(*this);} //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MEff2ff & operator=(const MEff2ff &); private: /** * Store the vector of FFSVertex pairs */ vector > scalar_; /** * Store the vector of FFVVertex pairs */ vector > vector_; /** * Store the vector of FFTVertex pairs */ vector > tensor_; /** + * Store any 4-point vertices + */ + vector four_; + + /** * Spinors */ - mutable vector > spin_; + mutable std::array spin_; /** * Barred spinors */ - mutable vector > sbar_; + mutable std::array sbar_; }; } #endif /* HERWIG_MEff2ff_H */ diff --git a/MatrixElement/General/MEff2rf.cc b/MatrixElement/General/MEff2rf.cc new file mode 100644 --- /dev/null +++ b/MatrixElement/General/MEff2rf.cc @@ -0,0 +1,580 @@ +// -*- C++ -*- +// +// This is the implementation of the non-inlined, non-templated member +// functions of the MEff2rf class. +// + +#include "MEff2rf.h" +#include "ThePEG/Interface/ClassDocumentation.h" +#include "ThePEG/Utilities/DescribeClass.h" +#include "ThePEG/Persistency/PersistentOStream.h" +#include "ThePEG/Persistency/PersistentIStream.h" + +using namespace Herwig; + + +double MEff2rf::me2() const { + // calculate the fermion spinors + for(unsigned int ix=0;ix<3;++ix) { + spin_[ix].clear(); + sbar_[ix].clear(); + unsigned int iy(ix); + if(ix==2) ++iy; + for(unsigned int ih=0;ih<2;++ih) { + spin_[ix].push_back(SpinorWaveFunction (rescaledMomenta()[iy], + mePartonData()[iy], + ih, ix<2 ? incoming : outgoing)); + sbar_[ix].push_back(SpinorBarWaveFunction(rescaledMomenta()[iy], + mePartonData()[iy], + ih, ix<2 ? incoming : outgoing)); + } + } + rs_ .clear(); + rsbar_.clear(); + // calculate the rs spinors + bool massless = mePartonData()[2]->mass()==ZERO; + for(unsigned int ih=0;ih<4;++ih) { + if(massless && (ih==1 || ih==2) ) continue; + rs_ .push_back(RSSpinorWaveFunction(rescaledMomenta()[2], + mePartonData()[2],ih, outgoing)); + rsbar_.push_back(RSSpinorBarWaveFunction(rescaledMomenta()[2], + mePartonData()[2],ih,outgoing)); + } + double full_me(0.); + if( mePartonData()[0]->id() > 0 && mePartonData()[1]->id() < 0) { + if(mePartonData()[2]->id()>0) + ffb2rfbHeME (full_me,true); + else + ffb2rbfHeME (full_me,true); + } + else if( mePartonData()[0]->id() > 0 && mePartonData()[1]->id() > 0 ) + ff2rfHeME(full_me,true); + else if( mePartonData()[0]->id() < 0 && mePartonData()[1]->id() < 0 ) + fbfb2rbfbHeME(full_me,true); + else + assert(false); + return full_me; +} + +IBPtr MEff2rf::clone() const { + return new_ptr(*this); +} + +IBPtr MEff2rf::fullclone() const { + return new_ptr(*this); +} + +void MEff2rf::doinit() { + GeneralHardME::doinit(); + scalar_.resize(numberOfDiags()); + vector_.resize(numberOfDiags()); + initializeMatrixElements(PDT::Spin1Half, PDT::Spin1Half, + PDT::Spin3Half, PDT::Spin1Half); + for(size_t ix = 0;ix < numberOfDiags(); ++ix) { + const HPDiagram & current = getProcessInfo()[ix]; + tcPDPtr offshell = current.intermediate; + if(offshell->iSpin() == PDT::Spin0) { + if(current.channelType == HPDiagram::sChannel || + (current.channelType == HPDiagram::tChannel && + !current.ordered.second)) { + AbstractFFSVertexPtr vert1 = dynamic_ptr_cast + (current.vertices.first); + AbstractRFSVertexPtr vert2 = dynamic_ptr_cast + (current.vertices.second); + scalar_[ix] = make_pair(vert1, vert2); + } + else { + AbstractFFSVertexPtr vert1 = dynamic_ptr_cast + (current.vertices.second); + AbstractRFSVertexPtr vert2 = dynamic_ptr_cast + (current.vertices.first ); + scalar_[ix] = make_pair(vert1, vert2); + } + } + else if(offshell->iSpin() == PDT::Spin1) { + if(current.channelType == HPDiagram::sChannel || + (current.channelType == HPDiagram::tChannel && + !current.ordered.second)) { + AbstractFFVVertexPtr vert1 = dynamic_ptr_cast + (current.vertices.first); + AbstractRFVVertexPtr vert2 = dynamic_ptr_cast + (current.vertices.second); + vector_[ix] = make_pair(vert1, vert2); + } + else { + AbstractFFVVertexPtr vert1 = dynamic_ptr_cast + (current.vertices.second); + AbstractRFVVertexPtr vert2 = dynamic_ptr_cast + (current.vertices.first ); + vector_[ix] = make_pair(vert1, vert2); + } + } + } +} + +void MEff2rf::persistentOutput(PersistentOStream & os) const { + os << scalar_ << vector_; +} + +void MEff2rf::persistentInput(PersistentIStream & is, int) { + is >> scalar_ >> vector_; + initializeMatrixElements(PDT::Spin1Half, PDT::Spin1Half, + PDT::Spin3Half, PDT::Spin1Half); +} + + +// The following static variable is needed for the type +// description system in ThePEG. +DescribeClass + describeHerwigMEff2rf("Herwig::MEff2rf", "Herwig.so"); + +void MEff2rf::Init() { + + static ClassDocumentation documentation + ("There is no documentation for the MEff2rf class"); + +} + +ProductionMatrixElement +MEff2rf::ffb2rfbHeME(double & me2, bool first) const { + const Energy2 q2(scale()); + // weights for the selection of the diagram + vector me(numberOfDiags(), 0.); + // weights for the selection of the colour flow + vector flow(numberOfFlows(),0.); + // flow over the helicities and diagrams + bool massless = mePartonData()[2]->mass()==ZERO; + for(unsigned int ifhel1 = 0; ifhel1 < 2; ++ifhel1) { + for(unsigned int ifhel2 = 0; ifhel2 < 2; ++ifhel2) { + for(unsigned int ofhel1 = 0; ofhel1 < 4; ++ofhel1) { + if(massless && (ofhel1==1 || ofhel1==2)) continue; + for(unsigned int ofhel2 = 0; ofhel2 < 2; ++ofhel2) { + vector flows(numberOfFlows(),0.); + for(HPCount ix = 0; ix < numberOfDiags(); ++ix) { + Complex diag(0.); + const HPDiagram & current = getProcessInfo()[ix]; + tcPDPtr offshell = current.intermediate; + if(current.channelType == HPDiagram::tChannel) { + if(offshell->iSpin() == PDT::Spin0) { + if(current.ordered.second) { + ScalarWaveFunction interS = scalar_[ix].first-> + evaluate(q2, 3, offshell,spin_[2][ofhel2],sbar_[1][ifhel2]); + diag = -scalar_[ix].second-> + evaluate(q2, spin_[0][ifhel1],rsbar_[ofhel1],interS); + } + else { + ScalarWaveFunction interS = scalar_[ix].second-> + evaluate(q2, 3, offshell,rs_[ofhel1],sbar_[1][ifhel2]); + diag = scalar_[ix].first-> + evaluate(q2, spin_[0][ifhel1],sbar_[2][ofhel2],interS); + } + } + else if(offshell->iSpin() == PDT::Spin1) { + if(current.ordered.second) { + VectorWaveFunction interV = vector_[ix].first-> + evaluate(q2, 3, offshell,spin_[2][ofhel2],sbar_[1][ifhel2]); + diag = -vector_[ix].second-> + evaluate(q2, spin_[0][ifhel1], rsbar_[ofhel1], interV); + } + else { + VectorWaveFunction interV = vector_[ix].second-> + evaluate(q2, 3, offshell,rs_[ofhel1],sbar_[1][ifhel2]); + diag = vector_[ix].first-> + evaluate(q2, spin_[0][ifhel1], sbar_[2][ofhel2], interV); + } + } + else + assert(false); + } + else if(current.channelType == HPDiagram::sChannel) { + if(offshell->iSpin() == PDT::Spin0) { + ScalarWaveFunction interS = scalar_[ix].first-> + evaluate(q2, 1, offshell, spin_[0][ifhel1], sbar_[1][ifhel2]); + diag = scalar_[ix].second-> + evaluate(q2,spin_[2][ofhel2],rsbar_[ofhel1], interS); + } + else if(offshell->iSpin() == PDT::Spin1) { + VectorWaveFunction interV = vector_[ix].first-> + evaluate(q2, 1, offshell,spin_[0][ifhel1], sbar_[1][ifhel2]); + diag = vector_[ix].second-> + evaluate(q2, spin_[2][ofhel2],rsbar_[ofhel1] , interV); + } + else + assert(false); + } + else + assert(false); + me[ix] += norm(diag); + diagramME()[ix](ifhel1, ifhel2, ofhel1, ofhel2) = diag; + //Compute flows + for(size_t iy = 0; iy < current.colourFlow.size(); ++iy) { + assert(current.colourFlow[iy].first me(numberOfDiags(), 0.); + // weights for the selection of the colour flow + vector flow(numberOfFlows(),0.); + // flow over the helicities and diagrams + bool massless = mePartonData()[2]->mass()==ZERO; + for(unsigned int ifhel1 = 0; ifhel1 < 2; ++ifhel1) { + for(unsigned int ifhel2 = 0; ifhel2 < 2; ++ifhel2) { + for(unsigned int ofhel1 = 0; ofhel1 < 4; ++ofhel1) { + if(massless && (ofhel1==1 || ofhel1==2)) continue; + for(unsigned int ofhel2 = 0; ofhel2 < 2; ++ofhel2) { + vector flows(numberOfFlows(),0.); + for(HPCount ix = 0; ix < numberOfDiags(); ++ix) { + Complex diag(0.); + const HPDiagram & current = getProcessInfo()[ix]; + tcPDPtr offshell = current.intermediate; + if(current.channelType == HPDiagram::tChannel) { + if(offshell->iSpin() == PDT::Spin0) { + if(current.ordered.second) { + ScalarWaveFunction interS = scalar_[ix].first-> + evaluate(q2, 3, offshell,spin_[2][ofhel2],sbar_[1][ifhel2]); + diag = -scalar_[ix].second-> + evaluate(q2, spin_[0][ifhel1],rsbar_[ofhel1],interS); + } + else { + ScalarWaveFunction interS = scalar_[ix].second-> + evaluate(q2, 3, offshell,rs_[ofhel1],sbar_[1][ifhel2]); + diag = scalar_[ix].first-> + evaluate(q2, spin_[0][ifhel1],sbar_[2][ofhel2],interS); + } + } + else if(offshell->iSpin() == PDT::Spin1) { + if(current.ordered.second) { + VectorWaveFunction interV = vector_[ix].first-> + evaluate(q2, 3, offshell,spin_[2][ofhel2],sbar_[1][ifhel2]); + diag = -vector_[ix].second-> + evaluate(q2, spin_[0][ifhel1], rsbar_[ofhel1], interV); + } + else { + VectorWaveFunction interV = vector_[ix].second-> + evaluate(q2, 3, offshell,rs_[ofhel1],sbar_[1][ifhel2]); + diag = vector_[ix].first-> + evaluate(q2, spin_[0][ifhel1], sbar_[3][ofhel2], interV); + } + } + else + assert(false); + } + else if(current.channelType == HPDiagram::sChannel) { + if(offshell->iSpin() == PDT::Spin0) { + ScalarWaveFunction interS = scalar_[ix].second-> + evaluate(q2, 1, offshell,rs_[ofhel1],sbar_[2][ofhel2]); + diag = -scalar_[ix].first-> + evaluate(q2, spin_[0][ifhel1], sbar_[1][ifhel2], interS); + } + else if(offshell->iSpin() == PDT::Spin1) { + VectorWaveFunction interV = vector_[ix].second-> + evaluate(q2, 1, offshell,rs_[ofhel1],sbar_[2][ofhel2]); + diag = -vector_[ix].first-> + evaluate(q2, spin_[0][ifhel1], sbar_[1][ifhel2], interV); + } + else + assert(false); + } + else + assert(false); + me[ix] += norm(diag); + diagramME()[ix](ifhel1, ifhel2, ofhel1, ofhel2) = diag; + //Compute flows + for(size_t iy = 0; iy < current.colourFlow.size(); ++iy) { + assert(current.colourFlow[iy].first me(numberOfDiags(), 0.); + // weights for the selection of the colour flow + vector flow(numberOfFlows(),0.); + bool massless = mePartonData()[2]->mass()==ZERO; + // flow over the helicities and diagrams + for(unsigned int ifhel1 = 0; ifhel1 < 2; ++ifhel1) { + for(unsigned int ifhel2 = 0; ifhel2 < 2; ++ifhel2) { + for(unsigned int ofhel1 = 0; ofhel1 < 4; ++ofhel1) { + if(massless && (ofhel1==1 || ofhel1==2)) continue; + for(unsigned int ofhel2 = 0; ofhel2 < 2; ++ofhel2) { + vector flows(numberOfFlows(),0.); + for(HPCount ix = 0; ix < numberOfDiags(); ++ix) { + Complex diag(0.); + const HPDiagram & current = getProcessInfo()[ix]; + tcPDPtr offshell = current.intermediate; + if(current.channelType == HPDiagram::tChannel) { + if(offshell->iSpin() == PDT::Spin0) { + if(current.ordered.second) { + ScalarWaveFunction interS = scalar_[ix].first-> + evaluate(q2, 3, offshell,spin_[1][ifhel2],sbar_[2][ofhel2]); + diag = scalar_[ix].second-> + evaluate(q2, spin_[0][ifhel1], rsbar_[ofhel1], interS); + } + else { + ScalarWaveFunction interS = scalar_[ix].second-> + evaluate(q2, 3, offshell,spin_[1][ifhel2],rsbar_[ofhel1]); + diag = -scalar_[ix].first-> + evaluate(q2, spin_[0][ifhel1], sbar_[2][ofhel2], interS); + } + } + else if(offshell->iSpin() == PDT::Spin1) { + if(current.ordered.second) { + VectorWaveFunction interV = vector_[ix].first-> + evaluate(q2, 3, offshell,spin_[1][ifhel2],sbar_[2][ofhel2]); + diag = vector_[ix].second-> + evaluate(q2, spin_[0][ifhel1], rsbar_[ofhel1], interV); + } + else { + VectorWaveFunction interV = vector_[ix].second-> + evaluate(q2, 3, offshell,spin_[1][ifhel2],rsbar_[ofhel1]); + diag = -vector_[ix].first-> + evaluate(q2, spin_[0][ifhel1], sbar_[2][ofhel2], interV); + } + } + else + assert(false); + } + else if(current.channelType == HPDiagram::sChannel) { + if(offshell->iSpin() == PDT::Spin0) { + ScalarWaveFunction interS = + scalar_[ix].first->evaluate(q2, 1, offshell, spin_[0][ifhel1], sbar_[1][ifhel2]); + diag = scalar_[ix].second->evaluate(q2, spin_[2][ofhel2],rsbar_[ofhel1],interS); + } + else if(offshell->iSpin() == PDT::Spin1) { + VectorWaveFunction interV = vector_[ix].first-> + evaluate(q2, 1, offshell,spin_[0][ifhel1], sbar_[1][ifhel2]); + diag = vector_[ix].second->evaluate(q2,spin_[2][ofhel2],rsbar_[ofhel1],interV); + } + else + assert(false); + } + else + assert(false); + me[ix] += norm(diag); + diagramME()[ix](ifhel1, ifhel2, ofhel1, ofhel2) = diag; + //Compute flows + for(size_t iy = 0; iy < current.colourFlow.size(); ++iy) { + assert(current.colourFlow[iy].first me(numberOfDiags(), 0.); + // weights for the selection of the colour flow + vector flow(numberOfFlows(),0.); + // flow over the helicities and diagrams + bool massless = mePartonData()[2]->mass()==ZERO; + // flow over the helicities and diagrams + for(unsigned int ifhel1 = 0; ifhel1 < 2; ++ifhel1) { + for(unsigned int ifhel2 = 0; ifhel2 < 2; ++ifhel2) { + for(unsigned int ofhel1 = 0; ofhel1 < 4; ++ofhel1) { + if(massless && (ofhel1==1 || ofhel1==2)) continue; + for(unsigned int ofhel2 = 0; ofhel2 < 2; ++ofhel2) { + vector flows(numberOfFlows(),0.); + for(HPCount ix = 0; ix < numberOfDiags(); ++ix) { + Complex diag(0.); + const HPDiagram & current = getProcessInfo()[ix]; + tcPDPtr offshell = current.intermediate; + if(current.channelType == HPDiagram::tChannel) { + if(offshell->iSpin() == PDT::Spin0) { + if(current.ordered.second) { + ScalarWaveFunction interS = scalar_[ix].first-> + evaluate(q2, 3, offshell,spin_[2][ofhel2],sbar_[1][ifhel2]); + diag = scalar_[ix].second-> + evaluate(q2, rs_[ofhel1], sbar_[0][ifhel1], interS); + } + else { + ScalarWaveFunction interS = scalar_[ix].second-> + evaluate(q2, 3, offshell,rs_[ofhel1],sbar_[1][ifhel2]); + diag = -scalar_[ix].first-> + evaluate(q2, spin_[2][ofhel2], sbar_[0][ifhel1], interS); + } + } + else if(offshell->iSpin() == PDT::Spin1) { + if(current.ordered.second) { + VectorWaveFunction interV = vector_[ix].first-> + evaluate(q2, 3, offshell,spin_[2][ofhel2],sbar_[1][ifhel2]); + diag = vector_[ix].second-> + evaluate(q2, rs_[ofhel1], sbar_[0][ifhel1], interV); + } + else { + VectorWaveFunction interV = vector_[ix].second-> + evaluate(q2, 3, offshell,rs_[ofhel1],sbar_[1][ifhel2]); + diag = -vector_[ix].first-> + evaluate(q2, spin_[2][ofhel2], sbar_[0][ifhel1], interV); + } + } + else + assert(false); + } + else if(current.channelType == HPDiagram::sChannel) { + if(offshell->CC()) offshell=offshell->CC(); + if(offshell->iSpin() == PDT::Spin0) { + ScalarWaveFunction interS = scalar_[ix].second-> + evaluate(q2, 1, offshell,spin_[2][ofhel2],rsbar_[ofhel1]); + diag = scalar_[ix].first-> + evaluate(q2, spin_[0][ifhel1], sbar_[1][ifhel2], interS); + } + else if(offshell->iSpin() == PDT::Spin1) { + VectorWaveFunction interV = vector_[ix].second-> + evaluate(q2, 1, offshell,spin_[2][ofhel2],rsbar_[ofhel1]); + diag = vector_[ix].first-> + evaluate(q2, spin_[0][ifhel1], sbar_[1][ifhel2], interV); + } + else + assert(false); + } + else + assert(false); + me[ix] += norm(diag); + diagramME()[ix](ifhel1, ifhel2, ofhel1, ofhel2) = diag; + //Compute flows + for(size_t iy = 0; iy < current.colourFlow.size(); ++iy) { + assert(current.colourFlow[iy].first1); + SpinorBarWaveFunction(sbar_[ix],hardpro[iy], + ix<2 ? incoming : outgoing,ix>1); + } + rs_ .clear(); + rsbar_.clear(); + // calculate the rs spinors + RSSpinorWaveFunction (rs_ , hardpro[2], outgoing, true); + RSSpinorBarWaveFunction(rsbar_, hardpro[2], outgoing, true); + double dummy(0.); + if( mePartonData()[0]->id() > 0 && mePartonData()[1]->id() < 0) { + if(mePartonData()[2]->id()>0) { + ProductionMatrixElement prodME = ffb2rfbHeME (dummy,true); + createVertex(prodME,hardpro); + } + else { + ProductionMatrixElement prodME = ffb2rbfHeME (dummy,true); + createVertex(prodME,hardpro); + } + } + else if( mePartonData()[0]->id() > 0 && mePartonData()[1]->id() > 0 ) { + ProductionMatrixElement prodME = ff2rfHeME(dummy,true); + createVertex(prodME,hardpro); + } + else if( mePartonData()[0]->id() < 0 && mePartonData()[1]->id() < 0 ) { + ProductionMatrixElement prodME = fbfb2rbfbHeME(dummy,true); + createVertex(prodME,hardpro); + } + else + assert(false); +} diff --git a/MatrixElement/General/MEff2rf.h b/MatrixElement/General/MEff2rf.h new file mode 100644 --- /dev/null +++ b/MatrixElement/General/MEff2rf.h @@ -0,0 +1,219 @@ +// -*- C++ -*- +#ifndef Herwig_MEff2rf_H +#define Herwig_MEff2rf_H +// +// This is the declaration of the MEff2rf class. +// + +#include "GeneralHardME.h" +#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" +#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" +#include "ThePEG/Helicity/WaveFunction/RSSpinorWaveFunction.h" +#include "ThePEG/Helicity/WaveFunction/RSSpinorBarWaveFunction.h" +#include "Herwig/MatrixElement/ProductionMatrixElement.h" +#include "ThePEG/Helicity/Vertex/AbstractFFSVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractRFSVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractRFVVertex.h" + +namespace Herwig { + +using namespace ThePEG; +using Helicity::SpinorWaveFunction; +using Helicity::SpinorBarWaveFunction; +using Helicity::RSSpinorWaveFunction; +using Helicity::RSSpinorBarWaveFunction; + +/** + * This is the implementation of the \f$ 2\to 2\f$ matrix element for + * a fermion-fermion to fermion RS fermion process. It inherits from + * GeneralHardME and implements the appropriate virtual functions. + * + * @see GeneralHardME + */ +class MEff2rf: public GeneralHardME { + +public: + + /** Vector of SpinorWaveFunctions. */ + typedef vector SpinorVector; + + /** Vector of SpinorBarWaveFunctions. */ + typedef vector SpinorBarVector; + + /** Vector of RSSpinorWaveFunctions. */ + typedef vector RSSpinorVector; + + /** Vector of RSSpinorBarWaveFunctions. */ + typedef vector RSSpinorBarVector; + +public: + + /** @name Virtual functions required by the MEBase class. */ + //@{ + /** + * The matrix element for the kinematical configuration + * previously provided by the last call to setKinematics(), suitably + * scaled by sHat() to give a dimension-less number. + * @return the matrix element scaled with sHat() to give a + * dimensionless number. + */ + virtual double me2() const; + //@} + +private: + + /** @name Functions to compute the ProductionMatrixElement. */ + //@{ + /** + * Compute the matrix element for \f$\Psi\bar{\Psi}\to\Psi\bar{\Psi}\f$ + * @param me2 colour averaged, spin summed ME + * @param first Whether or not first call to decide if colour decomposition etc + * should be calculated + * @return ProductionMatrixElement containing results of + * helicity calculations + */ + ProductionMatrixElement + ffb2rfbHeME(double & me2, bool first) const; + + /** + * Compute the matrix element for \f$\Psi\bar{\Psi}\to\Psi\bar{\Psi}\f$ + * @param me2 colour averaged, spin summed ME + * @param first Whether or not first call to decide if colour decomposition etc + * should be calculated + * @return ProductionMatrixElement containing results of + * helicity calculations + */ + ProductionMatrixElement + ffb2rbfHeME(double & me2, bool first) const; + + /** + * Compute the matrix element for \f$\Psi\Psi\to\Psi\Psi\f$ + * @param first Whether or not first call to decide if colour decomposition etc + * should be calculated + * @return ProductionMatrixElement containing results of + * helicity calculations + */ + ProductionMatrixElement ff2rfHeME(double & me2, bool first) const; + + /** + * Compute the matrix element for + * \f$\bar{\Psi}\bar{\Psi}\to\bar{\Psi}\bar{\Psi}\f$ + * @param me2 colour averaged, spin summed ME + * @param first Whether or not first call to decide if colour decomposition etc + * should be calculated + * @return ProductionMatrixElement containing results of + * helicity calculations + */ + ProductionMatrixElement fbfb2rbfbHeME(double & me2, bool first) const; + + /** + * Compute the matrix element for \f$\Psi\bar{\Psi}\to\lambda\lambda\f$ + * @param me2 colour averaged, spin summed ME + * @param first Whether or not first call to decide if colour decomposition etc + * should be calculated + * @return ProductionMatrixElement containing results of + * helicity calculations + */ + ProductionMatrixElement + ffb2mfmfHeME(double & me2, bool first) const; + //@} + + /** + * Construct the vertex information for the spin correlations + * @param sub Pointer to the relevent SubProcess + */ + virtual void constructVertex(tSubProPtr sub); + +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. + */ + MEff2rf & operator=(const MEff2rf &); + +private: + + /** + * Store the vector of FFSVertex pairs + */ + vector > scalar_; + + /** + * Store the vector of FFVVertex pairs + */ + vector > vector_; + + /** + * Spinors + */ + mutable std::array spin_; + + /** + * Barred spinors + */ + mutable std::array sbar_; + + mutable RSSpinorVector rs_; + mutable RSSpinorBarVector rsbar_; +}; + +} + +#endif /* Herwig_MEff2rf_H */ diff --git a/MatrixElement/General/MEff2ss.cc b/MatrixElement/General/MEff2ss.cc --- a/MatrixElement/General/MEff2ss.cc +++ b/MatrixElement/General/MEff2ss.cc @@ -1,318 +1,332 @@ // -*- C++ -*- // // MEff2ss.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 MEff2ss class. // #include "MEff2ss.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; using ThePEG::Helicity::VectorWaveFunction; using ThePEG::Helicity::TensorWaveFunction; using ThePEG::Helicity::incoming; using ThePEG::Helicity::outgoing; void MEff2ss::doinit() { GeneralHardME::doinit(); fermion_.resize(numberOfDiags()); + RSfermion_.resize(numberOfDiags()); scalar_ .resize(numberOfDiags()); vector_ .resize(numberOfDiags()); tensor_ .resize(numberOfDiags()); + fourPoint_.resize(numberOfDiags()); initializeMatrixElements(PDT::Spin1Half, PDT::Spin1Half, PDT::Spin0 , PDT::Spin0 ); for(HPCount i = 0; i < numberOfDiags(); ++i) { const HPDiagram & current = getProcessInfo()[i]; if(current.channelType == HPDiagram::tChannel) { if(current.intermediate->iSpin() == PDT::Spin1Half) fermion_[i] = make_pair(dynamic_ptr_cast(current.vertices.first), dynamic_ptr_cast(current.vertices.second)); + else if(current.intermediate->iSpin() == PDT::Spin3Half) + RSfermion_[i] = + make_pair(dynamic_ptr_cast(current.vertices.first), + dynamic_ptr_cast(current.vertices.second)); else throw InitException() << "MEFF2ss:doinit() - t-channel" << " intermediate must be a fermion " << Exception::runerror; } else if(current.channelType == HPDiagram::sChannel) { if(current.intermediate->iSpin() == PDT::Spin0) scalar_[i] = make_pair(dynamic_ptr_cast(current.vertices.first), dynamic_ptr_cast(current.vertices.second)); else if(current.intermediate->iSpin() == PDT::Spin1) vector_[i] = make_pair(dynamic_ptr_cast(current.vertices.first), dynamic_ptr_cast(current.vertices.second)); else if(current.intermediate->iSpin() == PDT::Spin2) tensor_[i] = make_pair(dynamic_ptr_cast(current.vertices.first), dynamic_ptr_cast(current.vertices.second)); else throw InitException() << "MEFF2ss:doinit() - s-channel" << " intermediate must be a vector or tensor " << Exception::runerror; } + else if(current.channelType == HPDiagram::fourPoint) { + fourPoint_[i] = dynamic_ptr_cast(current.vertices.first); + } else throw InitException() << "MEFF2ss:doinit() - Cannot find correct " << "channel from diagram. Vertex not cast! " << Exception::runerror; } } double MEff2ss::me2() const { // first setup wavefunctions for external particles SpinorVector sp(2); SpinorBarVector sbar(2); for( unsigned int i = 0; i < 2; ++i ) { sp[i] = SpinorWaveFunction (rescaledMomenta()[0], mePartonData()[0], i, incoming); sbar[i] = SpinorBarWaveFunction(rescaledMomenta()[1], mePartonData()[1], i, incoming); } ScalarWaveFunction sca1(rescaledMomenta()[2], mePartonData()[2], 1., outgoing); ScalarWaveFunction sca2(rescaledMomenta()[3], mePartonData()[3], 1., outgoing); // calculate the ME double full_me(0.); ff2ssME(sp, sbar, sca1, sca2, full_me,true); // debugging tests if needed #ifndef NDEBUG if( debugME() ) debug(full_me); #endif // return the answer return full_me; } ProductionMatrixElement MEff2ss::ff2ssME(const SpinorVector & sp, const SpinorBarVector & sbar, const ScalarWaveFunction & sca1, const ScalarWaveFunction & sca2, double & me2, bool first) const { // scale const Energy2 q2(scale()); // weights for the selection of the diagram vector me(numberOfDiags(), 0.); // weights for the selection of the colour flow vector flow(numberOfFlows(),0.); // flow over the helicities and diagrams for(unsigned int if1 = 0; if1 < 2; ++if1) { for(unsigned int if2 = 0; if2 < 2; ++if2) { vector flows(numberOfFlows(),0.); for(HPCount ix = 0; ix < numberOfDiags(); ++ix) { Complex diag(0.); const HPDiagram & current = getProcessInfo()[ix]; tcPDPtr internal(current.intermediate); - if(current.channelType == HPDiagram::tChannel && - internal->iSpin() == PDT::Spin1Half) { + if(current.channelType == HPDiagram::tChannel) { if(internal->CC()) internal=internal->CC(); - unsigned int iopt = ( abs(sbar[if2].particle()->id()) == abs(internal->id()) || - abs(sp[if1] .particle()->id()) == abs(internal->id())) ? 5 : 3; - SpinorBarWaveFunction interFB; - if(current.ordered.second) { - if(iopt==3) { + if(internal->iSpin() == PDT::Spin1Half) { + SpinorBarWaveFunction interFB; + if(current.ordered.second) { interFB = fermion_[ix].second-> - evaluate(q2, iopt, internal, sbar[if2], sca2); + evaluate(q2, 3, internal, sbar[if2], sca2); + diag = fermion_[ix].first->evaluate(q2, sp[if1], interFB, sca1); } else { interFB = fermion_[ix].second-> - evaluate(q2, iopt, internal, sbar[if2], sca2, 0.*GeV, 0.*GeV); + evaluate(q2, 3, internal, sbar[if2], sca1); + diag = fermion_[ix].first->evaluate(q2, sp[if1], interFB, sca2); } - diag = fermion_[ix].first->evaluate(q2, sp[if1], interFB, sca1); } - else { - if(iopt==3) { - interFB = fermion_[ix].second-> - evaluate(q2, iopt, internal, sbar[if2], sca1); + else if (internal->iSpin() == PDT::Spin3Half) { + RSSpinorBarWaveFunction interFB; + if(current.ordered.second) { + interFB = RSfermion_[ix].second-> + evaluate(q2, 3, internal, sbar[if2], sca2); + diag = RSfermion_[ix].first->evaluate(q2, sp[if1], interFB, sca1); } - else { - interFB = fermion_[ix].second-> - evaluate(q2, iopt, internal, sbar[if2], sca1, 0.*GeV, 0.*GeV); + else { + interFB = RSfermion_[ix].second-> + evaluate(q2, 3, internal, sbar[if2], sca1); + diag = RSfermion_[ix].first->evaluate(q2, sp[if1], interFB, sca2); } - diag = fermion_[ix].first->evaluate(q2, sp[if1], interFB, sca2); } + else + assert(false); } else if(current.channelType == HPDiagram::sChannel) { if(internal->iSpin() == PDT::Spin0) { ScalarWaveFunction interS = scalar_[ix].first-> evaluate(q2, 1, internal, sp[if1], sbar[if2]); diag = scalar_[ix].second->evaluate(q2, interS, sca2, sca1); } else if(internal->iSpin() == PDT::Spin1) { VectorWaveFunction interV = vector_[ix].first-> evaluate(q2, 1, internal, sp[if1], sbar[if2]); diag = vector_[ix].second->evaluate(q2, interV, sca2, sca1); } else if(internal->iSpin() == PDT::Spin2) { TensorWaveFunction interT = tensor_[ix].first-> evaluate(q2, 1, internal, sp[if1], sbar[if2]); diag = tensor_[ix].second ->evaluate(q2, sca2, sca1, interT); } } + else if(current.channelType == HPDiagram::fourPoint) { + diag = fourPoint_[ix]->evaluate(q2,sp[if1], sbar[if2],sca1,sca2); + } // diagram me[ix] += norm(diag); diagramME()[ix](if1,if2,0,0) = diag; // contributions to the different colour flows for(unsigned int iy = 0; iy < current.colourFlow.size(); ++iy) { assert(current.colourFlow[iy].first> fermion_ >> scalar_ >> vector_ >> tensor_; + is >> fermion_ >> scalar_ >> vector_ >> tensor_ >> fourPoint_ >> RSfermion_; initializeMatrixElements(PDT::Spin1Half, PDT::Spin1Half, PDT::Spin0 , PDT::Spin0 ); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigMEff2ss("Herwig::MEff2ss", "Herwig.so"); void MEff2ss::Init() { static ClassDocumentation documentation ("MEff2ss implements the ME calculation of the fermion-antifermion " "to scalar-scalar hard process."); } void MEff2ss::constructVertex(tSubProPtr sub) { //get particles ParticleVector ext = hardParticles(sub); //First calculate wave functions with off-shell momenta //to calculate correct spin information SpinorVector sp; SpinorBarVector sbar; SpinorWaveFunction (sp , ext[0], incoming, false); SpinorBarWaveFunction (sbar, ext[1], incoming, false); ScalarWaveFunction sca1( ext[2], outgoing, true); ScalarWaveFunction sca2( ext[3], outgoing, true); // Need to use rescale momenta to calculate matrix element setRescaledMomenta(ext); // wave functions with rescaled momenta SpinorWaveFunction spr(rescaledMomenta()[0], ext[0]->dataPtr(), incoming); SpinorBarWaveFunction sbr(rescaledMomenta()[1], ext[1]->dataPtr(), incoming); sca1 = ScalarWaveFunction(rescaledMomenta()[2], ext[2]->dataPtr(), outgoing); sca2 = ScalarWaveFunction(rescaledMomenta()[3], ext[3]->dataPtr(), outgoing); for( unsigned int ihel = 0; ihel < 2; ++ihel ) { spr.reset(ihel); sp[ihel] = spr; sbr.reset(ihel); sbar[ihel] = sbr; } double dummy(0.); ProductionMatrixElement pme = ff2ssME(sp, sbar, sca1, sca2, dummy,false); #ifndef NDEBUG if( debugME() ) debug(dummy/36.); #endif createVertex(pme,ext); } void MEff2ss::debug(double me2) const { if( !generator()->logfile().is_open() ) return; long id1 = mePartonData()[0]->id(); long id2 = mePartonData()[1]->id(); long id3 = mePartonData()[2]->id(); long id4 = mePartonData()[3]->id(); if( (abs(id1) != 1 && abs(id1) != 2) || (abs(id2) != 1 && abs(id2) != 2) || ( abs(id3) != 1000001 && abs(id3) != 1000002 && abs(id3) != 2000001 && abs(id3) != 2000002 ) || ( abs(id4) != 1000001 && abs(id4) != 1000002 && abs(id4) != 2000001 && abs(id4) != 2000002 ) ) return; tcSMPtr sm = generator()->standardModel(); double gs4 = sqr( 4.*Constants::pi*sm->alphaS(scale()) ); int Nc = sm->Nc(); double Cf = (sqr(Nc) - 1)/2./Nc; Energy2 s(sHat()); Energy2 mgos = sqr( getParticleData(ParticleID::SUSY_g)->mass()); Energy2 m3s = sqr(mePartonData()[2]->mass()); Energy2 m4s = sqr(mePartonData()[3]->mass()); Energy4 spt2 = uHat()*tHat() - m3s*m4s; Energy2 tgl(tHat() - mgos), ugl(uHat() - mgos); unsigned int alpha = abs(id3)/1000000; unsigned int beta = abs(id4)/1000000; bool iflav = ( abs(id1) == abs(id2) ); unsigned int oflav = ( abs(id3) - abs(id1) ) % 10; double analytic(0.); if( alpha != beta ) { if( ( id1 > 0 && id2 > 0) || ( id1 < 0 && id2 < 0) ) { analytic = spt2/sqr(tgl); if( iflav ) analytic += spt2/sqr(ugl); } else { analytic = s*mgos/sqr(tgl); } } else { if( oflav != 0 ) { analytic = 2.*spt2/sqr(s); } else if( ( id1 > 0 && id2 > 0) || ( id1 < 0 && id2 < 0) ) { analytic = s*mgos/sqr(tgl); if( iflav ) { analytic += s*mgos/sqr(ugl) - 2.*s*mgos/Nc/tgl/ugl; } analytic /= ( iflav ? 2. : 1.); } else { analytic = spt2/sqr(tgl); if( iflav ) { analytic += 2.*spt2/sqr(s) - 2.*spt2/Nc/s/tgl; } } } analytic *= gs4*Cf/2./Nc; double diff = abs(analytic - me2); if( diff > 1e-4 ) { generator()->log() << mePartonData()[0]->PDGName() << "," << mePartonData()[1]->PDGName() << "->" << mePartonData()[2]->PDGName() << "," << mePartonData()[3]->PDGName() << " difference: " << setprecision(10) << diff << " ratio: " << analytic/me2 << '\n'; } } diff --git a/MatrixElement/General/MEff2ss.h b/MatrixElement/General/MEff2ss.h --- a/MatrixElement/General/MEff2ss.h +++ b/MatrixElement/General/MEff2ss.h @@ -1,195 +1,201 @@ // -*- C++ -*- // // MEff2ss.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_MEff2ss_H #define HERWIG_MEff2ss_H // // This is the declaration of the MEff2ss class. // #include "GeneralHardME.h" #include "ThePEG/Helicity/Vertex/AbstractFFSVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractRFSVertex.h" #include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVSSVertex.h" #include "ThePEG/Helicity/Vertex/AbstractSSSVertex.h" #include "ThePEG/Helicity/Vertex/AbstractFFTVertex.h" #include "ThePEG/Helicity/Vertex/AbstractSSTVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractFFSSVertex.h" #include "Herwig/MatrixElement/ProductionMatrixElement.h" namespace Herwig { using namespace ThePEG; using ThePEG::Helicity::SpinorWaveFunction; using ThePEG::Helicity::SpinorBarWaveFunction; using ThePEG::Helicity::ScalarWaveFunction; /** * The MEff2ss class is designed to implement the matrix element for a * fermion-antifermion to scalar-scalar hard process. It inherits from * GeneralHardME and implements the appropriate virtual functions for this * specific spin combination. * - * @see \ref MEff2ssInterfaces "The interfaces" - * defined for MEff2ss. * @see GeneralHardME */ class MEff2ss: public GeneralHardME { public: /** Vector of SpinorWaveFunctions objects */ typedef vector SpinorVector; /** Vector of SpinorBarWaveFunction objects. */ typedef vector SpinorBarVector; public: - /** - * The default constructor. - */ - MEff2ss() : fermion_(0), vector_(0), tensor_(0) {} - /** @name Virtual functions required by the MEBase class. */ //@{ /** * The matrix element for the kinematical configuration * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. * @return the matrix element scaled with sHat() to give a * dimensionless number. */ virtual double me2() const; //@} /** * Construct the vertex information for the spin correlations * @param sub Pointer to the relevent SubProcess */ virtual void constructVertex(tSubProPtr sub); protected: /** * A debugging function to test the value of me2 against an * analytic function. * @param me2 The value of the \f$ |\bar{\mathcal{M}}|^2 \f$ */ virtual void debug(double me2) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const {return new_ptr(*this);} /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const {return new_ptr(*this);} //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MEff2ss & operator=(const MEff2ss &); private: /** * Calculate the matrix element * @param sp A vector of SpinorWaveFunction objects * @param sbar A vector of SpinorBarWaveFunction objects * @param sca1 A ScalarWaveFunction for an outgoing scalar * @param sca2 A ScalarWaveFunction for the other outgoing scalar * @param me2 The spin averaged matrix element * @param first Whether or not first call to decide if colour decomposition etc * should be calculated */ ProductionMatrixElement ff2ssME(const SpinorVector & sp, const SpinorBarVector & sbar, const ScalarWaveFunction & sca1, const ScalarWaveFunction & sca2, double & me2, bool first) const; private: /** * Storage for dynamically cast vertices for a diagram with intermediate + * vector + */ + vector > scalar_; + + /** + * Storage for dynamically cast vertices for a diagram with intermediate * fermion */ vector > fermion_; /** * Storage for dynamically cast vertices for a diagram with intermediate * vector */ - vector > scalar_; + vector > vector_; /** * Storage for dynamically cast vertices for a diagram with intermediate - * vector + * fermion */ - vector > vector_; + vector > RSfermion_; /** * Storage for dynamically cast vertices for a diagram with intermediate * tensor */ vector > tensor_; + + /** + * Storage for dynamically cast 4 point vertices + */ + vector fourPoint_; }; } #endif /* HERWIG_MEff2ss_H */ diff --git a/MatrixElement/General/MEff2sv.cc b/MatrixElement/General/MEff2sv.cc deleted file mode 100644 --- a/MatrixElement/General/MEff2sv.cc +++ /dev/null @@ -1,223 +0,0 @@ -// -*- C++ -*- -// -// MEff2sv.cc is a part of Herwig - A multi-purpose Monte Carlo event generator -// Copyright (C) 2002-2017 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 MEff2sv class. -// - -#include "MEff2sv.h" -#include "ThePEG/Utilities/DescribeClass.h" -#include "ThePEG/Interface/ClassDocumentation.h" -#include "ThePEG/Persistency/PersistentOStream.h" -#include "ThePEG/Persistency/PersistentIStream.h" - -using namespace Herwig; -using ThePEG::Helicity::incoming; -using ThePEG::Helicity::outgoing; - -void MEff2sv::doinit() { - GeneralHardME::doinit(); - scalar_.resize(numberOfDiags()); - vector_.resize(numberOfDiags()); - fermion_.resize(numberOfDiags()); - initializeMatrixElements(PDT::Spin1Half, PDT::Spin1Half, - PDT::Spin0,PDT::Spin1); - for(HPCount i = 0; i < numberOfDiags(); ++i) { - const HPDiagram & current = getProcessInfo()[i]; - if( current.channelType == HPDiagram::sChannel ) { - if( current.intermediate->iSpin() == PDT::Spin0 ) - scalar_[i] = - make_pair(dynamic_ptr_cast(current.vertices.first), - dynamic_ptr_cast(current.vertices.second)); - else if( current.intermediate->iSpin() == PDT::Spin1 ) - vector_[i] = - make_pair(dynamic_ptr_cast(current.vertices.first), - dynamic_ptr_cast(current.vertices.second)); - } - else if( current.channelType == HPDiagram::tChannel ) { - if(current.intermediate->iSpin() == PDT::Spin1Half) { - if( current.ordered.second ) - fermion_[i] = - make_pair(dynamic_ptr_cast(current.vertices.first), - dynamic_ptr_cast(current.vertices.second)); - else - fermion_[i] = - make_pair(dynamic_ptr_cast(current.vertices.second), - dynamic_ptr_cast(current.vertices.first)); - } - } - } -} - -void MEff2sv::persistentOutput(PersistentOStream & os) const { - os << scalar_ << vector_ << fermion_; -} - -void MEff2sv::persistentInput(PersistentIStream & is, int) { - is >> scalar_ >> vector_ >> fermion_; - initializeMatrixElements(PDT::Spin1Half, PDT::Spin1Half, - PDT::Spin0,PDT::Spin1); -} - -// The following static variable is needed for the type -// description system in ThePEG. -DescribeClass -describeHerwigMEff2sv("Herwig::MEff2sv", "Herwig.so"); - -void MEff2sv::Init() { - - static ClassDocumentation documentation - ("MEff2sv implements the ME calculation of the fermion-antifermion " - "to vector-scalar hard process."); - -} - -double MEff2sv::me2() const { - //set up wavefunctions - SpinorVector ina(2); - SpinorBarVector inb(2); - VBVector outa(3); - ScalarWaveFunction sca(rescaledMomenta()[2], mePartonData()[2], Complex(1.), - outgoing); - for(unsigned int ih = 0; ih < 2; ++ih) { - ina[ih] = SpinorWaveFunction(rescaledMomenta()[0], mePartonData()[0], - ih, incoming); - inb[ih] = SpinorBarWaveFunction(rescaledMomenta()[1], mePartonData()[1], - ih, incoming); - outa[2*ih] = VectorWaveFunction(rescaledMomenta()[3], mePartonData()[3], - 2*ih, outgoing); - } - if( mePartonData()[2]->mass() > ZERO ) { - outa[1] = VectorWaveFunction(rescaledMomenta()[3], mePartonData()[3], - 1, outgoing); - } - double full_me(0.); - ffb2svHeME(ina, inb, sca, outa, full_me,true); - return full_me; -} - -ProductionMatrixElement -MEff2sv::ffb2svHeME(SpinorVector & sp, SpinorBarVector & spbar, - ScalarWaveFunction & sca, VBVector & vec, - double & me2, bool first) const { - Energy2 m2(scale()); - bool mv = mePartonData()[2]->mass() == ZERO; - // weights for the selection of the diagram - vector me(numberOfDiags(), 0.); - // weights for the selection of the colour flow - vector flow(numberOfFlows(),0.); - me2 = 0.; - for(unsigned int ihel1 = 0; ihel1 < 2; ++ihel1) { - for(unsigned int ihel2 = 0; ihel2 < 2; ++ihel2) { - for(unsigned int ovhel = 0; ovhel < 3; ++ovhel) { - if( mv && ovhel == 1 ) continue; - vector flows(numberOfFlows(),0.); - for(HPCount ix = 0; ix < numberOfDiags(); ++ix) { - Complex diag(0.); - const HPDiagram & current = getProcessInfo()[ix]; - tcPDPtr offshell(current.intermediate); - if( current.channelType == HPDiagram::sChannel ) { - if( offshell->iSpin() == PDT::Spin0 ) { - ScalarWaveFunction interS = scalar_[ix].first-> - evaluate(m2, 1, offshell, sp[ihel1], spbar[ihel2]); - diag = scalar_[ix].second->evaluate(m2, vec[ovhel], sca, interS); - } - else if( offshell->iSpin() == PDT::Spin1 ) { - VectorWaveFunction interV = vector_[ix].first-> - evaluate(m2, 1, offshell, sp[ihel1], spbar[ihel2]); - diag = vector_[ix].second->evaluate(m2, vec[ovhel], interV, sca); - } - else diag = 0.0; - } - else if( current.channelType == HPDiagram::tChannel ) { - if( offshell->iSpin() == PDT::Spin1Half ) { - if( current.ordered.second ) { - SpinorBarWaveFunction interFB = fermion_[ix].second-> - evaluate(m2, 3, offshell, spbar[ihel2], vec[ovhel]); - diag = fermion_[ix].first-> - evaluate(m2, sp[ihel1], interFB, sca); - } - else { - SpinorBarWaveFunction interFB = fermion_[ix].first-> - evaluate(m2, 3, offshell, spbar[ihel2], sca); - diag = fermion_[ix].second-> - evaluate(m2, sp[ihel1], interFB, vec[ovhel]); - } - } - } - else diag = 0.; - me[ix] += norm(diag); - diagramME()[ix](ihel1, ihel2, 0, ovhel) = diag; - //Compute flows - for(size_t iy = 0; iy < current.colourFlow.size(); ++iy) { - assert(current.colourFlow[iy].firstdataPtr()->mass() == ZERO); - SpinorWaveFunction (sp, hdp[0], incoming, false); - SpinorBarWaveFunction (spbar, hdp[1], incoming, false); - ScalarWaveFunction sca ( hdp[2], outgoing, true); - VectorWaveFunction (vec, hdp[3], outgoing, true, mv); - //Need to use rescale momenta to calculate matrix element - setRescaledMomenta(hdp); - // wavefunctions with rescaled momenta - SpinorWaveFunction spr(rescaledMomenta()[0], - hdp[0]->dataPtr(), incoming); - SpinorBarWaveFunction sbr(rescaledMomenta()[1], - hdp[1]->dataPtr(), incoming); - sca = ScalarWaveFunction (rescaledMomenta()[2], - hdp[2]->dataPtr(), outgoing); - VectorWaveFunction vr(rescaledMomenta()[3], - hdp[3]->dataPtr(), mv, outgoing); - for( unsigned int ihel = 0; ihel < 2; ++ihel ) { - spr.reset(ihel); - sp[ihel] = spr; - sbr.reset(ihel); - spbar[ihel] = sbr; - vr.reset(2*ihel); - vec[2*ihel] = vr; - } - if( !mv ) { - vr.reset(1); - vec[1] = vr; - } - double dummy(0.); - ProductionMatrixElement prodme = ffb2svHeME(sp, spbar, sca, vec, dummy,false); - createVertex(prodme,hdp); -} - - diff --git a/MatrixElement/General/MEff2sv.h b/MatrixElement/General/MEff2sv.h deleted file mode 100644 --- a/MatrixElement/General/MEff2sv.h +++ /dev/null @@ -1,199 +0,0 @@ -// -*- C++ -*- -// -// MEff2sv.h is a part of Herwig - A multi-purpose Monte Carlo event generator -// Copyright (C) 2002-2017 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_MEff2sv_H -#define HERWIG_MEff2sv_H -// -// This is the declaration of the MEff2sv class. -// - -#include "GeneralHardME.h" -#include "ThePEG/Helicity/Vertex/AbstractFFSVertex.h" -#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h" -#include "ThePEG/Helicity/Vertex/AbstractVSSVertex.h" -#include "ThePEG/Helicity/Vertex/AbstractVVSVertex.h" -#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" -#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" -#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" -#include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h" -#include "Herwig/MatrixElement/ProductionMatrixElement.h" - -namespace Herwig { -using namespace ThePEG; -using Helicity::SpinorWaveFunction; -using Helicity::SpinorBarWaveFunction; -using Helicity::VectorWaveFunction; -using Helicity::ScalarWaveFunction; - -/** - * The MEff2sv class is designed to implement the matrix element for a - * fermion-antifermion to vector-scalar hard process. It inherits from - * GeneralHardME and implements the appropriate virtual functions for this - * specific spin combination. - * - * @see \ref MEff2svInterfaces "The interfaces" - * defined for MEff2sv. - * @see GeneralHardME - */ -class MEff2sv: public GeneralHardME { - -public: - - /** @name Typedefs */ - //@{ - /** - * A vector of SpinorWaveFunctions - */ - typedef vector SpinorVector; - - /** - * A vector of SpinorWaveBarFunctions - */ - typedef vector SpinorBarVector; - - /** - * A vector of VectorWaveFunctions - */ - typedef vector VBVector; - //@} - -public: - - /** - * The default constructor. - */ - MEff2sv() : scalar_(0), vector_(0), fermion_(0) {} - - /** @name Virtual functions required by the MEBase class. */ - //@{ - /** - * The matrix element for the kinematical configuration - * previously provided by the last call to setKinematics(), suitably - * scaled by sHat() to give a dimension-less number. - * @return the matrix element scaled with sHat() to give a - * dimensionless number. - */ - virtual double me2() const; - //@} - - /** - * Construct the vertex information for the spin correlations - * @param sub Pointer to the relevent SubProcess - */ - virtual void constructVertex(tSubProPtr sub); - -public: - - /** @name Functions used by the persistent I/O system. */ - //@{ - /** - * Function used to write out object persistently. - * @param os the persistent output stream written to. - */ - void persistentOutput(PersistentOStream & os) const; - - /** - * Function used to read in object persistently. - * @param is the persistent input stream read from. - * @param version the version number of the object when written. - */ - void persistentInput(PersistentIStream & is, int version); - //@} - - /** - * The standard Init function used to initialize the interfaces. - * Called exactly once for each class by the class description system - * before the main function starts or - * when this class is dynamically loaded. - */ - static void Init(); - -protected: - - /** @name Standard Interfaced functions. */ - //@{ - /** - * Initialize this object after the setup phase before saving an - * EventGenerator to disk. - * @throws InitException if object could not be initialized properly. - */ - virtual void doinit(); - //@} - -protected: - - /** @name Clone Methods. */ - //@{ - /** - * Make a simple clone of this object. - * @return a pointer to the new object. - */ - virtual IBPtr clone() const {return new_ptr(*this);} - - /** Make a clone of this object, possibly modifying the cloned object - * to make it sane. - * @return a pointer to the new object. - */ - virtual IBPtr fullclone() const {return new_ptr(*this);} - //@} - -private: - - /** - * The assignment operator is private and must never be called. - * In fact, it should not even be implemented. - */ - MEff2sv & operator=(const MEff2sv &); - -private: - - /** @name Functions to compute the ProductionMatrixElement. */ - //@{ - /** - * Compute the matrix element for \f$\Psi\bar{\Psi}\to\Psi\bar{\Psi}\f$ - * @param sp Spinors for first incoming particle - * @param spbar SpinorBar Wavefunctions for second incoming particle - * @param vec VectorWaveFunctions for outgoing vector - * @param sca Outgoing ScalarWaveFunction - * @param me2 colour averaged, spin summed ME - * @param first Whether or not first call to decide if colour decomposition etc - * should be calculated - * @return ProductionMatrixElement containing results of - * helicity calculations - */ - ProductionMatrixElement - ffb2svHeME(SpinorVector & sp, SpinorBarVector & spbar, - ScalarWaveFunction & sca, VBVector & vec, - double & me2,bool first) const; - //@} - - -private: - - /** - * Storage for dynamically cast vertices for a diagram with intermediate - * scalar - */ - vector > scalar_; - - /** - * Storage for dynamically cast vertices for a diagram with intermediate - * vector - */ - vector > vector_; - - /** - * Storage for dynamically cast vertices for a diagram with intermediate - * fermion - */ - vector > fermion_; -}; - -} - -#endif /* HERWIG_MEff2sv_H */ diff --git a/MatrixElement/General/MEff2tv.cc b/MatrixElement/General/MEff2ts.cc copy from MatrixElement/General/MEff2tv.cc copy to MatrixElement/General/MEff2ts.cc --- a/MatrixElement/General/MEff2tv.cc +++ b/MatrixElement/General/MEff2ts.cc @@ -1,337 +1,223 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member -// functions of the MEff2tv class. +// functions of the MEff2ts class. // -#include "MEff2tv.h" +#include "MEff2ts.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; -IBPtr MEff2tv::clone() const { +IBPtr MEff2ts::clone() const { return new_ptr(*this); } -IBPtr MEff2tv::fullclone() const { +IBPtr MEff2ts::fullclone() const { return new_ptr(*this); } -void MEff2tv::persistentOutput(PersistentOStream & os) const { - os << fermion_ << vector_ << fourPoint_; +void MEff2ts::persistentOutput(PersistentOStream & os) const { + os << fermion_ << scalar_ << fourPoint_; } -void MEff2tv::persistentInput(PersistentIStream & is, int) { - is >> fermion_ >> vector_ >> fourPoint_; +void MEff2ts::persistentInput(PersistentIStream & is, int) { + is >> fermion_ >> scalar_ >> fourPoint_; initializeMatrixElements(PDT::Spin1Half, PDT::Spin1Half, - PDT::Spin2 , PDT::Spin1); + PDT::Spin2 , PDT::Spin0); } // The following static variable is needed for the type // description system in ThePEG. -DescribeClass -describeHerwigMEff2tv("Herwig::MEff2tv", "Herwig.so"); +DescribeClass +describeHerwigMEff2ts("Herwig::MEff2ts", "Herwig.so"); -void MEff2tv::Init() { +void MEff2ts::Init() { - static ClassDocumentation documentation - ("The MEff2tv class implements the general matrix element for " - "fermion-antifermion -> tensor vector"); + static ClassDocumentation documentation + ("The MEff2ts class implements the general matrix element for " + "fermion-antifermion -> tensor scalar"); } -double MEff2tv::me2() const { +double MEff2ts::me2() const { // first setup wavefunctions for external particles SpinorVector sp(2); SpinorBarVector sbar(2); - VBVector vec(3); + ScalarWaveFunction sca(rescaledMomenta()[3], mePartonData()[3],outgoing); TBVector ten(5); bool tMass = meMomenta()[2].mass()!=ZERO; - bool vMass = meMomenta()[3].mass()!=ZERO; for( unsigned int i = 0; i < 5; ++i ) { if(i<2) { sp[i] = SpinorWaveFunction (rescaledMomenta()[0], mePartonData()[0], i, incoming); sbar[i] = SpinorBarWaveFunction(rescaledMomenta()[1], mePartonData()[1], i, incoming); } if( tMass || i==0 || i==4) { ten[i] = TensorWaveFunction(rescaledMomenta()[2], mePartonData()[2],i , outgoing); } - if(i<3 && (i!=1||vMass) ) { - vec[i] = VectorWaveFunction(rescaledMomenta()[3], mePartonData()[3],i , - outgoing); - } } // calculate the ME double full_me(0.); - ffb2tvHeME(sp, sbar, ten, vec, full_me,true); - // debugging tests if needed -#ifndef NDEBUG - if( debugME() ) debug(full_me); -#endif + ffb2tsHeME(sp, sbar, ten, sca, full_me,true); // return the answer return full_me; } -void MEff2tv::doinit() { +void MEff2ts::doinit() { GeneralHardME::doinit(); fermion_ .resize(numberOfDiags()); - vector_ .resize(numberOfDiags()); + scalar_ .resize(numberOfDiags()); fourPoint_ .resize(numberOfDiags()); initializeMatrixElements(PDT::Spin1Half, PDT::Spin1Half, - PDT::Spin2 , PDT::Spin1); + PDT::Spin2 , PDT::Spin0); for(HPCount i = 0; i < numberOfDiags(); ++i) { const HPDiagram & current = getProcessInfo()[i]; if(current.channelType == HPDiagram::tChannel) { if(current.intermediate->iSpin() != PDT::Spin1Half) - throw InitException() << "MEff2tv:doinit() - Cannot find correct " + throw InitException() << "MEff2ts:doinit() - Cannot find correct " << "t-channel from diagram. Vertex not cast! " << Exception::runerror; if( current.ordered.second ) fermion_[i] = make_pair(dynamic_ptr_cast(current.vertices.first), - dynamic_ptr_cast(current.vertices.second)); + dynamic_ptr_cast(current.vertices.second)); else fermion_[i] = make_pair(dynamic_ptr_cast(current.vertices.second), - dynamic_ptr_cast(current.vertices.first)); + dynamic_ptr_cast(current.vertices.first)); } else if(current.channelType == HPDiagram::sChannel) { - if(current.intermediate->iSpin() != PDT::Spin1) - throw InitException() << "MEff2tv:doinit() - Cannot find correct " + if(current.intermediate->iSpin() != PDT::Spin0) + throw InitException() << "MEff2ts:doinit() - Cannot find correct " << "s-channel from diagram. Vertex not cast! " << Exception::runerror; - vector_[i] = - make_pair(dynamic_ptr_cast(current.vertices.first), - dynamic_ptr_cast(current.vertices.second)); + scalar_[i] = + make_pair(dynamic_ptr_cast(current.vertices.first), + dynamic_ptr_cast(current.vertices.second)); } else if(current.channelType == HPDiagram::fourPoint) { fourPoint_[i] = - dynamic_ptr_cast(current.vertices.first); + dynamic_ptr_cast(current.vertices.first); } } } -ProductionMatrixElement MEff2tv:: -ffb2tvHeME(SpinorVector & sp, SpinorBarVector & sb, - TBVector & ten, VBVector & vec, +ProductionMatrixElement MEff2ts:: +ffb2tsHeME(SpinorVector & sp, SpinorBarVector & sb, + TBVector & ten, ScalarWaveFunction & sca, double & me2,bool first) const { // scale const Energy2 q2(scale()); // weights for the selection of the diagram vector me(numberOfDiags(), 0.); // weights for the selection of the colour flow vector flow(numberOfFlows(),0.); bool tMass = meMomenta()[2].mass() != ZERO; - bool vMass = meMomenta()[3].mass() != ZERO; // flow over the helicities and diagrams for(unsigned int if1 = 0; if1 < 2; ++if1) { for(unsigned int if2 = 0; if2 < 2; ++if2) { for(unsigned int it=0; it<5; ++it) { if( (it>0&&it<4) && !tMass ) continue; - for(unsigned int iv=0; iv<3;++iv) { - if(iv==1&&!vMass) continue; - vector flows(numberOfFlows(),0.); - for(HPCount ix = 0; ix < numberOfDiags(); ++ix) { - Complex diag(0.); - const HPDiagram & current = getProcessInfo()[ix]; - tcPDPtr internal(current.intermediate); - if(current.channelType == HPDiagram::tChannel) { - if(current.ordered.second) { - if(internal->CC()) internal = internal->CC(); - SpinorBarWaveFunction interFB = fermion_[ix].second-> - evaluate(q2,5,internal,sb[if2],vec[iv]); - diag = fermion_[ix].first-> - evaluate(q2,sp[if1],interFB,ten[it]); - } - else { - SpinorWaveFunction interF = fermion_[ix].second-> - evaluate(q2,5,internal,sp[if1],vec[iv]); - diag = fermion_[ix].first-> - evaluate(q2,interF,sb[if2],ten[it]); - } + vector flows(numberOfFlows(),0.); + for(HPCount ix = 0; ix < numberOfDiags(); ++ix) { + Complex diag(0.); + const HPDiagram & current = getProcessInfo()[ix]; + tcPDPtr internal(current.intermediate); + if(current.channelType == HPDiagram::tChannel) { + if(current.ordered.second) { + if(internal->CC()) internal = internal->CC(); + SpinorBarWaveFunction interFB = fermion_[ix].second-> + evaluate(q2,5,internal,sb[if2],sca); + diag = fermion_[ix].first-> + evaluate(q2,sp[if1],interFB,ten[it]); } - else if(current.channelType == HPDiagram::sChannel) { - VectorWaveFunction interV = vector_[ix].first-> - evaluate(q2, 1, internal, sp[if1], sb[if2],vec[iv].mass()); - diag = vector_[ix].second->evaluate(q2, interV, vec[iv],ten[it], - vec[iv].mass()); - } - else if(current.channelType == HPDiagram::fourPoint) { - diag = fourPoint_[ix]-> - evaluate(q2,sp[if1],sb[if2],vec[iv],ten[it]); - } - // diagram - me[ix] += norm(diag); - diagramME()[ix](if1,if2,it,iv) = diag; - // contributions to the different colour flows - for(unsigned int iy = 0; iy < current.colourFlow.size(); ++iy) { - assert(current.colourFlow[iy].first + evaluate(q2,5,internal,sp[if1],sca); + diag = fermion_[ix].first-> + evaluate(q2,interF,sb[if2],ten[it]); } } - // MEs for the different colour flows - for(unsigned int iy = 0; iy < numberOfFlows(); ++iy) - flowME()[iy](if1,if2,it,iv) = flows[iy]; - // contribution to the squared matrix element - for(unsigned int ii = 0; ii < numberOfFlows(); ++ii) - for(unsigned int ij = 0; ij < numberOfFlows(); ++ij) - me2 += getColourFactors()[ii][ij]*(flows[ii]*conj(flows[ij])).real(); - // contribution to the colour flow - for(unsigned int ii = 0; ii < numberOfFlows(); ++ii) { - flow[ii] += getColourFactors()[ii][ii]*norm(flows[ii]); + else if(current.channelType == HPDiagram::sChannel) { + ScalarWaveFunction interS = scalar_[ix].first-> + evaluate(q2, 1, internal, sp[if1], sb[if2],sca.mass()); + diag = scalar_[ix].second->evaluate(q2, interS, sca,ten[it]); } + else if(current.channelType == HPDiagram::fourPoint) { + diag = fourPoint_[ix]-> + evaluate(q2,sp[if1],sb[if2],sca,ten[it]); + } + // diagram + me[ix] += norm(diag); + diagramME()[ix](if1,if2,it,0) = diag; + // contributions to the different colour flows + for(unsigned int iy = 0; iy < current.colourFlow.size(); ++iy) { + assert(current.colourFlow[iy].firstlogfile().is_open() ) return; - long id1 = mePartonData()[0]->id(); - long id2 = mePartonData()[1]->id(); - long id4 = mePartonData()[3]->id(); - if(id1==-id2&&id1<=5&&id4==ParticleID::g) { - unsigned int iloc(0); - for(;ilocnorm()); - InvEnergy kappa = abs(vector_[iloc].second->norm())*UnitRemoval::InvE; - Energy2 mg2 = sqr(meMomenta()[2].mass()); - double anal = sqr(gs)*sqr(kappa)/36.*(4.*uHat()*tHat()+sHat()*mg2)* - (sqr(tHat()-mg2)+sqr(uHat()-mg2))/sHat()/tHat()/uHat(); - double diff = abs((anal - me2)/(anal+me2)); - if( diff > 1e-4 ) { - generator()->log() - << mePartonData()[0]->PDGName() << "," - << mePartonData()[1]->PDGName() << "->" - << mePartonData()[2]->PDGName() << "," - << mePartonData()[3]->PDGName() << " difference: " - << setprecision(10) << diff << " ratio: " << anal/me2 - << '\n'; - } - } - else if(id1==-id2&&id1==ParticleID::eminus&&id4==ParticleID::gamma) { - unsigned int iloc(0); - for(;ilocnorm()); - InvEnergy kappa = abs(vector_[iloc].second->norm())*UnitRemoval::InvE; - Energy2 mg2 = sqr(meMomenta()[2].mass()); - double anal = sqr(gs)*sqr(kappa)/16./tHat()/uHat()/sHat()* - (4.*uHat()*tHat()+mg2*sHat())*(sqr(uHat()-mg2)+sqr(tHat()-mg2)); - double diff = abs((anal - me2)/(anal+me2)); - if( diff > 1e-4 ) { - generator()->log() - << mePartonData()[0]->PDGName() << "," - << mePartonData()[1]->PDGName() << "->" - << mePartonData()[2]->PDGName() << "," - << mePartonData()[3]->PDGName() << " difference: " - << setprecision(10) << diff << " ratio: " << anal/me2 - << '\n'; - } - } - else if(id1==-id2&&id1==ParticleID::eminus&&id4==ParticleID::Z0) { - unsigned int iloc(0); - for(;ilocnorm()); - InvEnergy kappa = abs(vector_[iloc].second->norm())*UnitRemoval::InvE; - Energy2 mg2 = sqr(meMomenta()[2].mass()); - Energy2 mz2 = sqr(meMomenta()[3].mass()); - double sw2 = SM().sin2ThetaW(); - double anal = sqr(gs)*sqr(kappa)/48./16./sw2/(1.-sw2)* - 2.*(1.-4.*sw2+8.*sqr(sw2))/sqr(tHat())/sqr(uHat())/sqr(sHat()-mz2)* - (8.*pow<3,1>(mz2)*uHat()*tHat()*(3.*mg2*(mg2-uHat()-tHat())+4.*uHat()*tHat()) - +2.*sqr(mz2)*uHat()*tHat()*(27.*pow<3,1>(mg2)-42.*sqr(mg2)*(uHat()+tHat()) - +15.*mg2*(sqr(uHat())+sqr(tHat())) - +80.*mg2*uHat()*tHat() - -28.*(sqr(uHat())*tHat()+uHat()*sqr(tHat()))) - +mz2*(3.*pow<4,1>(mg2)*(-sqr(uHat())-sqr(tHat())+12.*uHat()*tHat()) - +6.*pow<3,1>(mg2)*(pow<3,1>(uHat()) - -12.*(sqr(uHat())*tHat()+uHat()*sqr(tHat())) - +pow<3,1>(tHat())) - +3.*sqr(mg2)*(-pow<4,1>(uHat())+14.*pow<3,1>(uHat())*tHat() - +62.*sqr(uHat()*tHat())+14.*uHat()*pow<3,1>(tHat()) - -pow<4,1>(tHat())) - +6.*mg2*(-pow<4,1>(uHat())*tHat() - -23.*(pow<3,1>(uHat())*sqr(tHat())+pow<3,1>(tHat())*sqr(uHat())) - -uHat()*pow<4,1>(tHat())) - +36.*(pow<4,1>(uHat())*sqr(tHat())+pow<4,1>(tHat())*sqr(uHat())) - +52.*pow<3,1>(tHat()*uHat())) - +3.*tHat()*uHat()*(-mg2+uHat()+tHat())* - (-sqr(mg2)+mg2*(uHat()+tHat())-4.*uHat()*tHat())* - (2.*sqr(mg2)-2.*mg2*(uHat()+tHat())+sqr(uHat())+sqr(tHat()))); - double diff = abs((anal - me2)/(anal+me2)); - if( diff > 1e-4 ) { - generator()->log() - << mePartonData()[0]->PDGName() << "," - << mePartonData()[1]->PDGName() << "->" - << mePartonData()[2]->PDGName() << "," - << mePartonData()[3]->PDGName() << " difference: " - << setprecision(10) << diff - << " anal : " << anal - << " code : " << me2 - << " ratio: " << anal/me2 - << '\n'; - } - } -} - -void MEff2tv::constructVertex(tSubProPtr sub) { +void MEff2ts::constructVertex(tSubProPtr sub) { ParticleVector ext = hardParticles(sub); vector sp; SpinorWaveFunction(sp, ext[0], incoming, false); vector sbar; SpinorBarWaveFunction(sbar, ext[1], incoming, false); - vector v2; vector t1; bool mc = !(ext[2]->momentum().mass() > ZERO); - bool md = !(ext[3]->data() .mass() > ZERO); TensorWaveFunction(t1, ext[2], outgoing, true, mc); - VectorWaveFunction(v2, ext[3], outgoing, true, md); + ScalarWaveFunction sca(ext[3], outgoing, true); // Need to use rescale momenta to calculate matrix element setRescaledMomenta(ext); SpinorWaveFunction spr (rescaledMomenta()[0], ext[0]->dataPtr(), incoming); SpinorBarWaveFunction sbr(rescaledMomenta()[1], ext[1]->dataPtr(), incoming); TensorWaveFunction tr1 (rescaledMomenta()[2], ext[2]->dataPtr(), outgoing); - VectorWaveFunction vr2 (rescaledMomenta()[3], - ext[3]->dataPtr(), outgoing); + sca = ScalarWaveFunction(rescaledMomenta()[3], + ext[3]->dataPtr(), outgoing); for( unsigned int ihel = 0; ihel < 2; ++ihel ) { spr.reset(ihel); sp[ihel] = spr; sbr.reset(ihel); sbar[ihel] = sbr; tr1.reset(4*ihel); t1[4*ihel] = tr1; - vr2.reset(2*ihel); - v2[2*ihel] = vr2; } if( !mc ) { for(unsigned int ihel=1;ihel<4;++ihel) { tr1.reset(ihel); t1[ihel] = tr1; } } - if( !md ) { - vr2.reset(1); - v2[1] = vr2; - } double dummy(0.); - ProductionMatrixElement pme = ffb2tvHeME(sp, sbar, t1, v2,dummy,false); + ProductionMatrixElement pme = ffb2tsHeME(sp, sbar, t1, sca,dummy,false); createVertex(pme,ext); } diff --git a/MatrixElement/General/MEff2ts.h b/MatrixElement/General/MEff2ts.h new file mode 100644 --- /dev/null +++ b/MatrixElement/General/MEff2ts.h @@ -0,0 +1,180 @@ +// -*- C++ -*- +#ifndef HERWIG_MEff2ts_H +#define HERWIG_MEff2ts_H +// +// This is the declaration of the MEff2ts class. +// + +#include "GeneralHardME.h" +#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" +#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" +#include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h" +#include "ThePEG/Helicity/WaveFunction/TensorWaveFunction.h" +#include "ThePEG/Helicity/Vertex/AbstractFFTVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractSSTVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractFFSVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractFFSTVertex.h" + +namespace Herwig { + +using namespace ThePEG; +using Helicity::SpinorWaveFunction; +using Helicity::SpinorBarWaveFunction; +using Helicity::ScalarWaveFunction; +using Helicity::TensorWaveFunction; + +/** + * The MEff2ts class implements the general matrix element for fermion fermion -> tensor scalar + * + */ +class MEff2ts: public GeneralHardME { + +public: + + /** @name Typedefs */ + //@{ + /** + * A vector of SpinorWaveFunctions + */ + typedef vector SpinorVector; + + /** + * A vector of SpinorWaveBarFunctions + */ + typedef vector SpinorBarVector; + + /** + * A vector of VectorWaveFunctions + */ + typedef vector TBVector; + //@} + +public: + + /** + * The default constructor. + */ + MEff2ts() : fermion_(0), scalar_(0), fourPoint_(0) {} + + /** + * The matrix element for the kinematical configuration + * previously provided by the last call to setKinematics(), suitably + * scaled by sHat() to give a dimension-less number. + * @return the matrix element scaled with sHat() to give a + * dimensionless number. + */ + virtual double me2() const; + + /** + * Construct the vertex information for the spin correlations + * @param sub Pointer to the relevent SubProcess + */ + virtual void constructVertex(tSubProPtr sub); + +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. + */ + void doinit(); + //@} + +private: + + /** + * The assignment operator is private and must never be called. + * In fact, it should not even be implemented. + */ + MEff2ts & operator=(const MEff2ts &); + +private: + + /** @name Functions to compute the ProductionMatrixElement. */ + //@{ + /** + * Compute the matrix element for \f$\Psi\bar{\Psi}\to\Psi\bar{\Psi}\f$ + * @param sp Spinors for first incoming particle + * @param spbar SpinorBar Wavefunctions for second incoming particle + * @param sca ScalarWaveFunction for outgoing scalar + * @param ten Outgoing TensorWaveFunction + * @param me2 colour averaged, spin summed ME + * @param first Whether or not first call to decide if colour decomposition etc + * should be calculated + * @return ProductionMatrixElement containing results of + * helicity calculations + */ + ProductionMatrixElement + ffb2tsHeME(SpinorVector & sp, SpinorBarVector & spbar, + TBVector & ten, ScalarWaveFunction & sca, + double & me2,bool first) const; + //@} + +private: + + /** + * Store a pair of FFTVertex and FFVVertex pointers + */ + vector > fermion_; + + /** + * Store a pair of FFTVertex and VVTVertex pointers + */ + vector > scalar_; + + /** + * The four point vertex + */ + vector fourPoint_; + +}; + +} + +#endif /* HERWIG_MEff2ts_H */ diff --git a/MatrixElement/General/MEff2tv.h b/MatrixElement/General/MEff2tv.h --- a/MatrixElement/General/MEff2tv.h +++ b/MatrixElement/General/MEff2tv.h @@ -1,194 +1,193 @@ // -*- C++ -*- #ifndef HERWIG_MEff2tv_H #define HERWIG_MEff2tv_H // // This is the declaration of the MEff2tv class. // #include "GeneralHardME.h" #include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/TensorWaveFunction.h" #include "ThePEG/Helicity/Vertex/AbstractFFTVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVVTVertex.h" #include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h" #include "ThePEG/Helicity/Vertex/AbstractFFVTVertex.h" namespace Herwig { using namespace ThePEG; using Helicity::SpinorWaveFunction; using Helicity::SpinorBarWaveFunction; using Helicity::VectorWaveFunction; using Helicity::TensorWaveFunction; /** - * Here is the documentation of the MEff2tv class. + * The documentation of the MEff2tv class implements the general matrix element for + * vector vectro to tensor vector * - * @see \ref MEff2tvInterfaces "The interfaces" - * defined for MEff2tv. */ class MEff2tv: public GeneralHardME { public: /** @name Typedefs */ //@{ /** * A vector of SpinorWaveFunctions */ typedef vector SpinorVector; /** * A vector of SpinorWaveBarFunctions */ typedef vector SpinorBarVector; /** * A vector of VectorWaveFunctions */ typedef vector VBVector; /** * A vector of VectorWaveFunctions */ typedef vector TBVector; //@} public: /** * The default constructor. */ MEff2tv() : fermion_(0), vector_(0), fourPoint_(0) {} /** * The matrix element for the kinematical configuration * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. * @return the matrix element scaled with sHat() to give a * dimensionless number. */ virtual double me2() const; /** * Construct the vertex information for the spin correlations * @param sub Pointer to the relevent SubProcess */ virtual void constructVertex(tSubProPtr sub); 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. */ void doinit(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MEff2tv & operator=(const MEff2tv &); private: /** @name Functions to compute the ProductionMatrixElement. */ //@{ /** * Compute the matrix element for \f$\Psi\bar{\Psi}\to\Psi\bar{\Psi}\f$ * @param sp Spinors for first incoming particle * @param spbar SpinorBar Wavefunctions for second incoming particle * @param vec VectorWaveFunctions for outgoing vector * @param ten Outgoing TensorWaveFunction * @param me2 colour averaged, spin summed ME * @param first Whether or not first call to decide if colour decomposition etc * should be calculated * @return ProductionMatrixElement containing results of * helicity calculations */ ProductionMatrixElement ffb2tvHeME(SpinorVector & sp, SpinorBarVector & spbar, TBVector & ten, VBVector & vec, double & me2,bool first) const; //@} /** * A debugging function to test the value of me2 against an * analytic function. * @param me2 The value of the \f$ |\bar{\mathcal{M}}|^2 \f$ */ virtual void debug(double me2) const; private: /** * Store a pair of FFTVertex and FFVVertex pointers */ vector > fermion_; /** * Store a pair of FFTVertex and VVTVertex pointers */ vector > vector_; /** * The four point vertex */ vector fourPoint_; }; } #endif /* HERWIG_MEff2tv_H */ diff --git a/MatrixElement/General/MEff2vs.cc b/MatrixElement/General/MEff2vs.cc --- a/MatrixElement/General/MEff2vs.cc +++ b/MatrixElement/General/MEff2vs.cc @@ -1,222 +1,231 @@ // -*- C++ -*- // // MEff2vs.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 MEff2vs class. // #include "MEff2vs.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; using ThePEG::Helicity::incoming; using ThePEG::Helicity::outgoing; void MEff2vs::doinit() { GeneralHardME::doinit(); scalar_.resize(numberOfDiags()); vector_.resize(numberOfDiags()); fermion_.resize(numberOfDiags()); + four_.resize(numberOfDiags()); initializeMatrixElements(PDT::Spin1Half, PDT::Spin1Half, PDT::Spin1,PDT::Spin0); for(HPCount i = 0; i < numberOfDiags(); ++i) { const HPDiagram & current = getProcessInfo()[i]; if( current.channelType == HPDiagram::sChannel ) { if( current.intermediate->iSpin() == PDT::Spin0 ) scalar_[i] = make_pair(dynamic_ptr_cast(current.vertices.first), dynamic_ptr_cast(current.vertices.second)); else if( current.intermediate->iSpin() == PDT::Spin1 ) vector_[i] = make_pair(dynamic_ptr_cast(current.vertices.first), dynamic_ptr_cast(current.vertices.second)); } else if( current.channelType == HPDiagram::tChannel ) { if(current.intermediate->iSpin() == PDT::Spin1Half) { if( current.ordered.second ) fermion_[i] = make_pair(dynamic_ptr_cast(current.vertices.first), dynamic_ptr_cast(current.vertices.second)); else fermion_[i] = make_pair(dynamic_ptr_cast(current.vertices.second), dynamic_ptr_cast(current.vertices.first)); } } + else if( current.channelType == HPDiagram::fourPoint) { + four_[i] = dynamic_ptr_cast(current.vertices.first); + } } } void MEff2vs::persistentOutput(PersistentOStream & os) const { - os << scalar_ << vector_ << fermion_; + os << scalar_ << vector_ << fermion_ << four_; } void MEff2vs::persistentInput(PersistentIStream & is, int) { - is >> scalar_ >> vector_ >> fermion_; + is >> scalar_ >> vector_ >> fermion_ >> four_; initializeMatrixElements(PDT::Spin1Half, PDT::Spin1Half, PDT::Spin1,PDT::Spin0); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigMEff2vs("Herwig::MEff2vs", "Herwig.so"); void MEff2vs::Init() { static ClassDocumentation documentation ("MEff2vs implements the ME calculation of the fermion-antifermion " "to vector-scalar hard process."); } double MEff2vs::me2() const { //set up wavefunctions SpinorVector ina(2); SpinorBarVector inb(2); VBVector outa(3); + ScalarWaveFunction sca(rescaledMomenta()[3], mePartonData()[3], Complex(1.), outgoing); for(unsigned int ih = 0; ih < 2; ++ih) { ina[ih] = SpinorWaveFunction(rescaledMomenta()[0], mePartonData()[0], ih, incoming); inb[ih] = SpinorBarWaveFunction(rescaledMomenta()[1], mePartonData()[1], ih, incoming); outa[2*ih] = VectorWaveFunction(rescaledMomenta()[2], mePartonData()[2], 2*ih, outgoing); } if( mePartonData()[2]->mass() > ZERO ) { outa[1] = VectorWaveFunction(rescaledMomenta()[2], mePartonData()[2], 1, outgoing); } double full_me(0.); ffb2vsHeME(ina, inb, outa, sca, full_me,true); return full_me; } ProductionMatrixElement MEff2vs::ffb2vsHeME(SpinorVector & sp, SpinorBarVector & spbar, VBVector & vec, ScalarWaveFunction & sca, double & me2, bool first) const { Energy2 m2(scale()); bool mv = mePartonData()[2]->mass() == ZERO; // weights for the selection of the diagram vector me(numberOfDiags(), 0.); // weights for the selection of the colour flow vector flow(numberOfFlows(),0.); me2 = 0.; for(unsigned int ihel1 = 0; ihel1 < 2; ++ihel1) { for(unsigned int ihel2 = 0; ihel2 < 2; ++ihel2) { for(unsigned int ovhel = 0; ovhel < 3; ++ovhel) { if( mv && ovhel == 1 ) continue; vector flows(numberOfFlows(),0.); for(HPCount ix = 0; ix < numberOfDiags(); ++ix) { Complex diag(0.); const HPDiagram & current = getProcessInfo()[ix]; tcPDPtr offshell(current.intermediate); if( current.channelType == HPDiagram::sChannel ) { if( offshell->iSpin() == PDT::Spin0 ) { ScalarWaveFunction interS = scalar_[ix].first-> evaluate(m2, 1, offshell, sp[ihel1], spbar[ihel2]); - diag = scalar_[ix].second->evaluate(m2, vec[ovhel], sca, interS); + diag = scalar_[ix].second->evaluate(m2, vec[ovhel], sca, interS); } else if( offshell->iSpin() == PDT::Spin1 ) { VectorWaveFunction interV = vector_[ix].first-> evaluate(m2, 1, offshell, sp[ihel1], spbar[ihel2]); diag = vector_[ix].second->evaluate(m2, vec[ovhel], interV, sca); } else diag = 0.0; } else if( current.channelType == HPDiagram::tChannel ) { if( offshell->iSpin() == PDT::Spin1Half ) { if( current.ordered.second ) { if(offshell->CC()) offshell = offshell->CC(); SpinorBarWaveFunction interFB = fermion_[ix].second-> evaluate(m2, 3, offshell, spbar[ihel2], sca); diag = fermion_[ix].first-> evaluate(m2, sp[ihel1], interFB, vec[ovhel]); } else { if(offshell->CC()) offshell = offshell->CC(); SpinorBarWaveFunction interFB = fermion_[ix].first-> evaluate(m2, 3, offshell, spbar[ihel2], vec[ovhel]); diag = fermion_[ix].second-> evaluate(m2, sp[ihel1], interFB, sca); } } } - else diag = 0.0; + else if( current.channelType == HPDiagram::fourPoint) { + diag = four_[ix]->evaluate(m2,sp[ihel1], spbar[ihel2], vec[ovhel], sca); + } + else + assert(false); me[ix] += norm(diag); diagramME()[ix](ihel1, ihel2, ovhel, 0) = diag; //Compute flows for(size_t iy = 0; iy < current.colourFlow.size(); ++iy) { assert(current.colourFlow[iy].firstdataPtr()->mass() == ZERO); SpinorWaveFunction (sp, hdp[0], incoming, false); SpinorBarWaveFunction (spbar, hdp[1], incoming, false); VectorWaveFunction (vec, hdp[2], outgoing, true, mv); ScalarWaveFunction sca( hdp[3], outgoing, true); //Need to use rescale momenta to calculate matrix element setRescaledMomenta(hdp); // wavefunctions with rescaled momenta SpinorWaveFunction spr( rescaledMomenta()[0], hdp[0]->dataPtr(), incoming); SpinorBarWaveFunction sbr(rescaledMomenta()[1], hdp[1]->dataPtr(), incoming); VectorWaveFunction vr( rescaledMomenta()[2], hdp[2]->dataPtr(), outgoing); sca = ScalarWaveFunction( rescaledMomenta()[3], hdp[3]->dataPtr(), outgoing); for( unsigned int ihel = 0; ihel < 2; ++ihel ) { spr.reset(ihel); sp[ihel] = spr; sbr.reset(ihel); spbar[ihel] = sbr; vr.reset(2*ihel); vec[2*ihel] = vr; } if( !mv ) { vr.reset(1); vec[1] = vr; } double dummy(0.); ProductionMatrixElement prodme = ffb2vsHeME(sp, spbar, vec, sca, dummy,false); createVertex(prodme,hdp); } diff --git a/MatrixElement/General/MEff2vs.h b/MatrixElement/General/MEff2vs.h --- a/MatrixElement/General/MEff2vs.h +++ b/MatrixElement/General/MEff2vs.h @@ -1,199 +1,205 @@ // -*- C++ -*- // // MEff2vs.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_MEff2vs_H #define HERWIG_MEff2vs_H // // This is the declaration of the MEff2vs class. // #include "GeneralHardME.h" #include "ThePEG/Helicity/Vertex/AbstractFFSVertex.h" #include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVSSVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVVSVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractFFVSVertex.h" #include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h" #include "Herwig/MatrixElement/ProductionMatrixElement.h" namespace Herwig { using namespace ThePEG; using Helicity::SpinorWaveFunction; using Helicity::SpinorBarWaveFunction; using Helicity::VectorWaveFunction; using Helicity::ScalarWaveFunction; /** * The MEff2vs class is designed to implement the matrix element for a * fermion-antifermion to vector-scalar hard process. It inherits from * GeneralHardME and implements the appropriate virtual functions for this * specific spin combination. * * @see \ref MEff2vsInterfaces "The interfaces" * defined for MEff2vs. * @see GeneralHardME */ class MEff2vs: public GeneralHardME { public: /** @name Typedefs */ //@{ /** * A vector of SpinorWaveFunctions */ typedef vector SpinorVector; /** * A vector of SpinorWaveBarFunctions */ typedef vector SpinorBarVector; /** * A vector of VectorWaveFunctions */ typedef vector VBVector; //@} public: /** * The default constructor. */ MEff2vs() : scalar_(0), vector_(0), fermion_(0) {} /** @name Virtual functions required by the MEBase class. */ //@{ /** * The matrix element for the kinematical configuration * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. * @return the matrix element scaled with sHat() to give a * dimensionless number. */ virtual double me2() const; //@} /** * Construct the vertex information for the spin correlations * @param sub Pointer to the relevent SubProcess */ virtual void constructVertex(tSubProPtr sub); public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const {return new_ptr(*this);} /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const {return new_ptr(*this);} //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MEff2vs & operator=(const MEff2vs &); private: /** @name Functions to compute the ProductionMatrixElement. */ //@{ /** * Compute the matrix element for \f$\Psi\bar{\Psi}\to\Psi\bar{\Psi}\f$ * @param sp Spinors for first incoming particle * @param spbar SpinorBar Wavefunctions for second incoming particle * @param vec VectorWaveFunctions for outgoing vector * @param sca Outgoing ScalarWaveFunction * @param me2 colour averaged, spin summed ME * @param first Whether or not first call to decide if colour decomposition etc * should be calculated * @return ProductionMatrixElement containing results of * helicity calculations */ ProductionMatrixElement ffb2vsHeME(SpinorVector & sp, SpinorBarVector & spbar, VBVector & vec, ScalarWaveFunction & sca, double & me2,bool first) const; //@} private: /** * Storage for dynamically cast vertices for a diagram with intermediate * scalar */ vector > scalar_; /** * Storage for dynamically cast vertices for a diagram with intermediate * vector */ vector > vector_; /** * Storage for dynamically cast vertices for a diagram with intermediate * fermion */ vector > fermion_; + + /** + * Four point vertices + */ + vector four_; }; } #endif /* HERWIG_MEff2vs_H */ diff --git a/MatrixElement/General/MEfv2fs.cc b/MatrixElement/General/MEfv2fs.cc --- a/MatrixElement/General/MEfv2fs.cc +++ b/MatrixElement/General/MEfv2fs.cc @@ -1,388 +1,451 @@ // -*- C++ -*- // // MEfv2fs.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 MEfv2fs class. // #include "MEfv2fs.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; using ThePEG::Helicity::incoming; using ThePEG::Helicity::outgoing; void MEfv2fs::doinit() { GeneralHardME::doinit(); scalar_.resize(numberOfDiags()); fermion_.resize(numberOfDiags()); vector_.resize(numberOfDiags()); + four_.resize(numberOfDiags()); + RSfermion_.resize(numberOfDiags()); initializeMatrixElements(PDT::Spin1Half, PDT::Spin1, PDT::Spin1Half, PDT::Spin0); for(size_t ix = 0; ix < numberOfDiags(); ++ix) { HPDiagram curr = getProcessInfo()[ix]; if(curr.channelType == HPDiagram::tChannel) { AbstractFFSVertexPtr ffs = dynamic_ptr_cast(curr.vertices.first); if( curr.intermediate->iSpin() == PDT::Spin0 ) { AbstractVSSVertexPtr vss = dynamic_ptr_cast(curr.vertices.second); scalar_[ix] = make_pair(ffs, vss); } else if ( curr.intermediate->iSpin() == PDT::Spin1Half ) { AbstractFFVVertexPtr ffv = dynamic_ptr_cast(curr.vertices.second); fermion_[ix] = make_pair(ffs, ffv); } else if ( curr.intermediate->iSpin() == PDT::Spin1 ) { AbstractFFVVertexPtr ffv = dynamic_ptr_cast(curr.vertices.first); AbstractVVSVertexPtr vvs = dynamic_ptr_cast(curr.vertices.second); vector_[ix] = make_pair(ffv, vvs); } + else if ( curr.intermediate->iSpin() == PDT::Spin3Half ) { + AbstractRFSVertexPtr rfs = + dynamic_ptr_cast(curr.vertices.first); + AbstractRFVVertexPtr rfv = + dynamic_ptr_cast(curr.vertices.second); + RSfermion_[ix] = make_pair(rfs, rfv); + } else assert(false); } - else { - assert(curr.intermediate->iSpin() == PDT::Spin1Half ); - AbstractFFVVertexPtr ffv = - dynamic_ptr_cast(curr.vertices.first); - AbstractFFSVertexPtr ffs = - dynamic_ptr_cast(curr.vertices.second); - fermion_[ix] = make_pair(ffs, ffv); + else if(curr.channelType == HPDiagram::sChannel) { + if(curr.intermediate->iSpin() == PDT::Spin1Half ) { + AbstractFFVVertexPtr ffv = + dynamic_ptr_cast(curr.vertices.first); + AbstractFFSVertexPtr ffs = + dynamic_ptr_cast(curr.vertices.second); + fermion_[ix] = make_pair(ffs, ffv); + } + else { + AbstractRFVVertexPtr rfv = + dynamic_ptr_cast(curr.vertices.first); + AbstractRFSVertexPtr rfs = + dynamic_ptr_cast(curr.vertices.second); + RSfermion_[ix] = make_pair(rfs, rfv); + } } + else if(curr.channelType == HPDiagram::fourPoint) { + four_[ix] = dynamic_ptr_cast(curr.vertices.first); + } + else + assert(false); } } double MEfv2fs::me2() const { //massless vector VecWFVector vecIn(2); ScalarWaveFunction scaOut(rescaledMomenta()[3], mePartonData()[3], Complex(1.,0.), outgoing); double fullme(0.); if( mePartonData()[0]->id() > 0 ) { SpinorVector spIn(2); SpinorBarVector spbOut(2); for(size_t ih = 0; ih < 2; ++ih) { spIn[ih] = SpinorWaveFunction(rescaledMomenta()[0], mePartonData()[0], ih, incoming); spbOut[ih] = SpinorBarWaveFunction(rescaledMomenta()[2], mePartonData()[2], ih, outgoing); vecIn[ih] = VectorWaveFunction(rescaledMomenta()[1], mePartonData()[1], 2*ih, incoming); } fv2fbsHeME(spIn, vecIn, spbOut, scaOut, fullme,true); } else { SpinorBarVector spbIn(2); SpinorVector spOut(2); for(size_t ih = 0; ih < 2; ++ih) { spbIn[ih] = SpinorBarWaveFunction(rescaledMomenta()[0], mePartonData()[0], ih, incoming); spOut[ih] = SpinorWaveFunction(rescaledMomenta()[2], mePartonData()[2], ih, outgoing); vecIn[ih] = VectorWaveFunction(rescaledMomenta()[1], mePartonData()[1], 2*ih, incoming); } fbv2fsHeME(spbIn, vecIn, spOut, scaOut, fullme,true); } #ifndef NDEBUG if( debugME() ) debug(fullme); #endif return fullme; } ProductionMatrixElement MEfv2fs::fv2fbsHeME(const SpinorVector & spIn, const VecWFVector & vecIn, const SpinorBarVector & spbOut, const ScalarWaveFunction & scaOut, double & me2, bool first) const { const Energy2 q2(scale()); // weights for the selection of the diagram vector me(numberOfDiags(), 0.); // weights for the selection of the colour flow vector flow(numberOfFlows(),0.); me2 = 0.; for(unsigned int ihel1 = 0; ihel1 < 2; ++ihel1) { for(unsigned int ihel2 = 0; ihel2 < 2; ++ihel2) { for(unsigned int ohel1 = 0; ohel1 < 2; ++ohel1) { vector flows(numberOfFlows(),0.); for(size_t ix = 0; ix < numberOfDiags(); ++ix) { Complex diag(0.); const HPDiagram & current = getProcessInfo()[ix]; tcPDPtr offshell = current.intermediate; if( current.channelType == HPDiagram::tChannel ) { if( offshell->iSpin() == PDT::Spin0 ) { ScalarWaveFunction interS = scalar_[ix].first-> evaluate(q2, 3, offshell, spIn[ihel1], spbOut[ohel1]); diag = scalar_[ix].second-> evaluate(q2, vecIn[ihel2], scaOut, interS); } else if( offshell->iSpin() == PDT::Spin1Half ) { if(offshell->CC()) offshell = offshell->CC(); SpinorBarWaveFunction interFB = fermion_[ix].second-> evaluate(q2, 3, offshell,spbOut[ohel1],vecIn[ihel2]); diag = fermion_[ix].first-> evaluate(q2, spIn[ihel1], interFB, scaOut); } - else { + else if( offshell->iSpin() == PDT::Spin1 ) { VectorWaveFunction interV = vector_[ix].first-> evaluate(q2,3,offshell,spIn[ihel1],spbOut[ohel1]); diag = vector_[ix].second-> evaluate(q2, vecIn[ihel2], interV, scaOut); } + else if( offshell->iSpin() == PDT::Spin3Half ) { + if(offshell->CC()) offshell = offshell->CC(); + RSSpinorBarWaveFunction interFB = RSfermion_[ix].second-> + evaluate(q2, 3, offshell,spbOut[ohel1],vecIn[ihel2]); + diag = RSfermion_[ix].first-> + evaluate(q2, spIn[ihel1], interFB, scaOut); + } } else if( current.channelType == HPDiagram::sChannel ) { - // check if take intermediate massless - unsigned int propOpt = - abs(offshell->id()) != abs(spIn[ihel1].particle()->id()) ? 1 : 5; - SpinorWaveFunction interF = fermion_[ix].second-> - evaluate(q2, propOpt, offshell, spIn[ihel1], vecIn[ihel2]); - diag = fermion_[ix].first-> - evaluate(q2, interF, spbOut[ohel1], scaOut); + if( offshell->iSpin() == PDT::Spin1Half ) { + // check if take intermediate massless + unsigned int propOpt = + abs(offshell->id()) != abs(spIn[ihel1].particle()->id()) ? 1 : 5; + SpinorWaveFunction interF = fermion_[ix].second-> + evaluate(q2, propOpt, offshell, spIn[ihel1], vecIn[ihel2]); + diag = fermion_[ix].first-> + evaluate(q2, interF, spbOut[ohel1], scaOut); + } + else if( offshell->iSpin() == PDT::Spin3Half ) { + RSSpinorWaveFunction interF = RSfermion_[ix].second-> + evaluate(q2, 1, offshell, spIn[ihel1], vecIn[ihel2]); + diag = RSfermion_[ix].first-> + evaluate(q2, interF, spbOut[ohel1], scaOut); + } + else + assert(false); + } + else if( current.channelType == HPDiagram::fourPoint) { + diag = four_[ix]-> evaluate(q2, spIn[ihel1], spbOut[ohel1], + vecIn[ihel2], scaOut); } else assert(false); me[ix] += norm(diag); diagramME()[ix](ihel1, 2*ihel2, ohel1, 0) = diag; //Compute flows for(size_t iy = 0; iy < current.colourFlow.size(); ++iy) { assert(current.colourFlow[iy].first me(numberOfDiags(), 0.); // weights for the selection of the colour flow vector flow(numberOfFlows(),0.); me2 = 0.; for(unsigned int ihel1 = 0; ihel1 < 2; ++ihel1) { for(unsigned int ihel2 = 0; ihel2 < 2; ++ihel2) { for(unsigned int ohel1 = 0; ohel1 < 2; ++ohel1) { vector flows(numberOfFlows(),0.); for(HPCount ix = 0; ix < numberOfDiags(); ++ix) { Complex diag(0.); const HPDiagram & current = getProcessInfo()[ix]; tcPDPtr offshell = current.intermediate; if( current.channelType == HPDiagram::tChannel ) { if( offshell->iSpin() == PDT::Spin0 ) { ScalarWaveFunction interS = scalar_[ix].first-> evaluate(q2, 3, offshell, spOut[ohel1], spbIn[ihel1]); diag = scalar_[ix].second-> evaluate(q2, vecIn[ihel2], interS, scaOut); } else if( offshell->iSpin() == PDT::Spin1Half ) { SpinorBarWaveFunction interFB = fermion_[ix].first-> evaluate(q2, 3, offshell, spbIn[ihel1], scaOut); diag = fermion_[ix].second-> evaluate(q2, spOut[ohel1], interFB, vecIn[ihel2]); } else if( offshell->iSpin() == PDT::Spin1 ) { VectorWaveFunction interV = vector_[ix].first-> evaluate(q2,3,offshell, spOut[ohel1], spbIn[ihel1]); diag = vector_[ix].second-> evaluate(q2, vecIn[ihel2], interV, scaOut); } + else if( offshell->iSpin() == PDT::Spin3Half ) { + RSSpinorBarWaveFunction interFB = RSfermion_[ix].first-> + evaluate(q2, 3, offshell, spbIn[ihel1], scaOut); + diag = RSfermion_[ix].second-> + evaluate(q2, spOut[ohel1], interFB, vecIn[ihel2]); + } else assert(false); } else if( current.channelType == HPDiagram::sChannel ) { - // check if take intermediate massless - unsigned int propOpt = - abs(offshell->id()) != abs(spbIn[ihel1].particle()->id()) ? 1 : 5; - SpinorBarWaveFunction interFB = fermion_[ix].second-> - evaluate(q2, propOpt, offshell, spbIn[ihel1], vecIn[ihel2]); - diag = fermion_[ix].first-> - evaluate(q2, spOut[ohel1], interFB, scaOut); + if( offshell->iSpin() == PDT::Spin1Half ) { + // check if take intermediate massless + unsigned int propOpt = + abs(offshell->id()) != abs(spbIn[ihel1].particle()->id()) ? 1 : 5; + SpinorBarWaveFunction interFB = fermion_[ix].second-> + evaluate(q2, propOpt, offshell, spbIn[ihel1], vecIn[ihel2]); + diag = fermion_[ix].first-> + evaluate(q2, spOut[ohel1], interFB, scaOut); + } + else if( offshell->iSpin() == PDT::Spin3Half ) { + RSSpinorBarWaveFunction interFB = RSfermion_[ix].second-> + evaluate(q2, 1, offshell, spbIn[ihel1], vecIn[ihel2]); + diag = RSfermion_[ix].first-> + evaluate(q2, spOut[ohel1], interFB, scaOut); + } + else + assert(false); + } + else if( current.channelType == HPDiagram::fourPoint) { + diag = four_[ix]-> evaluate(q2, spOut[ohel1], spbIn[ihel1], + vecIn[ihel2], scaOut); } else assert(false); me[ix] += norm(diag); diagramME()[ix](ihel1, 2*ihel2, ohel1, 0) = diag; //Compute flows for(size_t iy = 0; iy < current.colourFlow.size(); ++iy) { assert(current.colourFlow[iy].first> scalar_ >> fermion_ >> vector_; + is >> scalar_ >> fermion_ >> vector_ >> four_ >> RSfermion_; initializeMatrixElements(PDT::Spin1Half, PDT::Spin1, PDT::Spin1Half, PDT::Spin0); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigMEfv2fs("Herwig::MEfv2fs", "Herwig.so"); void MEfv2fs::Init() { static ClassDocumentation documentation ("This class implements the matrix element for a fermion-vector to " "a fermioin-scalar."); } void MEfv2fs::constructVertex(tSubProPtr subp) { ParticleVector external = hardParticles(subp); //calculate production ME VecWFVector vecIn; VectorWaveFunction(vecIn, external[1], incoming, false, true); ScalarWaveFunction scaOut(external[3], outgoing, true); //Need to use rescale momenta to calculate matrix element setRescaledMomenta(external); double dummy(0.); if( external[0]->id() > 0 ) { SpinorVector spIn; SpinorBarVector spbOut; SpinorWaveFunction (spIn, external[0], incoming, false); SpinorBarWaveFunction(spbOut, external[2], outgoing, true); SpinorWaveFunction spr (rescaledMomenta()[0], external[0]->dataPtr(), incoming); VectorWaveFunction vr (rescaledMomenta()[1], external[1]->dataPtr(), incoming); SpinorBarWaveFunction sbr (rescaledMomenta()[2], external[2]->dataPtr(), outgoing); scaOut = ScalarWaveFunction(rescaledMomenta()[3], external[3]->dataPtr(), outgoing); for( unsigned int ihel = 0; ihel < 2; ++ihel ) { spr.reset(ihel); spIn[ihel] = spr; vr.reset(2*ihel); vecIn[ihel] = vr; sbr.reset(ihel); spbOut[ihel] = sbr; } ProductionMatrixElement prodME = fv2fbsHeME(spIn, vecIn, spbOut, scaOut, dummy,false); createVertex(prodME,external); } else { SpinorBarVector spbIn; SpinorVector spOut; SpinorBarWaveFunction(spbIn, external[0], incoming, false); SpinorWaveFunction (spOut, external[2], outgoing, true); SpinorBarWaveFunction sbr (rescaledMomenta()[0], external[0]->dataPtr(), incoming); VectorWaveFunction vr (rescaledMomenta()[1], external[1]->dataPtr(), incoming); SpinorWaveFunction spr (rescaledMomenta()[2], external[2]->dataPtr(), outgoing); scaOut = ScalarWaveFunction(rescaledMomenta()[3], external[3]->dataPtr(), outgoing); for( unsigned int ihel = 0; ihel < 2; ++ihel ) { sbr.reset(ihel); spbIn[ihel] = sbr; vr.reset(2*ihel); vecIn[ihel] = vr; spr.reset(ihel); spOut[ihel] = spr; } ProductionMatrixElement prodME = fbv2fsHeME(spbIn, vecIn, spOut, scaOut, dummy,false); createVertex(prodME,external); } #ifndef NDEBUG if( debugME() ) debug(dummy/96.); #endif } void MEfv2fs::debug(double me2) const { if( !generator()->logfile().is_open() ) return; long id1 = abs(mePartonData()[0]->id()); long id4 = abs(mePartonData()[3]->id()); if( (id1 != 1 && id1 != 2) || mePartonData()[1]->id() != 21 || mePartonData()[2]->id() != 1000021 || (id4 != 1000001 && id4 != 1000002 && id4 != 2000001 && id4 != 2000002) ) return; tcSMPtr sm = generator()->standardModel(); double gs4 = sqr( 4.*Constants::pi*sm->alphaS(scale()) ); int Nc = sm->Nc(); Energy2 m3s = sqr(mePartonData()[2]->mass()); Energy2 m4s = sqr(mePartonData()[3]->mass()); //formula has vf->fs so swap t and u Energy2 s(sHat()), t3(uHat() - m3s), u4(tHat() - m4s); double analytic = -gs4*( u4 + 2.*(m4s - m3s)*(1. + m3s/t3 + m4s/u4) )* ( sqr(u4) + sqr(s) - sqr(t3)/sqr(Nc) )/s/t3/u4/4.; double diff = abs( analytic - me2); if( diff > 1e-4 ) { generator()->log() << mePartonData()[0]->PDGName() << "," << mePartonData()[1]->PDGName() << "->" << mePartonData()[2]->PDGName() << "," << mePartonData()[3]->PDGName() << " difference: " << setprecision(10) << diff << " ratio: " << analytic/me2 << '\n'; } } diff --git a/MatrixElement/General/MEfv2fs.h b/MatrixElement/General/MEfv2fs.h --- a/MatrixElement/General/MEfv2fs.h +++ b/MatrixElement/General/MEfv2fs.h @@ -1,211 +1,214 @@ // -*- C++ -*- // // MEfv2fs.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_MEfv2fs_H #define HERWIG_MEfv2fs_H // // This is the declaration of the MEfv2fs class. // #include "GeneralHardME.h" #include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h" #include "Herwig/MatrixElement/ProductionMatrixElement.h" #include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h" #include "ThePEG/Helicity/Vertex/AbstractFFSVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractRFVVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractRFSVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVSSVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVVSVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractFFVSVertex.h" namespace Herwig { using namespace ThePEG; using ThePEG::Helicity::SpinorWaveFunction; using ThePEG::Helicity::SpinorBarWaveFunction; using ThePEG::Helicity::VectorWaveFunction; using ThePEG::Helicity::ScalarWaveFunction; /** * This class is designed to implement the matrix element for * fermion-vector to fermion scalar. It inherits from GeneralHardME * and implements the required virtual functions. * - * @see @see \ref MEfv2fsInterfaces "The Interfaces" - * defined for MEfv2fs. * @see GeneralHardME */ class MEfv2fs: public GeneralHardME { /** Vector of SpinorWaveFunctions. */ typedef vector SpinorVector; /** Vector of SpinorBarWaveFunctions. */ typedef vector SpinorBarVector; /** Vector of VectorWaveFunctions. */ typedef vector VecWFVector; public: - /** - * The default constructor. - */ - MEfv2fs() : scalar_(0), fermion_(0), vector_(0) {} - -public: - /** @name Virtual functions required by the GeneralHardME class. */ //@{ /** * The matrix element for the kinematical configuration * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. * @return the matrix element scaled with sHat() to give a * dimensionless number. */ virtual double me2() const; //@} /** * Construct the vertex information for the spin correlations * @param subp Pointer to the relevent SubProcess */ virtual void constructVertex(tSubProPtr subp); private: /** @name Functions to calculate production matrix elements and me2. */ //@{ /** * Calculate me2 and the production matrix element for the normal mode. * @param spIn Vector of SpinorWaveFunction for the incoming fermion * @param vecIn Vector of VectorWaveFunction for incoming boson * @param spbOut Vector of SpinorBarWaveFunction for outgoing fermion * @param scaOut ScalarWaveFunction for outgoing scalar. * @param first Whether or not first call to decide if colour decomposition etc * should be calculated * @param full_me The value of me2 calculation */ ProductionMatrixElement fv2fbsHeME(const SpinorVector & spIn, const VecWFVector & vecIn, const SpinorBarVector & spbOut, const ScalarWaveFunction & scaOut, double & full_me, bool first) const; /** * Calculate me2 and the production matrix element for the cc mode. * @param spbIn Vector of SpinorBarWaveFunction for the incoming fermion * @param vecIn Vector of VectorWaveFunction for incoming boson * @param spOut Vector of SpinorWaveFunction for outgoing fermion * @param scaOut ScalarWaveFunction for outgoing scalar. * @param first Whether or not first call to decide if colour decomposition etc * should be calculated * @param full_me The value of me2 calculation */ ProductionMatrixElement fbv2fsHeME(const SpinorBarVector & spbIn, const VecWFVector & vecIn, const SpinorVector & spOut, const ScalarWaveFunction & scaOut, double & full_me, bool first) const; //@} protected: /** * A debugging function to test the value of me2 against an * analytic function. * @param me2 The value of the \f$ |\bar{\mathcal{M}}|^2 \f$ */ virtual void debug(double me2) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ void doinit(); //@} protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const {return new_ptr(*this);} /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const {return new_ptr(*this);} //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MEfv2fs & operator=(const MEfv2fs &); private: /** * Store a pair of FFSVertex and VSSVertex pointers */ vector > scalar_; /** * Store a pair of FFSVertex and FFVVertex pointers */ vector > fermion_; /** * Store a pair of VVSVertex and FFVVertex pointers */ vector > vector_; - + + /** + * Store a pair of FFSVertex and FFVVertex pointers + */ + vector > RSfermion_; + + /** + * Store any 4-point vertices + */ + vector four_; }; } #endif /* HERWIG_MEfv2fs_H */ diff --git a/MatrixElement/General/MEfv2rs.cc b/MatrixElement/General/MEfv2rs.cc new file mode 100644 --- /dev/null +++ b/MatrixElement/General/MEfv2rs.cc @@ -0,0 +1,382 @@ +// -*- C++ -*- +// +// This is the implementation of the non-inlined, non-templated member +// functions of the MEfv2rs class. +// + +#include "MEfv2rs.h" +#include "ThePEG/Interface/ClassDocumentation.h" +#include "ThePEG/Utilities/DescribeClass.h" +#include "ThePEG/Persistency/PersistentOStream.h" +#include "ThePEG/Persistency/PersistentIStream.h" + +using namespace Herwig; + +double MEfv2rs::me2() const { + //massless vector + VecWFVector vecIn(2); + ScalarWaveFunction scaOut(rescaledMomenta()[3], mePartonData()[3], + Complex(1.,0.), outgoing); + double fullme(0.); + bool massless = mePartonData()[2]->mass()==ZERO; + if( mePartonData()[0]->id() > 0 ) { + SpinorVector spIn(2); + RSSpinorBarVector spbOut(4); + for(size_t ih = 0; ih < 2; ++ih) { + spIn[ih] = SpinorWaveFunction(rescaledMomenta()[0], mePartonData()[0], ih, + incoming); + vecIn[ih] = VectorWaveFunction(rescaledMomenta()[1], mePartonData()[1], 2*ih, + incoming); + } + for(size_t ih = 0; ih < 4; ++ih) { + if(massless && (ih==1 || ih==2)) continue; + spbOut[ih] = RSSpinorBarWaveFunction(rescaledMomenta()[2], mePartonData()[2], ih, + outgoing); + } + fv2rbsHeME(spIn, vecIn, spbOut, scaOut, fullme,true); + } + else { + SpinorBarVector spbIn(2); + RSSpinorVector spOut(4); + for(size_t ih = 0; ih < 2; ++ih) { + spbIn[ih] = SpinorBarWaveFunction(rescaledMomenta()[0], mePartonData()[0], ih, + incoming); + vecIn[ih] = VectorWaveFunction(rescaledMomenta()[1], mePartonData()[1], 2*ih, + incoming); + } + for(size_t ih = 0; ih < 4; ++ih) { + if(massless && (ih==1 || ih==2)) continue; + spOut[ih] = RSSpinorWaveFunction(rescaledMomenta()[2], mePartonData()[2], ih, + outgoing); + } + fbv2rsHeME(spbIn, vecIn, spOut, scaOut, fullme,true); + } + + return fullme; +} + +IBPtr MEfv2rs::clone() const { + return new_ptr(*this); +} + +IBPtr MEfv2rs::fullclone() const { + return new_ptr(*this); +} + +void MEfv2rs::doinit() { + GeneralHardME::doinit(); + scalar_.resize(numberOfDiags()); + fermion1_.resize(numberOfDiags()); + fermion2_.resize(numberOfDiags()); + vector_.resize(numberOfDiags()); + four_.resize(numberOfDiags()); + initializeMatrixElements(PDT::Spin1Half, PDT::Spin1, + PDT::Spin3Half, PDT::Spin0); + for(size_t ix = 0; ix < numberOfDiags(); ++ix) { + HPDiagram curr = getProcessInfo()[ix]; + if(curr.channelType == HPDiagram::tChannel) { + if( curr.intermediate->iSpin() == PDT::Spin0 ) { + AbstractRFSVertexPtr rfs = + dynamic_ptr_cast(curr.vertices.first); + AbstractVSSVertexPtr vss = + dynamic_ptr_cast(curr.vertices.second); + scalar_[ix] = make_pair(rfs, vss); + } + else if ( curr.intermediate->iSpin() == PDT::Spin1Half ) { + AbstractFFSVertexPtr ffs = + dynamic_ptr_cast(curr.vertices.first); + AbstractRFVVertexPtr rfv = + dynamic_ptr_cast(curr.vertices.second); + fermion2_[ix] = make_pair(ffs, rfv); + } + else if ( curr.intermediate->iSpin() == PDT::Spin1 ) { + AbstractRFVVertexPtr rfv = + dynamic_ptr_cast(curr.vertices.first); + AbstractVVSVertexPtr vvs = + dynamic_ptr_cast(curr.vertices.second); + vector_[ix] = make_pair(rfv, vvs); + } + else + assert(false); + } + else if (curr.channelType == HPDiagram::sChannel) { + assert(curr.intermediate->iSpin() == PDT::Spin1Half ); + AbstractFFVVertexPtr ffv = + dynamic_ptr_cast(curr.vertices.first); + AbstractRFSVertexPtr rfs = + dynamic_ptr_cast(curr.vertices.second); + fermion1_[ix] = make_pair(ffv,rfs); + } + else if (curr.channelType == HPDiagram::fourPoint) { + four_[ix] = dynamic_ptr_cast(curr.vertices.first); + } + else + assert(false); + } +} + +void MEfv2rs::persistentOutput(PersistentOStream & os) const { + os << scalar_ << fermion1_ << fermion2_ << vector_ << four_; +} + +void MEfv2rs::persistentInput(PersistentIStream & is, int) { + is >> scalar_ >> fermion1_ >> fermion2_ >> vector_ >> four_; + initializeMatrixElements(PDT::Spin1Half, PDT::Spin1, + PDT::Spin3Half, PDT::Spin0); +} + +// The following static variable is needed for the type +// description system in ThePEG. +DescribeClass +describeHerwigMEfv2rs("Herwig::MEfv2rs", "Herwig.so"); + +void MEfv2rs::Init() { + + static ClassDocumentation documentation + ("The MEfv2rs class implements the general matrix element for " + "fermion-vector to RS fermion scalar"); + +} + +ProductionMatrixElement +MEfv2rs::fv2rbsHeME(const SpinorVector & spIn, const VecWFVector & vecIn, + const RSSpinorBarVector & spbOut, + const ScalarWaveFunction & scaOut, + double & me2, bool first) const { + const Energy2 q2(scale()); + // weights for the selection of the diagram + vector me(numberOfDiags(), 0.); + // weights for the selection of the colour flow + vector flow(numberOfFlows(),0.); + me2 = 0.; + bool massless = mePartonData()[2]->mass()==ZERO; + for(unsigned int ihel1 = 0; ihel1 < 2; ++ihel1) { + for(unsigned int ihel2 = 0; ihel2 < 2; ++ihel2) { + for(unsigned int ohel1 = 0; ohel1 < 4; ++ohel1) { + if(massless && (ohel1==1 || ohel1==2)) continue; + vector flows(numberOfFlows(),0.); + for(size_t ix = 0; ix < numberOfDiags(); ++ix) { + Complex diag(0.); + const HPDiagram & current = getProcessInfo()[ix]; + tcPDPtr offshell = current.intermediate; + if( current.channelType == HPDiagram::tChannel ) { + if( offshell->iSpin() == PDT::Spin0 ) { + ScalarWaveFunction interS = scalar_[ix].first-> + evaluate(q2, 3, offshell, spIn[ihel1], spbOut[ohel1]); + diag = scalar_[ix].second-> + evaluate(q2, vecIn[ihel2], scaOut, interS); + } + else if( offshell->iSpin() == PDT::Spin1Half ) { + if(offshell->CC()) offshell = offshell->CC(); + SpinorBarWaveFunction interFB = fermion2_[ix].second-> + evaluate(q2, 3, offshell,spbOut[ohel1],vecIn[ihel2]); + diag = fermion2_[ix].first-> + evaluate(q2, spIn[ihel1], interFB, scaOut); + } + else { + VectorWaveFunction interV = vector_[ix].first-> + evaluate(q2,3,offshell,spIn[ihel1],spbOut[ohel1]); + diag = vector_[ix].second-> + evaluate(q2, vecIn[ihel2], interV, scaOut); + } + } + else if( current.channelType == HPDiagram::sChannel ) { + // check if take intermediate massless + unsigned int propOpt = + abs(offshell->id()) != abs(spIn[ihel1].particle()->id()) ? 1 : 5; + SpinorWaveFunction interF = fermion1_[ix].first-> + evaluate(q2, propOpt, offshell, spIn[ihel1], vecIn[ihel2]); + diag = fermion1_[ix].second-> + evaluate(q2, interF, spbOut[ohel1], scaOut); + } + else if( current.channelType == HPDiagram::fourPoint ) { + diag = four_[ix]-> + evaluate(q2, spIn[ihel1], spbOut[ohel1], vecIn[ihel2], scaOut); + } + else + assert(false); + me[ix] += norm(diag); + diagramME()[ix](ihel1, 2*ihel2, ohel1, 0) = diag; + //Compute flows + for(size_t iy = 0; iy < current.colourFlow.size(); ++iy) { + assert(current.colourFlow[iy].first me(numberOfDiags(), 0.); + // weights for the selection of the colour flow + vector flow(numberOfFlows(),0.); + me2 = 0.; + bool massless = mePartonData()[2]->mass()==ZERO; + for(unsigned int ihel1 = 0; ihel1 < 2; ++ihel1) { + for(unsigned int ihel2 = 0; ihel2 < 2; ++ihel2) { + for(unsigned int ohel1 = 0; ohel1 < 4; ++ohel1) { + if(massless && (ohel1==1 || ohel1==2)) continue; + vector flows(numberOfFlows(),0.); + for(HPCount ix = 0; ix < numberOfDiags(); ++ix) { + Complex diag(0.); + const HPDiagram & current = getProcessInfo()[ix]; + tcPDPtr offshell = current.intermediate; + if( current.channelType == HPDiagram::tChannel ) { + if( offshell->iSpin() == PDT::Spin0 ) { + ScalarWaveFunction interS = scalar_[ix].first-> + evaluate(q2, 3, offshell, spOut[ohel1], spbIn[ihel1]); + diag = scalar_[ix].second-> + evaluate(q2, vecIn[ihel2], interS, scaOut); + } + else if( offshell->iSpin() == PDT::Spin1Half ) { + SpinorBarWaveFunction interFB = fermion2_[ix].first-> + evaluate(q2, 3, offshell, spbIn[ihel1], scaOut); + diag = fermion2_[ix].second-> + evaluate(q2, spOut[ohel1], interFB, vecIn[ihel2]); + } + else if( offshell->iSpin() == PDT::Spin1 ) { + VectorWaveFunction interV = vector_[ix].first-> + evaluate(q2,3,offshell, spOut[ohel1], spbIn[ihel1]); + diag = vector_[ix].second-> + evaluate(q2, vecIn[ihel2], interV, scaOut); + } + else + assert(false); + } + else if( current.channelType == HPDiagram::sChannel ) { + // check if take intermediate massless + unsigned int propOpt = + abs(offshell->id()) != abs(spbIn[ihel1].particle()->id()) ? 1 : 5; + SpinorBarWaveFunction interFB = fermion1_[ix].first-> + evaluate(q2, propOpt, offshell, spbIn[ihel1], vecIn[ihel2]); + diag = fermion1_[ix].second-> + evaluate(q2, spOut[ohel1], interFB, scaOut); + } + else if( current.channelType == HPDiagram::fourPoint ) { + diag = four_[ix]-> evaluate(q2, spOut[ohel1], spbIn[ihel1], + vecIn[ihel2], scaOut); + } + else + assert(false); + me[ix] += norm(diag); + diagramME()[ix](ihel1, 2*ihel2, ohel1, 0) = diag; + //Compute flows + for(size_t iy = 0; iy < current.colourFlow.size(); ++iy) { + assert(current.colourFlow[iy].firstmass()==ZERO; + double dummy(0.); + if( external[0]->id() > 0 ) { + SpinorVector spIn; + RSSpinorBarVector spbOut; + SpinorWaveFunction (spIn, external[0], incoming, false); + RSSpinorBarWaveFunction(spbOut, external[2], outgoing, true); + + SpinorWaveFunction spr (rescaledMomenta()[0], + external[0]->dataPtr(), incoming); + VectorWaveFunction vr (rescaledMomenta()[1], + external[1]->dataPtr(), incoming); + RSSpinorBarWaveFunction sbr (rescaledMomenta()[2], + external[2]->dataPtr(), outgoing); + scaOut = ScalarWaveFunction(rescaledMomenta()[3], + external[3]->dataPtr(), outgoing); + + for( unsigned int ihel = 0; ihel < 2; ++ihel ) { + spr.reset(ihel); + spIn[ihel] = spr; + vr.reset(2*ihel); + vecIn[ihel] = vr; + } + for( unsigned int ihel = 0; ihel < 4; ++ihel ) { + if(massless && (ihel==1 || ihel==2)) continue; + sbr.reset(ihel); + spbOut[ihel] = sbr; + } + ProductionMatrixElement prodME = fv2rbsHeME(spIn, vecIn, spbOut, + scaOut, dummy,false); + createVertex(prodME,external); + } + else { + SpinorBarVector spbIn; + RSSpinorVector spOut; + SpinorBarWaveFunction(spbIn, external[0], incoming, false); + RSSpinorWaveFunction (spOut, external[2], outgoing, true); + SpinorBarWaveFunction sbr (rescaledMomenta()[0], + external[0]->dataPtr(), incoming); + VectorWaveFunction vr (rescaledMomenta()[1], + external[1]->dataPtr(), incoming); + RSSpinorWaveFunction spr (rescaledMomenta()[2], + external[2]->dataPtr(), outgoing); + scaOut = ScalarWaveFunction(rescaledMomenta()[3], + external[3]->dataPtr(), outgoing); + for( unsigned int ihel = 0; ihel < 2; ++ihel ) { + sbr.reset(ihel); + spbIn[ihel] = sbr; + vr.reset(2*ihel); + vecIn[ihel] = vr; + } + for( unsigned int ihel = 0; ihel < 4; ++ihel ) { + if(massless && (ihel==1 || ihel==2)) continue; + spr.reset(ihel); + spOut[ihel] = spr; + } + ProductionMatrixElement prodME = fbv2rsHeME(spbIn, vecIn, spOut, + scaOut, dummy,false); + createVertex(prodME,external); + } +} diff --git a/MatrixElement/General/MEfv2rs.h b/MatrixElement/General/MEfv2rs.h new file mode 100644 --- /dev/null +++ b/MatrixElement/General/MEfv2rs.h @@ -0,0 +1,204 @@ +// -*- C++ -*- +#ifndef Herwig_MEfv2rs_H +#define Herwig_MEfv2rs_H +// +// This is the declaration of the MEfv2rs class. +// + +#include "GeneralHardME.h" +#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" +#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" +#include "ThePEG/Helicity/WaveFunction/RSSpinorWaveFunction.h" +#include "ThePEG/Helicity/WaveFunction/RSSpinorBarWaveFunction.h" +#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" +#include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h" +#include "Herwig/MatrixElement/ProductionMatrixElement.h" +#include "ThePEG/Helicity/Vertex/AbstractRFVVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractRFSVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractRFVSVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractFFSVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractVSSVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractVVSVertex.h" + +namespace Herwig { + +using namespace ThePEG; + +/** + * This class is designed to implement the matrix element for + * fermion-vector to RS fermion scalar. It inherits from GeneralHardME + * and implements the required virtual functions. + * + * @see GeneralHardME + */ +class MEfv2rs: public GeneralHardME { + + /** Vector of SpinorWaveFunctions. */ + typedef vector SpinorVector; + + /** Vector of SpinorBarWaveFunctions. */ + typedef vector SpinorBarVector; + + /** Vector of RSSpinorWaveFunctions. */ + typedef vector RSSpinorVector; + + /** Vector of RSSpinorBarWaveFunctions. */ + typedef vector RSSpinorBarVector; + + /** Vector of VectorWaveFunctions. */ + typedef vector VecWFVector; + +public: + + /** @name Virtual functions required by the MEBase class. */ + //@{ + /** + * The matrix element for the kinematical configuration + * previously provided by the last call to setKinematics(), suitably + * scaled by sHat() to give a dimension-less number. + * @return the matrix element scaled with sHat() to give a + * dimensionless number. + */ + virtual double me2() const; + //@} + + /** + * Construct the vertex information for the spin correlations + * @param subp Pointer to the relevent SubProcess + */ + virtual void constructVertex(tSubProPtr subp); + +private: + + /** @name Functions to calculate production matrix elements and me2. */ + //@{ + /** + * Calculate me2 and the production matrix element for the normal mode. + * @param spIn Vector of SpinorWaveFunction for the incoming fermion + * @param vecIn Vector of VectorWaveFunction for incoming boson + * @param spbOut Vector of SpinorBarWaveFunction for outgoing fermion + * @param scaOut ScalarWaveFunction for outgoing scalar. + * @param first Whether or not first call to decide if colour decomposition etc + * should be calculated + * @param full_me The value of me2 calculation + */ + ProductionMatrixElement fv2rbsHeME(const SpinorVector & spIn, + const VecWFVector & vecIn, + const RSSpinorBarVector & spbOut, + const ScalarWaveFunction & scaOut, + double & full_me, bool first) const; + + /** + * Calculate me2 and the production matrix element for the cc mode. + * @param spbIn Vector of SpinorBarWaveFunction for the incoming fermion + * @param vecIn Vector of VectorWaveFunction for incoming boson + * @param spOut Vector of SpinorWaveFunction for outgoing fermion + * @param scaOut ScalarWaveFunction for outgoing scalar. + * @param first Whether or not first call to decide if colour decomposition etc + * should be calculated + * @param full_me The value of me2 calculation + */ + ProductionMatrixElement fbv2rsHeME(const SpinorBarVector & spbIn, + const VecWFVector & vecIn, + const RSSpinorVector & spOut, + const ScalarWaveFunction & scaOut, + double & full_me, bool first) const; + //@} + + +public: + + /** @name Functions used by the persistent I/O system. */ + //@{ + /** + * Function used to write out object persistently. + * @param os the persistent output stream written to. + */ + void persistentOutput(PersistentOStream & os) const; + + /** + * Function used to read in object persistently. + * @param is the persistent input stream read from. + * @param version the version number of the object when written. + */ + void persistentInput(PersistentIStream & is, int version); + //@} + + /** + * The standard Init function used to initialize the interfaces. + * Called exactly once for each class by the class description system + * before the main function starts or + * when this class is dynamically loaded. + */ + static void Init(); + +protected: + + /** @name Clone Methods. */ + //@{ + /** + * Make a simple clone of this object. + * @return a pointer to the new object. + */ + virtual IBPtr clone() const; + + /** Make a clone of this object, possibly modifying the cloned object + * to make it sane. + * @return a pointer to the new object. + */ + virtual IBPtr fullclone() const; + //@} + + +protected: + + /** @name Standard Interfaced functions. */ + //@{ + /** + * Initialize this object after the setup phase before saving an + * EventGenerator to disk. + * @throws InitException if object could not be initialized properly. + */ + virtual void doinit(); + //@} + +private: + + /** + * The assignment operator is private and must never be called. + * In fact, it should not even be implemented. + */ + MEfv2rs & operator=(const MEfv2rs &); + +private: + + /** + * Store a pair of FFSVertex and VSSVertex pointers + */ + vector > scalar_; + + /** + * Store a pair of FFSVertex and FFVVertex pointers + */ + vector > fermion1_; + + /** + * Store a pair of FFSVertex and FFVVertex pointers + */ + vector > fermion2_; + + /** + * Store a pair of VVSVertex and FFVVertex pointers + */ + vector > vector_; + + /** + * Store the 4-point vertices + */ + vector four_; +}; + +} + +#endif /* Herwig_MEfv2rs_H */ diff --git a/MatrixElement/General/MEfv2rv.cc b/MatrixElement/General/MEfv2rv.cc new file mode 100644 --- /dev/null +++ b/MatrixElement/General/MEfv2rv.cc @@ -0,0 +1,370 @@ +// -*- C++ -*- +// +// This is the implementation of the non-inlined, non-templated member +// functions of the MEfv2rv class. +// + +#include "MEfv2rv.h" +#include "ThePEG/Interface/ClassDocumentation.h" +#include "ThePEG/Utilities/DescribeClass.h" +#include "ThePEG/Persistency/PersistentOStream.h" +#include "ThePEG/Persistency/PersistentIStream.h" + +using namespace Herwig; +using ThePEG::Helicity::incoming; +using ThePEG::Helicity::outgoing; +using ThePEG::Helicity::SpinorWaveFunction; +using ThePEG::Helicity::SpinorBarWaveFunction; +using ThePEG::Helicity::RSSpinorWaveFunction; +using ThePEG::Helicity::RSSpinorBarWaveFunction; +using ThePEG::Helicity::VectorWaveFunction; + +void MEfv2rv::doinit() { + GeneralHardME::doinit(); + fermion_.resize(numberOfDiags()); + vector_.resize(numberOfDiags()); + four_ .resize(numberOfDiags()); + initializeMatrixElements(PDT::Spin1Half, PDT::Spin1, + PDT::Spin3Half, PDT::Spin1); + for(HPCount ix = 0; ix < numberOfDiags(); ++ix) { + HPDiagram diagram = getProcessInfo()[ix]; + PDT::Spin offspin = diagram.intermediate->iSpin(); + if ( diagram.channelType == HPDiagram::fourPoint) { + four_[ix] = dynamic_ptr_cast(diagram.vertices.first); + } + else if(diagram.channelType == HPDiagram::sChannel || + ( diagram.channelType == HPDiagram::tChannel + && offspin == PDT::Spin1Half)) { + AbstractFFVVertexPtr vert1 = dynamic_ptr_cast + (diagram.vertices.first); + AbstractRFVVertexPtr vert2 = dynamic_ptr_cast + (diagram.vertices.second); + fermion_[ix] = make_pair(vert1, vert2); + } + else { + if(offspin == PDT::Spin1) { + AbstractRFVVertexPtr vert1 = dynamic_ptr_cast + (diagram.vertices.first); + AbstractVVVVertexPtr vert2 = dynamic_ptr_cast + (diagram.vertices.second); + vector_[ix] = make_pair(vert1, vert2); + } + } + } +} + +double MEfv2rv::me2() const { + double fullme(0.); + //wavefunctions for the vectors + VBVector vecIn(2), vecOut(3); + bool mc = !(mePartonData()[3]->mass() > ZERO); + bool massless = mePartonData()[2]->mass()!=ZERO; + for(unsigned int i = 0; i < 2; ++i) { + vecIn[i] = VectorWaveFunction(rescaledMomenta()[1], mePartonData()[1], 2*i, + incoming); + vecOut[2*i] = VectorWaveFunction(rescaledMomenta()[3], mePartonData()[3], 2*i, + outgoing); + } + if( !mc ) + vecOut[1] = VectorWaveFunction(rescaledMomenta()[3], mePartonData()[3], 1, + outgoing); + // spinor wavefunctions and me call + if(mePartonData()[0]->id() > 0) { + SpinorVector sp(2); + RSSpinorBarVector spb(4); + for(unsigned int i = 0; i < 2; ++i) { + sp[i] = SpinorWaveFunction(rescaledMomenta()[0], mePartonData()[0], i, + incoming); + } + for(unsigned int i = 0; i < 4; ++i) { + if(massless && (i==1 || i==2)) continue; + spb[i] = RSSpinorBarWaveFunction(rescaledMomenta()[2], mePartonData()[2], i, + outgoing); + } + fv2rvHeME(sp, vecIn, spb, vecOut, mc, fullme,true); + } + else { + RSSpinorVector sp(4); + SpinorBarVector spb(2); + for(unsigned int i = 0; i < 2; ++i) { + spb[i] = SpinorBarWaveFunction(rescaledMomenta()[0], mePartonData()[0], i, + incoming); + } + for(unsigned int i = 0; i < 4; ++i) { + if(massless && (i==1 || i==2)) continue; + sp[i] = RSSpinorWaveFunction(rescaledMomenta()[2], mePartonData()[2], i, + outgoing); + } + fbv2rbvHeME(spb, vecIn, sp, vecOut, mc, fullme,true); + } + return fullme; +} + +IBPtr MEfv2rv::clone() const { + return new_ptr(*this); +} + +IBPtr MEfv2rv::fullclone() const { + return new_ptr(*this); +} + +void MEfv2rv::persistentOutput(PersistentOStream & os) const { + os << fermion_ << vector_ << four_; +} + +void MEfv2rv::persistentInput(PersistentIStream & is, int) { + is >> fermion_ >> vector_ >> four_; + initializeMatrixElements(PDT::Spin1Half, PDT::Spin1, + PDT::Spin3Half, PDT::Spin1); +} + + +// The following static variable is needed for the type +// description system in ThePEG. +DescribeClass + describeHerwigMEfv2rv("Herwig::MEfv2rv", "Herwig.so"); + +void MEfv2rv::Init() { + + static ClassDocumentation documentation + ("The MEfv2rv class implements the general matrix element for fv -> rv"); + +} + +ProductionMatrixElement +MEfv2rv::fv2rvHeME(const SpinorVector & spIn, const VBVector & vecIn, + const RSSpinorBarVector & spbOut, + const VBVector & vecOut, bool mc, + double & me2, bool first) const { + const Energy2 q2(scale()); + // weights for the selection of the diagram + vector me(numberOfDiags(), 0.); + // weights for the selection of the colour flow + vector flow(numberOfFlows(),0.); + bool massless = mePartonData()[2]->mass()!=ZERO; + me2 = 0.; + //loop over helicities + for(unsigned int ifh = 0; ifh < 2; ++ifh) { + for(unsigned int ivh = 0; ivh < 2; ++ivh) { + for(unsigned int ofh = 0; ofh < 4; ++ofh) { + if(massless && (ofh==1 || ofh==2)) continue; + for(unsigned int ovh = 0; ovh < 3; ++ovh) { + if(mc && ovh == 1) ++ovh; + vector flows(numberOfFlows(),0.); + for(HPCount ix = 0; ix < numberOfDiags(); ++ix) { + Complex diag(0.); + const HPDiagram & current = getProcessInfo()[ix]; + tcPDPtr offshell = current.intermediate; + if(current.channelType == HPDiagram::tChannel) { + //t-chan spin-1/2 + if(offshell->iSpin() == PDT::Spin1Half) { + if(offshell->CC()) offshell = offshell->CC(); + unsigned int iopt = abs(offshell->id())==abs(spIn[ifh].particle()->id()) ? 5 : 3; + SpinorBarWaveFunction interFB = fermion_[ix].second-> + evaluate(q2, iopt, offshell, spbOut[ofh], vecIn[ivh]); + diag = fermion_[ix].first-> + evaluate(q2, spIn[ifh], interFB, vecOut[ovh]); + } + else if(offshell->iSpin() == PDT::Spin1) { + VectorWaveFunction interV = vector_[ix].second-> + evaluate(q2, 3, offshell, vecIn[ivh], vecOut[ovh]); + diag = vector_[ix].first-> + evaluate(q2, spIn[ifh], spbOut[ofh], interV); + } + else + assert(false); + } + else if(current.channelType == HPDiagram::sChannel) { + if(offshell->CC()) offshell = offshell->CC(); + unsigned int iopt = abs(offshell->id())==abs(spIn[ifh].particle()->id()) ? 5 : 1; + SpinorBarWaveFunction interFB = fermion_[ix].second-> + evaluate(q2, iopt, offshell, spbOut[ofh], vecOut[ovh]); + diag = fermion_[ix].first-> + evaluate(q2, spIn[ifh], interFB, vecIn[ivh]); + } + else if(current.channelType == HPDiagram::fourPoint) { + diag = four_[ix]->evaluate(q2, spIn[ifh],spbOut[ofh],vecIn[ivh],vecOut[ovh]); + } + me[ix] += norm(diag); + diagramME()[ix](ifh, 2*ivh, ofh, ovh) = diag; + //Compute flows + for(size_t iy = 0; iy < current.colourFlow.size(); ++iy) { + assert(current.colourFlow[iy].first me(numberOfDiags(), 0.); + // weights for the selection of the colour flow + vector flow(numberOfFlows(),0.); + bool massless = mePartonData()[2]->mass()!=ZERO; + me2 = 0.; + //loop over helicities + for(unsigned int ifh = 0; ifh < 2; ++ifh) { + for(unsigned int ivh = 0; ivh < 2; ++ivh) { + for(unsigned int ofh = 0; ofh < 4; ++ofh) { + if(massless && (ofh==1 || ofh==2)) continue; + for(unsigned int ovh = 0; ovh < 3; ++ovh) { + if(mc && ovh == 1) ++ovh; + vector flows(numberOfFlows(),0.); + for(HPCount ix = 0; ix < numberOfDiags(); ++ix) { + Complex diag(0.); + const HPDiagram & current = getProcessInfo()[ix]; + tcPDPtr offshell = current.intermediate; + if(current.channelType == HPDiagram::tChannel) { + if(offshell->iSpin() == PDT::Spin1Half) { + SpinorBarWaveFunction interFB = fermion_[ix].first-> + evaluate(q2, 3, offshell, spbIn[ifh], vecOut[ovh]); + diag = fermion_[ix].second-> + evaluate(q2, spOut[ofh], interFB, vecIn[ivh]); + } + else if(offshell->iSpin() == PDT::Spin1) { + VectorWaveFunction interV = vector_[ix].first-> + evaluate(q2, 3, offshell, spOut[ofh], spbIn[ifh]); + diag = vector_[ix].second-> + evaluate(q2, vecIn[ivh], interV, vecOut[ovh]); + } + else + assert(false); + } + else if(current.channelType == HPDiagram::sChannel) { + if(offshell->iSpin() == PDT::Spin1Half) { + SpinorBarWaveFunction interFB = fermion_[ix].first-> + evaluate(q2, 1, offshell, spbIn[ifh], vecIn[ivh]); + diag = fermion_[ix].second-> + evaluate(q2, spOut[ofh], interFB, vecOut[ovh]); + } + else + assert(false); + } + else if(current.channelType == HPDiagram::fourPoint) { + diag = four_[ix]->evaluate(q2, spOut[ofh], spbIn[ifh],vecOut[ovh],vecIn[ivh]); + } + me[ix] += norm(diag); + diagramME()[ix](ifh, ivh, ovh, ofh) = diag; + //Compute flows + for(size_t iy = 0; iy < current.colourFlow.size(); ++iy) { + assert(current.colourFlow[iy].firstdata().mass() > ZERO); + bool md = !(ext[3]->data().mass() > ZERO); + VectorWaveFunction(v1, ext[1], incoming, false, true); + VectorWaveFunction(v3, ext[3], outgoing, true, md); + double dummy(0.); + // Need to use rescale momenta to calculate matrix element + setRescaledMomenta(ext); + // wavefunctions with rescaled momenta + // vector + VectorWaveFunction vir(rescaledMomenta()[1], + ext[1]->dataPtr(), incoming); + VectorWaveFunction vor(rescaledMomenta()[3], + ext[3]->dataPtr(), outgoing); + for( unsigned int ihel = 0; ihel < 2; ++ihel ) { + vir.reset(2*ihel); + v1[ihel] = vir; + vor.reset(2*ihel); + v3[2*ihel] = vor; + } + if( !md ) { + vor.reset(1); + v3[1] = vor; + } + // matrix element and spinor wavefunctions + if( ext[0]->id() > 0 ) { + SpinorVector sp; + RSSpinorBarVector sbar; + SpinorWaveFunction (sp , ext[0], incoming, false); + RSSpinorBarWaveFunction(sbar, ext[2], outgoing, true); + SpinorWaveFunction spr (rescaledMomenta()[0], + ext[0]->dataPtr(), incoming); + RSSpinorBarWaveFunction sbr(rescaledMomenta()[2], + ext[2]->dataPtr(), outgoing); + for( unsigned int ihel = 0; ihel < 2; ++ihel ) { + spr.reset(ihel); + sp[ihel] = spr; + } + for( unsigned int ihel = 0; ihel < 4; ++ihel ) { + if(mc &&(ihel==1 || ihel==2)) continue; + sbr.reset(ihel); + sbar[ihel] = sbr; + } + ProductionMatrixElement pme = fv2rvHeME(sp, v1, sbar, v3, md, dummy,false); + createVertex(pme,ext); + } + else { + RSSpinorVector sp; + SpinorBarVector sbar; + SpinorBarWaveFunction(sbar, ext[0], incoming, false); + RSSpinorWaveFunction(sp, ext[2], outgoing, true); + SpinorBarWaveFunction sbr(rescaledMomenta()[0], + ext[0]->dataPtr(), incoming); + RSSpinorWaveFunction spr (rescaledMomenta()[2], + ext[2]->dataPtr(), outgoing); + for( unsigned int ihel = 0; ihel < 2; ++ihel ) { + sbr.reset(ihel); + sbar[ihel] = sbr; + } + for( unsigned int ihel = 0; ihel < 4; ++ihel ) { + if(mc &&(ihel==1 || ihel==2)) continue; + spr.reset(ihel); + sp[ihel] = spr; + } + ProductionMatrixElement pme = fbv2rbvHeME(sbar, v1, sp, v3, md, dummy,false); + createVertex(pme,ext); + } +} diff --git a/MatrixElement/General/MEfv2rv.h b/MatrixElement/General/MEfv2rv.h new file mode 100644 --- /dev/null +++ b/MatrixElement/General/MEfv2rv.h @@ -0,0 +1,197 @@ +// -*- C++ -*- +#ifndef Herwig_MEfv2rv_H +#define Herwig_MEfv2rv_H +// +// This is the declaration of the MEfv2rv class. +// + +#include "GeneralHardME.h" +#include "Herwig/MatrixElement/ProductionMatrixElement.h" +#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" +#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" +#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" +#include "ThePEG/Helicity/WaveFunction/RSSpinorWaveFunction.h" +#include "ThePEG/Helicity/WaveFunction/RSSpinorBarWaveFunction.h" +#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractRFVVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractVVVVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractRFVVVertex.h" + +namespace Herwig { + +using namespace ThePEG; + +/** + * This class implements the matrix element for a fermion and a vector + * boson to a vector boson and a RS fermion. It inherits from GeneralHardME + * and implements the appropriate virtual functions. + * + * @see GeneralHardME + * + */ +class MEfv2rv: public GeneralHardME { + +public: + + /** A vector of SpinorWaveFunctions. */ + typedef vector SpinorVector; + + /** A vector of SpinorBarWaveFunctions. */ + typedef vector SpinorBarVector; + + /** A vector of SpinorWaveFunctions. */ + typedef vector RSSpinorVector; + + /** A vector of SpinorBarWaveFunctions. */ + typedef vector RSSpinorBarVector; + + /** A vector of VectorWaveFunctions. */ + typedef vector VBVector; + +public: + + /** @name Virtual functions required by the MEBase class. */ + //@{ + /** + * The matrix element for the kinematical configuration + * previously provided by the last call to setKinematics(), suitably + * scaled by sHat() to give a dimension-less number. + * @return the matrix element scaled with sHat() to give a + * dimensionless number. + */ + virtual double me2() const; + //@} + + /** + * Construct the vertex information for the spin correlations + * @param sub Pointer to the relevent SubProcess + */ + virtual void constructVertex(tSubProPtr sub); + +private: + + /** @name Functions to calculate the Helicity MatrixElement.*/ + //@{ + /** + * Calculate the matrix element for an incoming fermion + * @param spIn A vector of spinors for the incoming fermion + * @param vecIn A vector of VectorWaveFunctions for the incoming boson + * @param spbOut A vector of SpinorBarWaveFunctions for the outgoing fermion + * @param vecOut A vector of VectorWaveFunctions for the outgoing boson + * @param mc If the outgoing vector is massless or not + * @param first Whether or not first call to decide if colour decomposition etc + * should be calculated + * @param mesq The matrix element squared + */ + ProductionMatrixElement + fv2rvHeME(const SpinorVector & spIn, const VBVector & vecIn, + const RSSpinorBarVector & spbOut, + const VBVector & vecOut, bool mc, + double & mesq, bool first) const; + + /** + * Calculate the matrix element for an incoming anti-fermion + * @param spbIn A vector of SpinorBarWaveFunctions for the incoming anti-fermion + * @param vecIn A vector of VectorWaveFunctions for the incoming boson + * @param spOut A vector of Spinors for the outgoing antifermion + * @param vecOut A vector of VectorWaveFunctions for the outgoing boson + * @param mc If the outgoing vector is massless or not + * @param first Whether or not first call to decide if colour decomposition etc + * should be calculated + * @param mesq The matrix element squared + */ + ProductionMatrixElement + fbv2rbvHeME(const SpinorBarVector & spbIn, const VBVector & vecIn, + const RSSpinorVector & spOut, + const VBVector & vecOut, bool mc, + double & mesq, bool first) const; + //@} + +public: + + /** @name Functions used by the persistent I/O system. */ + //@{ + /** + * Function used to write out object persistently. + * @param os the persistent output stream written to. + */ + void persistentOutput(PersistentOStream & os) const; + + /** + * Function used to read in object persistently. + * @param is the persistent input stream read from. + * @param version the version number of the object when written. + */ + void persistentInput(PersistentIStream & is, int version); + //@} + + /** + * The standard Init function used to initialize the interfaces. + * Called exactly once for each class by the class description system + * before the main function starts or + * when this class is dynamically loaded. + */ + static void Init(); + +protected: + + /** @name Clone Methods. */ + //@{ + /** + * Make a simple clone of this object. + * @return a pointer to the new object. + */ + virtual IBPtr clone() const; + + /** Make a clone of this object, possibly modifying the cloned object + * to make it sane. + * @return a pointer to the new object. + */ + virtual IBPtr fullclone() const; + //@} + +protected: + + /** @name Standard Interfaced functions. */ + //@{ + /** + * Initialize this object after the setup phase before saving an + * EventGenerator to disk. + * @throws InitException if object could not be initialized properly. + */ + virtual void doinit(); + //@} + +private: + + /** + * The assignment operator is private and must never be called. + * In fact, it should not even be implemented. + */ + MEfv2rv & operator=(const MEfv2rv &); + +private: + + /** @name Store dynamically casted vertices. */ + //@{ + /** + * A pair off FFVVertex pointers + */ + vector > fermion_; + + /** + * A pair of FFVVertex, VVVertex pointers + */ + vector > vector_; + + /** + * Four point vertices + */ + vector four_; + //@} + +}; + +} + +#endif /* Herwig_MEfv2rv_H */ diff --git a/MatrixElement/General/MEfv2vf.cc b/MatrixElement/General/MEfv2vf.cc --- a/MatrixElement/General/MEfv2vf.cc +++ b/MatrixElement/General/MEfv2vf.cc @@ -1,379 +1,389 @@ // -*- C++ -*- // // MEfv2vf.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 MEfv2vf class. // #include "MEfv2vf.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; using ThePEG::Helicity::incoming; using ThePEG::Helicity::outgoing; using ThePEG::Helicity::SpinorWaveFunction; using ThePEG::Helicity::SpinorBarWaveFunction; using ThePEG::Helicity::VectorWaveFunction; void MEfv2vf::doinit() { GeneralHardME::doinit(); fermion_.resize(numberOfDiags()); vector_.resize(numberOfDiags()); + four_ .resize(numberOfDiags()); initializeMatrixElements(PDT::Spin1Half, PDT::Spin1, PDT::Spin1, PDT::Spin1Half); for(HPCount ix = 0; ix < numberOfDiags(); ++ix) { HPDiagram diagram = getProcessInfo()[ix]; PDT::Spin offspin = diagram.intermediate->iSpin(); - if(diagram.channelType == HPDiagram::sChannel || + if ( diagram.channelType == HPDiagram::fourPoint) { + four_[ix] = dynamic_ptr_cast(diagram.vertices.first); + } + else if(diagram.channelType == HPDiagram::sChannel || ( diagram.channelType == HPDiagram::tChannel && offspin == PDT::Spin1Half)) { AbstractFFVVertexPtr vert1 = dynamic_ptr_cast (diagram.vertices.first); AbstractFFVVertexPtr vert2 = dynamic_ptr_cast (diagram.vertices.second); fermion_[ix] = make_pair(vert1, vert2); } else { if(offspin == PDT::Spin1) { AbstractFFVVertexPtr vert1 = dynamic_ptr_cast (diagram.vertices.first); AbstractVVVVertexPtr vert2 = dynamic_ptr_cast (diagram.vertices.second); vector_[ix] = make_pair(vert1, vert2); } } } } double MEfv2vf::me2() const { //wavefunctions SpinorVector sp(2); VBVector vecIn(2), vecOut(3); SpinorBarVector spb(2); double fullme(0.); bool mc = !(mePartonData()[2]->mass() > ZERO); if(mePartonData()[0]->id() > 0) { for(unsigned int i = 0; i < 2; ++i) { sp[i] = SpinorWaveFunction(rescaledMomenta()[0], mePartonData()[0], i, incoming); vecIn[i] = VectorWaveFunction(rescaledMomenta()[1], mePartonData()[1], 2*i, - incoming); + incoming); vecOut[2*i] = VectorWaveFunction(rescaledMomenta()[2], mePartonData()[2], 2*i, - outgoing); + outgoing); spb[i] = SpinorBarWaveFunction(rescaledMomenta()[3], mePartonData()[3], i, outgoing); } if( !mc ) vecOut[1] = VectorWaveFunction(rescaledMomenta()[2], mePartonData()[2], 1, outgoing); fv2vfHeME(sp, vecIn, vecOut, mc, spb, fullme,true); } else { for(unsigned int i = 0; i < 2; ++i) { spb[i] = SpinorBarWaveFunction(rescaledMomenta()[0], mePartonData()[0], i, incoming); vecIn[i] = VectorWaveFunction(rescaledMomenta()[1], mePartonData()[1], 2*i, incoming); vecOut[2*i] = VectorWaveFunction(rescaledMomenta()[2], mePartonData()[2], 2*i, outgoing); sp[i] = SpinorWaveFunction(rescaledMomenta()[3], mePartonData()[3], i, outgoing); } if( !mc ) vecOut[1] = VectorWaveFunction(rescaledMomenta()[2], mePartonData()[2], 1, outgoing); fbv2vfbHeME(spb, vecIn, vecOut, mc, sp, fullme,true); } #ifndef NDEBUG if( debugME() ) debug(fullme); #endif return fullme; } ProductionMatrixElement MEfv2vf::fv2vfHeME(const SpinorVector & spIn, const VBVector & vecIn, const VBVector & vecOut, bool mc, const SpinorBarVector & spbOut, double & me2, bool first) const { const Energy2 q2(scale()); // weights for the selection of the diagram vector me(numberOfDiags(), 0.); // weights for the selection of the colour flow vector flow(numberOfFlows(),0.); me2 = 0.; //loop over helicities for(unsigned int ifh = 0; ifh < 2; ++ifh) { for(unsigned int ivh = 0; ivh < 2; ++ivh) { for(unsigned int ovh = 0; ovh < 3; ++ovh) { if(mc && ovh == 1) ++ovh; for(unsigned int ofh = 0; ofh < 2; ++ofh) { vector flows(numberOfFlows(),0.); for(HPCount ix = 0; ix < numberOfDiags(); ++ix) { Complex diag(0.); const HPDiagram & current = getProcessInfo()[ix]; tcPDPtr offshell = current.intermediate; if(current.channelType == HPDiagram::tChannel) { //t-chan spin-1/2 if(offshell->iSpin() == PDT::Spin1Half) { if(offshell->CC()) offshell = offshell->CC(); unsigned int iopt = abs(offshell->id())==abs(spIn[ifh].particle()->id()) ? 5 : 3; SpinorBarWaveFunction interFB = fermion_[ix].second-> evaluate(q2, iopt, offshell, spbOut[ofh], vecIn[ivh]); diag = fermion_[ix].first-> evaluate(q2, spIn[ifh], interFB, vecOut[ovh]); } else if(offshell->iSpin() == PDT::Spin1) { VectorWaveFunction interV = vector_[ix].second-> evaluate(q2, 3, offshell, vecIn[ivh], vecOut[ovh]); diag = vector_[ix].first-> evaluate(q2, spIn[ifh], spbOut[ofh], interV); } else diag = 0.0; } else if(current.channelType == HPDiagram::sChannel) { if(offshell->CC()) offshell = offshell->CC(); unsigned int iopt = abs(offshell->id())==abs(spIn[ifh].particle()->id()) ? 5 : 1; SpinorBarWaveFunction interFB = fermion_[ix].second-> evaluate(q2, iopt, offshell, spbOut[ofh], vecOut[ovh]); diag = fermion_[ix].first-> evaluate(q2, spIn[ifh], interFB, vecIn[ivh]); } + else if(current.channelType == HPDiagram::fourPoint) { + diag = four_[ix]->evaluate(q2, spIn[ifh],spbOut[ofh],vecIn[ivh],vecOut[ovh]); + } me[ix] += norm(diag); diagramME()[ix](ifh, 2*ivh, ovh, ofh) = diag; //Compute flows for(size_t iy = 0; iy < current.colourFlow.size(); ++iy) { assert(current.colourFlow[iy].first me(numberOfDiags(), 0.); // weights for the selection of the colour flow vector flow(numberOfFlows(),0.); me2 = 0.; //loop over helicities for(unsigned int ifh = 0; ifh < 2; ++ifh) { for(unsigned int ivh = 0; ivh < 2; ++ivh) { for(unsigned int ovh = 0; ovh < 3; ++ovh) { if(mc && ovh == 1) ++ovh; for(unsigned int ofh = 0; ofh < 2; ++ofh) { vector flows(numberOfFlows(),0.); for(HPCount ix = 0; ix < numberOfDiags(); ++ix) { Complex diag(0.); const HPDiagram & current = getProcessInfo()[ix]; tcPDPtr offshell = current.intermediate; if(current.channelType == HPDiagram::tChannel) { if(offshell->iSpin() == PDT::Spin1Half) { SpinorBarWaveFunction interFB = fermion_[ix].first-> evaluate(q2, 3, offshell, spbIn[ifh], vecOut[ovh]); diag = fermion_[ix].second-> evaluate(q2, spOut[ofh], interFB, vecIn[ivh]); } else if(offshell->iSpin() == PDT::Spin1) { VectorWaveFunction interV = vector_[ix].first-> evaluate(q2, 3, offshell, spOut[ofh], spbIn[ifh]); diag = vector_[ix].second-> evaluate(q2, vecIn[ivh], interV, vecOut[ovh]); } else diag = 0.0; } else if(current.channelType == HPDiagram::sChannel) { if(offshell->iSpin() == PDT::Spin1Half) { SpinorBarWaveFunction interFB = fermion_[ix].first-> evaluate(q2, 1, offshell, spbIn[ifh], vecIn[ivh]); diag = fermion_[ix].second-> evaluate(q2, spOut[ofh], interFB, vecOut[ovh]); } } + else if(current.channelType == HPDiagram::fourPoint) { + diag = four_[ix]->evaluate(q2, spOut[ofh], spbIn[ifh],vecOut[ovh],vecIn[ivh]); + } me[ix] += norm(diag); diagramME()[ix](ifh, ivh, ovh, ofh) = diag; //Compute flows for(size_t iy = 0; iy < current.colourFlow.size(); ++iy) { assert(current.colourFlow[iy].first> fermion_ >> vector_; + is >> fermion_ >> vector_ >> four_; initializeMatrixElements(PDT::Spin1Half, PDT::Spin1, PDT::Spin1, PDT::Spin1Half); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigMEfv2vf("Herwig::MEfv2vf", "Herwig.so"); void MEfv2vf::Init() { static ClassDocumentation documentation ("This is the implementation of the matrix element for a fermion-vector boson" "to a vector-fermion."); } void MEfv2vf::constructVertex(tSubProPtr sub) { ParticleVector ext = hardParticles(sub); VBVector v1, v3; bool mc = !(ext[2]->data().mass() > ZERO); SpinorVector sp; SpinorBarVector sbar; VectorWaveFunction(v1, ext[1], incoming, false, true); VectorWaveFunction(v3, ext[2], outgoing, true, mc); double dummy(0.); //Need to use rescale momenta to calculate matrix element setRescaledMomenta(ext); // wavefunctions with rescaled momenta VectorWaveFunction vir(rescaledMomenta()[1], ext[1]->dataPtr(), incoming); VectorWaveFunction vor(rescaledMomenta()[2], ext[2]->dataPtr(), outgoing); if( ext[0]->id() > 0 ) { SpinorWaveFunction (sp , ext[0], incoming, false); SpinorBarWaveFunction(sbar, ext[3], outgoing, true); SpinorWaveFunction spr (rescaledMomenta()[0], ext[0]->dataPtr(), incoming); SpinorBarWaveFunction sbr(rescaledMomenta()[3], ext[3]->dataPtr(), outgoing); for( unsigned int ihel = 0; ihel < 2; ++ihel ) { spr.reset(ihel); sp[ihel] = spr; vir.reset(2*ihel); v1[ihel] = vir; vor.reset(2*ihel); v3[2*ihel] = vor; sbr.reset(ihel); sbar[ihel] = sbr; } if( !mc ) { vor.reset(1); v3[1] = vor; } ProductionMatrixElement pme = fv2vfHeME(sp, v1, v3, mc, sbar, dummy,false); createVertex(pme,ext); } else { SpinorBarWaveFunction(sbar, ext[0], incoming, false); SpinorWaveFunction(sp, ext[3], outgoing, true); SpinorBarWaveFunction sbr(rescaledMomenta()[0], ext[0]->dataPtr(), incoming); SpinorWaveFunction spr (rescaledMomenta()[3], ext[3]->dataPtr(), outgoing); for( unsigned int ihel = 0; ihel < 2; ++ihel ) { sbr.reset(ihel); sbar[ihel] = sbr; vir.reset(2*ihel); v1[ihel] = vir; vor.reset(2*ihel); v3[2*ihel] = vor; spr.reset(ihel); sp[ihel] = spr; } if( !mc ) { vor.reset(1); v3[1] = vor; } ProductionMatrixElement pme = fbv2vfbHeME(sbar, v1, v3, mc, sp, dummy,false); createVertex(pme,ext); } #ifndef NDEBUG if( debugME() ) debug(dummy); #endif } void MEfv2vf::debug(double me2) const { if( !generator()->logfile().is_open() ) return; long id1 = abs(mePartonData()[0]->id()); long id4 = abs(mePartonData()[3]->id()); if( (id1 != 1 && id1 != 2) || mePartonData()[1]->id() != 21 || mePartonData()[2]->id() != 5100021 || (id4 != 5100001 && id4 != 5100002 && id4 != 6100001 && id4 != 6100002) ) return; tcSMPtr sm = generator()->standardModel(); double gs4 = sqr( 4.*Constants::pi*sm->alphaS(scale()) ); Energy2 s(sHat()); Energy2 mf2 = meMomenta()[2].m2(); // Energy4 spt2 = uHat()*tHat() - sqr(mf2); //swap t and u as formula defines process vf->vf Energy2 t3(uHat() - mf2), u4(tHat() - mf2); Energy4 s2(sqr(s)), t3s(sqr(t3)), u4s(sqr(u4)); double analytic = -gs4*( 5.*s2/12./t3s + s2*s/t3s/u4 + 11.*s*u4/6./t3s + 5.*u4s/12./t3s + u4s*u4/s/t3s)/3.; double diff = abs(analytic - me2); if( diff > 1e-4 ) { generator()->log() << mePartonData()[0]->PDGName() << "," << mePartonData()[1]->PDGName() << "->" << mePartonData()[2]->PDGName() << "," << mePartonData()[3]->PDGName() << " difference: " << setprecision(10) << diff << " ratio: " << analytic/me2 << '\n'; } } diff --git a/MatrixElement/General/MEfv2vf.h b/MatrixElement/General/MEfv2vf.h --- a/MatrixElement/General/MEfv2vf.h +++ b/MatrixElement/General/MEfv2vf.h @@ -1,198 +1,204 @@ // -*- C++ -*- // // MEfv2vf.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_MEfv2vf_H #define HERWIG_MEfv2vf_H // // This is the declaration of the MEfv2vf class. // #include "GeneralHardME.h" #include "Herwig/MatrixElement/ProductionMatrixElement.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" #include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVVVVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractFFVVVertex.h" namespace Herwig { using namespace ThePEG; /** * This class implements the matrix element for a fermion and a vector * boson to a fermion and a vector boson. It inherits from GeneralHardME * and implements the appropriate virtual functions. + * + * @see GeneralHardME * - * @see \ref MEfv2vfInterfaces "The interfaces" - * defined for MEfv2vf. */ class MEfv2vf: public GeneralHardME { public: /** A vector of SpinorWaveFunctions. */ typedef vector SpinorVector; /** A vector of SpinorBarWaveFunctions. */ typedef vector SpinorBarVector; /** A vector of VectorWaveFunctions. */ typedef vector VBVector; public: /** @name Virtual functions required by the MEBase class. */ //@{ /** * The matrix element for the kinematical configuration * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. * @return the matrix element scaled with sHat() to give a * dimensionless number. */ virtual double me2() const; //@} /** * Construct the vertex information for the spin correlations * @param sub Pointer to the relevent SubProcess */ virtual void constructVertex(tSubProPtr sub); private: /** @name Functions to calculate the Helicity MatrixElement.*/ //@{ /** * Calculate the matrix element for an incoming fermion * @param spIn A vector of spinors for the incoming fermion * @param vecIn A vector of VectorWaveFunctions for the incoming boson * @param spbOut A vector of SpinorBarWaveFunctions for the outgoing fermion * @param vecOut A vector of VectorWaveFunctions for the outgoing boson * @param mc If the outgoing vector is massless or not * @param first Whether or not first call to decide if colour decomposition etc * should be calculated * @param mesq The matrix element squared */ ProductionMatrixElement fv2vfHeME(const SpinorVector & spIn, const VBVector & vecIn, const VBVector & vecOut, bool mc, const SpinorBarVector & spbOut, double & mesq, bool first) const; /** * Calculate the matrix element for an incoming anti-fermion * @param spbIn A vector of SpinorBarWaveFunctions for the incoming anti-fermion * @param vecIn A vector of VectorWaveFunctions for the incoming boson * @param spOut A vector of Spinors for the outgoing antifermion * @param vecOut A vector of VectorWaveFunctions for the outgoing boson * @param mc If the outgoing vector is massless or not * @param first Whether or not first call to decide if colour decomposition etc * should be calculated * @param mesq The matrix element squared */ ProductionMatrixElement fbv2vfbHeME(const SpinorBarVector & spbIn, const VBVector & vecIn, const VBVector & vecOut, bool mc, const SpinorVector & spOut, double & mesq, bool first) const; //@} protected: /** * A debugging function to test the value of me2 against an * analytic function. * @param me2 The value of the \f$ |\bar{\mathcal{M}}|^2 \f$ */ virtual void debug(double me2) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const {return new_ptr(*this);} /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const {return new_ptr(*this);} //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MEfv2vf & operator=(const MEfv2vf &); private: /** @name Store dynamically casted vertices. */ //@{ /** * A pair off FFVVertex pointers */ vector > fermion_; /** * A pair of FFVVertex, VVVertex pointers */ vector > vector_; - //@} + + /** + * Four point vertices + */ + vector four_; + //@} }; } #endif /* HERWIG_MEfv2vf_H */ diff --git a/MatrixElement/General/MEvv2ff.cc b/MatrixElement/General/MEvv2ff.cc --- a/MatrixElement/General/MEvv2ff.cc +++ b/MatrixElement/General/MEvv2ff.cc @@ -1,280 +1,316 @@ // -*- C++ -*- // // MEvv2ff.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 MEvv2ff class. // #include "MEvv2ff.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; using ThePEG::Helicity::TensorWaveFunction; using ThePEG::Helicity::incoming; using ThePEG::Helicity::outgoing; void MEvv2ff::doinit() { GeneralHardME::doinit(); scalar_ .resize(numberOfDiags()); fermion_.resize(numberOfDiags()); vector_ .resize(numberOfDiags()); + RSfermion_.resize(numberOfDiags()); tensor_ .resize(numberOfDiags()); + four_ .resize(numberOfDiags()); initializeMatrixElements(PDT::Spin1 , PDT::Spin1, PDT::Spin1Half, PDT::Spin1Half); for( size_t i = 0; i < numberOfDiags(); ++i ) { HPDiagram dg = getProcessInfo()[i]; if( dg.channelType == HPDiagram::tChannel ) { - AbstractFFVVertexPtr ffv1 = - dynamic_ptr_cast(dg.vertices.first); - AbstractFFVVertexPtr ffv2 = - dynamic_ptr_cast(dg.vertices.second); - fermion_[i] = make_pair(ffv1, ffv2); + if( dg.intermediate->iSpin() == PDT::Spin1Half ) { + AbstractFFVVertexPtr ffv1 = + dynamic_ptr_cast(dg.vertices.first); + AbstractFFVVertexPtr ffv2 = + dynamic_ptr_cast(dg.vertices.second); + fermion_[i] = make_pair(ffv1, ffv2); + } + else if( dg.intermediate->iSpin() == PDT::Spin3Half ) { + AbstractRFVVertexPtr rfv1 = + dynamic_ptr_cast(dg.vertices.first); + AbstractRFVVertexPtr rfv2 = + dynamic_ptr_cast(dg.vertices.second); + RSfermion_[i] = make_pair(rfv1, rfv2); + } + else + assert(false); } else if( dg.channelType == HPDiagram::sChannel ) { if( dg.intermediate->iSpin() == PDT::Spin0 ) { AbstractVVSVertexPtr vvs = dynamic_ptr_cast(dg.vertices.first ); AbstractFFSVertexPtr ffs = dynamic_ptr_cast(dg.vertices.second); scalar_[i] = make_pair(vvs,ffs); } else if( dg.intermediate->iSpin() == PDT::Spin1) { AbstractVVVVertexPtr vvv = dynamic_ptr_cast(dg.vertices.first); AbstractFFVVertexPtr ffv = dynamic_ptr_cast(dg.vertices.second); vector_[i] = make_pair(vvv,ffv); } else if(dg.intermediate->iSpin() == PDT::Spin2) { AbstractVVTVertexPtr vvt = dynamic_ptr_cast(dg.vertices.first); AbstractFFTVertexPtr fft = dynamic_ptr_cast(dg.vertices.second); tensor_[i] = make_pair(vvt,fft); } } + else if ( dg.channelType == HPDiagram::fourPoint) { + four_[i] = dynamic_ptr_cast(dg.vertices.first); + } } } double MEvv2ff::me2() const { // Set up wavefuctions VBVector v1(2), v2(2); SpinorVector sp(2); SpinorBarVector sbar(2); for( size_t i = 0; i < 2; ++i ) { v1[i] = VectorWaveFunction(rescaledMomenta()[0],mePartonData()[0], 2*i, - incoming); + incoming); v2[i] = VectorWaveFunction(rescaledMomenta()[1],mePartonData()[1], 2*i, - incoming); + incoming); sbar[i] = SpinorBarWaveFunction(rescaledMomenta()[2], mePartonData()[2], i, outgoing); sp[i] = SpinorWaveFunction(rescaledMomenta()[3], mePartonData()[3], i, outgoing); } double full_me(0.); vv2ffME(v1, v2, sbar, sp, full_me,true); #ifndef NDEBUG if( debugME() ) debug(full_me); #endif return full_me; } ProductionMatrixElement MEvv2ff::vv2ffME(const VBVector & v1, const VBVector & v2, const SpinorBarVector & sbar,const SpinorVector & sp, double & me2, bool first) const { - const Energy mass = sp[0].mass(); const Energy2 q2 = scale(); // weights for the selection of the diagram vector me(numberOfDiags(), 0.); // weights for the selection of the colour flow vector flow(numberOfFlows(),0.); //sum over vector helicities for(unsigned int iv1 = 0; iv1 < 2; ++iv1) { for(unsigned int iv2 = 0; iv2 < 2; ++iv2) { //sum over fermion helicities for(unsigned int of1 = 0; of1 < 2; ++of1) { for(unsigned int of2 = 0; of2 < 2; ++of2) { vector flows(numberOfFlows(),0.); for(HPCount ix = 0; ix < numberOfDiags(); ++ix) { Complex diag(0.); const HPDiagram & current = getProcessInfo()[ix]; PDPtr offshell = current.intermediate; - if(current.channelType == HPDiagram::tChannel && - offshell->iSpin() == PDT::Spin1Half) { - if(current.ordered.second) { - SpinorBarWaveFunction interF = fermion_[ix].first-> - evaluate(q2, 3, offshell, sbar[of1], v1[iv1], mass); - diag = fermion_[ix].second-> - evaluate(q2, sp[of2], interF, v2[iv2]); + if(current.channelType == HPDiagram::tChannel) { + if(offshell->iSpin() == PDT::Spin1Half) { + if(current.ordered.second) { + SpinorBarWaveFunction interF = fermion_[ix].first-> + evaluate(q2, 3, offshell, sbar[of1], v1[iv1]); + diag = fermion_[ix].second-> + evaluate(q2, sp[of2], interF, v2[iv2]); + } + else { + SpinorWaveFunction interF = fermion_[ix].first-> + evaluate(q2, 3, offshell, sp[of2], v1[iv1]); + diag = fermion_[ix].second-> + evaluate(q2, interF, sbar[of1], v2[iv2]); + } } - else { - SpinorWaveFunction interF = fermion_[ix].second-> - evaluate(q2, 3, offshell, sp[of2], v1[iv1], mass); - diag = fermion_[ix].first-> - evaluate(q2, interF, sbar[of1], v2[iv2]); + else if (offshell->iSpin() == PDT::Spin3Half) { + if(current.ordered.second) { + RSSpinorBarWaveFunction interF = RSfermion_[ix].first-> + evaluate(q2, 3, offshell, sbar[of1], v1[iv1]); + diag = RSfermion_[ix].second-> + evaluate(q2, sp[of2], interF, v2[iv2]); + } + else { + RSSpinorWaveFunction interF = RSfermion_[ix].first-> + evaluate(q2, 3, offshell, sp[of2], v1[iv1]); + diag = RSfermion_[ix].second-> + evaluate(q2, interF, sbar[of1], v2[iv2]); + } } + else + assert(false); } else if(current.channelType == HPDiagram::sChannel) { if(offshell->iSpin() == PDT::Spin0) { ScalarWaveFunction interS = scalar_[ix].first-> evaluate(q2, 1, offshell, v1[iv1], v2[iv2]); diag = scalar_[ix].second-> evaluate(q2, sp[of2], sbar[of1], interS); } else if(offshell->iSpin() == PDT::Spin1) { VectorWaveFunction interV = vector_[ix].first-> evaluate(q2, 1, offshell, v1[iv1], v2[iv2]); diag = vector_[ix].second-> evaluate(q2, sp[of2], sbar[of1], interV); } else if(offshell->iSpin() == PDT::Spin2) { TensorWaveFunction interT = tensor_[ix].first-> evaluate(q2, 1, offshell, v1[iv1], v2[iv2]); diag = tensor_[ix].second-> evaluate(q2, sp[of2], sbar[of1], interT); } } - else diag = 0.; + else if(current.channelType == HPDiagram::fourPoint) { + diag = four_[ix]->evaluate(q2, sp[of2], sbar[of1], v1[iv1], v2[iv2]); + } + else + assert(false); me[ix] += norm(diag); diagramME()[ix](2*iv1, 2*iv2, of1, of2) = diag; //Compute flows for(size_t iy = 0; iy < current.colourFlow.size(); ++iy) { assert(current.colourFlow[iy].first> scalar_ >> fermion_ >> vector_ >> tensor_; + is >> scalar_ >> fermion_ >> vector_ >> RSfermion_ >> tensor_ >> four_; initializeMatrixElements(PDT::Spin1 , PDT::Spin1, PDT::Spin1Half, PDT::Spin1Half); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigMEvv2ff("Herwig::MEvv2ff", "Herwig.so"); void MEvv2ff::Init() { static ClassDocumentation documentation ("The MEvv2ff class handles the ME calculation for the general " "spin configuration vector-vector to fermion-antifermion\n."); } void MEvv2ff::constructVertex(tSubProPtr sub) { ParticleVector ext = hardParticles(sub); // wavefunction with real momenta VBVector v1, v2; VectorWaveFunction(v1, ext[0], incoming, false, true); VectorWaveFunction(v2, ext[1], incoming, false, true); SpinorBarVector sbar; SpinorBarWaveFunction(sbar, ext[2], outgoing, true); SpinorVector sp; SpinorWaveFunction(sp, ext[3], outgoing, true); // rescale momenta setRescaledMomenta(ext); // wavefuncions with rescaled momenta VectorWaveFunction v1r(rescaledMomenta()[0], ext[0]->dataPtr(), incoming); VectorWaveFunction v2r(rescaledMomenta()[1], ext[1]->dataPtr(), incoming); SpinorBarWaveFunction sbr(rescaledMomenta()[2], ext[2]->dataPtr(), outgoing); SpinorWaveFunction spr(rescaledMomenta()[3], ext[3]->dataPtr(), outgoing); for( unsigned int ihel = 0; ihel < 2; ++ihel ) { v1r.reset(2*ihel); v1[ihel] = v1r; v2r.reset(2*ihel); v2[ihel] = v2r; sbr.reset(ihel); sbar[ihel] = sbr; spr.reset(ihel); sp[ihel] = spr; } double dummy(0.); ProductionMatrixElement pme = vv2ffME(v1, v2, sbar, sp, dummy,false); #ifndef NDEBUG if( debugME() ) debug(dummy); #endif createVertex(pme,ext); } void MEvv2ff::debug(double me2) const { if( !generator()->logfile().is_open() ) return; long id3(abs(mePartonData()[2]->id())), id4(abs(mePartonData()[3]->id())); if( mePartonData()[0]->id() != 21 || mePartonData()[1]->id() != 21 || id3 != id4 || (id3 != 1000021 && id3 != 5100002 && id3 != 5100001 && id3 != 6100002 && id3 != 6100001) ) return; tcSMPtr sm = generator()->standardModel(); double gs4 = sqr( 4.*Constants::pi*sm->alphaS(scale()) ); int Nc = sm->Nc(); Energy2 s(sHat()); Energy2 mf2 = meMomenta()[2].m2(); Energy4 spt2 = uHat()*tHat() - sqr(mf2); Energy2 t3(tHat() - mf2), u4(uHat() - mf2); double analytic(0.); if( id3 == 1000021 ) { analytic = gs4*sqr(Nc)*u4*t3* ( sqr(u4) + sqr(t3) + 4.*mf2*s*spt2/u4/t3 ) * ( 1./sqr(s*t3) + 1./sqr(s*u4) + 1./sqr(u4*t3) )/2./(Nc*Nc - 1.); } else { double brac = sqr(s)/6./t3/u4 - 3./8.; analytic = gs4*( -4.*sqr(mf2)*brac/t3/u4 + 4.*mf2*brac/s + brac - 1./3. + 3.*t3*u4/4/s/s); } double diff = abs(analytic - me2); if( diff > 1e-4 ) { generator()->log() << mePartonData()[0]->PDGName() << "," << mePartonData()[1]->PDGName() << "->" << mePartonData()[2]->PDGName() << "," << mePartonData()[3]->PDGName() << " difference: " << setprecision(10) << diff << " ratio: " << analytic/me2 << '\n'; } } diff --git a/MatrixElement/General/MEvv2ff.h b/MatrixElement/General/MEvv2ff.h --- a/MatrixElement/General/MEvv2ff.h +++ b/MatrixElement/General/MEvv2ff.h @@ -1,187 +1,198 @@ // -*- C++ -*- // // MEvv2ff.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_MEvv2ff_H #define HERWIG_MEvv2ff_H // // This is the declaration of the MEvv2ff class. // #include "GeneralHardME.h" #include "ThePEG/Helicity/Vertex/AbstractFFSVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVVSVertex.h" #include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractRFVVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVVVVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVVTVertex.h" #include "ThePEG/Helicity/Vertex/AbstractFFTVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractFFVVVertex.h" #include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "Herwig/MatrixElement/ProductionMatrixElement.h" namespace Herwig { using namespace ThePEG; using ThePEG::Helicity::SpinorWaveFunction; using ThePEG::Helicity::SpinorBarWaveFunction; using ThePEG::Helicity::VectorWaveFunction; /** * This class is designed to implement the matrix element for the * \f$2 \rightarrow 2\f$ process vector-vector to fermion-antifermion pair. It * inherits from GeneralHardME and implements the me2() virtual function. * - * @see \ref MEvv2ffInterfaces "The Interfaces" - * defined for MEvv2ff. * @see GeneralHardME * */ class MEvv2ff: public GeneralHardME { public: /** A Vector of VectorWaveFunction objects. */ typedef vector VBVector; /** A vector of SpinorBarWaveFunction objects. */ typedef vector SpinorVector; /** A vector of SpinorBarWaveFunction objects. */ typedef vector SpinorBarVector; public: /** @name Virtual functions required by the MEBase class. */ //@{ /** * The matrix element for the kinematical configuration * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. * @return the matrix element scaled with sHat() to give a * dimensionless number. */ virtual double me2() const; //@} /** * Construct the vertex information for the spin correlations * @param sub Pointer to the relevent SubProcess */ virtual void constructVertex(tSubProPtr sub); private: /** * Calculate the value of the matrix element */ ProductionMatrixElement vv2ffME(const VBVector & v1, const VBVector & v2, const SpinorBarVector & sbar, const SpinorVector & sp, double & me2, bool first) const; protected: /** * A debugging function to test the value of me2 against an * analytic function. * @param me2 The value of the \f$ |\bar{\mathcal{M}}|^2 \f$ */ virtual void debug(double me2) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const {return new_ptr(*this);} /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const {return new_ptr(*this);} //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MEvv2ff & operator=(const MEvv2ff &); private: /** @name Dynamically casted vertices. */ //@{ /** * Intermediate scalar */ vector > scalar_; + /** * Intermediate fermion */ vector > fermion_; /** * Intermediate vector */ vector > vector_; /** + * Intermediate RS fermion + */ + vector > RSfermion_; + + /** * Intermediate tensor */ vector > tensor_; + + /** + * Four point vertices + */ + vector four_; //@} }; } #endif /* HERWIG_MEvv2ff_H */ diff --git a/MatrixElement/General/MEvv2rf.cc b/MatrixElement/General/MEvv2rf.cc new file mode 100644 --- /dev/null +++ b/MatrixElement/General/MEvv2rf.cc @@ -0,0 +1,377 @@ +// -*- C++ -*- +// +// This is the implementation of the non-inlined, non-templated member +// functions of the MEvv2rf class. +// + +#include "MEvv2rf.h" +#include "ThePEG/Interface/ClassDocumentation.h" +#include "ThePEG/Utilities/DescribeClass.h" +#include "ThePEG/Persistency/PersistentOStream.h" +#include "ThePEG/Persistency/PersistentIStream.h" + +using namespace Herwig; +using ThePEG::Helicity::incoming; +using ThePEG::Helicity::outgoing; + +IBPtr MEvv2rf::clone() const { + return new_ptr(*this); +} + +IBPtr MEvv2rf::fullclone() const { + return new_ptr(*this); +} + +void MEvv2rf::doinit() { + GeneralHardME::doinit(); + scalar_ .resize(numberOfDiags()); + fermion_.resize(numberOfDiags()); + vector_ .resize(numberOfDiags()); + four_ .resize(numberOfDiags()); + initializeMatrixElements(PDT::Spin1 , PDT::Spin1, + PDT::Spin3Half, PDT::Spin1Half); + + for( size_t i = 0; i < numberOfDiags(); ++i ) { + HPDiagram dg = getProcessInfo()[i]; + if( dg.channelType == HPDiagram::tChannel ) { + AbstractRFVVertexPtr rfv; + AbstractFFVVertexPtr ffv; + if(dg.ordered.second) { + rfv = dynamic_ptr_cast(dg.vertices.first); + ffv = dynamic_ptr_cast(dg.vertices.second); + } + else { + rfv = dynamic_ptr_cast(dg.vertices.second); + ffv = dynamic_ptr_cast(dg.vertices.first ); + } + fermion_[i] = make_pair(rfv, ffv); + } + else if( dg.channelType == HPDiagram::sChannel ) { + if( dg.intermediate->iSpin() == PDT::Spin0 ) { + AbstractVVSVertexPtr vvs = + dynamic_ptr_cast(dg.vertices.first ); + AbstractRFSVertexPtr rfs = + dynamic_ptr_cast(dg.vertices.second); + scalar_[i] = make_pair(vvs,rfs); + } + else if( dg.intermediate->iSpin() == PDT::Spin1) { + AbstractVVVVertexPtr vvv = + dynamic_ptr_cast(dg.vertices.first); + AbstractRFVVertexPtr rfv = + dynamic_ptr_cast(dg.vertices.second); + vector_[i] = make_pair(vvv,rfv); + } + } + else if ( dg.channelType == HPDiagram::fourPoint) { + four_[i] = dynamic_ptr_cast(dg.vertices.first); + } + } +} + +void MEvv2rf::persistentOutput(PersistentOStream & os) const { + os << scalar_ << fermion_ << vector_ << four_; +} + +void MEvv2rf::persistentInput(PersistentIStream & is, int) { + is >> scalar_ >> fermion_ >> vector_ >> four_; + initializeMatrixElements(PDT::Spin1 , PDT::Spin1, + PDT::Spin3Half, PDT::Spin1Half); +} + +//The following static variable is needed for the type +// description system in ThePEG. +DescribeClass +describeHerwigMEvv2rf("Herwig::MEvv2rf", "Herwig.so"); + +void MEvv2rf::Init() { + + static ClassDocumentation documentation + ("The MEvv2rf class handes the ME calculation for vv -> rf"); + +} + +double MEvv2rf::me2() const { + // set up the vector wavefunctions + VBVector v1(2), v2(2); + for( size_t i = 0; i < 2; ++i ) { + v1[i] = VectorWaveFunction(rescaledMomenta()[0],mePartonData()[0], 2*i, + incoming); + v2[i] = VectorWaveFunction(rescaledMomenta()[1],mePartonData()[1], 2*i, + incoming); + } + // setup spinor wavefunctions and decide which case to use + bool massless = mePartonData()[2]->mass()==ZERO; + double full_me(0.); + if(mePartonData()[2]->id()<0) { + RSSpinorVector sp(4); SpinorBarVector sbar(2); + for( size_t i = 0; i < 4; ++i ) { + if(massless && (i==2||i==3)) continue; + sp[i] = RSSpinorWaveFunction(rescaledMomenta()[2], mePartonData()[2], i, + outgoing); + } + for( size_t i = 0; i < 2; ++i ) { + sbar[i] = SpinorBarWaveFunction(rescaledMomenta()[3], mePartonData()[3], i, + outgoing); + } + vv2frME(v1, v2, sbar, sp, full_me,true); + } + else { + SpinorVector sp(2); RSSpinorBarVector sbar(4); + for( size_t i = 0; i < 4; ++i ) { + if(massless && (i==2||i==3)) continue; + sbar[i] = RSSpinorBarWaveFunction(rescaledMomenta()[2], mePartonData()[2], i, + outgoing); + } + for( size_t i = 0; i < 2; ++i ) { + sp[i] = SpinorWaveFunction(rescaledMomenta()[3], mePartonData()[3], i, + outgoing); + } + vv2rfME(v1, v2, sbar, sp, full_me,true); + } + return full_me; +} + +ProductionMatrixElement +MEvv2rf::vv2rfME(const VBVector & v1, const VBVector & v2, + const RSSpinorBarVector & sbar,const SpinorVector & sp, + double & me2, bool first) const { + // scale + const Energy2 q2 = scale(); + // whether or not rs fermion is massless + bool massless = mePartonData()[2]->mass()==ZERO; + // weights for the selection of the diagram + vector me(numberOfDiags(), 0.); + // weights for the selection of the colour flow + vector flow(numberOfFlows(),0.); + //sum over vector helicities + for(unsigned int iv1 = 0; iv1 < 2; ++iv1) { + for(unsigned int iv2 = 0; iv2 < 2; ++iv2) { + //sum over fermion helicities + for(unsigned int of1 = 0; of1 < 4; ++of1) { + if(massless && (of1==1 || of1==2) ) continue; + for(unsigned int of2 = 0; of2 < 2; ++of2) { + vector flows(numberOfFlows(),0.); + for(HPCount ix = 0; ix < numberOfDiags(); ++ix) { + Complex diag(0.); + const HPDiagram & current = getProcessInfo()[ix]; + tPDPtr offshell = current.intermediate; + if(current.channelType == HPDiagram::tChannel && + offshell->iSpin() == PDT::Spin1Half) { + if(current.ordered.second) { + SpinorBarWaveFunction interF = fermion_[ix].first-> + evaluate(q2, 3, offshell, sbar[of1], v1[iv1]); + diag = fermion_[ix].second-> + evaluate(q2, sp[of2], interF, v2[iv2]); + } + else { + SpinorWaveFunction interF = fermion_[ix].second-> + evaluate(q2, 3, offshell, sp[of2], v1[iv1]); + diag = fermion_[ix].first-> + evaluate(q2, interF, sbar[of1], v2[iv2]); + } + } + else if(current.channelType == HPDiagram::sChannel) { + if(offshell->iSpin() == PDT::Spin0) { + ScalarWaveFunction interS = scalar_[ix].first-> + evaluate(q2, 1, offshell, v1[iv1], v2[iv2]); + diag = scalar_[ix].second-> + evaluate(q2, sp[of2], sbar[of1], interS); + } + else if(offshell->iSpin() == PDT::Spin1) { + VectorWaveFunction interV = vector_[ix].first-> + evaluate(q2, 1, offshell, v1[iv1], v2[iv2]); + diag = vector_[ix].second-> + evaluate(q2, sp[of2], sbar[of1], interV); + } + } + else if(current.channelType == HPDiagram::fourPoint) { + diag = four_[ix]->evaluate(q2, sp[of2], sbar[of1], v1[iv1], v2[iv2]); + } + else + assert(false); + me[ix] += norm(diag); + diagramME()[ix](2*iv1, 2*iv2, of1, of2) = diag; + //Compute flows + for(size_t iy = 0; iy < current.colourFlow.size(); ++iy) { + assert(current.colourFlow[iy].firstmass()==ZERO; + // weights for the selection of the diagram + vector me(numberOfDiags(), 0.); + // weights for the selection of the colour flow + vector flow(numberOfFlows(),0.); + //sum over vector helicities + for(unsigned int iv1 = 0; iv1 < 2; ++iv1) { + for(unsigned int iv2 = 0; iv2 < 2; ++iv2) { + //sum over fermion helicities + for(unsigned int of1 = 0; of1 < 4; ++of1) { + for(unsigned int of2 = 0; of2 < 2; ++of2) { + if(massless && (of2==1 || of2==2) ) continue; + vector flows(numberOfFlows(),0.); + for(HPCount ix = 0; ix < numberOfDiags(); ++ix) { + Complex diag(0.); + const HPDiagram & current = getProcessInfo()[ix]; + tPDPtr offshell = current.intermediate; + if(current.channelType == HPDiagram::tChannel && + offshell->iSpin() == PDT::Spin1Half) { + if(current.ordered.second) { + SpinorWaveFunction interF = fermion_[ix].first-> + evaluate(q2, 3, offshell, sp[of2], v1[iv1]); + diag = fermion_[ix].second-> + evaluate(q2, interF, sbar[of1],v2[iv2]); + } + else { + SpinorBarWaveFunction interF = fermion_[ix].second-> + evaluate(q2, 3, offshell, sbar[of1], v1[iv1]); + diag = fermion_[ix].first-> + evaluate(q2, sp[of2], interF, v2[iv2]); + } + } + else if(current.channelType == HPDiagram::sChannel) { + if(offshell->iSpin() == PDT::Spin0) { + ScalarWaveFunction interS = scalar_[ix].first-> + evaluate(q2, 1, offshell, v1[iv1], v2[iv2]); + diag = scalar_[ix].second-> + evaluate(q2, sp[of2], sbar[of1], interS); + } + else if(offshell->iSpin() == PDT::Spin1) { + VectorWaveFunction interV = vector_[ix].first-> + evaluate(q2, 1, offshell, v1[iv1], v2[iv2]); + diag = vector_[ix].second-> + evaluate(q2, sp[of2], sbar[of1], interV); + } + } + else if(current.channelType == HPDiagram::fourPoint) { + diag = four_[ix]->evaluate(q2, sp[of2], sbar[of1], v1[iv1], v2[iv2]); + } + else + assert(false); + me[ix] += norm(diag); + diagramME()[ix](2*iv1, 2*iv2, of2, of1) = diag; + //Compute flows + for(size_t iy = 0; iy < current.colourFlow.size(); ++iy) { + assert(current.colourFlow[iy].firstdataPtr(), incoming); + VectorWaveFunction v2r(rescaledMomenta()[1], + ext[1]->dataPtr(), incoming); + ProductionMatrixElement pme; + for( unsigned int ihel = 0; ihel < 2; ++ihel ) { + v1r.reset(2*ihel); + v1[ihel] = v1r; + v2r.reset(2*ihel); + v2[ihel] = v2r; + } + // setup spinor wavefunctions and decide which case to use + bool massless = mePartonData()[2]->mass()==ZERO; + double dummy(0.); + if(ext[2]->id()<0) { + RSSpinorVector sp; + RSSpinorWaveFunction(sp, ext[2], outgoing, true); + SpinorBarVector sbar; + SpinorBarWaveFunction(sbar, ext[3], outgoing, true); + // wavefuncions with rescaled momenta + SpinorBarWaveFunction sbr(rescaledMomenta()[3], + ext[3]->dataPtr(), outgoing); + RSSpinorWaveFunction spr(rescaledMomenta()[2], + ext[2]->dataPtr(), outgoing); + for( unsigned int ihel = 0; ihel < 2; ++ihel ) { + sbr.reset(ihel); + sbar[ihel] = sbr; + } + for( unsigned int ihel = 0; ihel < 4; ++ihel ) { + if(massless && (ihel==1 || ihel==2)) continue; + spr.reset(ihel); + sp[ihel] = spr; + } + pme = vv2frME(v1, v2, sbar, sp, dummy,false); + } + else { + SpinorVector sp; + SpinorWaveFunction(sp, ext[3], outgoing, true); + RSSpinorBarVector sbar; + RSSpinorBarWaveFunction(sbar, ext[2], outgoing, true); + // wavefuncions with rescaled momenta + RSSpinorBarWaveFunction sbr(rescaledMomenta()[2], + ext[2]->dataPtr(), outgoing); + SpinorWaveFunction spr(rescaledMomenta()[3], + ext[3]->dataPtr(), outgoing); + for( unsigned int ihel = 0; ihel < 4; ++ihel ) { + if(massless && (ihel==1 || ihel==2)) continue; + sbr.reset(ihel); + sbar[ihel] = sbr; + } + for( unsigned int ihel = 0; ihel < 2; ++ihel ) { + spr.reset(ihel); + sp[ihel] = spr; + } + pme = vv2rfME(v1, v2, sbar, sp, dummy,false); + } + createVertex(pme,ext); +} diff --git a/MatrixElement/General/MEvv2rf.h b/MatrixElement/General/MEvv2rf.h new file mode 100644 --- /dev/null +++ b/MatrixElement/General/MEvv2rf.h @@ -0,0 +1,182 @@ +// -*- C++ -*- +#ifndef Herwig_MEvv2rf_H +#define Herwig_MEvv2rf_H +// +// This is the declaration of the MEvv2rf class. +// + +#include "GeneralHardME.h" +#include "ThePEG/Helicity/Vertex/AbstractRFSVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractVVSVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractRFVVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractVVVVertex.h" +#include "ThePEG/Helicity/Vertex/AbstractRFVVVertex.h" +#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" +#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" +#include "ThePEG/Helicity/WaveFunction/RSSpinorWaveFunction.h" +#include "ThePEG/Helicity/WaveFunction/RSSpinorBarWaveFunction.h" +#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" +#include "Herwig/MatrixElement/ProductionMatrixElement.h" + +namespace Herwig { + +using namespace ThePEG; + +/** + * This class is designed to implement the matrix element for the + * \f$2 \rightarrow 2\f$ process vector-vector to fermion- RS fermion. It + * inherits from GeneralHardME and implements the me2() virtual function. + * + * @see GeneralHardME + * + */ +class MEvv2rf: public GeneralHardME { + +public: + + /** A Vector of VectorWaveFunction objects. */ + typedef vector VBVector; + + /** A vector of SpinorBarWaveFunction objects. */ + typedef vector SpinorVector; + + /** A vector of SpinorBarWaveFunction objects. */ + typedef vector SpinorBarVector; + + /** A vector of SpinorBarWaveFunction objects. */ + typedef vector RSSpinorVector; + + /** A vector of SpinorBarWaveFunction objects. */ + typedef vector RSSpinorBarVector; + +public: + + /** @name Virtual functions required by the MEBase class. */ + //@{ + /** + * The matrix element for the kinematical configuration + * previously provided by the last call to setKinematics(), suitably + * scaled by sHat() to give a dimension-less number. + * @return the matrix element scaled with sHat() to give a + * dimensionless number. + */ + virtual double me2() const; + //@} + + /** + * Construct the vertex information for the spin correlations + * @param sub Pointer to the relevent SubProcess + */ + virtual void constructVertex(tSubProPtr sub); + +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: + + /** + * Calculate the value of the matrix element + */ + ProductionMatrixElement vv2rfME(const VBVector & v1, const VBVector & v2, + const RSSpinorBarVector & sbar, + const SpinorVector & sp, + double & me2, bool first) const; + + /** + * Calculate the value of the matrix element + */ + ProductionMatrixElement vv2frME(const VBVector & v1, const VBVector & v2, + const SpinorBarVector & sbar, + const RSSpinorVector & sp, + double & me2, bool first) const; + +private: + + /** + * The assignment operator is private and must never be called. + * In fact, it should not even be implemented. + */ + MEvv2rf & operator=(const MEvv2rf &); +private: + + /** @name Dynamically casted vertices. */ + //@{ + /** + * Intermediate scalar + */ + vector > scalar_; + + /** + * Intermediate fermion + */ + vector > fermion_; + + /** + * Intermediate vector + */ + vector > vector_; + + /** + * Four point vertices + */ + vector four_; + //@} + +}; + +} + +#endif /* Herwig_MEvv2rf_H */ diff --git a/MatrixElement/General/MEvv2ss.cc b/MatrixElement/General/MEvv2ss.cc --- a/MatrixElement/General/MEvv2ss.cc +++ b/MatrixElement/General/MEvv2ss.cc @@ -1,312 +1,313 @@ // -*- C++ -*- // // MEvv2ss.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 MEvv2ss class. // #include "MEvv2ss.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; using ThePEG::Helicity::TensorWaveFunction; using ThePEG::Helicity::incoming; using ThePEG::Helicity::outgoing; void MEvv2ss::doinit() { GeneralHardME::doinit(); scalar1_.resize(numberOfDiags()); scalar2_.resize(numberOfDiags()); scalar3_.resize(numberOfDiags()); vector_ .resize(numberOfDiags()); tensor_ .resize(numberOfDiags()); + contact_.resize(numberOfDiags()); initializeMatrixElements(PDT::Spin1, PDT::Spin1, PDT::Spin0, PDT::Spin0); for(size_t i = 0; i < numberOfDiags(); ++i ) { HPDiagram dg = getProcessInfo()[i]; if( !dg.intermediate ) { - contact_ = dynamic_ptr_cast(dg.vertices.first); + contact_[i] = dynamic_ptr_cast(dg.vertices.first); } else if(dg.channelType == HPDiagram::tChannel) { if (dg.intermediate->iSpin() == PDT::Spin0 ) { AbstractVSSVertexPtr vss1 = dynamic_ptr_cast(dg.vertices.first); AbstractVSSVertexPtr vss2 = dynamic_ptr_cast(dg.vertices.second); scalar2_[i] = make_pair(vss1, vss2); } else if( dg.intermediate->iSpin() == PDT::Spin1 ) { AbstractVVSVertexPtr vvs1 = dynamic_ptr_cast(dg.vertices.first); AbstractVVSVertexPtr vvs2 = dynamic_ptr_cast(dg.vertices.second); scalar3_[i] = make_pair(vvs1, vvs2); } else assert(false); } else { if( dg.intermediate->iSpin() == PDT::Spin0 ) { AbstractVVSVertexPtr vvs = dynamic_ptr_cast(dg.vertices.first); AbstractSSSVertexPtr sss = dynamic_ptr_cast(dg.vertices.second); scalar1_[i] = make_pair(vvs, sss); } else if( dg.intermediate->iSpin() == PDT::Spin1 ) { AbstractVVVVertexPtr vvv = dynamic_ptr_cast(dg.vertices.first); AbstractVSSVertexPtr vss = dynamic_ptr_cast(dg.vertices.second); vector_[i] = make_pair(vvv, vss); } else if( dg.intermediate->iSpin() == PDT::Spin2 ) { AbstractVVTVertexPtr vvt = dynamic_ptr_cast(dg.vertices.first); AbstractSSTVertexPtr sst = dynamic_ptr_cast(dg.vertices.second); tensor_[i] = make_pair(vvt, sst); } } } } double MEvv2ss::me2() const { VBVector v1(2), v2(2); for( size_t i = 0; i < 2; ++i ) { v1[i] = VectorWaveFunction(rescaledMomenta()[0],mePartonData()[0], 2*i, incoming); v2[i] = VectorWaveFunction(rescaledMomenta()[1],mePartonData()[1], 2*i, incoming); } ScalarWaveFunction sca1(rescaledMomenta()[2],mePartonData()[2], Complex(1.,0.),outgoing); ScalarWaveFunction sca2(rescaledMomenta()[3],mePartonData()[3], Complex(1.,0.),outgoing); double full_me(0.); vv2ssME(v1, v2, sca1, sca2, full_me , true); #ifndef NDEBUG if( debugME() ) debug(full_me); #endif return full_me; } ProductionMatrixElement MEvv2ss::vv2ssME(const VBVector & v1, const VBVector & v2, const ScalarWaveFunction & sca1, const ScalarWaveFunction & sca2, double & me2, bool first) const { const Energy2 m2(scale()); const Energy masst = sca1.mass(), massu = sca2.mass(); // weights for the selection of the diagram vector me(numberOfDiags(), 0.); // weights for the selection of the colour flow vector flow(numberOfFlows(),0.); //loop over vector helicities for(unsigned int iv1 = 0; iv1 < 2; ++iv1) { for(unsigned int iv2 = 0; iv2 < 2; ++iv2) { vector flows(numberOfFlows(),0.); // loop over diagrams for(HPCount ix = 0; ix < numberOfDiags(); ++ix) { Complex diag(0.); const HPDiagram & current = getProcessInfo()[ix]; // do four-point diag first if(current.channelType == HPDiagram::fourPoint) { - diag = contact_->evaluate(m2, v1[iv1], v2[iv2], sca1, sca2); + diag = contact_[ix]->evaluate(m2, v1[iv1], v2[iv2], sca1, sca2); } else { tcPDPtr offshell = current.intermediate; if(current.channelType == HPDiagram::tChannel) { if(offshell->iSpin() == PDT::Spin0) { if(current.ordered.second) { ScalarWaveFunction interS = scalar2_[ix].first-> evaluate(m2, 3, offshell, v1[iv1], sca1, masst); diag = scalar2_[ix].second->evaluate(m2, v2[iv2], interS, sca2); } else { ScalarWaveFunction interS = scalar2_[ix].first-> evaluate(m2, 3, offshell, v1[iv1], sca2, massu); diag = scalar2_[ix].second->evaluate(m2, v2[iv2], interS, sca1); } } else { if(current.ordered.second) { VectorWaveFunction interV = scalar3_[ix].first-> evaluate(m2, 3, offshell, v1[iv1], sca1); diag = scalar3_[ix].second->evaluate(m2, v2[iv2], interV, sca2); } else { VectorWaveFunction interV = scalar3_[ix].first-> evaluate(m2, 3, offshell, v1[iv1], sca2); diag = scalar3_[ix].second->evaluate(m2, v2[iv2], interV, sca1); } } } else if(current.channelType == HPDiagram::sChannel) { if(offshell->iSpin() == PDT::Spin0) { ScalarWaveFunction interS = scalar1_[ix].first-> evaluate(m2, 1, offshell, v1[iv1], v2[iv2]); diag = scalar1_[ix].second->evaluate(m2, interS, sca1, sca2); } else if(offshell->iSpin() == PDT::Spin1) { VectorWaveFunction interV = vector_[ix].first-> evaluate(m2, 1, offshell, v1[iv1], v2[iv2]); diag = vector_[ix].second->evaluate(m2, interV, sca1, sca2); } else if(offshell->iSpin() == PDT::Spin2) { TensorWaveFunction interT = tensor_[ix].first-> evaluate(m2, 1, offshell, v1[iv1], v2[iv2]); diag = tensor_[ix].second->evaluate(m2, sca1, sca2, interT); } } else diag = 0.; } me[ix] += norm(diag); diagramME()[ix](2*iv1, 2*iv2, 0, 0) = diag; //Compute flows for(size_t iy = 0; iy < current.colourFlow.size(); ++iy) { assert(current.colourFlow[iy].first> scalar1_ >> scalar2_ >> scalar3_ >> vector_ >> tensor_ >> contact_; initializeMatrixElements(PDT::Spin1, PDT::Spin1, PDT::Spin0, PDT::Spin0); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigMEvv2ss("Herwig::MEvv2ss", "Herwig.so"); void MEvv2ss::Init() { static ClassDocumentation documentation ("This class implements the ME for the vector-vector to scalar-scalar " "hard-process"); } void MEvv2ss::constructVertex(tSubProPtr sub) { ParticleVector ext = hardParticles(sub); VBVector v1, v2; // set up the wavefunctions with real momenta VectorWaveFunction(v1, ext[0], incoming, false, true); VectorWaveFunction(v2, ext[1], incoming, false, true); ScalarWaveFunction sca1(ext[2], outgoing, true); ScalarWaveFunction sca2(ext[3], outgoing, true); // calculate rescaled moment setRescaledMomenta(ext); // wavefunctions with rescaled momenta VectorWaveFunction v1r (rescaledMomenta()[0], ext[0]->dataPtr(), incoming); VectorWaveFunction v2r (rescaledMomenta()[1], ext[1]->dataPtr(), incoming); sca1 = ScalarWaveFunction(rescaledMomenta()[2], ext[2]->dataPtr(), outgoing); sca2 = ScalarWaveFunction(rescaledMomenta()[3], ext[3]->dataPtr(), outgoing); for( unsigned int ihel = 0; ihel < 2; ++ihel ) { v1r.reset(2*ihel); v1[ihel] = v1r; v2r.reset(2*ihel); v2[ihel] = v2r; } double dummy(0.); ProductionMatrixElement pme = vv2ssME(v1, v2, sca1, sca2, dummy , false); #ifndef NDEBUG if( debugME() ) debug(dummy); #endif createVertex(pme,ext); } void MEvv2ss::debug(double me2) const { if( !generator()->logfile().is_open() ) return; if( mePartonData()[0]->id() != 21 || mePartonData()[1]->id() != 21) return; long id3 = abs(mePartonData()[2]->id()); long id4 = abs(mePartonData()[3]->id()); int type = -1; //SUSY gg>~q~q if( ((id3 >= 1000001 && id3 <= 1000006 ) && (id4 >= 1000001 && id4 <= 1000006 ) ) || ((id3 >= 2000001 && id3 <= 2000006 ) && (id4 >= 2000001 && id4 <= 2000006 ) ) ) { type = 0; } // Sextet production else if(mePartonData()[2]->iColour() == PDT::Colour6 && mePartonData()[3]->iColour() == PDT::Colour6bar ) { type = 1; } else { return; } double gs4 = sqr( 4.*Constants::pi*SM().alphaS(scale())); int Nc = SM().Nc(); Energy4 s2 = sqr(sHat()); Energy2 m3s = meMomenta()[2].m2(); Energy2 m4s = meMomenta()[3].m2(); Energy4 spt2 = uHat()*tHat() - m3s*m4s; Energy2 t3 = tHat()-m3s, u4 = uHat()-m4s; Energy4 t3s = sqr(t3) , u4s = sqr(u4); Energy8 pre = gs4*(sqr(spt2) + s2*m3s*m4s); // matrix element double analytic(0.); // triplet scalars if(type==0) { analytic = pre*Nc* ( u4s + t3s - s2/sqr(Nc) )/2./(sqr(Nc) - 1.)/s2/t3s/u4s; } // sextet scalars else if(type==1) { analytic = pre*(Nc+2.)/(sqr(Nc)-1.)/Nc* ((Nc+2.)*(Nc-1.)/t3s/u4s - sqr(Nc)/t3/u4/s2); } double diff = abs(analytic - me2)/(analytic+me2); if( diff > 1e-10 ) { generator()->log() << mePartonData()[0]->PDGName() << "," << mePartonData()[1]->PDGName() << "->" << mePartonData()[2]->PDGName() << "," << mePartonData()[3]->PDGName() << " difference: " << setprecision(10) << diff << " ratio: " << analytic/me2 << '\n'; } } diff --git a/MatrixElement/General/MEvv2ss.h b/MatrixElement/General/MEvv2ss.h --- a/MatrixElement/General/MEvv2ss.h +++ b/MatrixElement/General/MEvv2ss.h @@ -1,199 +1,199 @@ // -*- C++ -*- // // MEvv2ss.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_MEvv2ss_H #define HERWIG_MEvv2ss_H // // This is the declaration of the MEvv2ss class. // #include "GeneralHardME.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h" #include "ThePEG/Helicity/Vertex/AbstractVVSVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVSSVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVVVVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVVTVertex.h" #include "ThePEG/Helicity/Vertex/AbstractSSTVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVVSSVertex.h" #include "ThePEG/Helicity/Vertex/AbstractSSSVertex.h" #include "Herwig/MatrixElement/ProductionMatrixElement.h" namespace Herwig { using namespace ThePEG; using ThePEG::Helicity::VectorWaveFunction; using ThePEG::Helicity::ScalarWaveFunction; /** * This is the implementation of the matrix element for the process * vector-vector to scalar-scalar. It inherits from GeneralHardME and * implements the required virtual functions. * * @see \ref MEff2ffInterfaces "The Interfaces" * defined for MEff2ff. * @see GeneralHardME */ class MEvv2ss: public GeneralHardME { public: /** A vector of VectorWaveFunction objects*/ typedef vector VBVector; public: /** @name Virtual functions required by the MEBase class. */ //@{ /** * The matrix element for the kinematical configuration * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. * @return the matrix element scaled with sHat() to give a * dimensionless number. */ virtual double me2() const; //@} /** * Set the Hardvertex for the spin correlations * @param sub */ virtual void constructVertex(tSubProPtr sub); private: /** * Calculate the matrix element. * @param v1 A vector of VectorWaveFunction objects for the first boson * @param v2 A vector of VectorWaveFunction objects for the second boson * @param sca1 A ScalarWaveFunction for the first outgoing * @param sca2 A ScalarWaveFunction for the second outgoing * @param me2 The value of the spin-summed matrix element squared * (to be calculated) * @param first Whether or not first call to decide if colour decomposition etc * should be calculated */ ProductionMatrixElement vv2ssME(const VBVector & v1, const VBVector & v2, const ScalarWaveFunction & sca1, const ScalarWaveFunction & sca2, double & me2, bool first) const; protected: /** * A debugging function to test the value of me2 against an * analytic function. * @param me2 The value of the \f$ |\bar{\mathcal{M}}|^2 \f$ */ virtual void debug(double me2) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const {return new_ptr(*this);} /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const {return new_ptr(*this);} //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MEvv2ss & operator=(const MEvv2ss &); private: /** @name The dynamically casted vertices. */ //@{ /** * Intermediate s-channel scalar */ vector > scalar1_; /** * Intermediate t-channel scalar */ vector > scalar2_; /** * Intermediate t-channel scalar */ vector > scalar3_; /** * Intermediate s-channel vector */ vector > vector_; /** * Intermediate s-channel tensor */ vector > tensor_; /** * The contact vertex */ - AbstractVVSSVertexPtr contact_; + vector contact_; //@} }; } #endif /* HERWIG_MEvv2ss_H */ diff --git a/MatrixElement/General/MEvv2vs.cc b/MatrixElement/General/MEvv2vs.cc --- a/MatrixElement/General/MEvv2vs.cc +++ b/MatrixElement/General/MEvv2vs.cc @@ -1,259 +1,260 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the MEvv2vs class. // #include "MEvv2vs.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; using ThePEG::Helicity::ScalarWaveFunction; using ThePEG::Helicity::VectorWaveFunction; using ThePEG::Helicity::incoming; using ThePEG::Helicity::outgoing; IBPtr MEvv2vs::clone() const { return new_ptr(*this); } IBPtr MEvv2vs::fullclone() const { return new_ptr(*this); } void MEvv2vs::persistentOutput(PersistentOStream & os) const { - os << scalar_ << vector_ << fourPointVertex_; + os << scalar_ << vector_ << four_; } void MEvv2vs::persistentInput(PersistentIStream & is, int) { - is >> scalar_ >> vector_ >> fourPointVertex_; + is >> scalar_ >> vector_ >> four_; initializeMatrixElements(PDT::Spin1, PDT::Spin1, PDT::Spin1, PDT::Spin0); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigMEvv2vs("Herwig::MEvv2vs", "Herwig.so"); void MEvv2vs::Init() { static ClassDocumentation documentation ("The MEvv2vs class implements the general matrix elements" " for vector vector -> vector scalar"); } void MEvv2vs::doinit() { GeneralHardME::doinit(); scalar_.resize(numberOfDiags()); vector_.resize(numberOfDiags()); + four_.resize(numberOfDiags()); initializeMatrixElements(PDT::Spin1, PDT::Spin1, PDT::Spin1, PDT::Spin0); for(size_t i = 0; i < numberOfDiags(); ++i) { HPDiagram diag = getProcessInfo()[i]; tcPDPtr offshell = diag.intermediate; if(!offshell) { - fourPointVertex_ = + four_[i] = dynamic_ptr_cast(diag.vertices.first); } else if(offshell->iSpin() == PDT::Spin0) { AbstractVVSVertexPtr vert1; AbstractVSSVertexPtr vert2; if(diag.channelType == HPDiagram::sChannel || (diag.channelType == HPDiagram::tChannel && diag.ordered.second)) { vert1 = dynamic_ptr_cast(diag.vertices.first ); vert2 = dynamic_ptr_cast(diag.vertices.second); } else { vert1 = dynamic_ptr_cast(diag.vertices.second); vert2 = dynamic_ptr_cast(diag.vertices.first ); } scalar_[i] = make_pair(vert1, vert2); } else if(offshell->iSpin() == PDT::Spin1) { AbstractVVVVertexPtr vert1; AbstractVVSVertexPtr vert2; if(diag.channelType == HPDiagram::sChannel || (diag.channelType == HPDiagram::tChannel && diag.ordered.second)) { vert1 = dynamic_ptr_cast(diag.vertices.first ); vert2 = dynamic_ptr_cast(diag.vertices.second); } else { vert1 = dynamic_ptr_cast(diag.vertices.second); vert2 = dynamic_ptr_cast(diag.vertices.first ); } vector_[i] = make_pair(vert1, vert2); } } } double MEvv2vs::me2() const { VBVector va(2), vb(2), vc(3); for(unsigned int i = 0; i < 2; ++i) { va[i] = VectorWaveFunction(rescaledMomenta()[0], mePartonData()[0], 2*i, incoming); vb[i] = VectorWaveFunction(rescaledMomenta()[1], mePartonData()[1], 2*i, incoming); } //always 0 and 2 polarisations for(unsigned int i = 0; i < 2; ++i) { vc[2*i] = VectorWaveFunction(rescaledMomenta()[2], mePartonData()[2], 2*i, outgoing); } bool mc = !(mePartonData()[2]->mass() > ZERO); //massive vector, also 1 if( !mc ) vc[1] = VectorWaveFunction(rescaledMomenta()[2], mePartonData()[2], 1, outgoing); ScalarWaveFunction sd(rescaledMomenta()[3], mePartonData()[3], outgoing); double full_me(0.); vv2vsHeME(va, vb, vc, mc, sd, full_me,true); return full_me; } ProductionMatrixElement MEvv2vs::vv2vsHeME(VBVector & vin1, VBVector & vin2, VBVector & vout1, bool mc, ScalarWaveFunction & sd, double & me2, bool first) const { const Energy2 q2(scale()); const Energy mass = vout1[0].mass(); // weights for the selection of the diagram vector me(numberOfDiags(), 0.); // weights for the selection of the colour flow vector flow(numberOfFlows(),0.); // flow over the helicities and diagrams for(unsigned int ihel1 = 0; ihel1 < 2; ++ihel1) { for(unsigned int ihel2 = 0; ihel2 < 2; ++ihel2) { for(unsigned int ohel1 = 0; ohel1 < 3; ++ohel1) { if(mc && ohel1 == 1) ++ohel1; vector flows(numberOfFlows(),0.); for(HPCount ix = 0; ix < numberOfDiags(); ++ix) { Complex diag(0.); const HPDiagram & current = getProcessInfo()[ix]; tcPDPtr offshell = current.intermediate; if(!offshell) { - diag = fourPointVertex_->evaluate(q2, vin1[ihel1], vin2[ihel2], - vout1[ohel1], sd); + diag = four_[ix]->evaluate(q2, vin1[ihel1], vin2[ihel2], + vout1[ohel1], sd); } else if(current.channelType == HPDiagram::sChannel) { if(offshell->iSpin() == PDT::Spin0) { ScalarWaveFunction interS = scalar_[ix].first-> evaluate(q2, 1, offshell,vin1[ihel1], vin2[ihel2]); diag = scalar_[ix].second-> evaluate(q2, vout1[ohel1], sd, interS); } else if(offshell->iSpin() == PDT::Spin1) { VectorWaveFunction interV = vector_[ix].first-> evaluate(q2, 1, offshell, vin1[ihel1], vin2[ihel2]); diag = vector_[ix].second-> evaluate(q2, vout1[ohel1], interV, sd); } else assert(false); } else if(current.channelType == HPDiagram::tChannel) { if(offshell->iSpin() == PDT::Spin0) { if(current.ordered.second) { ScalarWaveFunction interS = scalar_[ix]. first->evaluate(q2, 3, offshell, vin1[ihel1],vout1[ohel1], mass); diag = scalar_[ix].second-> evaluate(q2, vin2[ihel2], sd, interS); } else { ScalarWaveFunction interS = scalar_[ix].first-> evaluate(q2, 3, offshell, vin2[ihel2],vout1[ohel1], mass); diag = scalar_[ix].second-> evaluate(q2, vin1[ihel1], sd, interS); } } else if(offshell->iSpin() == PDT::Spin1) { if(current.ordered.second) { VectorWaveFunction interV = vector_[ix]. first->evaluate(q2, 3, offshell, vin1[ihel1],vout1[ohel1], mass); diag = vector_[ix].second-> evaluate(q2, vin2[ihel2], interV, sd); } else { VectorWaveFunction interV = vector_[ix].first-> evaluate(q2, 3, offshell, vin2[ihel2],vout1[ohel1], mass); diag = vector_[ix].second-> evaluate(q2, vin1[ihel1], interV, sd); } } else assert(false); } else assert(false); me[ix] += norm(diag); diagramME()[ix](2*ihel1, 2*ihel2, ohel1,0) = diag; //Compute flows for(size_t iy = 0; iy < current.colourFlow.size(); ++iy) { assert(current.colourFlow[iy].firstdata().mass() > ZERO); VectorWaveFunction(v3, ext[2], outgoing, true, mc); ScalarWaveFunction sd(ext[3], outgoing, true); // Need to use rescale momenta to calculate matrix element setRescaledMomenta(ext); // wave functions with rescaled momenta VectorWaveFunction vr1(rescaledMomenta()[0], ext[0]->dataPtr(), incoming); VectorWaveFunction vr2(rescaledMomenta()[1], ext[1]->dataPtr(), incoming); VectorWaveFunction vr3(rescaledMomenta()[2], ext[2]->dataPtr(), outgoing); ScalarWaveFunction sr4(rescaledMomenta()[3], ext[3]->dataPtr(), outgoing); for( unsigned int ihel = 0; ihel < 2; ++ihel ) { vr1.reset(2*ihel); v1[ihel] = vr1; vr2.reset(2*ihel); v2[ihel] = vr2; vr3.reset(2*ihel); v3[2*ihel] = vr3; } if( !mc ) { vr3.reset(1); v3[1] = vr3; } double dummy(0.); ProductionMatrixElement pme = vv2vsHeME(v1, v2, v3, mc, sd, dummy,false); createVertex(pme,ext); } diff --git a/MatrixElement/General/MEvv2vs.h b/MatrixElement/General/MEvv2vs.h --- a/MatrixElement/General/MEvv2vs.h +++ b/MatrixElement/General/MEvv2vs.h @@ -1,163 +1,163 @@ // -*- C++ -*- #ifndef HERWIG_MEvv2vs_H #define HERWIG_MEvv2vs_H // // This is the declaration of the MEvv2vs class. // #include "GeneralHardME.h" #include "ThePEG/Helicity/Vertex/AbstractVVVVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVVSVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVSSVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVVVSVertex.h" #include "Herwig/MatrixElement/ProductionMatrixElement.h" namespace Herwig { using namespace ThePEG; using Helicity::VectorWaveFunction; using Helicity::ScalarWaveFunction; /** * This is the implementation of the matrix element for * \f$2\to 2\f$ massless vector-boson pair to a vector and scalar boson. * It inherits from GeneralHardME and implements the appropriate virtual * member functions. * * @see \ref MEvv2vsInterfaces "The interfaces" * defined for MEvv2vs. */ class MEvv2vs: public GeneralHardME { public: /** * Typedef for VectorWaveFunction */ typedef vector VBVector; public: /** @name Virtual functions required by the GeneralHardME class. */ //@{ /** * The matrix element for the kinematical configuration * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. * @return the matrix element scaled with sHat() to give a * dimensionless number. */ virtual double me2() const; //@} /** * Construct the vertex information for the spin correlations * @param sub Pointer to the relevent SubProcess */ virtual void constructVertex(tSubProPtr sub); private: /** * Compute the matrix element for \f$V\, V\to V\, V\f$ * @param vin1 VectorWaveFunctions for first incoming particle * @param vin2 VectorWaveFunctions for second incoming particle * @param vout1 VectorWaveFunctions for first outgoing particle * @param mc Whether vout1 is massless or not * @param sout2 ScalarWaveFunction for outgoing particle * @param me2 colour averaged, spin summed ME * @param first Whether or not first call to decide if colour decomposition etc * should be calculated * @return ProductionMatrixElement containing results of * helicity calculations */ ProductionMatrixElement vv2vsHeME(VBVector & vin1, VBVector & vin2, VBVector & vout1, bool mc, ScalarWaveFunction & sout2, double & me2, bool first ) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MEvv2vs & operator=(const MEvv2vs &); private: /** * Store the dynamically casted VVSVertex and VSSVertex pointers */ vector > scalar_; /** * Store the dynamically casted VVVVertex and VVSVertex pointers */ vector > vector_; /** * Store the dynamically casted VVVSVertex pointer */ - AbstractVVVSVertexPtr fourPointVertex_; + vector four_; }; } #endif /* HERWIG_MEvv2vs_H */ diff --git a/MatrixElement/General/MEvv2vv.cc b/MatrixElement/General/MEvv2vv.cc --- a/MatrixElement/General/MEvv2vv.cc +++ b/MatrixElement/General/MEvv2vv.cc @@ -1,344 +1,407 @@ // -*- C++ -*- // // MEvv2vv.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 MEvv2vv class. // #include "MEvv2vv.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" +#include "Herwig/Models/StandardModel/StandardModel.h" using namespace Herwig; using ThePEG::Helicity::ScalarWaveFunction; using ThePEG::Helicity::TensorWaveFunction; using ThePEG::Helicity::incoming; using ThePEG::Helicity::outgoing; void MEvv2vv::doinit() { GeneralHardME::doinit(); scalar_.resize(numberOfDiags()); vector_.resize(numberOfDiags()); tensor_.resize(numberOfDiags()); + four_ .resize(numberOfDiags()); initializeMatrixElements(PDT::Spin1, PDT::Spin1, PDT::Spin1, PDT::Spin1); for(size_t i = 0; i < numberOfDiags(); ++i) { HPDiagram diag = getProcessInfo()[i]; tcPDPtr offshell = diag.intermediate; if(!offshell) - fourPointVertex_ = dynamic_ptr_cast + four_[i] = dynamic_ptr_cast (diag.vertices.first); else if(offshell->iSpin() == PDT::Spin0) { AbstractVVSVertexPtr vert1 = dynamic_ptr_cast (diag.vertices.first); AbstractVVSVertexPtr vert2 = dynamic_ptr_cast (diag.vertices.second); scalar_[i] = make_pair(vert1, vert2); } else if(offshell->iSpin() == PDT::Spin1) { AbstractVVVVertexPtr vert1 = dynamic_ptr_cast (diag.vertices.first); AbstractVVVVertexPtr vert2 = dynamic_ptr_cast (diag.vertices.second); vector_[i] = make_pair(vert1, vert2); } else if(offshell->iSpin() == PDT::Spin2) { AbstractVVTVertexPtr vert1 = dynamic_ptr_cast (diag.vertices.first); AbstractVVTVertexPtr vert2 = dynamic_ptr_cast (diag.vertices.second); tensor_[i] = make_pair(vert1, vert2); } } + if(colour()==Colour88to88||colour()==Colour88to66bar) { + tcHwSMPtr hwsm= dynamic_ptr_cast(standardModel()); + for(size_t i = 0; i < numberOfDiags(); ++i) { + HPDiagram diag = getProcessInfo()[i]; + if(diag.intermediate) continue; + vector order; + for(map >::const_iterator it=hwsm->couplings().begin(); + it!=hwsm->couplings().end();++it) { + order.push_back(0); + if(diag.vertices.first ) order.back() += diag.vertices.first ->orderInCoupling(it->second.first); + if(diag.vertices.second&&diag.vertices.first->getNpoint()==3) + order.back() += diag.vertices.second->orderInCoupling(it->second.first); + } + vector matchdiags; + for(size_t j = 0; j < numberOfDiags(); ++j) { + HPDiagram diag2 = getProcessInfo()[j]; + if(!diag2.intermediate || + (diag2.intermediate->iColour()==PDT::Colour8 && + diag2.intermediate->iColour()==PDT::Colour6 && + diag2.intermediate->iColour()==PDT::Colour6bar)) continue; + unsigned int iloc(0); + bool match=true; + for(map >::const_iterator it=hwsm->couplings().begin(); + it!=hwsm->couplings().end();++it) { + int otemp(0); + if(diag2.vertices.first ) otemp += diag2.vertices.first ->orderInCoupling(it->second.first); + if(diag2.vertices.second&&diag2.vertices.first->getNpoint()==3) + otemp += diag2.vertices.second->orderInCoupling(it->second.first); + if(otemp!=order[iloc]) { + match = false; + break; + } + iloc+=1; + } + if(!match) continue; + matchdiags.push_back(j); + } + double weight = 3./double(matchdiags.size()); + for(unsigned int iy=0;iy >(1,make_pair(i,weight)); + } + } } double MEvv2vv::me2() const { VBVector va(2), vb(2), vc(3), vd(3); for(unsigned int i = 0; i < 2; ++i) { va[i] = VectorWaveFunction(rescaledMomenta()[0], mePartonData()[0], 2*i, incoming); vb[i] = VectorWaveFunction(rescaledMomenta()[1], mePartonData()[1], 2*i, incoming); } //always 0 and 2 polarisations for(unsigned int i = 0; i < 2; ++i) { vc[2*i] = VectorWaveFunction(rescaledMomenta()[2], mePartonData()[2], 2*i, outgoing); vd[2*i] = VectorWaveFunction(rescaledMomenta()[3], mePartonData()[3], 2*i, outgoing); } bool mc = !(mePartonData()[2]->mass() > ZERO); //massive vector, also 1 if( !mc ) vc[1] = VectorWaveFunction(rescaledMomenta()[2], mePartonData()[2], 1, outgoing); bool md = !(mePartonData()[3]->mass() > ZERO); if( !md ) vd[1] = VectorWaveFunction(rescaledMomenta()[3], mePartonData()[3], 1, outgoing); double full_me(0.); vv2vvHeME(va, vb, vc, mc, vd, md, full_me,true); #ifndef NDEBUG if( debugME() ) debug(full_me); #endif return full_me; } ProductionMatrixElement MEvv2vv::vv2vvHeME(VBVector & vin1, VBVector & vin2, VBVector & vout1, bool mc, VBVector & vout2, bool md, double & me2, bool first) const { const Energy2 q2(scale()); const Energy mass = vout1[0].mass(); // weights for the selection of the diagram vector me(numberOfDiags(), 0.); // weights for the selection of the colour flow vector flow(numberOfFlows(),0.); // flow over the helicities and diagrams for(unsigned int ihel1 = 0; ihel1 < 2; ++ihel1) { for(unsigned int ihel2 = 0; ihel2 < 2; ++ihel2) { for(unsigned int ohel1 = 0; ohel1 < 3; ++ohel1) { if(mc && ohel1 == 1) ++ohel1; for(unsigned int ohel2 = 0; ohel2 < 3; ++ohel2) { if(md && ohel2 == 1) ++ohel2; vector flows(numberOfFlows(),0.); for(HPCount ix = 0; ix < numberOfDiags(); ++ix) { Complex diag(0.); const HPDiagram & current = getProcessInfo()[ix]; tcPDPtr offshell = current.intermediate; if(current.channelType == HPDiagram::sChannel) { if(offshell->iSpin() == PDT::Spin0) { ScalarWaveFunction interS = scalar_[ix].first->evaluate(q2, 1, offshell, vin1[ihel1], vin2[ihel2]); diag = scalar_[ix].second-> evaluate(q2, vout1[ohel1], vout2[ohel2], interS); } else if(offshell->iSpin() == PDT::Spin1) { VectorWaveFunction interV = vector_[ix].first-> evaluate(q2, 1, offshell, vin1[ihel1], vin2[ihel2]); diag = vector_[ix].second-> evaluate(q2, vout1[ohel1], vout2[ohel2], interV); if(colour()==Colour88to88) - diag += fourPointVertex_->evaluate(q2, 0, vout1[ohel1], vin2[ihel2], - vout2[ohel2], vin1[ihel1]); + for(unsigned int iy=0;iyevaluate(q2, 0, vout1[ohel1], vin2[ihel2], + vout2[ohel2], vin1[ihel1]); + } else if(colour()==Colour88to66bar) - diag -= fourPointVertex_->evaluate(q2, 0, vout1[ohel1], vin2[ihel2], - vout2[ohel2], vin1[ihel1]); + for(unsigned int iy=0;iyevaluate(q2, 0, vout1[ohel1], vin2[ihel2], + vout2[ohel2], vin1[ihel1]); + } } else if(offshell->iSpin() == PDT::Spin2) { TensorWaveFunction interT = tensor_[ix].first-> evaluate(q2, 1, offshell, vin1[ihel1], vin2[ihel2]); diag = tensor_[ix].second-> evaluate(q2, vout1[ohel1], vout2[ohel2],interT); } else assert(false); } else if(current.channelType == HPDiagram::tChannel) { if(offshell->iSpin() == PDT::Spin0) { if(current.ordered.second) { ScalarWaveFunction interS = scalar_[ix]. first->evaluate(q2, 3, offshell, vin1[ihel1],vout1[ohel1]); diag = scalar_[ix].second-> evaluate(q2, vin2[ihel2], vout2[ohel2], interS); } else { ScalarWaveFunction interS = scalar_[ix].first-> evaluate(q2, 3, offshell, vin2[ihel2],vout1[ohel1]); diag = scalar_[ix].second-> evaluate(q2, vin1[ihel1], vout2[ohel2], interS); } } else if(offshell->iSpin() == PDT::Spin1) { if(current.ordered.second) { VectorWaveFunction interV = vector_[ix]. first->evaluate(q2, 3, offshell, vin1[ihel1],vout1[ohel1], mass); diag = vector_[ix].second-> evaluate(q2, vin2[ihel2], interV, vout2[ohel2]); if(colour()==Colour88to88 || colour()==Colour88to66bar) - diag += fourPointVertex_->evaluate(q2, 0, vin1[ihel1], vin2[ihel2], - vout1[ohel1], vout2[ohel2]); + for(unsigned int iy=0;iyevaluate(q2, 0, vin1[ihel1], vin2[ihel2], + vout1[ohel1], vout2[ohel2]); + } } else { if(offshell->CC()) offshell = offshell->CC(); VectorWaveFunction interV = vector_[ix].first-> evaluate(q2, 3, offshell, vin2[ihel2],vout1[ohel1], mass); diag = vector_[ix].second-> evaluate(q2, vin1[ihel1], interV, vout2[ohel2]); if(colour()==Colour88to88 || colour()==Colour88to66bar) - diag += fourPointVertex_-> - evaluate(q2, 0, vin2[ihel2], vin1[ihel1], - vout1[ohel1], vout2[ohel2]); + for(unsigned int iy=0;iy + evaluate(q2, 0, vin2[ihel2], vin1[ihel1], + vout1[ohel1], vout2[ohel2]); + } } } else if(offshell->iSpin() == PDT::Spin2) { if(current.ordered.second) { TensorWaveFunction interT = tensor_[ix].first-> evaluate(q2, 3, offshell, vin1[ihel1],vout1[ohel1]); diag = tensor_[ix].second-> evaluate(q2, vin2[ihel2], vout2[ohel2], interT); } else { TensorWaveFunction interT = tensor_[ix].first-> evaluate(q2, 3, offshell, vin2[ihel2],vout1[ohel1]); diag = tensor_[ix].second-> evaluate(q2, vin1[ihel1], vout2[ohel2], interT); } } else assert(false); } else if(current.channelType == HPDiagram::fourPoint) { if(colour()==Colour88to88||colour()==Colour88to66bar) diag = 0.; else - diag = fourPointVertex_->evaluate(q2, 0, vin1[ihel1], vin2[ihel2], - vout1[ohel1], vout2[ohel2]); + diag = four_[ix]->evaluate(q2, 0, vin1[ihel1], vin2[ihel2], + vout1[ohel1], vout2[ohel2]); } else assert(false); me[ix] += norm(diag); diagramME()[ix](2*ihel1, 2*ihel2, ohel1, ohel2) = diag; //Compute flows for(size_t iy = 0; iy < current.colourFlow.size(); ++iy) { assert(current.colourFlow[iy].first> scalar_ >> vector_ >> tensor_ >> fourPointVertex_; + is >> scalar_ >> vector_ >> tensor_ >> four_ >> fourFlow_; initializeMatrixElements(PDT::Spin1, PDT::Spin1, PDT::Spin1, PDT::Spin1); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigMEvv2vv("Herwig::MEvv2vv", "Herwig.so"); void MEvv2vv::Init() { static ClassDocumentation documentation ("This is the implementation of the 2 to 2 ME for a pair" "of massless vector-bosons to a pair of vector bosons"); } void MEvv2vv::constructVertex(tSubProPtr sub) { ParticleVector ext = hardParticles(sub); // set wave functions with real momenta VBVector v1, v2, v3, v4; VectorWaveFunction(v1, ext[0], incoming, false, true); VectorWaveFunction(v2, ext[1], incoming, false, true); //function to calculate me2 expects massless incoming vectors // and this constructor sets the '1' polarisation at element [2] //in the vector bool mc = !(ext[2]->data().mass() > ZERO); bool md = !(ext[3]->data().mass() > ZERO); VectorWaveFunction(v3, ext[2], outgoing, true, mc); VectorWaveFunction(v4, ext[3], outgoing, true, md); // Need to use rescale momenta to calculate matrix element setRescaledMomenta(ext); // wave functions with rescaled momenta VectorWaveFunction vr1(rescaledMomenta()[0], ext[0]->dataPtr(), incoming); VectorWaveFunction vr2(rescaledMomenta()[1], ext[1]->dataPtr(), incoming); VectorWaveFunction vr3(rescaledMomenta()[2], ext[2]->dataPtr(), outgoing); VectorWaveFunction vr4(rescaledMomenta()[3], ext[3]->dataPtr(), outgoing); for( unsigned int ihel = 0; ihel < 2; ++ihel ) { vr1.reset(2*ihel); v1[ihel] = vr1; vr2.reset(2*ihel); v2[ihel] = vr2; vr3.reset(2*ihel); v3[2*ihel] = vr3; vr4.reset(2*ihel); v4[2*ihel] = vr4; } if( !mc ) { vr3.reset(1); v3[1] = vr3; } if( !md ) { vr4.reset(1); v4[1] = vr4; } double dummy(0.); ProductionMatrixElement pme = vv2vvHeME(v1, v2, v3, mc, v4, md, dummy,false); #ifndef NDEBUG if( debugME() ) debug(dummy); #endif createVertex(pme,ext); } void MEvv2vv::debug(double me2) const { if( !generator()->logfile().is_open() ) return; if( mePartonData()[0]->id() != 21 || mePartonData()[1]->id() != 21 || mePartonData()[2]->id() != 5100021 || mePartonData()[3]->id() != 5100021 ) return; tcSMPtr sm = generator()->standardModel(); double gs4 = sqr( 4.*Constants::pi*sm->alphaS(scale()) ); Energy2 s(sHat()); Energy2 mf2 = meMomenta()[2].m2(); Energy2 t3(tHat() - mf2), u4(uHat() - mf2); Energy4 s2(sqr(s)), t3s(sqr(t3)), u4s(sqr(u4)); Energy4 num = s2 + t3s + u4s; double analytic = 3.*mf2*( mf2*num/t3s/u4s - num/s/t3/u4 ) + 1. + sqr(num)*num/4./s2/t3s/u4s - t3*u4/s2; analytic *= 9.*gs4/8.; double diff = abs( analytic - me2 ); if( diff > 1e-4 ) { generator()->log() << mePartonData()[0]->PDGName() << "," << mePartonData()[1]->PDGName() << "->" << mePartonData()[2]->PDGName() << "," << mePartonData()[3]->PDGName() << " difference: " << setprecision(10) << diff << " ratio: " << analytic/me2 << '\n'; } } diff --git a/MatrixElement/General/MEvv2vv.h b/MatrixElement/General/MEvv2vv.h --- a/MatrixElement/General/MEvv2vv.h +++ b/MatrixElement/General/MEvv2vv.h @@ -1,183 +1,188 @@ // -*- C++ -*- // // MEvv2vv.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_MEvv2vv_H #define HERWIG_MEvv2vv_H // // This is the declaration of the MEvv2vv class. // #include "GeneralHardME.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "ThePEG/Helicity/Vertex/AbstractVVVVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVVTVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVVSVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVVVVVertex.h" #include "Herwig/MatrixElement/ProductionMatrixElement.h" namespace Herwig { using namespace ThePEG; using Helicity::VectorWaveFunction; /** * This is the implementation of the matrix element for * \f$2\to 2\f$ massless vector-boson pair to vector-boson pair. It inherits from * GeneralHardME and implements the appropriate virtual member functions. * * @see \ref MEvv2vvInterfaces "The interfaces" * defined for MEvv2vv. */ class MEvv2vv: public GeneralHardME { public: /** * Typedef for VectorWaveFunction */ typedef vector VBVector; public: /** @name Virtual functions required by the GeneralHardME class. */ //@{ /** * The matrix element for the kinematical configuration * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. * @return the matrix element scaled with sHat() to give a * dimensionless number. */ virtual double me2() const; //@} /** * Construct the vertex information for the spin correlations * @param sub Pointer to the relevent SubProcess */ virtual void constructVertex(tSubProPtr sub); private: /** * Compute the matrix element for \f$V\, V\to V\, V\f$ * @param vin1 VectorWaveFunctions for first incoming particle * @param vin2 VectorWaveFunctions for second incoming particle * @param vout1 VectorWaveFunctions for first outgoing particle * @param mc Whether vout1 is massless or not * @param vout2 VectorWaveFunctions for outgoing particle * @param md Whether vout2 is massless or not * @param me2 colour averaged, spin summed ME * @param first Whether or not first call to decide if colour decomposition etc * should be calculated * @return ProductionMatrixElement containing results of * helicity calculations */ ProductionMatrixElement vv2vvHeME(VBVector & vin1, VBVector & vin2, VBVector & vout1, bool mc, VBVector & vout2, bool md, double & me2, bool first ) const; protected: /** * A debugging function to test the value of me2 against an * analytic function. * @param me2 The value of the \f$ |\bar{\mathcal{M}}|^2 \f$ */ virtual void debug(double me2) 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 {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(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MEvv2vv & operator=(const MEvv2vv &); private: /** * Store the dynamically casted VVSVertex pointers */ vector > scalar_; /** * Store the dynamically casted VVVVertex pointers */ vector > vector_; /** * Store the dynamically casted VVTVertex pointers */ vector > tensor_; /** * Store the dynamically casted VVVVVertex pointer */ - AbstractVVVVVertexPtr fourPointVertex_; + vector four_; + + /** + * Four points for colour flows + */ + map > > fourFlow_; }; } #endif /* HERWIG_MEvv2vv_H */ diff --git a/MatrixElement/General/Makefile.am b/MatrixElement/General/Makefile.am --- a/MatrixElement/General/Makefile.am +++ b/MatrixElement/General/Makefile.am @@ -1,20 +1,24 @@ noinst_LTLIBRARIES = libHwGeneralME.la libHwGeneralME_la_SOURCES = \ GeneralHardME.cc GeneralHardME.h GeneralHardME.fh \ MEvv2ff.cc MEvv2ff.h \ +MEvv2rf.cc MEvv2rf.h \ MEvv2ss.cc MEvv2ss.h \ MEfv2fs.cc MEfv2fs.h \ +MEfv2rs.cc MEfv2rs.h \ MEff2ss.cc MEff2ss.h \ MEff2ff.cc MEff2ff.h \ +MEff2rf.cc MEff2rf.h \ MEff2vv.cc MEff2vv.h \ MEfv2vf.cc MEfv2vf.h \ +MEfv2rv.cc MEfv2rv.h \ MEff2vs.cc MEff2vs.h \ -MEff2sv.cc MEff2sv.h \ MEvv2vv.cc MEvv2vv.h \ MEvv2vs.cc MEvv2vs.h \ MEff2tv.cc MEff2tv.h \ +MEff2ts.cc MEff2ts.h \ MEvv2tv.cc MEvv2tv.h \ MEfv2tf.cc MEfv2tf.h \ GeneralfftoVH.cc GeneralfftoVH.h GeneralfftoVH.fh\ GeneralfftoffH.cc GeneralfftoffH.h GeneralfftoffH.fh\ GeneralQQHiggs.cc GeneralQQHiggs.h GeneralQQHiggs.fh diff --git a/MatrixElement/Hadron/MEPP2HiggsVBF.cc b/MatrixElement/Hadron/MEPP2HiggsVBF.cc --- a/MatrixElement/Hadron/MEPP2HiggsVBF.cc +++ b/MatrixElement/Hadron/MEPP2HiggsVBF.cc @@ -1,1455 +1,1459 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the MEPP2HiggsVBF class. // #include "MEPP2HiggsVBF.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/PDT/StandardMatchers.h" #include #include "Herwig/Utilities/Maths.h" #include "Herwig/Models/StandardModel/StandardModel.h" #include "ThePEG/Repository/CurrentGenerator.h" #include "Herwig/Shower/RealEmissionProcess.h" using namespace Herwig; // namespace { // using namespace Herwig; // using namespace ThePEG; // using namespace ThePEG::Helicity; // void debuggingMatrixElement(bool BGF, // tcPDPtr partons1, tcPDPtr partons2, // tcPDPtr partons3, tcPDPtr partons4, // const Lorentz5Momentum & psystem0, // const Lorentz5Momentum & psystem1, // const Lorentz5Momentum & pother0, // const Lorentz5Momentum & pother1, // const Lorentz5Momentum & p0, // const Lorentz5Momentum & p1, // const Lorentz5Momentum & p2, // const Lorentz5Momentum & phiggs, // Energy2 Q12, Energy2 scale, // double old) { // // get the vertex and the boson // tcHwSMPtr hwsm=ThePEG::dynamic_ptr_cast // (CurrentGenerator::current().standardModel()); // assert(hwsm); // tcPDPtr boson; // AbstractFFVVertexPtr weakVertex; // AbstractFFVVertexPtr strongVertex = hwsm->vertexFFG(); // AbstractVVSVertexPtr higgsVertex = hwsm->vertexWWH(); // if(partons1->id()==partons2->id()) { // weakVertex = hwsm->vertexFFZ(); // boson = hwsm->getParticleData(ParticleID::Z0); // } // else { // weakVertex = hwsm->vertexFFW(); // boson = hwsm->getParticleData(ParticleID::Wplus); // } // tcPDPtr hdata = hwsm->getParticleData(ParticleID::h0); // tcPDPtr gluon = hwsm->getParticleData(ParticleID::g); // SpinorWaveFunction q1,q2; // SpinorBarWaveFunction qbar1,qbar2; // if(partons1->id()>0) { // q1 = SpinorWaveFunction (psystem0,partons1,incoming); // qbar1 = SpinorBarWaveFunction(psystem1,partons2,outgoing); // } // else { // q1 = SpinorWaveFunction (psystem1,partons2,outgoing); // qbar1 = SpinorBarWaveFunction(psystem0,partons1,incoming); // } // if(partons3->id()>0) { // q2 = SpinorWaveFunction (pother0,partons3,incoming); // qbar2 = SpinorBarWaveFunction(pother1,partons4,outgoing); // } // else { // q2 = SpinorWaveFunction (pother1,partons4,outgoing); // qbar2 = SpinorBarWaveFunction(pother0,partons3,incoming); // } // ScalarWaveFunction higgs(phiggs,hdata,outgoing); // if(!BGF) { // SpinorWaveFunction q1p; // SpinorBarWaveFunction qbar1p; // if(partons1->id()>0) { // q1p = SpinorWaveFunction (p0 ,partons1,incoming); // qbar1p = SpinorBarWaveFunction(p1 ,partons2,outgoing); // } // else { // q1p = SpinorWaveFunction (p1 ,partons2,outgoing); // qbar1p = SpinorBarWaveFunction(p0 ,partons1,incoming); // } // VectorWaveFunction gl(p2,gluon,outgoing); // double lome(0.),realme(0.); // for(unsigned int lhel1=0;lhel1<2;++lhel1) { // q2.reset(lhel1); // for(unsigned int lhel2=0;lhel2<2;++lhel2) { // qbar2.reset(lhel2); // VectorWaveFunction off1 // = weakVertex->evaluate(scale,3,boson,q2,qbar2); // VectorWaveFunction off2 // = higgsVertex->evaluate(scale,3,boson,off1,higgs); // for(unsigned int qhel1=0;qhel1<2;++qhel1) { // q1.reset(qhel1); // q1p.reset(qhel1); // for(unsigned int qhel2=0;qhel2<2;++qhel2) { // qbar1.reset(qhel2); // qbar1p.reset(qhel2); // Complex diag = weakVertex->evaluate(scale,q1,qbar1,off2); // lome += norm(diag); // for(unsigned int ghel=0;ghel<2;++ghel) { // gl.reset(2*ghel); // SpinorWaveFunction inter1 = // strongVertex->evaluate(Q12,5,q1p.particle(),q1p,gl); // Complex diag1 = weakVertex->evaluate(scale,inter1,qbar1p,off2); // SpinorBarWaveFunction inter2 = // strongVertex->evaluate(Q12,5,qbar1p.particle(),qbar1p,gl); // Complex diag2 = weakVertex->evaluate(scale,q1p,inter2,off2); // realme += norm(diag1+diag2); // } // } // } // } // } // double test1 = realme/lome/hwsm->alphaS(Q12)*Q12*UnitRemoval::InvE2; // cerr << "testing ratio A " << old/test1 << "\n"; // } // else { // SpinorWaveFunction q1p; // SpinorBarWaveFunction qbar1p; // if(partons1->id()>0) { // q1p = SpinorWaveFunction (p2,partons1->CC(),outgoing); // qbar1p = SpinorBarWaveFunction(p1,partons2 ,outgoing); // } // else { // q1p = SpinorWaveFunction (p1,partons2 ,outgoing); // qbar1p = SpinorBarWaveFunction(p2,partons1->CC(),outgoing); // } // VectorWaveFunction gl(p0,gluon,incoming); // double lome(0.),realme(0.); // for(unsigned int lhel1=0;lhel1<2;++lhel1) { // q2.reset(lhel1); // for(unsigned int lhel2=0;lhel2<2;++lhel2) { // qbar2.reset(lhel2); // VectorWaveFunction off1 // = weakVertex->evaluate(scale,3,boson,q2,qbar2); // VectorWaveFunction off2 // = higgsVertex->evaluate(scale,3,boson,off1,higgs); // for(unsigned int qhel1=0;qhel1<2;++qhel1) { // q1.reset(qhel1); // q1p.reset(qhel1); // for(unsigned int qhel2=0;qhel2<2;++qhel2) { // qbar1.reset(qhel2); // qbar1p.reset(qhel2); // Complex diag = weakVertex->evaluate(scale,q1,qbar1,off2); // lome += norm(diag); // for(unsigned int ghel=0;ghel<2;++ghel) { // gl.reset(2*ghel); // SpinorWaveFunction inter1 = // strongVertex->evaluate(Q12,5,q1p.particle(),q1p,gl); // Complex diag1 = weakVertex->evaluate(scale,inter1,qbar1p,off2); // SpinorBarWaveFunction inter2 = // strongVertex->evaluate(Q12,5,qbar1p.particle(),qbar1p,gl); // Complex diag2 = weakVertex->evaluate(scale,q1p,inter2,off2); // realme += norm(diag1+diag2); // } // } // } // } // } // double test1 = realme/lome/hwsm->alphaS(Q12)*Q12*UnitRemoval::InvE2; // cerr << "testing ratio B " << old/test1 << "\n"; // } // } // } MEPP2HiggsVBF::MEPP2HiggsVBF() : comptonWeight_(8.), BGFWeight_(30.), pTmin_(1.*GeV),initial_(10.),final_(8.), procProb_(0.5), comptonInt_(0.), bgfInt_(0.), nover_(0),maxwgt_(make_pair(0.,0.)) {} void MEPP2HiggsVBF::doinit() { gluon_ = getParticleData(ParticleID::g); // integrals of me over phase space double r5=sqrt(5.),darg((r5-1.)/(r5+1.)),ath(0.5*log((1.+1./r5)/(1.-1./r5))); comptonInt_ = 2.*(-21./20.-6./(5.*r5)*ath+sqr(Constants::pi)/3. -2.*Math::ReLi2(1.-darg)-2.*Math::ReLi2(1.-1./darg)); bgfInt_ = 121./9.-56./r5*ath; // get the vertex pointers from the SM object tcHwSMPtr hwsm= dynamic_ptr_cast(standardModel()); if(!hwsm) throw InitException() << "Wrong type of StandardModel object in " << "MEPP2HiggsVBF::doinit() the Herwig" << " version must be used" << Exception::runerror; // set the vertex setWWHVertex(hwsm->vertexWWH()); higgs(getParticleData(ParticleID::h0)); MEfftoffH::doinit(); } void MEPP2HiggsVBF::dofinish() { MEfftoffH::dofinish(); if(nover_==0) return; generator()->log() << "VBFMECorrection when applying the hard correction " << nover_ << " weights larger than one were generated of which" << " the largest was " << maxwgt_.first << " for the QCD compton" << " processes and " << maxwgt_.second << " for the BGF process\n"; } void MEPP2HiggsVBF::getDiagrams() const { // get the quark particle data objects as we'll be using them tcPDPtr q[6],qbar[6]; for ( int ix=0; ix<5; ++ix ) { q [ix] = getParticleData(ix+1); qbar[ix] = q[ix]->CC(); } // WW processes if(process()==0||process()==1) { std::vector > parentpair; parentpair.reserve(6); // don't even think of putting 'break' in here! switch(maxFlavour()) { case 5: if (minFlavour()<=4) parentpair.push_back(make_pair(getParticleData(ParticleID::b), getParticleData(ParticleID::c))); if (minFlavour()<=2) parentpair.push_back(make_pair(getParticleData(ParticleID::b), getParticleData(ParticleID::u))); + [[fallthrough]]; case 4: if (minFlavour()<=3) parentpair.push_back(make_pair(getParticleData(ParticleID::s), getParticleData(ParticleID::c))); if (minFlavour()<=1) parentpair.push_back(make_pair(getParticleData(ParticleID::d), getParticleData(ParticleID::c))); + [[fallthrough]]; case 3: if (minFlavour()<=2) parentpair.push_back(make_pair(getParticleData(ParticleID::s), getParticleData(ParticleID::u))); + [[fallthrough]]; case 2: if (minFlavour()<=1) parentpair.push_back(make_pair(getParticleData(ParticleID::d), getParticleData(ParticleID::u))); + [[fallthrough]]; default: ; } for(unsigned int ix=0;ix q1' q2' h if(parentpair[ix].first->id()id()) { add(new_ptr((Tree2toNDiagram(4), parentpair[ix].first, WMinus(), WPlus(), parentpair[iy].second, 1, parentpair[ix].second, 3, parentpair[iy].first, 2, higgs(),-1))); } else { add(new_ptr((Tree2toNDiagram(4), parentpair[iy].second, WPlus(), WMinus(), parentpair[ix].first, 1, parentpair[iy].first, 3, parentpair[ix].second, 2, higgs(),-1))); } // q1 qbar2 -> q1' qbar2' h add(new_ptr((Tree2toNDiagram(4), parentpair[ix].first, WMinus(), WPlus(), parentpair[iy].first->CC(), 1, parentpair[ix].second, 3, parentpair[iy].second->CC(), 2, higgs(),-1))); add(new_ptr((Tree2toNDiagram(4),parentpair[iy].second, WPlus(), WMinus(), parentpair[ix].second->CC(), 1, parentpair[iy].first, 3, parentpair[ix].first->CC(), 2, higgs(),-1))); // qbar1 qbar2 -> qbar1' qbar2' h if(parentpair[ix].first->id()id()) { add(new_ptr((Tree2toNDiagram(4), parentpair[ix].first->CC(), WPlus(), WMinus(), parentpair[iy].second->CC(), 1, parentpair[ix].second->CC(), 3, parentpair[iy].first->CC(), 2, higgs(),-1))); } else { add(new_ptr((Tree2toNDiagram(4), parentpair[iy].second->CC(), WMinus(), WPlus(), parentpair[ix].first->CC(), 1, parentpair[iy].first->CC(), 3, parentpair[ix].second->CC(), 2, higgs(),-1))); } } } } // ZZ processes if(process()==0||process()==2) { for(unsigned int ix=minFlavour()-1;ix q q H add(new_ptr((Tree2toNDiagram(4), q[ix], Z0(), Z0(), q[iy], 1, q[ix], 3, q[iy], 2, higgs(),-2))); // qbar qbar -> qbar qbar H add(new_ptr((Tree2toNDiagram(4), qbar[ix], Z0(), Z0(), qbar[iy], 1, qbar[ix], 3, qbar[iy], 2, higgs(),-2))); } // q qbar -> q qbar H for(unsigned int iy=minFlavour()-1;iy> initial_ >> final_ >> alpha_ >> iunit(pTmin_,GeV) >> comptonWeight_ >> BGFWeight_ >> gluon_ >> comptonInt_ >> bgfInt_ >> procProb_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigMEPP2HiggsVBF("Herwig::MEPP2HiggsVBF", "HwMEHadron.so"); void MEPP2HiggsVBF::Init() { static ClassDocumentation documentation ("The MEPP2HiggsVBF class implements Higgs production via vector-boson fusion"); static Reference interfaceShowerAlphaQCD ("ShowerAlphaQCD", "The object calculating the strong coupling constant", &MEPP2HiggsVBF::alpha_, false, false, true, false, false); static Parameter interfacepTMin ("pTMin", "The minimum pT", &MEPP2HiggsVBF::pTmin_, GeV, 1.*GeV, 0.0*GeV, 10.0*GeV, false, false, Interface::limited); static Parameter interfaceComptonWeight ("ComptonWeight", "Weight for the overestimate ofthe compton channel", &MEPP2HiggsVBF::comptonWeight_, 50.0, 0.0, 100.0, false, false, Interface::limited); static Parameter interfaceBGFWeight ("BGFWeight", "Weight for the overestimate of the BGF channel", &MEPP2HiggsVBF::BGFWeight_, 100.0, 0.0, 1000.0, false, false, Interface::limited); static Parameter interfaceProcessProbability ("ProcessProbability", "The probabilty of the QCD compton process for the process selection", &MEPP2HiggsVBF::procProb_, 0.3, 0.0, 1., false, false, Interface::limited); } RealEmissionProcessPtr MEPP2HiggsVBF::generateHardest(RealEmissionProcessPtr born, ShowerInteraction inter) { if(inter==ShowerInteraction::QED) return RealEmissionProcessPtr(); pair first,second; pair beams; pair hadrons; // get the incoming particles for(unsigned int ix=0;ixbornIncoming().size();++ix) { if(!first.first) { first.first = born->bornIncoming()[ix]; hadrons.first = born->hadrons()[ix]; beams.first = dynamic_ptr_cast(born->hadrons()[ix]->dataPtr()); } else { second.first = born->bornIncoming()[ix]; hadrons.second = born->hadrons()[ix]; beams.second = dynamic_ptr_cast(born->hadrons()[ix]->dataPtr()); } } // and the outgoing for(unsigned int ix=0;ixbornOutgoing().size();++ix) { if(born->bornOutgoing()[ix]->id()==ParticleID::h0) { higgs_ = born->bornOutgoing()[ix]; } else { if(abs(born->bornOutgoing()[ix]->id())>5) continue; if(born->bornOutgoing()[ix]->colourLine()&& born->bornOutgoing()[ix]->colourLine()==first.first->colourLine()) { first.second = born->bornOutgoing()[ix]; continue; } if(born->bornOutgoing()[ix]->antiColourLine()&& born->bornOutgoing()[ix]->antiColourLine()==first.first->antiColourLine()) { first.second = born->bornOutgoing()[ix]; continue; } if(born->bornOutgoing()[ix]->colourLine()&& born->bornOutgoing()[ix]->colourLine()==second.first->colourLine()) { second.second = born->bornOutgoing()[ix]; continue; } if(born->bornOutgoing()[ix]->antiColourLine()&& born->bornOutgoing()[ix]->antiColourLine()==second.first->antiColourLine()) { second.second = born->bornOutgoing()[ix]; continue; } } } // loop over the two possible emitting systems q_ [0] = first .second->momentum()-first .first->momentum(); q2_[0] = -q_[0].m2(); q_ [1] = second.second->momentum()-second.first->momentum(); q2_[1] = -q_[1].m2(); for(unsigned int ix=0;ix<2;++ix) { if(ix==1) { swap(first,second); swap(beams.first,beams.second); swap(hadrons.first,hadrons.second); } // check beam, all particles assert(beams.first && higgs_ && first .first && first.second && second.first && second.second); // beam and pdf beam_[ix] = beams.first; pdf_ [ix] = beam_[ix]->pdf(); assert(beam_[ix] && pdf_[ix] ); // Particle data objects partons_[ix][0] = first. first->dataPtr(); partons_[ix][1] = first.second->dataPtr(); partons_[ix][2] = second. first->dataPtr(); partons_[ix][3] = second.second->dataPtr(); // extract the born variables xB_[ix] = first.first->momentum().rho()/hadrons.first->momentum().rho(); Lorentz5Momentum pb = first.first->momentum(); Axis axis(q_[ix].vect().unit()); double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); rot_[ix] = LorentzRotation(); if(axis.perp2()>1e-20) { rot_[ix].setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); rot_[ix].rotateX(Constants::pi); } if(abs(1.-q_[ix].e()/q_[ix].vect().mag())>1e-6) rot_[ix].boostZ( q_[ix].e()/q_[ix].vect().mag()); pb *= rot_[ix]; if(pb.perp2()/GeV2>1e-20) { Boost trans = -1./pb.e()*pb.vect(); trans.setZ(0.); rot_[ix].boost(trans); } // momenta of the particles phiggs_ [ix] = rot_[ix]*higgs_->momentum(); pother_ [ix][0] = rot_[ix]*second. first->momentum(); pother_ [ix][1] = rot_[ix]*second.second->momentum(); psystem_[ix][0] = rot_[ix]* first. first->momentum(); psystem_[ix][1] = rot_[ix]* first.second->momentum(); q_[ix] *= rot_[ix]; pTCompton_[ix] = pTBGF_[ix] = ZERO; // generate a compton point generateCompton(ix); // generate a BGF point generateBGF(ix); } // no valid emissions, return if(pTCompton_[0]pT()[ShowerInteraction::QCD] = pTmin_; return born; } // find the maximum pT emission unsigned int system = 0; bool isCompton = false; Energy pTmax = -GeV; for(unsigned int ix=0;ix<2;++ix) { if(pTCompton_[ix]>pTmax) { pTmax = pTCompton_[ix]; isCompton = true; system = ix; } if(pTBGF_[ix]>pTmax) { pTmax = pTBGF_[ix]; isCompton = false; system = ix; } } if(system==0) { swap(first,second); swap(beams.first,beams.second); swap(hadrons.first,hadrons.second); } // the non emitting particles PPtr spectin =second.first ->dataPtr()->produceParticle(second.first ->momentum()); PPtr spectout=second.second->dataPtr()->produceParticle(second.second->momentum()); spectout->incomingColour(spectin,spectout->id()<0); PPtr higgs = higgs_->dataPtr()->produceParticle(higgs_->momentum()); rot_[system].invert(); PPtr newout,newin,emitted; bool FSR = false; bool isQuark = first.first->colourLine(); // compton hardest if(isCompton) { for(unsigned int ix=0;ixproduceParticle(ComptonMomenta_[system][1]); emitted = gluon_ ->produceParticle(ComptonMomenta_[system][2]); newin = partons_[system][0]->produceParticle(ComptonMomenta_[system][0]); FSR = !ComptonISFS_[system]; emitted->incomingColour(newin,!isQuark); emitted->colourConnect(newout,!isQuark); } // BGF hardest else { for(unsigned int ix=0;ixproduceParticle(BGFMomenta_[system][0]); emitted = partons_[system][0]->CC()->produceParticle(BGFMomenta_[system][2]); newout = partons_[system][1] ->produceParticle(BGFMomenta_[system][1]); emitted->incomingColour(newin, isQuark); newout ->incomingColour(newin,!isQuark); } pair x; pair radiators; if(born->bornIncoming()[0]!=first.first) { born->incoming().push_back(spectin); born->incoming().push_back(newin); x.first = born->bornIncoming()[0]->momentum().rho()/born->hadrons()[0]->momentum().rho(); x.second = newin ->momentum().rho()/born->hadrons()[1]->momentum().rho(); radiators.first = 1; } else { born->incoming().push_back(newin); born->incoming().push_back(spectin); x.first = newin ->momentum().rho()/born->hadrons()[0]->momentum().rho(); x.second = born->bornIncoming()[1]->momentum().rho()/born->hadrons()[1]->momentum().rho(); radiators.first = 0; } born->x(x); for(unsigned int ix=0;ixbornOutgoing().size();++ix) { if(born->bornOutgoing()[ix]==second.second) { born->outgoing().push_back(spectout); } else if(born->bornOutgoing()[ix]==first.second) { radiators.second = born->outgoing().size()+2; born->outgoing().push_back(newout); } else born->outgoing().push_back(higgs); } if(FSR) swap(radiators.first,radiators.second); born->emitter (radiators.first ); born->spectator(radiators.second); born->emitted(born->outgoing().size()+2); // radiated particle born->outgoing().push_back(emitted); born->pT()[ShowerInteraction::QCD] = isCompton ? pTCompton_[system] : pTBGF_[system]; born->interaction(ShowerInteraction::QCD); return born; } void MEPP2HiggsVBF::generateCompton(unsigned int system) { // calculate the A coefficient for the correlations acoeff_ = A(partons_[system][0],partons_[system][1], partons_[system][2],partons_[system][3]); // maximum value of the xT double xT = sqrt((1.-xB_[system])/xB_[system]); double xTMin = 2.*pTmin_/sqrt(q2_[system]); double zp; // prefactor double a = alpha_->overestimateValue()*comptonWeight_/Constants::twopi; // loop to generate kinematics double wgt(0.),xp(0.); l_ = 2.*pother_[system][0]/sqrt(q2_[system]); m_ = 2.*pother_[system][1]/sqrt(q2_[system]); vector azicoeff; do { wgt = 0.; // intergration variables dxT/xT^3 xT *= 1./sqrt(1.-2.*log(UseRandom::rnd())/a*sqr(xT)); // dz zp = UseRandom::rnd(); xp = 1./(1.+0.25*sqr(xT)/zp/(1.-zp)); // check allowed if(xp1.) continue; // phase-space piece of the weight wgt = 8.*(1.-xp)*zp/comptonWeight_; // PDF piece of the weight Energy2 mu2 = q2_[system]*((1.-xp)*(1-zp)*zp/xp+1.); double pdf = pdf_[system]->xfx(beam_[system],partons_[system][0], mu2 ,xB_[system]/xp)/ pdf_[system]->xfx(beam_[system],partons_[system][0], scale(),xB_[system] ); wgt *= max(pdf,0.); // me piece of the weight // double me = comptonME(system,xT,xp,zp,phi); double x2 = 1.-(1.-zp)/xp; azicoeff = ComptonME(xp,x2,xT,l_,m_); double me = 4./3.*alpha_->ratio(0.25*q2_[system]*sqr(xT))* (azicoeff[0]+0.5*azicoeff[2]+0.5*azicoeff[4]); wgt *= me; if(wgt>1.||wgt<-1e-8) { ostringstream wstring; wstring << "MEPP2HiggsVBF::generateCompton() " << "Weight greater than one or less than zero" << "wgt = " << wgt << "\n"; generator()->logWarning( Exception(wstring.str(), Exception::warning) ); } } while(xT>xTMin&&UseRandom::rnd()>wgt); if(xT<=xTMin) { pTCompton_[system]=-GeV; return; } // generate phi unsigned int itry(0); double phimax = std::accumulate(azicoeff.begin(),azicoeff.end(),0.); double phiwgt,phi; do { phi = UseRandom::rnd()*Constants::twopi; double cphi(cos(phi)),sphi(sin(phi)); phiwgt = azicoeff[0]+azicoeff[5]*sphi*cphi +azicoeff[1]*cphi+azicoeff[2]*sqr(cphi) +azicoeff[3]*sphi+azicoeff[4]*sqr(sphi); ++itry; } while (phimax*UseRandom::rnd() > phiwgt && itry<200); if(itry==200) throw Exception() << "Too many tries in MEPP2HiggsVBF" << "::generateCompton() to" << " generate phi" << Exception::eventerror; // momenta for the configuration Energy Q(sqrt(q2_[system])); double x1 = -1./xp; double x2 = 1.-(1.-zp)/xp; double x3 = 2.+x1-x2; Lorentz5Momentum p1( 0.5*Q*xT*cos(phi), 0.5*Q*xT*sin(phi), -0.5*Q*x2, 0.5*Q*sqrt(sqr(xT)+sqr(x2))); Lorentz5Momentum p2(-0.5*Q*xT*cos(phi), -0.5*Q*xT*sin(phi), -0.5*Q*x3, 0.5*Q*sqrt(sqr(xT)+sqr(x3))); Lorentz5Momentum p0(ZERO,ZERO,-0.5*Q*x1,-0.5*Q*x1); pTCompton_[system] = 0.5*Q*xT; ComptonMomenta_[system].resize(3); ComptonMomenta_[system][0] = p0; ComptonMomenta_[system][1] = p1; ComptonMomenta_[system][2] = p2; ComptonISFS_[system] = zp>xp; } double MEPP2HiggsVBF::comptonME(unsigned int system, double xT, double xp, double zp, double phi) { // scale and prefactors double CFfact = 4./3.*alpha_->ratio(0.25*q2_[system]*sqr(xT)); Energy Q(sqrt(q2_[system])); double x1 = -1./xp; double x2 = 1.-(1.-zp)/xp; double x3 = 2.+x1-x2; //set NLO momenta Lorentz5Momentum p1( 0.5*Q*xT*cos(phi), 0.5*Q*xT*sin(phi), -0.5*Q*x2, 0.5*Q*sqrt(sqr(xT)+sqr(x2))); Lorentz5Momentum p2(-0.5*Q*xT*cos(phi), -0.5*Q*xT*sin(phi), -0.5*Q*x3, 0.5*Q*sqrt(sqr(xT)+sqr(x3))); Lorentz5Momentum p0(ZERO,ZERO,-0.5*Q*x1,-0.5*Q*x1); Lorentz5Momentum qnlo = p2+p1-p0; // Breit frame variables Lorentz5Momentum r1 = -p0/x1; Lorentz5Momentum r2 = p1/x2; // electroweak parameters double c0L,c1L,c0R,c1R; // W if(partons_[system][0]->id()!=partons_[system][1]->id()) { c0L = sqrt(0.5); c0R = 0; c1L = sqrt(0.5); c1R = 0; } // Z else { if(abs(partons_[system][0]->id())%2==0) { c0L = generator()->standardModel()->vu()+ generator()->standardModel()->au(); c0R = generator()->standardModel()->vu()- generator()->standardModel()->au(); } else { c0L = generator()->standardModel()->vd()+ generator()->standardModel()->ad(); c0R = generator()->standardModel()->vd()- generator()->standardModel()->ad(); } if(abs(partons_[system][2]->id())%2==0) { c1L = generator()->standardModel()->vu()+ generator()->standardModel()->au(); c1R = generator()->standardModel()->vu()- generator()->standardModel()->au(); } else { c1L = generator()->standardModel()->vd()+ generator()->standardModel()->ad(); c1R = generator()->standardModel()->vd()- generator()->standardModel()->ad(); } c0L *= 0.25; c0R *= 0.25; c1L *= 0.25; c1R *= 0.25; } // Matrix element variables double G1 = sqr(c0L*c1L)+sqr(c0R*c1R); double G2 = sqr(c0L*c1R)+sqr(c0R*c1L); Energy4 term1,term2,loME; if(partons_[system][0]->id()>0) { if(partons_[system][2]->id()>0) { term1 = loMatrixElement(r1 ,pother_[system][0], qnlo+r1 ,pother_[system][1],G1,G2); term2 = loMatrixElement(r2-qnlo ,pother_[system][0], r2 ,pother_[system][1],G1,G2); loME = loMatrixElement(psystem_[system][0],pother_[system][0], psystem_[system][1],pother_[system][1],G1,G2); } else { term1 = loMatrixElement(r1 ,pother_[system][1], qnlo+r1 ,pother_[system][0],G1,G2); term2 = loMatrixElement(r2-qnlo ,pother_[system][1], r2 ,pother_[system][0],G1,G2); loME = loMatrixElement(psystem_[system][0],pother_[system][1], psystem_[system][1],pother_[system][0],G1,G2); } } else { if(partons_[system][2]->id()>0) { term1 = loMatrixElement(qnlo+r1 ,pother_[system][0], r1 ,pother_[system][1],G1,G2); term2 = loMatrixElement(r2 ,pother_[system][0], r2-qnlo ,pother_[system][1],G1,G2); loME = loMatrixElement(psystem_[system][1],pother_[system][0], psystem_[system][0],pother_[system][1],G1,G2); } else { term1 = loMatrixElement(qnlo+r1,pother_[system][1],r1 , pother_[system][0],G1,G2); term2 = loMatrixElement(r2 ,pother_[system][1],r2-qnlo, pother_[system][0],G1,G2); loME = loMatrixElement(psystem_[system][1],pother_[system][1], psystem_[system][0],pother_[system][0],G1,G2); } } double R1 = term1/loME; double R2 = sqr(x2)/(sqr(x2)+sqr(xT))*(term2/loME); // debuggingMatrixElement(false, // partons_[system][0],partons_[system][1], // partons_[system][2],partons_[system][3], // psystem_[system][0],psystem_[system][1], // pother_ [system][0],pother_ [system][1], // p0,p1,p2,phiggs_[system],q2_[system],scale(), // 8.*Constants::pi/(1.-xp)/(1.-zp)*(R1+sqr(xp)*(sqr(x2)+sqr(xT))*R2)); // cerr << "testing pieces A " << R1 << " " << sqr(xp)*(sqr(x2)+sqr(xT)) << " " << R2 << "\n"; return CFfact*(R1+sqr(xp)*(sqr(x2)+sqr(xT))*R2); } void MEPP2HiggsVBF::generateBGF(unsigned int system) { // maximum value of the xT double xT = (1.-xB_[system])/xB_[system]; double xTMin = 2.*pTmin_/sqrt(q2_[system]); double zp; // prefactor double a = alpha_->overestimateValue()*BGFWeight_/Constants::twopi; // loop to generate kinematics double wgt(0.),xp(0.); l_ = 2.*pother_[system][0]/sqrt(q2_[system]); m_ = 2.*pother_[system][1]/sqrt(q2_[system]); vector azicoeff; do { wgt = 0.; // intergration variables dxT/xT^3 xT *= 1./sqrt(1.-2.*log(UseRandom::rnd())/a*sqr(xT)); // dzp zp = UseRandom::rnd(); xp = 1./(1.+0.25*sqr(xT)/zp/(1.-zp)); // check allowed if(xp1.) continue; // phase-space piece of the weight wgt = 8.*sqr(1.-xp)*zp/BGFWeight_; // PDF piece of the weight Energy2 mu2 = q2_[system]*((1.-xp)*(1-zp)*zp/xp+1.); wgt *= pdf_[system]->xfx(beam_[system],gluon_ , mu2 ,xB_[system]/xp)/ pdf_[system]->xfx(beam_[system],partons_[system][0], scale(),xB_[system]); // me piece of the weight //double me = BGFME(system,xT,xp,zp,phi); double x1 = -1./xp; double x2 = 1.-(1.-zp)/xp; double x3 = 2.+x1-x2; azicoeff = BGFME(xp,x2,x3,xT,l_,m_); double me = 0.5*alpha_->ratio(0.25*q2_[system]*sqr(xT))* (azicoeff[0]+0.5*azicoeff[2]+0.5*azicoeff[4]); wgt *= me; if(wgt>1.||wgt<-1e-8) { ostringstream wstring; wstring << "MEPP2HiggsVBF::generateBGF() " << "Weight greater than one or less than zero" << "wgt = " << wgt << "\n"; generator()->logWarning( Exception(wstring.str(), Exception::warning) ); } } while(xT>xTMin&&UseRandom::rnd()>wgt); if(xT<=xTMin) { pTBGF_[system] = -GeV; return; } // generate phi unsigned int itry(0); double phimax = std::accumulate(azicoeff.begin(),azicoeff.end(),0.); double phiwgt,phi; do { phi = UseRandom::rnd()*Constants::twopi; double cphi(cos(phi)),sphi(sin(phi)); phiwgt = azicoeff[0]+azicoeff[5]*sphi*cphi +azicoeff[1]*cphi+azicoeff[2]*sqr(cphi) +azicoeff[3]*sphi+azicoeff[4]*sqr(sphi); ++itry; } while (phimax*UseRandom::rnd() > phiwgt && itry<200); if(itry==200) throw Exception() << "Too many tries in MEPP2HiggsVBF" << "::generateBGF() to" << " generate phi" << Exception::eventerror; // momenta for the configuration Energy Q(sqrt(q2_[system])); double x1 = -1./xp; double x2 = 1.-(1.-zp)/xp; double x3 = 2.+x1-x2; Lorentz5Momentum p1( 0.5*Q*xT*cos(phi), 0.5*Q*xT*sin(phi), -0.5*Q*x2, 0.5*Q*sqrt(sqr(xT)+sqr(x2))); Lorentz5Momentum p2(-0.5*Q*xT*cos(phi), -0.5*Q*xT*sin(phi), -0.5*Q*x3, 0.5*Q*sqrt(sqr(xT)+sqr(x3))); Lorentz5Momentum p0(ZERO,ZERO,-0.5*Q*x1,-0.5*Q*x1); pTBGF_[system] = 0.5*Q*xT; BGFMomenta_[system].resize(3); BGFMomenta_[system][0] = p0; BGFMomenta_[system][1] = p1; BGFMomenta_[system][2] = p2; } double MEPP2HiggsVBF::BGFME(unsigned int system, double xT, double xp, double zp, double phi) { // scale and prefactors double TRfact = 0.5*alpha_->ratio(0.25*q2_[system]*sqr(xT)); Energy Q(sqrt(q2_[system])); double x1 = -1./xp; double x2 = 1.-(1.-zp)/xp; double x3 = 2.+x1-x2; // Set NLO momenta Lorentz5Momentum p1( 0.5*Q*xT*cos(phi), 0.5*Q*xT*sin(phi), -0.5*Q*x2, 0.5*Q*sqrt(sqr(xT)+sqr(x2))); Lorentz5Momentum p2(-0.5*Q*xT*cos(phi), -0.5*Q*xT*sin(phi), -0.5*Q*x3, 0.5*Q*sqrt(sqr(xT)+sqr(x3))); Lorentz5Momentum p0(ZERO,ZERO,-0.5*Q*x1,-0.5*Q*x1); Lorentz5Momentum qnlo = p2+p1-p0; // Breit frame variables Lorentz5Momentum r2 = p1/x2; Lorentz5Momentum r3 = -p2/x3; // electroweak parameters double c0L,c1L,c0R,c1R; // W if(partons_[system][0]->id()!=partons_[system][1]->id()) { c0L = sqrt(0.5); c0R = 0; c1L = sqrt(0.5); c1R = 0; } // Z else { if(abs(partons_[system][0]->id())%2==0) { c0L = generator()->standardModel()->vu()+ generator()->standardModel()->au(); c0R = generator()->standardModel()->vu()- generator()->standardModel()->au(); } else { c0L = generator()->standardModel()->vd()+ generator()->standardModel()->ad(); c0R = generator()->standardModel()->vd()- generator()->standardModel()->ad(); } if(abs(partons_[system][2]->id())%2==0) { c1L = generator()->standardModel()->vu()+ generator()->standardModel()->au(); c1R = generator()->standardModel()->vu()- generator()->standardModel()->au(); } else { c1L = generator()->standardModel()->vd()+ generator()->standardModel()->ad(); c1R = generator()->standardModel()->vd()- generator()->standardModel()->ad(); } c0L *= 0.25; c0R *= 0.25; c1L *= 0.25; c1R *= 0.25; } // Matrix element variables double G1 = sqr(c0L*c1L)+sqr(c0R*c1R); double G2 = sqr(c0L*c1R)+sqr(c0R*c1L); Energy4 term2,term3,loME; if(partons_[system][0]->id()>0) { if(partons_[system][2]->id()>0) { term2 = loMatrixElement(r2-qnlo,pother_[system][0], r2 ,pother_[system][1],G1,G2); term3 = loMatrixElement(r3 ,pother_[system][0], qnlo+r3,pother_[system][1],G1,G2); loME = loMatrixElement(psystem_[system][0],pother_[system][0], psystem_[system][1],pother_[system][1],G1,G2); } else { term2 = loMatrixElement(r2-qnlo,pother_[system][1], r2 ,pother_[system][0],G1,G2); term3 = loMatrixElement(r3 ,pother_[system][1], qnlo+r3,pother_[system][0],G1,G2); loME = loMatrixElement(psystem_[system][0],pother_[system][1], psystem_[system][1],pother_[system][0],G1,G2); } } else { if(partons_[system][2]->id()>0) { term2 = loMatrixElement(r2 ,pother_[system][0], r2-qnlo,pother_[system][1],G1,G2); term3 = loMatrixElement(qnlo+r3,pother_[system][0], r3 ,pother_[system][1],G1,G2); loME = loMatrixElement(psystem_[system][1],pother_[system][0], psystem_[system][0],pother_[system][1],G1,G2); } else { term2 = loMatrixElement(r2 ,pother_[system][1], r2-qnlo,pother_[system][0],G1,G2); term3 = loMatrixElement(qnlo+r3,pother_[system][1], r3 ,pother_[system][0],G1,G2); loME = loMatrixElement(psystem_[system][1],pother_[system][1], psystem_[system][0],pother_[system][0],G1,G2); } } double R3 = sqr(x3)/(sqr(x3)+sqr(xT))*(term3/loME); double R2 = sqr(x2)/(sqr(x2)+sqr(xT))*(term2/loME); // debuggingMatrixElement(true, // partons_[system][0],partons_[system][1], // partons_[system][2],partons_[system][3], // psystem_[system][0],psystem_[system][1], // pother_ [system][0],pother_ [system][1], // p0,p1,p2,phiggs_[system],q2_[system], // 8.*Constants::pi/zp/(1.-zp)*(sqr(xp)*(sqr(x3)+sqr(xT))*R3+ // sqr(xp)*(sqr(x2)+sqr(xT))*R2)); return TRfact* (sqr(xp)*(sqr(x3)+sqr(xT))*R3+ sqr(xp)*(sqr(x2)+sqr(xT))*R2); } Energy4 MEPP2HiggsVBF::loMatrixElement(const Lorentz5Momentum &p1, const Lorentz5Momentum &p2, const Lorentz5Momentum &q1, const Lorentz5Momentum &q2, double G1, double G2) const { return G1*(p1*p2)*(q1*q2) + G2*(p1*q2)*(q1*p2); } void MEPP2HiggsVBF::initializeMECorrection(RealEmissionProcessPtr born, double & initial, double & final) { systems_.clear(); for(unsigned int ix=0;ixbornIncoming().size();++ix) { if(QuarkMatcher::Check(born->bornIncoming()[ix]->data())) { systems_.push_back(tChannelPair()); systems_.back().hadron = born->hadrons()[ix]; systems_.back().beam = dynamic_ptr_cast(systems_.back().hadron->dataPtr()); systems_.back().incoming = born->bornIncoming()[ix]; systems_.back().pdf = systems_.back().beam->pdf(); } } vector outgoing; for(unsigned int ix=0;ixbornOutgoing().size();++ix) { if(born->bornOutgoing()[ix]->id()==ParticleID::h0) higgs_ = born->bornOutgoing()[ix]; else if(QuarkMatcher::Check(born->bornOutgoing()[ix]->data())) outgoing.push_back(born->bornOutgoing()[ix]); } assert(outgoing.size()==2&&higgs_); // match up the quarks for(unsigned int ix=0;ixcolourLine()) { for(unsigned int iy=0;iycolourLine()==systems_[ix].incoming->colourLine()) { systems_[ix].outgoing=outgoing[iy]; break; } } } else { for(unsigned int iy=0;iyantiColourLine()==systems_[ix].incoming->antiColourLine()) { systems_[ix].outgoing=outgoing[iy]; break; } } } } assert(systems_[0].outgoing&&systems_[1].outgoing); assert(systems_.size()==2); initial = initial_; final = final_; } RealEmissionProcessPtr MEPP2HiggsVBF::applyHardMatrixElementCorrection(RealEmissionProcessPtr born) { static const double eps = 1e-6; // select emitting line if(UseRandom::rndbool()) swap(systems_[0],systems_[1]); // extract the born variables q_[0] = systems_[0].outgoing->momentum()-systems_[0].incoming->momentum(); q2_[0] = -q_[0].m2(); Energy Q = sqrt(q2_[0]); xB_[0] = systems_[0].incoming->momentum().rho()/systems_[0].hadron->momentum().rho(); // construct lorentz transform from lab to breit frame Lorentz5Momentum phadron = systems_[0].hadron->momentum(); phadron.setMass(0.*GeV); phadron.rescaleEnergy(); Lorentz5Momentum pcmf = phadron+0.5/xB_[0]*q_[0]; pcmf.rescaleMass(); LorentzRotation rot(-pcmf.boostVector()); Lorentz5Momentum pbeam = rot*phadron; Axis axis(pbeam.vect().unit()); double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); rot.rotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); Lorentz5Momentum pout = rot*(systems_[1].outgoing->momentum()+higgs_->momentum()); rot.rotateZ(-atan2(pout.y(),pout.x())); // calculate the A coefficient for the correlations acoeff_ = A(systems_[0].incoming->dataPtr(),systems_[0].outgoing->dataPtr(), systems_[1].incoming->dataPtr(),systems_[1].outgoing->dataPtr()); vector azicoeff; // select the type of process bool BGF = UseRandom::rnd()>procProb_; double wgt,xp,zp,x1,x2,x3,xperp; l_ = 2.*(rot*systems_[1].incoming->momentum())/Q; m_ = 2.*(rot*systems_[1].outgoing->momentum())/Q; // compton process if(!BGF) { wgt = generateComptonPoint(xp,zp); if(xpvalue(mu2)/procProb_; // PDF piece wgt *= systems_[0].pdf->xfx(systems_[0].beam, systems_[0].incoming->dataPtr(),mu2 ,xB_[0]/xp)/ systems_[0].pdf->xfx(systems_[0].beam, systems_[0].incoming->dataPtr(),scale(),xB_[0] ); // numerator factors wgt /= (1.-xp)*(1.-zp); // other bits xperp = sqrt(4.*(1.-xp)*(1.-zp)*zp/xp); x1 = -1./xp; x2 = 1.-(1.-zp)/xp; x3 = 2.+x1-x2; // matrix element pieces azicoeff = ComptonME(xp,x2,xperp,l_,m_); } else { wgt = generateBGFPoint(xp,zp); if(xp<1e-6) return RealEmissionProcessPtr(); // common pieces Energy2 mu2 = q2_[0]*((1.-xp)*(1-zp)*zp/xp+1); wgt *= 0.25/Constants::pi*alpha_->value(mu2)/(1.-procProb_); // PDF piece wgt *= systems_[0].pdf->xfx(systems_[0].beam, gluon_ ,mu2 ,xB_[0]/xp)/ systems_[0].pdf->xfx(systems_[0].beam, systems_[0].incoming->dataPtr(),scale(),xB_[0] ); // numerator factors wgt /= (1.-zp); // other bits xperp = sqrt(4.*(1.-xp)*(1.-zp)*zp/xp); x1 = -1./xp; x2 = 1.-(1.-zp)/xp; x3 = 2.+x1-x2; // matrix element pieces azicoeff = BGFME(xp,x2,x3,xperp,l_,m_); } // compute the azimuthal average of the weight wgt *= azicoeff[0]+0.5*(azicoeff[2]+azicoeff[4]); // finally factor as picked one line wgt *= 2.; // decide whether or not to accept the weight if(UseRandom::rnd()>wgt) return RealEmissionProcessPtr(); // if accepted generate generate phi unsigned int itry(0); double phimax = std::accumulate(azicoeff.begin(),azicoeff.end(),0.); double phiwgt,phi; do { phi = UseRandom::rnd()*Constants::twopi; double cphi(cos(phi)),sphi(sin(phi)); phiwgt = azicoeff[0]+azicoeff[5]*sphi*cphi +azicoeff[1]*cphi+azicoeff[2]*sqr(cphi) +azicoeff[3]*sphi+azicoeff[4]*sqr(sphi); ++itry; } while (phimax*UseRandom::rnd() > phiwgt && itry<200); if(itry==200) throw Exception() << "Too many tries in VBFMECorrection" << "::applyHardMatrixElementCorrection() to" << " generate phi" << Exception::eventerror; // compute the new incoming and outgoing momenta Lorentz5Momentum p1 = Lorentz5Momentum( 0.5*Q*xperp*cos(phi), 0.5*Q*xperp*sin(phi), -0.5*Q*x2,0.*GeV,0.*GeV); p1.rescaleEnergy(); Lorentz5Momentum p2 = Lorentz5Momentum(-0.5*Q*xperp*cos(phi),-0.5*Q*xperp*sin(phi), -0.5*Q*x3,0.*GeV,0.*GeV); p2.rescaleEnergy(); Lorentz5Momentum pin(0.*GeV,0.*GeV,-0.5*x1*Q,-0.5*x1*Q,0.*GeV); // debugging code to test vs helicity amplitude expression for matrix elements // double cphi(cos(phi)),sphi(sin(phi)); // double old = (azicoeff[0]+azicoeff[5]*sphi*cphi // +azicoeff[1]*cphi+azicoeff[2]*sqr(cphi) // +azicoeff[3]*sphi+azicoeff[4]*sqr(sphi)); // if(!BGF) { // old *= 8.*Constants::pi/(1.-xp)/(1.-zp); // } // else { // old *= 8.*Constants::pi/zp/(1.-zp); // } // debuggingMatrixElement(BGF, // systems_[0].incoming->dataPtr(), // systems_[0].outgoing->dataPtr(), // systems_[1].incoming->dataPtr(), // systems_[1].outgoing->dataPtr(), // rot*systems_[0].incoming->momentum(), // rot*systems_[0].outgoing->momentum(), // rot*systems_[1].incoming->momentum(), // rot*systems_[1].outgoing->momentum(), // pin,p1,p2,rot*higgs_->momentum(), // q2_[0],scale(),old); // we need inverse of the rotation, i.e back to lab from breit rot.invert(); // transform the momenta to lab frame pin *= rot; p1 *= rot; p2 *= rot; // test to ensure outgoing particles can be put on-shell if(!BGF) { if(p1.e()dataPtr()->constituentMass()) return RealEmissionProcessPtr(); if(p2.e()constituentMass()) return RealEmissionProcessPtr(); } else { if(p1.e()dataPtr() ->constituentMass()) return RealEmissionProcessPtr(); if(p2.e()dataPtr()->CC()->constituentMass()) return RealEmissionProcessPtr(); } // stats for weights > 1 if(wgt>1.) { ++nover_; if(!BGF) maxwgt_.first = max(maxwgt_.first ,wgt); else maxwgt_.second = max(maxwgt_.second,wgt); } // create the new particles and add to ShowerTree bool isQuark = systems_[0].incoming->colourLine(); bool FSR= false; PPtr newin,newout,emitted; if(!BGF) { newin = systems_[0].incoming->dataPtr()->produceParticle(pin); emitted = gluon_ ->produceParticle(p2 ); newout = systems_[0].outgoing->dataPtr()->produceParticle(p1 ); emitted->incomingColour(newin,!isQuark); emitted->colourConnect(newout,!isQuark); FSR = xp>zp; } else { newin = gluon_ ->produceParticle(pin); emitted = systems_[0].incoming->dataPtr()->CC()->produceParticle(p2 ); newout = systems_[0].outgoing->dataPtr() ->produceParticle(p1 ); emitted->incomingColour(newin, isQuark); newout ->incomingColour(newin,!isQuark); FSR = false; } pair x; pair radiators; if(born->bornIncoming()[0]!=systems_[0].incoming) { born->incoming().push_back(born->bornIncoming()[0]); born->incoming().push_back(newin); x.first = born->bornIncoming()[0]->momentum().rho()/born->hadrons()[0]->momentum().rho(); x.second = x.first = xB_[0]/xp; radiators.first = 1; } else { born->incoming().push_back(newin); born->incoming().push_back(born->bornIncoming()[1]); x.first = xB_[0]/xp; x.second = born->bornIncoming()[1]->momentum().rho()/born->hadrons()[1]->momentum().rho(); radiators.first = 0; } born->x(x); for(unsigned int ix=0;ixbornOutgoing().size();++ix) { if(born->bornOutgoing()[ix]!=systems_[0].outgoing) { born->outgoing().push_back(born->bornOutgoing()[ix]); } else { radiators.second = born->outgoing().size()+2; born->outgoing().push_back(newout); } } if(FSR) swap(radiators.first,radiators.second); born->emitter (radiators.first ); born->spectator(radiators.second); born->emitted(born->outgoing().size()+2); // radiated particle born->outgoing().push_back(emitted); born->interaction(ShowerInteraction::QCD); return born; } double MEPP2HiggsVBF::A(tcPDPtr qin1, tcPDPtr qout1, tcPDPtr qin2, tcPDPtr ) { double output; // charged current if(qin1->id()!=qout1->id()) { output = 2; } // neutral current else { double cvl,cal,cvq,caq; if(abs(qin2->id())%2==0) { cvl = generator()->standardModel()->vu(); cal = generator()->standardModel()->au(); } else { cvl = generator()->standardModel()->vd(); cal = generator()->standardModel()->ad(); } if(abs(qin1->id())%2==0) { cvq = generator()->standardModel()->vu(); caq = generator()->standardModel()->au(); } else { cvq = generator()->standardModel()->vd(); caq = generator()->standardModel()->ad(); } output = 8.*cvl*cal*cvq*caq/(sqr(cvl)+sqr(cal))/(sqr(cvq)+sqr(caq)); } if(qin1->id()<0) output *= -1.; if(qin2->id()<0) output *= -1; return output; } double MEPP2HiggsVBF::generateComptonPoint(double &xp, double & zp) { static const double maxwgt = 50.; double wgt,xperp2,x2; do { xp = UseRandom::rnd(); double zpmin = xp, zpmax = 1./(1.+xp*(1.-xp)); zp = 1.-pow((1.-zpmin)/(1.-zpmax),UseRandom::rnd())*(1.-zpmax); wgt = log((1.-zpmin)/(1.-zpmax))*(1.-zp); if(UseRandom::rndbool()) swap(xp,zp); xperp2 = 4.*(1.-xp)*(1.-zp)*zp/xp; x2 = 1.-(1.-zp)/xp; wgt *= 2.*(1.+sqr(xp)*(sqr(x2)+1.5*xperp2))/(1.-xp)/(1.-zp); if(wgt>maxwgt) if(wgt>maxwgt) { ostringstream wstring; wstring << "MEPP2HiggsVBF::generateComptonPoint() " << "Weight greater than maximum" << "wgt = " << wgt << " maxwgt = " << maxwgt << "\n"; generator()->logWarning( Exception(wstring.str(), Exception::warning) ); } } while(wgtmaxwgt) { ostringstream wstring; wstring << "DISBase::generateBGFPoint " << "Weight greater than maximum " << "wgt = " << wgt << " maxwgt = 1\n"; generator()->logWarning( Exception(wstring.str(), Exception::warning) ); } } while(wgt & ids, const double & z, const Energy & scale, const Energy & pT) { bool veto = !UseRandom::rndbool(fs ? 1./final_ : 1./initial_); // check if me correction should be applied long id[2]={progenitor->id(),parent->id()}; if(id[0]!=id[1]||id[1]==ParticleID::g) return veto; // if not from the right side if(progenitor!=systems_[0].incoming && progenitor!=systems_[0].outgoing) return veto; // check if hardest so far if(pT azicoeff = ComptonME(xp,x2,xperp,l_,m_); wgt = (azicoeff[0]+0.5*azicoeff[2]+0.5*azicoeff[4])* xp/(1.+sqr(z))/final_; if(wgt<.0||wgt>1.) { ostringstream wstring; wstring << "Soft ME correction weight too large or " << "negative for FSR in MEPP2HiggsVBF::" << "softMatrixElementVeto() soft weight " << " xp = " << xp << " zp = " << zp << " weight = " << wgt << "\n"; generator()->logWarning( Exception(wstring.str(), Exception::warning) ); } } else { double xp = 2.*z/(1.+zk+sqrt(sqr(1.+zk)-4.*z*zk)); double zp = 0.5* (1.-zk+sqrt(sqr(1.+zk)-4.*z*zk)); double xperp = sqrt(4.*(1.-xp)*(1.-zp)*zp/xp); double x1 = -1./xp, x2 = 1.-(1.-zp)/xp, x3 = 2.+x1-x2; // compton if(ids[0]->id()!=ParticleID::g) { vector azicoeff = ComptonME(xp,x2,xperp,l_,m_); wgt = (azicoeff[0]+0.5*azicoeff[2]+0.5*azicoeff[4])* xp*(1.-z)/(1.-xp)/(1.+sqr(z))/(1.-zp+xp-2.*xp*(1.-zp)); } // BGF else { vector azicoeff = BGFME(xp,x2,x3,xperp,l_,m_); wgt = (azicoeff[0]+0.5*azicoeff[2]+0.5*azicoeff[4])* xp/(1.-zp+xp-2.*xp*(1.-zp))/(sqr(z)+sqr(1.-z)); } wgt /=initial_; if(wgt<.0||wgt>1.) { ostringstream wstring; wstring << "Soft ME correction weight too large or " << "negative for ISR in MEPP2HiggsVBF::" << "softMatrixElementVeto() soft weight " << " xp = " << xp << " zp = " << zp << " weight = " << wgt << "\n"; generator()->logWarning( Exception(wstring.str(), Exception::warning) ); } } // return whether or not vetoed return !UseRandom::rndbool(wgt); } vector MEPP2HiggsVBF::ComptonME(double xp, double x2, double xperp, LorentzVector l, LorentzVector m) { vector output(6,0.); double cos2 = x2 /sqrt(sqr(x2)+sqr(xperp)); double sin2 = xperp/sqrt(sqr(x2)+sqr(xperp)); // no phi dependence output[0] = l.t()*m.t()-l.z()*m.z()*sqr(cos2)+0.5*acoeff_*cos2*(l.t()*m.z()-l.z()*m.t()); // cos(phi) output[1] = sin2*(-l.x()*m.t()-l.t()*m.x() + 0.5*acoeff_*cos2*(l.z()*m.x()-m.z()*l.x())); // cos(phi)^2 output[2] = +sqr(sin2)*l.x()*m.x(); // sin(phi) output[3] = sin2*(-l.t()*m.y()-l.y()*m.t() + 0.5*acoeff_*cos2*(l.z()*m.y()-m.z()*l.y())); // sin(phi)^2 output[4] = +sqr(sin2)*l.y()*m.y(); // sin(phi)cos(phi) output[5] = +sqr(sin2)*(m.y()*l.x()+m.x()*l.y()); // additional factors double denom = -l.z()*m.z()+l.t()*m.t()+0.5*acoeff_*(l.t()*m.z()-l.z()*m.t()); double fact = sqr(xp)*(sqr(x2)+sqr(xperp))/denom; for(unsigned int ix=0;ix MEPP2HiggsVBF::BGFME(double xp, double x2, double x3, double xperp, LorentzVector l, LorentzVector m) { vector output(6,0.); double denom = -l.z()*m.z()+l.t()*m.t()+0.5*acoeff_*(l.t()*m.z()-l.z()*m.t()); double cos2 = x2 /sqrt(sqr(x2)+sqr(xperp)); double sin2 = xperp/sqrt(sqr(x2)+sqr(xperp)); double fact2 = sqr(xp)*(sqr(x2)+sqr(xperp))/denom; double cos3 = x3 /sqrt(sqr(x3)+sqr(xperp)); double sin3 = xperp/sqrt(sqr(x3)+sqr(xperp)); double fact3 = sqr(xp)*(sqr(x3)+sqr(xperp))/denom; // no phi dependence output[0] = fact2*(l.t()*m.t()-l.z()*m.z()*sqr(cos2) + 0.5*acoeff_*cos2*(l.t()*m.z()-l.z()*m.t())) + fact3*(l.t()*m.t()-l.z()*m.z()*sqr(cos3) - 0.5*acoeff_*cos3*(l.t()*m.z()-l.z()*m.t())); // cos(phi) output[1] = fact2*sin2*( - l.x()*m.t()-l.t()*m.x() + 0.5*acoeff_*cos2*(l.z()*m.x()-m.z()*l.x())) - fact3*sin3*( - l.x()*m.t()-l.t()*m.x() - 0.5*acoeff_*cos3*(l.z()*m.x()-m.z()*l.x())) ; // cos(phi)^2 output[2] = (fact2*sqr(sin2)+fact3*sqr(sin3))*l.x()*m.x(); // sin(phi) output[3] = fact2*sin2*( - l.t()*m.y()-l.y()*m.t() + 0.5*acoeff_*cos2*(l.z()*m.y()-m.z()*l.y())) - fact3*sin3*( - l.t()*m.y()-l.y()*m.t() - 0.5*acoeff_*cos3*(l.z()*m.y()-m.z()*l.y())); // sin(phi)^2 output[4] = (fact2*sqr(sin2)+fact3*sqr(sin3))*l.y()*m.y(); // sin(phi)cos(phi) output[5] = (fact2*sqr(sin2)+fact3*sqr(sin3))*(m.y()*l.x()+m.x()*l.y()); // return the answer return output; } diff --git a/MatrixElement/Hadron/MEPP2QQHiggs.cc b/MatrixElement/Hadron/MEPP2QQHiggs.cc --- a/MatrixElement/Hadron/MEPP2QQHiggs.cc +++ b/MatrixElement/Hadron/MEPP2QQHiggs.cc @@ -1,636 +1,636 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the MEPP2QQH class. // #include "MEPP2QQHiggs.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "Herwig/Models/StandardModel/StandardModel.h" #include "ThePEG/Utilities/SimplePhaseSpace.h" #include "Herwig/Utilities/Kinematics.h" #include "ThePEG/Cuts/Cuts.h" #include "Herwig/MatrixElement/HardVertex.h" using namespace Herwig; MEPP2QQHiggs::MEPP2QQHiggs() : quarkFlavour_(6), process_(0), shapeOpt_(2), mh_(), wh_(), alpha_(1.1) {} // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigMEPP2QQHiggs("Herwig::MEPP2QQHiggs", "HwMEHadron.so"); void MEPP2QQHiggs::Init() { static ClassDocumentation documentation ("The MEPP2QQHiggs class implements the matrix elements for the " "production of the Higgs boson in association with a heavy quark-antiquark pair"); static Switch interfaceQuarkType ("QuarkType", "The type of quark", &MEPP2QQHiggs::quarkFlavour_, 6, false, false); static SwitchOption interfaceQuarkTypeBottom (interfaceQuarkType, "Bottom", "Produce bottom-antibottom", 5); static SwitchOption interfaceQuarkTypeTop (interfaceQuarkType, "Top", "Produce top-antitop", 6); static Switch interfaceProcess ("Process", "Which subprocesses to include", &MEPP2QQHiggs::process_, 0, false, false); static SwitchOption interfaceProcessAll (interfaceProcess, "All", "Include all subprocesses", 0); static SwitchOption interfaceProcess1 (interfaceProcess, "gg", "Include only gg -> QQbarH processes", 1); static SwitchOption interfaceProcessqbarqbarqbarqbar (interfaceProcess, "qqbar", "Include only qbar qbar -> QQbarH processes", 2); static Switch interfaceShapeOption ("ShapeScheme", "Option for the treatment of the Higgs resonance shape", &MEPP2QQHiggs::shapeOpt_, 2, false, false); static SwitchOption interfaceStandardShapeFixed (interfaceShapeOption, "FixedBreitWigner", "Breit-Wigner s-channel resonance", 1); static SwitchOption interfaceStandardShapeRunning (interfaceShapeOption, "MassGenerator", "Use the mass generator to give the shape", 2); static SwitchOption interfaceStandardShapeOnShell (interfaceShapeOption, "OnShell", "Produce an on-shell Higgs boson", 0); static Parameter interfaceAlpha ("Alpha", "Power for the generation of the tranverse mass in the pT mapping", &MEPP2QQHiggs::alpha_, 1.1, 0.0, 10.0, false, false, Interface::limited); } Energy2 MEPP2QQHiggs::scale() const { return sHat(); // return sqr(mePartonData()[2]->mass()+mePartonData()[3]->mass()+ // mePartonData()[4]->mass()); } int MEPP2QQHiggs::nDim() const { return 4 + int(shapeOpt_>0); } unsigned int MEPP2QQHiggs::orderInAlphaS() const { return 2; } unsigned int MEPP2QQHiggs::orderInAlphaEW() const { return 1; } IBPtr MEPP2QQHiggs::clone() const { return new_ptr(*this); } IBPtr MEPP2QQHiggs::fullclone() const { return new_ptr(*this); } void MEPP2QQHiggs::setKinematics() { HwMEBase::setKinematics(); } void MEPP2QQHiggs::persistentOutput(PersistentOStream & os) const { os << quarkFlavour_ << process_ << shapeOpt_ << ounit(mh_,GeV) << ounit(wh_,GeV) << hmass_ << GGGVertex_ << QQGVertex_ << QQHVertex_ << gluon_ << higgs_ << quark_ << antiquark_ << alpha_; } void MEPP2QQHiggs::persistentInput(PersistentIStream & is, int) { is >> quarkFlavour_ >> process_ >> shapeOpt_ >> iunit(mh_,GeV) >> iunit(wh_,GeV) >> hmass_ >> GGGVertex_ >> QQGVertex_ >> QQHVertex_ >> gluon_ >> higgs_ >> quark_ >> antiquark_ >> alpha_; } void MEPP2QQHiggs::doinit() { HwMEBase::doinit(); // stuff for the higgs mass higgs_=getParticleData(ParticleID::h0); mh_ = higgs_->mass(); wh_ = higgs_->width(); if(higgs_->massGenerator()) { hmass_=dynamic_ptr_cast(higgs_->massGenerator()); } if(shapeOpt_==2&&!hmass_) throw InitException() << "If using the mass generator for the line shape in MEPP2QQHiggs::doinit()" << "the mass generator must be an instance of the GenericMassGenerator class" << Exception::runerror; // get the vertex pointers from the SM object tcHwSMPtr hwsm= dynamic_ptr_cast(standardModel()); // do the initialisation if(!hwsm) throw InitException() << "Wrong type of StandardModel object in " << "MEPP2QQHiggs::doinit() the Herwig" << " version must be used" << Exception::runerror; GGGVertex_ = hwsm->vertexGGG(); QQGVertex_ = hwsm->vertexFFG(); QQHVertex_ = hwsm->vertexFFH(); // get the particle data objects gluon_=getParticleData(ParticleID::g); for(int ix=1;ix<=6;++ix) { quark_.push_back( getParticleData( ix)); antiquark_.push_back(getParticleData(-ix)); } } bool MEPP2QQHiggs::generateKinematics(const double * r) { jacobian(1.); // CMS energy Energy rs = sqrt(sHat()); // quark mass Energy mq(quark_[quarkFlavour_-1]->mass()); // generate the higgs mass Energy mh(mh_); if(shapeOpt_!=0) { Energy mhmax = min(rs-2.*mq,higgs_->massMax()); Energy mhmin = max(ZERO ,higgs_->massMin()); if(mhmax<=mhmin) return false; double rhomin = atan2((sqr(mhmin)-sqr(mh_)), mh_*wh_); double rhomax = atan2((sqr(mhmax)-sqr(mh_)), mh_*wh_); mh = sqrt(mh_*wh_*tan(rhomin+r[4]*(rhomax-rhomin))+sqr(mh_)); jacobian(jacobian()*(rhomax-rhomin)); } if(rs ZERO ) { double ctm = 1.0 - sqr(ptmin/p1); if ( ctm <= 0.0 ) return false; ctmin = max(ctmin, -sqrt(ctm)); ctmax = min(ctmax, sqrt(ctm)); } double cos1 = getCosTheta(ctmin,ctmax,r[0]); double sin1(sqrt(1.-sqr(cos1))); double phi1 = Constants::twopi*UseRandom::rnd(); Lorentz5Momentum p13(sin1*p1*cos(phi1),sin1*p1*sin(phi1),cos1*p1, sqrt(sqr(p1)+m132),m13); meMomenta()[3].setVect(Momentum3(-sin1*p1*cos(phi1),-sin1*p1*sin(phi1),-cos1*p1)); meMomenta()[3].setMass(mq); meMomenta()[3].rescaleEnergy(); bool test=Kinematics::twoBodyDecay(p13,mq,mh,-1.+2*r[2],r[3]*Constants::twopi, meMomenta()[2],meMomenta()[4]); if(!test) return false; m232 = (meMomenta()[3]+meMomenta()[4]).m2(); double D = 2./(pow(sqr(mq)/(m132-sqr(mq)),alpha_)+ pow(sqr(mq)/(m232-sqr(mq)),alpha_)); jacobian(0.5*jacobian()*rs/m13*sqr(mq)*D*(rhomax-rhomin)/sHat()); } // second branch else { double rtemp = 2.*(r[1]-0.5); double rho = rhomin+rtemp*(rhomax-rhomin); if(alpha_==0) m232 = sqr(mq)*rho; else if(alpha_==1) m232 = sqr(mq)*(exp(rho)+1.); else m232 = sqr(mq)*(pow(rho,1./(1.-alpha_))+1.); Energy m23 = sqrt(m232); try { p1 = SimplePhaseSpace::getMagnitude(sHat(), m23, mq); p2 = SimplePhaseSpace::getMagnitude(m232,mq,mh); } catch ( ImpossibleKinematics ) { return false; } Energy ptmin = lastCuts().minKT(mePartonData()[2]); double ctmin = -1.0, ctmax = 1.0; if ( ptmin > ZERO ) { double ctm = 1.0 - sqr(ptmin/p1); if ( ctm <= 0.0 ) return false; ctmin = max(ctmin, -sqrt(ctm)); ctmax = min(ctmax, sqrt(ctm)); } double cos1 = getCosTheta(ctmin,ctmax,r[0]); double sin1(sqrt(1.-sqr(cos1))); double phi1 = Constants::twopi*UseRandom::rnd(); Lorentz5Momentum p23(-sin1*p1*cos(phi1),-sin1*p1*sin(phi1),-cos1*p1, sqrt(sqr(p1)+m232),m23); meMomenta()[2].setVect(Momentum3(sin1*p1*cos(phi1),sin1*p1*sin(phi1),cos1*p1)); meMomenta()[2].setMass(mq); meMomenta()[2].rescaleEnergy(); bool test=Kinematics::twoBodyDecay(p23,mq,mh,-1.+2*r[2],r[3]*Constants::twopi, meMomenta()[3],meMomenta()[4]); if(!test) return false; m132 = (meMomenta()[2]+meMomenta()[4]).m2(); double D = 2./(pow(sqr(mq)/(m132-sqr(mq)),alpha_)+ pow(sqr(mq)/(m232-sqr(mq)),alpha_)); jacobian(0.5*jacobian()*rs/m23*sqr(mq)*D*(rhomax-rhomin)/sHat()); } // calculate jacobian jacobian(0.125*jacobian()*p1*p2/sHat()); // check cuts vector out; tcPDVector tout; for(unsigned int ix=2;ix<5;++ix) { out .push_back(meMomenta()[ix]); tout.push_back(mePartonData()[ix]); } return lastCuts().passCuts(tout, out, mePartonData()[0], mePartonData()[1]); } CrossSection MEPP2QQHiggs::dSigHatDR() const { using Constants::pi; // jacobian factor for the higgs InvEnergy2 bwfact; Energy moff = meMomenta()[4].mass(); if(shapeOpt_==1) { bwfact = mePartonData()[4]->generateWidth(moff)*moff/pi/ (sqr(sqr(moff)-sqr(mh_))+sqr(mh_*wh_)); } - else { + else if(shapeOpt_==2) { bwfact = hmass_->BreitWignerWeight(moff); } double jac1 = shapeOpt_==0 ? 1. : double(bwfact*(sqr(sqr(moff)-sqr(mh_))+sqr(mh_*wh_))/(mh_*wh_)); return sqr(hbarc)*me2()*jacobian()*jac1/sHat()/pow(Constants::twopi,3); } void MEPP2QQHiggs::getDiagrams() const { tPDPtr Q = quark_[quarkFlavour_-1]; tPDPtr QB = antiquark_[quarkFlavour_-1]; // gg -> q qbar h0 subprocesses if(process_==0||process_==1) { // first t-channel add(new_ptr((Tree2toNDiagram(3), gluon_, QB, gluon_, 1, Q, 4, Q , 2, QB, 4, higgs_, -1))); add(new_ptr((Tree2toNDiagram(4), gluon_, QB, QB, gluon_, 1, Q, 3, QB, 2, higgs_, -2))); add(new_ptr((Tree2toNDiagram(3),gluon_,QB,gluon_, 1, Q, 2, QB, 5, QB, 5, higgs_, -3))); // interchange add(new_ptr((Tree2toNDiagram(3),gluon_,Q,gluon_, 2, Q, 4, Q , 1, QB, 4, higgs_, -4))); add(new_ptr((Tree2toNDiagram(4),gluon_,Q,Q,gluon_, 3, Q, 1, QB, 2, higgs_, -5))); add(new_ptr((Tree2toNDiagram(3),gluon_,Q,gluon_, 2, Q, 1, QB, 5, QB, 5, higgs_, -6))); // s-channel add(new_ptr((Tree2toNDiagram(2),gluon_,gluon_, 1, gluon_, 3, Q, 4, Q, 3, QB, 4, higgs_, -7))); add(new_ptr((Tree2toNDiagram(2),gluon_,gluon_, 1, gluon_, 3,Q, 3, QB, 5, QB, 5, higgs_, -8))); } // q qbar -> q qbar if(process_==0||process_==2) { for(unsigned int ix=1;ix<5;++ix) { // gluon s-channel add(new_ptr((Tree2toNDiagram(2),quark_[ix-1], antiquark_[ix-1], 1, gluon_, 3, Q, 4, Q , 3, QB, 4, higgs_, -9))); add(new_ptr((Tree2toNDiagram(2),quark_[ix-1], antiquark_[ix-1], 1, gluon_, 3, Q, 3, QB, 5, QB, 5, higgs_, -10))); } } } double MEPP2QQHiggs::me2() const { // total matrix element double me(0.); // gg initiated processes if(mePartonData()[0]->id()==ParticleID::g) { VectorWaveFunction g1w(meMomenta()[0],mePartonData()[0],incoming); VectorWaveFunction g2w(meMomenta()[1],mePartonData()[1],incoming); SpinorBarWaveFunction qw(meMomenta()[2],mePartonData()[2],outgoing); SpinorWaveFunction qbarw(meMomenta()[3],mePartonData()[3],outgoing); ScalarWaveFunction higgs(meMomenta()[4],mePartonData()[4],1.,outgoing); vector g1,g2; vector q; vector qbar; for(unsigned int ix=0;ix<2;++ix) { g1w.reset(2*ix);g1.push_back(g1w); g2w.reset(2*ix);g2.push_back(g2w); qw.reset(ix);q.push_back(qw); qbarw.reset(ix);qbar.push_back(qbarw); } // calculate the matrix element me=ggME(g1,g2,q,qbar,higgs,0); } // q qbar initiated else { SpinorWaveFunction q1w(meMomenta()[0],mePartonData()[0],incoming); SpinorBarWaveFunction q2w(meMomenta()[1],mePartonData()[1],incoming); SpinorBarWaveFunction q3w(meMomenta()[2],mePartonData()[2],outgoing); SpinorWaveFunction q4w(meMomenta()[3],mePartonData()[3],outgoing); ScalarWaveFunction higgs(meMomenta()[4],mePartonData()[4],1.,outgoing); vector q1,q4; vector q2,q3; for(unsigned int ix=0;ix<2;++ix) { q1w.reset(ix);q1.push_back(q1w); q2w.reset(ix);q2.push_back(q2w); q3w.reset(ix);q3.push_back(q3w); q4w.reset(ix);q4.push_back(q4w); } // calculate the matrix element me = qqME(q1,q2,q3,q4,higgs,0); } return me*sHat()*UnitRemoval::InvE2; } double MEPP2QQHiggs::ggME(vector &g1, vector &g2, vector & q, vector & qbar, ScalarWaveFunction & hwave, unsigned int iflow) const { // scale Energy2 mt(scale()); Energy mass = q[0].mass(); // matrix element to be stored if(iflow!=0) me_.reset(ProductionMatrixElement(PDT::Spin1,PDT::Spin1, PDT::Spin1Half,PDT::Spin1Half, PDT::Spin0)); // calculate the matrix element double output(0.),sumflow[2]={0.,0.}; double sumdiag[8]={0.,0.,0.,0.,0.,0.,0.,0.}; Complex diag[8],flow[2]; VectorWaveFunction interv; SpinorWaveFunction inters,QBoff; SpinorBarWaveFunction intersb,Qoff; for(unsigned int ihel1=0;ihel1<2;++ihel1) { for(unsigned int ihel2=0;ihel2<2;++ihel2) { interv = GGGVertex_->evaluate(mt,5,gluon_,g1[ihel1],g2[ihel2]); for(unsigned int ohel1=0;ohel1<2;++ohel1) { Qoff = QQHVertex_->evaluate(mt,3,q[ohel1].particle()->CC(), q[ohel1],hwave,mass); for(unsigned int ohel2=0;ohel2<2;++ohel2) { QBoff = QQHVertex_->evaluate(mt,3,qbar[ohel2].particle()->CC(), qbar[ohel2],hwave,mass); // 1st diagram inters = QQGVertex_->evaluate(mt,1,qbar[ohel2].particle()->CC(), qbar[ohel2],g2[ihel2],mass); diag[0] = QQGVertex_->evaluate(mt,inters,Qoff,g1[ihel1]); // 2nd diagram intersb = QQGVertex_->evaluate(mt,1,q[ohel1].particle()->CC(), q[ohel1],g1[ihel1],mass); diag[1] = QQHVertex_->evaluate(mt,inters,intersb,hwave); // 3rd diagram diag[2] = QQGVertex_->evaluate(mt,QBoff,intersb,g2[ihel2]); // 4th diagram inters = QQGVertex_->evaluate(mt,1,qbar[ohel2].particle()->CC(), qbar[ohel2],g1[ihel1],mass); diag[3] = QQGVertex_->evaluate(mt,inters,Qoff,g2[ihel2]); // 5th diagram intersb = QQGVertex_->evaluate(mt,1,q[ohel1].particle()->CC(), q[ohel1],g2[ihel2],mass); diag[4] = QQHVertex_->evaluate(mt,inters,intersb,hwave); // 6th diagram diag[5] = QQGVertex_->evaluate(mt,QBoff,intersb,g1[ihel1]); // 7th diagram diag[6] = QQGVertex_->evaluate(mt,qbar[ohel2],Qoff ,interv); // 8th diagram diag[7] = QQGVertex_->evaluate(mt,QBoff ,q[ohel1],interv); // colour flows flow[0]=diag[0]+diag[1]+diag[2]+(diag[6]+diag[7]); flow[1]=diag[3]+diag[4]+diag[5]-(diag[6]+diag[7]); // sums for(unsigned int ix=0;ix<8;++ix) sumdiag[ix] += norm(diag[ix]); for(unsigned int ix=0;ix<2;++ix) sumflow[ix] += norm(flow[ix]); // total output +=real(flow[0]*conj(flow[0])+flow[1]*conj(flow[1]) -0.25*flow[0]*conj(flow[1])); // store the me if needed if(iflow!=0) me_(2*ihel1,2*ihel2,ohel1,ohel2,0)=flow[iflow-1]; } } } } // select a colour flow flow_ = 1 + UseRandom::rnd2(sumflow[0],sumflow[1]); if(flow_==1) sumdiag[0]=sumdiag[1]=sumdiag[2]=0.; else sumdiag[3]=sumdiag[4]=sumdiag[5]=0.; // select a diagram from that flow double prob = UseRandom::rnd(); for(unsigned int ix=0;ix<8;++ix) { if(prob<=sumdiag[ix]) { diagram_=1+ix; break; } prob -= sumdiag[ix]; } // final part of colour and spin factors return output/48.; } double MEPP2QQHiggs::qqME(vector & q1, vector & q2, vector & q3, vector & q4, ScalarWaveFunction & hwave, unsigned int iflow) const { // scale Energy2 mt(scale()); Energy mass = q3[0].mass(); // matrix element to be stored if(iflow!=0) me_.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1Half,PDT::Spin1Half, PDT::Spin0)); // calculate the matrix element double output(0.),sumdiag[2]={0.,0.}; Complex diag[2]; VectorWaveFunction interv; SpinorWaveFunction QBoff; SpinorBarWaveFunction Qoff; for(unsigned int ihel1=0;ihel1<2;++ihel1) { for(unsigned int ihel2=0;ihel2<2;++ihel2) { interv = QQGVertex_->evaluate(mt,5,gluon_,q1[ihel1],q2[ihel2]); for(unsigned int ohel1=0;ohel1<2;++ohel1) { Qoff = QQHVertex_->evaluate(mt,3,q3[ohel1].particle()->CC(), q3[ohel1],hwave,mass); for(unsigned int ohel2=0;ohel2<2;++ohel2) { QBoff = QQHVertex_->evaluate(mt,3,q4[ohel2].particle()->CC(), q4[ohel2],hwave,mass); // 1st diagram diag[0] = QQGVertex_->evaluate(mt,q4[ohel2],Qoff,interv); // 2nd diagram diag[1] = QQGVertex_->evaluate(mt,QBoff,q3[ohel1],interv); // sum of diagrams for(unsigned int ix=0;ix<2;++ix) sumdiag[ix] += norm(diag[ix]); diag[0] += diag[1]; output += norm(diag[0]); if(iflow!=0) me_(ihel1,ihel2,ohel1,ohel2,0) = diag[0]; } } } } // only 1 colour flow flow_=1; // select a diagram diagram_ = 9+UseRandom::rnd2(sumdiag[0],sumdiag[1]); // final part of colour and spin factors return output/18.; } Selector MEPP2QQHiggs::colourGeometries(tcDiagPtr diag) const { // colour lines for gg -> Q Qbar H static const ColourLines cgg[10]= {ColourLines("1 4 5, -1 -2 3 , -3 -6 "), ColourLines("1 5 , -1 -2 -3 4, -4 -6 "), ColourLines("1 4 , -1 -2 3 , -3 -5 -6"), ColourLines("3 4 5, 1 2 -3 , -1 -6 "), ColourLines("4 5 , 1 2 3 -4, -1 -6"), ColourLines("3 4 , 1 2 -3 , -1 -5 -6"), ColourLines("1 3 4 5, -1 2, -2 -3 -6"), ColourLines("2 3 4 5, 1 -2, -1 -3 -6"), ColourLines("1 3 4, -1 2, -2 -3 -5 -6"), ColourLines("2 3 4, 1 -2, -1 -3 -5 -6")}; // colour lines for q qbar -> Q Qbar H static const ColourLines cqq[2]= {ColourLines("1 3 4 5, -2 -3 -6"), ColourLines("1 3 4 , -2 -3 -5 -6")}; // select the colour flow (as all ready picked just insert answer) Selector sel; switch(abs(diag->id())) { // gg -> q qbar subprocess case 1: case 2: case 3: case 4: case 5: case 6: sel.insert(1.0, &cgg[abs(diag->id())-1]); break; case 7: sel.insert(1.0, &cgg[5 + flow_]); break; case 8: sel.insert(1.0, &cgg[7 + flow_]); break; // q qbar -> q qbar subprocess case 9: case 10: sel.insert(1.0, &cqq[abs(diag->id())-9]); break; } return sel; } Selector MEPP2QQHiggs::diagrams(const DiagramVector & diags) const { // select the diagram, this is easy for us as we have already done it Selector sel; for ( DiagramIndex i = 0; i < diags.size(); ++i ) { if(diags[i]->id()==-int(diagram_)) sel.insert(1.0, i); else sel.insert(0., i); } return sel; } void MEPP2QQHiggs::constructVertex(tSubProPtr sub) { // extract the particles in the hard process ParticleVector hard; hard.push_back(sub->incoming().first); hard.push_back(sub->incoming().second); for(unsigned int ix=0;ix<3;++ix) hard.push_back(sub->outgoing()[ix]); // identify the process and calculate the matrix element if(hard[0]->id()<0) swap(hard[0],hard[1]); if(hard[2]->id()==ParticleID::h0) swap(hard[2],hard[4]); if(hard[3]->id()==ParticleID::h0) swap(hard[3],hard[4]); if(hard[2]->id()<0) swap(hard[2],hard[3]); if(hard[0]->id()==ParticleID::g) { vector g1,g2; vector q; vector qbar; // off-shell wavefunctions for the spin correlations VectorWaveFunction( g1,hard[0],incoming,false,true,true); VectorWaveFunction( g2,hard[1],incoming,false,true,true); SpinorBarWaveFunction(q ,hard[2],outgoing,true ,true); SpinorWaveFunction( qbar,hard[3],outgoing,true ,true); ScalarWaveFunction hwave( hard[4],outgoing,true); g1[1]=g1[2];g2[1]=g2[2]; ggME(g1,g2,q,qbar,hwave,flow_); } // q qbar -> Q Qbar Higgs else { vector q1,q4; vector q2,q3; // off-shell for spin correlations SpinorWaveFunction( q1,hard[0],incoming,false,true); SpinorBarWaveFunction(q2,hard[1],incoming,false,true); SpinorBarWaveFunction(q3,hard[2],outgoing,true ,true); SpinorWaveFunction( q4,hard[3],outgoing,true ,true); ScalarWaveFunction hwave( hard[4],outgoing,true); qqME(q1,q2,q3,q4,hwave,flow_); } // construct the vertex HardVertexPtr hardvertex=new_ptr(HardVertex()); // set the matrix element for the vertex hardvertex->ME(me_); // set the pointers and to and from the vertex for(unsigned int ix=0;ix<5;++ix) hard[ix]->spinInfo()->productionVertex(hardvertex); } diff --git a/MatrixElement/Hadron/MEPP2SingleTop.cc b/MatrixElement/Hadron/MEPP2SingleTop.cc --- a/MatrixElement/Hadron/MEPP2SingleTop.cc +++ b/MatrixElement/Hadron/MEPP2SingleTop.cc @@ -1,659 +1,663 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the MEPP2SingleTop class. // #include "MEPP2SingleTop.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "Herwig/Models/StandardModel/StandardModel.h" #include "Herwig/MatrixElement/HardVertex.h" using namespace Herwig; MEPP2SingleTop::MEPP2SingleTop() : process_(1), maxflavour_(5), topOption_(1), wOption_(1) {} IBPtr MEPP2SingleTop::clone() const { return new_ptr(*this); } IBPtr MEPP2SingleTop::fullclone() const { return new_ptr(*this); } void MEPP2SingleTop::doinit() { HwMEBase::doinit(); vector massopt(2,0); massopt[0] = topOption_; if(process_==1) { massopt[1]= 0; } else if(process_==2) { massopt[1]= 1; } else if(process_==3) { massopt[1]= wOption_; } massOption(massopt); // mass option rescalingOption(2); // get the vertices we need // get a pointer to the standard model object in the run static const tcHwSMPtr hwsm = dynamic_ptr_cast(standardModel()); if (!hwsm) throw InitException() << "hwsm pointer is null in" << " MEPP2SingleTop::doinit()" << Exception::abortnow; // get pointers to all required Vertex objects FFWvertex_ = hwsm->vertexFFW(); FFGvertex_ = hwsm->vertexFFG(); } void MEPP2SingleTop::persistentOutput(PersistentOStream & os) const { os << process_ << FFWvertex_ << FFGvertex_ << maxflavour_ << topOption_ << wOption_; } void MEPP2SingleTop::persistentInput(PersistentIStream & is, int) { is >> process_ >> FFWvertex_ >> FFGvertex_ >> maxflavour_ >> topOption_ >> wOption_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigMEPP2SingleTop("Herwig::MEPP2SingleTop", "HwMEHadron.so"); void MEPP2SingleTop::Init() { static ClassDocumentation documentation ("The MEPP2SingleTop class implements the production of " "a single top quark."); static Switch interfaceProcess ("Process", "The process to generate", &MEPP2SingleTop::process_, 1, false, false); static SwitchOption interfaceProcesstChannel (interfaceProcess, "tChannel", "Generate t-channel W exchange processes", 1); static SwitchOption interfaceProcesssChannel (interfaceProcess, "sChannel", "Generate s-channel W exchange processes", 2); static SwitchOption interfaceProcesstW (interfaceProcess, "tW", "Generate top production in association with a W boson", 3); static Parameter interfaceMaximumFlavour ("MaximumFlavour", "The maximum flavour of the non-top quarks", &MEPP2SingleTop::maxflavour_, 5, 1, 5, false, false, Interface::limited); static Switch interfaceTopMassOption ("TopMassOption", "Option for the treatment of the top quark masses", &MEPP2SingleTop::topOption_, 1, false, false); static SwitchOption interfaceTopMassOptionOnMassShell (interfaceTopMassOption, "OnMassShell", "The top is produced on its mass shell", 1); static SwitchOption interfaceTopMassOptionOffShell (interfaceTopMassOption, "OffShell", "The top is generated off-shell using the mass and width generator.", 2); static Switch interfaceWMassOption ("WMassOption", "Option for the treatment of the top quark masses", &MEPP2SingleTop::wOption_, 1, false, false); static SwitchOption interfaceWMassOptionOnMassShell (interfaceWMassOption, "OnMassShell", "The W is produced on its mass shell", 1); static SwitchOption interfaceWMassOptionOffShell (interfaceWMassOption, "OffShell", "The W is generated off-shell using the mass and width generator.", 2); } Energy2 MEPP2SingleTop::scale() const{ if(process_==2) return sHat(); Energy2 s(0.5*sHat()),u(0.5*(uHat()-meMomenta()[3].mass2())), t(0.5*(tHat()-meMomenta()[2].mass2())); return 4.*s*t*u/(s*s+t*t+u*u); } unsigned int MEPP2SingleTop::orderInAlphaS() const { return process_!=3 ? 0 : 1; } unsigned int MEPP2SingleTop::orderInAlphaEW() const { return process_!=3 ? 2 : 1; } void MEPP2SingleTop::getDiagrams() const { tcPDPtr g = getParticleData(ParticleID::g); tcPDPtr Wp = getParticleData(ParticleID::Wplus ); tcPDPtr Wm = getParticleData(ParticleID::Wminus); tcPDPtr tp = getParticleData(ParticleID::t); tcPDPtr tb = tp->CC(); // light particles typedef std::vector > Pairvector; Pairvector lightPair; switch(maxflavour_) { case 5: lightPair.push_back(make_pair(getParticleData(ParticleID::b), getParticleData(ParticleID::cbar))); lightPair.push_back(make_pair(getParticleData(ParticleID::b), getParticleData(ParticleID::ubar))); + [[fallthrough]]; case 4: lightPair.push_back(make_pair(getParticleData(ParticleID::s), getParticleData(ParticleID::cbar))); lightPair.push_back(make_pair(getParticleData(ParticleID::d), getParticleData(ParticleID::cbar))); + [[fallthrough]]; case 3: lightPair.push_back(make_pair(getParticleData(ParticleID::s), getParticleData(ParticleID::ubar))); + [[fallthrough]]; case 2: lightPair.push_back(make_pair(getParticleData(ParticleID::d), getParticleData(ParticleID::ubar))); + [[fallthrough]]; default: ; } // top partner vector topPartner; for(long ix=1;ix<=maxflavour_;ix+=2) topPartner.push_back(getParticleData(ix)); // t-channel if(process_==1) { for (Pairvector::const_iterator light = lightPair.begin(); light != lightPair.end(); ++light) { // lights tcPDPtr qNeg1 = light->first; tcPDPtr qNeg2 = light->second->CC(); tcPDPtr qPos1 = light->first ->CC(); tcPDPtr qPos2 = light->second; if(SM().CKM(*qNeg2,*qNeg1)<1e-30) continue; for(unsigned int ix=0;ixCC(), Wm, qNeg1, 1, tb, 2, qNeg2, -3))); add(new_ptr((Tree2toNDiagram(3), topPartner[ix]->CC(), Wm, qPos2, 1, tb, 2, qPos1, -4))); } } } else if(process_==2) { Pairvector::const_iterator light = lightPair.begin(); for (; light != lightPair.end(); ++light) { // lights tcPDPtr qNeg1 = light->first ; tcPDPtr qNeg2 = light->second; tcPDPtr qPos1 = qNeg2->CC(); tcPDPtr qPos2 = qNeg1->CC(); if(SM().CKM(*qPos1,*qNeg1)<1e-30) continue; for(unsigned int ix=0;ixCC(), -12))); } } } else if(process_==3) { for(unsigned int ix=0;ixCC(), g, 1, topPartner[ix]->CC(), 3, tb, 3, Wp, -23))); add(new_ptr((Tree2toNDiagram(3), topPartner[ix]->CC(), tb, g, 3, tb, 1, Wp, -24))); } } else assert(false); } Selector MEPP2SingleTop::diagrams(const DiagramVector & diags) const { Selector sel; for ( DiagramIndex i = 0; i < diags.size(); ++i ) { // only one diagram for t- and s-channel processes if ( abs(diags[i]->id()) <20 ) sel.insert(1.0, i); else if ( abs(diags[i]->id()) <23 ) sel.insert(meInfo()[abs(diags[i]->id())-21],i); else sel.insert(meInfo()[abs(diags[i]->id())-23],i); } return sel; } Selector MEPP2SingleTop::colourGeometries(tcDiagPtr diag) const { // t-channel static ColourLines ct[4]={ColourLines(" 1 4, 3 5"), ColourLines(" 1 4, -3 -5"), ColourLines("-1 -4, 3 5"), ColourLines("-1 -4, -3 -5")}; // s-channel static ColourLines cs[2]={ColourLines("1 -2, -4 5"), ColourLines("1 -2, 4 -5")}; // tW static ColourLines ctw[4]={ColourLines(" 1 -2, 2 3 4"), ColourLines(" 1 2 -3, 3 4"), ColourLines("-1 2, -2 -3 -4"), ColourLines("-1 -2 3, -3 -4")}; // select the right one Selector sel; int id = abs(diag->id()); switch (id) { case 1: case 2: case 3: case 4: sel.insert(1.0, &ct[id-1]); break; case 11: case 12: sel.insert(1.0, &cs[id-11]); break; case 21: case 22: case 23: case 24: sel.insert(1.0, &ctw[id-21]); break; default: assert(false); }; return sel; } double MEPP2SingleTop::me2() const { if(process_==1) { vector f1,f2; vector a1,a2; SpinorWaveFunction sf1,sf2; SpinorBarWaveFunction sa1,sa2; if(mePartonData()[0]->id()>0) { sf1 = SpinorWaveFunction (meMomenta()[0],mePartonData()[0],incoming); sa1 = SpinorBarWaveFunction(meMomenta()[2],mePartonData()[2],outgoing); } else { sa1 = SpinorBarWaveFunction(meMomenta()[0],mePartonData()[0],incoming); sf1 = SpinorWaveFunction (meMomenta()[2],mePartonData()[2],outgoing); } if(mePartonData()[1]->id()>0) { sf2 = SpinorWaveFunction (meMomenta()[1],mePartonData()[1],incoming); sa2 = SpinorBarWaveFunction(meMomenta()[3],mePartonData()[3],outgoing); } else { sa2 = SpinorBarWaveFunction(meMomenta()[1],mePartonData()[1],incoming); sf2 = SpinorWaveFunction (meMomenta()[3],mePartonData()[3],outgoing); } for(unsigned int ix=0;ix<2;++ix) { sf1.reset(ix); f1.push_back(sf1); sf2.reset(ix); f2.push_back(sf2); sa1.reset(ix); a1.push_back(sa1); sa2.reset(ix); a2.push_back(sa2); } return tChannelME(f1,a1,f2,a2,false); } else if(process_==2) { vector fin,aout; vector ain,fout; SpinorWaveFunction q (meMomenta()[0],mePartonData()[0],incoming); SpinorBarWaveFunction qbar(meMomenta()[1],mePartonData()[1],incoming); SpinorBarWaveFunction f; SpinorWaveFunction fbar; if(mePartonData()[2]->id()==ParticleID::t) { f = SpinorBarWaveFunction(meMomenta()[2],mePartonData()[2],outgoing); fbar = SpinorWaveFunction (meMomenta()[3],mePartonData()[3],outgoing); } else { f = SpinorBarWaveFunction(meMomenta()[3],mePartonData()[3],outgoing); fbar = SpinorWaveFunction (meMomenta()[2],mePartonData()[2],outgoing); } for(unsigned int ix=0;ix<2;++ix) { q.reset(ix) ; fin.push_back(q); qbar.reset(ix); ain.push_back(qbar); f.reset(ix) ;fout.push_back(f); fbar.reset(ix);aout.push_back(fbar); } return sChannelME(fin,ain,fout,aout,false); } else { SpinorWaveFunction sf; SpinorBarWaveFunction sa; vector f1; vector a1; vector gl,vec; if(mePartonData()[0]->id()>0) { sf = SpinorWaveFunction (meMomenta()[0],mePartonData()[0],incoming); sa = SpinorBarWaveFunction(meMomenta()[2],mePartonData()[2],outgoing); } else { sa = SpinorBarWaveFunction(meMomenta()[0],mePartonData()[0],incoming); sf = SpinorWaveFunction (meMomenta()[2],mePartonData()[2],outgoing); } VectorWaveFunction gluon(meMomenta()[1],mePartonData()[1],incoming); VectorWaveFunction wbos (meMomenta()[3],mePartonData()[3],outgoing); for(unsigned int ix=0;ix<2;++ix) { sf.reset(ix); f1.push_back(sf); sa.reset(ix); a1.push_back(sa); gluon.reset(2*ix); gl.push_back(gluon); wbos.reset(ix); vec.push_back(wbos); } wbos.reset(2); vec.push_back(wbos); return tWME(f1,gl,a1,vec,false); } } double MEPP2SingleTop::sChannelME(vector & fin , vector & ain , vector & fout, vector & aout, bool calc) const { // matrix element to be stored ProductionMatrixElement newme(PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1Half,PDT::Spin1Half); // positive or negative W boson bool positive = mePartonData()[0]->iCharge() + mePartonData()[1]->iCharge() > 0; tcPDPtr wBoson = positive ? getParticleData(ParticleID::Wplus) : getParticleData(ParticleID::Wminus); // sum over helicities to get the matrix element double me = 0.; for(unsigned int ihel1=0;ihel1<2;++ihel1) { for(unsigned int ihel2=0;ihel2<2;++ihel2) { VectorWaveFunction inter = FFWvertex_->evaluate(scale(),1,wBoson,fin[ihel1],ain[ihel2]); for(unsigned int ohel1=0;ohel1<2;++ohel1) { for(unsigned int ohel2=0;ohel2<2;++ohel2) { Complex diag = FFWvertex_->evaluate(scale(),aout[ohel2],fout[ohel1],inter); // sum over helicities me += norm(diag); if(calc) { if(fout[ohel1].id()==ParticleID::t) newme(ihel1,ihel2,ohel1,ohel2) = diag; else newme(ihel1,ihel2,ohel2,ohel1) = diag; } } } } } // results // spin and colour factor double colspin=1./12.; if(abs(fout[0].id())<=6) colspin*=3.; if(calc) me_.reset(newme); return me*colspin; } double MEPP2SingleTop::tChannelME(vector & f1, vector & a1, vector & f2, vector & a2, bool calc) const { // matrix element to be stored ProductionMatrixElement newme(PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1Half,PDT::Spin1Half); tcPDPtr wBoson = getParticleData(ParticleID::Wplus); // sum over helicities to get the matrix element double me = 0.; unsigned int ihel[4]; for(unsigned int ihel1=0;ihel1<2;++ihel1) { for(unsigned int ohel1=0;ohel1<2;++ohel1) { VectorWaveFunction inter = FFWvertex_->evaluate(scale(),3,wBoson, f1[ihel1],a1[ohel1]); ihel[0] = ihel1; ihel[2] = ohel1; if(f1[ihel1].direction()==outgoing) swap(ihel[0],ihel[2]); for(unsigned int ihel2=0;ihel2<2;++ihel2) { for(unsigned int ohel2=0;ohel2<2;++ohel2) { Complex diag = FFWvertex_->evaluate(scale(),f2[ihel2],a2[ohel2],inter); // sum over helicities me += norm(diag); ihel[1] = ihel2; ihel[3] = ohel2; if(f2[ihel2].direction()==outgoing) swap(ihel[1],ihel[3]); if(calc) newme(ihel[0],ihel[1],ihel[2],ihel[3]) = diag; } } } } // results // spin and colour factor double colspin = 1./4.; if(calc) me_.reset(newme); // Energy mt = getParticleData(ParticleID::t)->mass(); // Energy mw = getParticleData(ParticleID::Wplus)->mass(); // double test1 // = 0.25*sqr(4.*Constants::pi*SM().alphaEM(scale())/SM().sin2ThetaW())* // sHat()*(sHat()-sqr(mt))/sqr(tHat()-sqr(mw)); // double test2 // = 0.25*sqr(4.*Constants::pi*SM().alphaEM(scale())/SM().sin2ThetaW())* // uHat()*(uHat()-sqr(mt))/sqr(tHat()-sqr(mw)); return me*colspin; } double MEPP2SingleTop::tWME(vector & fin, vector & gin, vector & fout, vector & Wout, bool calc) const { if(calc) me_.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1, PDT::Spin1Half,PDT::Spin1)); double me[3]={0.,0.,0.}; Complex diag[2]; Energy2 mt=scale(); for(unsigned int ihel=0;ihel<2;++ihel) { for(unsigned int ghel=0;ghel<2;++ghel) { for(unsigned int ohel=0;ohel<2;++ohel) { for(unsigned int whel=0;whel<3;++whel) { if(fin[ihel].direction()==incoming) { // 1st diagram SpinorWaveFunction inters = FFGvertex_->evaluate(mt,5,mePartonData()[0], fin[ihel],gin[ghel]); diag[0]= FFWvertex_->evaluate(mt,inters,fout[ohel],Wout[whel]); // 2nd diagram SpinorBarWaveFunction interb = FFGvertex_->evaluate(mt,3,mePartonData()[2], fout[ohel],gin[ghel]); diag[1]= FFWvertex_->evaluate(mt,fin[ihel],interb,Wout[whel]); } else { // 1st diagram SpinorBarWaveFunction interb = FFGvertex_->evaluate(mt,5,mePartonData()[0], fout[ihel],gin[ghel]); diag[0]= FFWvertex_->evaluate(mt,fin[ohel],interb,Wout[whel]); // 2nd diagram SpinorWaveFunction inters = FFGvertex_->evaluate(mt,3,mePartonData()[2], fin[ohel],gin[ghel]); diag[1]= FFWvertex_->evaluate(mt,inters,fout[ihel],Wout[whel]); } // diagram contributions me[1] += norm(diag[0]); me[2] += norm(diag[1]); // total diag[0] += diag[1]; me[0] += norm(diag[0]); if(calc) me_(ihel,ghel,ohel,whel) = diag[0]; } } } } // results // initial state spin and colour average double colspin=1./24./4.; // and C_F N_c from matrix element colspin *=4.; DVector save; for(unsigned int ix=0;ix<3;++ix) { me[ix] *= colspin; if(ix>0) save.push_back(me[ix]); } meInfo(save); return me[0]; } void MEPP2SingleTop::constructVertex(tSubProPtr sub) { // extract the particles in the hard process ParticleVector hard; hard.push_back(sub->incoming().first); hard.push_back(sub->incoming().second); hard.push_back(sub->outgoing()[0]); hard.push_back(sub->outgoing()[1]); if(mePartonData()[0]->id()!=hard[0]->id()) { swap(hard[0],hard[1]); } if(mePartonData()[2]->id()!=hard[2]->id()) { swap(hard[2],hard[3]); } // on-shell for matrix element vector momenta; cPDVector data; for(unsigned int ix=0;ix<4;++ix) { momenta.push_back(hard[ix]->momentum()); data .push_back(hard[ix]->dataPtr()); } rescaleMomenta(momenta,data); if(process_==1) { vector f1,f2; vector a1,a2; // off-shell wavefunctions for the spin correlations (and on shell for matrix elements) SpinorWaveFunction sf1,sf2; SpinorBarWaveFunction sa1,sa2; if(hard[0]->id()>0) { SpinorWaveFunction (f1,hard[0],incoming,false,true); SpinorBarWaveFunction(a1,hard[2],outgoing,true,true); sf1 = SpinorWaveFunction (rescaledMomenta()[0],data[0],incoming); sa1 = SpinorBarWaveFunction(rescaledMomenta()[2],data[2],outgoing); } else { SpinorBarWaveFunction(a1,hard[0],incoming,false,true); SpinorWaveFunction (f1,hard[2],outgoing,true,true); sa1 = SpinorBarWaveFunction(rescaledMomenta()[0],data[0],incoming); sf1 = SpinorWaveFunction (rescaledMomenta()[2],data[2],outgoing); } if(hard[1]->id()>0) { SpinorWaveFunction (f2,hard[1],incoming,false,true); SpinorBarWaveFunction(a2,hard[3],outgoing,true,true); sf2 = SpinorWaveFunction (rescaledMomenta()[1],data[1],incoming); sa2 = SpinorBarWaveFunction(rescaledMomenta()[3],data[3],outgoing); } else { SpinorBarWaveFunction(a2,hard[1],incoming,false,true); SpinorWaveFunction (f2,hard[3],outgoing,true,true); sa2 = SpinorBarWaveFunction(rescaledMomenta()[1],data[1],incoming); sf2 = SpinorWaveFunction (rescaledMomenta()[3],data[3],outgoing); } for(unsigned int ix=0;ix<2;++ix) { sf1.reset(ix); f1[ix] = sf1; sf2.reset(ix); f2[ix] = sf2; sa1.reset(ix); a1[ix] = sa1; sa2.reset(ix); a2[ix] = sa2; } tChannelME(f1,a1,f2,a2,true); } else if(process_==2) { vector fin,aout; vector ain,fout; SpinorWaveFunction (fin,hard[0],incoming,false,true); SpinorBarWaveFunction(ain,hard[1],incoming,false,true); SpinorWaveFunction q (rescaledMomenta()[0],data[0],incoming); SpinorBarWaveFunction qbar(rescaledMomenta()[1],data[1],incoming); SpinorBarWaveFunction f; SpinorWaveFunction fbar; if(hard[2]->id()==ParticleID::t) { SpinorBarWaveFunction(fout,hard[2],outgoing,true,true); SpinorWaveFunction (aout,hard[3],outgoing,true,true); f = SpinorBarWaveFunction(rescaledMomenta()[2],data[2],outgoing); fbar = SpinorWaveFunction (rescaledMomenta()[3],data[3],outgoing); } else { SpinorBarWaveFunction(fout,hard[3],outgoing,true,true); SpinorWaveFunction (aout,hard[2],outgoing,true,true); f = SpinorBarWaveFunction(rescaledMomenta()[3],data[3],outgoing); fbar = SpinorWaveFunction (rescaledMomenta()[2],data[2],outgoing); } for(unsigned int ix=0;ix<2;++ix) { q.reset(ix) ; fin[ix] = q; qbar.reset(ix); ain[ix] = qbar; f.reset(ix) ;fout[ix] = f; fbar.reset(ix);aout[ix] = fbar; } sChannelME(fin,ain,fout,aout,true); } else { SpinorWaveFunction sf; SpinorBarWaveFunction sa; vector f1; vector a1; vector gl,vec; if(hard[0]->id()>0) { SpinorWaveFunction (f1,hard[0],incoming,false,true); SpinorBarWaveFunction(a1,hard[2],outgoing,true ,true); sf = SpinorWaveFunction (rescaledMomenta()[0],data[0],incoming); sa = SpinorBarWaveFunction(rescaledMomenta()[2],data[2],outgoing); } else { SpinorBarWaveFunction(a1,hard[0],incoming,false,true); SpinorWaveFunction (f1,hard[2],outgoing,true ,true); sa = SpinorBarWaveFunction(rescaledMomenta()[0],data[0],incoming); sf = SpinorWaveFunction (rescaledMomenta()[2],data[2],outgoing); } VectorWaveFunction(gl,hard[1],incoming,false,true ,true); VectorWaveFunction(vec,hard[3],outgoing,true,false,true); VectorWaveFunction gluon(rescaledMomenta()[1],data[1],incoming); VectorWaveFunction wbos (rescaledMomenta()[3],data[3],outgoing); gl[1]=gl[2]; for(unsigned int ix=0;ix<2;++ix) { sf.reset(ix); f1[ix] = sf; sa.reset(ix); a1[ix] = sa; gluon.reset(2*ix); gl[ix] = gluon; wbos.reset(ix); vec[ix] = wbos; } wbos.reset(2); vec[2] = wbos; tWME(f1,gl,a1,vec,true); } // construct the vertex HardVertexPtr hardvertex=new_ptr(HardVertex()); // set the matrix element for the vertex hardvertex->ME(me_); // set the pointers and to and from the vertex for(unsigned int ix=0;ix<4;++ix) hard[ix]->spinInfo()->productionVertex(hardvertex); } diff --git a/MatrixElement/Hadron/MEPP2VGamma.cc b/MatrixElement/Hadron/MEPP2VGamma.cc --- a/MatrixElement/Hadron/MEPP2VGamma.cc +++ b/MatrixElement/Hadron/MEPP2VGamma.cc @@ -1,382 +1,386 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the MEPP2VGamma class. // #include "MEPP2VGamma.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/Handlers/StandardXComb.h" #include "Herwig/Models/StandardModel/StandardModel.h" #include "Herwig/MatrixElement/HardVertex.h" using namespace Herwig; MEPP2VGamma::MEPP2VGamma() : process_(0), maxflavour_(5), massOption_(2) {} unsigned int MEPP2VGamma::orderInAlphaS() const { return 0; } unsigned int MEPP2VGamma::orderInAlphaEW() const { return 2; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigMEPP2VGamma("Herwig::MEPP2VGamma", "HwMEHadron.so"); void MEPP2VGamma::Init() { static ClassDocumentation documentation ("The MEPP2VGamma class simulates the production of" " W+/-gamma and Z0gamma in hadron-hadron collisions" " using the 2->2 matrix elements"); static Switch interfaceProcess ("Process", "Which processes to include", &MEPP2VGamma::process_, 0, false, false); static SwitchOption interfaceProcessAll (interfaceProcess, "All", "Include all the processes", 0); static SwitchOption interfaceProcessWGamma (interfaceProcess, "WGamma", "Only include W+/-gamma", 1); static SwitchOption interfaceProcessZGamma (interfaceProcess, "ZGamma", "Only include ZGamma", 2); static Parameter interfaceMaximumFlavour ("MaximumFlavour", "The maximum flavour allowed for the incoming quarks", &MEPP2VGamma::maxflavour_, 5, 2, 5, false, false, Interface::limited); static Switch interfaceMassOption ("MassOption", "Option for the treatment of the boson masses", &MEPP2VGamma::massOption_, 1, false, false); static SwitchOption interfaceMassOptionOnMassShell (interfaceMassOption, "OnMassShell", "The boson is produced on its mass shell", 1); static SwitchOption interfaceMassOption2 (interfaceMassOption, "OffShell", "The bosons are generated off-shell using the mass and width generator.", 2); } void MEPP2VGamma::persistentOutput(PersistentOStream & os) const { os << FFPvertex_ << FFWvertex_ << FFZvertex_ << WWWvertex_ << process_ << massOption_; } void MEPP2VGamma::persistentInput(PersistentIStream & is, int) { is >> FFPvertex_ >> FFWvertex_ >> FFZvertex_ >> WWWvertex_ >> process_ >> massOption_; } Energy2 MEPP2VGamma::scale() const { return sHat(); } IBPtr MEPP2VGamma::clone() const { return new_ptr(*this); } IBPtr MEPP2VGamma::fullclone() const { return new_ptr(*this); } void MEPP2VGamma::doinit() { HwMEBase::doinit(); // mass option vector mopt(2,1); mopt[0]=massOption_; massOption(mopt); rescalingOption(2); // get the vertices we need // get a pointer to the standard model object in the run static const tcHwSMPtr hwsm = dynamic_ptr_cast(standardModel()); if (!hwsm) throw InitException() << "hwsm pointer is null in" << " MEPP2VGamma::doinit()" << Exception::abortnow; // get pointers to all required Vertex objects FFZvertex_ = hwsm->vertexFFZ(); FFPvertex_ = hwsm->vertexFFP(); WWWvertex_ = hwsm->vertexWWW(); FFWvertex_ = hwsm->vertexFFW(); } Selector MEPP2VGamma::colourGeometries(tcDiagPtr diag) const { static ColourLines cs("1 -2"); static ColourLines ct("1 2 -3"); Selector sel; if(diag->id()<-2) sel.insert(1.0, &cs); else sel.insert(1.0, &ct); return sel; } void MEPP2VGamma::getDiagrams() const { typedef std::vector > Pairvector; tcPDPtr wPlus = getParticleData(ParticleID::Wplus ); tcPDPtr wMinus = getParticleData(ParticleID::Wminus); tcPDPtr z0 = getParticleData(ParticleID::Z0 ); tcPDPtr gamma = getParticleData(ParticleID::gamma); // W+/- gamma if(process_==0||process_==1) { // possible parents Pairvector parentpair; parentpair.reserve(6); // don't even think of putting 'break' in here! switch(maxflavour_) { case 5: parentpair.push_back(make_pair(getParticleData(ParticleID::b), getParticleData(ParticleID::cbar))); parentpair.push_back(make_pair(getParticleData(ParticleID::b), getParticleData(ParticleID::ubar))); + [[fallthrough]]; case 4: parentpair.push_back(make_pair(getParticleData(ParticleID::s), getParticleData(ParticleID::cbar))); parentpair.push_back(make_pair(getParticleData(ParticleID::d), getParticleData(ParticleID::cbar))); + [[fallthrough]]; case 3: parentpair.push_back(make_pair(getParticleData(ParticleID::s), getParticleData(ParticleID::ubar))); + [[fallthrough]]; case 2: parentpair.push_back(make_pair(getParticleData(ParticleID::d), getParticleData(ParticleID::ubar))); + [[fallthrough]]; default: ; } // W+ gamma for(unsigned int ix=0;ixCC(), parentpair[ix].first, parentpair[ix].first->CC(), 1, wPlus, 2, gamma, -1))); add(new_ptr((Tree2toNDiagram(3), parentpair[ix].second->CC(), parentpair[ix].second->CC() , parentpair[ix].first->CC(), 2, wPlus, 1, gamma, -2))); add(new_ptr((Tree2toNDiagram(2), parentpair[ix].second->CC(), parentpair[ix].first->CC(), 1, wPlus, 3, wPlus, 3, gamma, -3))); } // W- gamma for(unsigned int ix=0;ixCC(), parentpair[ix].second, 1, wMinus, 2, gamma, -1))); add(new_ptr((Tree2toNDiagram(3), parentpair[ix].first, parentpair[ix].first , parentpair[ix].second, 2, wMinus, 1, gamma, -2))); add(new_ptr((Tree2toNDiagram(2), parentpair[ix].first, parentpair[ix].second, 1, wMinus, 3, wMinus, 3, gamma, -3))); } } if(process_==0||process_==2) { for(int ix=1;ix<=maxflavour_;++ix) { tcPDPtr qk = getParticleData(ix); tcPDPtr qb = qk->CC(); add(new_ptr((Tree2toNDiagram(3), qk, qk, qb, 1, z0, 2, gamma, -1))); add(new_ptr((Tree2toNDiagram(3), qk, qk, qb, 2, z0, 1, gamma, -2))); } } } Selector MEPP2VGamma::diagrams(const DiagramVector & diags) const { Selector sel; for ( DiagramIndex i = 0; i < diags.size(); ++i ) sel.insert(meInfo()[abs(diags[i]->id()) - 1], i); return sel; } double MEPP2VGamma::me2() const { // setup momenta and particle data for the external wavefunctions // incoming SpinorWaveFunction em_in( meMomenta()[0],mePartonData()[0],incoming); SpinorBarWaveFunction ep_in( meMomenta()[1],mePartonData()[1],incoming); // outgoing VectorWaveFunction v1_out(meMomenta()[2],mePartonData()[2],outgoing); VectorWaveFunction v2_out(meMomenta()[3],mePartonData()[3],outgoing); vector f1; vector a1; vector v1,v2; // calculate the wavefunctions for(unsigned int ix=0;ix<3;++ix) { if(ix<2) { em_in.reset(ix); f1.push_back(em_in); ep_in.reset(ix); a1.push_back(ep_in); } v1_out.reset(ix); v1.push_back(v1_out); if(ix!=1) { v2_out.reset(ix); v2.push_back(v2_out); } } if(mePartonData()[2]->id()==ParticleID::Z0) { return ZGammaME(f1,a1,v1,v2,false); } else { return WGammaME(f1,a1,v1,v2,false); } } double MEPP2VGamma::ZGammaME(vector & f1, vector & a1, vector & v1, vector & v2, bool calc) const { double output(0.); vector me(3,0.0); if(calc) me_.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1,PDT::Spin1)); vector diag(2,0.0); SpinorWaveFunction inter; for(unsigned int ihel1=0;ihel1<2;++ihel1) { for(unsigned int ihel2=0;ihel2<2;++ihel2) { for(unsigned int ohel1=0;ohel1<3;++ohel1) { for(unsigned int ohel2=0;ohel2<2;++ohel2) { inter = FFZvertex_->evaluate(scale(),5,f1[ihel1].particle()->CC(), f1[ihel1],v1[ohel1]); diag[0] = FFPvertex_->evaluate(scale(),inter,a1[ihel2],v2[ohel2]); inter = FFPvertex_->evaluate(scale(),5,f1[ihel1].particle()->CC(), f1[ihel1] ,v2[ohel2]); diag[1] = FFZvertex_->evaluate(scale(),inter,a1[ihel2],v1[ohel1]); // individual diagrams for (size_t ii=0; ii<2; ++ii) me[ii] += std::norm(diag[ii]); // full matrix element diag[0] += diag[1]; output += std::norm(diag[0]); // storage of the matrix element for spin correlations if(calc) me_(ihel1,ihel2,ohel1,ohel2) = diag[0]; } } } } DVector save(3); for (size_t i = 0; i < 3; ++i) { save[i] = 0.25 * me[i]; } meInfo(save); return 0.25*output/3.; } double MEPP2VGamma::WGammaME(vector & f1, vector & a1, vector & v1, vector & v2, bool calc) const { double output(0.); vector me(3,0.0); if(calc) me_.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1,PDT::Spin1)); vector diag(3,0.0); SpinorWaveFunction inter; for(unsigned int ihel1=0;ihel1<2;++ihel1) { for(unsigned int ihel2=0;ihel2<2;++ihel2) { VectorWaveFunction interW = FFWvertex_->evaluate(scale(),3,v1[0].particle(), f1[ihel1],a1[ihel2]); for(unsigned int ohel1=0;ohel1<3;++ohel1) { for(unsigned int ohel2=0;ohel2<2;++ohel2) { // t-channel diagrams inter = FFWvertex_->evaluate(scale(),5,a1[ihel1].particle(), f1[ihel1],v1[ohel1]); diag[0] = FFPvertex_->evaluate(scale(),inter,a1[ihel2],v2[ohel2]); inter = FFPvertex_->evaluate(scale(),5,f1[ihel1].particle()->CC(), f1[ihel1] ,v2[ohel2]); diag[1] = FFWvertex_->evaluate(scale(),inter,a1[ihel2],v1[ohel1]); // s-channel diagram diag[2] = WWWvertex_->evaluate(scale(),interW,v1[ohel1],v2[ohel2]); // individual diagrams for (size_t ii=0; ii<3; ++ii) me[ii] += std::norm(diag[ii]); // full matrix element diag[0] += diag[1]+diag[2]; output += std::norm(diag[0]); // storage of the matrix element for spin correlations if(calc) me_(ihel1,ihel2,ohel1,ohel2) = diag[0]; } } } } DVector save(3); for (size_t i = 0; i < 3; ++i) save[i] = 0.25 * me[i]; meInfo(save); // spin and colour factors output *= 0.25/3.; // testing code // int iu = abs(mePartonData()[0]->id()); // int id = abs(mePartonData()[1]->id()); // if(iu%2!=0) swap(iu,id); // iu = (iu-2)/2; // id = (id-1)/2; // double ckm = SM().CKM(iu,id); // InvEnergy4 dsigdt = Constants::pi*sqr(SM().alphaEM(scale())) // /6./sqr(sHat())/SM().sin2ThetaW()*sqr(1./(1.+tHat()/uHat())-1./3.)* // (sqr(tHat())+sqr(uHat())+2.*sqr(getParticleData(ParticleID::Wplus)->mass())*sHat())/ // tHat()/uHat(); // double test = 16.*ckm*Constants::pi*sqr(sHat())*dsigdt; // cerr << "testing W gamma " << test << " " << output << " " // << (test-output)/(test+output) << "\n"; return output; } void MEPP2VGamma::constructVertex(tSubProPtr sub) { // extract the particles in the hard process ParticleVector hard; hard.push_back(sub->incoming().first); hard.push_back(sub->incoming().second); hard.push_back(sub->outgoing()[0]); hard.push_back(sub->outgoing()[1]); // order of particles unsigned int order[4]={0,1,2,3}; if(hard[order[0]]->id()<0) swap(order[0],order[1]); vector q; vector qb; SpinorWaveFunction (q ,hard[order[0]],incoming,false); SpinorBarWaveFunction(qb,hard[order[1]],incoming,false); vector w1,w2; if(hard[order[2]]->id()==ParticleID::gamma) swap(order[2],order[3]); VectorWaveFunction (w1,hard[order[2]],outgoing,true ,false); VectorWaveFunction (w2,hard[order[3]],outgoing,true ,true ); w2[1]=w2[2]; // q qbar -> Z gamma if(hard[order[2]]->id()==ParticleID::Z0) { ZGammaME(q,qb,w1,w2,true); } // q qbar -> W gamma else { WGammaME(q,qb,w1,w2,true); } // construct the vertex HardVertexPtr hardvertex=new_ptr(HardVertex()); // set the matrix element for the vertex hardvertex->ME(me_); // set the pointers and to and from the vertex for(unsigned int ix=0;ix<4;++ix) hard[order[ix]]->spinInfo()->productionVertex(hardvertex); } diff --git a/MatrixElement/Hadron/MEPP2VV.cc b/MatrixElement/Hadron/MEPP2VV.cc --- a/MatrixElement/Hadron/MEPP2VV.cc +++ b/MatrixElement/Hadron/MEPP2VV.cc @@ -1,543 +1,547 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the MEPP2VV class. // #include "MEPP2VV.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/Handlers/StandardXComb.h" #include "Herwig/Models/StandardModel/StandardModel.h" #include "Herwig/MatrixElement/HardVertex.h" using namespace Herwig; MEPP2VV::MEPP2VV() : process_(0), maxflavour_(5), massOption_(2) {} unsigned int MEPP2VV::orderInAlphaS() const { return 0; } unsigned int MEPP2VV::orderInAlphaEW() const { return 2; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigMEPP2VV("Herwig::MEPP2VV", "HwMEHadron.so"); void MEPP2VV::Init() { static ClassDocumentation documentation ("The MEPP2VV class simulates the production of W+W-, " "W+/-Z0 and Z0Z0 in hadron-hadron collisions using the 2->2" " matrix elements"); static Switch interfaceProcess ("Process", "Which processes to include", &MEPP2VV::process_, 0, false, false); static SwitchOption interfaceProcessAll (interfaceProcess, "All", "Include all the processes", 0); static SwitchOption interfaceProcessWW (interfaceProcess, "WW", "Only include W+W-", 1); static SwitchOption interfaceProcessWZ (interfaceProcess, "WZ", "Only include W+/-Z", 2); static SwitchOption interfaceProcessZZ (interfaceProcess, "ZZ", "Only include ZZ", 3); static SwitchOption interfaceProcessWpZ (interfaceProcess, "WpZ", "Only include W+ Z", 4); static SwitchOption interfaceProcessWmZ (interfaceProcess, "WmZ", "Only include W- Z", 5); static Parameter interfaceMaximumFlavour ("MaximumFlavour", "The maximum flavour allowed for the incoming quarks", &MEPP2VV::maxflavour_, 5, 2, 5, false, false, Interface::limited); static Switch interfaceMassOption ("MassOption", "Option for the treatment of the boson masses", &MEPP2VV::massOption_, 1, false, false); static SwitchOption interfaceMassOptionOnMassShell (interfaceMassOption, "OnMassShell", "The boson is produced on its mass shell", 1); static SwitchOption interfaceMassOption2 (interfaceMassOption, "OffShell", "The bosons are generated off-shell using the mass and width generator.", 2); } void MEPP2VV::persistentOutput(PersistentOStream & os) const { os << FFPvertex_ << FFWvertex_ << FFZvertex_ << WWWvertex_ << process_ << massOption_ << maxflavour_; } void MEPP2VV::persistentInput(PersistentIStream & is, int) { is >> FFPvertex_ >> FFWvertex_ >> FFZvertex_ >> WWWvertex_ >> process_ >> massOption_ >> maxflavour_; } Energy2 MEPP2VV::scale() const { return sHat(); } IBPtr MEPP2VV::clone() const { return new_ptr(*this); } IBPtr MEPP2VV::fullclone() const { return new_ptr(*this); } void MEPP2VV::doinit() { HwMEBase::doinit(); // mass option massOption(vector(2,massOption_)); rescalingOption(2); // get the vertices we need // get a pointer to the standard model object in the run static const tcHwSMPtr hwsm = dynamic_ptr_cast(standardModel()); if (!hwsm) throw InitException() << "hwsm pointer is null in" << " MEPP2VV::doinit()" << Exception::abortnow; // get pointers to all required Vertex objects FFZvertex_ = hwsm->vertexFFZ(); FFPvertex_ = hwsm->vertexFFP(); WWWvertex_ = hwsm->vertexWWW(); FFWvertex_ = hwsm->vertexFFW(); } double MEPP2VV::getCosTheta(double ctmin, double ctmax, const double r) { double rand = r; Energy2 m12 = sqr(meMomenta()[2].mass()); Energy2 m22 = sqr(meMomenta()[3].mass()); Energy2 D1 = sHat()-m12-m22; Energy4 lambda = sqr(D1) - 4*m12*m22; double D = D1 / sqrt(lambda); if(mePartonData()[2]->id()==ParticleID::Z0&& mePartonData()[3]->id()==ParticleID::Z0) { double prob = 0.5; double costh; double fraction1 = (D-ctmax)/(D-ctmin); double fraction2 = (D+ctmin)/(D+ctmax); if(rand<=prob) { rand /=prob; costh = D - (D - ctmin) * pow(fraction1, rand); } else { rand = (rand-prob)/(1.-prob); costh =-D + (D + ctmax) * pow(fraction2, rand); } jacobian(1./(prob /((costh - D) * log(fraction1))- (1.-prob)/((costh + D) * log(fraction2)))); return costh; } else { double fraction = (D-ctmax)/(D-ctmin); double costh = D - (D - ctmin) * pow(fraction, rand); jacobian((costh - D) * log(fraction)); return costh; } } Selector MEPP2VV::colourGeometries(tcDiagPtr diag) const { static ColourLines cs("1 -2"); static ColourLines ct("1 2 -3"); Selector sel; if(abs(diag->partons()[2]->id())==24&&abs(diag->partons()[3]->id())==24) { if(diag->id()<=-4) sel.insert(1.0, &cs); else sel.insert(1.0, &ct); } else if(abs(diag->partons()[2]->id())==24&&diag->partons()[3]->id()==23) { if(diag->id()==-3) sel.insert(1.0, &cs); else sel.insert(1.0, &ct); } else { sel.insert(1.0, &ct); } return sel; } void MEPP2VV::getDiagrams() const { typedef std::vector > Pairvector; tcPDPtr wPlus = getParticleData(ParticleID::Wplus ); tcPDPtr wMinus = getParticleData(ParticleID::Wminus); tcPDPtr z0 = getParticleData(ParticleID::Z0 ); tcPDPtr gamma = getParticleData(ParticleID::gamma); // W+ W- if(process_==0||process_==1) { for(int ix=1;ix<=maxflavour_;++ix) { tcPDPtr qk = getParticleData(ix); tcPDPtr w1 = ix%2==0 ? wPlus : wMinus; tcPDPtr w2 = ix%2!=0 ? wPlus : wMinus; for(int iy=1;iy<=maxflavour_;++iy) { if(abs(ix-iy)%2!=0) continue; tcPDPtr qb = getParticleData(-iy); // s channel photon add(new_ptr((Tree2toNDiagram(2), qk, qb, 1, gamma, 3, w1, 3, w2, -4))); // s-channel Z add(new_ptr((Tree2toNDiagram(2), qk, qb, 1, z0, 3, w1, 3, w2, -5))); // t-channel if(ix%2==0) { int idiag=0; for(int iz=1;iz<=5;iz+=2) { --idiag; tcPDPtr tc = getParticleData(iz); add(new_ptr((Tree2toNDiagram(3), qk, tc, qb, 1, w1, 2, w2, idiag))); } } else { int idiag=0; for(int iz=2;iz<=6;iz+=2) { --idiag; tcPDPtr tc = getParticleData(iz); add(new_ptr((Tree2toNDiagram(3), qk, tc, qb, 1, w1, 2, w2, idiag))); } } } } } // W+/- Z if(process_==0||process_==2||process_==4||process_==5) { // possible parents Pairvector parentpair; parentpair.reserve(6); // don't even think of putting 'break' in here! switch(maxflavour_) { case 5: parentpair.push_back(make_pair(getParticleData(ParticleID::b), getParticleData(ParticleID::cbar))); parentpair.push_back(make_pair(getParticleData(ParticleID::b), getParticleData(ParticleID::ubar))); + [[fallthrough]]; case 4: parentpair.push_back(make_pair(getParticleData(ParticleID::s), getParticleData(ParticleID::cbar))); parentpair.push_back(make_pair(getParticleData(ParticleID::d), getParticleData(ParticleID::cbar))); + [[fallthrough]]; case 3: parentpair.push_back(make_pair(getParticleData(ParticleID::s), getParticleData(ParticleID::ubar))); + [[fallthrough]]; case 2: parentpair.push_back(make_pair(getParticleData(ParticleID::d), getParticleData(ParticleID::ubar))); + [[fallthrough]]; default: ; } // W+ Z if(process_==0||process_==2||process_==4) { for(unsigned int ix=0;ixCC(), parentpair[ix].first, parentpair[ix].first->CC(), 1, wPlus, 2, z0, -1))); add(new_ptr((Tree2toNDiagram(3), parentpair[ix].second->CC(), parentpair[ix].second->CC() , parentpair[ix].first->CC(), 2, wPlus, 1, z0, -2))); add(new_ptr((Tree2toNDiagram(2), parentpair[ix].second->CC(), parentpair[ix].first->CC(), 1, wPlus, 3, wPlus, 3, z0, -3))); } } // W- Z if(process_==0||process_==2||process_==5) { for(unsigned int ix=0;ixCC(), parentpair[ix].second, 1, wMinus, 2, z0, -1))); add(new_ptr((Tree2toNDiagram(3), parentpair[ix].first, parentpair[ix].first , parentpair[ix].second, 2, wMinus, 1, z0, -2))); add(new_ptr((Tree2toNDiagram(2), parentpair[ix].first, parentpair[ix].second, 1, wMinus, 3, wMinus, 3, z0, -3))); } } } // Z Z if(process_==0||process_==3) { for(int ix=1;ix<=maxflavour_;++ix) { tcPDPtr qk = getParticleData(ix); tcPDPtr qb = qk->CC(); add(new_ptr((Tree2toNDiagram(3), qk, qk, qb, 1, z0, 2, z0, -1))); add(new_ptr((Tree2toNDiagram(3), qk, qk, qb, 2, z0, 1, z0, -2))); } } } Selector MEPP2VV::diagrams(const DiagramVector & diags) const { Selector sel; for ( DiagramIndex i = 0; i < diags.size(); ++i ) sel.insert(meInfo()[abs(diags[i]->id())-1], i); return sel; } double MEPP2VV::me2() const { // setup momenta and particle data for the external wavefunctions // incoming SpinorWaveFunction em_in( meMomenta()[0],mePartonData()[0],incoming); SpinorBarWaveFunction ep_in( meMomenta()[1],mePartonData()[1],incoming); // outgoing VectorWaveFunction v1_out(meMomenta()[2],mePartonData()[2],outgoing); VectorWaveFunction v2_out(meMomenta()[3],mePartonData()[3],outgoing); vector f1; vector a1; vector v1,v2; // calculate the wavefunctions for(unsigned int ix=0;ix<3;++ix) { if(ix<2) { em_in.reset(ix); f1.push_back(em_in); ep_in.reset(ix); a1.push_back(ep_in); } v1_out.reset(ix); v1.push_back(v1_out); v2_out.reset(ix); v2.push_back(v2_out); } if(mePartonData()[2]->id()==ParticleID::Z0&& mePartonData()[3]->id()==ParticleID::Z0) { return ZZME(f1,a1,v1,v2,false); } else if(abs(mePartonData()[2]->id())==ParticleID::Wplus&& abs(mePartonData()[3]->id())==ParticleID::Wplus) { return WWME(f1,a1,v1,v2,false); } else { return WZME(f1,a1,v1,v2,false); } } double MEPP2VV::WWME(vector & f1, vector & a1, vector & v1, vector & v2, bool calc) const { double output(0.); vector me(5,0.0); if(calc) me_.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1,PDT::Spin1)); // particle data for the t-channel intermediate tcPDPtr tc[3]; if(f1[0].particle()->id()%2==0) { for (int ix=0;ix<3;++ix) tc[ix] = getParticleData(1+2*ix); } else { for (int ix=0;ix<3;++ix) tc[ix] = getParticleData(2+2*ix); } tcPDPtr gamma = getParticleData(ParticleID::gamma); tcPDPtr z0 = getParticleData(ParticleID::Z0); vector diag(5,0.0); VectorWaveFunction interP,interZ; bool sChannel = f1[0].particle()->id() == -a1[0].particle()->id(); for(unsigned int ihel1=0;ihel1<2;++ihel1) { for(unsigned int ihel2=0;ihel2<2;++ihel2) { if(sChannel) { interP = FFPvertex_->evaluate(scale(),3,gamma,f1[ihel1],a1[ihel2]); interZ = FFZvertex_->evaluate(scale(),3,z0 ,f1[ihel1],a1[ihel2]); } for(unsigned int ohel1=0;ohel1<3;++ohel1) { for(unsigned int ohel2=0;ohel2<3;++ohel2) { // s-channel photon diag[3] = sChannel ? WWWvertex_->evaluate(scale(),interP,v2[ohel2],v1[ohel1]) : 0.; // s-channel Z0 diag[4] = sChannel ? WWWvertex_->evaluate(scale(),interZ,v2[ohel2],v1[ohel1]) : 0.; // t-channel for(unsigned int ix=0;ix<3;++ix) { SpinorWaveFunction inter = FFWvertex_->evaluate(scale(),(abs(tc[ix]->id())!=6 ? 5 : 1), tc[ix],f1[ihel1],v1[ohel1]); diag[ix] = FFWvertex_->evaluate(scale(),inter,a1[ihel2],v2[ohel2]); } // individual diagrams for (size_t ii=0; ii<5; ++ii) me[ii] += std::norm(diag[ii]); // full matrix element diag[0] += diag[1]+diag[2]+diag[3]+diag[4]; output += std::norm(diag[0]); // storage of the matrix element for spin correlations if(calc) me_(ihel1,ihel2,ohel1,ohel2) = diag[0]; } } } } DVector save(5); for (size_t i = 0; i < 5; ++i) { save[i] = 0.25 * me[i]; } meInfo(save); return 0.25*output/3.; } double MEPP2VV::WZME(vector & f1, vector & a1, vector & v1, vector & v2, bool calc) const { double output(0.); vector me(5,0.0); if(calc) me_.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1,PDT::Spin1)); vector diag(3,0.0); SpinorWaveFunction inter; for(unsigned int ihel1=0;ihel1<2;++ihel1) { for(unsigned int ihel2=0;ihel2<2;++ihel2) { VectorWaveFunction interW = FFWvertex_->evaluate(scale(),3,v1[0].particle(), f1[ihel1],a1[ihel2]); for(unsigned int ohel1=0;ohel1<3;++ohel1) { for(unsigned int ohel2=0;ohel2<3;++ohel2) { // t-channel diagrams inter = FFWvertex_->evaluate(scale(),5,a1[ihel1].particle(), f1[ihel1],v1[ohel1]); diag[0] = FFZvertex_->evaluate(scale(),inter,a1[ihel2],v2[ohel2]); inter = FFZvertex_->evaluate(scale(),5,f1[ihel1].particle(), f1[ihel1] ,v2[ohel2]); diag[1] = FFWvertex_->evaluate(scale(),inter,a1[ihel2],v1[ohel1]); // s-channel diagram diag[2] = WWWvertex_->evaluate(scale(),interW,v1[ohel1],v2[ohel2]); // individual diagrams for (size_t ii=0; ii<3; ++ii) me[ii] += std::norm(diag[ii]); // full matrix element diag[0] += diag[1]+diag[2]; output += std::norm(diag[0]); // storage of the matrix element for spin correlations if(calc) me_(ihel1,ihel2,ohel1,ohel2) = diag[0]; } } } } DVector save(5); for (size_t i = 0; i < 5; ++i) { save[i] = 0.25 * me[i]; } meInfo(save); return 0.25*output/3.; } double MEPP2VV::ZZME(vector & f1, vector & a1, vector & v1, vector & v2, bool calc) const { double output(0.); vector me(5,0.0); if(calc) me_.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1,PDT::Spin1)); vector diag(2,0.0); SpinorWaveFunction inter; for(unsigned int ihel1=0;ihel1<2;++ihel1) { for(unsigned int ihel2=0;ihel2<2;++ihel2) { for(unsigned int ohel1=0;ohel1<3;++ohel1) { for(unsigned int ohel2=0;ohel2<3;++ohel2) { inter = FFZvertex_->evaluate(scale(),5,f1[ihel1].particle(), f1[ihel1],v1[ohel1]); diag[0] = FFZvertex_->evaluate(scale(),inter,a1[ihel2],v2[ohel2]); inter = FFZvertex_->evaluate(scale(),5,f1[ihel1].particle(), f1[ihel1] ,v2[ohel2]); diag[1] = FFZvertex_->evaluate(scale(),inter,a1[ihel2],v1[ohel1]); // individual diagrams for (size_t ii=0; ii<2; ++ii) me[ii] += std::norm(diag[ii]); // full matrix element diag[0] += diag[1]; output += std::norm(diag[0]); // storage of the matrix element for spin correlations if(calc) me_(ihel1,ihel2,ohel1,ohel2) = diag[0]; } } } } // identical particle factor output /= 2.; DVector save(5); for (size_t i = 0; i < 5; ++i) { save[i] = 0.25 * me[i]; } meInfo(save); return 0.25*output/3.; } void MEPP2VV::constructVertex(tSubProPtr sub) { // extract the particles in the hard process ParticleVector hard; hard.push_back(sub->incoming().first); hard.push_back(sub->incoming().second); hard.push_back(sub->outgoing()[0]); hard.push_back(sub->outgoing()[1]); // order of particles unsigned int order[4]={0,1,2,3}; if(hard[order[0]]->id()<0) swap(order[0],order[1]); vector q; vector qb; SpinorWaveFunction (q ,hard[order[0]],incoming,false); SpinorBarWaveFunction(qb,hard[order[1]],incoming,false); vector w1,w2; // q qbar -> Z Z if(hard[order[2]]->id()==ParticleID::Z0&& hard[order[3]]->id()==ParticleID::Z0) { VectorWaveFunction (w1,hard[order[2]],outgoing,true ,false); VectorWaveFunction (w2,hard[order[3]],outgoing,true ,false); ZZME(q,qb,w1,w2,true); } // q qbar -> W W else if(abs(hard[order[2]]->id())==ParticleID::Wplus&& abs(hard[order[3]]->id())==ParticleID::Wplus) { if((hard[order[0]]->id()%2==1&&hard[order[2]]->id()==ParticleID::Wplus)|| (hard[order[0]]->id()%2==0&&hard[order[2]]->id()==ParticleID::Wminus)) swap(order[2],order[3]); VectorWaveFunction (w1,hard[order[2]],outgoing,true ,false); VectorWaveFunction (w2,hard[order[3]],outgoing,true ,false); WWME(q,qb,w1,w2,true); } // q qbar -> W Z else { if(abs(hard[order[2]]->id())!=ParticleID::Wplus) swap(order[2],order[3]); VectorWaveFunction (w1,hard[order[2]],outgoing,true ,false); VectorWaveFunction (w2,hard[order[3]],outgoing,true ,false); WZME(q,qb,w1,w2,true); } // construct the vertex HardVertexPtr hardvertex=new_ptr(HardVertex()); // set the matrix element for the vertex hardvertex->ME(me_); // set the pointers and to and from the vertex for(unsigned int ix=0;ix<4;++ix) hard[order[ix]]->spinInfo()->productionVertex(hardvertex); } diff --git a/MatrixElement/Hadron/MEPP2WH.cc b/MatrixElement/Hadron/MEPP2WH.cc --- a/MatrixElement/Hadron/MEPP2WH.cc +++ b/MatrixElement/Hadron/MEPP2WH.cc @@ -1,153 +1,157 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the MEPP2WH class. // #include "MEPP2WH.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "Herwig/Models/StandardModel/StandardModel.h" using namespace Herwig; MEPP2WH::MEPP2WH() : _plusminus(0) {} // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigMEPP2WH("Herwig::MEPP2WH", "HwMEHadron.so"); void MEPP2WH::persistentOutput(PersistentOStream & os) const { os << _plusminus; } void MEPP2WH::persistentInput(PersistentIStream & is, int) { is >> _plusminus; } void MEPP2WH::Init() { static ClassDocumentation documentation ("The MEPP2WH class implements the matrix element for the Bjorken" " process q qbar -> WH"); static Switch interfacePlusMinus ("Wcharge", "Which intermediate W bosons to include", &MEPP2WH::_plusminus, 0, false, false); static SwitchOption interfacePlusMinusAll (interfacePlusMinus, "Both", "Include W+ and W-", 0); static SwitchOption interfacePlusMinusPlus (interfacePlusMinus, "Plus", "Only include W+", 1); static SwitchOption interfacePlusMinusMinus (interfacePlusMinus, "Minus", "Only include W-", 2); } void MEPP2WH::getDiagrams() const { // which intgermediates to include bool wplus =_plusminus==0||_plusminus==1; bool wminus=_plusminus==0||_plusminus==2; tPDPtr higgs = getParticleData(ParticleID::h0); // possible parents vector parentpair; parentpair.reserve(6); // don't even think of putting 'break' in here! switch(maxFlavour()) { case 5: parentpair.push_back(make_pair(getParticleData(ParticleID::b), getParticleData(ParticleID::cbar))); parentpair.push_back(make_pair(getParticleData(ParticleID::b), getParticleData(ParticleID::ubar))); + [[fallthrough]]; case 4: parentpair.push_back(make_pair(getParticleData(ParticleID::s), getParticleData(ParticleID::cbar))); parentpair.push_back(make_pair(getParticleData(ParticleID::d), getParticleData(ParticleID::cbar))); + [[fallthrough]]; case 3: parentpair.push_back(make_pair(getParticleData(ParticleID::s), getParticleData(ParticleID::ubar))); + [[fallthrough]]; case 2: parentpair.push_back(make_pair(getParticleData(ParticleID::d), getParticleData(ParticleID::ubar))); + [[fallthrough]]; default: ; } // possible children typedef Selector DecaySelector; // for W+ DecaySelector wpdec = getParticleData(ParticleID::Wplus)->decaySelector(); vector wpdecays; for(DecaySelector::const_iterator cit=wpdec.begin();cit!=wpdec.end();++cit) { if(cit->second->orderedProducts().size()!=2) continue; if(cit->second->orderedProducts()[0]->id()>0) wpdecays.push_back(make_pair(cit->second->orderedProducts()[0], cit->second->orderedProducts()[1])); else wpdecays.push_back(make_pair(cit->second->orderedProducts()[1], cit->second->orderedProducts()[0])); } // for W- DecaySelector wmdec = getParticleData(ParticleID::Wminus)->decaySelector(); vector wmdecays; for(DecaySelector::const_iterator cit=wmdec.begin();cit!=wmdec.end();++cit) { if(cit->second->orderedProducts().size()!=2) continue; if(cit->second->orderedProducts()[0]->id()>0) wmdecays.push_back(make_pair(cit->second->orderedProducts()[0], cit->second->orderedProducts()[1])); else wmdecays.push_back(make_pair(cit->second->orderedProducts()[1], cit->second->orderedProducts()[0])); } vector::const_iterator parent = parentpair.begin(); for (; parent != parentpair.end(); ++parent) { // W- modes if(wminus) { for(unsigned int ix=0;ixfirst, parent->second, 1, WMinus(), 3, higgs, 3, WMinus(), 5, wmdecays[ix].first,5, wmdecays[ix].second,-1))); } } // W+ modes if(wplus) { for(unsigned int ix=0;ixsecond->CC(), parent->first->CC(), 1, WPlus(), 3, higgs, 3, WPlus(), 5, wpdecays[ix].first, 5, wpdecays[ix].second, -1))); } } } } void MEPP2WH::doinit() { // get the vedrtex pointers from the SM object tcHwSMPtr hwsm= dynamic_ptr_cast(standardModel()); if(!hwsm) throw InitException() << "Wrong type of StandardModel object in " << "MEPP2WH::doinit() the Herwig" << " version must be used" << Exception::runerror; // set the vertex setWWHVertex(hwsm->vertexWWH()); higgs(getParticleData(ParticleID::h0)); MEfftoVH::doinit(); } diff --git a/MatrixElement/Hadron/MEPP2WJet.cc b/MatrixElement/Hadron/MEPP2WJet.cc --- a/MatrixElement/Hadron/MEPP2WJet.cc +++ b/MatrixElement/Hadron/MEPP2WJet.cc @@ -1,838 +1,842 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the MEPP2WJet class. // #include "MEPP2WJet.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "Herwig/Models/StandardModel/StandardModel.h" #include "ThePEG/Helicity/Vertex/Vector/FFVVertex.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Handlers/StandardXComb.h" #include "ThePEG/Utilities/SimplePhaseSpace.h" #include "ThePEG/Cuts/Cuts.h" #include "Herwig/MatrixElement/HardVertex.h" using namespace Herwig; MEPP2WJet::MEPP2WJet() : _process(0), _maxflavour(5), _plusminus(0), _wdec(0), _widthopt(1) {} void MEPP2WJet::doinit() { HwMEBase::doinit(); _wplus = getParticleData(ThePEG::ParticleID::Wplus ); _wminus = getParticleData(ThePEG::ParticleID::Wminus); // cast the SM pointer to the Herwig SM pointer ThePEG::Ptr::transient_const_pointer hwsm=ThePEG::dynamic_ptr_cast< ThePEG::Ptr ::transient_const_pointer>(standardModel()); // do the initialisation if(!hwsm) throw InitException() << "Must be Herwig::StandardModel in MEPP2WJet::doinit()" << Exception::runerror; // set the vertex pointers _theFFWVertex = hwsm->vertexFFW(); _theQQGVertex = hwsm->vertexFFG(); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigMEPP2WJet("Herwig::MEPP2WJet", "HwMEHadron.so"); void MEPP2WJet::Init() { static ClassDocumentation documentation ("The MEPP2WJet class implements the matrix element for W + jet production"); static Parameter interfaceMaxFlavour ( "MaxFlavour", "The heaviest incoming quark flavour this matrix element is allowed to handle " "(if applicable).", &MEPP2WJet::_maxflavour, 5, 0, 8, false, false, true); static Switch interfaceProcess ("Process", "Which subprocesses to include", &MEPP2WJet::_process, 0, false, false); static SwitchOption interfaceProcessAll (interfaceProcess, "All", "Include all subprocesses", 0); static SwitchOption interfaceProcessqqbar (interfaceProcess, "qqbar", "Only include q qbar -> W g process", 1); static SwitchOption interfaceProcessqg (interfaceProcess, "qg", "Only include the q g -> W q process", 2); static SwitchOption interfaceProcessqbarg (interfaceProcess, "qbarg", "Only include the qbar g -> W qbar process", 3); static Switch interfacePlusMinus ("Wcharge", "Which intermediate W bosons to include", &MEPP2WJet::_plusminus, 0, false, false); static SwitchOption interfacePlusMinusAll (interfacePlusMinus, "Both", "Include W+ and W-", 0); static SwitchOption interfacePlusMinusPlus (interfacePlusMinus, "Plus", "Only include W+", 1); static SwitchOption interfacePlusMinusMinus (interfacePlusMinus, "Minus", "Only include W-", 2); static Switch interfaceWDecay ("WDecay", "Which processes to include", &MEPP2WJet::_wdec, 0, false, false); static SwitchOption interfaceWDecayAll (interfaceWDecay, "All", "Include all SM fermions as outgoing particles", 0); static SwitchOption interfaceWDecayQuarks (interfaceWDecay, "Quarks", "Only include outgoing quarks", 1); static SwitchOption interfaceWDecayLeptons (interfaceWDecay, "Leptons", "All include outgoing leptons", 2); static SwitchOption interfaceWDecayElectron (interfaceWDecay, "Electron", "Only include outgoing e nu_e", 3); static SwitchOption interfaceWDecayMuon (interfaceWDecay, "Muon", "Only include outgoing mu nu_mu", 4); static SwitchOption interfaceWDecayTau (interfaceWDecay, "Tau", "Only include outgoing tauu nu_tau", 5); static SwitchOption interfaceWDecayUpDown (interfaceWDecay, "UpDown", "Only include outgoing u dbar/ d ubar", 6); static SwitchOption interfaceWDecayUpStrange (interfaceWDecay, "UpStrange", "Only include outgoing u sbar/ s ubar", 7); static SwitchOption interfaceWDecayUpBottom (interfaceWDecay, "UpBottom", "Only include outgoing u bbar/ b ubar", 8); static SwitchOption interfaceWDecayCharmDown (interfaceWDecay, "CharmDown", "Only include outgoing c dbar/ d cbar", 9); static SwitchOption interfaceWDecayCharmStrange (interfaceWDecay, "CharmStrange", "Only include outgoing c sbar/ s cbar", 10); static SwitchOption interfaceWDecayCharmBottom (interfaceWDecay, "CharmBottom", "Only include outgoing c bbar/ b cbar", 11); static Switch interfaceWidthOption ("WidthOption", "The option for handling the width of the off-shell W boson", &MEPP2WJet::_widthopt, 1, false, false); static SwitchOption interfaceWidthOptionFixedDenominator (interfaceWidthOption, "FixedDenominator", "Use a fixed with in the W propagator but the full matrix element" " in the numerator", 1); static SwitchOption interfaceWidthOptionAllRunning (interfaceWidthOption, "AllRunning", "Use a running width in the W propagator and the full matrix " "element in the numerator", 2); } void MEPP2WJet::getDiagrams() const { // which intgermediates to include bool wplus = _plusminus==0 || _plusminus==1; bool wminus = _plusminus==0 || _plusminus==2; // possible incoming and outgoing particles typedef std::vector > Pairvector; // possible parents Pairvector parentpair; parentpair.reserve(6); // don't even think of putting 'break' in here! switch(_maxflavour) { case 5: parentpair.push_back(make_pair(ParticleID::b, ParticleID::cbar)); parentpair.push_back(make_pair(ParticleID::b, ParticleID::ubar)); + [[fallthrough]]; case 4: parentpair.push_back(make_pair(ParticleID::s, ParticleID::cbar)); parentpair.push_back(make_pair(ParticleID::d, ParticleID::cbar)); + [[fallthrough]]; case 3: parentpair.push_back(make_pair(ParticleID::s, ParticleID::ubar)); + [[fallthrough]]; case 2: parentpair.push_back(make_pair(ParticleID::d, ParticleID::ubar)); + [[fallthrough]]; default: ; } // possible children Pairvector childpair; childpair.reserve(9); childpair.push_back(make_pair(ParticleID::eminus, ParticleID::nu_ebar)); childpair.push_back(make_pair(ParticleID::muminus, ParticleID::nu_mubar)); childpair.push_back(make_pair(ParticleID::tauminus, ParticleID::nu_taubar)); childpair.push_back(make_pair(ParticleID::d, ParticleID::ubar)); childpair.push_back(make_pair(ParticleID::s, ParticleID::ubar)); childpair.push_back(make_pair(ParticleID::b, ParticleID::ubar)); childpair.push_back(make_pair(ParticleID::d, ParticleID::cbar)); childpair.push_back(make_pair(ParticleID::s, ParticleID::cbar)); childpair.push_back(make_pair(ParticleID::b, ParticleID::cbar)); // gluon for diagrams tcPDPtr g = getParticleData(ParticleID::g); // loop over the children bool lepton,quark; Pairvector::const_iterator child = childpair.begin(); for (; child != childpair.end(); ++child) { // allowed leptonic decay lepton=child->first>10&& (_wdec==0||_wdec==2|| (abs(child->first)-5)/2==int(_wdec)); // allowed quark decay quark =abs(child->second)<10&& (_wdec==0||_wdec==1|| (abs(child->second)==2&&(abs(child->first)+11)/2==int(_wdec))|| (abs(child->second)==4&&(abs(child->first)+17)/2==int(_wdec))); // if decay not allowed skip if(!(quark||lepton)) continue; // decay products tcPDPtr lNeg1 = getParticleData(child->first); tcPDPtr lNeg2 = getParticleData(child->second); tcPDPtr lPos1 = lNeg2->CC(); tcPDPtr lPos2 = lNeg1->CC(); Pairvector::const_iterator parent = parentpair.begin(); for (; parent != parentpair.end(); ++parent) { // parents tcPDPtr qNeg1 = getParticleData(parent->first); tcPDPtr qNeg2 = getParticleData(parent->second); tcPDPtr qPos1 = qNeg2->CC(); tcPDPtr qPos2 = qNeg1->CC(); // diagrams // q qbar annhilation processes if(_process==0||_process==1) { // q qbar -> W- g if(wminus) { add(new_ptr((Tree2toNDiagram(3), qNeg1, qNeg2, qNeg2, 1, _wminus, 2, g, 4, lNeg1, 4, lNeg2, -1))); add(new_ptr((Tree2toNDiagram(3), qNeg1, qNeg1, qNeg2, 2, _wminus, 1, g, 4, lNeg1, 4, lNeg2, -2))); } // q qbar -> W+ g if(wplus) { add(new_ptr((Tree2toNDiagram(3), qPos1, qPos2, qPos2, 1, _wplus, 2, g, 4, lPos1, 4, lPos2, -3))); add(new_ptr((Tree2toNDiagram(3), qPos1, qPos1, qPos2, 2, _wplus, 1, g, 4, lPos1, 4, lPos2, -4))); } } // q g compton if(_process==0||_process==2) { if(wminus) { add(new_ptr((Tree2toNDiagram(3), qNeg1, qPos1, g , 1, _wminus, 2, qPos1, 4, lNeg1, 4, lNeg2, -5))); add(new_ptr((Tree2toNDiagram(2), qNeg1, g, 1, qNeg1, 3, _wminus, 3, qPos1, 4, lNeg1, 4, lNeg2, -6))); } if(wplus) { add(new_ptr((Tree2toNDiagram(3), qPos1, qNeg1, g, 1, _wplus, 2, qNeg1, 4, lPos1, 4, lPos2, -7))); add(new_ptr((Tree2toNDiagram(2), qPos1, g, 1, qNeg1, 3, _wplus, 3, qNeg1, 4, lPos1, 4, lPos2, -8))); } } // qbar g compton if(_process==0||_process==3) { if(wminus) { add(new_ptr((Tree2toNDiagram(3), qNeg2, qPos2, g, 1, _wminus, 2, qPos2, 4, lNeg1, 4, lNeg2, -9 ))); add(new_ptr((Tree2toNDiagram(2), qNeg2, g, 1, qNeg2, 3, _wminus, 3, qPos2, 4, lNeg1, 4, lNeg2, -10))); } if(wplus) { add(new_ptr((Tree2toNDiagram(3), qPos2, qNeg2, g, 1, _wplus, 2, qNeg2, 4, lPos1, 4, lPos2, -11))); add(new_ptr((Tree2toNDiagram(2), qPos2, g, 1, qPos2, 3, _wplus, 3, qNeg2, 4, lPos1, 4, lPos2, -12))); } } } } } unsigned int MEPP2WJet::orderInAlphaS() const { return 1; } unsigned int MEPP2WJet::orderInAlphaEW() const { return 2; } void MEPP2WJet::persistentOutput(PersistentOStream & os) const { os << _theFFWVertex << _theQQGVertex << _wplus << _widthopt << _wminus << _process << _maxflavour << _plusminus << _wdec; } void MEPP2WJet::persistentInput(PersistentIStream & is, int) { is >> _theFFWVertex >> _theQQGVertex >> _wplus >> _widthopt >> _wminus >> _process >> _maxflavour >> _plusminus >> _wdec; } int MEPP2WJet::nDim() const { return 5; } Selector MEPP2WJet::colourGeometries(tcDiagPtr diag) const { // colour lines for q qbar -> W g static const ColourLines cqqbar[4]={ColourLines("1 -2 5,-3 -5"), ColourLines("1 5, -5 2 -3"), ColourLines("1 -2 5,-3 -5,6 -7"), ColourLines("1 5, -5 2 -3,6 -7")}; // colour lines for q g -> W q static const ColourLines cqg [4]={ColourLines("1 2 -3,3 5"), ColourLines("1 -2,2 3 5"), ColourLines("1 2 -3,3 5,6 -7"), ColourLines("1 -2,2 3 5,6 -7")}; // colour lines for qbar q -> W qbar static const ColourLines cqbarg[4]={ColourLines("-1 -2 3,-3 -5"), ColourLines("-1 2,-2 -3 -5"), ColourLines("-1 -2 3,-3 -5,6 -7"), ColourLines("-1 2,-2 -3 -5,6 -7")}; // select the correct line unsigned int icol = mePartonData()[3]->coloured() ? 2 : 0; Selector sel; switch(abs(diag->id())) { case 1 : case 3: sel.insert(1.0, &cqqbar[icol]); break; case 2 : case 4: sel.insert(1.0, &cqqbar[icol+1]); break; case 5 : case 7: sel.insert(1.0, &cqg[icol]); break; case 6 : case 8: sel.insert(1.0, &cqg[icol+1]); break; case 9 : case 11: sel.insert(1.0, &cqbarg[icol]); break; case 10 : case 12: sel.insert(1.0, &cqbarg[icol+1]); break; } return sel; } Selector MEPP2WJet::diagrams(const DiagramVector & diags) const { Selector sel; for ( DiagramIndex i = 0; i < diags.size(); ++i ) { int id=abs(diags[i]->id()); if (id <= 2 ) sel.insert(meInfo()[id- 1],i); else if(id <= 4 ) sel.insert(meInfo()[id- 3],i); else if(id <= 6 ) sel.insert(meInfo()[id- 5],i); else if(id <= 8 ) sel.insert(meInfo()[id- 7],i); else if(id <= 10) sel.insert(meInfo()[id- 9],i); else if(id <= 12) sel.insert(meInfo()[id-11],i); } return sel; } Energy2 MEPP2WJet::scale() const { return _scale; } CrossSection MEPP2WJet::dSigHatDR() const { return me2()*jacobian()/(16.0*sqr(Constants::pi)*sHat())*sqr(hbarc); } bool MEPP2WJet::generateKinematics(const double * r) { // initialize jacobian jacobian(1.); // cms energy Energy ecm=sqrt(sHat()); // find the right W pointer tcPDPtr wdata = mePartonData()[3]->iCharge()+mePartonData()[4]->iCharge() > 0 ? _wplus :_wminus; // first generate the mass of the off-shell gauge boson // minimum mass of the tcPDVector ptemp; ptemp.push_back(mePartonData()[3]); ptemp.push_back(mePartonData()[4]); Energy2 minMass2 = max(lastCuts().minSij(mePartonData()[3],mePartonData()[4]), lastCuts().minS(ptemp)); // minimum pt of the jet Energy ptmin = max(lastCuts().minKT(mePartonData()[2]), lastCuts().minKT(wdata)); // maximum mass of the gauge boson so pt is possible Energy2 maxMass2 = min(ecm*(ecm-2.*ptmin),lastCuts().maxS(ptemp)); if(maxMass2<=ZERO||minMass2massMin())); maxMass2 = min(maxMass2,sqr(wdata->massMax())); // return if not kinematically possible if(minMass2>maxMass2) return false; // generation of the mass Energy M(wdata->mass()),Gamma(wdata->width()); Energy2 M2(sqr(M)),MG(M*Gamma); double rhomin = atan2((minMass2-M2),MG); double rhomax = atan2((maxMass2-M2),MG); _mw2=M2+MG*tan(rhomin+r[1]*(rhomax-rhomin)); Energy mw=sqrt(_mw2); // jacobian jacobian(jacobian()*(sqr(_mw2-M2)+sqr(MG))/MG*(rhomax-rhomin)/sHat()); // set the masses of the outgoing particles in the 2-2 scattering meMomenta()[2].setMass(ZERO); Lorentz5Momentum pw(mw); // generate the polar angle of the hard scattering double ctmin(-1.0), ctmax(1.0); Energy q(ZERO); try { q = SimplePhaseSpace::getMagnitude(sHat(), meMomenta()[2].mass(),mw); } catch ( ImpossibleKinematics ) { return false; } Energy2 pq = sqrt(sHat())*q; if ( ptmin > ZERO ) { double ctm = 1.0 - sqr(ptmin/q); if ( ctm <= 0.0 ) return false; ctmin = max(ctmin, -sqrt(ctm)); ctmax = min(ctmax, sqrt(ctm)); } if ( ctmin >= ctmax ) return false; double cth = getCosTheta(ctmin, ctmax, r[0]); // momenta of particle in hard scattering Energy pt = q*sqrt(1.0-sqr(cth)); double phi=2.0*Constants::pi*r[2]; meMomenta()[2].setVect(Momentum3( pt*sin(phi), pt*cos(phi), q*cth)); pw.setVect( Momentum3(-pt*sin(phi),-pt*cos(phi),-q*cth)); meMomenta()[2].rescaleEnergy(); pw.rescaleEnergy(); // set the scale _scale = _mw2+sqr(pt); // generate the momenta of the W decay products meMomenta()[3].setMass(mePartonData()[3]->mass()); meMomenta()[4].setMass(mePartonData()[4]->mass()); Energy q2 = ZERO; try { q2 = SimplePhaseSpace::getMagnitude(_mw2, meMomenta()[3].mass(), meMomenta()[4].mass()); } catch ( ImpossibleKinematics ) { return false; } double cth2 =-1.+2.*r[3]; double phi2=Constants::twopi*r[4]; Energy pt2 =q2*sqrt(1.-sqr(cth2)); Lorentz5Momentum pl[2]={Lorentz5Momentum( pt2*cos(phi2), pt2*sin(phi2), q2*cth2,ZERO, meMomenta()[3].mass()), Lorentz5Momentum(-pt2*cos(phi2),-pt2*sin(phi2),-q2*cth2,ZERO, meMomenta()[4].mass())}; pl[0].rescaleEnergy(); pl[1].rescaleEnergy(); Boost boostv(pw.boostVector()); pl[0].boost(boostv); pl[1].boost(boostv); meMomenta()[3] = pl[0]; meMomenta()[4] = pl[1]; // check passes all the cuts vector out(3); out[0] = meMomenta()[2]; out[1] = meMomenta()[3]; out[2] = meMomenta()[4]; tcPDVector tout(3); tout[0] = mePartonData()[2]; tout[1] = mePartonData()[3]; tout[2] = mePartonData()[4]; if ( !lastCuts().passCuts(tout, out, mePartonData()[0], mePartonData()[1]) ) return false; // jacobian jacobian((pq/sHat())*Constants::pi*jacobian()/8./sqr(Constants::pi)*q2/mw); return true; } double MEPP2WJet::me2() const { InvEnergy2 output(ZERO); // construct spinors for the leptons (always the same) vector lm; vector lp; SpinorBarWaveFunction lmout(meMomenta()[3],mePartonData()[3],outgoing); SpinorWaveFunction lpout(meMomenta()[4],mePartonData()[4],outgoing); for(unsigned int ix=0;ix<2;++ix) { lmout.reset(ix);lm.push_back(lmout); lpout.reset(ix);lp.push_back(lpout); } // q g to q W if(mePartonData()[0]->id()<=6&&mePartonData()[0]->id()>0&& mePartonData()[1]->id()==ParticleID::g) { // polarization states for the particles vector fin; vector gin; vector fout; SpinorWaveFunction qin (meMomenta()[0],mePartonData()[0],incoming); VectorWaveFunction glin(meMomenta()[1],mePartonData()[1],incoming); SpinorBarWaveFunction qout(meMomenta()[2],mePartonData()[2],outgoing); for(unsigned int ix=0;ix<2;++ix) { qin.reset(ix) ; fin.push_back(qin); glin.reset(2*ix); gin.push_back(glin); qout.reset(ix);fout.push_back(qout); } output=qgME(fin,gin,fout,lm,lp); } // qbar g to qbar W else if(mePartonData()[0]->id()>=-6&&mePartonData()[0]->id()<0&& mePartonData()[1]->id()==ParticleID::g) { vector ain; vector gin; vector aout; SpinorBarWaveFunction qbin (meMomenta()[0],mePartonData()[0],incoming); VectorWaveFunction glin (meMomenta()[1],mePartonData()[1],incoming); SpinorWaveFunction qbout(meMomenta()[2],mePartonData()[2],outgoing); for(unsigned int ix=0;ix<2;++ix) { qbin.reset(ix) ; ain.push_back(qbin); glin.reset(2*ix) ; gin.push_back(glin); qbout.reset(ix);aout.push_back(qbout); } output=qbargME(ain,gin,aout,lm,lp); } // q qbar to g W else { vector fin; vector ain; vector gout; SpinorWaveFunction qin (meMomenta()[0],mePartonData()[0],incoming); SpinorBarWaveFunction qbin(meMomenta()[1],mePartonData()[1],incoming); VectorWaveFunction glout(meMomenta()[2],mePartonData()[2],outgoing); for(unsigned int ix=0;ix<2;++ix) { qin.reset(ix) ; fin.push_back(qin); qbin.reset(ix) ; ain.push_back(qbin); glout.reset(2*ix); gout.push_back(glout); } output=qqbarME(fin,ain,gout,lm,lp); } return output*sHat(); } InvEnergy2 MEPP2WJet::qqbarME(vector & fin, vector & ain, vector & gout, vector & lm, vector & lp, bool calc) const { // if calculation spin corrections construct the me if(calc) _me.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1,PDT::Spin1Half, PDT::Spin1Half)); // some integers unsigned int ihel1,ihel2,ohel1,ohel2,ohel3; // find the right W pointer tcPDPtr wdata = mePartonData()[3]->iCharge()+mePartonData()[4]->iCharge() > 0 ? _wplus :_wminus; // compute the W current for speed VectorWaveFunction bcurr[2][2]; for(ohel2=0;ohel2<2;++ohel2) { for(ohel3=0;ohel3<2;++ohel3) { bcurr[ohel2][ohel3] = _theFFWVertex->evaluate(_mw2,_widthopt,wdata, lp[ohel3],lm[ohel2]); } } double me[3]={0.,0.,0.}; Complex diag[2]; SpinorWaveFunction inters; SpinorBarWaveFunction interb; for(ihel1=0;ihel1<2;++ihel1) { for(ihel2=0;ihel2<2;++ihel2) { for(ohel1=0;ohel1<2;++ohel1) { // intermediates for the diagrams inters=_theQQGVertex->evaluate(_scale,5,mePartonData()[0], fin[ihel1],gout[ohel1]); interb=_theQQGVertex->evaluate(_scale,5,mePartonData()[1], ain[ihel2],gout[ohel1]); for(ohel2=0;ohel2<2;++ohel2) { for(ohel3=0;ohel3<2;++ohel3) { diag[0] = _theFFWVertex->evaluate(_mw2,fin[ihel1],interb, bcurr[ohel2][ohel3]); diag[1] = _theFFWVertex->evaluate(_mw2,inters,ain[ihel2], bcurr[ohel2][ohel3]); // diagram contributions me[1] += norm(diag[0]); me[2] += norm(diag[1]); // total diag[0] += diag[1]; me[0] += norm(diag[0]); if(calc) _me(ihel1,ihel2,2*ohel1,ohel2,ohel3) = diag[0]; } } } } } // results // initial state spin and colour average double colspin=1./9./4.; // and C_F N_c from matrix element colspin *= 4.; // colour factor for the W decay if(mePartonData()[3]->coloured()) colspin*=3.; DVector save; for(unsigned int ix=0;ix<3;++ix) { me[ix]*=colspin; if(ix>0) save.push_back(me[ix]); } meInfo(save); return me[0] * UnitRemoval::InvE2; } InvEnergy2 MEPP2WJet::qgME(vector & fin, vector & gin, vector & fout, vector & lm, vector & lp, bool calc) const { // if calculation spin corrections construct the me if(calc) _me.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1, PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1Half)); // find the right W pointer tcPDPtr wdata = mePartonData()[3]->iCharge()+mePartonData()[4]->iCharge() > 0 ? _wplus :_wminus; // some integers unsigned int ihel1,ihel2,ohel1,ohel2,ohel3; // compute the leptonic W current for speed VectorWaveFunction bcurr[2][2]; for(ohel2=0;ohel2<2;++ohel2) { for(ohel3=0;ohel3<2;++ohel3) { bcurr[ohel2][ohel3] = _theFFWVertex->evaluate(_mw2,_widthopt,wdata, lp[ohel3],lm[ohel2]); } } // compute the matrix elements double me[3]={0.,0.,0.}; Complex diag[2]; SpinorWaveFunction inters; SpinorBarWaveFunction interb; for(ihel1=0;ihel1<2;++ihel1) { for(ihel2=0;ihel2<2;++ihel2) { for(ohel1=0;ohel1<2;++ohel1) { // intermediates for the diagrams interb=_theQQGVertex->evaluate(_scale,5,mePartonData()[2], fout[ohel1],gin[ihel2]); inters=_theQQGVertex->evaluate(_scale,5,mePartonData()[0], fin[ihel1],gin[ihel2]); for(ohel2=0;ohel2<2;++ohel2) { for(ohel3=0;ohel3<2;++ohel3) { diag[0]=_theFFWVertex->evaluate(_mw2,fin[ihel1],interb, bcurr[ohel2][ohel3]); diag[1]=_theFFWVertex->evaluate(_mw2,inters,fout[ohel1], bcurr[ohel2][ohel3]); // diagram contributions me[1] += norm(diag[0]); me[2] += norm(diag[1]); // total diag[0] += diag[1]; me[0] += norm(diag[0]); if(calc) _me(ihel1,2*ihel2,ohel1,ohel2,ohel3) = diag[0]; } } } } } // results // initial state spin and colour average double colspin=1./24./4.; // and C_F N_c from matrix element colspin *=4.; // colour factor for the W decay if(mePartonData()[3]->coloured()) colspin*=3.; DVector save; for(unsigned int ix=0;ix<3;++ix) { me[ix]*=colspin; if(ix>0) save.push_back(me[ix]); } meInfo(save); return me[0] * UnitRemoval::InvE2; } InvEnergy2 MEPP2WJet::qbargME(vector & fin, vector & gin, vector & fout, vector & lm, vector & lp, bool calc) const { // if calculation spin corrections construct the me if(calc) _me.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1, PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1Half)); // find the right W pointer tcPDPtr wdata = mePartonData()[3]->iCharge()+mePartonData()[4]->iCharge() > 0 ? _wplus :_wminus; // some integers unsigned int ihel1,ihel2,ohel1,ohel2,ohel3; // compute the leptonic W current for speed VectorWaveFunction bcurr[2][2]; for(ohel2=0;ohel2<2;++ohel2) { for(ohel3=0;ohel3<2;++ohel3) { bcurr[ohel2][ohel3] = _theFFWVertex->evaluate(_mw2,_widthopt,wdata, lp[ohel3],lm[ohel2]); } } // compute the matrix elements double me[3]={0.,0.,0.}; Complex diag[2]; SpinorWaveFunction inters; SpinorBarWaveFunction interb; for(ihel1=0;ihel1<2;++ihel1) { for(ihel2=0;ihel2<2;++ihel2) { for(ohel1=0;ohel1<2;++ohel1) { // intermediates for the diagrams inters=_theQQGVertex->evaluate(_scale,5,mePartonData()[2]->CC(), fout[ohel1],gin[ihel2]); interb=_theQQGVertex->evaluate(_scale,5,mePartonData()[0], fin[ihel1],gin[ihel2]); for(ohel2=0;ohel2<2;++ohel2) { for(ohel3=0;ohel3<2;++ohel3) { diag[0]= _theFFWVertex->evaluate(_mw2,inters,fin[ihel1], bcurr[ohel2][ohel3]); diag[1]= _theFFWVertex->evaluate(_mw2,fout[ohel1],interb, bcurr[ohel2][ohel3]); // diagram contributions me[1] += norm(diag[0]); me[2] += norm(diag[1]); // total diag[0] += diag[1]; me[0] += norm(diag[0]); if(calc) _me(ihel1,2*ihel2,ohel1,ohel2,ohel3) = diag[0]; } } } } } // results // initial state spin and colour average double colspin=1./24./4.; // and C_F N_c from matrix element colspin *= 4.; // colour factor for the W decay if(mePartonData()[3]->coloured()) colspin*=3.; DVector save; for(unsigned int ix=0;ix<3;++ix) { me[ix]*=colspin; if(ix>0) save.push_back(me[ix]); } meInfo(save); return me[0] * UnitRemoval::InvE2; } void MEPP2WJet::constructVertex(tSubProPtr sub) { // extract the particles in the hard process ParticleVector hard(5); // incoming hard[0]=sub->incoming().first; hard[1]=sub->incoming().second; if((hard[0]->id()<0&&hard[1]->id()<=6)|| hard[0]->id()==ParticleID::g) swap(hard[0],hard[1]); // outgoing for(unsigned int ix=0;ix<3;++ix) { unsigned int iloc; PPtr mother=sub->outgoing()[ix]->parents()[0]; if(mother&&abs(mother->id())==ParticleID::Wplus) { if(sub->outgoing()[ix]->id()>0) iloc=3; else iloc=4; } else iloc=2; hard[iloc]=sub->outgoing()[ix]; } // wavefunctions for the W decay products vector lm; vector lp; SpinorBarWaveFunction(lm,hard[3],outgoing,true,true); SpinorWaveFunction (lp,hard[4],outgoing,true,true); // identify hard process and calculate matrix element // q g to q W if(hard[0]->id()<=6&&hard[0]->id()>0&&hard[1]->id()==ParticleID::g) { vector fin; vector gin; vector fout; SpinorWaveFunction (fin ,hard[0],incoming,false,true); VectorWaveFunction (gin ,hard[1],incoming,false,true,true); SpinorBarWaveFunction (fout,hard[2],outgoing,true ,true); gin[1]=gin[2]; qgME(fin,gin,fout,lm,lp,true); } // qbar g to qbar W else if(hard[0]->id()>=-6&&hard[0]->id()<0&&hard[1]->id()==ParticleID::g) { vector ain; vector gin; vector aout; SpinorBarWaveFunction(ain ,hard[0],incoming,false,true); VectorWaveFunction (gin ,hard[1],incoming,false,true,true); SpinorWaveFunction (aout,hard[2],outgoing,true ,true); gin[1]=gin[2]; qbargME(ain,gin,aout,lm,lp,true); } // q qbar to g W else { vector fin; vector ain; vector gout; SpinorWaveFunction (fin ,hard[0],incoming,false,true); SpinorBarWaveFunction(ain ,hard[1],incoming,false,true); VectorWaveFunction (gout,hard[2],outgoing,true ,true,true); gout[1]=gout[2]; qqbarME(fin,ain,gout,lm,lp,true); } // construct the vertex HardVertexPtr hardvertex=new_ptr(HardVertex()); // set the matrix element for the vertex hardvertex->ME(_me); // set the pointers and to and from the vertex for(unsigned int ix=0;ix<5;++ix) (hard[ix]->spinInfo())->productionVertex(hardvertex); } diff --git a/MatrixElement/Hadron/MEqq2W2ff.cc b/MatrixElement/Hadron/MEqq2W2ff.cc --- a/MatrixElement/Hadron/MEqq2W2ff.cc +++ b/MatrixElement/Hadron/MEqq2W2ff.cc @@ -1,357 +1,361 @@ // -*- C++ -*- // // MEqq2W2ff.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 MEqq2W2ff class. // #include "MEqq2W2ff.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "ThePEG/Handlers/StandardXComb.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "Herwig/Models/StandardModel/StandardModel.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/PDT/EnumParticles.h" #include "Herwig/MatrixElement/HardVertex.h" #include using namespace Herwig; MEqq2W2ff::MEqq2W2ff() : _maxflavour(5), _plusminus(0), _process(0) { massOption(vector(2,1)); } void MEqq2W2ff::doinit() { DrellYanBase::doinit(); _wp=getParticleData(ThePEG::ParticleID::Wplus); _wm=getParticleData(ThePEG::ParticleID::Wminus); // cast the SM pointer to the Herwig SM pointer tcHwSMPtr hwsm=ThePEG::dynamic_ptr_cast(standardModel()); // do the initialisation if(hwsm) _theFFWVertex = hwsm->vertexFFW(); else throw InitException() << "Must be the Herwig StandardModel class in " << "MEqq2W2ff::doinit" << Exception::abortnow; } void MEqq2W2ff::getDiagrams() const { // which intgermediates to include bool wplus =_plusminus==0||_plusminus==1; bool wminus=_plusminus==0||_plusminus==2; // possible incoming and outgoing particles typedef std::vector > Pairvector; // possible parents Pairvector parentpair; parentpair.reserve(6); // don't even think of putting 'break' in here! switch(_maxflavour) { case 5: parentpair.push_back(make_pair(ParticleID::b, ParticleID::cbar)); parentpair.push_back(make_pair(ParticleID::b, ParticleID::ubar)); + [[fallthrough]]; case 4: parentpair.push_back(make_pair(ParticleID::s, ParticleID::cbar)); parentpair.push_back(make_pair(ParticleID::d, ParticleID::cbar)); + [[fallthrough]]; case 3: parentpair.push_back(make_pair(ParticleID::s, ParticleID::ubar)); + [[fallthrough]]; case 2: parentpair.push_back(make_pair(ParticleID::d, ParticleID::ubar)); + [[fallthrough]]; default: ; } // possible children Pairvector childpair; childpair.reserve(9); childpair.push_back(make_pair(ParticleID::eminus, ParticleID::nu_ebar)); childpair.push_back(make_pair(ParticleID::muminus, ParticleID::nu_mubar)); childpair.push_back(make_pair(ParticleID::tauminus, ParticleID::nu_taubar)); childpair.push_back(make_pair(ParticleID::d, ParticleID::ubar)); childpair.push_back(make_pair(ParticleID::s, ParticleID::ubar)); childpair.push_back(make_pair(ParticleID::b, ParticleID::ubar)); childpair.push_back(make_pair(ParticleID::d, ParticleID::cbar)); childpair.push_back(make_pair(ParticleID::s, ParticleID::cbar)); childpair.push_back(make_pair(ParticleID::b, ParticleID::cbar)); // loop over the children bool lepton,quark; Pairvector::const_iterator child = childpair.begin(); for (; child != childpair.end(); ++child) { assert(child->first > 0 && child->second < 0); // allowed leptonic decay lepton = child->first > 10 && (_process==0 || _process==2 || (child->first - 5)/2 == int(_process)); // allowed quark decay quark = child->first < 10 && (_process==0 || _process==1 || (child->second == -2 && (child->first + 11)/2 == int(_process)) || (child->second == -4 && (child->first + 17)/2 == int(_process)) ); // if decay not allowed skip if(!(quark || lepton)) continue; // decay products tcPDPtr lNeg1 = getParticleData(child->first); tcPDPtr lNeg2 = getParticleData(child->second); tcPDPtr lPos1 = lNeg2->CC(); tcPDPtr lPos2 = lNeg1->CC(); Pairvector::const_iterator parent = parentpair.begin(); for (; parent != parentpair.end(); ++parent) { // parents tcPDPtr qNeg1 = getParticleData(parent->first); tcPDPtr qNeg2 = getParticleData(parent->second); tcPDPtr qPos1 = qNeg2->CC(); tcPDPtr qPos2 = qNeg1->CC(); // diagrams if(wminus) add(new_ptr((Tree2toNDiagram(2), qNeg1, qNeg2, 1, _wm, 3, lNeg1, 3, lNeg2, -1))); if(wplus) add(new_ptr((Tree2toNDiagram(2), qPos1, qPos2, 1, _wp, 3, lPos1, 3, lPos2, -2))); } } } Energy2 MEqq2W2ff::scale() const { return sHat(); } double MEqq2W2ff::me2() const { vector fin,aout; vector ain,fout; SpinorWaveFunction q (meMomenta()[0],mePartonData()[0],incoming); SpinorBarWaveFunction qbar(meMomenta()[1],mePartonData()[1],incoming); SpinorBarWaveFunction f (meMomenta()[2],mePartonData()[2],outgoing); SpinorWaveFunction fbar(meMomenta()[3],mePartonData()[3],outgoing); for(unsigned int ix=0;ix<2;++ix) { q.reset(ix) ; fin.push_back(q); qbar.reset(ix); ain.push_back(qbar); f.reset(ix) ;fout.push_back(f); fbar.reset(ix);aout.push_back(fbar); } return qqbarME(fin,ain,fout,aout,false); } unsigned int MEqq2W2ff::orderInAlphaS() const { return 0; } unsigned int MEqq2W2ff::orderInAlphaEW() const { return 2; } Selector MEqq2W2ff::diagrams(const DiagramVector &) const { Selector sel; sel.insert(1.0, 0); return sel; } Selector MEqq2W2ff::colourGeometries(tcDiagPtr) const { static const ColourLines c1("1 -2"); static const ColourLines c2("1 -2,4 -5"); Selector sel; if(abs(mePartonData()[2]->id())<=6) sel.insert(1.0, &c2); else sel.insert(1.0, &c1); return sel; } void MEqq2W2ff::persistentOutput(PersistentOStream & os) const { os << _maxflavour << _plusminus << _process << _theFFWVertex << _wp << _wm; } void MEqq2W2ff::persistentInput(PersistentIStream & is, int) { is >> _maxflavour >> _plusminus >> _process >> _theFFWVertex >> _wp >> _wm; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigMEqq2W2ff("Herwig::MEqq2W2ff", "HwMEHadron.so"); void MEqq2W2ff::Init() { static ClassDocumentation documentation ("The MEqq2W2ff class implements the matrix element for" "q qbar to Standard Model fermions via W exchange using helicity amplitude" "techniques"); static Parameter interfaceMaxFlavour ( "MaxFlavour", "The heaviest incoming quark flavour this matrix element is allowed to handle " "(if applicable).", &MEqq2W2ff::_maxflavour, 5, 0, 5, false, false, true); static Switch interfacePlusMinus ("Wcharge", "Which intermediate W bosons to include", &MEqq2W2ff::_plusminus, 0, false, false); static SwitchOption interfacePlusMinusAll (interfacePlusMinus, "Both", "Include W+ and W-", 0); static SwitchOption interfacePlusMinusPlus (interfacePlusMinus, "Plus", "Only include W+", 1); static SwitchOption interfacePlusMinusMinus (interfacePlusMinus, "Minus", "Only include W-", 2); static Switch interfaceProcess ("Process", "Which processes to include", &MEqq2W2ff::_process, 0, false, false); static SwitchOption interfaceProcessAll (interfaceProcess, "All", "Include all SM fermions as outgoing particles", 0); static SwitchOption interfaceProcessQuarks (interfaceProcess, "Quarks", "Only include outgoing quarks", 1); static SwitchOption interfaceProcessLeptons (interfaceProcess, "Leptons", "All include outgoing leptons", 2); static SwitchOption interfaceProcessElectron (interfaceProcess, "Electron", "Only include outgoing e nu_e", 3); static SwitchOption interfaceProcessMuon (interfaceProcess, "Muon", "Only include outgoing mu nu_mu", 4); static SwitchOption interfaceProcessTau (interfaceProcess, "Tau", "Only include outgoing tauu nu_tau", 5); static SwitchOption interfaceProcessUpDown (interfaceProcess, "UpDown", "Only include outgoing u dbar/ d ubar", 6); static SwitchOption interfaceProcessUpStrange (interfaceProcess, "UpStrange", "Only include outgoing u sbar/ s ubar", 7); static SwitchOption interfaceProcessUpBottom (interfaceProcess, "UpBottom", "Only include outgoing u bbar/ b ubar", 8); static SwitchOption interfaceProcessCharmDown (interfaceProcess, "CharmDown", "Only include outgoing c dbar/ d cbar", 9); static SwitchOption interfaceProcessCharmStrange (interfaceProcess, "CharmStrange", "Only include outgoing c sbar/ s cbar", 10); static SwitchOption interfaceProcessCharmBottom (interfaceProcess, "CharmBottom", "Only include outgoing c bbar/ b cbar", 11); } double MEqq2W2ff::qqbarME(vector & fin , vector & ain , vector & fout, vector & aout, bool calc) const { // matrix element to be stored ProductionMatrixElement newme(PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1Half,PDT::Spin1Half); // positive or negative W boson bool positive = mePartonData()[0]->iCharge() + mePartonData()[1]->iCharge() > 0; unsigned int ihel1,ihel2,ohel1,ohel2; // sum over helicities to get the matrix element double me = 0.; VectorWaveFunction inter; for(ihel1=0;ihel1<2;++ihel1) { for(ihel2=0;ihel2<2;++ihel2) { for(ohel1=0;ohel1<2;++ohel1) { for(ohel2=0;ohel2<2;++ohel2) { Complex diag = 0.0; if (positive) { // the Wp exchange inter = _theFFWVertex->evaluate(scale(),1,_wp,fin[ihel1],ain[ihel2]); diag = _theFFWVertex->evaluate(scale(),aout[ohel2],fout[ohel1],inter); } else { // the Wm exchange inter = _theFFWVertex->evaluate(scale(),1,_wm,fin[ihel1],ain[ihel2]); diag = _theFFWVertex->evaluate(scale(),aout[ohel2],fout[ohel1],inter); } // sum over helicities me += real(diag*conj(diag)); if(calc) newme(ihel1,ihel2,ohel1,ohel2) = diag; } } } } // results // spin and colour factor double colspin=1./12.; if(abs(fout[0].id())<=6) colspin*=3.; if(calc) _me.reset(newme); return me*colspin; } void MEqq2W2ff::constructVertex(tSubProPtr sub) { // extract the particles in the hard process ParticleVector hard; hard.push_back(sub->incoming().first);hard.push_back(sub->incoming().second); hard.push_back(sub->outgoing()[0]);hard.push_back(sub->outgoing()[1]); // order of particles unsigned int order[4]={0,1,2,3}; if(hard[0]->id()<0){order[0]=1;order[1]=0;} if(hard[2]->id()<0){order[2]=3;order[3]=2;} vector fin,aout; vector ain,fout; SpinorWaveFunction( fin ,hard[order[0]],incoming,false,true); SpinorBarWaveFunction(ain ,hard[order[1]],incoming,false,true); SpinorBarWaveFunction(fout,hard[order[2]],outgoing,true ,true); SpinorWaveFunction( aout,hard[order[3]],outgoing,true ,true); qqbarME(fin,ain,fout,aout,true); // construct the vertex HardVertexPtr hardvertex=new_ptr(HardVertex()); // set the matrix element for the vertex hardvertex->ME(_me); // set the pointers and to and from the vertex for(unsigned int ix=0;ix<4;++ix) hard[order[ix]]->spinInfo()->productionVertex(hardvertex); } diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/Makefile.am b/MatrixElement/Matchbox/Builtin/Amplitudes/Makefile.am --- a/MatrixElement/Matchbox/Builtin/Amplitudes/Makefile.am +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/Makefile.am @@ -1,72 +1,72 @@ pkglib_LTLIBRARIES = HwMatchboxBuiltin.la HwMatchboxBuiltin_la_LDFLAGS = \ -$(AM_LDFLAGS) -module -version-info 4:0:0 +$(AM_LDFLAGS) -module -version-info 4:1:0 nodist_HwMatchboxBuiltin_la_SOURCES = \ Amplitudes__all.cc BUILT_SOURCES = Amplitudes__all.cc CLEANFILES = Amplitudes__all.cc Amplitudes__all.cc : $(DIR_H_FILES) $(DIR_CC_FILES) Makefile @echo "Concatenating .cc files into $@" @$(top_srcdir)/cat_with_cpplines $(DIR_CC_FILES) > $@ EXTRA_DIST = $(ALL_H_FILES) $(ALL_CC_FILES) DIR_H_FILES = $(addprefix $(srcdir)/,$(ALL_H_FILES)) ALL_H_FILES = \ MatchboxCurrents.h \ MatchboxZGammaAmplitude.h \ MatchboxAmplitudellbarqqbargg.h \ MatchboxAmplitudellbarqqbarg.h \ MatchboxAmplitudellbarqqbar.h \ MatchboxAmplitudellbarqqbarqqbar.h \ MatchboxAmplitudelnuqqbargg.h \ MatchboxAmplitudelnuqqbarg.h \ MatchboxAmplitudelnuqqbar.h \ MatchboxAmplitudelnuqqbarqqbar.h \ MatchboxAmplitudehbbbarg.h \ MatchboxAmplitudehbbbar.h \ MatchboxAmplitudehggg.h \ MatchboxAmplitudehgg.h \ MatchboxAmplitudehqqbarg.h \ MatchboxAmplitudeqqbarttbar.h \ MatchboxAmplitudeqqbarttbarg.h \ MatchboxAmplitudeggttbar.h \ MatchboxAmplitudeggttbarg.h \ HelAmps_sm.h \ Parameters_sm.h \ MG_qqx2ttx.h \ MG_qqx2ttxg.h \ MG_gg2ttx.h \ MG_gg2ttxg.h DIR_CC_FILES = $(addprefix $(srcdir)/,$(ALL_CC_FILES)) ALL_CC_FILES = \ MatchboxCurrents.cc \ MatchboxZGammaAmplitude.cc \ MatchboxAmplitudellbarqqbar.cc \ MatchboxAmplitudellbarqqbarg.cc \ MatchboxAmplitudellbarqqbargg.cc \ MatchboxAmplitudellbarqqbarqqbar.cc \ MatchboxAmplitudelnuqqbar.cc \ MatchboxAmplitudelnuqqbarg.cc \ MatchboxAmplitudelnuqqbargg.cc \ MatchboxAmplitudelnuqqbarqqbar.cc \ MatchboxAmplitudehbbbar.cc \ MatchboxAmplitudehbbbarg.cc \ MatchboxAmplitudehgg.cc \ MatchboxAmplitudehggg.cc \ MatchboxAmplitudehqqbarg.cc \ MatchboxAmplitudeqqbarttbar.cc \ MatchboxAmplitudeqqbarttbarg.cc \ MatchboxAmplitudeggttbar.cc \ MatchboxAmplitudeggttbarg.cc \ HelAmps_sm.cc \ Parameters_sm.cc \ MG_qqx2ttx.cc \ MG_qqx2ttxg.cc \ MG_gg2ttx.cc \ MG_gg2ttxg.cc diff --git a/MatrixElement/Matchbox/External/GoSam/GoSamAmplitude.cc b/MatrixElement/Matchbox/External/GoSam/GoSamAmplitude.cc --- a/MatrixElement/Matchbox/External/GoSam/GoSamAmplitude.cc +++ b/MatrixElement/Matchbox/External/GoSam/GoSamAmplitude.cc @@ -1,1063 +1,1069 @@ // -*- C++ -*- // // GoSamAmplitude.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 GoSamAmplitude class. // #include "GoSamAmplitude.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Command.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Utilities/StringUtils.h" #include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h" #include "Herwig/API/Filesystem.h" #include #include #include #include #include namespace bfs = Herwig::filesystem; using namespace Herwig; #ifndef HERWIG_BINDIR #error Makefile.am needs to define HERWIG_BINDIR #endif #ifndef HERWIG_PKGDATADIR #error Makefile.am needs to define HERWIG_PKGDATADIR #endif #ifndef GOSAM_PREFIX #error Makefile.am needs to define GOSAM_PREFIX #endif //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// GoSamAmplitude::GoSamAmplitude() : theAccuracyTarget(6),theCodeExists(false),theFormOpt(true),theNinja(true), theHiggsEff(false),theMassiveLeptons(false),theLoopInducedOption(0), isitDR(false),doneGoSamInit(false),doneGoSamInitRun(false), bindir_(HERWIG_BINDIR), pkgdatadir_(HERWIG_PKGDATADIR), GoSamPrefix_(GOSAM_PREFIX) {} GoSamAmplitude::~GoSamAmplitude() {} IBPtr GoSamAmplitude::clone() const { return new_ptr(*this); } IBPtr GoSamAmplitude::fullclone() const { return new_ptr(*this); } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// void GoSamAmplitude::doinit() { optionalContractFile() = name() + ".OLPContract.lh"; MatchboxOLPME::doinit(); doneGoSamInit = true; } void GoSamAmplitude::doinitrun() { optionalContractFile() = name() + ".OLPContract.lh"; MatchboxOLPME::doinitrun(); doneGoSamInitRun = true; } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// extern "C" void OLP_Start(const char*, int* i); extern "C" void OLP_Polvec(double*, double*, double*); extern "C" void OLP_SetParameter(char*, double*, double*, int*); extern "C" void OLP_PrintParameter(char*); extern "C" void OLP_EvalSubProcess2(int*, double*, double*, double*, double*); //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// bool GoSamAmplitude::startOLP(const map, int>& procs) { char char_cwd[256]; getcwd(char_cwd, sizeof(char_cwd)); string cwd = string(char_cwd); string folderMatchboxBuild = factory()->buildStorage(); folderMatchboxBuild.erase(folderMatchboxBuild.begin()); // set all necessary path and file names gosamPath = gosamPathInterface == "" ? cwd + folderMatchboxBuild + "GoSam" : gosamPathInterface; // When transitioning to C++ 11 this length()-1 workaround can be replaced by string.back() if (gosamPath.at(gosamPath.length()-1) != '/') gosamPath.append("/"); gosamSourcePath = gosamPath + "source/"; gosamInstallPath = gosamPath + "build/"; // create all the directories if (!bfs::is_directory(gosamPath)){ try { bfs::create_directory(gosamPath); } catch (exception& e) { throw Exception() << "--------------------------------------------------------------------------------\n" << "The following exception occured:\n\n" << " " << e.what() << "\n\n" << " -> Please create the parent directory of\n" << " " << gosamPath << "\n" << " manually!\n" << "--------------------------------------------------------------------------------\n" << Exception::runerror; } } if (!bfs::is_directory(gosamSourcePath)) bfs::create_directory(gosamSourcePath); if (!bfs::is_directory(gosamInstallPath)) bfs::create_directory(gosamInstallPath); contractFileTitle = name() + ".OLPContract.lh"; contractFileName = gosamPath + "/" + contractFileTitle; string orderFileName = gosamPath + "/" + name() + ".OLPOrder.lh"; // Set the path variable (plus file name) where to find the GoSam specific input file gosamSetupInFileName = gosamSetupInFileNameInterface == "" ? gosamPath + "/setup.gosam.in" : gosamSetupInFileNameInterface; // Use the python script gosam2herwig to make replacements in the GoSam // specific input file at gosamSetupInFileName. If the GoSam input file // does not exist yet at gosamSetupInFileName the python script will get // it from src/defaults/ before making the replacements. string cmd = "python "+bindir_+"/gosam2herwig "; cmd+=" --usrinfile="+gosamSetupInFileNameInterface; cmd+=" --infile="+gosamSetupInFileName+".tbu"; cmd+=" --definfile="+pkgdatadir_+"/defaults/setup.gosam.in"; cmd+=" --formtempdir="+StringUtils::replace(gosamSourcePath, string("/"), string("\\/")); //@FORMTEMPDIR@ cmd+=" --reduction="+(theNinja ? string("ninja,golem95") : string("samurai,golem95")); //@REDUCTIONPROGRAMS@ cmd+=" --formopt="+(theFormOpt ? string("") : string(", noformopt")); //@FORMOPT@ cmd+=" --higgseff="+(theHiggsEff ? string("smehc") : string("smdiag")); //@MODEL@ std::system(cmd.c_str()); if ( factory()->initVerbose() ) { generator()->log() << "\n\n>>> NOTE: According to the repository settings for the GoSam interface:\n" << flush; if (theHiggsEff) generator()->log() << "\n -- GoSam will use a model with an effective ggH coupling (model=smehc).\n" << flush; else if (!theHiggsEff) generator()->log() << "\n -- GoSam will use its default model (model=smdiag).\n" << flush; if (theNinja) generator()->log() << " -- GoSam will use Ninja as reduction program (reduction_programs=ninja,golem95).\n" << flush; else if (!theNinja) generator()->log() << " -- GoSam will use Samurai as reduction program (reduction_programs=samurai,golem95).\n" << flush; if (theFormOpt) generator()->log() << " -- Form optimization switched on (extensions=autotools).\n" << flush; else if (!theFormOpt) generator()->log() << " -- Form optimization switched off (extensions=autotools, noformopt).\n" << flush; if (theNinja && !theFormOpt) throw Exception() << "GoSamAmplitude: Ninja reduction needs form optimization!\n" << Exception::runerror; if (gosamSetupInFileNameInterface == "") { generator()->log() << "\n Please be aware that you are using a copy of the default GoSam input file!\n" << " Please note that if you need special options to be considered for the specific\n" << " process you are looking at (diagram filtering, etc.) these are not automatically\n" << " set for you. In that case please consider to specify your own GoSam input file\n" << " via 'set " << name() << ":SetupInFilename' in the input file.\n\n" << flush; } // If one uses a custom GoSam input file at gosamSetupInFileName = gosamSetupInFileNameInterface // then please note that not all options in there might match the corresponding Herwig repository // options if (gosamSetupInFileNameInterface != "") { generator()->log() << "\n Please be aware that you are using a custom GoSam input file!\n" << " Please note that if you have set the options for model, reduction_programs,\n" << " extensions and/or form.tempdir manually these will of course not be replaced\n" << " by the corresponding repository settings mentioned above.\n\n" << flush; } generator()->log() << "\n>>> NOTE: GoSam may return the set of used parameters for this process via the OLP_PrintParameter() function:\n\n" << " -- If Debug::level > 1, the OLP parameters are being written to file: at " << factory()->runStorage() + name() + ".OLPParameters.lh.\n\n" << flush; } double accuracyTarget = 1.0/pow(10.0,accuracyTargetNegExp()); time_t rawtime; time (&rawtime); accuracyFileTitle = name() + ".OLPAccuracy.lh"; accuracyFile = factory()->buildStorage() + accuracyFileTitle; ofstream accuracyFileStream; if ( Debug::level > 1 ) { accuracyFileStream.open(accuracyFile.c_str()); // Opening accuracyFile once here removes all previous content before the read step accuracyFileStream << "\nFile to contain those PSPs for which GoSam evaluated one-loop interference terms or loop induced ME2s\n" << "with acc > target accuracy = " << accuracyTarget << ". Date/Time: " << ctime(&rawtime) << endl; } if ( factory()->initVerbose() ) { generator()->log() << "\n>>> NOTE: GoSam will return the accuracy of one-loop interference terms or loop induced ME2s\n" << " at every PSP via the BLHA2 acc parameter:\n\n" << " -- In cases where acc > 10^-AccuracyTarget = " << accuracyTarget << " the corresponding PSPs are being dis-\n" << " carded.\n" << " -- The default value for AccuracyTarget is 6, but you may consider setting it otherwise\n" << " via 'set " << name() << ":AccuracyTarget' in the input file.\n" << " -- Currently the value for AccuracyTarget is set to " << accuracyTargetNegExp() << ".\n" << " -- If Debug::level > 1, the discarded PSPs are being written to file: at " + accuracyFile << ".\n" << " -- If the amount of PSPs with acc > " << accuracyTarget << " is significant, please consider to re-evaluate\n" << " your process setup (accuracy target, masses, cuts, etc.)!\n\n\n" << flush; } // check for old order file and create it if it doesn't already exist fillOrderFile(procs, orderFileName); ifstream ifile(contractFileName.c_str()); if(!ifile){ signOLP(orderFileName, contractFileName); } if ( !checkOLPContract(contractFileName) ) { throw Exception() << "GoSamAmplitude: failed to start GoSam" << Exception::runerror; } if (!( DynamicLoader::load(gosamInstallPath+"/lib/libgolem_olp.so") || DynamicLoader::load(gosamInstallPath+"/lib64/libgolem_olp.so") || DynamicLoader::load(gosamInstallPath+"/lib/libgolem_olp.dylib") || DynamicLoader::load(gosamInstallPath+"/lib64/libgolem_olp.dylib"))) buildGoSam(); int status = -1; startOLP(contractFileTitle, status); if ( status != 1 ) return false; return true; } void GoSamAmplitude::startOLP(const string& contract, int& status) { string tempcontract = contract; char char_cwd[256]; getcwd(char_cwd, sizeof(char_cwd)); string cwd = string(char_cwd); string folderMatchboxBuild = factory()->buildStorage(); folderMatchboxBuild.erase(folderMatchboxBuild.begin()); gosamPath = gosamPathInterface == "" ? cwd + folderMatchboxBuild + "GoSam" : gosamPathInterface; // When transitioning to C++ 11 this length()-1 workaround can be replaced by string.back() if (gosamPath.at(gosamPath.length()-1) != '/') gosamPath.append("/"); if (!( DynamicLoader::load(gosamPath+"build/lib/libgolem_olp.so") || DynamicLoader::load(gosamPath+"build/lib64/libgolem_olp.so") || DynamicLoader::load(gosamPath+"build/lib/libgolem_olp.dylib") || DynamicLoader::load(gosamPath+"build/lib64/libgolem_olp.dylib"))) throw Exception() << "GoSamAmplitude: Failed to load GoSam. Please check the log file.\n" << Exception::runerror; tempcontract = gosamPath + tempcontract; OLP_Start(tempcontract.c_str(), &status); // hand over input parameters for EW scheme considered int pStatus = 0; double zero = 0.0; if ( SM().ewScheme() == 0 || SM().ewScheme() == 6 ) { // EW/Scheme Default and EW/Scheme Independent throw Exception() << "GoSamAmplitude: `Best value' schemes are not supported by GoSam" << Exception::runerror; } else if ( SM().ewScheme() == 4 ) { // EW/Scheme mW (uses mW,GF,sin2thetaW) seems not to be supported by GoSam throw Exception() << "GoSamAmplitude: `mW' scheme is not supported by GoSam" << Exception::runerror; } else if ( SM().ewScheme() == 1 ) { // EW/Scheme GMuScheme (uses mW,mZ,GF) double in1=getParticleData(ParticleID::Z0)->hardProcessMass()/GeV; double in2=getParticleData(ParticleID::Wplus)->hardProcessMass()/GeV; double in3=SM().fermiConstant()*GeV2; OLP_SetParameter((char *)"mass(23)",&in1,&zero,&pStatus); OLP_SetParameter((char *)"mass(24)",&in2,&zero,&pStatus); OLP_SetParameter((char *)"Gf",&in3,&zero,&pStatus); } else if ( SM().ewScheme() == 2 ) { // EW/Scheme alphaMZScheme (uses mW,mZ,alpha(mZ)) double in1=getParticleData(ParticleID::Z0)->hardProcessMass()/GeV; double in2=getParticleData(ParticleID::Wplus)->hardProcessMass()/GeV; double in3=SM().alphaEMMZ(); OLP_SetParameter((char *)"mass(23)",&in1,&zero,&pStatus); OLP_SetParameter((char *)"mass(24)",&in2,&zero,&pStatus); OLP_SetParameter((char *)"alpha",&in3,&zero,&pStatus); } else if ( SM().ewScheme() == 3 ) { // EW/Scheme NoMass (uses alpha(mZ),GF,sin2thetaW) double in1=SM().fermiConstant()*GeV2; double in2=SM().alphaEMMZ(); double in3=SM().sin2ThetaW(); OLP_SetParameter((char *)"Gf",&in1,&zero,&pStatus); OLP_SetParameter((char *)"alpha",&in2,&zero,&pStatus); OLP_SetParameter((char *)"sw2",&in3,&zero,&pStatus); } else if ( SM().ewScheme() == 5 ) { // EW/Scheme mZ (uses mZ,alphaEM,sin2thetaW) double in1=getParticleData(ParticleID::Z0)->hardProcessMass()/GeV; double in2=SM().alphaEMMZ(); double in3=SM().sin2ThetaW(); OLP_SetParameter((char *)"mass(23)",&in1,&zero,&pStatus); OLP_SetParameter((char *)"alpha",&in2,&zero,&pStatus); OLP_SetParameter((char *)"sw2",&in3,&zero,&pStatus); } else if ( SM().ewScheme() == 7 ) { // EW/Scheme FeynRulesUFO (uses mZ,GF,alpha(mZ)) double in1=getParticleData(ParticleID::Z0)->hardProcessMass()/GeV; double in2=SM().alphaEMMZ(); double in3=SM().fermiConstant()*GeV2; OLP_SetParameter((char *)"mass(23)",&in1,&zero,&pStatus); OLP_SetParameter((char *)"alpha",&in2,&zero,&pStatus); OLP_SetParameter((char *)"Gf",&in3,&zero,&pStatus); } + // hand over widths of Z and W + double wZ = getParticleData(23)->hardProcessWidth()/GeV; + double wW = getParticleData(24)->hardProcessWidth()/GeV; + OLP_SetParameter((char*)"width(23)",&wZ,&zero,&pStatus); + OLP_SetParameter((char*)"width(24)",&wW,&zero,&pStatus); + // hand over mass and width of the Higgs double wH = getParticleData(25)->hardProcessWidth()/GeV; double mH = getParticleData(25)->hardProcessMass()/GeV; OLP_SetParameter((char*)"width(25)",&wH,&zero,&pStatus); OLP_SetParameter((char*)"mass(25)",&mH,&zero,&pStatus); // hand over initial input parameter for alphaS double as = SM().alphaS(); OLP_SetParameter((char *)"alphaS", &as, &zero, &pStatus); // fill massive Particle vector if (massiveParticles.empty()) { // with quark masses for (int i=1; i<=6; ++i) if (getParticleData(i)->hardProcessMass()/GeV > 0.0) massiveParticles.push_back(i); // with lepton masses if (theMassiveLeptons && getParticleData(11)->hardProcessMass()/GeV > 0.0) massiveParticles.push_back(11); if (theMassiveLeptons && getParticleData(13)->hardProcessMass()/GeV > 0.0) massiveParticles.push_back(13); if (theMassiveLeptons && getParticleData(15)->hardProcessMass()/GeV > 0.0) massiveParticles.push_back(15); } // hand over quark (and possibly lepton) masses and widths (iff massive) if ( massiveParticles.size() != 0 ) { for ( vector::const_iterator mID = massiveParticles.begin(); mID != massiveParticles.end(); ++mID ) { string mstr; string wstr; int mInt = *mID; double mass=getParticleData(mInt)->hardProcessMass()/GeV; double width=getParticleData(mInt)->hardProcessWidth()/GeV; std::stringstream ss; ss << mInt; string str = ss.str(); mstr="mass("+str+")"; wstr="width("+str+")"; char * mchar = new char[mstr.size()+1]; char * wchar = new char[wstr.size()+1]; std::copy(mstr.begin(),mstr.end(),mchar); std::copy(wstr.begin(),wstr.end(),wchar); mchar[mstr.size()] = '\0'; wchar[wstr.size()] = '\0'; OLP_SetParameter( mchar, &mass, &zero, &pStatus ); OLP_SetParameter( wchar, &width, &zero, &pStatus ); delete[] mchar; delete[] wchar; // Nicer but not working properly: // double mass=getParticleData(*mID)->hardProcessMass()/GeV; // double width=getParticleData(*mID)->hardProcessWidth()/GeV; // string mstr="mass("+static_cast(&(ostringstream()<<(*mID)))->str()+")"; // string wstr="width("+static_cast(&(ostringstream()<<(*mID)))->str()+")"; // cout<<"\n massiv "< 1 ) { string ppstr = factory()->runStorage() + name() + ".OLPParameters.lh"; OLP_PrintParameter(const_cast(ppstr.c_str())); } didStartOLP() = true; } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// void GoSamAmplitude::fillOrderFile(const map, int>& procs, string orderFileName) { for ( map, int>::const_iterator p = procs.begin() ; p != procs.end() ; ++p ) { std::stringstream Processstr; std::stringstream Typestr; Processstr << (*p).first.first.legs[0]->id() << " " << (*p).first.first.legs[1]->id() << " -> "; for ( PDVector::const_iterator o = (*p).first.first.legs.begin() + 2 ; o != (*p).first.first.legs.end() ; ++o ) Processstr << (**o).id() << " "; if ( (*p).first.second == ProcessType::treeME2 ) { Typestr << "Tree"; } else if ( (*p).first.second == ProcessType::loopInducedME2 ) { Typestr << "LoopInduced"; } else if ( (*p).first.second == ProcessType::colourCorrelatedME2 ) { Typestr << "ccTree"; } else if ( (*p).first.second == ProcessType::spinColourCorrelatedME2 ) { Typestr << "scTree"; } else if ( (*p).first.second == ProcessType::oneLoopInterference ) { Typestr << "Loop"; } gosamprocinfo pro = gosamprocinfo((*p).second, -1, Processstr.str(), Typestr.str()); pro.setOAs(p->first.first.orderInAlphaS); pro.setOAew(p->first.first.orderInAlphaEW); processmap[(*p).second] = pro; } ifstream oldOrderFileStream(orderFileName.c_str()); if (oldOrderFileStream){ oldOrderFileStream.close(); return; } ofstream orderFile(orderFileName.c_str()); int asPower = 100; int minlegs = 100; int maxlegs = -1; int maxasPower = -1; int aewPower = 100; int maxaewPower = -1; for ( map, int>::const_iterator t = procs.begin() ; t != procs.end() ; ++t ) { asPower = min(asPower, static_cast(t->first.first.orderInAlphaS)); minlegs = min(minlegs, static_cast(t->first.first.legs.size())); maxlegs = max(maxlegs, static_cast(t->first.first.legs.size())); maxasPower = max(maxasPower, static_cast(t->first.first.orderInAlphaS)); aewPower = min(aewPower, static_cast(t->first.first.orderInAlphaEW)); maxaewPower = max(maxaewPower, static_cast(t->first.first.orderInAlphaEW)); } orderFile << "# OLP order file created by Herwig/Matchbox for GoSam\n\n"; orderFile << "InterfaceVersion BLHA2\n"; orderFile << "MatrixElementSquareType CHsummed\n"; orderFile << "CorrectionType QCD\n"; orderFile << "IRregularisation " << (isDR() ? "DRED" : "CDR") << "\n"; // loop over quarks to check if they have non-zero masses for (int i=1; i<=6; ++i) if (getParticleData(i)->hardProcessMass()/GeV > 0.0) massiveParticles.push_back(i); // check if leptons have non-zero masses (iff theMassiveLeptons==true) if (theMassiveLeptons && getParticleData(11)->hardProcessMass()/GeV > 0.0) massiveParticles.push_back(11); if (theMassiveLeptons && getParticleData(13)->hardProcessMass()/GeV > 0.0) massiveParticles.push_back(13); if (theMassiveLeptons && getParticleData(15)->hardProcessMass()/GeV > 0.0) massiveParticles.push_back(15); if ( massiveParticles.size() != 0 ) { orderFile << "MassiveParticles "; for ( vector::const_iterator mID = massiveParticles.begin(); mID != massiveParticles.end(); ++mID ) { int mInt = *mID; orderFile << mInt << " "; } orderFile << "\n"; } orderFile << "\n"; vector < string > types; types.push_back("Tree"); types.push_back("LoopInduced"); types.push_back("ccTree"); types.push_back("scTree"); types.push_back("Loop"); for ( int i = asPower ; i != maxasPower + 1 ; i++ ) { for ( int j = aewPower ; j != maxaewPower + 1 ; j++ ) { orderFile << "\nAlphasPower " << i << "\n"; orderFile << "AlphaPower " << j << "\n"; for ( vector::iterator it = types.begin() ; it != types.end() ; it++ ) { if ( *it == "LoopInduced" ) continue; for ( map::iterator p = processmap.begin() ; p != processmap.end() ; ++p ) if ( (*p).second.Tstr() == *it && i == (*p).second.orderAs() && j == (*p).second.orderAew() ) { orderFile << "\nAmplitudeType " << *it << "\n"; break; } for ( map::iterator p = processmap.begin() ; p != processmap.end() ; ++p ) if ( (*p).second.Tstr() == *it && i == (*p).second.orderAs() && j == (*p).second.orderAew() ) { orderFile << (*p).second.Pstr() << "\n"; } } } } // Write out the loop induced processes separately int asPowerLI = 100; int aewPowerLI = 100; for ( map::iterator p = processmap.begin() ; p != processmap.end() ; ++p ) { if ( (*p).second.Tstr() != "LoopInduced" ) continue; if ( (*p).second.orderAs() != asPowerLI || (*p).second.orderAew() != aewPowerLI ) { asPowerLI = (*p).second.orderAs(); aewPowerLI = (*p).second.orderAew(); // At the moment GoSam requires for qcd loop induced processes the as coupling power // which would correspond to an associated fictitious Born process orderFile << "\nAlphasPower " << (asPowerLI-2) << "\n"; orderFile << "AlphaPower " << aewPowerLI << "\n"; orderFile << "\nAmplitudeType " << "LoopInduced" << "\n"; } orderFile << (*p).second.Pstr() << "\n"; } orderFile << flush; } void GoSamAmplitude::signOLP(const string& order, const string& contract) { if(!theCodeExists){ char char_cwd[256]; getcwd(char_cwd, sizeof(char_cwd)); string cwd = string(char_cwd); string folderMatchboxBuild = factory()->buildStorage(); folderMatchboxBuild.erase(folderMatchboxBuild.begin()); generator()->log() << "\n>>> generating GoSam amplitudes. This may take some time, please be patient.\n" << ">>> see " + cwd + folderMatchboxBuild + "gosam-amplitudes.log for details.\n" << flush; string cmd = GoSamPrefix_+"/bin/gosam.py --olp --output-file=" + contract + " --config=" + gosamSetupInFileName+".tbu" + " --destination=" + gosamSourcePath + " " + order + " > " + cwd + folderMatchboxBuild + "gosam-amplitudes.log 2>&1"; std::system(cmd.c_str()); cmd = "python "+bindir_+"/gosam2herwig "; cmd += " --makelink "; // cmd += " --makelinkfrom=contract "; cmd += " --makelinkfrom="+gosamPath+"/"+name()+".OLPContract.lh"; cmd += " --makelinkto="+factory()->buildStorage() + name() + ".OLPContract.lh"; std::system(cmd.c_str()); } } bool GoSamAmplitude::checkOLPContract(string contractFileName) { ifstream infile(contractFileName.c_str()); string line; vector < string > contractfile; while (std::getline(infile, line)) contractfile.push_back(line); for ( map::iterator p = processmap.begin() ; p != processmap.end() ; p++ ) { bool righttype = false; for ( vector::iterator linex = contractfile.begin() ; linex != contractfile.end() ; ++linex ) { if ( (*linex).find("AmplitudeType ")!= std::string::npos ) { if ( (*linex).find(" " + (*p).second.Tstr() + " ")!= std::string::npos ) { righttype = true; } else { righttype = false; } } if ( righttype ) { if ( (*linex).find((*p).second.Pstr()) != std::string::npos && (*p).second.Pstr().length() == (*linex).find("|") ) { string sub = (*linex).substr((*linex).find("|") + 1, (*linex).find("#") - (*linex).find("|") - 1); // | 1 23 # buggy?? if ( sub.find(" 1 ") != 0 ) throw Exception() << "GoSamAmplitude: Failed to check contractfile. Please check the logfile.\n" << Exception::runerror; string subx = sub.substr(3); int subint; istringstream(subx) >> subint; (*p).second.setGID(subint); } } } } string ids = factory()->buildStorage() + "GoSam.ids.dat"; ofstream IDS(ids.c_str()); idpair.clear(); for ( map::iterator p = processmap.begin() ; p != processmap.end() ; p++ ) idpair.push_back(-1); idpair.push_back(-1); for ( map::iterator p = processmap.begin() ; p != processmap.end() ; p++ ) { idpair[(*p).second.HID()]=(*p).second.GID(); IDS << (*p).second.HID() << " " << (*p).second.GID() << " " << (*p).second.Tstr() << "\n"; if ( (*p).second.GID() == -1 ) return 0; } IDS << flush; return 1; } bool GoSamAmplitude::buildGoSam() { if(!theCodeExists){ generator()->log() << "\n>>> compiling GoSam amplitudes. This may take some time, please be patient.\n" << ">>> see " + gosamSourcePath + "gosam-build.log for details.\n\n" << flush; string cmd = "cd " + gosamSourcePath + " && sh autogen.sh FCFLAGS=-g --prefix=" + gosamInstallPath + " --disable-static > gosam-build.log 2>&1"; std::system(cmd.c_str()); if (!gosamBuildScript.empty()) { cmd = "cd " + gosamSourcePath + " && " + gosamBuildScript + " >> gosam-build.log 2>&1"; std::system(cmd.c_str()); } std::system(cmd.c_str()); cmd = "cd " + gosamSourcePath + " && make install >> gosam-build.log 2>&1"; std::system(cmd.c_str()); } theCodeExists=true; return 1; } void GoSamAmplitude::getids() const { string line = factory()->buildStorage() + "GoSam.ids.dat"; ifstream infile(line.c_str()); int hid; int gid; string type; while (std::getline(infile, line)) { idpair.push_back(-1); idtypepair.push_back(" "); } infile.close(); string line2 = factory()->buildStorage() + "GoSam.ids.dat"; ifstream infile2(line2.c_str()); idpair.push_back(-1); idtypepair.push_back(" "); while (std::getline(infile2, line2)) { istringstream(line2) >> hid >> gid >> type; idpair[hid]=gid; idtypepair[hid]=type; } infile.close(); } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// void GoSamAmplitude::evalSubProcess() const { useMe(); double units = pow(lastSHat() / GeV2, int(mePartonData().size()) - 4.); fillOLPMomenta(lastXComb().meMomenta(),mePartonData(),reshuffleMasses()); double scale = sqrt(mu2() / GeV2); if (hasRunningAlphaS()) { int pStatus = 0; double zero = 0.0; double as; as = lastAlphaS(); OLP_SetParameter((char *)"alphaS", &as, &zero, &pStatus); } double out[7] = { }; double acc; if ( idpair.size() == 0 ){ getids(); } int id = -99; if ( olpId()[ProcessType::loopInducedME2] ) id = olpId()[ProcessType::loopInducedME2]; else if ( olpId()[ProcessType::oneLoopInterference] ) id = olpId()[ProcessType::oneLoopInterference]; else id = olpId()[ProcessType::treeME2]; int callid(idpair[id]); // If id denotes the Herwig ID, this returns the GoSam ID string calltype(idtypepair[id]); // If id denotes the Herwig ID, this returns the amplitude type OLP_EvalSubProcess2(&(callid), olpMomenta(), &scale, out, &acc); double accuracyTarget = 1.0/pow(10.0,accuracyTargetNegExp()); accuracyFileTitle = name() + ".OLPAccuracy.lh"; accuracyFile = factory()->buildStorage() + accuracyFileTitle; ofstream accuracyFileStream; if ( (olpId()[ProcessType::oneLoopInterference]||olpId()[ProcessType::loopInducedME2]) && acc > accuracyTarget ) { if ( Debug::level > 1 ) { accuracyFileStream.open(accuracyFile.c_str(),ios::app); vector currentpsp = lastXComb().meMomenta(); time_t rawtime; time (&rawtime); if (doneGoSamInit) accuracyFileStream << "READ phase: "; else if (doneGoSamInitRun) accuracyFileStream << "RUN phase: "; accuracyFileStream << "Sub-process with Herwig ID = " << id << " and GoSam ID = " << callid << ", " << ctime(&rawtime); accuracyFileStream << "GoSam evaluated one-loop interference or loop induced ME2 with acc = " << acc << " > target accuracy = " << accuracyTarget << ", at PSP [in units of GeV]:" << endl; for (size_t i=0; i!=currentpsp.size(); ++i) { accuracyFileStream << "(t,x,y,z,mass;m)[" << i << "]=(" << currentpsp[i].t()/GeV << "," << currentpsp[i].x()/GeV << "," << currentpsp[i].y()/GeV << "," << currentpsp[i].z()/GeV << "," << currentpsp[i].mass()/GeV << ";" << currentpsp[i].m()/GeV << ")" << endl; } accuracyFileStream << endl; } throw Veto(); // Dispose of PSP } if ( olpId()[ProcessType::oneLoopInterference] ) { if (calculateTreeME2()) lastTreeME2(out[3] * units); lastOneLoopInterference((out[2])* units); lastOneLoopPoles(pair(out[0] * units, out[1] * units)); } else if ( olpId()[ProcessType::treeME2] ) { lastTreeME2(out[3] * units); } else if ( olpId()[ProcessType::loopInducedME2] ) { lastTreeME2(out[2] * units); } } void GoSamAmplitude::evalColourCorrelator(pair ) const { double units = pow(lastSHat() / GeV2, int(mePartonData().size()) - 4.); fillOLPMomenta(lastXComb().meMomenta(),mePartonData(),reshuffleMasses()); double scale = sqrt(mu2() / GeV2); if (hasRunningAlphaS()) { int pStatus = 0; double zero = 0.0; double as; as = lastAlphaS(); OLP_SetParameter((char *)"alphaS", &as, &zero, &pStatus); } int n = lastXComb().meMomenta().size(); colourCorrelatorResults.resize(n * (n - 1) / 2); if ( idpair.size() == 0 ) getids(); int callid(idpair[olpId()[ProcessType::colourCorrelatedME2]]); double acc; OLP_EvalSubProcess2(&(callid), olpMomenta(), &scale, &colourCorrelatorResults[0], &acc); cPDVector particles = lastXComb().matrixElement()->mePartonData(); for ( int i = 0 ; i < n ; ++i ) { for ( int j = i + 1 ; j < n ; ++j ) { lastColourCorrelator(make_pair(i, j), colourCorrelatorResults[i+j*(j-1)/2] * units); } } } void GoSamAmplitude::evalSpinColourCorrelator(pair ) const { double units = pow(lastSHat() / GeV2, int(mePartonData().size()) - 4.); fillOLPMomenta(lastXComb().meMomenta(),mePartonData(),reshuffleMasses()); double scale = sqrt(mu2() / GeV2); if (hasRunningAlphaS()) { int pStatus = 0; double zero = 0.0; double as; as = lastAlphaS(); OLP_SetParameter((char *)"alphaS", &as, &zero, &pStatus); } int n = lastXComb().meMomenta().size(); spinColourCorrelatorResults.resize(2*n*n); if ( idpair.size() == 0 ) getids(); double acc; int callid(idpair[olpId()[ProcessType::spinColourCorrelatedME2]]); OLP_EvalSubProcess2(&(callid), olpMomenta(), &scale, &spinColourCorrelatorResults[0], &acc); for ( int i = 0; i < n; ++i ) { for ( int j = 0; j < n; ++j ) { Complex scc(spinColourCorrelatorResults[2*i+2*n*j]*units, spinColourCorrelatorResults[2*i+2*n*j+1]*units); lastColourSpinCorrelator(make_pair(i,j),scc); } } } LorentzVector GoSamAmplitude::plusPolarization(const Lorentz5Momentum& p, const Lorentz5Momentum& n, int inc) const { double pvec[4] = {p.t()/GeV,p.x()/GeV,p.y()/GeV,p.z()/GeV}; double nvec[4] = {n.t()/GeV,n.x()/GeV,n.y()/GeV,n.z()/GeV}; double out[8] ={ }; OLP_Polvec(pvec,nvec,out); LorentzVector res; Complex a(out[0],out[1]); res.setT(a); Complex b(out[2],out[3]); res.setX(b); Complex c(out[4],out[5]); res.setY(c); Complex d(out[6],out[7]); res.setZ(d); if (inc<2) return res.conjugate(); else return res; } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void GoSamAmplitude::persistentOutput(PersistentOStream & os) const { os << idpair << idtypepair << processmap << gosamPathInterface << gosamSetupInFileNameInterface << gosamBuildScript << gosamPath << gosamSourcePath << gosamInstallPath << gosamSetupInFileName << orderFileTitle << contractFileTitle << contractFileName << orderFileName << theCodeExists << theFormOpt << theNinja << isitDR << massiveParticles << theHiggsEff << theAccuracyTarget << theMassiveLeptons << theLoopInducedOption << doneGoSamInit << doneGoSamInitRun << bindir_ << pkgdatadir_ << GoSamPrefix_; } void GoSamAmplitude::persistentInput(PersistentIStream & is, int) { is >> idpair >> idtypepair >> processmap >> gosamPathInterface >> gosamSetupInFileNameInterface >> gosamBuildScript >> gosamPath >> gosamSourcePath >> gosamInstallPath >> gosamSetupInFileName >> orderFileTitle >> contractFileTitle >> contractFileName >> orderFileName >> theCodeExists >> theFormOpt >> theNinja >> isitDR >> massiveParticles >> theHiggsEff >> theAccuracyTarget >> theMassiveLeptons >> theLoopInducedOption >> doneGoSamInit >> doneGoSamInitRun >> bindir_ >> pkgdatadir_ >> GoSamPrefix_; } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct (the class and its base class), and that the constructor // arguments are correct (the class name and the name of the dynamically // loadable library where the class implementation can be found). DescribeClass describeHerwigGoSamAmplitude("Herwig::GoSamAmplitude", "HwMatchboxGoSam.so"); void GoSamAmplitude::Init() { static ClassDocumentation documentation("GoSamAmplitude implements an interface to GoSam.", "Matrix elements have been calculated using GoSam \\cite{Cullen:2011xs}, \\cite{Cullen:2014yla}", "%\\cite{Cullen:2011xs}\n" "\\bibitem{Cullen:2011xs}\n" "G.~Cullen et al.,\n" "``GoSam: A Program for Automated One-Loop Calculations,''\n" "arXiv:1111.6534 [hep-ph].\n" "%%CITATION = ARXIV:1111.6534;%%\n" "%\\cite{Cullen:2014yla}\n" "\\bibitem{Cullen:2014yla}\n" "G.~Cullen et al.,\n" "``GoSaam-2.0: a tool for automated one-loop calculations within the Standard Model and beyond,''\n" "arXiv:1404.7096 [hep-ph].\n" "%%CITATION = ARXIV:1404.7096;%%"); static Parameter interfaceProcessPath ("ProcessPath", "Prefix for the process source code, include files and library produced by GoSam.", &GoSamAmplitude::gosamPathInterface, "", false, false); static Parameter interfaceSetupInFilename ("SetupInFilename", "File name of the GoSam infile (typically setup.gosam.in) to be used. If left empty a new setup.gosam.in is created in the location specified in Path", &GoSamAmplitude::gosamSetupInFileNameInterface, "", false, false); static Switch interfaceCodeExists ("CodeExists", "Switch on or off if Code already exists/not exists.", &GoSamAmplitude::theCodeExists, true, false, false); static SwitchOption interfaceCodeExistsYes (interfaceCodeExists, "Yes", "Switch True if Code already exists.", true); static SwitchOption interfaceCodeExistsNo (interfaceCodeExists, "No", "Switch False if Code has to be build.", false); static Switch interfaceisitDR ("isDR", "Switch on or off DR.", &GoSamAmplitude::isitDR, false, false, false); static SwitchOption interfaceisitDRYes (interfaceisitDR, "Yes", "Switch True.", true); static SwitchOption interfaceisitDRNo (interfaceisitDR, "No", "Switch False.", false); static Switch interfaceFormOpt ("FormOpt", "Switch On/Off formopt", &GoSamAmplitude::theFormOpt, true, false, false); static SwitchOption interfaceFormOptYes (interfaceFormOpt, "Yes", "Yes", true); static SwitchOption interfaceFormOptNo (interfaceFormOpt, "No", "No", false); static Switch interfaceNinja ("Ninja", "Switch On/Off for reduction with Ninja. If Off then Samurai is used.", &GoSamAmplitude::theNinja, true, false, false); static SwitchOption interfaceNinjaYes (interfaceNinja, "Yes", "Yes", true); static SwitchOption interfaceNinjaNo (interfaceNinja, "No", "No", false); static Switch interfaceHiggsEff ("HiggsEff", "Switch On/Off for effective higgs model.", &GoSamAmplitude::theHiggsEff, false, false, false); static SwitchOption interfaceHiggsEffYes (interfaceHiggsEff, "Yes", "Yes", true); static SwitchOption interfaceHiggsEffNo (interfaceHiggsEff, "No", "No", false); static Parameter interfaceBuildScript ("BuildScript", "File name of a custom build script, which is called between 'autogen.sh'" "and 'make install'. It can be used for parallelization.", &GoSamAmplitude::gosamBuildScript, "", false, false); static Parameter interfaceAccuracyTarget ("AccuracyTarget", "Integer to parametrize the threshold value for the BLHA2 acc parameter, returned by GoSam in the case of " "sub-processes with one-loop intereference terms or loop induced sub-processes." "If acc > 10^-AccuracyTarget the corresponding PSP is being discarded. Discarded PSPs are written to file " "if Debug::level > 1.", &GoSamAmplitude::theAccuracyTarget, 6, 0, 0, false, false, Interface::lowerlim); static Switch interfaceMassiveLeptons ("MassiveLeptons", "If set to Yes, then pass on the light lepton masses - as well as the tau mass - to GoSam." "Otherwise GoSam will use light leptons of zero mass as default, as well as its own default tau mass.", &GoSamAmplitude::theMassiveLeptons, false, false, false); static SwitchOption interfaceMassiveLeptonsNo (interfaceMassiveLeptons, "No", "No", false); static SwitchOption interfaceMassiveLeptonsYes (interfaceMassiveLeptons, "Yes", "Yes", true); static Switch interfaceLoopInducedOption ("LoopInducedOption", "Options for the GoSam interface, in the case that a loop induced process is being considered. The default " "option is 0, for which only the squared one-loop amplitude in the Standard Model is being considered. All " "other options consider additional contributions from a model with an effective interaction, which lead to " "the same final state, such as the squared effective amplitude, or the interference term between the one- " "loop amplitude in the Standard Model and the effective amplitude, or any additive combinations therefrom. " "In order to use those options an appropriate model has to be used.", &GoSamAmplitude::theLoopInducedOption, 0, false, false); static SwitchOption interfaceLoopInducedOptionLI2 (interfaceLoopInducedOption, "LI2", "Only consider the squared one-loop amplitude in the Standard Model.", 0); static SwitchOption interfaceLoopInducedOptionEff2 (interfaceLoopInducedOption, "Eff2", "Only consider the squared effective amplitude.", 1); static SwitchOption interfaceLoopInducedOptionLIEffInterference (interfaceLoopInducedOption, "LIEffInterference", "Only consider the interference term between the one-loop amplitude " "in the Standard Model and the effective amplitude.", 2); static SwitchOption interfaceLoopInducedOptionLI2plusEff2 (interfaceLoopInducedOption, "LI2plusEff2", "Consider the sum of the squared one-loop amplitude in the Standard " "Model plus the squared effective amplitude.", 3); static SwitchOption interfaceLoopInducedOptionLI2plusLIEffInterference (interfaceLoopInducedOption, "LI2plusEffInterference", "Consider the sum of the squared one-loop amplitude in the Standard " "Model plus the interference term between the one-loop amplitude in " "the Standard Model and the effective amplitude.", 4); static SwitchOption interfaceLoopInducedOptionEff2plusLIEffInterference (interfaceLoopInducedOption, "Eff2plusEffInterference", "Consider the sum of the squared effective amplitude plus the inter- " "ference term between the one-loop amplitude in the Standard Model " "and the effective amplitude.", 5); static SwitchOption interfaceLoopInducedOptionAllAdditions (interfaceLoopInducedOption, "AllAdditions", "Consider the sum of the squared one-loop amplitude in the Standard " "Model plus all other contributions, which come with the effective " "Model.", 6); static Parameter interfaceBinDir ("BinDir", "The location for the installed executable", &GoSamAmplitude::bindir_, string(HERWIG_BINDIR), false, false); static Parameter interfacePKGDATADIR ("DataDir", "The location for the installed Herwig data files", &GoSamAmplitude::pkgdatadir_, string(HERWIG_PKGDATADIR), false, false); static Parameter interfaceGoSamPrefix ("GoSamPrefix", "The prefix for the location of GoSam", &GoSamAmplitude::GoSamPrefix_, string(GOSAM_PREFIX), false, false); } diff --git a/MatrixElement/Matchbox/External/Makefile.am b/MatrixElement/Matchbox/External/Makefile.am --- a/MatrixElement/Matchbox/External/Makefile.am +++ b/MatrixElement/Matchbox/External/Makefile.am @@ -1,95 +1,95 @@ SUBDIRS = BLHAGeneric VBFNLO NJet GoSam OpenLoops MadGraph pkglib_LTLIBRARIES = ############## if HAVE_GOSAM pkglib_LTLIBRARIES += HwMatchboxGoSam.la endif HwMatchboxGoSam_la_LDFLAGS = \ -$(AM_LDFLAGS) -module -version-info 14:0:0 +$(AM_LDFLAGS) -module -version-info 14:1:0 HwMatchboxGoSam_la_CPPFLAGS = $(AM_CPPFLAGS) \ -DHERWIG_BINDIR="\"$(bindir)\"" \ -DHERWIG_PKGDATADIR="\"$(pkgdatadir)\"" \ -DGOSAM_PREFIX="\"$(GOSAMPREFIX)\"" HwMatchboxGoSam_la_SOURCES = \ GoSam/GoSamAmplitude.cc ############### if HAVE_VBFNLO pkglib_LTLIBRARIES += HwMatchboxVBFNLO.la endif -HwMatchboxVBFNLO_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 3:0:0 +HwMatchboxVBFNLO_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 3:1:0 HwMatchboxVBFNLO_la_CPPFLAGS = $(AM_CPPFLAGS) HwMatchboxVBFNLO_la_CPPFLAGS += -I$(VBFNLOINCLUDE) HwMatchboxVBFNLO_la_CPPFLAGS += -DVBFNLOLIB=$(VBFNLOLIB) HwMatchboxVBFNLO_la_SOURCES = \ VBFNLO/VBFNLOAmplitude.cc \ VBFNLO/VBFNLOPhasespace.cc ############### if HAVE_OPENLOOPS pkglib_LTLIBRARIES += HwMatchboxOpenLoops.la endif HwMatchboxOpenLoops_la_SOURCES = \ OpenLoops/OpenLoopsAmplitude.cc HwMatchboxOpenLoops_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 13:1:0 HwMatchboxOpenLoops_la_CPPFLAGS = $(AM_CPPFLAGS) \ -DOPENLOOPSLIBS="\"$(OPENLOOPSLIBS)\"" \ -DOPENLOOPSPREFIX="\"$(OPENLOOPSPREFIX)\"" ############## if HAVE_NJET pkglib_LTLIBRARIES += HwMatchboxNJet.la endif HwMatchboxNJet_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 13:0:0 HwMatchboxNJet_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(NJETINCLUDEPATH) \ -DNJET_PREFIX="\"$(NJETPREFIX)\"" \ -DNJET_LIBS="\"$(NJETLIBPATH)\"" HwMatchboxNJet_la_SOURCES = \ NJet/NJetsAmplitude.cc ############## if HAVE_MADGRAPH pkglib_LTLIBRARIES += HwMatchboxMadGraph.la endif HwMatchboxMadGraph_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 4:1:0 HwMatchboxMadGraph_la_SOURCES = \ MadGraph/MadGraphAmplitude.cc HwMatchboxMadGraph_la_CPPFLAGS = $(AM_CPPFLAGS) \ -DHERWIG_BINDIR="\"$(bindir)\"" \ -DHERWIG_INCLUDEDIR="\"$(includedir)\"" \ -DHERWIG_PKGDATADIR="\"$(pkgdatadir)\"" \ -DMADGRAPH_PREFIX="\"$(MADGRAPHPREFIX)\"" diff --git a/MatrixElement/Matchbox/External/VBFNLO/VBFNLOAmplitude.cc b/MatrixElement/Matchbox/External/VBFNLO/VBFNLOAmplitude.cc --- a/MatrixElement/Matchbox/External/VBFNLO/VBFNLOAmplitude.cc +++ b/MatrixElement/Matchbox/External/VBFNLO/VBFNLOAmplitude.cc @@ -1,477 +1,495 @@ // -*- C++ -*- // // VBFNLOAmplitude.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 VBFNLOAmplitude class. // #include "VBFNLOAmplitude.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Utilities/DynamicLoader.h" #include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h" #include #include "VBFNLO/utilities/BLHAinterface.h" #define DEFSTR(s) CPPSTR(s) #define CPPSTR(s) #s using namespace Herwig; VBFNLOAmplitude::VBFNLOAmplitude() : theRanHelSum(false), theAnomCoupl(false), VBFNLOlib_(DEFSTR(VBFNLOLIB)) {} VBFNLOAmplitude::~VBFNLOAmplitude() {} IBPtr VBFNLOAmplitude::clone() const { return new_ptr(*this); } IBPtr VBFNLOAmplitude::fullclone() const { return new_ptr(*this); } void VBFNLOAmplitude::signOLP(const string& order, const string& contract) { int status = 0; OLP_Order(const_cast(order.c_str()), const_cast(contract.c_str()),&status); if ( status != 1 ) throw Exception() << "VBFNLOAmplitude: Failed to sign contract with VBFNLO.\n" << "The BLHA contract file " << contract << "\n" << "may contain further details about the error." << Exception::runerror; } void VBFNLOAmplitude::setOLPParameter(const string& name, double value) const { int pStatus = 0; double zero = 0.0; OLP_SetParameter(const_cast(name.c_str()),&value,&zero,&pStatus); if ( !pStatus ) throw Exception() << "VBFNLOAmplitude: VBFNLO failed to set parameter '" << name << "' to " << value << "\n" << Exception::runerror; } void VBFNLOAmplitude::startOLP(const string& contract, int& status) { OLP_Start(const_cast(contract.c_str()), &status); map::const_iterator it=reshuffleMasses().find(ParticleID::b); double bmass; if(it==reshuffleMasses().end()) bmass = getParticleData(ParticleID::b)->hardProcessMass()/GeV; else bmass = it->second/GeV; setOLPParameter("mass(5)",bmass); setOLPParameter("mass(6)",getParticleData(ParticleID::t)->hardProcessMass()/GeV); setOLPParameter("mass(23)",getParticleData(ParticleID::Z0)->hardProcessMass()/GeV); setOLPParameter("mass(24)",getParticleData(ParticleID::Wplus)->hardProcessMass()/GeV); setOLPParameter("mass(25)",getParticleData(ParticleID::h0)->hardProcessMass()/GeV); setOLPParameter("width(23)",getParticleData(ParticleID::Z0)->hardProcessWidth()/GeV); setOLPParameter("width(24)",getParticleData(ParticleID::Wplus)->hardProcessWidth()/GeV); setOLPParameter("width(25)",getParticleData(ParticleID::h0)->hardProcessWidth()/GeV); setOLPParameter("alpha",SM().alphaEMMZ()); setOLPParameter("sw2",SM().sin2ThetaW()); setOLPParameter("Gf",SM().fermiConstant()*GeV2); setOLPParameter("Nf",factory()->nLight()); setOLPParameter("alphas",SM().alphaS()); setOLPParameter("ranhelsum",theRanHelSum); setOLPParameter("anomcoupl",theAnomCoupl); didStartOLP() = true; } void VBFNLOAmplitude::loadVBFNLO() { if ( ! DynamicLoader::load(VBFNLOlib_+"/libVBFNLO.so") ) { string error1 = DynamicLoader::lastErrorMessage; if ( ! DynamicLoader::load(VBFNLOlib_+"/libVBFNLO.dylib") ) { string error2 = DynamicLoader::lastErrorMessage; if ( ! DynamicLoader::load("libVBFNLO.so") ) { string error3 = DynamicLoader::lastErrorMessage; if ( ! DynamicLoader::load("libVBFNLO.dylib") ) { string error4 = DynamicLoader::lastErrorMessage; throw Exception() << "VBFNLOAmplitude: failed to load libVBFNLO.so/dylib\n" << "Error messages are:\n\n" << "* " << VBFNLOlib_ << "/libVBFNLO.so:\n" << error1 << "\n" << "* " << VBFNLOlib_ << "/libVBFNLO.dylib:\n" << error2 << "\n" << "* libVBFNLO.so:\n" << error3 << "\n" << "* libVBFNLO.dylib:\n" << error4 << "\n" << Exception::runerror; } } } } } bool VBFNLOAmplitude::startOLP(const map,int>& procs) { loadVBFNLO(); string orderFileName = factory()->buildStorage() + name() + ".OLPOrder.lh"; ofstream orderFile(orderFileName.c_str()); olpOrderFileHeader(orderFile); // add VBFNLO specifics here olpOrderFileProcesses(orderFile,procs); orderFile << flush; orderFile.close(); string contractFileName = factory()->buildStorage() + name() + ".OLPContract.lh"; signOLP(orderFileName, contractFileName); int status = -1; startOLP(contractFileName,status); if ( status != 1 ) return false; return true; } LorentzVector VBFNLOAmplitude::plusPolarization(const Lorentz5Momentum& p, const Lorentz5Momentum& n, int inc) const { // shamelessly stolen from the GoSam interface; mind that we can // always cast eq (5.7) in the manual into a form that it only uses // and then switch bvetween eps_+ for an outgoing and // eps_- for an incoming gluon. double pvec[4] = {p.t()/GeV,p.x()/GeV,p.y()/GeV,p.z()/GeV}; double nvec[4] = {n.t()/GeV,n.x()/GeV,n.y()/GeV,n.z()/GeV}; double out[8] ={ }; OLP_Polvec(pvec,nvec,out); LorentzVector res; Complex a(out[0],out[1]); res.setT(a); Complex b(out[2],out[3]); res.setX(b); Complex c(out[4],out[5]); res.setY(c); Complex d(out[6],out[7]); res.setZ(d); if (inc<2) return res.conjugate(); else return res; } void VBFNLOAmplitude::evalSubProcess() const { useMe(); double units = pow(lastSHat()/GeV2,mePartonData().size()-4.); fillOLPMomenta(lastXComb().meMomenta(),mePartonData(),reshuffleMasses()); double scale = sqrt(mu2()/GeV2); if (hasRunningAlphaS()) setOLPParameter("alphas",lastAlphaS()); double acc = -1.0; double out[4]={}; int id = olpId()[ProcessType::oneLoopInterference] ? olpId()[ProcessType::oneLoopInterference] : olpId()[ProcessType::treeME2]; if (theRanHelSum) { - vector helicityrn = amplitudeRandomNumbers(); + vector helicityrn; + if ( lastHeadMatchboxXComb() ) { + helicityrn = lastHeadMatchboxXComb()->amplitudeRandomNumbers(); + } else { + helicityrn = amplitudeRandomNumbers(); + } if (helicityrn.size()>0) { setOLPParameter("HelicityRN",helicityrn[0]); } } OLP_EvalSubProcess2(&id, olpMomenta(), &scale, out, &acc); if ( olpId()[ProcessType::oneLoopInterference] ) { lastTreeME2(out[3]*units); lastOneLoopInterference(out[2]*units); lastOneLoopPoles(pair(out[0]*units,out[1]*units)); } else if ( olpId()[ProcessType::treeME2] ) { lastTreeME2(out[0]*units); } else assert(false); } void VBFNLOAmplitude::evalColourCorrelator(pair) const { double units = pow(lastSHat()/GeV2,mePartonData().size()-4.); fillOLPMomenta(lastXComb().meMomenta(),mePartonData(),reshuffleMasses()); double scale = sqrt(mu2()/GeV2); if (hasRunningAlphaS()) setOLPParameter("alphas",lastAlphaS()); double acc = -1.0; int n = lastXComb().meMomenta().size(); colourCorrelatorResults.resize(n*(n-1)/2); int id = olpId()[ProcessType::colourCorrelatedME2]; - if ( theRanHelSum ) { + if (theRanHelSum) { + vector helicityrn; if ( lastHeadMatchboxXComb() ) { - vector helicityrn = lastHeadMatchboxXComb()->amplitudeRandomNumbers(); - if (helicityrn.size()>0) { - setOLPParameter("HelicityRN",helicityrn[0]); - } - } else if ( amplitudeRandomNumbers().size() > 0 ) { - vector helicityrn = amplitudeRandomNumbers(); - if (helicityrn.size()>0) { - setOLPParameter("HelicityRN",helicityrn[0]); - } + helicityrn = lastHeadMatchboxXComb()->amplitudeRandomNumbers(); + } else { + helicityrn = amplitudeRandomNumbers(); + } + if (helicityrn.size()>0) { + setOLPParameter("HelicityRN",helicityrn[0]); } } OLP_EvalSubProcess2(&id, olpMomenta(), &scale, &colourCorrelatorResults[0], &acc); for ( int i = 0; i < n; ++i ) for ( int j = i+1; j < n; ++j ) { lastColourCorrelator(make_pair(i,j),colourCorrelatorResults[i+j*(j-1)/2]*units); } } void VBFNLOAmplitude::evalSpinColourCorrelator(pair) const { double units = pow(lastSHat()/GeV2,mePartonData().size()-4.); fillOLPMomenta(lastXComb().meMomenta(),mePartonData(),reshuffleMasses()); double scale = sqrt(mu2()/GeV2); if (hasRunningAlphaS()) setOLPParameter("alphas",lastAlphaS()); double acc = -1.0; int n = lastXComb().meMomenta().size(); spinColourCorrelatorResults.resize(2*n*n); int id = olpId()[ProcessType::spinColourCorrelatedME2]; - if (theRanHelSum && lastHeadMatchboxXComb()) { - vector helicityrn = lastHeadMatchboxXComb()->amplitudeRandomNumbers(); + if (theRanHelSum) { + vector helicityrn; + if ( lastHeadMatchboxXComb() ) { + helicityrn = lastHeadMatchboxXComb()->amplitudeRandomNumbers(); + } else { + helicityrn = amplitudeRandomNumbers(); + } if (helicityrn.size()>0) { setOLPParameter("HelicityRN",helicityrn[0]); } } OLP_EvalSubProcess2(&id, olpMomenta(), &scale, &spinColourCorrelatorResults[0], &acc); for ( int i = 0; i < n; ++i ) for ( int j = 0; j < n; ++j ) { if ( i == j || mePartonData()[i]->id() != 21 ) continue; Complex scc(spinColourCorrelatorResults[2*i+2*n*j]*units, spinColourCorrelatorResults[2*i+2*n*j+1]*units); lastColourSpinCorrelator(make_pair(i,j),scc); } } double VBFNLOAmplitude::largeNME2(Ptr::tptr cptr) const { if ( calculateLargeNME2() ) evalLargeNSubProcess(cptr); return lastLargeNME2(); } void VBFNLOAmplitude::evalLargeNSubProcess(Ptr::tptr) const { double units = pow(lastSHat()/GeV2,mePartonData().size()-4.); fillOLPMomenta(lastXComb().meMomenta(),mePartonData(),reshuffleMasses()); double scale = sqrt(mu2()/GeV2); if (hasRunningAlphaS()) setOLPParameter("alphas",lastAlphaS()); double acc = -1.0; double out[4]={}; int id = olpId()[ProcessType::oneLoopInterference] ? olpId()[ProcessType::oneLoopInterference] : olpId()[ProcessType::treeME2]; if (theRanHelSum) { - vector helicityrn = amplitudeRandomNumbers(); + vector helicityrn; + if ( lastHeadMatchboxXComb() ) { + helicityrn = lastHeadMatchboxXComb()->amplitudeRandomNumbers(); + } else { + helicityrn = amplitudeRandomNumbers(); + } if (helicityrn.size()>0) { setOLPParameter("HelicityRN",helicityrn[0]); } } setOLPParameter("Nc",-1); // large-N limit OLP_EvalSubProcess2(&id, olpMomenta(), &scale, out, &acc); setOLPParameter("Nc",generator()->standardModel()->Nc()); if ( olpId()[ProcessType::oneLoopInterference] ) { lastLargeNME2(out[3]*units); lastOneLoopInterference(out[2]*units); lastOneLoopPoles(pair(out[0]*units,out[1]*units)); } else if ( olpId()[ProcessType::treeME2] ) { lastLargeNME2(out[0]*units); } else assert(false); } double VBFNLOAmplitude::largeNColourCorrelatedME2(pair ij, Ptr::tptr cptr) const { double cfac = 1.; double Nc = generator()->standardModel()->Nc(); if ( mePartonData()[ij.first]->iColour() == PDT::Colour8 ) { cfac = Nc; } else if ( mePartonData()[ij.first]->iColour() == PDT::Colour3 || mePartonData()[ij.first]->iColour() == PDT::Colour3bar ) { cfac = Nc/2.; } else assert(false); if ( calculateLargeNColourCorrelator(ij) ) evalLargeNColourCorrelator(ij,cptr); return lastLargeNColourCorrelator(ij)/cfac; } void VBFNLOAmplitude::evalLargeNColourCorrelator(pair, Ptr::tptr) const { double units = pow(lastSHat()/GeV2,mePartonData().size()-4.); fillOLPMomenta(lastXComb().meMomenta(),mePartonData(),reshuffleMasses()); double scale = sqrt(mu2()/GeV2); if (hasRunningAlphaS()) setOLPParameter("alphas",lastAlphaS()); double acc = -1.0; int n = lastXComb().meMomenta().size(); colourCorrelatorResults.resize(n*(n-1)/2); int id = olpId()[ProcessType::colourCorrelatedME2]; - if (theRanHelSum && lastHeadMatchboxXComb()) { - vector helicityrn = lastHeadMatchboxXComb()->amplitudeRandomNumbers(); + if (theRanHelSum) { + vector helicityrn; + if ( lastHeadMatchboxXComb() ) { + helicityrn = lastHeadMatchboxXComb()->amplitudeRandomNumbers(); + } else { + helicityrn = amplitudeRandomNumbers(); + } if (helicityrn.size()>0) { setOLPParameter("HelicityRN",helicityrn[0]); } } setOLPParameter("Nc",-1); // large-N limit OLP_EvalSubProcess2(&id, olpMomenta(), &scale, &colourCorrelatorResults[0], &acc); setOLPParameter("Nc",generator()->standardModel()->Nc()); for ( int i = 0; i < n; ++i ) for ( int j = i+1; j < n; ++j ) { lastLargeNColourCorrelator(make_pair(i,j),colourCorrelatorResults[i+j*(j-1)/2]*units); } } void VBFNLOAmplitude::doinit() { loadVBFNLO(); MatchboxOLPME::doinit(); } void VBFNLOAmplitude::doinitrun() { loadVBFNLO(); MatchboxOLPME::doinitrun(); } void VBFNLOAmplitude::persistentOutput(PersistentOStream & os) const { os << colourCorrelatorResults << spinColourCorrelatorResults << theRanHelSum << theAnomCoupl << VBFNLOlib_; } void VBFNLOAmplitude::persistentInput(PersistentIStream & is, int) { is >> colourCorrelatorResults >> spinColourCorrelatorResults >> theRanHelSum >> theAnomCoupl >> VBFNLOlib_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigVBFNLOAmplitude("Herwig::VBFNLOAmplitude", "HwMatchboxVBFNLO.so"); void VBFNLOAmplitude::Init() { static ClassDocumentation documentation ("VBFNLOAmplitude implements an interface to VBFNLO.", "Matrix elements have been calculated using VBFNLO " "(Ref.~\\cite{VBFNLO} and process-specific references)\n", "%\\cite{VBFNLO}\n" "\\bibitem{Arnold:2008rz}\n" "K.~Arnold, M.~Bahr, G.~Bozzi, F.~Campanario, C.~Englert, T.~Figy, " "N.~Greiner and C.~Hackstein {\\it et al.},\n" "``VBFNLO: A Parton level Monte Carlo for processes with electroweak bosons,''\n" "Comput.\\ Phys.\\ Commun.\\ {\\bf 180} (2009) 1661\n" "[arXiv:0811.4559 [hep-ph]];\n" "%%CITATION = ARXIV:0811.4559;%%\n" "J.~Baglio, J.~Bellm, F.~Campanario, B.~Feigl, J.~Frank, T.~Figy, " "M.~Kerner and L.~D.~Ninh {\\it et al.},\n" "``Release Note - VBFNLO 2.7.0,''\n" "arXiv:1404.3940 [hep-ph].\n" "%%CITATION = ARXIV:1404.3940;%%\n"); static Switch interfaceRandomHelicitySummation ("RandomHelicitySummation", "Switch for random helicity summation of leptons and photons", &VBFNLOAmplitude::theRanHelSum, false, false, false); static SwitchOption interfaceRandomHelicitySummationYes (interfaceRandomHelicitySummation, "Yes", "Perform random helicity summation", true); static SwitchOption interfaceRandomHelicitySummationNo (interfaceRandomHelicitySummation, "No", "Sum over all helicity combinations", false); static Switch interfaceAnomalousCouplings ("AnomalousCouplings", "Switch for anomalous couplings", &VBFNLOAmplitude::theAnomCoupl, false, false, false); static SwitchOption interfaceAnomalousCouplingsYes (interfaceAnomalousCouplings, "Yes", "Switch anomalous couplings on", true); static SwitchOption interfaceAnomalousCouplingsNo (interfaceAnomalousCouplings, "No", "Switch anomalous couplings off", false); } diff --git a/MatrixElement/Matchbox/Matching/DipoleMatching.cc b/MatrixElement/Matchbox/Matching/DipoleMatching.cc --- a/MatrixElement/Matchbox/Matching/DipoleMatching.cc +++ b/MatrixElement/Matchbox/Matching/DipoleMatching.cc @@ -1,139 +1,147 @@ // -*- C++ -*- // // DipoleMatching.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 DipoleMatching class. // #include "DipoleMatching.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.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 "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" using namespace Herwig; DipoleMatching::DipoleMatching() {} DipoleMatching::~DipoleMatching() {} IBPtr DipoleMatching::clone() const { return new_ptr(*this); } IBPtr DipoleMatching::fullclone() const { return new_ptr(*this); } CrossSection DipoleMatching::dSigHatDR() const { double xme2 = 0.; pair ij(dipole()->bornEmitter(), dipole()->bornSpectator()); double ccme2 = dipole()->underlyingBornME()->largeNColourCorrelatedME2(ij,theLargeNBasis); if(ccme2==0.)return 0.*nanobarn; double lnme2=dipole()->underlyingBornME()->largeNME2(theLargeNBasis); if(lnme2==0){ generator()->log() <<"\nDipoleMatching: "; generator()->log() <<"\n LargeNME2 is ZERO, while largeNColourCorrelatedME2 is not ZERO." ; generator()->log() <<"\n This is too seriuos.\n" ; generator()->log() << Exception::runerror; } ccme2 *= dipole()->underlyingBornME()->me2() /lnme2; xme2 = dipole()->me2Avg(ccme2); xme2 /= dipole()->underlyingBornME()->lastXComb().lastAlphaS(); double bornPDF = bornPDFWeight(dipole()->underlyingBornME()->lastScale()); if ( bornPDF == 0.0 ) return ZERO; xme2 *= bornPDF; if ( profileScales() ) xme2 *= profileScales()->hardScaleProfile(dipole()->showerHardScale(),dipole()->lastPt()); CrossSection res = sqr(hbarc) * realXComb()->jacobian() * subtractionScaleWeight() * xme2 / (2. * realXComb()->lastSHat()); return res; } double DipoleMatching::me2() const { throw Exception() << "DipoleMatching::me2(): Not intented to use. Disable the ShowerApproximationGenerator." << Exception::runerror; return 0.; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void DipoleMatching::persistentOutput(PersistentOStream & os) const { os << theShowerHandler; } void DipoleMatching::persistentInput(PersistentIStream & is, int) { is >> theShowerHandler; } void DipoleMatching::doinit() { if ( theShowerHandler ) { + theShowerHandler->init(); hardScaleFactor(theShowerHandler->hardScaleFactor()); factorizationScaleFactor(theShowerHandler->factorizationScaleFactor()); renormalizationScaleFactor(theShowerHandler->renormalizationScaleFactor()); profileScales(theShowerHandler->profileScales()); restrictPhasespace(theShowerHandler->restrictPhasespace()); hardScaleIsMuF(theShowerHandler->hardScaleIsMuF()); + if ( theShowerHandler->showerPhaseSpaceOption() == 0 ) { + useOpenZ(false); + } else if ( theShowerHandler->showerPhaseSpaceOption() == 1 ) { + useOpenZ(true); + } else { + throw InitException() << "DipoleMatching::doinit(): Choice of shower phase space cannot be handled by the matching"; + } } // need to fo this after for consistency checks ShowerApproximation::doinit(); } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct (the class and its base class), and that the constructor // arguments are correct (the class name and the name of the dynamically // loadable library where the class implementation can be found). DescribeClass describeHerwigDipoleMatching("Herwig::DipoleMatching", "HwDipoleMatching.so HwShower.so"); void DipoleMatching::Init() { static ClassDocumentation documentation ("DipoleMatching implements NLO matching with the dipole shower."); static Reference interfaceShowerHandler ("ShowerHandler", "The dipole shower handler object to use.", &DipoleMatching::theShowerHandler, false, false, true, true, false); interfaceShowerHandler.rank(-1); } diff --git a/MatrixElement/Matchbox/Matching/Makefile.am b/MatrixElement/Matchbox/Matching/Makefile.am --- a/MatrixElement/Matchbox/Matching/Makefile.am +++ b/MatrixElement/Matchbox/Matching/Makefile.am @@ -1,24 +1,24 @@ noinst_LTLIBRARIES = libHwMatchboxMatching.la pkglib_LTLIBRARIES = HwQTildeMatching.la HwDipoleMatching.la libHwMatchboxMatching_la_SOURCES = \ HardScaleProfile.h \ HardScaleProfile.cc \ ShowerApproximation.h \ ShowerApproximation.cc \ ShowerApproximationKernel.h \ ShowerApproximationKernel.cc \ ShowerApproximationGenerator.h \ ShowerApproximationGenerator.cc \ MEMatching.h \ MEMatching.cc HwQTildeMatching_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 3:0:0 HwQTildeMatching_la_SOURCES = \ QTildeMatching.h \ QTildeMatching.cc -HwDipoleMatching_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 3:0:0 +HwDipoleMatching_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 3:1:0 HwDipoleMatching_la_SOURCES = \ DipoleMatching.h \ DipoleMatching.cc diff --git a/MatrixElement/Matchbox/Matching/ShowerApproximation.cc b/MatrixElement/Matchbox/Matching/ShowerApproximation.cc --- a/MatrixElement/Matchbox/Matching/ShowerApproximation.cc +++ b/MatrixElement/Matchbox/Matching/ShowerApproximation.cc @@ -1,716 +1,716 @@ // -*- C++ -*- // // ShowerApproximation.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 ShowerApproximation class. // #include "ShowerApproximation.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/TildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/InvertedTildeKinematics.h" using namespace Herwig; ShowerApproximation::ShowerApproximation() : HandlerBase(), theExtrapolationX(1.0), theBelowCutoff(false), theFFPtCut(1.0*GeV), theFFScreeningScale(ZERO), theFIPtCut(1.0*GeV), theFIScreeningScale(ZERO), theIIPtCut(1.0*GeV), theIIScreeningScale(ZERO), theSafeCut(0.0*GeV), theRestrictPhasespace(true), theHardScaleFactor(1.0), theRenormalizationScaleFactor(1.0), theFactorizationScaleFactor(1.0), theRealEmissionScaleInSubtraction(showerScale), theBornScaleInSubtraction(showerScale), theEmissionScaleInSubtraction(showerScale), theRealEmissionScaleInSplitting(showerScale), theBornScaleInSplitting(showerScale), theEmissionScaleInSplitting(showerScale), theRenormalizationScaleFreeze(1.*GeV), theFactorizationScaleFreeze(1.*GeV), - maxPtIsMuF(false) {} + maxPtIsMuF(false), theOpenZ(true) {} ShowerApproximation::~ShowerApproximation() {} void ShowerApproximation::setLargeNBasis() { assert(dipole()->realEmissionME()->matchboxAmplitude()); if ( !dipole()->realEmissionME()->matchboxAmplitude()->treeAmplitudes() ) return; if ( !theLargeNBasis ) { if ( !dipole()->realEmissionME()->matchboxAmplitude()->colourBasis() ) throw Exception() << "ShowerApproximation::setLargeNBasis(): Expecting a colour basis object." << Exception::runerror; theLargeNBasis = dipole()->realEmissionME()->matchboxAmplitude()->colourBasis()->cloneMe(); theLargeNBasis->clear(); theLargeNBasis->doLargeN(); } } void ShowerApproximation::setDipole(Ptr::tptr dip) { theDipole = dip; setLargeNBasis(); } Ptr::tptr ShowerApproximation::dipole() const { return theDipole; } Ptr::tptr ShowerApproximation::showerTildeKinematics() const { return Ptr::tptr(); } Ptr::tptr ShowerApproximation::showerInvertedTildeKinematics() const { return Ptr::tptr(); } void ShowerApproximation::checkCutoff() { assert(!showerTildeKinematics()); } void ShowerApproximation::getShowerVariables() { // check for the cutoff dipole()->isAboveCutoff(isAboveCutoff()); // get the hard scale dipole()->showerHardScale(hardScale()); // set the shower scale and variables for completeness dipole()->showerScale(dipole()->lastPt()); dipole()->showerParameters().resize(1); dipole()->showerParameters()[0] = dipole()->lastZ(); // check for phase space dipole()->isInShowerPhasespace(isInShowerPhasespace()); } bool ShowerApproximation::isAboveCutoff() const { if ( dipole()->bornEmitter() > 1 && dipole()->bornSpectator() > 1 ) { return dipole()->lastPt() >= max(ffPtCut(),safeCut()); } else if ( ( dipole()->bornEmitter() > 1 && dipole()->bornSpectator() < 2 ) || ( dipole()->bornEmitter() < 2 && dipole()->bornSpectator() > 1 ) ) { return dipole()->lastPt() >= max(fiPtCut(),safeCut()); } else { assert(dipole()->bornEmitter() < 2 && dipole()->bornSpectator() < 2); return dipole()->lastPt() >= max(iiPtCut(),safeCut()); } return true; } Energy ShowerApproximation::hardScale() const { if ( !maxPtIsMuF ) { if ( !bornCXComb()->mePartonData()[0]->coloured() && !bornCXComb()->mePartonData()[1]->coloured() ) { Energy maxPt = (bornCXComb()->meMomenta()[0] + bornCXComb()->meMomenta()[1]).m(); maxPt *= hardScaleFactor(); return maxPt; } Energy maxPt = generator()->maximumCMEnergy(); vector::const_iterator p = bornCXComb()->meMomenta().begin() + 2; cPDVector::const_iterator pp = bornCXComb()->mePartonData().begin() + 2; for ( ; p != bornCXComb()->meMomenta().end(); ++p, ++pp ) if ( (**pp).coloured() ) maxPt = min(maxPt,p->mt()); if ( maxPt == generator()->maximumCMEnergy() ) maxPt = (bornCXComb()->meMomenta()[0] + bornCXComb()->meMomenta()[1]).m(); maxPt *= hardScaleFactor(); return maxPt; } else { return hardScaleFactor()*sqrt(bornCXComb()->lastShowerScale()); } } bool ShowerApproximation::isInShowerPhasespace() const { if ( !dipole()->isAboveCutoff() ) return false; if ( !restrictPhasespace() ) return true; InvertedTildeKinematics& kinematics = const_cast(*dipole()->invertedTildeKinematics()); tcStdXCombPtr tmpreal = kinematics.realXComb(); tcStdXCombPtr tmpborn = kinematics.bornXComb(); Ptr::tptr tmpdip = kinematics.dipole(); Energy hard = dipole()->showerHardScale(); Energy pt = dipole()->lastPt(); double z = dipole()->lastZ(); pair zbounds(0.,1.); kinematics.dipole(const_ptr_cast::tptr>(theDipole)); kinematics.prepare(realCXComb(),bornCXComb()); if ( pt > hard ) { kinematics.dipole(tmpdip); kinematics.prepare(tmpreal,tmpborn); return false; } try { - zbounds = kinematics.zBounds(pt,hard); + zbounds = kinematics.zBounds(pt,openZ() ? kinematics.ptMax() : hard); } catch(...) { kinematics.dipole(tmpdip); kinematics.prepare(tmpreal,tmpborn); throw; } kinematics.dipole(tmpdip); kinematics.prepare(tmpreal,tmpborn); return z > zbounds.first && z < zbounds.second; } Energy2 ShowerApproximation::showerEmissionScale() const { Energy2 mur = sqr(dipole()->lastPt()); if ( dipole()->bornEmitter() > 1 && dipole()->bornSpectator() > 1 ) { return mur + sqr(ffScreeningScale()); } else if ( ( dipole()->bornEmitter() > 1 && dipole()->bornSpectator() < 2 ) || ( dipole()->bornEmitter() < 2 && dipole()->bornSpectator() > 1 ) ) { return mur + sqr(fiScreeningScale()); } else { assert(dipole()->bornEmitter() < 2 && dipole()->bornSpectator() < 2); return mur + sqr(iiScreeningScale()); } return mur; } Energy2 ShowerApproximation::bornRenormalizationScale() const { return sqr(dipole()->underlyingBornME()->renormalizationScaleFactor()) * dipole()->underlyingBornME()->renormalizationScale(); } Energy2 ShowerApproximation::bornFactorizationScale() const { return sqr(dipole()->underlyingBornME()->factorizationScaleFactor()) * dipole()->underlyingBornME()->factorizationScale(); } Energy2 ShowerApproximation::realRenormalizationScale() const { return sqr(dipole()->realEmissionME()->renormalizationScaleFactor()) * dipole()->realEmissionME()->renormalizationScale(); } Energy2 ShowerApproximation::realFactorizationScale() const { return sqr(dipole()->realEmissionME()->factorizationScaleFactor()) * dipole()->realEmissionME()->factorizationScale(); } double ShowerApproximation::bornPDFWeight(Energy2 muf) const { if ( !bornCXComb()->mePartonData()[0]->coloured() && !bornCXComb()->mePartonData()[1]->coloured() ) return 1.; if ( muf < sqr(theFactorizationScaleFreeze) ) muf = sqr(theFactorizationScaleFreeze); double pdfweight = 1.; if ( bornCXComb()->mePartonData()[0]->coloured() && dipole()->underlyingBornME()->havePDFWeight1() ) pdfweight *= dipole()->underlyingBornME()->pdf1(muf,theExtrapolationX); if ( bornCXComb()->mePartonData()[1]->coloured() && dipole()->underlyingBornME()->havePDFWeight2() ) pdfweight *= dipole()->underlyingBornME()->pdf2(muf,theExtrapolationX); return pdfweight; } double ShowerApproximation::realPDFWeight(Energy2 muf) const { if ( !realCXComb()->mePartonData()[0]->coloured() && !realCXComb()->mePartonData()[1]->coloured() ) return 1.; if ( muf < sqr(theFactorizationScaleFreeze) ) muf = sqr(theFactorizationScaleFreeze); double pdfweight = 1.; if ( realCXComb()->mePartonData()[0]->coloured() && dipole()->realEmissionME()->havePDFWeight1() ) pdfweight *= dipole()->realEmissionME()->pdf1(muf,theExtrapolationX); if ( realCXComb()->mePartonData()[1]->coloured() && dipole()->realEmissionME()->havePDFWeight2() ) pdfweight *= dipole()->realEmissionME()->pdf2(muf,theExtrapolationX); return pdfweight; } double ShowerApproximation::scaleWeight(int rScale, int bScale, int eScale) const { double emissionAlpha = 1.; Energy2 emissionScale = ZERO; Energy2 showerscale = ZERO; if ( eScale == showerScale || bScale == showerScale || eScale == showerScale ) { showerscale = showerRenormalizationScale(); if ( showerscale < sqr(theRenormalizationScaleFreeze) ) showerscale = sqr(theFactorizationScaleFreeze); } if ( eScale == showerScale ) { emissionAlpha = SM().alphaS(showerscale); emissionScale = showerFactorizationScale(); } else if ( eScale == realScale ) { emissionAlpha = dipole()->realEmissionME()->lastXComb().lastAlphaS(); emissionScale = dipole()->realEmissionME()->lastScale(); } else if ( eScale == bornScale ) { emissionAlpha = dipole()->underlyingBornME()->lastXComb().lastAlphaS(); emissionScale = dipole()->underlyingBornME()->lastScale(); } double emissionPDF = realPDFWeight(emissionScale); double couplingFactor = 1.; if ( bScale != rScale ) { double bornAlpha = 1.; if ( bScale == showerScale ) { bornAlpha = SM().alphaS(showerscale); } else if ( bScale == realScale ) { bornAlpha = dipole()->realEmissionME()->lastXComb().lastAlphaS(); } else if ( bScale == bornScale ) { bornAlpha = dipole()->underlyingBornME()->lastXComb().lastAlphaS(); } double realAlpha = 1.; if ( rScale == showerScale ) { realAlpha = SM().alphaS(showerscale); } else if ( rScale == realScale ) { realAlpha = dipole()->realEmissionME()->lastXComb().lastAlphaS(); } else if ( rScale == bornScale ) { realAlpha = dipole()->underlyingBornME()->lastXComb().lastAlphaS(); } couplingFactor *= pow(realAlpha/bornAlpha,(double)(dipole()->underlyingBornME()->orderInAlphaS())); } Energy2 hardScale = ZERO; if ( bScale == showerScale ) { hardScale = showerFactorizationScale(); } else if ( bScale == realScale ) { hardScale = dipole()->realEmissionME()->lastScale(); } else if ( bScale == bornScale ) { hardScale = dipole()->underlyingBornME()->lastScale(); } double bornPDF = bornPDFWeight(hardScale); if ( bornPDF < 1e-8 ) bornPDF = 0.0; if ( emissionPDF < 1e-8 ) emissionPDF = 0.0; if ( emissionPDF == 0.0 || bornPDF == 0.0 ) return 0.0; return emissionAlpha * emissionPDF * couplingFactor / bornPDF; } double ShowerApproximation::channelWeight(int emitter, int emission, int spectator, int) const { double cfac = 1.; double Nc = generator()->standardModel()->Nc(); if (realCXComb()->mePartonData()[emitter]->iColour() == PDT::Colour8){ if (realCXComb()->mePartonData()[emission]->iColour() == PDT::Colour8) cfac = Nc; else if ( realCXComb()->mePartonData()[emission]->iColour() == PDT::Colour3 || realCXComb()->mePartonData()[emission]->iColour() == PDT::Colour3bar) cfac = 0.5; else assert(false); } else if ((realCXComb()->mePartonData()[emitter] ->iColour() == PDT::Colour3 || realCXComb()->mePartonData()[emitter] ->iColour() == PDT::Colour3bar)) cfac = (sqr(Nc)-1.)/(2.*Nc); else assert(false); // do the most simple thing for the time being; needs fixing later if ( realCXComb()->mePartonData()[emission]->id() == ParticleID::g ) { Energy2 pipk = realCXComb()->meMomenta()[emitter] * realCXComb()->meMomenta()[spectator]; Energy2 pipj = realCXComb()->meMomenta()[emitter] * realCXComb()->meMomenta()[emission]; Energy2 pjpk = realCXComb()->meMomenta()[emission] * realCXComb()->meMomenta()[spectator]; return cfac *GeV2 * pipk / ( pipj * ( pipj + pjpk ) ); } return cfac * GeV2 / (realCXComb()->meMomenta()[emitter] * realCXComb()->meMomenta()[emission]); } double ShowerApproximation::channelWeight() const { double currentChannel = channelWeight(dipole()->realEmitter(), dipole()->realEmission(), dipole()->realSpectator(), dipole()->bornEmitter()); if ( currentChannel == 0. ) return 0.; double sum = 0.; for ( vector::tptr>::const_iterator dip = dipole()->partnerDipoles().begin(); dip != dipole()->partnerDipoles().end(); ++dip ) sum += channelWeight((**dip).realEmitter(), (**dip).realEmission(), (**dip).realSpectator(), (**dip).bornEmitter()); assert(sum > 0.0); return currentChannel / sum; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void ShowerApproximation::doinit() { if ( profileScales() ) { if ( profileScales()->unrestrictedPhasespace() && restrictPhasespace() ) { generator()->log() << "ShowerApproximation warning: The scale profile chosen requires an unrestricted phase space,\n" << "however, the phase space was set to be restricted. Will switch to unrestricted phase space.\n" << flush; restrictPhasespace(false); } } HandlerBase::doinit(); } void ShowerApproximation::persistentOutput(PersistentOStream & os) const { os << theLargeNBasis << theBornXComb << theRealXComb << theTildeXCombs << theDipole << theBelowCutoff << ounit(theFFPtCut,GeV) << ounit(theFFScreeningScale,GeV) << ounit(theFIPtCut,GeV) << ounit(theFIScreeningScale,GeV) << ounit(theIIPtCut,GeV) << ounit(theIIScreeningScale,GeV) << ounit(theSafeCut,GeV) << theRestrictPhasespace << theHardScaleFactor << theRenormalizationScaleFactor << theFactorizationScaleFactor << theExtrapolationX << theRealEmissionScaleInSubtraction << theBornScaleInSubtraction << theEmissionScaleInSubtraction << theRealEmissionScaleInSplitting << theBornScaleInSplitting << theEmissionScaleInSplitting << ounit(theRenormalizationScaleFreeze,GeV) << ounit(theFactorizationScaleFreeze,GeV) << maxPtIsMuF - << theHardScaleProfile; + << theHardScaleProfile << theOpenZ; } void ShowerApproximation::persistentInput(PersistentIStream & is, int) { is >> theLargeNBasis >> theBornXComb >> theRealXComb >> theTildeXCombs >> theDipole >> theBelowCutoff >> iunit(theFFPtCut,GeV) >> iunit(theFFScreeningScale,GeV) >> iunit(theFIPtCut,GeV) >> iunit(theFIScreeningScale,GeV) >> iunit(theIIPtCut,GeV) >> iunit(theIIScreeningScale,GeV) >> iunit(theSafeCut,GeV) >> theRestrictPhasespace >> theHardScaleFactor >> theRenormalizationScaleFactor >> theFactorizationScaleFactor >> theExtrapolationX >> theRealEmissionScaleInSubtraction >> theBornScaleInSubtraction >> theEmissionScaleInSubtraction >> theRealEmissionScaleInSplitting >> theBornScaleInSplitting >> theEmissionScaleInSplitting >> iunit(theRenormalizationScaleFreeze,GeV) >> iunit(theFactorizationScaleFreeze,GeV) >> maxPtIsMuF - >> theHardScaleProfile; + >> theHardScaleProfile >> theOpenZ; } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct (the class and its base class), and that the constructor // arguments are correct (the class name and the name of the dynamically // loadable library where the class implementation can be found). DescribeAbstractClass describeHerwigShowerApproximation("Herwig::ShowerApproximation", "Herwig.so"); void ShowerApproximation::Init() { static ClassDocumentation documentation ("ShowerApproximation describes the shower emission to be used " "in NLO matching."); static Parameter interfaceFFPtCut ("FFPtCut", "Set the pt infrared cutoff", &ShowerApproximation::theFFPtCut, GeV, 1.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceFIPtCut ("FIPtCut", "Set the pt infrared cutoff", &ShowerApproximation::theFIPtCut, GeV, 1.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceIIPtCut ("IIPtCut", "Set the pt infrared cutoff", &ShowerApproximation::theIIPtCut, GeV, 1.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceSafeCut ("SafeCut", "Set the enhanced infrared cutoff for the Matching.", &ShowerApproximation::theSafeCut, GeV, 0.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceFFScreeningScale ("FFScreeningScale", "Set the screening scale", &ShowerApproximation::theFFScreeningScale, GeV, 0.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceFIScreeningScale ("FIScreeningScale", "Set the screening scale", &ShowerApproximation::theFIScreeningScale, GeV, 0.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceIIScreeningScale ("IIScreeningScale", "Set the screening scale", &ShowerApproximation::theIIScreeningScale, GeV, 0.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Switch interfaceRestrictPhasespace ("RestrictPhasespace", "Switch on or off phasespace restrictions", &ShowerApproximation::theRestrictPhasespace, true, false, false); static SwitchOption interfaceRestrictPhasespaceYes (interfaceRestrictPhasespace, "Yes", "Perform phasespace restrictions", true); static SwitchOption interfaceRestrictPhasespaceNo (interfaceRestrictPhasespace, "No", "Do not perform phasespace restrictions", false); static Parameter interfaceHardScaleFactor ("HardScaleFactor", "The hard scale factor.", &ShowerApproximation::theHardScaleFactor, 1.0, 0.0, 0, false, false, Interface::lowerlim); static Parameter interfaceRenormalizationScaleFactor ("RenormalizationScaleFactor", "The hard scale factor.", &ShowerApproximation::theRenormalizationScaleFactor, 1.0, 0.0, 0, false, false, Interface::lowerlim); static Parameter interfaceFactorizationScaleFactor ("FactorizationScaleFactor", "The hard scale factor.", &ShowerApproximation::theFactorizationScaleFactor, 1.0, 0.0, 0, false, false, Interface::lowerlim); static Parameter interfaceExtrapolationX ("ExtrapolationX", "The x from which on extrapolation should be performed.", &ShowerApproximation::theExtrapolationX, 1.0, 0.0, 1.0, false, false, Interface::limited); static Switch interfaceRealEmissionScaleInSubtraction ("RealEmissionScaleInSubtraction", "Set the scale choice for the real emission cross section in the matching subtraction.", &ShowerApproximation::theRealEmissionScaleInSubtraction, showerScale, false, false); static SwitchOption interfaceRealEmissionScaleInSubtractionRealScale (interfaceRealEmissionScaleInSubtraction, "RealScale", "Use the real emission scale.", realScale); static SwitchOption interfaceRealEmissionScaleInSubtractionBornScale (interfaceRealEmissionScaleInSubtraction, "BornScale", "Use the Born scale.", bornScale); static SwitchOption interfaceRealEmissionScaleInSubtractionShowerScale (interfaceRealEmissionScaleInSubtraction, "ShowerScale", "Use the shower scale", showerScale); interfaceRealEmissionScaleInSubtraction.rank(-1); static Switch interfaceBornScaleInSubtraction ("BornScaleInSubtraction", "Set the scale choice for the Born cross section in the matching subtraction.", &ShowerApproximation::theBornScaleInSubtraction, showerScale, false, false); static SwitchOption interfaceBornScaleInSubtractionRealScale (interfaceBornScaleInSubtraction, "RealScale", "Use the real emission scale.", realScale); static SwitchOption interfaceBornScaleInSubtractionBornScale (interfaceBornScaleInSubtraction, "BornScale", "Use the Born scale.", bornScale); static SwitchOption interfaceBornScaleInSubtractionShowerScale (interfaceBornScaleInSubtraction, "ShowerScale", "Use the shower scale", showerScale); interfaceBornScaleInSubtraction.rank(-1); static Switch interfaceEmissionScaleInSubtraction ("EmissionScaleInSubtraction", "Set the scale choice for the emission in the matching subtraction.", &ShowerApproximation::theEmissionScaleInSubtraction, showerScale, false, false); static SwitchOption interfaceEmissionScaleInSubtractionRealScale (interfaceEmissionScaleInSubtraction, "RealScale", "Use the real emission scale.", realScale); static SwitchOption interfaceEmissionScaleInSubtractionEmissionScale (interfaceEmissionScaleInSubtraction, "BornScale", "Use the Born scale.", bornScale); static SwitchOption interfaceEmissionScaleInSubtractionShowerScale (interfaceEmissionScaleInSubtraction, "ShowerScale", "Use the shower scale", showerScale); interfaceEmissionScaleInSubtraction.rank(-1); static Switch interfaceRealEmissionScaleInSplitting ("RealEmissionScaleInSplitting", "Set the scale choice for the real emission cross section in the splitting.", &ShowerApproximation::theRealEmissionScaleInSplitting, showerScale, false, false); static SwitchOption interfaceRealEmissionScaleInSplittingRealScale (interfaceRealEmissionScaleInSplitting, "RealScale", "Use the real emission scale.", realScale); static SwitchOption interfaceRealEmissionScaleInSplittingBornScale (interfaceRealEmissionScaleInSplitting, "BornScale", "Use the Born scale.", bornScale); static SwitchOption interfaceRealEmissionScaleInSplittingShowerScale (interfaceRealEmissionScaleInSplitting, "ShowerScale", "Use the shower scale", showerScale); interfaceRealEmissionScaleInSplitting.rank(-1); static Switch interfaceBornScaleInSplitting ("BornScaleInSplitting", "Set the scale choice for the Born cross section in the splitting.", &ShowerApproximation::theBornScaleInSplitting, showerScale, false, false); static SwitchOption interfaceBornScaleInSplittingRealScale (interfaceBornScaleInSplitting, "RealScale", "Use the real emission scale.", realScale); static SwitchOption interfaceBornScaleInSplittingBornScale (interfaceBornScaleInSplitting, "BornScale", "Use the Born scale.", bornScale); static SwitchOption interfaceBornScaleInSplittingShowerScale (interfaceBornScaleInSplitting, "ShowerScale", "Use the shower scale", showerScale); interfaceBornScaleInSplitting.rank(-1); static Switch interfaceEmissionScaleInSplitting ("EmissionScaleInSplitting", "Set the scale choice for the emission in the splitting.", &ShowerApproximation::theEmissionScaleInSplitting, showerScale, false, false); static SwitchOption interfaceEmissionScaleInSplittingRealScale (interfaceEmissionScaleInSplitting, "RealScale", "Use the real emission scale.", realScale); static SwitchOption interfaceEmissionScaleInSplittingEmissionScale (interfaceEmissionScaleInSplitting, "BornScale", "Use the Born scale.", bornScale); static SwitchOption interfaceEmissionScaleInSplittingShowerScale (interfaceEmissionScaleInSplitting, "ShowerScale", "Use the shower scale", showerScale); interfaceEmissionScaleInSplitting.rank(-1); static Parameter interfaceRenormalizationScaleFreeze ("RenormalizationScaleFreeze", "The freezing scale for the renormalization scale.", &ShowerApproximation::theRenormalizationScaleFreeze, GeV, 1.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); interfaceRenormalizationScaleFreeze.rank(-1); static Parameter interfaceFactorizationScaleFreeze ("FactorizationScaleFreeze", "The freezing scale for the factorization scale.", &ShowerApproximation::theFactorizationScaleFreeze, GeV, 1.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); interfaceFactorizationScaleFreeze.rank(-1); static Reference interfaceHardScaleProfile ("HardScaleProfile", "The hard scale profile to use.", &ShowerApproximation::theHardScaleProfile, false, false, true, true, false); static Reference interfaceLargeNBasis ("LargeNBasis", "Set the large-N colour basis implementation.", &ShowerApproximation::theLargeNBasis, false, false, true, true, false); interfaceLargeNBasis.rank(-1); static Switch interfaceMaxPtIsMuF ("MaxPtIsMuF", "", &ShowerApproximation::maxPtIsMuF, false, false, false); static SwitchOption interfaceMaxPtIsMuFYes (interfaceMaxPtIsMuF, "Yes", "", true); static SwitchOption interfaceMaxPtIsMuFNo (interfaceMaxPtIsMuF, "No", "", false); } diff --git a/MatrixElement/Matchbox/Matching/ShowerApproximation.h b/MatrixElement/Matchbox/Matching/ShowerApproximation.h --- a/MatrixElement/Matchbox/Matching/ShowerApproximation.h +++ b/MatrixElement/Matchbox/Matching/ShowerApproximation.h @@ -1,675 +1,691 @@ // -*- C++ -*- // // ShowerApproximation.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_ShowerApproximation_H #define Herwig_ShowerApproximation_H // // This is the declaration of the ShowerApproximation class. // #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/Handlers/StandardXComb.h" #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.fh" #include "Herwig/MatrixElement/Matchbox/Utility/ColourBasis.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/TildeKinematics.fh" #include "Herwig/MatrixElement/Matchbox/Phasespace/InvertedTildeKinematics.fh" #include "HardScaleProfile.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief ShowerApproximation describes the shower emission to be used * in NLO matching. * */ class ShowerApproximation: public HandlerBase { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ ShowerApproximation(); /** * The destructor. */ virtual ~ShowerApproximation(); //@} public: /** * Return true, if this shower approximation will require a * splitting generator */ virtual bool needsSplittingGenerator() const { return false; } /** * Return true, if this shower approximation will require * H events */ virtual bool hasHEvents() const { return true; } /** * Return true, if this shower approximation will require tilde * XCombs for the real phase space point generated */ virtual bool needsTildeXCombs() const { return false; } /** * Return true, if this shower approximation will require * a truncated parton shower */ virtual bool needsTruncatedShower() const { return false; } /** * Return the tilde kinematics object returning the shower * kinematics parametrization if different from the nominal dipole * mappings. */ virtual Ptr::tptr showerTildeKinematics() const; /** * Return the tilde kinematics object returning the shower * kinematics parametrization if different from the nominal dipole * mappings. */ virtual Ptr::tptr showerInvertedTildeKinematics() const; public: /** * Set the XComb object describing the Born process */ void setBornXComb(tStdXCombPtr xc) { theBornXComb = xc; } /** * Return the XComb object describing the Born process */ tStdXCombPtr bornXComb() const { return theBornXComb; } /** * Return the XComb object describing the Born process */ tcStdXCombPtr bornCXComb() const { return theBornXComb; } /** * Set the XComb object describing the real emission process */ void setRealXComb(tStdXCombPtr xc) { theRealXComb = xc; } /** * Return the XComb object describing the real emission process */ tStdXCombPtr realXComb() const { return theRealXComb; } /** * Return the XComb object describing the real emission process */ tcStdXCombPtr realCXComb() const { return theRealXComb; } /** * Set the tilde xcomb objects associated to the real xcomb */ void setTildeXCombs(const vector& xc) { theTildeXCombs = xc; } /** * Return the tilde xcomb objects associated to the real xcomb */ const vector& tildeXCombs() const { return theTildeXCombs; } /** * Set the dipole in charge for the emission */ void setDipole(Ptr::tptr); /** * Return the dipole in charge for the emission */ Ptr::tptr dipole() const; /** * Return true, if this matching is capable of spin correlations. */ virtual bool hasSpinCorrelations() const { return false; } public: /** * Return true if one of the recently encountered configutations was * below the infrared cutoff. */ bool belowCutoff() const { return theBelowCutoff; } /** * Indicate that one of the recently encountered configutations was * below the infrared cutoff. */ void wasBelowCutoff() { theBelowCutoff = true; } /** * Reset the below cutoff flag. */ void resetBelowCutoff() { theBelowCutoff = false; } /** * Return the pt cut to be applied for final-final dipoles. */ Energy ffPtCut() const { return theFFPtCut; } /** * Return the pt cut to be applied for final-initial dipoles. */ Energy fiPtCut() const { return theFIPtCut; } /** * Return the pt cut to be applied for initial-initial dipoles. */ Energy iiPtCut() const { return theIIPtCut; } /** * Return the pt cut to be applied for initial-initial dipoles. */ Energy safeCut() const { return theSafeCut;} /** * Return the screening scale to be applied for final-final dipoles. */ Energy ffScreeningScale() const { return theFFScreeningScale; } /** * Return the screening scale to be applied for final-initial dipoles. */ Energy fiScreeningScale() const { return theFIScreeningScale; } /** * Return the screening scale to be applied for initial-initial dipoles. */ Energy iiScreeningScale() const { return theIIScreeningScale; } /** * Return the shower renormalization scale */ virtual Energy2 showerEmissionScale() const; /** * Return the shower renormalization scale */ Energy2 showerRenormalizationScale() const { return sqr(renormalizationScaleFactor())*showerEmissionScale(); } /** * Return the shower factorization scale */ Energy2 showerFactorizationScale() const { return sqr(factorizationScaleFactor())*showerEmissionScale(); } /** * Return the Born renormalization scale */ Energy2 bornRenormalizationScale() const; /** * Return the Born factorization scale */ Energy2 bornFactorizationScale() const; /** * Return the real emission renormalization scale */ Energy2 realRenormalizationScale() const; /** * Return the real emission factorization scale */ Energy2 realFactorizationScale() const; /** * Enumerate possible scale choices */ enum ScaleChoices { bornScale = 0, /** Use the born scales */ realScale = 1, /** Use the real scales */ showerScale = 2 /** Use the shower scales */ }; /** * Return the scale choice in the real emission cross section to be * used in the matching subtraction. */ int realEmissionScaleInSubtraction() const { return theRealEmissionScaleInSubtraction; } /** * Return the scale choice in the born cross section to be * used in the matching subtraction. */ int bornScaleInSubtraction() const { return theBornScaleInSubtraction; } /** * Return the scale choice in the emission contribution to be * used in the matching subtraction. */ int emissionScaleInSubtraction() const { return theEmissionScaleInSubtraction; } /** * Return the scale choice in the real emission cross section to be * used in the splitting. */ int realEmissionScaleInSplitting() const { return theRealEmissionScaleInSplitting; } /** * Return the scale choice in the born cross section to be * used in the splitting. */ int bornScaleInSplitting() const { return theBornScaleInSplitting; } /** * Return the scale choice in the emission contribution to be * used in the splitting. */ int emissionScaleInSplitting() const { return theEmissionScaleInSplitting; } /** * Return the scale weight */ double scaleWeight(int rScale, int bScale, int eScale) const; /** * Return the scale weight for the matching subtraction */ double subtractionScaleWeight() const { return scaleWeight(realEmissionScaleInSubtraction(), bornScaleInSubtraction(), emissionScaleInSubtraction()); } /** * Return the scale weight for the splitting */ double splittingScaleWeight() const { return scaleWeight(realEmissionScaleInSplitting(), bornScaleInSplitting(), emissionScaleInSplitting()); } public: /** * Return true, if the phase space restrictions of the dipole shower should * be applied. */ bool restrictPhasespace() const { return theRestrictPhasespace; } /** * Indicate that the phase space restrictions of the dipole shower should * be applied. */ void restrictPhasespace(bool yes) { theRestrictPhasespace = yes; } /** * Return profile scales */ Ptr::tptr profileScales() const { return theHardScaleProfile; } /** * Set profile scales */ void profileScales(Ptr::ptr prof) { theHardScaleProfile = prof; } /** * Return true if maximum pt should be deduced from the factorization scale */ bool hardScaleIsMuF() const { return maxPtIsMuF; } /** * Indicate that maximum pt should be deduced from the factorization scale */ void hardScaleIsMuF(bool yes) { maxPtIsMuF = yes; } /** * Return the scale factor for the hard scale */ double hardScaleFactor() const { return theHardScaleFactor; } /** * Set the scale factor for the hard scale */ void hardScaleFactor(double f) { theHardScaleFactor = f; } /** * Get the factorization scale factor */ double factorizationScaleFactor() const { return theFactorizationScaleFactor; } /** * Get the renormalization scale factor */ double renormalizationScaleFactor() const { return theRenormalizationScaleFactor; } /** * Set the factorization scale factor */ void factorizationScaleFactor(double f) { theFactorizationScaleFactor = f; } /** * Set the renormalization scale factor */ void renormalizationScaleFactor(double f) { theRenormalizationScaleFactor = f; } /** * Determine if the configuration is below or above the cutoff. */ virtual void checkCutoff(); /** * Determine all kinematic variables which are not provided by the * dipole kinematics; store all shower variables in the respective * dipole object for later use. */ virtual void getShowerVariables(); /** * Return the shower approximation to the real emission cross * section for the given pair of Born and real emission * configurations. */ virtual CrossSection dSigHatDR() const = 0; /** * Return the shower approximation splitting kernel for the given * pair of Born and real emission configurations in units of the * Born center of mass energy squared, and including a weight to * project onto the splitting given by the dipole used. */ virtual double me2() const = 0; /** * Return the Born PDF weight */ double bornPDFWeight(Energy2 muF) const; /** * Return the real emission PDF weight */ double realPDFWeight(Energy2 muF) const; protected: /** * Return true, if the shower was able to generate an emission * leading from the given Born to the given real emission process. */ virtual bool isInShowerPhasespace() const; /** * Return true, if the shower emission leading from the given Born * to the given real emission process would have been generated * above the shower's infrared cutoff. */ virtual bool isAboveCutoff() const; /** * Return the relevant hard scale */ virtual Energy hardScale() const; + /** + * Use the maximum available phase space for the momentum fraction + */ + void useOpenZ(bool yes) { theOpenZ = yes; } + + /** + * Return true if the maximum available phase space should be used + * for the momentum fraction + */ + bool openZ() const { return theOpenZ; } + public: /** * Generate a weight for the given dipole channel */ virtual double channelWeight(int emitter, int emission, int spectator, int bemitter) const; /** * Generate a normalized weight taking into account all channels */ virtual double channelWeight() const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). public: /** * A large-N colour basis to be used when reproducing the shower * kernels. */ Ptr::tptr largeNBasis() const { return theLargeNBasis; } protected: /** * A large-N colour basis to be used when reproducing the shower * kernels. */ Ptr::ptr theLargeNBasis; /** * Set the large-N basis */ void setLargeNBasis(); /** * The x value from which on we extrapolate PDFs for numerically stable ratios. */ double theExtrapolationX; private: /** * The XComb object describing the Born process */ tStdXCombPtr theBornXComb; /** * The XComb object describing the real emission process */ tStdXCombPtr theRealXComb; /** * The tilde xcomb objects associated to the real xcomb */ vector theTildeXCombs; /** * The dipole in charge for the emission */ Ptr::tptr theDipole; /** * True if one of the recently encountered configutations was below * the infrared cutoff. */ bool theBelowCutoff; /** * The pt cut to be applied for final-final dipoles. */ Energy theFFPtCut; /** * An optional screening scale for final-final dipoles; see * DipoleSplittingKernel */ Energy theFFScreeningScale; /** * The pt cut to be applied for final-initial dipoles. */ Energy theFIPtCut; /** * An optional screening scale for final-initial dipoles; see * DipoleSplittingKernel */ Energy theFIScreeningScale; /** * The pt cut to be applied for initial-initial dipoles. */ Energy theIIPtCut; /** * An optional screening scale for initial-initial dipoles; see * DipoleSplittingKernel */ Energy theIIScreeningScale; /** * The cut to be applied as an enhanced shower cutoff. */ Energy theSafeCut; /** * True, if the phase space restrictions of the dipole shower should * be applied. */ bool theRestrictPhasespace; /** * The scale factor for the hard scale */ double theHardScaleFactor; /** * The scale factor for the renormalization scale */ double theRenormalizationScaleFactor; /** * The scale factor for the factorization scale */ double theFactorizationScaleFactor; /** * The scale choice in the real emission cross section to be * used in the matching subtraction. */ int theRealEmissionScaleInSubtraction; /** * The scale choice in the born cross section to be * used in the matching subtraction. */ int theBornScaleInSubtraction; /** * The scale choice in the emission contribution to be * used in the matching subtraction. */ int theEmissionScaleInSubtraction; /** * The scale choice in the real emission cross section to be * used in the splitting. */ int theRealEmissionScaleInSplitting; /** * The scale choice in the born cross section to be * used in the splitting. */ int theBornScaleInSplitting; /** * The scale choice in the emission contribution to be * used in the splitting. */ int theEmissionScaleInSplitting; /** * A freezing value for the renormalization scale */ Energy theRenormalizationScaleFreeze; /** * A freezing value for the factorization scale */ Energy theFactorizationScaleFreeze; /** * True if maximum pt should be deduced from the factorization scale */ bool maxPtIsMuF; /** * The profile scales */ Ptr::ptr theHardScaleProfile; + /** + * Use the maximum available phase space for the momentum fraction + */ + bool theOpenZ; + private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ ShowerApproximation & operator=(const ShowerApproximation &); }; } #endif /* Herwig_ShowerApproximation_H */ diff --git a/MatrixElement/Matchbox/Scales/Makefile.am b/MatrixElement/Matchbox/Scales/Makefile.am --- a/MatrixElement/Matchbox/Scales/Makefile.am +++ b/MatrixElement/Matchbox/Scales/Makefile.am @@ -1,32 +1,32 @@ pkglib_LTLIBRARIES = HwMatchboxScales.la -HwMatchboxScales_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 4:0:0 +HwMatchboxScales_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 4:1:0 HwMatchboxScales_la_SOURCES = \ MatchboxHtScale.h \ MatchboxLeptonMassScale.h \ MatchboxLeptonPtScale.h \ MatchboxParticlePtScale.h \ MatchboxPtScale.h \ MatchboxHtScale.cc \ MatchboxLeptonMassScale.cc \ MatchboxLeptonPtScale.cc \ MatchboxParticlePtScale.cc \ MatchboxPtScale.cc \ MatchboxSHatScale.h \ MatchboxSHatScale.cc \ MatchboxTopMassScale.h \ MatchboxTopMassScale.cc \ MatchboxTopMTScale.h \ MatchboxTopMTScale.cc \ MatchboxTopSumMTScale.h \ MatchboxTopSumMTScale.cc \ MatchboxTopMinMTScale.h \ MatchboxTopMinMTScale.cc \ MatchboxTriVecScales.h \ MatchboxTriVecScales.cc \ MatchboxTopLinearSumMTScale.h \ MatchboxTopLinearSumMTScale.cc \ MatchboxTopIndividualMTScale.h \ MatchboxTopIndividualMTScale.cc diff --git a/MatrixElement/Matchbox/Scales/MatchboxHtScale.cc b/MatrixElement/Matchbox/Scales/MatchboxHtScale.cc --- a/MatrixElement/Matchbox/Scales/MatchboxHtScale.cc +++ b/MatrixElement/Matchbox/Scales/MatchboxHtScale.cc @@ -1,164 +1,164 @@ // -*- C++ -*- // // MatchboxHtScale.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 MatchboxHtScale class. // #include "MatchboxHtScale.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.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" using namespace Herwig; MatchboxHtScale::MatchboxHtScale() : theIncludeMT(false), theHTFactor(1.0), theMTFactor(1.0),theScalePtCut(15.*GeV) {} MatchboxHtScale::~MatchboxHtScale() {} IBPtr MatchboxHtScale::clone() const { return new_ptr(*this); } IBPtr MatchboxHtScale::fullclone() const { return new_ptr(*this); } Energy2 MatchboxHtScale::renormalizationScale() const { tcPDVector pd (mePartonData().begin() + 2, mePartonData().end()); vector p (meMomenta().begin() + 2, meMomenta().end()); tcPDPtr t1 = mePartonData()[0]; tcPDPtr t2 = mePartonData()[1]; tcCutsPtr cuts = lastCutsPtr(); theJetFinder->cluster(pd, p, cuts, t1, t2); initWeightFactors(pd,p,theJetFinder); // momentum of the non-jet system LorentzMomentum nonJetMomentum(ZERO,ZERO,ZERO,ZERO); // (weighted) pt of the jet systems Energy ptJetSum = ZERO; bool gotone = false; tcPDVector::const_iterator pdata = pd.begin(); vector::const_iterator mom = p.begin(); for ( ; mom != p.end(); ++pdata, ++mom ) { - if ( theJetFinder->unresolvedMatcher()->check(**pdata)&& - mom->perp()>theScalePtCut){ - //abs(mom->rapidity()+(!lastXCombPtr()->head()?lastXCombPtr()->lastY():lastXCombPtr()->head()->lastY()))<5.01 - gotone = true; - ptJetSum += jetPtWeight(*mom)*mom->perp(); + if ( theJetFinder->unresolvedMatcher()->check(**pdata) ){ + if( mom->perp() > theScalePtCut ){ + gotone = true; + ptJetSum += jetPtWeight(*mom)*mom->perp(); + } } else if ( theIncludeMT ) { nonJetMomentum += *mom; } } if ( !gotone && lastXCombPtr()->willPassCuts() ) throw Exception() << "MatchboxHtScale::renormalizationScale(): " << "No jets could be found. Check your setup." << "\nHint: The HT scale is defined with a PtMin cut on jets. (default:) " << "\n set /Herwig/MatrixElements/Matchbox/ScalesHTScale:JetPtCut 15.*GeV " << Exception::runerror; Energy mtNonJetSum = sqrt(nonJetMomentum.perp2() + nonJetMomentum.m2()); mtNonJetSum *= theMTFactor; ptJetSum *= theHTFactor; return sqr(ptJetSum + mtNonJetSum); } Energy2 MatchboxHtScale::factorizationScale() const { return renormalizationScale(); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void MatchboxHtScale::persistentOutput(PersistentOStream & os) const { os << theJetFinder << theIncludeMT << theHTFactor << theMTFactor << ounit(theScalePtCut,GeV); } void MatchboxHtScale::persistentInput(PersistentIStream & is, int) { is >> theJetFinder >> theIncludeMT >> theHTFactor >> theMTFactor >> iunit(theScalePtCut,GeV); } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct (the class and its base class), and that the constructor // arguments are correct (the class name and the name of the dynamically // loadable library where the class implementation can be found). DescribeClass describeHerwigMatchboxHtScale("Herwig::MatchboxHtScale", "HwMatchboxScales.so"); void MatchboxHtScale::Init() { static ClassDocumentation documentation ("MatchboxHtScale implements scale choices related to transverse momenta."); static Reference interfaceJetFinder ("JetFinder", "A reference to the jet finder.", &MatchboxHtScale::theJetFinder, false, false, true, false, false); static Switch interfaceIncludeMT ("IncludeMT", "Include the transverse masses of the non-jet objects.", &MatchboxHtScale::theIncludeMT, false, false, false); static SwitchOption interfaceIncludeMTYes (interfaceIncludeMT, "Yes", "", true); static SwitchOption interfaceIncludeMTNo (interfaceIncludeMT, "No", "", false); static Parameter interfaceHTFactor ("HTFactor", "A factor to scale the HT contribution.", &MatchboxHtScale::theHTFactor, 1.0, 0.0, 0, false, false, Interface::lowerlim); static Parameter interfaceMTFactor ("MTFactor", "A factor to scale the MT contribution.", &MatchboxHtScale::theMTFactor, 1.0, 0.0, 0, false, false, Interface::lowerlim); static Parameter interfaceScalePtCut ("JetPtCut", "The Pt cut to define jets in the sum.", &MatchboxHtScale::theScalePtCut, GeV, 15.*GeV, 0.*GeV, 0.*GeV, false, false, Interface::lowerlim); } diff --git a/Models/ADD/ADDModelFFGGRVertex.cc b/Models/ADD/ADDModelFFGGRVertex.cc --- a/Models/ADD/ADDModelFFGGRVertex.cc +++ b/Models/ADD/ADDModelFFGGRVertex.cc @@ -1,91 +1,92 @@ // -*- C++ -*- // // ADDModelFFGGRVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 ADDModelFFGGRVertex class. // #include "ADDModelFFGGRVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; using namespace ThePEG; ADDModelFFGGRVertex::ADDModelFFGGRVertex() : couplast_(0.), q2last_(ZERO), kappa_(ZERO), r_(ZERO) { orderInGem(1); orderInGs (1); + colourStructure(ColourStructure::SU3TFUND); } void ADDModelFFGGRVertex::doinit() { for(int ix=1;ix<7;++ix) { addToList(-ix,ix,21,39); } FFVTVertex::doinit(); tcHwADDPtr hwADD=dynamic_ptr_cast(generator()->standardModel()); if(!hwADD) throw Exception() << "Must have ADDModel in ADDModelFFGGRVertex::doinit()" << Exception::runerror; kappa_ = 2./hwADD->MPlanckBar(); r_ = sqr(hwADD->LambdaT())/hwADD->MPlanckBar(); } void ADDModelFFGGRVertex::persistentOutput(PersistentOStream & os) const { os << ounit(kappa_,InvGeV) << ounit(r_,GeV); } void ADDModelFFGGRVertex::persistentInput(PersistentIStream & is, int) { is >> iunit(kappa_,InvGeV) >> iunit(r_,GeV); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigADDModelFFGGRVertex("Herwig::ADDModelFFGGRVertex", "HwADDModel.so"); void ADDModelFFGGRVertex::Init() { static ClassDocumentation documentation ("The ADDModelFFGGRVertexxs class is the implementation" " of the two fermion vector coupling for the ADD model."); } #ifndef NDEBUG void ADDModelFFGGRVertex::setCoupling(Energy2 q2,tcPDPtr aa,tcPDPtr, tcPDPtr cc, tcPDPtr) { #else void ADDModelFFGGRVertex::setCoupling(Energy2 q2,tcPDPtr,tcPDPtr, tcPDPtr, tcPDPtr) { #endif // work out the particles assert(cc->id()==ParticleID::g && abs(aa->id()) <= 6); Complex coup; // overall factor if(q2last_!=q2||couplast_==0.) { couplast_ = strongCoupling(q2); q2last_=q2; } left (1.); right(1.); // set the coupling norm(UnitRemoval::E * kappa_ * couplast_); } Complex ADDModelFFGGRVertex::propagator(int iopt, Energy2 q2,tcPDPtr part, Energy mass, Energy width) { if(part->id()!=ParticleID::Graviton) return VertexBase::propagator(iopt,q2,part,mass,width); else return Complex(4.*Constants::pi*UnitRemoval::E2/sqr(r_)); } diff --git a/Models/ADD/ADDModelFFGRVertex.cc b/Models/ADD/ADDModelFFGRVertex.cc --- a/Models/ADD/ADDModelFFGRVertex.cc +++ b/Models/ADD/ADDModelFFGRVertex.cc @@ -1,73 +1,74 @@ // -*- C++ -*- // // ADDModelFFGRVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 ADDModelFFGRVertex class. // #include "ADDModelFFGRVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; using namespace ThePEG; void ADDModelFFGRVertex::persistentOutput(PersistentOStream & os) const { os << ounit(kappa_,InvGeV) << ounit(r_,GeV); } void ADDModelFFGRVertex::persistentInput(PersistentIStream & is, int) { is >> iunit(kappa_,InvGeV) >> iunit(r_,GeV); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigADDModelFFGRVertex("Herwig::ADDModelFFGRVertex", "HwADDModel.so"); void ADDModelFFGRVertex::Init() { static ClassDocumentation documentation ("The ADDModelFFGRVertex class is the ADDModel calculation" " of the fermion-antifermion-graviton vertex"); } void ADDModelFFGRVertex::setCoupling(Energy2,tcPDPtr,tcPDPtr, tcPDPtr) { norm(Complex(kappa_ * UnitRemoval::E)); } ADDModelFFGRVertex::ADDModelFFGRVertex() : kappa_(ZERO), r_(ZERO) { orderInGem(1); orderInGs (0); + colourStructure(ColourStructure::DELTA); } void ADDModelFFGRVertex::doinit() { // PDG codes for the particles // the quarks for (int ix=1;ix<7;++ix) addToList(-ix,ix,39); // the leptons for (int ix=11;ix<17;++ix) addToList(-ix,ix,39); FFTVertex::doinit(); tcHwADDPtr hwADD=dynamic_ptr_cast(generator()->standardModel()); if(!hwADD) throw Exception() << "Must have ADDModel in ADDModelFFGRVertex::doinit()" << Exception::runerror; kappa_=2./hwADD->MPlanckBar(); r_ = sqr(hwADD->LambdaT())/hwADD->MPlanckBar(); } Complex ADDModelFFGRVertex::propagator(int iopt, Energy2 q2,tcPDPtr part, Energy mass, Energy width) { if(part->id()!=ParticleID::Graviton) return VertexBase::propagator(iopt,q2,part,mass,width); else return Complex(4.*Constants::pi*UnitRemoval::E2/sqr(r_)); } diff --git a/Models/ADD/ADDModelFFWGRVertex.cc b/Models/ADD/ADDModelFFWGRVertex.cc --- a/Models/ADD/ADDModelFFWGRVertex.cc +++ b/Models/ADD/ADDModelFFWGRVertex.cc @@ -1,198 +1,199 @@ // -*- C++ -*- // // ADDModelFFWGRVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 ADDModelFFWGRVertex class. // #include "ADDModelFFWGRVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/Models/StandardModel/StandardCKM.h" using namespace Herwig; using namespace ThePEG; ADDModelFFWGRVertex::ADDModelFFWGRVertex() : charge_(17,0.), gl_(17,0.), gr_(17,0.), ckm_(3,vector(3,0.0)), couplast_(0.), q2last_(ZERO), kappa_(ZERO), r_(ZERO) { orderInGem(2); orderInGs (0); + colourStructure(ColourStructure::DELTA); } void ADDModelFFWGRVertex::doinit() { for(int ix=1;ix<7;++ix) { addToList(-ix,ix,22,39); addToList(-ix,ix,23,39); } for(int ix=11;ix<17;++ix) { addToList(-ix,ix,22,39); addToList(-ix,ix,23,39); } // particles for outgoing W- // quarks for(int ix=1;ix<6;ix+=2) { for(int iy=2;iy<7;iy+=2) { addToList(-ix, iy, -24,39); } } // leptons for(int ix=11;ix<17;ix+=2) { addToList(-ix, ix+1, -24,39); } // particles for outgoing W+ // quarks for(int ix=2;ix<7;ix+=2) { for(int iy=1;iy<6;iy+=2) { addToList(-ix, iy, 24,39); } } // leptons for(int ix=11;ix<17;ix+=2) { addToList(-ix-1, ix, 24,39); } FFVTVertex::doinit(); tcHwADDPtr hwADD=dynamic_ptr_cast(generator()->standardModel()); if(!hwADD) throw Exception() << "Must have ADDModel in ADDModelFFWGRVertex::doinit()" << Exception::runerror; double sw2 = sin2ThetaW(); double fact = 0.25/sqrt(sw2*(1.-sw2)); for(int ix=1;ix<4;++ix) { charge_[2*ix-1] = hwADD->ed(); charge_[2*ix ] = hwADD->eu(); charge_[2*ix+9 ] = hwADD->ee(); charge_[2*ix+10] = hwADD->enu(); gl_[2*ix-1] = fact*(hwADD->vd() + hwADD->ad() ); gl_[2*ix ] = fact*(hwADD->vu() + hwADD->au() ); gl_[2*ix+9 ] = fact*(hwADD->ve() + hwADD->ae() ); gl_[2*ix+10] = fact*(hwADD->vnu() + hwADD->anu()); gr_[2*ix-1] = fact*(hwADD->vd() - hwADD->ad() ); gr_[2*ix ] = fact*(hwADD->vu() - hwADD->au() ); gr_[2*ix+9 ] = fact*(hwADD->ve() - hwADD->ae() ); gr_[2*ix+10] = fact*(hwADD->vnu() - hwADD->anu()); } kappa_=2./hwADD->MPlanckBar(); r_ = sqr(hwADD->LambdaT())/hwADD->MPlanckBar(); Ptr::transient_pointer CKM = generator()->standardModel()->CKM(); // cast the CKM object to the HERWIG one ThePEG::Ptr::transient_const_pointer hwCKM = ThePEG::dynamic_ptr_cast< ThePEG::Ptr:: transient_const_pointer>(CKM); if(hwCKM) { vector< vector > CKM; CKM = hwCKM->getUnsquaredMatrix(generator()->standardModel()->families()); for(unsigned int ix=0;ix<3;++ix) { for(unsigned int iy=0;iy<3;++iy) { ckm_[ix][iy]=CKM[ix][iy]; } } } else { throw Exception() << "Must have access to the Herwig::StandardCKM object" << "for the CKM matrix in SMFFWVertex::doinit()" << Exception::runerror; } } void ADDModelFFWGRVertex::persistentOutput(PersistentOStream & os) const { os << charge_ << gl_ << gr_ << ounit(kappa_,InvGeV) << ckm_ << ounit(r_,GeV); } void ADDModelFFWGRVertex::persistentInput(PersistentIStream & is, int) { is >> charge_ >> gl_ >> gr_ >> iunit(kappa_,InvGeV) >> ckm_ >> iunit(r_,GeV); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigADDModelFFWGRVertex("Herwig::ADDModelFFWGRVertex", "HwADDModel.so"); void ADDModelFFWGRVertex::Init() { static ClassDocumentation documentation ("The ADDModelFFWGRVertexxs class is the implementation" " of the two fermion vector coupling for the ADD model."); } void ADDModelFFWGRVertex::setCoupling(Energy2 q2,tcPDPtr aa,tcPDPtr bb, tcPDPtr cc, tcPDPtr) { // work out the particles int iferm= abs(aa->id()); int ibos = abs(cc->id()); Complex coup; // overall factor assert( ibos >= 22 && ibos <= 24 ); if( q2last_ != q2 || couplast_ == 0. ) { couplast_ = electroMagneticCoupling(q2); q2last_ = q2; } // photon if(ibos==22) { // alpha coup = UnitRemoval::E * kappa_ * couplast_; // _charge of particle assert((iferm>=1 && iferm<=6)||(iferm>=11 &&iferm<=16)); coup *= charge_[iferm]; left (1.); right(1.); } // Z boson else if(ibos==23) { coup = UnitRemoval::E * kappa_ * couplast_; // _charge of particle assert((iferm>=1 && iferm<=6)||(iferm>=11 &&iferm<=16)); left (gl_[iferm]); right(gr_[iferm]); } else if(ibos==24) { coup = UnitRemoval::E * kappa_ * couplast_ * sqrt(0.5) / sqrt(sin2ThetaW()); // the left and right couplings int iferm=abs(aa->id()); int ianti=abs(bb->id()); // quarks if(iferm>=1 && iferm <=6) { int iu,id; // up type first if(iferm%2==0) { iu = iferm/2; id = (ianti+1)/2; } // down type first else { iu = ianti/2; id = (iferm+1)/2; } assert( iu>=1 && iu<=3 && id>=1 && id<=3); left(ckm_[iu-1][id-1]); right(0.); } // leptons else if(iferm>=11 && iferm <=16) { left(1.); right(0.); } else assert(false); } // set the coupling norm(coup); } Complex ADDModelFFWGRVertex::propagator(int iopt, Energy2 q2,tcPDPtr part, Energy mass, Energy width) { if(part->id()!=ParticleID::Graviton) return VertexBase::propagator(iopt,q2,part,mass,width); else return Complex(4.*Constants::pi*UnitRemoval::E2/sqr(r_)); } diff --git a/Models/ADD/ADDModelGGGGRVertex.cc b/Models/ADD/ADDModelGGGGRVertex.cc --- a/Models/ADD/ADDModelGGGGRVertex.cc +++ b/Models/ADD/ADDModelGGGGRVertex.cc @@ -1,84 +1,85 @@ // -*- C++ -*- // // ADDModelGGGGRVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 ADDModelGGGGRVertex class. // #include "ADDModelGGGGRVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; using namespace ThePEG; ADDModelGGGGRVertex::ADDModelGGGGRVertex() : kappa_(ZERO), r_(ZERO), couplast_(0.), q2last_(ZERO) { orderInGem(1); orderInGs (1); + colourStructure(ColourStructure::SU3F); } void ADDModelGGGGRVertex::doinit() { addToList(21, 21, 21, 39); VVVTVertex::doinit(); // set the graviton coupling tcHwADDPtr hwADD=dynamic_ptr_cast(generator()->standardModel()); if(!hwADD) throw Exception() << "Must have ADDModel in ADDModelGGGGRVertex::doinit()" << Exception::runerror; kappa_=2./hwADD->MPlanckBar(); r_ = sqr(hwADD->LambdaT())/hwADD->MPlanckBar(); } void ADDModelGGGGRVertex::persistentOutput(PersistentOStream & os) const { os << ounit(kappa_,InvGeV) << ounit(r_,GeV); } void ADDModelGGGGRVertex::persistentInput(PersistentIStream & is, int) { is >> iunit(kappa_,InvGeV) >> iunit(r_,GeV); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigADDModelGGGGRVertex("Herwig::ADDModelGGGGRVertex", "HwADDModel.so"); void ADDModelGGGGRVertex::Init() { static ClassDocumentation documentation ("The ADDModelGGGGRVertex class is the four point coupling" " of three vector bosons and a graviton in the Randell-Sundrum model."); } #ifndef NDEBUG void ADDModelGGGGRVertex::setCoupling(Energy2 q2,tcPDPtr a,tcPDPtr b, tcPDPtr c, tcPDPtr) { #else void ADDModelGGGGRVertex::setCoupling(Energy2 q2,tcPDPtr,tcPDPtr, tcPDPtr, tcPDPtr) { #endif assert(a->id() == ParticleID::g && b->id() == ParticleID::g && c->id() == ParticleID::g); if(q2!=q2last_||couplast_==0.) { couplast_ = strongCoupling(q2); q2last_=q2; } norm(Complex(couplast_*kappa_*UnitRemoval::E)); } Complex ADDModelGGGGRVertex::propagator(int iopt, Energy2 q2,tcPDPtr part, Energy mass, Energy width) { if(part->id()!=ParticleID::Graviton) return VertexBase::propagator(iopt,q2,part,mass,width); else return Complex(4.*Constants::pi*UnitRemoval::E2/sqr(r_)); } diff --git a/Models/ADD/ADDModelSSGRVertex.cc b/Models/ADD/ADDModelSSGRVertex.cc --- a/Models/ADD/ADDModelSSGRVertex.cc +++ b/Models/ADD/ADDModelSSGRVertex.cc @@ -1,69 +1,70 @@ // -*- C++ -*- // // ADDModelSSGRVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 ADDModelSSGRVertex class. // #include "ADDModelSSGRVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; using namespace ThePEG; ADDModelSSGRVertex::ADDModelSSGRVertex() : kappa_(ZERO), r_(ZERO) { orderInGem(1); orderInGs (0); + colourStructure(ColourStructure::SINGLET); } void ADDModelSSGRVertex::doinit() { addToList(25,25,39); SSTVertex::doinit(); tcHwADDPtr hwADD=dynamic_ptr_cast(generator()->standardModel()); if(!hwADD) throw Exception() << "Must have ADDModel in ADDModelSSGRVertex::doinit()" << Exception::runerror; kappa_=2./hwADD->MPlanckBar(); r_ = sqr(hwADD->LambdaT())/hwADD->MPlanckBar(); } void ADDModelSSGRVertex::persistentOutput(PersistentOStream & os) const { os << ounit(kappa_,InvGeV) << ounit(r_,GeV); } void ADDModelSSGRVertex::persistentInput(PersistentIStream & is, int) { is >> iunit(kappa_,InvGeV) >> iunit(r_,GeV); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigADDModelSSGRVertex("Herwig::ADDModelSSGRVertex", "HwADDModel.so"); void ADDModelSSGRVertex::Init() { static ClassDocumentation documentation ("The ADDModelSSGRVertex class is the implementation of" " the ADDModel scalar-scalar-graviton vertex"); } void ADDModelSSGRVertex::setCoupling(Energy2,tcPDPtr,tcPDPtr, tcPDPtr) { norm(Complex(kappa_ * UnitRemoval::E)); } Complex ADDModelSSGRVertex::propagator(int iopt, Energy2 q2,tcPDPtr part, Energy mass, Energy width) { if(part->id()!=ParticleID::Graviton) return VertexBase::propagator(iopt,q2,part,mass,width); else return Complex(4.*Constants::pi*UnitRemoval::E2/sqr(r_)); } diff --git a/Models/ADD/ADDModelVVGRVertex.cc b/Models/ADD/ADDModelVVGRVertex.cc --- a/Models/ADD/ADDModelVVGRVertex.cc +++ b/Models/ADD/ADDModelVVGRVertex.cc @@ -1,72 +1,73 @@ // -*- C++ -*- // // ADDModelVVGRVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 ADDModelVVGRVertex class. // #include "ADDModelVVGRVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; using namespace ThePEG; void ADDModelVVGRVertex::persistentOutput(PersistentOStream & os) const { os << ounit(kappa_,InvGeV) << ounit(r_,GeV); } void ADDModelVVGRVertex::persistentInput(PersistentIStream & is, int) { is >> iunit(kappa_,InvGeV) >> iunit(r_,GeV); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigADDModelVVGRVertex("Herwig::ADDModelVVGRVertex", "HwADDModel.so"); void ADDModelVVGRVertex::Init() { static ClassDocumentation documentation ("The ADDModelVVGRVertex class is the implementation" " of the ADDModel vector-vector-graviton vertex"); } void ADDModelVVGRVertex::setCoupling(Energy2,tcPDPtr,tcPDPtr, tcPDPtr) { norm(Complex(UnitRemoval::E * kappa_)); } ADDModelVVGRVertex::ADDModelVVGRVertex() : kappa_(ZERO), r_(ZERO) { orderInGem(1); orderInGs (0); + colourStructure(ColourStructure::DELTA); } void ADDModelVVGRVertex::doinit() { addToList(23,23,39); addToList(22,22,39); addToList(24,-24,39); addToList(21,21,39); VVTVertex::doinit(); tcHwADDPtr hwADD=dynamic_ptr_cast(generator()->standardModel()); if(!hwADD) throw Exception() << "Must be ADDModel in ADDModelVVGRVertex::doinit()" << Exception::runerror; kappa_=2./hwADD->MPlanckBar(); r_ = sqr(hwADD->LambdaT())/hwADD->MPlanckBar(); } Complex ADDModelVVGRVertex::propagator(int iopt, Energy2 q2,tcPDPtr part, Energy mass, Energy width) { if(part->id()!=ParticleID::Graviton) return VertexBase::propagator(iopt,q2,part,mass,width); else return Complex(4.*Constants::pi*UnitRemoval::E2/sqr(r_)); } diff --git a/Models/ADD/ADDModelWWWGRVertex.cc b/Models/ADD/ADDModelWWWGRVertex.cc --- a/Models/ADD/ADDModelWWWGRVertex.cc +++ b/Models/ADD/ADDModelWWWGRVertex.cc @@ -1,106 +1,107 @@ // -*- C++ -*- // // ADDModelWWWGRVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 ADDModelWWWGRVertex class. // #include "ADDModelWWWGRVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; using namespace ThePEG; ADDModelWWWGRVertex::ADDModelWWWGRVertex() : kappa_(ZERO), r_(ZERO), couplast_(0.), q2last_(ZERO), zfact_(0.) { // order in the couplings orderInGem(2); orderInGs (0); + colourStructure(ColourStructure::SINGLET); } void ADDModelWWWGRVertex::doinit() { addToList(24,-24, 22, 39); addToList(24,-24, 23, 39); VVVTVertex::doinit(); zfact_ = sqrt((1.-sin2ThetaW())/sin2ThetaW()); // set the graviton coupling tcHwADDPtr hwADD=dynamic_ptr_cast(generator()->standardModel()); if(!hwADD) throw Exception() << "Must have ADDModel in ADDModelWWWGRVertex::doinit()" << Exception::runerror; kappa_=2./hwADD->MPlanckBar(); r_ = sqr(hwADD->LambdaT())/hwADD->MPlanckBar(); } void ADDModelWWWGRVertex::persistentOutput(PersistentOStream & os) const { os << ounit(kappa_,InvGeV) << zfact_ << ounit(r_,GeV); } void ADDModelWWWGRVertex::persistentInput(PersistentIStream & is, int) { is >> iunit(kappa_,InvGeV) >> zfact_ >> iunit(r_,GeV); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigADDModelWWWGRVertex("Herwig::ADDModelWWWGRVertex", "HwADDModel.so"); void ADDModelWWWGRVertex::Init() { static ClassDocumentation documentation ("The ADDModelWWWGRVertex class is the four point coupling" " of three vector bosons and a graviton in the Randell-Sundrum model."); } // couplings for the WWWGR vertex void ADDModelWWWGRVertex::setCoupling(Energy2 q2,tcPDPtr a,tcPDPtr b, tcPDPtr c, tcPDPtr) { int ida=a->id(); int idb=b->id(); int idc=c->id(); // first the overall normalisation if(q2!=q2last_||couplast_==0.) { couplast_ = electroMagneticCoupling(q2); q2last_=q2; } // W- W+ photon and cylic perms if((ida==-24 && idb== 24 && idc== 22) || (ida== 22 && idb==-24 && idc== 24) || (ida== 24 && idb== 22 && idc==-24) ) norm(Complex(couplast_*kappa_*UnitRemoval::E)); // W+ W- photon (anticylic perms of above) else if((ida== 24 && idb==-24 && idc== 22) || (ida== 22 && idb== 24 && idc==-24) || (ida==-24 && idb== 22 && idc== 24) ) norm(-Complex(couplast_*kappa_*UnitRemoval::E)); // W- W+ Z and cylic perms else if((ida==-24 && idb== 24 && idc== 23) || (ida== 23 && idb==-24 && idc== 24) || (ida== 24 && idb== 23 && idc==-24) ) norm(Complex(couplast_*zfact_*kappa_*UnitRemoval::E)); // W+ W- Z (anticylic perms of above) else if((ida== 24 && idb==-24 && idc== 23) || (ida== 23 && idb== 24 && idc==-24) || (ida==-24 && idb== 23 && idc== 24) ) norm(-Complex(couplast_*zfact_*kappa_*UnitRemoval::E)); else assert(false); } Complex ADDModelWWWGRVertex::propagator(int iopt, Energy2 q2,tcPDPtr part, Energy mass, Energy width) { if(part->id()!=ParticleID::Graviton) return VertexBase::propagator(iopt,q2,part,mass,width); else return Complex(4.*Constants::pi*UnitRemoval::E2/sqr(r_)); } diff --git a/Models/Feynrules/python/ufo2herwig b/Models/Feynrules/python/ufo2herwig --- a/Models/Feynrules/python/ufo2herwig +++ b/Models/Feynrules/python/ufo2herwig @@ -1,387 +1,437 @@ #! /usr/bin/env python from __future__ import division import os, sys, pprint, argparse, re,copy from string import strip, Template # add path to the ufo conversion modules modulepath = os.path.join("@PKGLIBDIR@",'python') sys.path.append(modulepath) from ufo2peg import * # set up the option parser for command line input parser = argparse.ArgumentParser( description='Create Herwig model files from Feynrules UFO input.' ) parser.add_argument( 'ufodir', metavar='UFO_directory', help='the UFO model directory' ) parser.add_argument( '-v', '--verbose', action="store_true", help="print verbose output" ) parser.add_argument( '-n','--name', default="FRModel", help="set custom nametag for the model" ) parser.add_argument( '--ignore-skipped', action="store_true", help="ignore skipped vertices and produce output anyway" ) parser.add_argument( '--split-model', action="store_true", help="Split the model file into pieces to improve compilation for models with many parameters" ) parser.add_argument( '--no-generic-loop-vertices', action="store_true", help="Don't include the automatically generated generic loop vertices for h->gg and h->gamma gamma" ) parser.add_argument( + '--include-generic', + action="store_true", + help="Include support for generic spin structures (still experimental)" +) +parser.add_argument( + '--use-generic-for-tensors', + action="store_true", + help="Use the generic machinery for all tensor vertices (debugging only)" +) +parser.add_argument( '--forbidden-particle-name', action="append", default=["eta","phi"], help="Add particle names not allowed as names in UFO models to avoid conflicts with"+\ "Herwig internal particles, names will have _UFO appended" ) # get the arguments args = parser.parse_args() # import the model import imp path,mod = os.path.split(os.path.abspath(args.ufodir)) FR = imp.load_module(mod,*imp.find_module(mod,[path])) ################################################## ################################################## # get the Model name from the arguments modelname = args.name libname = modelname + '.so' # define arrays and variables #allplist = "" parmdecls = [] parmgetters = [] parmconstr = [] doinit = [] paramstoreplace_ = [] paramstoreplace_expressions_ = [] # get external parameters for printing parmsubs = dict( [ (p.name, p.value) for p in FR.all_parameters if p.nature == 'external' ] ) # evaluate python cmath def evaluate(x): import cmath return eval(x, {'cmath':cmath, 'complexconjugate':FR.function_library.complexconjugate}, parmsubs) ## get internal params into arrays internal = ( p for p in FR.all_parameters if p.nature == 'internal' ) #paramstoreplaceEW_ = [] #paramstoreplaceEW_expressions_ = [] # calculate internal parameters for p in internal: parmsubs.update( { p.name : evaluate(p.value) } ) # if 'aS' in p.value and p.name != 'aS': # paramstoreplace_.append(p.name) # paramstoreplace_expressions_.append(p.value) # if 'aEWM1' in p.value and p.name != 'aEWM1': # paramstoreplaceEW_.append(p.name) # paramstoreplaceEW_expressions_.append(p.value) parmvalues=copy.copy(parmsubs) # more arrays used for substitution in templates paramsforstream = [] parmmodelconstr = [] # loop over parameters and fill in template stuff according to internal/external and complex/real # WARNING: Complex external parameter input not tested! if args.verbose: print 'verbose mode on: printing all parameters' print '-'*60 paramsstuff = ('name', 'expression', 'default value', 'nature') pprint.pprint(paramsstuff) interfacedecl_T = """\ static Parameter<{modelname}, {type}> interface{pname} ("{pname}", "The interface for parameter {pname}", &{modelname}::{pname}_, {value}, 0, 0, false, false, Interface::nolimits); """ +# sort out the couplings +couplingDefns = { "QED" : 99, "QCD" : 99 } +try : + for coupling in FR.all_orders: + name = coupling.name.upper() + couplingDefns[name]= coupling.expansion_order +except: + for coupling in FR.all_couplings: + for name,value in coupling.order.iteritems(): + if(name not in couplingDefns) : + couplingDefns[name]=99 + +# sort out the particles + massnames = {} widthnames = {} for particle in FR.all_particles: # skip ghosts and goldstones if(isGhost(particle) or isGoldstone(particle)) : continue if particle.mass != 'ZERO': massnames[particle.mass] = abs(particle.pdg_code) if particle.width != 'ZERO': widthnames[particle.width] = abs(particle.pdg_code) interfaceDecls = [] modelparameters = {} for p in FR.all_parameters: value = parmsubs[p.name] if p.type == 'real': assert( value.imag < 1.0e-16 ) value = value.real if p.nature == 'external': if p not in massnames and p not in widthnames: interfaceDecls.append( interfacedecl_T.format(modelname=modelname, pname=p.name, value=value, type=typemap(p.type)) ) else: interfaceDecls.append('\n// no interface for %s. Use particle definition instead.\n' % p.name) if hasattr(p,'lhablock'): lhalabel = '{lhablock}_{lhacode}'.format( lhablock=p.lhablock.upper(), lhacode='_'.join(map(str,p.lhacode)) ) if p not in massnames and p not in widthnames: parmmodelconstr.append('set %s:%s ${%s}' % (modelname, p.name, lhalabel)) else: parmmodelconstr.append('# %s is taken from the particle setup' % p.name) modelparameters[lhalabel] = value parmsubs[p.name] = lhalabel else: if p not in massnames and p not in widthnames: parmmodelconstr.append('set %s:%s %s' % (modelname, p.name, value)) else: parmmodelconstr.append('# %s is taken from the particle setup' % p.name) parmsubs[p.name] = value if p not in massnames and p not in widthnames: parmconstr.append('%s_(%s)' % (p.name, value)) else: parmconstr.append('%s_()' % p.name) else : parmconstr.append('%s_()' % p.name) parmsubs[p.name] = value elif p.type == 'complex': value = complex(value) if p.nature == 'external': # # TODO: WE DO NOT HAVE COMPLEX INTERFACES IN THEPEG (yet?) # # interfaceDecls.append( # interfacedecl_T.format(modelname=modelname, # pname=p.name, # value='Complex(%s,%s)'%(value.real,value.imag), # type=typemap(p.type)) # ) # # parmmodelconstr.append('set %s:%s (%s,%s)' % (modelname, p.name, value.real, value.imag)) parmconstr.append('%s_(%s,%s)' % (p.name, value.real, value.imag)) else : parmconstr.append('%s_(%s,%s)' % (p.name, 0.,0.)) parmsubs[p.name] = value else: raise Exception('Unknown data type "%s".' % p.type) parmdecls.append(' %s %s_;' % (typemap(p.type), p.name)) parmgetters.append(' %s %s() const { return %s_; }' % (typemap(p.type),p.name, p.name)) paramsforstream.append('%s_' % p.name) expression, symbols = 'return %s_' % p.name, None if p.nature != 'external': expression, symbols = py2cpp(p.value) text = add_brackets(expression, symbols) text=text.replace('()()','()') doinit.append(' %s_ = %s;' % (p.name, text) ) if p in massnames: doinit.append(' resetMass(%s,%s_ * GeV);' % (massnames[p], p.name) ) elif p in widthnames: doinit.append(' getParticleData(%s)->width(%s_ * GeV);' % (widthnames[p], p.name) ) doinit.append(' getParticleData(%s)->cTau (%s_ == 0.0 ? Length() : hbarc/(%s_*GeV));' % (widthnames[p], p.name, p.name) ) doinit.append(' getParticleData(%s)->widthCut(10. * %s_ * GeV);' % (widthnames[p], p.name) ) elif p.nature == 'external': if p in massnames: doinit.append(' %s_ = getParticleData(%s)->mass() / GeV;' % (p.name, massnames[p]) ) elif p in widthnames: doinit.append(' %s_ = getParticleData(%s)->width() / GeV;' % (p.name, widthnames[p]) ) if args.verbose: pprint.pprint((p.name,p.value, value, p.nature)) pcwriter = ParamCardWriter(FR.all_parameters) paramcard_output = '\n'.join(pcwriter.output) ### special treatment # if p.name == 'aS': # expression = '0.25 * sqr(strongCoupling(q2)) / Constants::pi' # elif p.name == 'aEWM1': # expression = '4.0 * Constants::pi / sqr(electroMagneticCoupling(q2))' # elif p.name == 'Gf': # expression = 'generator()->standardModel()->fermiConstant() * GeV2' paramconstructor=': ' for ncount in range(0,len(parmconstr)) : paramconstructor += parmconstr[ncount] if(ncount != len(parmconstr) -1) : paramconstructor += ',' if(ncount%5 == 0 ) : paramconstructor += "\n" paramout="" paramin ="" for ncount in range(0,len(paramsforstream)) : if(ncount !=0 ) : paramout += "<< " + paramsforstream[ncount] paramin += ">> " + paramsforstream[ncount] else : paramout += paramsforstream[ncount] paramin += paramsforstream[ncount] if(ncount%5 == 0 ) : paramout += "\n" paramin += "\n" parmtextsubs = { 'parmgetters' : '\n'.join(parmgetters), 'parmdecls' : '\n'.join(parmdecls), 'parmconstr' : paramconstructor, 'getters' : '', 'decls' : '', 'addVertex' : '', 'doinit' : '\n'.join(doinit), 'ostream' : paramout, 'istream' : paramin , 'refs' : '', 'parmextinter': ''.join(interfaceDecls), 'ModelName': modelname, 'calcfunctions': '', 'param_card_data': paramcard_output } ################################################## ################################################## ################################################## # set up the conversion of the vertices -vertexConverter = VertexConverter(FR,parmvalues) +vertexConverter = VertexConverter(FR,parmvalues,couplingDefns) vertexConverter.readArgs(args) # convert the vertices vertexConverter.convert() +cdefs="" +couplingOrders="" +ncount=2 +for name,value in couplingDefns.iteritems() : + if(name=="QED") : + couplingOrders+=" setCouplings(\"%s\",make_pair(%s,%s));\n" %(name,1,value) + elif (name=="QCD") : + couplingOrders+=" setCouplings(\"%s\",make_pair(%s,%s));\n" %(name,2,value) + else : + ncount+=1 + cdefs +=" const T %s = %s;\n" % (name,ncount) + couplingOrders+=" setCouplings(\"%s\",make_pair(%s,%s));\n" % (name,ncount,value) +# coupling definitions +couplingTemplate= """\ +namespace ThePEG {{ +namespace Helicity {{ +namespace CouplingType {{ + typedef unsigned T; + /** + * Enums for couplings + */ +{coup} +}} +}} +}} +""" +if(cdefs!="") : + cdefs = couplingTemplate.format(coup=cdefs) +parmtextsubs['couplings'] = cdefs +parmtextsubs['couplingOrders'] = couplingOrders -################################################## -################################################## -################################################## - - +# particles plist, names = thepeg_particles(FR,parmsubs,modelname,modelparameters,args.forbidden_particle_name) particlelist = [ "# insert HPConstructor:Outgoing 0 /Herwig/{n}/Particles/{p}".format(n=modelname,p=p) for p in names ] # make the first one active to have something runnable in the example .in file particlelist[0] = particlelist[0][2:] particlelist = '\n'.join(particlelist) modelfilesubs = { 'plist' : plist, 'vlist' : vertexConverter.get_vertices(libname), 'setcouplings': '\n'.join(parmmodelconstr), 'ModelName': modelname } # write the files from templates according to the above subs if vertexConverter.should_print(): MODEL_HWIN = getTemplate('LHC-FR.in') if(not args.split_model) : MODEL_CC = [getTemplate('Model.cc')] else : MODEL_EXTRA_CC=getTemplate('Model6.cc') extra_names=[] extra_calcs=[] parmtextsubs['doinit']="" for i in range(0,len(doinit)) : if( i%20 == 0 ) : function_name = "initCalc" +str(int(i/20)) parmtextsubs['doinit'] += function_name +"();\n" parmtextsubs['calcfunctions'] += "void " + function_name + "();\n" extra_names.append(function_name) extra_calcs.append("") extra_calcs[-1] += doinit[i] + "\n" for i in range(0,len(extra_names)) : ccname = '%s_extra_%s.cc' % (modelname,i) writeFile( ccname, MODEL_EXTRA_CC.substitute({'ModelName' : modelname, 'functionName' : extra_names[i], 'functionCalcs' : extra_calcs[i] }) ) MODEL_CC = [getTemplate('Model1.cc'),getTemplate('Model2.cc'),getTemplate('Model3.cc'), getTemplate('Model4.cc'),getTemplate('Model5.cc')] MODEL_H = getTemplate('Model.h') print 'LENGTH',len(MODEL_CC) MODELINFILE = getTemplate('FR.model') writeFile( 'LHC-%s.in' % modelname, MODEL_HWIN.substitute({ 'ModelName' : modelname, 'Particles' : particlelist }) ) modeltemplate = Template( MODELINFILE.substitute(modelfilesubs) ) writeFile( '%s.h' % modelname, MODEL_H.substitute(parmtextsubs) ) for i in range(0,len(MODEL_CC)) : if(len(MODEL_CC)==1) : ccname = '%s.cc' % modelname else : ccname = '%s.cc' % (modelname + str(i)) writeFile( ccname, MODEL_CC[i].substitute(parmtextsubs) ) writeFile( modelname +'.template', modeltemplate.template ) writeFile( modelname +'.model', modeltemplate.substitute( modelparameters ) ) # copy the Makefile-FR to current directory, # replace with the modelname for compilation with open(os.path.join(modulepath,'Makefile-FR'),'r') as orig: with open('Makefile','w') as dest: dest.write(orig.read().replace("FeynrulesModel.so", libname)) print 'finished generating model:\t', modelname print 'model directory:\t\t', args.ufodir print 'generated:\t\t\t', len(FR.all_vertices), 'vertices' print '='*60 print 'library:\t\t\t', libname print 'input file:\t\t\t', 'LHC-' + modelname +'.in' print 'model file:\t\t\t', modelname +'.model' print '='*60 print """\ To complete the installation, compile by typing "make". An example input file is provided as LHC-FRModel.in, you'll need to change the required particles in there. """ print 'DONE!' print '='*60 diff --git a/Models/Feynrules/python/ufo2peg/GeneralVertex_class.template b/Models/Feynrules/python/ufo2peg/GeneralVertex_class.template new file mode 100644 --- /dev/null +++ b/Models/Feynrules/python/ufo2peg/GeneralVertex_class.template @@ -0,0 +1,41 @@ +class ${ModelName}${classname}: public Abstract${lorentztag}Vertex { + public: + ${ModelName}${classname}() { + colourStructure(ColourStructure::${colourStructure}); + ${addToPlist} + } + + ${evaldefs} + + void persistentOutput(PersistentOStream & os) const { os << model_; } + void persistentInput(PersistentIStream & is, int) { is >> model_; } + + virtual void setCoupling(Energy2, tcPDPtr, + tcPDPtr, tcPDPtr) {assert(false);} + + virtual void setCoupling(Energy2,tcPDPtr,tcPDPtr,tcPDPtr, + tcPDPtr) {assert(false);} + + protected: + + IBPtr clone() const { return new_ptr(*this); } + IBPtr fullclone() const { return new_ptr(*this); } + void doinit() { + model_ = dynamic_ptr_cast + (generator()->standardModel()); + assert(model_); + ${couplingOrders} + Abstract${lorentztag}Vertex::doinit(); + } + + private: + + ${ModelName}${classname} & operator=(const ${ModelName}${classname} &); + + tcHw${ModelName}Ptr model_; +}; +DescribeClass<${ModelName}${classname},Helicity::Abstract${lorentztag}Vertex> +describeHerwig${ModelName}${classname}("Herwig::${ModelName}${classname}", + "${ModelName}.so"); + +${evalimpls} diff --git a/Models/Feynrules/python/ufo2peg/Model.cc.template b/Models/Feynrules/python/ufo2peg/Model.cc.template --- a/Models/Feynrules/python/ufo2peg/Model.cc.template +++ b/Models/Feynrules/python/ufo2peg/Model.cc.template @@ -1,93 +1,94 @@ // -*- C++ -*- // // ${ModelName}.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2007 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the ${ModelName} class. // #include "${ModelName}.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Helicity/Vertex/VertexBase.h" #include "ThePEG/Utilities/DescribeClass.h" #include //#include "Herwig/Models/General/ModelGenerator.h" using namespace ThePEG; using namespace Herwig; ${ModelName}::${ModelName}() ${parmconstr} {} IBPtr ${ModelName}::clone() const { return new_ptr(*this); } IBPtr ${ModelName}::fullclone() const { return new_ptr(*this); } void ${ModelName}::doinit() { ${doinit} BSMModel::doinit(); ${addVertex} writeParamCard(); +${couplingOrders} } void ${ModelName}::doinitrun() { BSMModel::doinitrun(); writeParamCard(); } void ${ModelName}::persistentOutput(PersistentOStream & os) const { os << ${ostream} ; } void ${ModelName}::persistentInput(PersistentIStream & is, int) { is >> ${istream} ; } void ${ModelName}::writeParamCard() const { ofstream card("param_card.dat"); card << "#####################################################\n" << "## DO NOT EDIT - GENERATED BY HERWIG UFO CONVERTER ##\n" << "#####################################################\n\n"; card ${param_card_data} << '\n'; card.close(); } // Static variable needed for the type description system in ThePEG. DescribeClass<${ModelName},BSMModel> describeThePEG${ModelName}("Herwig::${ModelName}", "${ModelName}.so"); void ${ModelName}::Init() { ${refs} static ClassDocumentation<${ModelName}> documentation ("The ${ModelName} class inherits from BSMModel" "and supplies additional couplings and access to the ${ModelName}" "vertices for helicity amplitude calculations" ); ${parmextinter} } diff --git a/Models/Feynrules/python/ufo2peg/Model.h.template b/Models/Feynrules/python/ufo2peg/Model.h.template --- a/Models/Feynrules/python/ufo2peg/Model.h.template +++ b/Models/Feynrules/python/ufo2peg/Model.h.template @@ -1,148 +1,150 @@ // -*- C++ -*- // // ${ModelName}.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2013 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_${ModelName}_H #define HERWIG_${ModelName}_H // This is the declaration of the ${ModelName} class. #include "Herwig/Models/General/BSMModel.h" +${couplings} + namespace Herwig { using namespace ThePEG; using ThePEG::Constants::pi; const Complex ii = Complex(0,1); /** \ingroup Models * * This is the Herwig ${ModelName} class which inherits from ThePEG * FeynRules Model class and implements additional FeynRules Model couplings, * access to vertices for helicity amplitude calculations etc. * * @see BSMModel */ class ${ModelName}: public BSMModel { public: /// Default constructor ${ModelName}(); 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); //@} /** * Write out a UFO param_card.dat that matches the configured values */ void writeParamCard() const; /** * Standard Init function used to initialize the interfaces. */ static void Init(); protected: virtual bool registerDefaultVertices() const { return false; } public: /** * Pointers to the objects handling the vertices. */ //@{ ${getters} ${parmgetters} //@} 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: /** * Initialize this object after the setup phase before saving and * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} private: /** * Private and non-existent assignment operator. */ ${ModelName} & operator=(const ${ModelName} &); private: /** * Helper functions for doinit */ //@{ ${calcfunctions} //@} private: /** * Pointers to the vertices for ${ModelName} Model helicity amplitude * calculations. */ //@{ ${decls} ${parmdecls} //@} }; } namespace ThePEG { ThePEG_DECLARE_POINTERS(Herwig::${ModelName},Hw${ModelName}Ptr); } #endif /* HERWIG_${ModelName}_H */ diff --git a/Models/Feynrules/python/ufo2peg/Vertex_class.template b/Models/Feynrules/python/ufo2peg/Vertex_class.template --- a/Models/Feynrules/python/ufo2peg/Vertex_class.template +++ b/Models/Feynrules/python/ufo2peg/Vertex_class.template @@ -1,43 +1,42 @@ class ${ModelName}${classname}: public ${lorentztag}Vertex { public: ${ModelName}${classname}() { ${header} + colourStructure(ColourStructure::${colourStructure}); ${addToPlist} } void setCoupling(Energy2 ${couplingptrs}) { ${symbolrefs} ${prepend} // getParams(q2); ${norm} ${left} ${right} ${append} } void persistentOutput(PersistentOStream & os) const { os << model_; } void persistentInput(PersistentIStream & is, int) { is >> model_; } // static void Init(); protected: IBPtr clone() const { return new_ptr(*this); } IBPtr fullclone() const { return new_ptr(*this); } void doinit() { model_ = dynamic_ptr_cast (generator()->standardModel()); assert(model_); // getParams(q2); ${parameters} - ${setCouplings} - orderInGem(${qedorder}); - orderInGs(${qcdorder}); + ${couplingOrders} ${lorentztag}Vertex::doinit(); } // void getParams(Energy2); private: ${ModelName}${classname} & operator=(const ${ModelName}${classname} &); // Complex leftval, rightval, normval; tcHw${ModelName}Ptr model_; }; DescribeClass<${ModelName}${classname},Helicity::${lorentztag}Vertex> describeHerwig${ModelName}${classname}("Herwig::${ModelName}${classname}", "${ModelName}.so"); // void ${ModelName}${classname}::getParams(Energy2 ) { // } diff --git a/Models/Feynrules/python/ufo2peg/check_lorentz.py b/Models/Feynrules/python/ufo2peg/check_lorentz.py --- a/Models/Feynrules/python/ufo2peg/check_lorentz.py +++ b/Models/Feynrules/python/ufo2peg/check_lorentz.py @@ -1,864 +1,864 @@ -import itertools,cmath,re,sys +import itertools,cmath,re from .helpers import SkipThisVertex,extractAntiSymmetricIndices from .converter import py2cpp from .lorentzparser import parse_lorentz +import string,re def compare(a,b) : num=abs(a-b) den=abs(a+b) if(den == 0. and 1e-10) : return True return num/den<1e-10 def evaluate(x,model,parmsubs): import cmath return eval(x, {'cmath':cmath, 'complexconjugate':model.function_library.complexconjugate}, parmsubs) -# ordering for EW VVV vertices +# ordering for EW VVV vertices (ordering not an issue as all same spin) def VVVordering(vertex) : pattern = "if((p1->id()==%s&&p2->id()==%s&&p3->id()==%s)"+\ "||(p1->id()==%s&&p2->id()==%s&&p3->id()==%s)||"+\ "(p1->id()==%s&&p2->id()==%s&&p3->id()==%s)) {norm(-norm());}" ordering = pattern%(vertex.particles[1].pdg_code, vertex.particles[0].pdg_code, vertex.particles[2].pdg_code, vertex.particles[0].pdg_code, vertex.particles[2].pdg_code, vertex.particles[1].pdg_code, vertex.particles[2].pdg_code, vertex.particles[1].pdg_code, vertex.particles[0].pdg_code) return ordering def tensorCouplings(vertex,value,prefactors,L,lorentztag,pos,all_couplings,order) : # split the structure into its different terms for analysis ordering="" structures = extractStructures(L) if(lorentztag == 'SST') : terms=[['P(1003,2)','P(2003,1)'], ['P(1003,1)','P(2003,2)'], ['P(-1,1)','P(-1,2)','Metric(1003,2003)'], ['Metric(1003,2003)']] signs=[1.,1.,-1.,-1.] new_couplings=[False]*len(terms) elif(lorentztag == 'FFT' ) : terms=[['P(2003,1)','Gamma(1003,2,1)'], ['P(2003,2)','Gamma(1003,2,1)'], ['P(1003,1)','Gamma(2003,2,1)'], ['P(1003,2)','Gamma(2003,2,1)'], ['P(-1,1)','Gamma(-1,2,1)','Metric(1003,2003)'], ['P(-1,2)','Gamma(-1,2,1)','Metric(1003,2003)'], ['Metric(1003,2003)']] signs=[1.,-1.,1.,-1.,-0.5,0.5,1.] new_couplings=[False]*3*len(terms) elif(lorentztag == 'VVT' ) : terms=[['P(-1,1)','P(-1,2)','Metric(1,2003)','Metric(2,1003)'], # from C term ['P(-1,1)','P(-1,2)','Metric(1,1003)','Metric(2,2003)'], # from C term ['P(-1,1)','P(-1,2)','Metric(1,2)','Metric(1003,2003)'], # from C term ['P(1,2)','P(2,1)','Metric(1003,2003)'], # from D term (sym) ['P(1,2)','P(2003,1)','Metric(2,1003)'], # 1st term ['P(1,2)','P(1003,1)','Metric(2,2003)'], # 1st swap ['P(2,1)','P(2003,2)','Metric(1,1003)'], # 2nd term ['P(2,1)','P(1003,2)','Metric(1,2003)'], # 2nd swap ['P(1003,2)','P(2003,1)','Metric(1,2)'], # 3rd term ['P(1003,1)','P(2003,2)','Metric(1,2)'], # 3rd swap ['Metric(1,2003)','Metric(2,1003)'], # from mass term ['Metric(1,1003)','Metric(2,2003)'], # from mass term ['Metric(1,2)','Metric(1003,2003)'], # from mass term ['P(1,1)','P(2,1)','Metric(1003,2003)'], # gauge terms ['P(1,2)','P(2,2)','Metric(1003,2003)'], # gauge terms ['P(1,1)','P(2,2)','Metric(1003,2003)'], # gauge terms ['P(1003,1)','P(1,1)','Metric(2,2003)'], # gauge terms ['P(1003,2)','P(2,2)','Metric(1,2003)'], # gauge terms ['P(2003,1)','P(1,1)','Metric(2,1003)'], # gauge terms ['P(2003,2)','P(2,2)','Metric(1,1003)'], # gauge terms ] signs=[1.,1.,-1.,1.,-1.,-1.,-1.,-1.,1.,1.,1.,1.,-1.,1.,1.,0.25,-1.,-1.,-1.,-1.] new_couplings=[False]*len(terms) elif(lorentztag == 'FFVT' ) : terms = [['Gamma(2004,2,1)','Metric(3,1004)'], ['Gamma(1004,2,1)','Metric(3,2004)'], ['Gamma(3,2,1)','Metric(1004,2004)'], ['Gamma(2004,2,-1)','Metric(3,1004)'], ['Gamma(1004,2,-1)','Metric(3,2004)'], ['Gamma(3,2,-1)','Metric(1004,2004)']] signs=[1.,1.,-0.5,1.,1.,-0.5] new_couplings=[False]*3*len(terms) elif(lorentztag == 'VVVT' ) : # the F(mu nu,rho sigma lambda) terms first terms = [['P(2004,2)','Metric(1,1004)','Metric(2,3)'],['P(2004,3)','Metric(1,1004)','Metric(2,3)'], ['P(1004,2)','Metric(1,2004)','Metric(2,3)'],['P(1004,3)','Metric(1,2004)','Metric(2,3)'], ['P(2004,3)','Metric(1,3)','Metric(2,1004)'],['P(2004,1)','Metric(1,3)','Metric(2,1004)'], ['P(1004,3)','Metric(1,3)','Metric(2,2004)'],['P(1004,1)','Metric(1,3)','Metric(2,2004)'], ['P(2004,1)','Metric(1,2)','Metric(3,1004)'],['P(2004,2)','Metric(1,2)','Metric(3,1004)'], ['P(1004,1)','Metric(1,2)','Metric(3,2004)'],['P(1004,2)','Metric(1,2)','Metric(3,2004)'], ['P(3,1)','Metric(1,2004)','Metric(2,1004)'],['P(3,2)','Metric(1,2004)','Metric(2,1004)'], ['P(3,1)','Metric(1,1004)','Metric(2,2004)'],['P(3,2)','Metric(1,1004)','Metric(2,2004)'], ['P(3,1)','Metric(1,2)','Metric(1004,2004)'],['P(3,2)','Metric(1,2)','Metric(1004,2004)'], ['P(2,3)','Metric(1,2004)','Metric(3,1004)'],['P(2,1)','Metric(1,2004)','Metric(3,1004)'], ['P(2,3)','Metric(1,1004)','Metric(3,2004)'],['P(2,1)','Metric(1,1004)','Metric(3,2004)'], ['P(2,3)','Metric(1,3)','Metric(1004,2004)'],['P(2,1)','Metric(1,3)','Metric(1004,2004)'], ['P(1,2)','Metric(2,2004)','Metric(3,1004)'],['P(1,3)','Metric(2,2004)','Metric(3,1004)'], ['P(1,2)','Metric(2,1004)','Metric(3,2004)'],['P(1,3)','Metric(2,1004)','Metric(3,2004)'], ['P(1,2)','Metric(2,3)','Metric(1004,2004)'],['P(1,3)','Metric(2,3)','Metric(1004,2004)']] signs = [1.,-1.,1.,-1.,1.,-1.,1.,-1.,1.,-1.,1.,-1., 1.,-1.,1.,-1.,-1.,1.,1.,-1.,1.,-1.,-1.,1.,1.,-1.,1.,-1.,-1.,1.] new_couplings=[False]*len(terms) l = lambda c: len(pos[c]) if l(8)!=3 : ordering = VVVordering(vertex) # unknown else : raise Exception('Unknown data type "%s".' % lorentztag) iterm=0 try : for term in terms: for perm in itertools.permutations(term): label = '*'.join(perm) for istruct in range(0,len(structures)) : if label in structures[istruct] : reminder = structures[istruct].replace(label,'1.',1) loc=iterm if(reminder.find("ProjM")>=0) : reminder=re.sub("\*ProjM\(.*,.\)","",reminder) loc+=len(terms) elif(reminder.find("ProjP")>=0) : reminder=re.sub("\*ProjP\(.*,.\)","",reminder) loc+=2*len(terms) structures[istruct] = "Done" val = eval(reminder, {'cmath':cmath} )*signs[iterm] if(new_couplings[loc]) : new_couplings[loc] += val else : new_couplings[loc] = val iterm+=1 except : SkipThisVertex() # check we've handled all the terms for val in structures: if(val!="Done") : raise SkipThisVertex() # special for FFVT if(lorentztag=="FFVT") : t_couplings=new_couplings new_couplings=[False]*9 for i in range(0,9) : j = i+3*(i/3) k = i+3+3*(i/3) if( not t_couplings[j]) : new_couplings[i] = t_couplings[k] else : new_couplings[i] = t_couplings[j] # set the couplings for icoup in range(0,len(new_couplings)) : if(new_couplings[icoup]) : new_couplings[icoup] = '(%s) * (%s) *(%s)' % (new_couplings[icoup],prefactors,value) if(len(all_couplings)==0) : all_couplings=new_couplings else : for icoup in range(0,len(new_couplings)) : if(new_couplings[icoup] and all_couplings[icoup]) : all_couplings[icoup] = '(%s) + (%s) ' % (new_couplings[icoup],all_couplings[icoup]) elif(new_couplings[icoup]) : all_couplings[icoup] = new_couplings[icoup] # return the results return (ordering,all_couplings) -def processTensorCouplings(lorentztag,vertex,model,parmsubs,all_couplings) : +def processTensorCouplings(lorentztag,vertex,model,parmsubs,all_couplings,order) : # check for fermion vertices (i.e. has L/R couplings) fermions = "FF" in lorentztag # test and process the values of the couplings tval = [False]*3 value = [False]*3 # loop over the colours for icolor in range(0,len(all_couplings)) : lmax = len(all_couplings[icolor]) if(fermions) : lmax /=3 # loop over the different terms for ix in range(0,lmax) : test = [False]*3 # normal case if( not fermions ) : test[0] = all_couplings[icolor][ix] else : # first case vector but no L/R couplings if( not all_couplings[icolor][lmax+ix] and not all_couplings[icolor][2*lmax+ix] ) : test[0] = all_couplings[icolor][ix] # special for mass terms and massless particles if(not all_couplings[icolor][ix]) : - code = abs(vertex.particles[0].pdg_code) + code = abs(vertex.particles[order[0]-1].pdg_code) if(ix==6 and code ==12 or code ==14 or code==16) : continue else : raise SkipThisVertex() # second case L/R couplings elif( not all_couplings[icolor][ix] ) : # L=R, replace with vector if(all_couplings[icolor][lmax+ix] == all_couplings[icolor][2*lmax+ix]) : test[0] = all_couplings[icolor][lmax+ix] else : test[1] = all_couplings[icolor][lmax+ix] test[2] = all_couplings[icolor][2*lmax+ix] else : raise SkipThisVertex() # special handling of mass terms # scalar divide by m**2 if((ix==3 and lorentztag=="SST") or ( ix>=10 and ix<=12 and lorentztag=="VVT" )) : for i in range(0,len(test)) : if(test[i]) : - test[i] = '(%s)/%s**2' % (test[i],vertex.particles[0].mass.value) + test[i] = '(%s)/%s**2' % (test[i],vertex.particles[order[0]-1].mass.value) # fermions divide by 4*m elif(ix==6 and lorentztag=="FFT" and - float(vertex.particles[0].mass.value) != 0. ) : + float(vertex.particles[order[0]-1].mass.value) != 0. ) : for i in range(0,len(test)) : if(test[i]) : - test[i] = '-(%s)/%s/4' % (test[i],vertex.particles[0].mass.value) + test[i] = '-(%s)/%s/4' % (test[i],vertex.particles[order[0]-1].mass.value) # set values on first pass if(not tval[0] and not tval[1] and not tval[2]) : value = test for i in range(0,len(test)) : if(test[i]) : tval[i] = evaluate(test[i],model,parmsubs) else : for i in range(0,len(test)) : if(not test[i] and not tval[i]) : continue if(not test[i] or not tval[i]) : # special for mass terms and vectors if(lorentztag=="VVT" and ix >=10 and ix <=12 and - float(vertex.particles[0].mass.value) == 0. ) : + float(vertex.particles[order[0]-1].mass.value) == 0. ) : continue # special for vector gauge terms if(lorentztag=="VVT" and ix>=13) : continue raise SkipThisVertex() tval2 = evaluate(test[i],model,parmsubs) if(abs(tval[i]-tval2)>1e-6) : # special for fermion mass term if fermions massless if(lorentztag=="FFT" and ix ==6 and tval2 == 0. and - float(vertex.particles[0].mass.value) == 0. ) : + float(vertex.particles[order[0]-1].mass.value) == 0. ) : continue raise SkipThisVertex() # simple clean up for i in range(0,len(value)): if(value[i]) : value[i] = value[i].replace("(1.0) * ","").replace(" * (1)","") # put everything together coup_left = 0. coup_right = 0. coup_norm = 0. if(lorentztag == "SST" or lorentztag == "VVT" or lorentztag == "VVVT" or lorentztag == "FFT" ) : coup_norm = value[0] if(value[1] or value[2]) : raise SkipThisVertex() elif(lorentztag=="FFVT") : if(not value[1] and not value[2]) : coup_norm = value[0] coup_left = "1." coup_right = "1." elif(not value[0]) : coup_norm = "1." if(value[1] and value[2]) : coup_left = value[1] coup_right = value[2] elif(value[1]) : coup_left = value[1] coup_right = "0." elif(value[2]) : coup_left = "0." coup_right = value[2] else : raise SkipThisVertex() else : raise SkipThisVertex() else : raise SkipThisVertex() # return the answer return (coup_left,coup_right,coup_norm) def extractStructures(L) : structure1 = L.structure.split() structures =[] sign='' for struct in structure1 : if(struct=='+') : continue elif(struct=='-') : sign='-' else : structures.append(sign+struct.strip()) sign='' return structures def changeSign(sign1,sign2) : if((sign1=="+" and sign2=="+") or\ (sign1=="-" and sign2=="-")) : return "+" else : return "-" def epsilonOrder(eps) : terms,sign = extractAntiSymmetricIndices(eps,"Epsilon(") return (sign,"Epsilon(%s,%s,%s,%s)" % (terms[0],terms[1],terms[2],terms[3])) def VVSEpsilon(couplings,struct) : if(struct.find("Epsilon")<0) : return fact="" sign="+" if(struct[-1]==")") : fact=struct.split("(")[0] if(fact.find("Epsilon")>=0) : fact="" else : struct=struct.split("(",1)[1][:-1] if(fact[0]=="-") : sign="-" fact=fact[1:] split = struct.split("*") # find the epsilon eps="" for piece in split : if(piece.find("Epsilon")>=0) : eps=piece split.remove(piece) break # and any prefactors for piece in split : if(piece.find("P(")<0) : split.remove(piece) if(piece[0]=="+" or piece[0]=="-") : sign=changeSign(sign,piece[0]) piece=piece[1:] if(fact=="") : fact=piece else : fact = "( %s ) * ( %s )" % (fact , piece) # now sort out the momenta for piece in split : terms=piece.split(",") terms[0]=terms[0].strip("P(") terms[1]=terms[1].strip(")") eps=eps.replace(terms[0],"P%s"%terms[1]) (nsign,eps)=epsilonOrder(eps) if(nsign>0) : sign=changeSign(sign,"-") if(fact=="") : fact="1." if(eps!="Epsilon(1,2,P1,P2)") : return if(couplings[6]==0.) : couplings[6] = "( %s%s )" % (sign,fact) else : couplings[6] = "( %s ) + ( %s%s )" % (couplings[6],sign,fact) def scalarVectorCouplings(value,prefactors,L,lorentztag,all_couplings,order) : # set up the types of term we are looking for if(lorentztag=="VVS") : couplings=[0.,0.,0.,0.,0.,0.,0.] terms=[['P(-1,%s)' % order[0], 'P(-1,%s)' % order[1], 'Metric(%s,%s)' %(order[0],order[1])], ['P(1,%s)' % order[0], 'P(2,%s)' % order[0]], ['P(1,%s)' % order[0], 'P(2,%s)' % order[1]], ['P(1,%s)' % order[1], 'P(2,%s)' % order[0]], ['P(1,%s)' % order[1], 'P(2,%s)' % order[1]], ['Metric(%s,%s)'%(order[0],order[1])]] elif(lorentztag=="VVSS") : couplings=[0.] terms=[['Metric(%s,%s)' % (order[0],order[1])]] elif(lorentztag=="VSS"): couplings=[0.,0.] terms=[['P(%s,%s)' % (order[0],order[2])], ['P(%s,%s)' % (order[0],order[1])]] # extract the lorentz structures structures = extractStructures(L) # handle the scalar couplings itype=-1 try : for term in terms: itype+=1 for perm in itertools.permutations(term): label = '*'.join(perm) for istruct in range(0,len(structures)) : if label in structures[istruct] : reminder = structures[istruct].replace(label,'1.',1) couplings[itype]+=eval(reminder, {'cmath':cmath} ) structures[istruct]='Done' except : raise SkipThisVertex() # special for VVS and epsilon # handle the pseudoscalar couplings for struct in structures : if(struct != "Done" ) : if(lorentztag=="VVS") : VVSEpsilon(couplings,struct) else : raise SkipThisVertex() # put it all together if(len(all_couplings)==0) : for ic in range(0,len(couplings)) : if(couplings[ic]!=0.) : all_couplings.append('(%s) * (%s) * (%s)' % (prefactors,value,couplings[ic])) else : all_couplings.append(False) else : for ic in range(0,len(couplings)) : if(couplings[ic]!=0. and all_couplings[ic]) : all_couplings[ic] = '(%s) * (%s) * (%s) + (%s) ' % (prefactors,value, couplings[ic],all_couplings[ic]) elif(couplings[ic]!=0) : all_couplings[ic] = '(%s) * (%s) * (%s) ' % (prefactors,value,couplings[ic]) return all_couplings def processScalarVectorCouplings(lorentztag,vertex,model,parmsubs,all_couplings,header,order) : # check the values tval = [False]*len(all_couplings[0]) value =[False]*len(all_couplings[0]) for icolor in range(0,len(all_couplings)) : for ix in range(0,len(all_couplings[icolor])) : if(not value[ix]) : value[ix] = all_couplings[icolor][ix] if(value[ix] and not tval[ix]) : tval[ix] = evaluate(value[ix],model,parmsubs) elif(value[ix]) : tval2 = evaluate(all_couplings[icolor][0],model,parmsubs) if(abs(tval[ix]-tval2)>1e-6) : raise SkipThisVertex() append = "" symbols = set() coup_norm=0. if(lorentztag=="VVS") : if(not value[0] and not value[1] and not value[2] and \ not value[3] and not value[4] and not value[6] and value[5]) : coup_norm=value[5] else : for ix in range(0,len(value)) : if(value[ix]) : value[ix], sym = py2cpp(value[ix]) symbols |= sym else : value[ix]=0. lorentztag = 'GeneralVVS' header="kinematics(true);" # g_mu,nv piece of coupling if(value[5]!=0.) : append +='a00( %s + Complex(( %s )* GeV2/invariant(1,2)));\n' % ( value[0],value[5]) else : append +='a00( %s );\n' % value[0] # other couplings append += 'a11( %s );\n a12( %s );\n a21( %s );\n a22( %s );\n aEp( %s );\n' % \ ( value[1],value[2],value[3],value[4],value[6] ) coup_norm="1." elif(lorentztag=="VVSS") : coup_norm = value[0] elif(lorentztag=="VSS") : if(abs(tval[0]+tval[1])>1e-6) : for ix in range(0,len(value)) : if(value[ix]) : value[ix], sym = py2cpp(value[ix]) symbols |= sym else : value[ix]=0. coup_norm = "1." append = 'if(p2->id()==%s) { a( %s ); b( %s);}\n else { a( %s ); b( %s);}' \ % (vertex.particles[order[1]-1].pdg_code, value[0],value[1],value[1],value[0]) else : coup_norm = value[1] append = 'if(p2->id()!=%s){norm(-norm());}' \ % vertex.particles[order[1]-1].pdg_code # return the answer return (coup_norm,append,lorentztag,header,symbols) def getIndices(term) : if(term[0:2]=="P(") : indices = term.strip(")").strip("P(").split(",") mom = int(indices[1]) index = int(indices[0]) return (True,mom,index) else : return (False,0,0) def lorentzScalar(vertex,L) : dotProduct = """(invariant( i[{i1}], i[{i2}] )/GeV2)""" structures=L.structure.split() output="(" for struct in structures: if(struct=="+" or struct=="-") : output+=struct continue structure = struct.split("*") worked = False mom=-1 newTerm="" while True : term = structure[-1] structure.pop() (momentum,mom,index) = getIndices(term) if( not momentum) : break # look for the matching momenta for term in structure : (momentum,mom2,index2) = getIndices(term) if(index2==index) : structure.remove(term) dot = dotProduct.format(i1=mom-1,i2=mom2-1) if(newTerm=="") : newTerm = dot else : newTerm = " ( %s) * ( %s ) " % (newTerm,dot) if(len(structure)==0) : worked = True break if(not worked) : return False else : output+=newTerm output+=")" return output kinematicsline = """\ long id [3]={{{id1},{id2},{id3}}}; long id2[3]={{p1->id(),p2->id(),p3->id()}}; unsigned int i[3]; for(unsigned int ix=0;ix<3;++ix) {{ for(unsigned int iy=0;iy<3;++iy) {{ if(id[ix]==id2[iy]) {{ i[ix] = iy; id2[iy]=0; break; }} }} }} double hw_kine1 = {kine}; """ kinematicsline2 = """\ long id [4]={{{id1},{id2},{id3},{id4}}}; long id2[4]={{p1->id(),p2->id(),p3->id(),p4->id()}}; unsigned int i[4]; for(unsigned int ix=0;ix<4;++ix) {{ for(unsigned int iy=0;iy<4;++iy) {{ if(id[ix]==id2[iy]) {{ i[ix] = iy; id2[iy]=0; break; }} }} }} double hw_kine1 = {kine}; """ kinematicsline3 ="""\ double hw_kine{i} = {kine}; """ def scalarCouplings(vertex,value,prefactors,L,lorentztag, all_couplings,prepend,header) : try : val = int(L.structure) except : output = lorentzScalar(vertex,L) if( not output ) : raise SkipThisVertex() else : if(prepend=="") : if(lorentztag=="SSS") : + # order doesn't matter here, all same spin prepend = kinematicsline.format(id1=vertex.particles[0].pdg_code, + id2=vertex.particles[1].pdg_code, + id3=vertex.particles[2].pdg_code, + kine=output) + else : + # order doesn't matter here, all same spin + prepend = kinematicsline2.format(id1=vertex.particles[0].pdg_code, id2=vertex.particles[1].pdg_code, id3=vertex.particles[2].pdg_code, + id4=vertex.particles[3].pdg_code, kine=output) - else : - prepend = kinematicsline2.format(id1=vertex.particles[0].pdg_code, - id2=vertex.particles[1].pdg_code, - id3=vertex.particles[2].pdg_code, - id4=vertex.particles[2].pdg_code, - kine=output) value = "(%s) *(hw_kine1)" % value else : osplit=prepend.split("\n") i=-1 while osplit[i]=="": i=i-1 ikin=int(osplit[i].split("=")[0].replace("double hw_kine",""))+1 prepend +=kinematicsline3.format(kine=output,i=ikin) value = "(%s) *(hw_kine%s)" % (value,ikin) header="kinematics(true);" if(len(all_couplings)==0) : all_couplings.append('(%s) * (%s)' % (prefactors,value)) else : all_couplings[0] = '(%s) * (%s) + (%s)' % (prefactors,value,all_couplings[0]) return (prepend, header,all_couplings) def processScalarCouplings(model,parmsubs,all_couplings) : tval = False value = False for icolor in range(0,len(all_couplings)) : if(len(all_couplings[icolor])!=1) : raise SkipThisVertex() if(not value) : value = all_couplings[icolor][0] m = re.findall('hw_kine[0-9]*', all_couplings[icolor][0]) if m: for kine in m: # bizarre number for checks, must be a better option parmsubs[kine] = 987654321. if(not tval) : tval = evaluate(value,model,parmsubs) else : tval2 = evaluate(all_couplings[icolor][0],model,parmsubs) if(abs(tval[i]-tval2)>1e-6) : raise SkipThisVertex() # cleanup and return the answer return value.replace("(1.0) * ","").replace(" * (1)","") def vectorCouplings(vertex,value,prefactors,L,lorentztag,pos, all_couplings,append,qcd,order) : structures=extractStructures(L) terms=[] signs=[] if(lorentztag=="VVV") : terms=[['P(%s,%s)' % (order[2],order[0]),'Metric(%s,%s)' % (order[0],order[1])], ['P(%s,%s)' % (order[2],order[1]),'Metric(%s,%s)' % (order[0],order[1])], ['P(%s,%s)' % (order[1],order[0]),'Metric(%s,%s)' % (order[0],order[2])], ['P(%s,%s)' % (order[1],order[2]),'Metric(%s,%s)' % (order[0],order[2])], ['P(%s,%s)' % (order[0],order[1]),'Metric(%s,%s)' % (order[1],order[2])], ['P(%s,%s)' % (order[0],order[2]),'Metric(%s,%s)' % (order[1],order[2])]] signs=[1.,-1.,-1.,1.,1.,-1.] elif(lorentztag=="VVVV") : terms=[['Metric(%s,%s)' % (order[0],order[3]),'Metric(%s,%s)' % (order[1],order[2])], ['Metric(%s,%s)' % (order[0],order[2]),'Metric(%s,%s)' % (order[1],order[3])], ['Metric(%s,%s)' % (order[0],order[1]),'Metric(%s,%s)' % (order[2],order[3])]] signs=[1.,1.,1.] elif(lorentztag=="VVVS") : terms=[['P(%s,%s)' % (order[2],order[0]),'Metric(%s,%s)' % (order[0],order[1])], ['P(%s,%s)' % (order[2],order[1]),'Metric(%s,%s)' % (order[0],order[1])], ['P(%s,%s)' % (order[1],order[0]),'Metric(%s,%s)' % (order[0],order[2])], ['P(%s,%s)' % (order[1],order[2]),'Metric(%s,%s)' % (order[0],order[2])], ['P(%s,%s)' % (order[0],order[1]),'Metric(%s,%s)' % (order[1],order[2])], ['P(%s,%s)' % (order[0],order[2]),'Metric(%s,%s)' % (order[1],order[2])], ['Epsilon(1,2,3,-1)','P(-1,1)'],['Epsilon(1,2,3,-1)','P(-1,2)'], ['Epsilon(1,2,3,-1)','P(-1,3)']] signs=[1.,-1.,-1.,1.,1.,-1.,1.,1.,1.] # extract the couplings new_couplings = [False]*len(terms) iterm=0 try : for term in terms: for perm in itertools.permutations(term): label = '*'.join(perm) for istruct in range(0,len(structures)) : if label in structures[istruct] : reminder = structures[istruct].replace(label,'1.',1) structures[istruct] = "Done" val = eval(reminder, {'cmath':cmath} )*signs[iterm] if(new_couplings[iterm]) : new_couplings[iterm] += val else : new_couplings[iterm] = val iterm += 1 except : raise SkipThisVertex() # check we've handled all the terms for val in structures: if(val!="Done") : raise SkipThisVertex() # set the couplings for icoup in range(0,len(new_couplings)) : if(new_couplings[icoup]) : new_couplings[icoup] = '(%s) * (%s) *(%s)' % (new_couplings[icoup],prefactors,value) if(len(all_couplings)==0) : all_couplings=new_couplings else : for icoup in range(0,len(new_couplings)) : if(new_couplings[icoup] and all_couplings[icoup]) : all_couplings[icoup] = '(%s) * (%s) *(%s) + (%s) ' % (new_couplings[icoup],prefactors,value,all_couplings[icoup]) elif(new_couplings[icoup]) : all_couplings[icoup] = new_couplings[icoup] # ordering for VVV type vertices if(len(pos[8]) != 3 and (lorentztag=="VVV" or lorentztag=="VVVS")) : append = VVVordering(vertex) return all_couplings,append def processVectorCouplings(lorentztag,vertex,model,parmsubs,all_couplings,append,header) : value = False tval = False if(lorentztag=="VVV") : for icolor in range(0,len(all_couplings)) : # loop over the different terms for ix in range(0,len(all_couplings[icolor])) : if(not value) : value = all_couplings[icolor][ix] tval = evaluate(value,model,parmsubs) else : tval2 = evaluate(all_couplings[icolor][ix],model,parmsubs) if(abs(tval-tval2)>1e-6) : raise SkipThisVertex() elif(lorentztag=="VVVV") : order=[] colours = vertex.color if(len(colours)==1) : tval=[] for i in range(0,3) : tval.append(evaluate(all_couplings[0][i],model,parmsubs)) if(compare(tval[2],-2.*tval[1]) and compare(tval[2],-2.*tval[0]) ) : order=[0,1,2,3] value = "0.5*(%s)" % all_couplings[0][2] elif(compare(tval[1],-2.*tval[2]) and compare(tval[1],-2.*tval[0]) ) : order=[0,2,1,3] value = "0.5*(%s)" % all_couplings[0][1] elif(compare(tval[0],-2.*tval[2]) and compare(tval[0],-2.*tval[1]) ) : order=[0,3,1,2] value = "0.5*(%s)" % all_couplings[0][0] else: - sys.stderr.write( - 'Warning: unsupported {tag} ( {ps} ) Lorentz structure in {name}:\n' - .format(tag="VVVV", name=vertex.name, ps=' '.join(map(str,vertex.particles))) - ) raise SkipThisVertex() pattern = \ "bool done[4]={false,false,false,false};\n" + \ " tcPDPtr part[4]={p1,p2,p3,p4};\n" + \ " unsigned int iorder[4]={0,0,0,0};\n" + \ " for(unsigned int ix=0;ix<4;++ix) {\n" + \ " if(!done[0] && part[ix]->id()==%s) {done[0]=true; iorder[%s] = ix; continue;}\n" + \ " if(!done[1] && part[ix]->id()==%s) {done[1]=true; iorder[%s] = ix; continue;}\n" + \ " if(!done[2] && part[ix]->id()==%s) {done[2]=true; iorder[%s] = ix; continue;}\n" + \ " if(!done[3] && part[ix]->id()==%s) {done[3]=true; iorder[%s] = ix; continue;}\n" + \ " }\n" + \ " setType(2);\n" + \ " setOrder(iorder[0],iorder[1],iorder[2],iorder[3]);" + # order doesn't matter here same spin append = pattern % ( vertex.particles[0].pdg_code,order[0], vertex.particles[1].pdg_code,order[1], vertex.particles[2].pdg_code,order[2], vertex.particles[3].pdg_code,order[3] ) else : for icolor in range(0,len(all_couplings)) : col=colours[icolor].split("*") if(len(col)==2 and "f(" in col[0] and "f(" in col[1]) : sign = 1 for i in range(0,2) : col[i],stemp = extractAntiSymmetricIndices(col[i],"f(") for ix in range(0,len(col[i])): col[i][ix]=int(col[i][ix]) sign *=stemp if(col[0][0]>col[1][0]) : col[0],col[1] = col[1],col[0] # first flow if(col[0][0]==1 and col[0][1]==2 and col[1][0] ==3 and col[1][1] == 4) : if(all_couplings[icolor][2] or not all_couplings[icolor][0] or not all_couplings[icolor][1]) : raise SkipThisVertex() if(not value) : - value = all_couplings[icolor][0] + value = all_couplings[icolor][1] tval = evaluate(value,model,parmsubs) - tval2 = evaluate(all_couplings[icolor][0],model,parmsubs) - tval3 = -evaluate(all_couplings[icolor][1],model,parmsubs) + tval2 = -evaluate(all_couplings[icolor][0],model,parmsubs) + tval3 = evaluate(all_couplings[icolor][1],model,parmsubs) elif(col[0][0]==1 and col[0][1]==3 and col[1][0] ==2 and col[1][1] == 4) : if(all_couplings[icolor][1] or not all_couplings[icolor][0] or not all_couplings[icolor][2]) : raise SkipThisVertex() if(not value) : - value = all_couplings[icolor][0] + value = all_couplings[icolor][2] tval = evaluate(value,model,parmsubs) - tval2 = evaluate(all_couplings[icolor][0],model,parmsubs) - tval3 = -evaluate(all_couplings[icolor][2],model,parmsubs) + tval2 = -evaluate(all_couplings[icolor][0],model,parmsubs) + tval3 = evaluate(all_couplings[icolor][2],model,parmsubs) elif(col[0][0]==1 and col[0][1]==4 and col[1][0] ==2 and col[1][1] == 3) : if(all_couplings[icolor][0] or not all_couplings[icolor][1] or not all_couplings[icolor][2]) : raise SkipThisVertex() if(not value) : - value = all_couplings[icolor][1] + value = all_couplings[icolor][2] tval = evaluate(value,model,parmsubs) - tval2 = evaluate(all_couplings[icolor][1],model,parmsubs) - tval3 = -evaluate(all_couplings[icolor][2],model,parmsubs) + tval2 = -evaluate(all_couplings[icolor][1],model,parmsubs) + tval3 = evaluate(all_couplings[icolor][2],model,parmsubs) else : raise SkipThisVertex() if(abs(tval-tval2)>1e-6 or abs(tval-tval3)>1e-6 ) : raise SkipThisVertex() append = 'setType(1);\nsetOrder(0,1,2,3);' else : print 'unknown colour structure for VVVV vertex' raise SkipThisVertex() elif(lorentztag=="VVVS") : try : # two distinct cases 0-5 = , 6-8= if(all_couplings[0][0]) : imin=0 imax=6 header="scalar(true);" else : imin=6 imax=9 header="scalar(false);" for icolor in range(0,len(all_couplings)) : # loop over the different terms for ix in range(imin,imax) : if(not value) : value = all_couplings[icolor][ix] tval = evaluate(value,model,parmsubs) else : tval2 = evaluate(value,model,parmsubs) if(abs(tval-tval2)>1e-6) : raise SkipThisVertex() except : SkipThisVertex() # cleanup and return the answer value = value.replace("(1.0) * ","").replace(" * (1)","") return (value,append,header) def fermionCouplings(value,prefactors,L,all_couplings,order) : new_couplings=[False,False] try : new_couplings[0],new_couplings[1] = parse_lorentz(L.structure) except : raise SkipThisVertex() for i in range(0,2) : if new_couplings[i]: new_couplings[i] = '(%s) * (%s) * (%s)' % (prefactors,new_couplings[i],value) if(len(all_couplings)==0) : all_couplings=new_couplings else : for i in range(0,len(new_couplings)) : if(new_couplings[i] and all_couplings[i]) : all_couplings[i] = '(%s) + (%s) ' % (new_couplings[i],all_couplings[i]) elif(new_couplings[i]) : all_couplings[i] = new_couplings[i] return all_couplings -def processFermionCouplings(lorentztag,vertex,model,parmsubs,all_couplings) : +def processFermionCouplings(lorentztag,vertex,model,parmsubs,all_couplings,order) : leftcontent = all_couplings[0][0] if all_couplings[0][0] else "0." rightcontent = all_couplings[0][1] if all_couplings[0][1] else "0." tval=[evaluate( leftcontent,model,parmsubs), evaluate(rightcontent,model,parmsubs)] for icolor in range(0,len(all_couplings)) : # loop over the different terms for ix in range(0,len(all_couplings[icolor])) : tval2 = evaluate(all_couplings[icolor][ix],model,parmsubs) if all_couplings[icolor][ix] else 0. if(abs(tval[ix]-tval2)>1e-6) : raise SkipThisVertex() normcontent = "1." append="" if lorentztag == 'FFV': append = ('if(p1->id()!=%s) {Complex ltemp=left(), rtemp=right(); left(-rtemp); right(-ltemp);}' - % vertex.particles[0].pdg_code) + % vertex.particles[order[0]-1].pdg_code) return normcontent,leftcontent,rightcontent,append def RSCouplings(value,prefactors,L,all_couplings,order) : raise SkipThisVertex() diff --git a/Models/Feynrules/python/ufo2peg/converter.py b/Models/Feynrules/python/ufo2peg/converter.py --- a/Models/Feynrules/python/ufo2peg/converter.py +++ b/Models/Feynrules/python/ufo2peg/converter.py @@ -1,162 +1,185 @@ """ AST visitor class to convert Python expressions into C++ as used by ThePEG """ import ast +convertHerwig=False -def py2cpp(expr): +def py2cpp(expr,con=False): """Convert expr to C++ form. Wraps the converter class.""" + global convertHerwig + convertHerwig=con result = PyToCpp().parse(expr) return result class PyToCppException(Exception): """Base class for all PyToCpp exceptions.""" class PyToCpp(ast.NodeVisitor): """Convert Python math expressions into C++. Returns a tuple (expr,syms): expr -- C++-compatible expression syms -- set of all free variables Usage: >>> expr = '3+2**a*b' >>> PyToCpp().parse(expr) ('(3.0+(pow(2.0,a)*b))', set(['a', 'b'])) Note: The converter is currently not generic, it relies on the conventions of Feynrules' UFO format on the one hand and ThePEG's C++ types on the other. """ def parse(self,expression): """Convert expression to C++ format.""" self.result = [] self.symbols = set() + expression=expression.replace("abs(","cmath.abs(") tree = ast.parse(expression) #print ast.dump(tree) return self.visit(tree) ################################## def visit_Module(self,node): self.generic_visit(node) return ''.join(self.result), self.symbols def generic_visit(self,node): typename = type(node).__name__ harmless = ['Module','Expr'] if typename not in harmless: raise PyToCppException('Missing implementation for %s' % typename) super(PyToCpp,self).generic_visit(node) def visit_UnaryOp(self,node): self.result.append('(') self.visit(node.op) self.visit(node.operand) self.result.append(')') def visit_BinOp(self,node): if type(node.op) == type(ast.Pow()): return self.pow_node(node) self.result.append('(') self.visit(node.left) self.visit(node.op) self.visit(node.right) self.result.append(')') def pow_node(self,node): if is_square(node): self.result.append('sqr(') self.visit(node.left) self.result.append(')') else: self.result.append('pow(') self.visit(node.left) self.result.append(',') self.visit(node.right) self.result.append(')') def visit_Call(self,node): if is_ii(node): self.result.append('ii') else: self.visit(node.func) self.result.append('(') for a in node.args: self.visit(a) self.result.append(',') if self.result[-1] == ',': del self.result[-1] self.result.append(')') def visit_Attribute(self,node): if node.value.id != 'cmath': err = "Don't know how to convert %s module." % node.value.id raise PyToCppException(err) self.result.append(node.attr) def visit_Num(self,node): # some zeros are encoded as 0j if node.n == 0: text = '0.0' - else: text = str(float(node.n)) + elif (node.n==complex("1j") ) : + text = "ii" + elif (node.n==complex("-1j") ) : + text = "-ii" + elif (node.n==complex("2j") ) : + text = "2.*ii" + else: + text = str(float(node.n)) self.result.append(text) def visit_Name(self,node): text = str(node.id) if text == 'complex': text = 'Complex' elif text == 'complexconjugate': text = 'conj' + elif convertHerwig : + if text == 'I' : + text = "ii" + elif ( text.find("UnitRemoval")==0) : + text = "%s::%s" % (text[:11],text[11:]) + elif(text[0]=="P" or text[0]=="E" or text[0] == "V") : + if text[-1] in ["x","y","z","t"] : + text = "%s.%s()" % (text[0:-1],text[-1]) + elif(text[0]=="R") : + text = "%s.%s()" % (text[:-3],text[-3:]) + elif(text[0]=="s") : + text = "%s.%s()" % (text[:-2],text[-2:]) elif text not in []: self.symbols.add(text) self.result.append(text) def visit_Mult(self,node): self.result.append('*') def visit_Add(self,node): self.result.append('+') def visit_Sub(self,node): self.result.append('-') def visit_USub(self,node): self.result.append('-') def visit_UAdd(self,node): self.result.append('+') def visit_Div(self,node): self.result.append('/') def visit_Pow(self,node): err = "Shold never get here. BinaryOp catches Pow calls." raise PyToCppException(err) ### Helpers def is_square(node): """Check if a Pow object is just a square.""" try: return node.right.n == 2.0 except: return False def is_ii(node): """Check if a Call object is just the imaginary unit.""" try: return ( node.func.id == 'complex' and node.args[0].n == 0 and node.args[1].n == 1 ) except: return False if __name__ == "__main__": import doctest doctest.testmod() diff --git a/Models/Feynrules/python/ufo2peg/general_lorentz.py b/Models/Feynrules/python/ufo2peg/general_lorentz.py new file mode 100644 --- /dev/null +++ b/Models/Feynrules/python/ufo2peg/general_lorentz.py @@ -0,0 +1,3018 @@ +import copy +from .helpers import SkipThisVertex,def_from_model +from .converter import py2cpp +import string,re +from string import Template + +epsValue=[[[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]], + [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]], + [[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]], + [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]], + [[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]], + [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]], + [[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]], + [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]]] + +epsValue[0][1][2][3] = -1. +epsValue[0][1][3][2] = 1. +epsValue[0][2][1][3] = 1. +epsValue[0][2][3][1] = -1. +epsValue[0][3][1][2] = -1. +epsValue[0][3][2][1] = 1. +epsValue[1][0][2][3] = 1. +epsValue[1][0][3][2] = -1. +epsValue[1][2][0][3] = -1. +epsValue[1][2][3][0] = 1. +epsValue[1][3][0][2] = 1. +epsValue[1][3][2][0] = -1. +epsValue[2][0][1][3] = -1. +epsValue[2][0][3][1] = 1. +epsValue[2][1][0][3] = 1. +epsValue[2][1][3][0] = -1. +epsValue[2][3][0][1] = -1. +epsValue[2][3][1][0] = 1. +epsValue[3][0][1][2] = 1. +epsValue[3][0][2][1] = -1. +epsValue[3][1][0][2] = -1. +epsValue[3][1][2][0] = 1. +epsValue[3][2][0][1] = 1. +epsValue[3][2][1][0] = -1. + +# self contracted tensor propagator +tPropA=[[],[],[],[]] +tPropA[0].append(Template("-2. / 3. * (M${iloc}2 + 2 * P${iloc}t ** 2) * (M${iloc}2 -p2)*OM${iloc}**2")) +tPropA[0].append(Template("-4. / 3. * P${iloc}t * P${iloc}x * (M${iloc}2 -p2)*OM${iloc}**2")) +tPropA[0].append(Template("-4. / 3. * P${iloc}t * P${iloc}y * (M${iloc}2 -p2)*OM${iloc}**2")) +tPropA[0].append(Template("-4. / 3. * P${iloc}t * P${iloc}z * (M${iloc}2 -p2)*OM${iloc}**2")) +tPropA[1].append(Template("-4. / 3. * P${iloc}t * P${iloc}x * (M${iloc}2 -p2)*OM${iloc}**2")) +tPropA[1].append(Template(" 2. / 3. * (M${iloc}2 - 2 * P${iloc}x ** 2) * (M${iloc}2 -p2)*OM${iloc}**2")) +tPropA[1].append(Template("-4. / 3. * P${iloc}x * P${iloc}y * (M${iloc}2 -p2)*OM${iloc}**2")) +tPropA[1].append(Template("-4. / 3. * P${iloc}x * P${iloc}z * (M${iloc}2 -p2)*OM${iloc}**2")) +tPropA[2].append(Template("-4. / 3. * P${iloc}t * P${iloc}y * (M${iloc}2 -p2)*OM${iloc}**2")) +tPropA[2].append(Template("-4. / 3. * P${iloc}x * P${iloc}y * (M${iloc}2 -p2)*OM${iloc}**2")) +tPropA[2].append(Template(" 2. / 3. * (M${iloc}2 - 2 * P${iloc}y ** 2) * (M${iloc}2 -p2)*OM${iloc}**2")) +tPropA[2].append(Template("-4. / 3. * P${iloc}y * P${iloc}z * (M${iloc}2 -p2)*OM${iloc}**2")) +tPropA[3].append(Template("-4. / 3. * P${iloc}t * P${iloc}z * (M${iloc}2 -p2)*OM${iloc}**2")) +tPropA[3].append(Template("-4. / 3. * P${iloc}x * P${iloc}z * (M${iloc}2 -p2)*OM${iloc}**2")) +tPropA[3].append(Template("-4. / 3. * P${iloc}y * P${iloc}z * (M${iloc}2 -p2)*OM${iloc}**2")) +tPropA[3].append(Template(" 2. / 3. * (M${iloc}2 - 2 * P${iloc}z ** 2) * (M${iloc}2 -p2)*OM${iloc}**2")) + +# tensor propagator 1 index contracted +tPropB=[[[],[],[],[]],[[],[],[],[]],[[],[],[],[]],[[],[],[],[]]] +tPropB[0][0].append(Template("4. / 3. * (${V}t - ${dot}*OM${iloc} * P${iloc}t) * (1. - OM${iloc} * P${iloc}t ** 2)")) +tPropB[0][0].append(Template("-2 * (${V}t - ${dot}*OM${iloc} * P${iloc}t)*OM${iloc} * P${iloc}t * P${iloc}x - 2. / 3. * (1. - OM${iloc} * P${iloc}t ** 2) * (${V}x - ${dot}*OM${iloc} * P${iloc}x)")) +tPropB[0][0].append(Template(" -2 * (${V}t - ${dot}*OM${iloc} * P${iloc}t)*OM${iloc} * P${iloc}t * P${iloc}y - 2. / 3. * (1. - OM${iloc} * P${iloc}t ** 2) * (${V}y - ${dot}*OM${iloc} * P${iloc}y)")) +tPropB[0][0].append(Template(" -2 * (${V}t - ${dot}*OM${iloc} * P${iloc}t)*OM${iloc} * P${iloc}t * P${iloc}z - 2. / 3. * (1. - OM${iloc} * P${iloc}t ** 2) * (${V}z - ${dot}*OM${iloc} * P${iloc}z)")) +tPropB[0][1].append(Template(" -(${V}t - ${dot}*OM${iloc} * P${iloc}t)*OM${iloc} * P${iloc}t * P${iloc}x / 3. + (1. - OM${iloc} * P${iloc}t ** 2) * (${V}x - ${dot}*OM${iloc} * P${iloc}x)")) +tPropB[0][1].append(Template(" (${V}t - ${dot}*OM${iloc} * P${iloc}t) * (-1. - OM${iloc} * P${iloc}x ** 2) - OM${iloc} * P${iloc}t * P${iloc}x * (${V}x - ${dot}*OM${iloc} * P${iloc}x) / 3.")) +tPropB[0][1].append(Template("-(${V}t - ${dot}*OM${iloc} * P${iloc}t)*OM${iloc} * P${iloc}x * P${iloc}y - OM${iloc} * P${iloc}t * P${iloc}y * (${V}x - ${dot}*OM${iloc} * P${iloc}x) + 2. / 3.*OM${iloc} * P${iloc}t * P${iloc}x * (${V}y - ${dot}*OM${iloc} * P${iloc}y)")) +tPropB[0][1].append(Template("-(${V}t - ${dot}*OM${iloc} * P${iloc}t)*OM${iloc} * P${iloc}x * P${iloc}z - OM${iloc} * P${iloc}t * P${iloc}z * (${V}x - ${dot}*OM${iloc} * P${iloc}x) + 2. / 3.*OM${iloc} * P${iloc}t * P${iloc}x * (${V}z - ${dot}*OM${iloc} * P${iloc}z)")) +tPropB[0][2].append(Template(" -(${V}t - ${dot}*OM${iloc} * P${iloc}t)*OM${iloc} * P${iloc}t * P${iloc}y / 3. + (1. - OM${iloc} * P${iloc}t ** 2) * (${V}y - ${dot}*OM${iloc} * P${iloc}y)")) +tPropB[0][2].append(Template("-(${V}t - ${dot}*OM${iloc} * P${iloc}t)*OM${iloc} * P${iloc}x * P${iloc}y - OM${iloc} * P${iloc}t * P${iloc}x * (${V}y - ${dot}*OM${iloc} * P${iloc}y) + 2. / 3.*OM${iloc} * P${iloc}t * P${iloc}y * (${V}x - ${dot}*OM${iloc} * P${iloc}x)")) +tPropB[0][2].append(Template(" (${V}t - ${dot}*OM${iloc} * P${iloc}t) * (-1. - OM${iloc} * P${iloc}y ** 2) - OM${iloc} * P${iloc}t * P${iloc}y * (${V}y - ${dot}*OM${iloc} * P${iloc}y) / 3.")) +tPropB[0][2].append(Template("-(${V}t - ${dot}*OM${iloc} * P${iloc}t)*OM${iloc} * P${iloc}y * P${iloc}z - OM${iloc} * P${iloc}t * P${iloc}z * (${V}y - ${dot}*OM${iloc} * P${iloc}y) + 2. / 3.*OM${iloc} * P${iloc}t * P${iloc}y * (${V}z - ${dot}*OM${iloc} * P${iloc}z)")) +tPropB[0][3].append(Template(" -(${V}t - ${dot}*OM${iloc} * P${iloc}t)*OM${iloc} * P${iloc}t * P${iloc}z / 3. + (1. - OM${iloc} * P${iloc}t ** 2) * (${V}z - ${dot}*OM${iloc} * P${iloc}z)")) +tPropB[0][3].append(Template("-(${V}t - ${dot}*OM${iloc} * P${iloc}t)*OM${iloc} * P${iloc}x * P${iloc}z - OM${iloc} * P${iloc}t * P${iloc}x * (${V}z - ${dot}*OM${iloc} * P${iloc}z) + 2. / 3.*OM${iloc} * P${iloc}t * P${iloc}z * (${V}x - ${dot}*OM${iloc} * P${iloc}x)")) +tPropB[0][3].append(Template(" -(${V}t - ${dot}*OM${iloc} * P${iloc}t)*OM${iloc} * P${iloc}y * P${iloc}z - OM${iloc} * P${iloc}t * P${iloc}y * (${V}z - ${dot}*OM${iloc} * P${iloc}z) + 2. / 3.*OM${iloc} * P${iloc}t * P${iloc}z * (${V}y - ${dot}*OM${iloc} * P${iloc}y)")) +tPropB[0][3].append(Template("(${V}t - ${dot}*OM${iloc} * P${iloc}t) * (-1. - OM${iloc} * P${iloc}z ** 2) - OM${iloc} * P${iloc}t * P${iloc}z * (${V}z - ${dot}*OM${iloc} * P${iloc}z) / 3.")) + +tPropB[1][0].append(Template("-(${V}t - ${dot}*OM${iloc} * P${iloc}t)*OM${iloc} * P${iloc}t * P${iloc}x / 3. + (1 - OM${iloc} * P${iloc}t ** 2) * (${V}x - ${dot}*OM${iloc} * P${iloc}x)")) +tPropB[1][0].append(Template(" (${V}t - ${dot}*OM${iloc} * P${iloc}t) * (-1 - OM${iloc} * P${iloc}x ** 2) - OM${iloc} * P${iloc}t * P${iloc}x * (${V}x - ${dot}*OM${iloc} * P${iloc}x) / 3.")) +tPropB[1][0].append(Template(" -(${V}t - ${dot}*OM${iloc} * P${iloc}t)*OM${iloc} * P${iloc}x * P${iloc}y - OM${iloc} * P${iloc}t * P${iloc}y * (${V}x - ${dot}*OM${iloc} * P${iloc}x) + 2. / 3.*OM${iloc} * P${iloc}t * P${iloc}x * (${V}y - ${dot}*OM${iloc} * P${iloc}y)")) +tPropB[1][0].append(Template(" -(${V}t - ${dot}*OM${iloc} * P${iloc}t)*OM${iloc} * P${iloc}x * P${iloc}z - OM${iloc} * P${iloc}t * P${iloc}z * (${V}x - ${dot}*OM${iloc} * P${iloc}x) + 2. / 3.*OM${iloc} * P${iloc}t * P${iloc}x * (${V}z - ${dot}*OM${iloc} * P${iloc}z)")) +tPropB[1][1].append(Template(" -2*OM${iloc} * P${iloc}t * P${iloc}x * (${V}x - ${dot}*OM${iloc} * P${iloc}x) - 2. / 3. * (${V}t - ${dot}*OM${iloc} * P${iloc}t) * (-1 - OM${iloc} * P${iloc}x ** 2)")) +tPropB[1][1].append(Template(" 4. / 3. * (${V}x - ${dot}*OM${iloc} * P${iloc}x) * (-1 - OM${iloc} * P${iloc}x ** 2)")) +tPropB[1][1].append(Template(" -2 * (${V}x - ${dot}*OM${iloc} * P${iloc}x)*OM${iloc} * P${iloc}x * P${iloc}y - 2. / 3. * (-1 - OM${iloc} * P${iloc}x ** 2) * (${V}y - ${dot}*OM${iloc} * P${iloc}y)")) +tPropB[1][1].append(Template(" -2 * (${V}x - ${dot}*OM${iloc} * P${iloc}x)*OM${iloc} * P${iloc}x * P${iloc}z - 2. / 3. * (-1 - OM${iloc} * P${iloc}x ** 2) * (${V}z - ${dot}*OM${iloc} * P${iloc}z)")) +tPropB[1][2].append(Template(" -OM${iloc} * P${iloc}t * P${iloc}y * (${V}x - ${dot}*OM${iloc} * P${iloc}x) - OM${iloc} * P${iloc}t * P${iloc}x * (${V}y - ${dot}*OM${iloc} * P${iloc}y) + 2. / 3. * (${V}t - ${dot}*OM${iloc} * P${iloc}t)*OM${iloc} * P${iloc}x * P${iloc}y")) +tPropB[1][2].append(Template(" -(${V}x - ${dot}*OM${iloc} * P${iloc}x)*OM${iloc} * P${iloc}x * P${iloc}y / 3. + (-1 - OM${iloc} * P${iloc}x ** 2) * (${V}y - ${dot}*OM${iloc} * P${iloc}y)")) +tPropB[1][2].append(Template(" (${V}x - ${dot}*OM${iloc} * P${iloc}x) * (-1 - OM${iloc} * P${iloc}y ** 2) - OM${iloc} * P${iloc}x * P${iloc}y * (${V}y - ${dot}*OM${iloc} * P${iloc}y) / 3.")) +tPropB[1][2].append(Template("-(${V}x - ${dot}*OM${iloc} * P${iloc}x)*OM${iloc} * P${iloc}y * P${iloc}z - OM${iloc} * P${iloc}x * P${iloc}z * (${V}y - ${dot}*OM${iloc} * P${iloc}y) + 2. / 3.*OM${iloc} * P${iloc}x * P${iloc}y * (${V}z - ${dot}*OM${iloc} * P${iloc}z)")) +tPropB[1][3].append(Template("-OM${iloc} * P${iloc}t * P${iloc}z * (${V}x - ${dot}*OM${iloc} * P${iloc}x) - OM${iloc} * P${iloc}t * P${iloc}x * (${V}z - ${dot}*OM${iloc} * P${iloc}z) + 2. / 3. * (${V}t - ${dot}*OM${iloc} * P${iloc}t)*OM${iloc} * P${iloc}x * P${iloc}z")) +tPropB[1][3].append(Template(" -(${V}x - ${dot}*OM${iloc} * P${iloc}x)*OM${iloc} * P${iloc}x * P${iloc}z / 3. + (-1 - OM${iloc} * P${iloc}x ** 2) * (${V}z - ${dot}*OM${iloc} * P${iloc}z)")) +tPropB[1][3].append(Template(" -(${V}x - ${dot}*OM${iloc} * P${iloc}x)*OM${iloc} * P${iloc}y * P${iloc}z - OM${iloc} * P${iloc}x * P${iloc}y * (${V}z - ${dot}*OM${iloc} * P${iloc}z) + 2. / 3.*OM${iloc} * P${iloc}x * P${iloc}z * (${V}y - ${dot}*OM${iloc} * P${iloc}y)")) +tPropB[1][3].append(Template("(${V}x - ${dot}*OM${iloc} * P${iloc}x) * (-1 - OM${iloc} * P${iloc}z ** 2) - OM${iloc} * P${iloc}x * P${iloc}z * (${V}z - ${dot}*OM${iloc} * P${iloc}z) / 3.")) + +tPropB[2][0].append(Template(" -(${V}t - ${dot}*OM${iloc} * P${iloc}t)*OM${iloc} * P${iloc}t * P${iloc}y / 3. + (1 - OM${iloc} * P${iloc}t ** 2) * (${V}y - ${dot}*OM${iloc} * P${iloc}y)")) +tPropB[2][0].append(Template(" -(${V}t - ${dot}*OM${iloc} * P${iloc}t)*OM${iloc} * P${iloc}x * P${iloc}y - OM${iloc} * P${iloc}t * P${iloc}x * (${V}y - ${dot}*OM${iloc} * P${iloc}y) + 2. / 3.*OM${iloc} * P${iloc}t * P${iloc}y * (${V}x - ${dot}*OM${iloc} * P${iloc}x)")) +tPropB[2][0].append(Template(" (${V}t - ${dot}*OM${iloc} * P${iloc}t) * (-1 - OM${iloc} * P${iloc}y ** 2) - OM${iloc} * P${iloc}t * P${iloc}y * (${V}y - ${dot}*OM${iloc} * P${iloc}y) / 3.")) +tPropB[2][0].append(Template(" -(${V}t - ${dot}*OM${iloc} * P${iloc}t)*OM${iloc} * P${iloc}y * P${iloc}z - OM${iloc} * P${iloc}t * P${iloc}z * (${V}y - ${dot}*OM${iloc} * P${iloc}y) + 2. / 3.*OM${iloc} * P${iloc}t * P${iloc}y * (${V}z - ${dot}*OM${iloc} * P${iloc}z)")) +tPropB[2][1].append(Template("-OM${iloc} * P${iloc}t * P${iloc}y * (${V}x - ${dot}*OM${iloc} * P${iloc}x) - OM${iloc} * P${iloc}t * P${iloc}x * (${V}y - ${dot}*OM${iloc} * P${iloc}y) + 2. / 3. * (${V}t - ${dot}*OM${iloc} * P${iloc}t)*OM${iloc} * P${iloc}x * P${iloc}y")) +tPropB[2][1].append(Template("-(${V}x - ${dot}*OM${iloc} * P${iloc}x)*OM${iloc} * P${iloc}x * P${iloc}y / 3. + (-1 - OM${iloc} * P${iloc}x ** 2) * (${V}y - ${dot}*OM${iloc} * P${iloc}y)")) +tPropB[2][1].append(Template(" (${V}x - ${dot}*OM${iloc} * P${iloc}x) * (-1 - OM${iloc} * P${iloc}y ** 2) - OM${iloc} * P${iloc}x * P${iloc}y * (${V}y - ${dot}*OM${iloc} * P${iloc}y) / 3.")) +tPropB[2][1].append(Template("-(${V}x - ${dot}*OM${iloc} * P${iloc}x)*OM${iloc} * P${iloc}y * P${iloc}z - OM${iloc} * P${iloc}x * P${iloc}z * (${V}y - ${dot}*OM${iloc} * P${iloc}y) + 2. / 3.*OM${iloc} * P${iloc}x * P${iloc}y * (${V}z - ${dot}*OM${iloc} * P${iloc}z)")) +tPropB[2][2].append(Template(" -2*OM${iloc} * P${iloc}t * P${iloc}y * (${V}y - ${dot}*OM${iloc} * P${iloc}y) - 2. / 3. * (${V}t - ${dot}*OM${iloc} * P${iloc}t) * (-1 - OM${iloc} * P${iloc}y ** 2)")) +tPropB[2][2].append(Template(" -2*OM${iloc} * P${iloc}x * P${iloc}y * (${V}y - ${dot}*OM${iloc} * P${iloc}y) - 2. / 3. * (${V}x - ${dot}*OM${iloc} * P${iloc}x) * (-1 - OM${iloc} * P${iloc}y ** 2)")) +tPropB[2][2].append(Template("4. / 3. * (${V}y - ${dot}*OM${iloc} * P${iloc}y) * (-1 - OM${iloc} * P${iloc}y ** 2)")) +tPropB[2][2].append(Template(" -2 * (${V}y - ${dot}*OM${iloc} * P${iloc}y)*OM${iloc} * P${iloc}y * P${iloc}z - 2. / 3. * (-1 - OM${iloc} * P${iloc}y ** 2) * (${V}z - ${dot}*OM${iloc} * P${iloc}z)")) +tPropB[2][3].append(Template(" -OM${iloc} * P${iloc}t * P${iloc}z * (${V}y - ${dot}*OM${iloc} * P${iloc}y) - OM${iloc} * P${iloc}t * P${iloc}y * (${V}z - ${dot}*OM${iloc} * P${iloc}z) + 2. / 3. * (${V}t - ${dot}*OM${iloc} * P${iloc}t)*OM${iloc} * P${iloc}y * P${iloc}z")) +tPropB[2][3].append(Template(" -OM${iloc} * P${iloc}x * P${iloc}z * (${V}y - ${dot}*OM${iloc} * P${iloc}y) - OM${iloc} * P${iloc}x * P${iloc}y * (${V}z - ${dot}*OM${iloc} * P${iloc}z) + 2. / 3. * (${V}x - ${dot}*OM${iloc} * P${iloc}x)*OM${iloc} * P${iloc}y * P${iloc}z")) +tPropB[2][3].append(Template(" -(${V}y - ${dot}*OM${iloc} * P${iloc}y)*OM${iloc} * P${iloc}y * P${iloc}z / 3. + (-1 - OM${iloc} * P${iloc}y ** 2) * (${V}z - ${dot}*OM${iloc} * P${iloc}z)")) +tPropB[2][3].append(Template(" (${V}y - ${dot}*OM${iloc} * P${iloc}y) * (-1 - OM${iloc} * P${iloc}z ** 2) - OM${iloc} * P${iloc}y * P${iloc}z * (${V}z - ${dot}*OM${iloc} * P${iloc}z) / 3.")) + +tPropB[3][0].append(Template(" -(${V}t - ${dot}*OM${iloc} * P${iloc}t)*OM${iloc} * P${iloc}t * P${iloc}z / 3. + (1 - OM${iloc} * P${iloc}t ** 2) * (${V}z - ${dot}*OM${iloc} * P${iloc}z)")) +tPropB[3][0].append(Template(" -(${V}t - ${dot}*OM${iloc} * P${iloc}t)*OM${iloc} * P${iloc}x * P${iloc}z - OM${iloc} * P${iloc}t * P${iloc}x * (${V}z - ${dot}*OM${iloc} * P${iloc}z) + 2. / 3.*OM${iloc} * P${iloc}t * P${iloc}z * (${V}x - ${dot}*OM${iloc} * P${iloc}x)")) +tPropB[3][0].append(Template("-(${V}t - ${dot}*OM${iloc} * P${iloc}t)*OM${iloc} * P${iloc}y * P${iloc}z - OM${iloc} * P${iloc}t * P${iloc}y * (${V}z - ${dot}*OM${iloc} * P${iloc}z) + 2. / 3.*OM${iloc} * P${iloc}t * P${iloc}z * (${V}y - ${dot}*OM${iloc} * P${iloc}y)")) +tPropB[3][0].append(Template(" (${V}t - ${dot}*OM${iloc} * P${iloc}t) * (-1 - OM${iloc} * P${iloc}z ** 2) - OM${iloc} * P${iloc}t * P${iloc}z * (${V}z - ${dot}*OM${iloc} * P${iloc}z) / 3.")) +tPropB[3][1].append(Template("-OM${iloc} * P${iloc}t * P${iloc}z * (${V}x - ${dot}*OM${iloc} * P${iloc}x) - OM${iloc} * P${iloc}t * P${iloc}x * (${V}z - ${dot}*OM${iloc} * P${iloc}z) + 2. / 3. * (${V}t - ${dot}*OM${iloc} * P${iloc}t)*OM${iloc} * P${iloc}x * P${iloc}z")) +tPropB[3][1].append(Template(" -(${V}x - ${dot}*OM${iloc} * P${iloc}x)*OM${iloc} * P${iloc}x * P${iloc}z / 3. + (-1 - OM${iloc} * P${iloc}x ** 2) * (${V}z - ${dot}*OM${iloc} * P${iloc}z)")) +tPropB[3][1].append(Template(" -(${V}x - ${dot}*OM${iloc} * P${iloc}x)*OM${iloc} * P${iloc}y * P${iloc}z - OM${iloc} * P${iloc}x * P${iloc}y * (${V}z - ${dot}*OM${iloc} * P${iloc}z) + 2. / 3.*OM${iloc} * P${iloc}x * P${iloc}z * (${V}y - ${dot}*OM${iloc} * P${iloc}y)")) +tPropB[3][1].append(Template(" (${V}x - ${dot}*OM${iloc} * P${iloc}x) * (-1 - OM${iloc} * P${iloc}z ** 2) - OM${iloc} * P${iloc}x * P${iloc}z * (${V}z - ${dot}*OM${iloc} * P${iloc}z) / 3.")) +tPropB[3][2].append(Template(" -OM${iloc} * P${iloc}t * P${iloc}z * (${V}y - ${dot}*OM${iloc} * P${iloc}y) - OM${iloc} * P${iloc}t * P${iloc}y * (${V}z - ${dot}*OM${iloc} * P${iloc}z) + 2. / 3. * (${V}t - ${dot}*OM${iloc} * P${iloc}t)*OM${iloc} * P${iloc}y * P${iloc}z")) +tPropB[3][2].append(Template("-OM${iloc} * P${iloc}x * P${iloc}z * (${V}y - ${dot}*OM${iloc} * P${iloc}y) - OM${iloc} * P${iloc}x * P${iloc}y * (${V}z - ${dot}*OM${iloc} * P${iloc}z) + 2. / 3. * (${V}x - ${dot}*OM${iloc} * P${iloc}x)*OM${iloc} * P${iloc}y * P${iloc}z")) +tPropB[3][2].append(Template(" -(${V}y - ${dot}*OM${iloc} * P${iloc}y)*OM${iloc} * P${iloc}y * P${iloc}z / 3. + (-1 - OM${iloc} * P${iloc}y ** 2) * (${V}z - ${dot}*OM${iloc} * P${iloc}z)")) +tPropB[3][2].append(Template(" (${V}y - ${dot}*OM${iloc} * P${iloc}y) * (-1 - OM${iloc} * P${iloc}z ** 2) - OM${iloc} * P${iloc}y * P${iloc}z * (${V}z - ${dot}*OM${iloc} * P${iloc}z) / 3.")) +tPropB[3][3].append(Template(" -2*OM${iloc} * P${iloc}t * P${iloc}z * (${V}z - ${dot}*OM${iloc} * P${iloc}z) - 2. / 3. * (${V}t - ${dot}*OM${iloc} * P${iloc}t) * (-1 - OM${iloc} * P${iloc}z ** 2)")) +tPropB[3][3].append(Template("-2*OM${iloc} * P${iloc}x * P${iloc}z * (${V}z - ${dot}*OM${iloc} * P${iloc}z) - 2. / 3. * (${V}x - ${dot}*OM${iloc} * P${iloc}x) * (-1 - OM${iloc} * P${iloc}z ** 2)")) +tPropB[3][3].append(Template("-2*OM${iloc} * P${iloc}y * P${iloc}z * (${V}z - ${dot}*OM${iloc} * P${iloc}z) - 2. / 3. * (${V}y - ${dot}*OM${iloc} * P${iloc}y) * (-1 - OM${iloc} * P${iloc}z ** 2)")) +tPropB[3][3].append(Template("4. / 3. * (${V}z - ${dot}*OM${iloc} * P${iloc}z) * (-1 - OM${iloc} * P${iloc}z ** 2)")) + +# tensor propagator, no contracted indices +tPropC=[[[[],[],[],[]],[[],[],[],[]],[[],[],[],[]],[[],[],[],[]]], + [[[],[],[],[]],[[],[],[],[]],[[],[],[],[]],[[],[],[],[]]], + [[[],[],[],[]],[[],[],[],[]],[[],[],[],[]],[[],[],[],[]]], + [[[],[],[],[]],[[],[],[],[]],[[],[],[],[]],[[],[],[],[]]]] +tPropC[0][0][0].append(Template("4./3. * (1 - OM${iloc} * P${iloc}t ** 2) ** 2")) +tPropC[0][0][0].append(Template("-4./3. * (1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}t * P${iloc}x")) +tPropC[0][0][0].append(Template("-4./3. * (1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}t * P${iloc}y")) +tPropC[0][0][0].append(Template("-4./3. * (1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}t * P${iloc}z")) +tPropC[0][0][1].append(Template("-4./3. * (1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}t * P${iloc}x")) +tPropC[0][0][1].append(Template("2*OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}x ** 2 - 2./3. * (1 - OM${iloc} * P${iloc}t ** 2) * (-1 - OM${iloc} * P${iloc}x ** 2)")) +tPropC[0][0][1].append(Template("2*OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}x * P${iloc}y + 2./3. * (1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}x * P${iloc}y")) +tPropC[0][0][1].append(Template("2*OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}x * P${iloc}z + 2./3. * (1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}x * P${iloc}z")) +tPropC[0][0][2].append(Template("-4./3. * (1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}t * P${iloc}y")) +tPropC[0][0][2].append(Template("2*OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}x * P${iloc}y + 2./3. * (1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}x * P${iloc}y")) +tPropC[0][0][2].append(Template("2*OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}y ** 2 - 2./3. * (1 - OM${iloc} * P${iloc}t ** 2) * (-1 - OM${iloc} * P${iloc}y ** 2)")) +tPropC[0][0][2].append(Template("2*OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}y * P${iloc}z + 2./3. * (1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}y * P${iloc}z")) +tPropC[0][0][3].append(Template("-4./3. * (1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}t * P${iloc}z")) +tPropC[0][0][3].append(Template("2*OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}x * P${iloc}z + 2./3. * (1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}x * P${iloc}z")) +tPropC[0][0][3].append(Template("2*OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}y * P${iloc}z + 2./3. * (1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}y * P${iloc}z")) +tPropC[0][0][3].append(Template("2*OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}z ** 2 - 2./3. * (1 - OM${iloc} * P${iloc}t ** 2) * (-1 - OM${iloc} * P${iloc}z ** 2)")) + +tPropC[0][1][0].append(Template("-4./3. * (1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}t * P${iloc}x")) +tPropC[0][1][0].append(Template("(1 - OM${iloc} * P${iloc}t ** 2) * (-1 - OM${iloc} * P${iloc}x ** 2) + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}x ** 2 /3.")) +tPropC[0][1][0].append(Template("-(1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}x * P${iloc}y + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}x * P${iloc}y /3.")) +tPropC[0][1][0].append(Template("-(1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}x * P${iloc}z + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}x * P${iloc}z /3.")) +tPropC[0][1][1].append(Template("(1 - OM${iloc} * P${iloc}t ** 2) * (-1 - OM${iloc} * P${iloc}x ** 2) + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}x ** 2 /3.")) +tPropC[0][1][1].append(Template("-4./3.*OM${iloc} * P${iloc}t * P${iloc}x * (-1 - OM${iloc} * P${iloc}x ** 2)")) +tPropC[0][1][1].append(Template("OM${iloc}**2 * P${iloc}t * P${iloc}x ** 2 * P${iloc}y /3. - OM${iloc} * P${iloc}t * P${iloc}y * (-1 - OM${iloc} * P${iloc}x ** 2)")) +tPropC[0][1][1].append(Template("OM${iloc}**2 * P${iloc}t * P${iloc}x ** 2 * P${iloc}z /3. - OM${iloc} * P${iloc}t * P${iloc}z * (-1 - OM${iloc} * P${iloc}x ** 2)")) +tPropC[0][1][2].append(Template("-(1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}x * P${iloc}y + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}x * P${iloc}y /3.")) +tPropC[0][1][2].append(Template("OM${iloc}**2 * P${iloc}t * P${iloc}x ** 2 * P${iloc}y /3. - OM${iloc} * P${iloc}t * P${iloc}y * (-1 - OM${iloc} * P${iloc}x ** 2)")) +tPropC[0][1][2].append(Template("2*OM${iloc}**2 * P${iloc}t * P${iloc}y ** 2 * P${iloc}x + 2./3.*OM${iloc} * P${iloc}t * P${iloc}x * (-1 - OM${iloc} * P${iloc}y ** 2)")) +tPropC[0][1][2].append(Template("4./3.*OM${iloc}**2 * P${iloc}t * P${iloc}y * P${iloc}x * P${iloc}z")) +tPropC[0][1][3].append(Template("-(1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}x * P${iloc}z + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}x * P${iloc}z /3.")) +tPropC[0][1][3].append(Template("OM${iloc}**2 * P${iloc}t * P${iloc}x ** 2 * P${iloc}z /3. - OM${iloc} * P${iloc}t * P${iloc}z * (-1 - OM${iloc} * P${iloc}x ** 2)")) +tPropC[0][1][3].append(Template("4./3.*OM${iloc}**2 * P${iloc}t * P${iloc}y * P${iloc}x * P${iloc}z")) +tPropC[0][1][3].append(Template("2*OM${iloc}**2 * P${iloc}t * P${iloc}z ** 2 * P${iloc}x + 2./3.*OM${iloc} * P${iloc}t * P${iloc}x * (-1 - OM${iloc} * P${iloc}z ** 2)")) + +tPropC[0][2][0].append(Template("-4./3. * (1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}t * P${iloc}y")) +tPropC[0][2][0].append(Template("-(1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}x * P${iloc}y + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}x * P${iloc}y /3.")) +tPropC[0][2][0].append(Template("(1 - OM${iloc} * P${iloc}t ** 2) * (-1 - OM${iloc} * P${iloc}y ** 2) + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}y ** 2 /3.")) +tPropC[0][2][0].append(Template("-(1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}y * P${iloc}z + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}y * P${iloc}z /3.")) +tPropC[0][2][1].append(Template("-(1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}x * P${iloc}y + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}x * P${iloc}y /3.")) +tPropC[0][2][1].append(Template("2*OM${iloc}**2 * P${iloc}t * P${iloc}x ** 2 * P${iloc}y + 2./3.*OM${iloc} * P${iloc}t * P${iloc}y * (-1 - OM${iloc} * P${iloc}x ** 2)")) +tPropC[0][2][1].append(Template("-OM${iloc} * P${iloc}t * P${iloc}x * (-1 - OM${iloc} * P${iloc}y ** 2) + OM${iloc}**2 * P${iloc}t * P${iloc}y ** 2 * P${iloc}x /3.")) +tPropC[0][2][1].append(Template("4./3.*OM${iloc}**2 * P${iloc}t * P${iloc}y * P${iloc}x * P${iloc}z")) +tPropC[0][2][2].append(Template("(1 - OM${iloc} * P${iloc}t ** 2) * (-1 - OM${iloc} * P${iloc}y ** 2) + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}y ** 2 /3.")) +tPropC[0][2][2].append(Template("-OM${iloc} * P${iloc}t * P${iloc}x * (-1 - OM${iloc} * P${iloc}y ** 2) + OM${iloc}**2 * P${iloc}t * P${iloc}y ** 2 * P${iloc}x /3.")) +tPropC[0][2][2].append(Template("-4./3.*OM${iloc} * P${iloc}t * P${iloc}y * (-1 - OM${iloc} * P${iloc}y ** 2)")) +tPropC[0][2][2].append(Template("OM${iloc}**2 * P${iloc}t * P${iloc}y ** 2 * P${iloc}z /3. - OM${iloc} * P${iloc}t * P${iloc}z * (-1 - OM${iloc} * P${iloc}y ** 2)")) +tPropC[0][2][3].append(Template("-(1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}y * P${iloc}z + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}y * P${iloc}z /3.")) +tPropC[0][2][3].append(Template("4./3.*OM${iloc}**2 * P${iloc}t * P${iloc}y * P${iloc}x * P${iloc}z")) +tPropC[0][2][3].append(Template("OM${iloc}**2 * P${iloc}t * P${iloc}y ** 2 * P${iloc}z /3. - OM${iloc} * P${iloc}t * P${iloc}z * (-1 - OM${iloc} * P${iloc}y ** 2)")) +tPropC[0][2][3].append(Template("2*OM${iloc}**2 * P${iloc}t * P${iloc}z ** 2 * P${iloc}y + 2./3.*OM${iloc} * P${iloc}t * P${iloc}y * (-1 - OM${iloc} * P${iloc}z ** 2)")) + +tPropC[0][3][0].append(Template("-4./3. * (1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}t * P${iloc}z")) +tPropC[0][3][0].append(Template("-(1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}x * P${iloc}z + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}x * P${iloc}z /3.")) +tPropC[0][3][0].append(Template("-(1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}y * P${iloc}z + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}y * P${iloc}z /3.")) +tPropC[0][3][0].append(Template("(1 - OM${iloc} * P${iloc}t ** 2) * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}z ** 2 /3.")) +tPropC[0][3][1].append(Template("-(1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}x * P${iloc}z + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}x * P${iloc}z /3.")) +tPropC[0][3][1].append(Template("2*OM${iloc}**2 * P${iloc}t * P${iloc}x ** 2 * P${iloc}z + 2./3.*OM${iloc} * P${iloc}t * P${iloc}z * (-1 - OM${iloc} * P${iloc}x ** 2)")) +tPropC[0][3][1].append(Template("4./3.*OM${iloc}**2 * P${iloc}t * P${iloc}y * P${iloc}x * P${iloc}z")) +tPropC[0][3][1].append(Template("-OM${iloc} * P${iloc}t * P${iloc}x * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}t * P${iloc}z ** 2 * P${iloc}x /3.")) +tPropC[0][3][2].append(Template("-(1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}y * P${iloc}z + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}y * P${iloc}z /3.")) +tPropC[0][3][2].append(Template("4./3.*OM${iloc}**2 * P${iloc}t * P${iloc}y * P${iloc}x * P${iloc}z")) +tPropC[0][3][2].append(Template("2*OM${iloc}**2 * P${iloc}t * P${iloc}y ** 2 * P${iloc}z + 2./3.*OM${iloc} * P${iloc}t * P${iloc}z * (-1 - OM${iloc} * P${iloc}y ** 2)")) +tPropC[0][3][2].append(Template("-OM${iloc} * P${iloc}t * P${iloc}y * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}t * P${iloc}z ** 2 * P${iloc}y /3.")) +tPropC[0][3][3].append(Template("(1 - OM${iloc} * P${iloc}t ** 2) * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}z ** 2 /3.")) +tPropC[0][3][3].append(Template("-OM${iloc} * P${iloc}t * P${iloc}x * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}t * P${iloc}z ** 2 * P${iloc}x /3.")) +tPropC[0][3][3].append(Template("-OM${iloc} * P${iloc}t * P${iloc}y * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}t * P${iloc}z ** 2 * P${iloc}y /3.")) +tPropC[0][3][3].append(Template("-4./3.*OM${iloc} * P${iloc}t * P${iloc}z * (-1 - OM${iloc} * P${iloc}z ** 2)")) + +tPropC[1][0][0].append(Template(" -4./3. * (1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}t * P${iloc}x")) +tPropC[1][0][0].append(Template(" (1 - OM${iloc} * P${iloc}t ** 2) * (-1 - OM${iloc} * P${iloc}x ** 2) + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}x ** 2 /3.")) +tPropC[1][0][0].append(Template(" -(1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}x * P${iloc}y + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}x * P${iloc}y /3.")) +tPropC[1][0][0].append(Template(" -(1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}x * P${iloc}z + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}x * P${iloc}z /3.")) +tPropC[1][0][1].append(Template(" (1 - OM${iloc} * P${iloc}t ** 2) * (-1 - OM${iloc} * P${iloc}x ** 2) + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}x ** 2 /3.")) +tPropC[1][0][1].append(Template(" -4./3.*OM${iloc} * P${iloc}t * P${iloc}x * (-1 - OM${iloc} * P${iloc}x ** 2)")) +tPropC[1][0][1].append(Template(" OM${iloc}**2 * P${iloc}t * P${iloc}x ** 2 * P${iloc}y /3. - OM${iloc} * P${iloc}t * P${iloc}y * (-1 - OM${iloc} * P${iloc}x ** 2)")) +tPropC[1][0][1].append(Template(" OM${iloc}**2 * P${iloc}t * P${iloc}x ** 2 * P${iloc}z /3. - OM${iloc} * P${iloc}t * P${iloc}z * (-1 - OM${iloc} * P${iloc}x ** 2)")) +tPropC[1][0][2].append(Template(" -(1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}x * P${iloc}y + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}x * P${iloc}y /3.")) +tPropC[1][0][2].append(Template(" OM${iloc}**2 * P${iloc}t * P${iloc}x ** 2 * P${iloc}y /3. - OM${iloc} * P${iloc}t * P${iloc}y * (-1 - OM${iloc} * P${iloc}x ** 2)")) +tPropC[1][0][2].append(Template(" 2*OM${iloc}**2 * P${iloc}t * P${iloc}y ** 2 * P${iloc}x + 2./3.*OM${iloc} * P${iloc}t * P${iloc}x * (-1 - OM${iloc} * P${iloc}y ** 2)")) +tPropC[1][0][2].append(Template(" 4./3.*OM${iloc}**2 * P${iloc}t * P${iloc}y * P${iloc}x * P${iloc}z")) +tPropC[1][0][3].append(Template(" -(1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}x * P${iloc}z + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}x * P${iloc}z /3.")) +tPropC[1][0][3].append(Template(" OM${iloc}**2 * P${iloc}t * P${iloc}x ** 2 * P${iloc}z /3. - OM${iloc} * P${iloc}t * P${iloc}z * (-1 - OM${iloc} * P${iloc}x ** 2)")) +tPropC[1][0][3].append(Template(" 4./3.*OM${iloc}**2 * P${iloc}t * P${iloc}y * P${iloc}x * P${iloc}z")) +tPropC[1][0][3].append(Template(" 2*OM${iloc}**2 * P${iloc}t * P${iloc}z ** 2 * P${iloc}x + 2./3.*OM${iloc} * P${iloc}t * P${iloc}x * (-1 - OM${iloc} * P${iloc}z ** 2)")) +tPropC[1][1][0].append(Template(" 2*OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}x ** 2 - 2./3. * (1 - OM${iloc} * P${iloc}t ** 2) * (-1 - OM${iloc} * P${iloc}x ** 2)")) +tPropC[1][1][0].append(Template(" -4./3.*OM${iloc} * P${iloc}t * P${iloc}x * (-1 - OM${iloc} * P${iloc}x ** 2)")) +tPropC[1][1][0].append(Template(" 2*OM${iloc}**2 * P${iloc}t * P${iloc}x ** 2 * P${iloc}y + 2./3.*OM${iloc} * P${iloc}t * P${iloc}y * (-1 - OM${iloc} * P${iloc}x ** 2)")) +tPropC[1][1][0].append(Template(" 2*OM${iloc}**2 * P${iloc}t * P${iloc}x ** 2 * P${iloc}z + 2./3.*OM${iloc} * P${iloc}t * P${iloc}z * (-1 - OM${iloc} * P${iloc}x ** 2)")) +tPropC[1][1][1].append(Template(" -4./3.*OM${iloc} * P${iloc}t * P${iloc}x * (-1 - OM${iloc} * P${iloc}x ** 2)")) +tPropC[1][1][1].append(Template(" 4./3. * (-1 - OM${iloc} * P${iloc}x ** 2) ** 2")) +tPropC[1][1][1].append(Template(" -4./3. * (-1 - OM${iloc} * P${iloc}x ** 2)*OM${iloc} * P${iloc}x * P${iloc}y")) +tPropC[1][1][1].append(Template(" -4./3. * (-1 - OM${iloc} * P${iloc}x ** 2)*OM${iloc} * P${iloc}x * P${iloc}z")) +tPropC[1][1][2].append(Template(" 2*OM${iloc}**2 * P${iloc}t * P${iloc}x ** 2 * P${iloc}y + 2./3.*OM${iloc} * P${iloc}t * P${iloc}y * (-1 - OM${iloc} * P${iloc}x ** 2)")) +tPropC[1][1][2].append(Template(" -4./3. * (-1 - OM${iloc} * P${iloc}x ** 2)*OM${iloc} * P${iloc}x * P${iloc}y")) +tPropC[1][1][2].append(Template(" 2*OM${iloc}**2 * P${iloc}x ** 2 * P${iloc}y ** 2 - 2./3. * (-1 - OM${iloc} * P${iloc}x ** 2) * (-1 - OM${iloc} * P${iloc}y ** 2)")) +tPropC[1][1][2].append(Template(" 2*OM${iloc}**2 * P${iloc}x ** 2 * P${iloc}y * P${iloc}z + 2./3. * (-1 - OM${iloc} * P${iloc}x ** 2)*OM${iloc} * P${iloc}y * P${iloc}z")) +tPropC[1][1][3].append(Template(" 2*OM${iloc}**2 * P${iloc}t * P${iloc}x ** 2 * P${iloc}z + 2./3.*OM${iloc} * P${iloc}t * P${iloc}z * (-1 - OM${iloc} * P${iloc}x ** 2)")) +tPropC[1][1][3].append(Template(" -4./3. * (-1 - OM${iloc} * P${iloc}x ** 2)*OM${iloc} * P${iloc}x * P${iloc}z")) +tPropC[1][1][3].append(Template(" 2*OM${iloc}**2 * P${iloc}x ** 2 * P${iloc}y * P${iloc}z + 2./3. * (-1 - OM${iloc} * P${iloc}x ** 2)*OM${iloc} * P${iloc}y * P${iloc}z")) +tPropC[1][1][3].append(Template(" 2*OM${iloc}**2 * P${iloc}x ** 2 * P${iloc}z ** 2 - 2./3. * (-1 - OM${iloc} * P${iloc}x ** 2) * (-1 - OM${iloc} * P${iloc}z ** 2)")) + +tPropC[1][2][0].append(Template("2*OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}x * P${iloc}y + 2./3. * (1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}x * P${iloc}y")) +tPropC[1][2][0].append(Template("OM${iloc}**2 * P${iloc}t * P${iloc}x ** 2 * P${iloc}y /3. - OM${iloc} * P${iloc}t * P${iloc}y * (-1 - OM${iloc} * P${iloc}x ** 2)")) +tPropC[1][2][0].append(Template("-OM${iloc} * P${iloc}t * P${iloc}x * (-1 - OM${iloc} * P${iloc}y ** 2) + OM${iloc}**2 * P${iloc}t * P${iloc}y ** 2 * P${iloc}x /3.")) +tPropC[1][2][0].append(Template("4./3.*OM${iloc}**2 * P${iloc}t * P${iloc}y * P${iloc}x * P${iloc}z ")) +tPropC[1][2][1].append(Template("OM${iloc}**2 * P${iloc}t * P${iloc}x ** 2 * P${iloc}y /3. - OM${iloc} * P${iloc}t * P${iloc}y * (-1 - OM${iloc} * P${iloc}x ** 2)")) +tPropC[1][2][1].append(Template(" -4./3. * (-1 - OM${iloc} * P${iloc}x ** 2)*OM${iloc} * P${iloc}x * P${iloc}y ")) +tPropC[1][2][1].append(Template(" (-1 - OM${iloc} * P${iloc}x ** 2) * (-1 - OM${iloc} * P${iloc}y ** 2) + OM${iloc}**2 * P${iloc}x ** 2 * P${iloc}y ** 2 /3. ")) +tPropC[1][2][1].append(Template(" -(-1 - OM${iloc} * P${iloc}x ** 2)*OM${iloc} * P${iloc}y * P${iloc}z + OM${iloc}**2 * P${iloc}x ** 2 * P${iloc}y * P${iloc}z /3.")) +tPropC[1][2][2].append(Template(" -OM${iloc} * P${iloc}t * P${iloc}x * (-1 - OM${iloc} * P${iloc}y ** 2) + OM${iloc}**2 * P${iloc}t * P${iloc}y ** 2 * P${iloc}x /3.")) +tPropC[1][2][2].append(Template(" (-1 - OM${iloc} * P${iloc}x ** 2) * (-1 - OM${iloc} * P${iloc}y ** 2) + OM${iloc}**2 * P${iloc}x ** 2 * P${iloc}y ** 2 /3. ")) +tPropC[1][2][2].append(Template(" -4./3.*OM${iloc} * P${iloc}x * P${iloc}y * (-1 - OM${iloc} * P${iloc}y ** 2) ")) +tPropC[1][2][2].append(Template(" OM${iloc}**2 * P${iloc}x * P${iloc}y ** 2 * P${iloc}z /3. - OM${iloc} * P${iloc}x * P${iloc}z * (-1 - OM${iloc} * P${iloc}y ** 2)")) +tPropC[1][2][3].append(Template(" 4./3.*OM${iloc}**2 * P${iloc}t * P${iloc}y * P${iloc}x * P${iloc}z ")) +tPropC[1][2][3].append(Template(" -(-1 - OM${iloc} * P${iloc}x ** 2)*OM${iloc} * P${iloc}y * P${iloc}z + OM${iloc}**2 * P${iloc}x ** 2 * P${iloc}y * P${iloc}z /3.")) +tPropC[1][2][3].append(Template(" OM${iloc}**2 * P${iloc}x * P${iloc}y ** 2 * P${iloc}z /3. - OM${iloc} * P${iloc}x * P${iloc}z * (-1 - OM${iloc} * P${iloc}y ** 2)")) +tPropC[1][2][3].append(Template(" 2*OM${iloc}**2 * P${iloc}x * P${iloc}z ** 2 * P${iloc}y + 2./3.*OM${iloc} * P${iloc}x * P${iloc}y * (-1 - OM${iloc} * P${iloc}z ** 2)")) + +tPropC[1][3][0].append(Template("2*OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}x * P${iloc}z + 2./3. * (1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}x * P${iloc}z")) +tPropC[1][3][0].append(Template("OM${iloc}**2 * P${iloc}t * P${iloc}x ** 2 * P${iloc}z /3. - OM${iloc} * P${iloc}t * P${iloc}z * (-1 - OM${iloc} * P${iloc}x ** 2)")) +tPropC[1][3][0].append(Template("4./3.*OM${iloc}**2 * P${iloc}t * P${iloc}y * P${iloc}x * P${iloc}z ")) +tPropC[1][3][0].append(Template("-OM${iloc} * P${iloc}t * P${iloc}x * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}t * P${iloc}z ** 2 * P${iloc}x /3.")) +tPropC[1][3][1].append(Template("OM${iloc}**2 * P${iloc}t * P${iloc}x ** 2 * P${iloc}z /3. - OM${iloc} * P${iloc}t * P${iloc}z * (-1 - OM${iloc} * P${iloc}x ** 2)")) +tPropC[1][3][1].append(Template("-4./3. * (-1 - OM${iloc} * P${iloc}x ** 2)*OM${iloc} * P${iloc}x * P${iloc}z ")) +tPropC[1][3][1].append(Template("-(-1 - OM${iloc} * P${iloc}x ** 2)*OM${iloc} * P${iloc}y * P${iloc}z + OM${iloc}**2 * P${iloc}x ** 2 * P${iloc}y * P${iloc}z /3.")) +tPropC[1][3][1].append(Template("(-1 - OM${iloc} * P${iloc}x ** 2) * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}x ** 2 * P${iloc}z ** 2 /3. ")) +tPropC[1][3][2].append(Template("4./3.*OM${iloc}**2 * P${iloc}t * P${iloc}y * P${iloc}x * P${iloc}z ")) +tPropC[1][3][2].append(Template("-(-1 - OM${iloc} * P${iloc}x ** 2)*OM${iloc} * P${iloc}y * P${iloc}z + OM${iloc}**2 * P${iloc}x ** 2 * P${iloc}y * P${iloc}z /3.")) +tPropC[1][3][2].append(Template("2*OM${iloc}**2 * P${iloc}x * P${iloc}y ** 2 * P${iloc}z + 2./3.*OM${iloc} * P${iloc}x * P${iloc}z * (-1 - OM${iloc} * P${iloc}y ** 2)")) +tPropC[1][3][2].append(Template("-OM${iloc} * P${iloc}x * P${iloc}y * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}x * P${iloc}z ** 2 * P${iloc}y /3.")) +tPropC[1][3][3].append(Template("-OM${iloc} * P${iloc}t * P${iloc}x * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}t * P${iloc}z ** 2 * P${iloc}x /3.")) +tPropC[1][3][3].append(Template("(-1 - OM${iloc} * P${iloc}x ** 2) * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}x ** 2 * P${iloc}z ** 2 /3. ")) +tPropC[1][3][3].append(Template("-OM${iloc} * P${iloc}x * P${iloc}y * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}x * P${iloc}z ** 2 * P${iloc}y /3.")) +tPropC[1][3][3].append(Template("-4./3.*OM${iloc} * P${iloc}x * P${iloc}z * (-1 - OM${iloc} * P${iloc}z ** 2)")) + +tPropC[2][0][0].append(Template("-4./3. * (1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}t * P${iloc}y ")) +tPropC[2][0][0].append(Template("-(1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}x * P${iloc}y + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}x * P${iloc}y /3. ")) +tPropC[2][0][0].append(Template("(1 - OM${iloc} * P${iloc}t ** 2) * (-1 - OM${iloc} * P${iloc}y ** 2) + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}y ** 2 /3. ")) +tPropC[2][0][0].append(Template("-(1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}y * P${iloc}z + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}y * P${iloc}z /3. ")) +tPropC[2][0][1].append(Template("-(1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}x * P${iloc}y + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}x * P${iloc}y /3. ")) +tPropC[2][0][1].append(Template("2*OM${iloc}**2 * P${iloc}t * P${iloc}x ** 2 * P${iloc}y + 2./3.*OM${iloc} * P${iloc}t * P${iloc}y * (-1 - OM${iloc} * P${iloc}x ** 2)")) +tPropC[2][0][1].append(Template("-OM${iloc} * P${iloc}t * P${iloc}x * (-1 - OM${iloc} * P${iloc}y ** 2) + OM${iloc}**2 * P${iloc}t * P${iloc}y ** 2 * P${iloc}x /3.")) +tPropC[2][0][1].append(Template("4./3.*OM${iloc}**2 * P${iloc}t * P${iloc}y * P${iloc}x * P${iloc}z ")) +tPropC[2][0][2].append(Template("(1 - OM${iloc} * P${iloc}t ** 2) * (-1 - OM${iloc} * P${iloc}y ** 2) + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}y ** 2 /3. ")) +tPropC[2][0][2].append(Template("-OM${iloc} * P${iloc}t * P${iloc}x * (-1 - OM${iloc} * P${iloc}y ** 2) + OM${iloc}**2 * P${iloc}t * P${iloc}y ** 2 * P${iloc}x /3.")) +tPropC[2][0][2].append(Template("-4./3.*OM${iloc} * P${iloc}t * P${iloc}y * (-1 - OM${iloc} * P${iloc}y ** 2) ")) +tPropC[2][0][2].append(Template("OM${iloc}**2 * P${iloc}t * P${iloc}y ** 2 * P${iloc}z /3. - OM${iloc} * P${iloc}t * P${iloc}z * (-1 - OM${iloc} * P${iloc}y ** 2)")) +tPropC[2][0][3].append(Template("-(1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}y * P${iloc}z + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}y * P${iloc}z /3. ")) +tPropC[2][0][3].append(Template("4./3.*OM${iloc}**2 * P${iloc}t * P${iloc}y * P${iloc}x * P${iloc}z ")) +tPropC[2][0][3].append(Template("OM${iloc}**2 * P${iloc}t * P${iloc}y ** 2 * P${iloc}z /3. - OM${iloc} * P${iloc}t * P${iloc}z * (-1 - OM${iloc} * P${iloc}y ** 2)")) +tPropC[2][0][3].append(Template("2*OM${iloc}**2 * P${iloc}t * P${iloc}z ** 2 * P${iloc}y + 2./3.*OM${iloc} * P${iloc}t * P${iloc}y * (-1 - OM${iloc} * P${iloc}z ** 2)")) + +tPropC[2][1][0].append(Template("2*OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}x * P${iloc}y + 2./3. * (1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}x * P${iloc}y")) +tPropC[2][1][0].append(Template("OM${iloc}**2 * P${iloc}t * P${iloc}x ** 2 * P${iloc}y /3. - OM${iloc} * P${iloc}t * P${iloc}y * (-1 - OM${iloc} * P${iloc}x ** 2)")) +tPropC[2][1][0].append(Template("-OM${iloc} * P${iloc}t * P${iloc}x * (-1 - OM${iloc} * P${iloc}y ** 2) + OM${iloc}**2 * P${iloc}t * P${iloc}y ** 2 * P${iloc}x /3.")) +tPropC[2][1][0].append(Template("4./3.*OM${iloc}**2 * P${iloc}t * P${iloc}y * P${iloc}x * P${iloc}z ")) +tPropC[2][1][1].append(Template("OM${iloc}**2 * P${iloc}t * P${iloc}x ** 2 * P${iloc}y /3. - OM${iloc} * P${iloc}t * P${iloc}y * (-1 - OM${iloc} * P${iloc}x ** 2)")) +tPropC[2][1][1].append(Template("-4./3. * (-1 - OM${iloc} * P${iloc}x ** 2)*OM${iloc} * P${iloc}x * P${iloc}y ")) +tPropC[2][1][1].append(Template("(-1 - OM${iloc} * P${iloc}x ** 2) * (-1 - OM${iloc} * P${iloc}y ** 2) + OM${iloc}**2 * P${iloc}x ** 2 * P${iloc}y ** 2 /3. ")) +tPropC[2][1][1].append(Template("-(-1 - OM${iloc} * P${iloc}x ** 2)*OM${iloc} * P${iloc}y * P${iloc}z + OM${iloc}**2 * P${iloc}x ** 2 * P${iloc}y * P${iloc}z /3.")) +tPropC[2][1][2].append(Template("-OM${iloc} * P${iloc}t * P${iloc}x * (-1 - OM${iloc} * P${iloc}y ** 2) + OM${iloc}**2 * P${iloc}t * P${iloc}y ** 2 * P${iloc}x /3.")) +tPropC[2][1][2].append(Template("(-1 - OM${iloc} * P${iloc}x ** 2) * (-1 - OM${iloc} * P${iloc}y ** 2) + OM${iloc}**2 * P${iloc}x ** 2 * P${iloc}y ** 2 /3. ")) +tPropC[2][1][2].append(Template("-4./3.*OM${iloc} * P${iloc}x * P${iloc}y * (-1 - OM${iloc} * P${iloc}y ** 2) ")) +tPropC[2][1][2].append(Template("OM${iloc}**2 * P${iloc}x * P${iloc}y ** 2 * P${iloc}z /3. - OM${iloc} * P${iloc}x * P${iloc}z * (-1 - OM${iloc} * P${iloc}y ** 2)")) +tPropC[2][1][3].append(Template("4./3.*OM${iloc}**2 * P${iloc}t * P${iloc}y * P${iloc}x * P${iloc}z ")) +tPropC[2][1][3].append(Template("-(-1 - OM${iloc} * P${iloc}x ** 2)*OM${iloc} * P${iloc}y * P${iloc}z + OM${iloc}**2 * P${iloc}x ** 2 * P${iloc}y * P${iloc}z /3.")) +tPropC[2][1][3].append(Template("OM${iloc}**2 * P${iloc}x * P${iloc}y ** 2 * P${iloc}z /3. - OM${iloc} * P${iloc}x * P${iloc}z * (-1 - OM${iloc} * P${iloc}y ** 2)")) +tPropC[2][1][3].append(Template("2*OM${iloc}**2 * P${iloc}x * P${iloc}z ** 2 * P${iloc}y + 2./3.*OM${iloc} * P${iloc}x * P${iloc}y * (-1 - OM${iloc} * P${iloc}z ** 2)")) + +tPropC[2][2][0].append(Template("2*OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}y ** 2 - 2./3. * (1 - OM${iloc} * P${iloc}t ** 2) * (-1 - OM${iloc} * P${iloc}y ** 2) ")) +tPropC[2][2][0].append(Template("2*OM${iloc}**2 * P${iloc}t * P${iloc}y ** 2 * P${iloc}x + 2./3.*OM${iloc} * P${iloc}t * P${iloc}x * (-1 - OM${iloc} * P${iloc}y ** 2) ")) +tPropC[2][2][0].append(Template("-4./3.*OM${iloc} * P${iloc}t * P${iloc}y * (-1 - OM${iloc} * P${iloc}y ** 2) ")) +tPropC[2][2][0].append(Template("2*OM${iloc}**2 * P${iloc}t * P${iloc}y ** 2 * P${iloc}z + 2./3.*OM${iloc} * P${iloc}t * P${iloc}z * (-1 - OM${iloc} * P${iloc}y ** 2) ")) +tPropC[2][2][1].append(Template("2*OM${iloc}**2 * P${iloc}t * P${iloc}y ** 2 * P${iloc}x + 2./3.*OM${iloc} * P${iloc}t * P${iloc}x * (-1 - OM${iloc} * P${iloc}y ** 2) ")) +tPropC[2][2][1].append(Template("2*OM${iloc}**2 * P${iloc}x ** 2 * P${iloc}y ** 2 - 2./3. * (-1 - OM${iloc} * P${iloc}x ** 2) * (-1 - OM${iloc} * P${iloc}y ** 2) ")) +tPropC[2][2][1].append(Template("-4./3.*OM${iloc} * P${iloc}x * P${iloc}y * (-1 - OM${iloc} * P${iloc}y ** 2) ")) +tPropC[2][2][1].append(Template("2*OM${iloc}**2 * P${iloc}x * P${iloc}y ** 2 * P${iloc}z + 2./3.*OM${iloc} * P${iloc}x * P${iloc}z * (-1 - OM${iloc} * P${iloc}y ** 2) ")) +tPropC[2][2][2].append(Template("-4./3.*OM${iloc} * P${iloc}t * P${iloc}y * (-1 - OM${iloc} * P${iloc}y ** 2) ")) +tPropC[2][2][2].append(Template("-4./3.*OM${iloc} * P${iloc}x * P${iloc}y * (-1 - OM${iloc} * P${iloc}y ** 2) ")) +tPropC[2][2][2].append(Template("4./3. * (-1 - OM${iloc} * P${iloc}y ** 2) ** 2 ")) +tPropC[2][2][2].append(Template("-4./3. * (-1 - OM${iloc} * P${iloc}y ** 2)*OM${iloc} * P${iloc}y * P${iloc}z ")) +tPropC[2][2][3].append(Template("2*OM${iloc}**2 * P${iloc}t * P${iloc}y ** 2 * P${iloc}z + 2./3.*OM${iloc} * P${iloc}t * P${iloc}z * (-1 - OM${iloc} * P${iloc}y ** 2) ")) +tPropC[2][2][3].append(Template("2*OM${iloc}**2 * P${iloc}x * P${iloc}y ** 2 * P${iloc}z + 2./3.*OM${iloc} * P${iloc}x * P${iloc}z * (-1 - OM${iloc} * P${iloc}y ** 2) ")) +tPropC[2][2][3].append(Template("-4./3. * (-1 - OM${iloc} * P${iloc}y ** 2)*OM${iloc} * P${iloc}y * P${iloc}z ")) +tPropC[2][2][3].append(Template("2*OM${iloc}**2 * P${iloc}y ** 2 * P${iloc}z ** 2 - 2./3. * (-1 - OM${iloc} * P${iloc}y ** 2) * (-1 - OM${iloc} * P${iloc}z ** 2)")) + +tPropC[2][3][0].append(Template(" 2*OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}y * P${iloc}z + 2./3. * (1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}y * P${iloc}z")) +tPropC[2][3][0].append(Template(" 4./3.*OM${iloc}**2 * P${iloc}t * P${iloc}y * P${iloc}x * P${iloc}z ")) +tPropC[2][3][0].append(Template(" OM${iloc}**2 * P${iloc}t * P${iloc}y ** 2 * P${iloc}z /3. - OM${iloc} * P${iloc}t * P${iloc}z * (-1 - OM${iloc} * P${iloc}y ** 2)")) +tPropC[2][3][0].append(Template(" -OM${iloc} * P${iloc}t * P${iloc}y * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}t * P${iloc}z ** 2 * P${iloc}y /3.")) +tPropC[2][3][1].append(Template(" 4./3.*OM${iloc}**2 * P${iloc}t * P${iloc}y * P${iloc}x * P${iloc}z ")) +tPropC[2][3][1].append(Template(" 2*OM${iloc}**2 * P${iloc}x ** 2 * P${iloc}y * P${iloc}z + 2./3. * (-1 - OM${iloc} * P${iloc}x ** 2)*OM${iloc} * P${iloc}y * P${iloc}z")) +tPropC[2][3][1].append(Template(" OM${iloc}**2 * P${iloc}x * P${iloc}y ** 2 * P${iloc}z /3. - OM${iloc} * P${iloc}x * P${iloc}z * (-1 - OM${iloc} * P${iloc}y ** 2)")) +tPropC[2][3][1].append(Template(" -OM${iloc} * P${iloc}x * P${iloc}y * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}x * P${iloc}z ** 2 * P${iloc}y /3.")) +tPropC[2][3][2].append(Template(" OM${iloc}**2 * P${iloc}t * P${iloc}y ** 2 * P${iloc}z /3. - OM${iloc} * P${iloc}t * P${iloc}z * (-1 - OM${iloc} * P${iloc}y ** 2)")) +tPropC[2][3][2].append(Template(" OM${iloc}**2 * P${iloc}x * P${iloc}y ** 2 * P${iloc}z /3. - OM${iloc} * P${iloc}x * P${iloc}z * (-1 - OM${iloc} * P${iloc}y ** 2)")) +tPropC[2][3][2].append(Template(" -4./3. * (-1 - OM${iloc} * P${iloc}y ** 2)*OM${iloc} * P${iloc}y * P${iloc}z ")) +tPropC[2][3][2].append(Template(" (-1 - OM${iloc} * P${iloc}y ** 2) * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}y ** 2 * P${iloc}z ** 2 /3. ")) +tPropC[2][3][3].append(Template(" -OM${iloc} * P${iloc}t * P${iloc}y * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}t * P${iloc}z ** 2 * P${iloc}y /3.")) +tPropC[2][3][3].append(Template(" -OM${iloc} * P${iloc}x * P${iloc}y * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}x * P${iloc}z ** 2 * P${iloc}y /3.")) +tPropC[2][3][3].append(Template(" (-1 - OM${iloc} * P${iloc}y ** 2) * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}y ** 2 * P${iloc}z ** 2 /3. ")) +tPropC[2][3][3].append(Template(" -4./3.*OM${iloc} * P${iloc}y * P${iloc}z * (-1 - OM${iloc} * P${iloc}z ** 2) ")) + +tPropC[3][0][0].append(Template(" -4./3. * (1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}t * P${iloc}z ")) +tPropC[3][0][0].append(Template(" -(1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}x * P${iloc}z + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}x * P${iloc}z /3. ")) +tPropC[3][0][0].append(Template(" -(1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}y * P${iloc}z + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}y * P${iloc}z /3. ")) +tPropC[3][0][0].append(Template(" (1 - OM${iloc} * P${iloc}t ** 2) * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}z ** 2 /3. ")) +tPropC[3][0][1].append(Template(" -(1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}x * P${iloc}z + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}x * P${iloc}z /3. ")) +tPropC[3][0][1].append(Template(" 2*OM${iloc}**2 * P${iloc}t * P${iloc}x ** 2 * P${iloc}z + 2./3.*OM${iloc} * P${iloc}t * P${iloc}z * (-1 - OM${iloc} * P${iloc}x ** 2)")) +tPropC[3][0][1].append(Template(" 4./3.*OM${iloc}**2 * P${iloc}t * P${iloc}y * P${iloc}x * P${iloc}z ")) +tPropC[3][0][1].append(Template(" -OM${iloc} * P${iloc}t * P${iloc}x * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}t * P${iloc}z ** 2 * P${iloc}x /3.")) +tPropC[3][0][2].append(Template(" -(1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}y * P${iloc}z + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}y * P${iloc}z /3. ")) +tPropC[3][0][2].append(Template(" 4./3.*OM${iloc}**2 * P${iloc}t * P${iloc}y * P${iloc}x * P${iloc}z ")) +tPropC[3][0][2].append(Template(" 2*OM${iloc}**2 * P${iloc}t * P${iloc}y ** 2 * P${iloc}z + 2./3.*OM${iloc} * P${iloc}t * P${iloc}z * (-1 - OM${iloc} * P${iloc}y ** 2)")) +tPropC[3][0][2].append(Template(" -OM${iloc} * P${iloc}t * P${iloc}y * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}t * P${iloc}z ** 2 * P${iloc}y /3.")) +tPropC[3][0][3].append(Template(" (1 - OM${iloc} * P${iloc}t ** 2) * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}z ** 2 /3. ")) +tPropC[3][0][3].append(Template(" -OM${iloc} * P${iloc}t * P${iloc}x * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}t * P${iloc}z ** 2 * P${iloc}x /3.")) +tPropC[3][0][3].append(Template(" -OM${iloc} * P${iloc}t * P${iloc}y * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}t * P${iloc}z ** 2 * P${iloc}y /3.")) +tPropC[3][0][3].append(Template(" -4./3.*OM${iloc} * P${iloc}t * P${iloc}z * (-1 - OM${iloc} * P${iloc}z ** 2)")) + +tPropC[3][1][0].append(Template(" 2*OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}x * P${iloc}z + 2./3. * (1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}x * P${iloc}z")) +tPropC[3][1][0].append(Template(" OM${iloc}**2 * P${iloc}t * P${iloc}x ** 2 * P${iloc}z /3. - OM${iloc} * P${iloc}t * P${iloc}z * (-1 - OM${iloc} * P${iloc}x ** 2)")) +tPropC[3][1][0].append(Template(" 4./3.*OM${iloc}**2 * P${iloc}t * P${iloc}y * P${iloc}x * P${iloc}z ")) +tPropC[3][1][0].append(Template(" -OM${iloc} * P${iloc}t * P${iloc}x * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}t * P${iloc}z ** 2 * P${iloc}x /3.")) +tPropC[3][1][1].append(Template(" OM${iloc}**2 * P${iloc}t * P${iloc}x ** 2 * P${iloc}z /3. - OM${iloc} * P${iloc}t * P${iloc}z * (-1 - OM${iloc} * P${iloc}x ** 2)")) +tPropC[3][1][1].append(Template(" -4./3. * (-1 - OM${iloc} * P${iloc}x ** 2)*OM${iloc} * P${iloc}x * P${iloc}z ")) +tPropC[3][1][1].append(Template(" -(-1 - OM${iloc} * P${iloc}x ** 2)*OM${iloc} * P${iloc}y * P${iloc}z + OM${iloc}**2 * P${iloc}x ** 2 * P${iloc}y * P${iloc}z /3.")) +tPropC[3][1][1].append(Template(" (-1 - OM${iloc} * P${iloc}x ** 2) * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}x ** 2 * P${iloc}z ** 2 /3. ")) +tPropC[3][1][2].append(Template(" 4./3.*OM${iloc}**2 * P${iloc}t * P${iloc}y * P${iloc}x * P${iloc}z ")) +tPropC[3][1][2].append(Template(" -(-1 - OM${iloc} * P${iloc}x ** 2)*OM${iloc} * P${iloc}y * P${iloc}z + OM${iloc}**2 * P${iloc}x ** 2 * P${iloc}y * P${iloc}z /3.")) +tPropC[3][1][2].append(Template(" 2*OM${iloc}**2 * P${iloc}x * P${iloc}y ** 2 * P${iloc}z + 2./3.*OM${iloc} * P${iloc}x * P${iloc}z * (-1 - OM${iloc} * P${iloc}y ** 2)")) +tPropC[3][1][2].append(Template(" -OM${iloc} * P${iloc}x * P${iloc}y * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}x * P${iloc}z ** 2 * P${iloc}y /3.")) +tPropC[3][1][3].append(Template(" -OM${iloc} * P${iloc}t * P${iloc}x * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}t * P${iloc}z ** 2 * P${iloc}x /3.")) +tPropC[3][1][3].append(Template(" (-1 - OM${iloc} * P${iloc}x ** 2) * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}x ** 2 * P${iloc}z ** 2 /3. ")) +tPropC[3][1][3].append(Template(" -OM${iloc} * P${iloc}x * P${iloc}y * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}x * P${iloc}z ** 2 * P${iloc}y /3.")) +tPropC[3][1][3].append(Template(" -4./3.*OM${iloc} * P${iloc}x * P${iloc}z * (-1 - OM${iloc} * P${iloc}z ** 2) ")) + +tPropC[3][2][0].append(Template(" 2*OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}y * P${iloc}z + 2./3. * (1 - OM${iloc} * P${iloc}t ** 2)*OM${iloc} * P${iloc}y * P${iloc}z")) +tPropC[3][2][0].append(Template(" 4./3.*OM${iloc}**2 * P${iloc}t * P${iloc}y * P${iloc}x * P${iloc}z")) +tPropC[3][2][0].append(Template(" OM${iloc}**2 * P${iloc}t * P${iloc}y ** 2 * P${iloc}z /3. - OM${iloc} * P${iloc}t * P${iloc}z * (-1 - OM${iloc} * P${iloc}y ** 2)")) +tPropC[3][2][0].append(Template(" -OM${iloc} * P${iloc}t * P${iloc}y * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}t * P${iloc}z ** 2 * P${iloc}y /3.")) +tPropC[3][2][1].append(Template(" 4./3.*OM${iloc}**2 * P${iloc}t * P${iloc}y * P${iloc}x * P${iloc}z")) +tPropC[3][2][1].append(Template(" 2*OM${iloc}**2 * P${iloc}x ** 2 * P${iloc}y * P${iloc}z + 2./3. * (-1 - OM${iloc} * P${iloc}x ** 2)*OM${iloc} * P${iloc}y * P${iloc}z")) +tPropC[3][2][1].append(Template(" OM${iloc}**2 * P${iloc}x * P${iloc}y ** 2 * P${iloc}z /3. - OM${iloc} * P${iloc}x * P${iloc}z * (-1 - OM${iloc} * P${iloc}y ** 2)")) +tPropC[3][2][1].append(Template(" -OM${iloc} * P${iloc}x * P${iloc}y * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}x * P${iloc}z ** 2 * P${iloc}y /3.")) +tPropC[3][2][2].append(Template(" OM${iloc}**2 * P${iloc}t * P${iloc}y ** 2 * P${iloc}z /3. - OM${iloc} * P${iloc}t * P${iloc}z * (-1 - OM${iloc} * P${iloc}y ** 2)")) +tPropC[3][2][2].append(Template(" OM${iloc}**2 * P${iloc}x * P${iloc}y ** 2 * P${iloc}z /3. - OM${iloc} * P${iloc}x * P${iloc}z * (-1 - OM${iloc} * P${iloc}y ** 2)")) +tPropC[3][2][2].append(Template(" -4./3. * (-1 - OM${iloc} * P${iloc}y ** 2)*OM${iloc} * P${iloc}y * P${iloc}z")) +tPropC[3][2][2].append(Template(" (-1 - OM${iloc} * P${iloc}y ** 2) * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}y ** 2 * P${iloc}z ** 2 /3. ")) +tPropC[3][2][3].append(Template(" -OM${iloc} * P${iloc}t * P${iloc}y * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}t * P${iloc}z ** 2 * P${iloc}y /3.")) +tPropC[3][2][3].append(Template(" -OM${iloc} * P${iloc}x * P${iloc}y * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}x * P${iloc}z ** 2 * P${iloc}y /3.")) +tPropC[3][2][3].append(Template(" (-1 - OM${iloc} * P${iloc}y ** 2) * (-1 - OM${iloc} * P${iloc}z ** 2) + OM${iloc}**2 * P${iloc}y ** 2 * P${iloc}z ** 2 /3. ")) +tPropC[3][2][3].append(Template(" -4./3.*OM${iloc} * P${iloc}y * P${iloc}z * (-1 - OM${iloc} * P${iloc}z ** 2)")) + +tPropC[3][3][0].append(Template(" 2*OM${iloc}**2 * P${iloc}t ** 2 * P${iloc}z ** 2 - 2./3. * (1 - OM${iloc} * P${iloc}t ** 2) * (-1 - OM${iloc} * P${iloc}z ** 2)")) +tPropC[3][3][0].append(Template(" 2*OM${iloc}**2 * P${iloc}t * P${iloc}z ** 2 * P${iloc}x + 2./3.*OM${iloc} * P${iloc}t * P${iloc}x * (-1 - OM${iloc} * P${iloc}z ** 2)")) +tPropC[3][3][0].append(Template(" 2*OM${iloc}**2 * P${iloc}t * P${iloc}z ** 2 * P${iloc}y + 2./3.*OM${iloc} * P${iloc}t * P${iloc}y * (-1 - OM${iloc} * P${iloc}z ** 2)")) +tPropC[3][3][0].append(Template(" -4./3.*OM${iloc} * P${iloc}t * P${iloc}z * (-1 - OM${iloc} * P${iloc}z ** 2) ")) +tPropC[3][3][1].append(Template(" 2*OM${iloc}**2 * P${iloc}t * P${iloc}z ** 2 * P${iloc}x + 2./3.*OM${iloc} * P${iloc}t * P${iloc}x * (-1 - OM${iloc} * P${iloc}z ** 2)")) +tPropC[3][3][1].append(Template(" 2*OM${iloc}**2 * P${iloc}x ** 2 * P${iloc}z ** 2 - 2./3. * (-1 - OM${iloc} * P${iloc}x ** 2) * (-1 - OM${iloc} * P${iloc}z ** 2)")) +tPropC[3][3][1].append(Template(" 2*OM${iloc}**2 * P${iloc}x * P${iloc}z ** 2 * P${iloc}y + 2./3.*OM${iloc} * P${iloc}x * P${iloc}y * (-1 - OM${iloc} * P${iloc}z ** 2)")) +tPropC[3][3][1].append(Template(" -4./3.*OM${iloc} * P${iloc}x * P${iloc}z * (-1 - OM${iloc} * P${iloc}z ** 2) ")) +tPropC[3][3][2].append(Template(" 2*OM${iloc}**2 * P${iloc}t * P${iloc}z ** 2 * P${iloc}y + 2./3.*OM${iloc} * P${iloc}t * P${iloc}y * (-1 - OM${iloc} * P${iloc}z ** 2)")) +tPropC[3][3][2].append(Template(" 2*OM${iloc}**2 * P${iloc}x * P${iloc}z ** 2 * P${iloc}y + 2./3.*OM${iloc} * P${iloc}x * P${iloc}y * (-1 - OM${iloc} * P${iloc}z ** 2)")) +tPropC[3][3][2].append(Template(" 2*OM${iloc}**2 * P${iloc}y ** 2 * P${iloc}z ** 2 - 2./3. * (-1 - OM${iloc} * P${iloc}y ** 2) * (-1 - OM${iloc} * P${iloc}z ** 2)")) +tPropC[3][3][2].append(Template(" -4./3.*OM${iloc} * P${iloc}y * P${iloc}z * (-1 - OM${iloc} * P${iloc}z ** 2)")) +tPropC[3][3][3].append(Template(" -4./3.*OM${iloc} * P${iloc}t * P${iloc}z * (-1 - OM${iloc} * P${iloc}z ** 2)")) +tPropC[3][3][3].append(Template(" -4./3.*OM${iloc} * P${iloc}x * P${iloc}z * (-1 - OM${iloc} * P${iloc}z ** 2)")) +tPropC[3][3][3].append(Template(" -4./3.*OM${iloc} * P${iloc}y * P${iloc}z * (-1 - OM${iloc} * P${iloc}z ** 2)")) +tPropC[3][3][3].append(Template(" 4./3. * (-1 - OM${iloc} * P${iloc}z ** 2) ** 2")) + +imap=["t","x","y","z"] + +RSDotProduct = Template("${s}ts${si}*${v}t-${s}xs${si}*${v}x-${s}ys${si}*${v}y-${s}zs${si}*${v}z") + +vTemplateT="""\ +{header} {{ + if({type}W{iloc}.id()=={id}) {{ + return {normal}; + }} + else {{ + return {transpose}; + }} + }}; +""" + +vTemplate4="""\ +{header} {{ +{swap} + if(id{iloc1}=={id1}) {{ + if(id{iloc2}=={id2}) {{ + return {res1}; + }} + else {{ + return {res2}; + }} + }} + else {{ + if(id{iloc2}=={id2}) {{ + return {res3}; + }} + else {{ + return {res4}; + }} + }} +}}; + +""" + +vecTemplate="""\ + Energy2 p2 = P{iloc}.m2(); + LorentzPolarizationVector vtemp = {res}; + Complex fact = -Complex(0.,1.)*({cf})*propagator(iopt,p2,out,mass,width); + if(mass.real() < ZERO) mass = (iopt==5) ? ZERO : out->mass(); + complex mass2 = sqr(mass); + if(mass.real()==ZERO) {{ + vtemp =fact*vtemp; + }} + else {{ + complex dot = P{iloc}*vtemp; + vtemp = fact*(vtemp-dot/mass2*P{iloc}); + }} + return VectorWaveFunction(P{iloc},out,vtemp.x(),vtemp.y(),vtemp.z(),vtemp.t()); +""" + + +sTemplate="""\ + Energy2 p2 = P{iloc}.m2(); + if(mass.real() < ZERO) mass = (iopt==5) ? ZERO : out->mass(); + Complex fact = Complex(0.,1.)*({cf})*propagator(iopt,p2,out,mass,width); + Lorentz{offTypeA} newSpin = fact*({res}); + return {offTypeB}(P{iloc},out,newSpin); +""" + +RSTemplate="""\ + if(mass.real() < ZERO) mass = (iopt==5) ? ZERO : out->mass(); + Energy2 p2 = P{iloc}.m2(); + Complex fact = Complex(0.,-1.)*({cf})*propagator(iopt,p2,out,mass,width); + complex Omass = mass.real()==ZERO ? InvEnergy(ZERO) : 1./mass; + Lorentz{offTypeA} newSpin = fact*({res}); + return {offTypeB}(P{iloc},out,newSpin); +""" + +scaTemplate="""\ + if(mass.real() < ZERO) mass = (iopt==5) ? ZERO : out->mass(); + Energy2 p2 = P{iloc}.m2(); + Complex fact = Complex(0.,1.)*({cf})*propagator(iopt,p2,out,mass,width); + complex output = fact*({res}); + return ScalarWaveFunction(P{iloc},out,output); +""" + +tenTemplate="""\ + if(mass.real() < ZERO) mass = (iopt==5) ? ZERO : out->mass(); + InvEnergy2 OM{iloc} = mass.real()==ZERO ? InvEnergy2(ZERO) : 1./sqr(mass.real()); + Energy2 M{iloc}2 = sqr(mass.real()); + Energy2 p2 = P{iloc}.m2(); + Complex fact = Complex(0.,1.)*({cf})*propagator(iopt,p2,out,mass,width); + LorentzTensor output = fact*({res}); + return TensorWaveFunction(P{iloc},out,output); +""" + +# various strings for matrixes +I4 = "Matrix([[1.,0,0,0],[0,1.,0,0],[0,0,1.,0],[0,0,0,1.]])" +G5 = "Matrix([[-1.,0,0,0],[0,-1.,0,0],[0,0,1.,0],[0,0,0,1.]])" +PM = "Matrix([[1.,0,0,0],[0,1.,0,0],[0,0,0,0],[0,0,0,0]])" +PP = "Matrix([[0,0,0,0],[0,0,0,0],[0,0,1.,0],[0,0,0,1.]])" + + +vslash = Template("Matrix([[0,0,${v}TMZ,-${v}XMY],[0,0,-${v}XPY,${v}TPZ],[${v}TPZ,${v}XMY,0,0],[${v}XPY,${v}TMZ,0,0]])") +vslashS = Template("${v}TPZ=Symbol(\"${v}TPZ\")\n${v}TMZ=Symbol(\"${v}TMZ\")\n${v}XPY=Symbol(\"${v}XPY\")\n${v}XMY=Symbol(\"${v}XMY\")\n") +momCom = Template("${v}t = Symbol(\"${v}t\")\n${v}x = Symbol(\"${v}x\")\n${v}y = Symbol(\"${v}y\")\n${v}z = Symbol(\"${v}z\")\n") +vslashD = Template("complex<${var}> ${v}TPZ = ${v}.t()+${v}.z();\n complex<${var}> ${v}TMZ = ${v}.t()-${v}.z();\n complex<${var}> ${v}XPY = ${v}.x()+Complex(0.,1.)*${v}.y();\n complex<${var}> ${v}XMY = ${v}.x()-Complex(0.,1.)*${v}.y();") +vslashM = Template("Matrix([[$m,0,${v}TMZ,-${v}XMY],[0,$m,-${v}XPY,${v}TPZ],[${v}TPZ,${v}XMY,$m,0],[${v}XPY,${v}TMZ,0,$m]])") +vslashM2 = Template("Matrix([[$m,0,-${v}TMZ,${v}XMY],[0,$m,${v}XPY,-${v}TPZ],[-${v}TPZ,-${v}XMY,$m,0],[-${v}XPY,-${v}TMZ,0,$m]])") +vslashMS = Template("${v}TPZ=Symbol(\"${v}TPZ\")\n${v}TMZ=Symbol(\"${v}TMZ\")\n${v}XPY=Symbol(\"${v}XPY\")\n${v}XMY=Symbol(\"${v}XMY\")\n${m}=Symbol(\"${m}\")\nO${m}=Symbol(\"O${m}\")\n") + +rslash = Template("Matrix([[$m,0,${v}TMZ,-${v}XMY],[0,$m,-${v}XPY,${v}TPZ],[${v}TPZ,${v}XMY,$m,0],[${v}XPY,${v}TMZ,0,$m]])*( ($${eta}-2./3.*O${m}**2*${v}$${A}*${v}$${B})*Matrix([[1.,0,0,0],[0,1.,0,0],[0,0,1.,0],[0,0,0,1.]]) -1./3.*$${DA}*$${DB} -1./3.*O${m}*(${v}$${B}*$${DA}-${v}$${A}*$${DB}))") +rslashB = Template("Matrix([[$m,0,${v}TMZ,-${v}XMY],[0,$m,-${v}XPY,${v}TPZ],[${v}TPZ,${v}XMY,$m,0],[${v}XPY,${v}TMZ,0,$m]])*( (${v2}$${A}-2./3.*O${m}**2*${v}$${A}*${dot})*Matrix([[1.,0,0,0],[0,1.,0,0],[0,0,1.,0],[0,0,0,1.]]) -1./3.*$${DA}*${DB} -1./3.*O${m}*(${dot}*$${DA}-${v}$${A}*${DB}))") + + + +rslash2 = Template("Matrix([[$m,0,-${v}TMZ,${v}XMY],[0,$m,${v}XPY,-${v}TPZ],[-${v}TPZ,-${v}XMY,$m,0],[-${v}XPY,-${v}TMZ,0,$m]])*( ($${eta}-2./3.*O${m}**2*${v}$${A}*${v}$${B})*Matrix([[1.,0,0,0],[0,1.,0,0],[0,0,1.,0],[0,0,0,1.]]) -1./3.*$${DA}*$${DB} +1./3.*O${m}*(${v}$${B}*$${DA}-${v}$${A}*$${DB}))") +rslash2B = Template("Matrix([[$m,0,-${v}TMZ,${v}XMY],[0,$m,${v}XPY,-${v}TPZ],[-${v}TPZ,-${v}XMY,$m,0],[-${v}XPY,-${v}TMZ,0,$m]])*( (${v2}$${B}-2./3.*O${m}**2*${dot}*${v}$${B})*Matrix([[1.,0,0,0],[0,1.,0,0],[0,0,1.,0],[0,0,0,1.]]) -1./3.*${DA}*$${DB} +1./3.*O${m}*(${v}$${B}*${DA}-${dot}*$${DB}))") + +dirac=["Matrix([[0,0,1.,0],[0,0,0,1.],[1.,0,0,0],[0,1.,0,0]])","Matrix([[0,0,0,1.],[0,0,1.,0],[0,-1.,0,0],[-1.,0,0,0]])", + "Matrix([[0,0,0,complex(0, -1.)],[0,0,complex(0, 1.),0],[0,complex(0, 1.),0,0],[complex(0, -1.),0,0,0]])", + "Matrix([[0,0,1.,0],[0,0,0,-1.],[-1.,0,0,0],[0,1.,0,0]])"] +CC = "Matrix([[0,1.,0,0],[-1.,0,0,0],[0,0,0,-1.],[0,0,1.,0]])" +CD = "Matrix([[0,-1.,0,0],[1.,0,0,0],[0,0,0,1.],[0,0,-1.,0]])" + +evaluateTemplate = """\ +{decl} {{ + {momenta} + {waves} +{swap} + {symbols} + {couplings} +{defns} + {result} +}} +""" +spinor = Template("Matrix([[${s}s1],[${s}s2],[${s}s3],[${s}s4]])") +sbar = Template("Matrix([[${s}s1,${s}s2,${s}s3,${s}s4]])") +sline = Template("${s}s1=Symbol(\"${s}s1\")\n${s}s2=Symbol(\"${s}s2\")\n${s}s3=Symbol(\"${s}s3\")\n${s}s4=Symbol(\"${s}s4\")\n") + +RSSpinorTemplate = Template("${type}(${outxs1},\n${outxs2},\n${outxs3},\n${outxs4},\n${outys1},\n${outys2},\n${outys3},\n${outys4},\n${outzs1},\n${outzs2},\n${outzs3},\n${outzs4},\n${outts1},\n${outts2},\n${outts3},\n${outts4})") +SpinorTemplate = Template("${type}(${outs1},\n${outs2},\n${outs3},\n${outs4})") + +class LorentzIndex : + """ A simple classs to store a Lorentz index """ + type="" + value=0 + dimension=0 + def __repr__(self): + if(self.type=="V" and not isinstance(self.value,int)) : + return self.value + else : + return "%s%s" % (self.type,self.value) + + def __init__(self,val) : + if(isinstance(val,int)) : + self.dimension=0 + if(val<0) : + self.type="D" + self.value = val + elif(val>0 and val/1000==0) : + self.type="E" + self.value = val + elif(val>0 and val/1000==1) : + self.type="T1" + self.value = val%1000 + elif(val>0 and val/1000==2) : + self.type="T2" + self.value = val%1000 + else : + print "Unknown value in Lorentz index:",val + raise SkipThisVertex() + else : + print "Unknown value in Lorentz index:",val + raise SkipThisVertex() + + def __eq__(self,other): + if(not isinstance(other,LorentzIndex)) : + return False + return ( (self.type, self.value) + == (other.type, other.value) ) + + def __hash__(self) : + return hash((self.type,self.value)) + +class DiracMatrix: + """A simple class to store Dirac matrices""" + name ="" + value="" + index=0 + def __init(self) : + self.name="" + self.value="" + self.index=0 + + def __repr__(self) : + if(self.value==0) : + return "%s" % self.index + else : + return "%s" % self.value + +class LorentzStructure: + """A simple class to store a Lorentz structures""" + name="" + value=0 + lorentz=[] + spin=[] + + def __init(self) : + self.name="" + self.value=0 + self.lorentz=[] + self.spin=[] + + def __repr__(self): + output = self.name + if((self.name=="P" or self.name=="Tensor") and self.value!=0) : + output += "%s" % self.value + if(self.name=="int" or self.name=="sign") : + output += "=%s" % self.value + elif(len(self.spin)==0) : + output += "(" + for val in self.lorentz : + output += "%s," % val + output=output.rstrip(",") + output+=")" + elif(len(self.lorentz)==0) : + output += "(" + for val in self.spin : + output += "%s," % val + output=output.rstrip(",") + output+=")" + else : + output += "(" + for val in self.lorentz : + output += "%s," % val + for val in self.spin : + output += "%s," % val + output=output.rstrip(",") + output+=")" + return output + +def LorentzCompare(a,b) : + if(a.name=="int" and b.name=="int") : + return int(abs(b.value)-abs(a.value)) + elif(a.name=="int") : + return -1 + elif(b.name=="int") : + return 1 + elif(len(a.spin)==0) : + if(len(b.spin)==0) : + return len(b.lorentz)-len(a.lorentz) + else : + return -1 + elif(len(b.spin)==0) : + return 1 + else : + if(len(a.spin)==0 or len(b.spin)==0) : + print 'Index problem in lorentz compare',\ + a.name,b.name,a.spin,b.spin + raise SkipThisVertex() + if(a.spin[0]>0 or b.spin[1]>0 ) : return -1 + if(a.spin[1]>0 or b.spin[0]>0 ) : return 1 + if(a.spin[1]==b.spin[0]) : return -1 + if(b.spin[1]==a.spin[0]) : return 1 + return 0 + +def extractIndices(struct) : + if(struct.find("(")<0) : return [] + temp=struct.split("(")[1].split(")")[0].split(",") + output=[] + for val in temp : + output.append(int(val)) + return output + +def parse_structure(structure,spins) : + output=[] + found = True + while(found) : + found = False + # signs between terms + if(structure=="+" or structure=="-") : + output.append(LorentzStructure()) + output[0].name="sign" + output[0].value=structure[0]+"1." + output[0].value=float(output[0].value) + output[0].lorentz=[] + output[0].spin=[] + return output + # simple numeric pre/post factors + elif((structure[0]=="-" or structure[0]=="+") and + structure[-1]==")" and structure[1]=="(") : + output.append(LorentzStructure()) + output[-1].name="int" + output[-1].value=structure[0]+"1." + output[-1].value=float(output[-1].value) + output[-1].lorentz=[] + output[-1].spin=[] + structure=structure[2:-1] + found=True + elif(structure[0]=="(") : + temp=structure.rsplit(")",1) + structure=temp[0][1:] + output.append(LorentzStructure()) + output[-1].name="int" + output[-1].value="1."+temp[1] + output[-1].value=float(eval(output[-1].value)) + output[-1].lorentz=[] + output[-1].spin=[] + found=True + elif(structure[0:2]=="-(") : + temp=structure.rsplit(")",1) + structure=temp[0][2:] + output.append(LorentzStructure()) + output[-1].name="int" + output[-1].value="-1."+temp[1] + output[-1].value=float(eval(output[-1].value)) + output[-1].lorentz=[] + output[-1].spin=[] + found=True + # special handling for powers + power = False + if("**" in structure ) : + power = True + structure = structure.replace("**","^") + structures = structure.split("*") + if(power) : + for j in range(0,len(structures)): + if(structures[j].find("^")>=0) : + temp = structures[j].split("^") + structures[j] = temp[0] + for i in range(0,int(temp[1])-1) : + structures.append(temp[0]) + # split up the structure + for struct in structures: + ind = extractIndices(struct) + # different types of object + # object with only spin indices + if(struct.find("Identity")==0 or + struct.find("Proj")==0 or + struct.find("Gamma5")==0) : + output.append(LorentzStructure()) + output[-1].spin=ind + output[-1].lorentz=[] + output[-1].name=struct.split("(")[0] + output[-1].value=0 + if(len(struct.replace("%s(%s,%s)" % (output[-1].name,ind[0],ind[1]),""))!=0) : + print "Problem handling %s structure " % output[-1].name + raise SkipThisVertex() + # objects with 2 lorentz indices + elif(struct.find("Metric")==0) : + output.append(LorentzStructure()) + output[-1].lorentz=[LorentzIndex(ind[0]),LorentzIndex(ind[1])] + output[-1].name=struct.split("(")[0] + output[-1].value=0 + output[-1].spin=[] + if(len(struct.replace("%s(%s,%s)" % (output[-1].name,ind[0],ind[1]),""))!=0) : + print "Problem handling %s structure " % output[-1].name + raise SkipThisVertex() + elif(struct.find("P(")==0) : + output.append(LorentzStructure()) + output[-1].lorentz=[LorentzIndex(ind[0])] + output[-1].name=struct.split("(")[0] + output[-1].value=ind[1] + output[-1].spin=[] + if(len(struct.replace("%s(%s,%s)" % (output[-1].name,ind[0],ind[1]),""))!=0) : + print "Problem handling %s structure " % output[-1].name + raise SkipThisVertex() + # 1 lorentz and 1 spin index + elif(struct.find("Gamma")==0) : + output.append(LorentzStructure()) + output[-1].lorentz=[LorentzIndex(ind[0])] + output[-1].spin=[ind[1],ind[2]] + output[-1].name=struct.split("(")[0] + output[-1].value=1 + if(len(struct.replace("%s(%s,%s,%s)" % (output[-1].name,ind[0],ind[1],ind[2]),""))!=0) : + print "problem parsing gamma matrix",struct + raise SkipThisVertex() + # objects with 4 lorentz indices + elif(struct.find("Epsilon")==0) : + output.append(LorentzStructure()) + output[-1].lorentz=[] + for i in range(0,len(ind)) : + output[-1].lorentz.append(LorentzIndex(ind[i])) + output[-1].spin=[] + output[-1].name=struct.split("(")[0] + output[-1].value=1 + if(len(struct.replace("%s(%s,%s,%s,%s)" % (output[-1].name,ind[0],ind[1],ind[2],ind[3]),""))!=0) : + print 'Problem parsing epsilon',struct + raise SkipThisVertex() + # scalars + else : + try : + output.append(LorentzStructure()) + output[-1].value=float(struct) + output[-1].name="int" + output[-1].lorentz=[] + output[-1].spin=[] + except : + if(struct.find("complex")==0) : + vals = struct[0:-1].replace("complex(","").split(",") + output[-1].value=complex(float(vals[0]),float(vals[1])) + output[-1].name="int" + output[-1].lorentz=[] + output[-1].spin=[] + else : + print 'Problem parsing scalar',struct + raise SkipThisVertex() + # now do the sorting + if(len(output)==1) : return output + output = sorted(output,cmp=LorentzCompare) + # fix indices in the RS case + if(4 in spins) : + for i in range(0,len(output)) : + for ll in range(0,len(output[i].lorentz)) : + if(spins[output[i].lorentz[ll].value-1]==4 and + output[i].lorentz[ll].type=="E") : + output[i].lorentz[ll].type="R" + # return the answer + return output + +def constructDotProduct(ind1,ind2,defns) : + (ind1,ind2) = sorted((ind1,ind2),cmp=indSort) + dimension=ind1.dimension+ind2.dimension + # this product already dealt with ? + if((ind1,ind2) in defns) : + name = defns[(ind1,ind2)][0] + # handle the product + else : + name = "dot%s" % (len(defns)+1) + unit = computeUnit(dimension) + defns[(ind1,ind2)] = [name,"complex<%s> %s = %s*%s;" % (unit,name,ind1,ind2)] + return (name,dimension) + +def contract(parsed) : + for j in range(0,len(parsed)) : + if(parsed[j]=="") : continue + if(parsed[j].name=="P") : + # simplest case + if(parsed[j].lorentz[0].type=="E" or + parsed[j].lorentz[0].type=="P") : + newIndex = LorentzIndex(parsed[j].value) + newIndex.type="P" + newIndex.dimension=1 + parsed[j].name="Metric" + parsed[j].lorentz.append(newIndex) + parsed[j].lorentz = sorted(parsed[j].lorentz,cmp=indSort) + continue + ll=1 + found=False + for k in range(0,len(parsed)) : + if(j==k or parsed[k]=="" ) : continue + for i in range(0,len(parsed[k].lorentz)) : + if(parsed[k].lorentz[i] == parsed[j].lorentz[0]) : + parsed[k].lorentz[i].type="P" + parsed[k].lorentz[i].value = parsed[j].value + parsed[k].lorentz[i].dimension=1 + if(parsed[k].name=="P") : + parsed[k].lorentz.append(LorentzIndex(parsed[k].value)) + parsed[k].lorentz[1].type="P" + parsed[k].lorentz[1].dimension=1 + parsed[k].name="Metric" + parsed[k].value = 0 + found=True + break + if(found) : + parsed[j]="" + break + return [x for x in parsed if x != ""] + +def computeUnit(dimension) : + if(isinstance(dimension,int)) : + dtemp = dimension + else : + dtemp=dimension[1]+dimension[2] + if(dtemp==0) : + unit="double" + elif(dtemp==1) : + unit="Energy" + elif(dtemp==-1) : + unit="InvEnergy" + elif(dtemp>0) : + unit="Energy%s" % (dtemp) + elif(dtemp<0) : + unit="InvEnergy%s" % (dtemp) + return unit + +def computeUnit2(dimension,vDim) : + # first correct for any coupling power in vertex + totalDim = int(dimension[0])+dimension[2]+vDim-4 + output="" + if(totalDim!=0) : + if(totalDim>0) : + if(totalDim==1) : + output = "1./GeV" + elif(totalDim==2) : + output = "1./GeV2" + else : + output="1." + for i in range(0,totalDim) : + output +="/GeV" + else : + if(totalDim==-1) : + output = "GeV" + elif(totalDim==-2) : + output = "GeV2" + else : + output="1." + for i in range(0,-totalDim) : + output +="*GeV" + expr="" + # now remove the remaining dimensionality + removal=dimension[1]-int(dimension[0])-vDim+4 + if(removal!=0) : + if(removal>0) : + if(removal==1) : + expr = "UnitRemovalInvE" + else : + expr = "UnitRemovalInvE%s" % removal + else : + if(removal==-1) : + expr = "UnitRemovalE" + else : + expr = "UnitRemovalE%s" % (-removal) + if(output=="") : return expr + elif(expr=="") : return output + else : return "%s*%s" %(output,expr) + +# order the indices of a dot product +def indSort(a,b) : + if(not isinstance(a,LorentzIndex) or + not isinstance(b,LorentzIndex)) : + print "Trying to sort something that's not a Lorentz index",a,b + raise SkipThisVertex() + if(a.type==b.type) : + i1=a.value + i2=b.value + if(i1>i2) : + return 1 + elif(i10) : + output="+" + else : + output="-" + parsed=[] + return (output,parsed,dimension,eps) + # replace integers (really lorentz scalars) + for j in range(0,len(parsed)) : + if(parsed[j]!="" and parsed[j].name=="int") : + output *= parsed[j].value + parsed[j]="" + # bracket this for safety + if(output!="") : output = "(%s)" % output + # special for tensor indices + if("T" in lorentztag) : + for j in range(0,len(parsed)) : + if(parsed[j]=="") :continue + # check for tensor index + found=False + for li in parsed[j].lorentz : + if(li.type[0]=="T") : + index = li + found=True + break + if(not found) : continue + # workout the other index for the tensor + index2 = LorentzIndex(li.value) + if(index.type=="T1") : + index2.type="T2" + else : + index2.type="T1" + # special is tensor contracted with itself + if(parsed[j].name=="Metric" and index2 == parsed[j].lorentz[1]) : + parsed[j].name = "Tensor" + parsed[j].value = index.value + parsed[j].lorentz = [] + if(iloc!=index.value) : + name= "traceT%s" % parsed[j].value + if( name in defns ) : + output += "*(%s)" % defns[name][0] + else : + defns[name] = [name,"Complex %s = T%s.trace();" % (name,parsed[j].value)] + output += "*(%s)" % defns[name][0] + parsed[j]="" + continue + # otherwise search for the match + for k in range(j+1,len(parsed)) : + found = False + for li in parsed[k].lorentz : + if(li == index2) : + found=True + break + if(not found) : continue + if(parsed[j].name=="P") : + newIndex1 = LorentzIndex(parsed[j].value) + newIndex1.type="P" + newIndex1.dimension=1 + elif(parsed[j].name=="Metric") : + for li in parsed[j].lorentz : + if(li != index) : + newIndex1=li + break + else : + print 'Unknown object with tensor index, first object',parsed[j] + raise SkipThisVertex() + if(parsed[k].name=="P") : + newIndex2 = LorentzIndex(parsed[k].value) + newIndex2.type="P" + newIndex2.dimension=1 + elif(parsed[k].name=="Metric") : + for li in parsed[k].lorentz : + if(li != index) : + newIndex2=li + break + elif(parsed[k].name=="Gamma") : + # if we can't contract + if(index.value==iloc or (newIndex1.type=="E" and newIndex1.value==iloc)) : + newIndex2=index2 + # otherwise contract + else : + unit=computeUnit(newIndex1.dimension) + if(index.type=="T1") : + name="T%s%sF" % (index.value,newIndex1) + defns[name] = [name,"LorentzVector > %s = T%s.preDot(%s);" % (unit,name,index.value,newIndex1)] + else : + name="T%s%sS" % (index.value,newIndex1) + defns[name] = [name,"LorentzVector > %s = T%s.postDot(%s);" % (unit,name,index.value,newIndex1)] + parsed[j]="" + gIndex=LorentzIndex(-1) + gIndex.type="V" + gIndex.value=name + gIndex.dimension=newIndex1.dimension + parsed[k].lorentz[0] = gIndex + break + else : + print 'Unknown object with tensor index, second object',parsed[j],parsed[k] + raise SkipThisVertex() + if(index2.type=="T1") : + newIndex1,newIndex2=newIndex2,newIndex1 + parsed[j].name = "Tensor" + parsed[j].value= int(index.value) + parsed[j].lorentz= [newIndex1,newIndex2] + if(parsed[k].name!="Gamma") : parsed[k]="" + break + # main handling of lorentz structures + for j in range(0,len(parsed)) : + if(parsed[j]=="") : continue + if(parsed[j].name=="Metric") : + # check whether or not we can contract + canContract=True + for ll in parsed[j].lorentz : + if((ll.type=="E" and ll.value==iloc) or ll.type=="R") : + canContract = False + break + if(not canContract) : continue + # if we can do it + (name,dTemp) = constructDotProduct(parsed[j].lorentz[0],parsed[j].lorentz[1],defns) + output += "*(%s)" % name + dimension[2] += dTemp + parsed[j]="" + elif(parsed[j].name=="Epsilon") : + if(not eps) : eps = True + # work out which, if any of the indices can be summed over + summable=[] + for ix in range(0,len(parsed[j].lorentz)) : + if(parsed[j].lorentz[ix].type=="P" or + (parsed[j].lorentz[ix].type=="E" and iloc !=parsed[j].lorentz[ix].value)) : + summable.append(True) + else : + summable.append(False) + sc = summable.count(True) + # less than 3 contractable indices, leave for later + if(sc<3) : + continue + # can contract to a vector + elif(sc==3) : + offLoc = -1 + for i in range(0,len(summable)): + if(not summable[i]) : + offLoc = i + break + else : + offLoc = 0 + indices=[] + dTemp=0 + for ix in range(0,len(parsed[j].lorentz)) : + dTemp += parsed[j].lorentz[ix].dimension + if(ix!=offLoc) : indices.append(parsed[j].lorentz[ix]) + # contract all the indices + if(sc==4) : + dimension[2] += dTemp + iTemp = (parsed[j].lorentz[0],parsed[j].lorentz[1], + parsed[j].lorentz[2],parsed[j].lorentz[3]) + if(iTemp in defns) : + output += "*(%s)" % defns[iTemp][0] + parsed[j]="" + else : + name = "dot%s" % (len(defns)+1) + unit = computeUnit(dTemp) + defns[iTemp] = [name,"complex<%s> %s =-%s*epsilon(%s,%s,%s);" % (unit,name,parsed[j].lorentz[0], + indices[0],indices[1],indices[2]) ] + output += "*(%s)" % name + parsed[j]="" + # contract 3 indices leaving a vector + else : + iTemp = (indices[0],indices[1],indices[2]) + sign = "1" + if(offLoc%2!=0) : sign="-1" + if(iTemp in defns) : + name = defns[iTemp][0] + else : + name = "V%s" % (len(defns)+1) + unit = computeUnit(dTemp) + defns[iTemp] = [name,"LorentzVector > %s =-epsilon(%s,%s,%s);" % (unit,name, + indices[0],indices[1],indices[2]) ] + newIndex = LorentzIndex(int(name[1:])) + newIndex.type="V" + newIndex.dimension=dTemp + output += "*(%s)" % (sign) + oi = parsed[j].lorentz[offLoc] + if(oi.type!="D") : + parsed[j].name="Metric" + parsed[j].spins=[] + parsed[j].value=0 + parsed[j].lorentz=[newIndex,oi] + else : + found=False + for k in range(0,len(parsed)): + if(k==j or parsed[k]=="") : continue + for ll in range(0,len(parsed[k].lorentz)) : + if(parsed[k].lorentz[ll]==oi) : + found=True + parsed[k].lorentz[ll]=newIndex + break + if(found) : break + if(not found) : + print "Problem contracting indices of Epsilon tensor" + raise SkipThisVertex() + parsed[j]="" + elif(parsed[j].name=="Tensor") : + # not an external tensor + if(parsed[j].value!=iloc) : + # now check the lorentz indices + con=[] + uncon=[] + dtemp=0 + for li in parsed[j].lorentz : + if(li.type=="P" or li.type=="V") : + con.append(li) + dtemp+=li.dimension + elif(li.type=="E") : + if(li.value!=iloc) : + con.append(li) + else : + uncon.append(li) + else : + print "Can't handle index ",li,"in tensor",parsed[j] + raise SkipThisVertex() + if(len(con)==2) : + iTemp = ("T%s%s%s"% (parsed[j].value,con[0],con[1])) + dimension[2]+=dtemp + if(iTemp in defns) : + output += "*(%s)" % defns[iTemp][0] + else : + unit=computeUnit(dtemp) + name = "dot%s" % (len(defns)+1) + defns[iTemp] = [name,"complex<%s> %s = T%s.preDot(%s)*%s;" % (unit,name,parsed[j].value,con[0],con[1])] + output += "*(%s)" % name + parsed[j]="" + # handled in final stage + else : + continue + elif(parsed[j].name.find("Proj")>=0 or + parsed[j].name.find("Gamma")>=0 or + parsed[j].name.find("Identity")>=0) : + continue + elif(parsed[j].name=="P" and parsed[j].lorentz[0].type=="R") : + continue + else : + print 'Lorentz structure',parsed[j],'not handled' + raise SkipThisVertex() + # remove leading * + if(output!="" and output[0]=="*") : output = output[1:] + # remove any (now) empty elements + parsed = [x for x in parsed if x != ""] + return (output,parsed,dimension,eps) + +def finalContractions(output,parsed,dimension,lorentztag,iloc,defns) : + if(len(parsed)==0) : + return (output,dimension) + elif(len(parsed)!=1) : + print "Summation can't be handled",parsed + raise SkipThisVertex() + if(parsed[0].name=="Tensor") : + # contracted with off-shell vector + if(parsed[0].value!=iloc) : + found = False + for ll in parsed[0].lorentz : + if(ll.type=="E" and ll.value==iloc) : + found = True + else : + lo=ll + if(found) : + dimension[2]+= lo.dimension + unit=computeUnit(lo.dimension) + if(lo==parsed[0].lorentz[0]) : + name="T%s%sF" % (parsed[0].value,lo) + defns[name] = [name,"LorentzVector > %s = T%s.preDot(%s);" % (unit,name,parsed[0].value,lo)] + else : + name="T%s%sS" % (parsed[0].value,lo) + defns[name] = [name,"LorentzVector > %s = T%s.postDot(%s);" % (unit,name,parsed[0].value,lo)] + parsed[0]="" + if(output=="") : output="1." + output = "(%s)*(%s)" %(output,name) + else : + print "Can\'t contract tensor",lo,iloc + raise SkipThisVertex() + # off-shell tensor + else : + if(len(parsed[0].lorentz)!=0) : + dimension[2]+=parsed[0].lorentz[0].dimension+parsed[0].lorentz[1].dimension + tensor = tensorPropagator(parsed[0],defns) + if(output=="") : output="1." + output = [output,tensor,()] + elif(parsed[0].name=="Metric") : + found = False + for ll in parsed[0].lorentz : + if(ll.type=="E" and ll.value==iloc) : + found = True + else : + lo=ll + if(found) : + parsed[0]="" + dimension[2] += lo.dimension + if(output=="") : output="1." + output = "(%s)*(%s)" %(output,lo) + else : + print "Structure can't be handled",parsed,iloc + raise SkipThisVertex() + return (output,dimension) + +def tensorPropagator(struct,defns) : + # dummy index + i0 = LorentzIndex(-1000) + # index for momentum of propagator + ip = LorentzIndex(struct.value) + ip.type="P" + ip.dimension=1 + # the metric tensor + terms=[] + if(len(struct.lorentz)==0) : + (dp,dTemp) = constructDotProduct(ip,ip,defns) + pre = "-1./3.*(1.-%s*OM%s)" % (dp,struct.value) + terms.append((pre,i0,i0)) + pre = "-2./3.*(1.-%s*OM%s)" % (dp,struct.value) + terms.append(("%s*OM%s" %(pre,struct.value),ip,ip)) + else : + # indices of the tensor + ind1 = struct.lorentz[0] + ind2 = struct.lorentz[1] + # the dot products we need + (d1,dtemp) = constructDotProduct(ind1,ip,defns) + (d2,dtemp) = constructDotProduct(ind2,ip,defns) + (d3,dtemp) = constructDotProduct(ind1,ind2,defns) + # various terms in the propagator + terms.append(("0.5",ind1,ind2)) + terms.append(("-0.5*OM%s*%s"%(struct.value,d1),ip,ind2)) + terms.append(("-0.5*OM%s*%s"%(struct.value,d2),ind1,ip)) + terms.append(("0.5",ind2,ind1)) + terms.append(("-0.5*OM%s*%s"%(struct.value,d2),ip,ind1)) + terms.append(("-0.5*OM%s*%s"%(struct.value,d1),ind2,ip)) + terms.append(("-1./3.*"+d3,i0,i0)) + terms.append(("1./3.*OM%s*%s*%s"%(struct.value,d1,d2),i0,i0)) + terms.append(("1./3.*OM%s*%s"%(struct.value,d3),ip,ip)) + terms.append(("2./3.*OM%s*OM%s*%s*%s"%(struct.value,struct.value,d1,d2),ip,ip)) + # compute the output as a dict + output={} + for i1 in imap: + for i2 in imap : + val="" + for term in terms: + if(term[0][0]!="-") : + pre = "+"+term[0] + else : + pre = term[0] + if(term[1]==i0) : + if(i1==i2) : + if(i1=="t") : + val += pre + else : + if(pre[0]=="+") : + val +="-"+pre[1:] + else : + val +="+"+pre[1:] + + + else : + val += "%s*%s%s*%s%s" % (pre,term[1],i1,term[2],i2) + output["%s%s" % (i1,i2) ] = val.replace("+1*","+").replace("-1*","-") + return output + +def generateVertex(iloc,L,parsed,lorentztag,vertex,defns) : + # try to import sympy and exit if required + try : + import sympy + from sympy import Matrix,Symbol + except : + print 'ufo2herwig uses the python sympy module to translate general lorentz structures.' + print 'This must be installed if you wish to use this option.' + print 'EXITTING' + quit() + eps=False + # parse the lorentz structures + output = [1.]*len(parsed) + dimension=[] + for i in range(0,len(parsed)) : + dimension.append([0,0,0]) + for i in range (0,len(parsed)) : + (output[i],parsed[i],dimension[i],eps) = finishParsing(parsed[i],dimension[i],lorentztag,iloc,defns,eps) + # still need to process gamma matrix strings for fermions + if(lorentztag[0] in ["F","R"] ) : + return convertDirac(output,dimension,eps,iloc,L,parsed,lorentztag,vertex,defns) + # return the answer + else : + handled=True + for i in range (0,len(parsed)) : + if(len(parsed[i])!=0) : + handled = False + break + if(not handled) : + for i in range (0,len(parsed)) : + (output[i],dimension[i]) = finalContractions(output[i],parsed[i],dimension[i],lorentztag,iloc,defns) + return (output,dimension,eps) + +def convertDirac(output,dimension,eps,iloc,L,parsed,lorentztag,vertex,defns) : + for i in range(0,len(parsed)): + # skip empty elements + if(len(parsed[i])==0 or (len(parsed[i])==1 and parsed[i][0]=="")) : continue + # parse the string + (output[i],dimension[i],defns) = convertDiracStructure(parsed[i],output[i],dimension[i], + defns,iloc,L,lorentztag,vertex) + return (output,dimension,eps) + +# parse the gamma matrices +def convertMatrix(structure,spins,unContracted,Symbols,dtemp,defns,iloc) : + i1 = structure.spin[0] + i2 = structure.spin[1] + if(structure.name=="Identity") : + output = DiracMatrix() + output.value = I4 + output.index=0 + output.name="M" + structure="" + elif(structure.name=="Gamma5") : + output = DiracMatrix() + output.value = G5 + output.index=0 + output.name="M" + structure="" + elif(structure.name=="ProjM") : + output = DiracMatrix() + output.value = PM + output.index=0 + output.name="M" + structure="" + elif(structure.name=="ProjP") : + output = DiracMatrix() + output.value = PP + output.index=0 + output.name="M" + structure="" + elif(structure.name=="Gamma") : + # gamma(mu) lorentz matrix contracted with dummy index + if(structure.lorentz[0].type=="D" or structure.lorentz[0].type=="R") : + if(structure.lorentz[0] not in unContracted) : + unContracted[structure.lorentz[0]] = 0 + output = DiracMatrix() + output.value=0 + output.index=structure.lorentz[0] + output.name="GMU" + structure="" + elif(structure.lorentz[0].type == "E" and + structure.lorentz[0].value == iloc ) : + if(structure.lorentz[0] not in unContracted) : + unContracted[structure.lorentz[0]] = 0 + output = DiracMatrix() + output.value=0 + output.index=structure.lorentz[0] + output.name="GMU" + structure="" + elif(structure.lorentz[0].type == "T1" or + structure.lorentz[0].type == "T2") : + if(structure.lorentz[0] not in unContracted) : + unContracted[structure.lorentz[0]] = 0 + output = DiracMatrix() + output.value=0 + output.index=structure.lorentz[0] + output.name="GMU" + structure="" + else : + output=DiracMatrix() + output.name="M" + output.value = vslash.substitute({ "v" : structure.lorentz[0]}) + Symbols += vslashS.substitute({ "v" : structure.lorentz[0]}) + variable = computeUnit(structure.lorentz[0].dimension) + #if(structure.lorentz[0].type!="V" or + # structure.lorentz[0].type=="V") : + dtemp[2] += structure.lorentz[0].dimension + defns["vv%s" % structure.lorentz[0] ] = \ + ["vv%s" % structure.lorentz[0], + vslashD.substitute({ "var" : variable, + "v" : structure.lorentz[0]})] + structure="" + else : + print 'Unknown Gamma matrix structure',structure + raise SkipThisVertex() + return (i1,i2,output,structure,Symbols) + + +def checkRSContract(parsed,loc,dtemp) : + rindex=LorentzIndex(loc) + rindex.type="R" + contract="" + for i in range(0,len(parsed)) : + if(parsed[i]=="") : continue + found = False + for ll in range(0,len(parsed[i].lorentz)) : + if(parsed[i].lorentz[ll]==rindex) : + found=True + break + if(not found) : + continue + if(parsed[i].name=="P") : + dtemp[2]+=1 + contract = LorentzIndex(parsed[i].value) + contract.type="P" + contract.dimension=1 + parsed[i]="" + break + elif(parsed[i].name=="Metric") : + for ll in parsed[i].lorentz : + if(ll==rindex) : + continue + else : + break + if(ll.type=="P") : + dtemp[2]+=1 + contract=ll + parsed[i]="" + break + elif(parsed[i].name=="Epsilon") : + continue + else : + print "Unkonwn type contracted with RS spinor",parsed[i] + raise SkipThisVertex() + return contract + +def processChain(dtemp,parsed,spins,Symbols,unContracted,defns,iloc) : + # piece of dimension which is common (0.5 for sbar and spinor) + dtemp[0]+=1 + # set up the spin indices + sind = 0 + lind = 0 + expr=[] + # now find the next thing in the matrix string + ii = 0 + index=0 + while True : + # already handled + if(parsed[ii]=="") : + ii+=1 + continue + # start of the chain + elif(sind==0 and len(parsed[ii].spin)==2 and parsed[ii].spin[0]>0 ) : + (sind,index,matrix,parsed[ii],Symbols) \ + = convertMatrix(parsed[ii],spins,unContracted,Symbols,dtemp,defns,iloc) + expr.append(matrix) + # next element in the chain + elif(index!=0 and len(parsed[ii].spin)==2 and parsed[ii].spin[0]==index) : + (crap,index,matrix,parsed[ii],Symbols) \ + = convertMatrix(parsed[ii],spins,unContracted,Symbols,dtemp,defns,iloc) + expr.append(matrix) + # check the index to see if we're at the end + if(index>0) : + lind=index + break + ii+=1 + if(ii>=len(parsed)) : + print "Can't parsed the chain of dirac matrices" + print parsed + raise SkipThisVertex() + # start and end of the spin chains + # first particle spin 1/2 + if(spins[sind-1]==2) : + start = DiracMatrix() + endT = DiracMatrix() + start.index=0 + endT .index=0 + # start of chain and end of transpose + # off shell + if(sind==iloc) : + start.name="M" + endT .name="M" + start.value = vslashM .substitute({ "v" : "P%s" % sind, "m" : "M%s" % sind} ) + Symbols += vslashMS.substitute({ "v" : "P%s" % sind, "m" : "M%s" % sind} ) + endT.value = vslashM2.substitute({ "v" : "P%s" % sind, "m" : "M%s" % sind} ) + defns["vvP%s" % sind ] = ["vvP%s" % sind , + vslashD.substitute({ "var" : "Energy", + "v" : "P%s" % sind })] + dtemp[1]+=1 + # onshell + else : + start.name="S" + endT .name="S" + subs = {'s' : ("sbar%s" % sind)} + start.value = sbar .substitute(subs) + Symbols += sline.substitute(subs) + subs = {'s' : ("s%s" % sind)} + endT.value = spinor.substitute(subs) + Symbols += sline.substitute(subs) + # spin 3/2 fermion + elif spins[sind-1]==4 : + # check if we can easily contract + contract=checkRSContract(parsed,sind,dtemp) + # off-shell + if(sind==iloc) : + oindex = LorentzIndex(sind) + oindex.type="O" + unContracted[oindex]=0 + Symbols += vslashMS.substitute({ "v" : "P%s" % sind, "m" : "M%s" % sind} ) + Symbols += momCom.substitute({"v" : "P%s" %sind }) + defns["vvP%s" % sind ] = ["vvP%s" % sind , + vslashD.substitute({ "var" : "Energy", + "v" : "P%s" % sind })] + dtemp[1] += 1 + if(contract=="") : + rindex = LorentzIndex(sind) + rindex.type="R" + start=DiracMatrix() + start.value = Template(rslash.substitute({ "v" : "P%s" % sind, "m" : "M%s" % sind, "loc" : sind })) + start.name = "RP" + start.index = (oindex,rindex) + endT=DiracMatrix() + endT.value = Template(rslash2.substitute({ "v" : "P%s" % sind, "m" : "M%s" % sind, "loc" : sind })) + endT.name = "RP" + endT.index = (rindex,oindex) + else : + # construct dot product + pi = LorentzIndex(sind) + pi.type="P" + pi.dimension=1 + (name,dummy) = constructDotProduct(pi,contract,defns) + Symbols += momCom.substitute({"v" : contract }) + RB = vslash.substitute({ "v" : contract}) + Symbols += vslashS.substitute({ "v" : contract }) + Symbols += "%s = Symbol('%s')\n" % (name,name) + defns["vv%s" % contract ] = ["vv%s" % contract, + vslashD.substitute({ "var" : computeUnit(contract.dimension), + "v" : "%s" % contract })] + start=DiracMatrix() + start.name="RQ" + start.index = oindex + start.value =Template( rslashB.substitute({ "v" : "P%s" % sind, "m" : "M%s" % sind, "loc" : sind, + "DB" : RB, "dot" : name , "v2" : contract})) + + endT=DiracMatrix() + endT.name = "RQ" + endT.index = oindex + endT.value = Template(rslash2B.substitute({ "v" : "P%s" % sind, "m" : "M%s" % sind, "loc" : sind , + "DA" : RB, "dot" : name , "v2" : contract})) + # on-shell + else : + start = DiracMatrix() + endT = DiracMatrix() + # no contraction + if(contract=="" or (contract.type=="E" and contract.value==iloc) ) : + if contract == "" : + contract = LorentzIndex(sind) + contract.type="R" + # start of matrix string + start.value = Template(sbar .substitute({'s' : ("Rsbar%s${L}" % sind)})) + start.name="RS" + start.index = contract + # end of transpose string + endT.value=Template(spinor.substitute({'s' : ("Rs%s${L}" % sind)})) + endT.name="RS" + endT.index = contract + unContracted[contract]=0 + # variables for sympy + for LI in imap : + Symbols += sline.substitute({'s' : ("Rs%s%s" % (sind,LI))}) + Symbols += sline.substitute({'s' : ("Rsbar%s%s" % (sind,LI))}) + else : + # start of matrix string + start.name="S" + start.value = "Matrix([[%s,%s,%s,%s]])" % (RSDotProduct.substitute({'s' : ("Rsbar%s" % sind), 'v':contract, 'si' : 1}), + RSDotProduct.substitute({'s' : ("Rsbar%s" % sind), 'v':contract, 'si' : 2}), + RSDotProduct.substitute({'s' : ("Rsbar%s" % sind), 'v':contract, 'si' : 3}), + RSDotProduct.substitute({'s' : ("Rsbar%s" % sind), 'v':contract, 'si' : 4})) + endT.name="S" + endT.value = "Matrix([[%s],[%s],[%s],[%s]])" % (RSDotProduct.substitute({'s' : ("Rs%s" % sind), 'v':contract, 'si' : 1}), + RSDotProduct.substitute({'s' : ("Rs%s" % sind), 'v':contract, 'si' : 2}), + RSDotProduct.substitute({'s' : ("Rs%s" % sind), 'v':contract, 'si' : 3}), + RSDotProduct.substitute({'s' : ("Rs%s" % sind), 'v':contract, 'si' : 4})) + Symbols += momCom.substitute({"v" : contract }) + for LI in ["x","y","z","t"] : + Symbols += sline.substitute({'s' : ("Rs%s%s" % (sind,LI))}) + Symbols += sline.substitute({'s' : ("Rsbar%s%s" % (sind,LI))}) + # last particle spin 1/2 + if( spins[lind-1]==2 ) : + end = DiracMatrix() + startT = DiracMatrix() + end .index=0 + startT.index=0 + # end of chain + if(lind==iloc) : + end.name ="M" + startT.name="M" + end.value = vslashM2.substitute({ "v" : "P%s" % lind, "m" : "M%s" % lind} ) + startT.value = vslashM.substitute({ "v" : "P%s" % lind, "m" : "M%s" % lind} ) + Symbols += vslashMS.substitute({ "v" : "P%s" % lind, "m" : "M%s" % lind} ) + defns["vvP%s" % lind ] = ["vvP%s" % lind , + vslashD.substitute({ "var" : "Energy", + "v" : "P%s" % lind })] + dtemp[1] += 1 + else : + startT.name="S" + end .name="S" + subs = {'s' : ("s%s" % lind)} + end.value = spinor.substitute(subs) + Symbols += sline.substitute(subs) + subs = {'s' : ("sbar%s" % lind)} + startT.value = sbar .substitute(subs) + Symbols += sline.substitute(subs) + # last particle spin 3/2 + elif spins[lind-1]==4 : + # check if we can easily contract + contract=checkRSContract(parsed,lind,dtemp) + # off-shell + if(lind==iloc) : + oindex = LorentzIndex(lind) + oindex.type="O" + unContracted[oindex]=0 + Symbols += vslashMS.substitute({ "v" : "P%s" % lind, "m" : "M%s" % lind} ) + Symbols += momCom.substitute({"v" : "P%s" %lind }) + defns["vvP%s" % lind ] = ["vvP%s" % lind , + vslashD.substitute({ "var" : "Energy", + "v" : "P%s" % lind })] + dtemp[1] += 1 + if(contract=="") : + rindex = LorentzIndex(lind) + rindex.type="R" + end=DiracMatrix() + end.value = Template(rslash2.substitute({ "v" : "P%s" % lind, "m" : "M%s" % lind, "loc" : lind })) + end.name = "RP" + end.index = (rindex,oindex) + startT=DiracMatrix() + startT.value=Template(rslash.substitute({ "v" : "P%s" % lind, "m" : "M%s" % lind, "loc" : lind })) + startT.name = "RP" + startT.index = (oindex,rindex) + else : + # construct dot product + pi = LorentzIndex(lind) + pi.type="P" + pi.dimension=1 + (name,unit) = constructDotProduct(pi,contract,defns) + Symbols += momCom.substitute({"v" : contract }) + RB = vslash.substitute({ "v" : contract}) + Symbols += vslashS.substitute({ "v" : contract }) + Symbols += "%s = Symbol('%s')\n" % (name,name) + defns["vv%s" % contract ] = ["vv%s" % contract, + vslashD.substitute({ "var" : computeUnit(contract.dimension), + "v" : "%s" % contract })] + end=DiracMatrix() + end.name="RQ" + end.index = oindex + end.value =Template( rslash2B.substitute({ "v" : "P%s" % lind, "m" : "M%s" % lind, "loc" : lind, + "DA" : RB, "dot" : name , "v2" : contract})) + + startT=DiracMatrix() + startT.name = "RQ" + startT.index = oindex + startT.value = Template(rslashB.substitute({ "v" : "P%s" % lind, "m" : "M%s" % lind, "loc" : lind , + "DB" : RB, "dot" : name , "v2" : contract})) + # on-shell + else : + end = DiracMatrix() + startT = DiracMatrix() + # no contraction + if(contract=="" or (contract.type=="E" and contract.value==iloc) ) : + if contract == "" : + contract = LorentzIndex(lind) + contract.type="R" + # end of matrix string + end.value = Template(spinor.substitute({'s' : ("Rs%s${L}" % lind)})) + end.name = "RS" + end.index = contract + # start of matrix string + startT.value = Template(sbar .substitute({'s' : ("Rsbar%s${L}" % lind)})) + startT.name = "RS" + startT.index = contract + unContracted[contract]=0 + # variables for sympy + for LI in imap : + Symbols += sline.substitute({'s' : ("Rs%s%s" % (lind,LI))}) + Symbols += sline.substitute({'s' : ("Rsbar%s%s" % (lind,LI))}) + # contraction + else : + # end of the matrix string + end.name = "S" + end.value = "Matrix([[%s],[%s],[%s],[%s]])" % (RSDotProduct.substitute({'s' : ("Rs%s" % lind), 'v':contract, 'si' : 1}), + RSDotProduct.substitute({'s' : ("Rs%s" % lind), 'v':contract, 'si' : 2}), + RSDotProduct.substitute({'s' : ("Rs%s" % lind), 'v':contract, 'si' : 3}), + RSDotProduct.substitute({'s' : ("Rs%s" % lind), 'v':contract, 'si' : 4})) + startT.name = "S" + startT.value = "Matrix([[%s,%s,%s,%s]])" % (RSDotProduct.substitute({'s' : ("Rsbar%s" % lind), 'v':contract, 'si' : 1}), + RSDotProduct.substitute({'s' : ("Rsbar%s" % lind), 'v':contract, 'si' : 2}), + RSDotProduct.substitute({'s' : ("Rsbar%s" % lind), 'v':contract, 'si' : 3}), + RSDotProduct.substitute({'s' : ("Rsbar%s" % lind), 'v':contract, 'si' : 4})) + Symbols += momCom.substitute({"v" : contract }) + for LI in ["x","y","z","t"] : + Symbols += sline.substitute({'s' : ("Rs%s%s" % (lind,LI))}) + Symbols += sline.substitute({'s' : ("Rsbar%s%s" % (lind,LI))}) + return(sind,lind,expr,start,startT,end,endT,Symbols) + +def calculateDirac(expr,start,end,startT,endT,sind,lind,Symbols,iloc) : + res=[] + for ichain in range(0,len(start)) : + # calculate the matrix string + etemp="*".join(str(x) for x in expr[ichain]) + temp={} + exec("import sympy\nfrom sympy import Symbol,Matrix\n"+Symbols+"result="+ + ( "%s*%s*%s" %(start[ichain],etemp,end[ichain]))) in temp + res.append(temp["result"]) + tempT={} + exec("import sympy\nfrom sympy import Symbol,Matrix,Transpose\n"+Symbols+"result="+ + ( "%s*%s*Transpose(%s)*%s*%s" %(startT[0],CC,etemp,CD,endT[0]))) in tempT + res.append(tempT["result"]) + if(len(start)==1) : + if(iloc==0 or (iloc!=sind[0] and iloc!=lind[0])) : + sVal = {'s' : temp ["result"][0,0],'sT' : tempT["result"][0,0]} + else : + sVal={} + for jj in range(1,5) : + sVal["s%s" % jj] = temp ["result"][jj-1] + sVal["sT%s" % jj] = tempT["result"][jj-1] + else : + sVal={} + sVal["s" ] = res[0][0,0]*res[2][0,0] + sVal["sT2" ] = res[0][0,0]*res[3][0,0] + sVal["sT1" ] = res[1][0,0]*res[2][0,0] + sVal["sT12"] = res[1][0,0]*res[3][0,0] + return sVal + +def addToOutput(res,nchain,sign,rTemp) : + # 1 spin chain + if(nchain==1) : + for ii in range(0,2) : + if(rTemp[ii][0].shape[0]==1) : + # result is scalar + if(rTemp[ii][0].shape[1]==1) : + if(len(res[ii])==0) : + res[ii].append(sign*rTemp [ii][0][0,0]) + else : + res[ii][0] += sign*rTemp [ii][0][0,0] + # result is a spinor + elif(rTemp[ii][0].shape[1]==4) : + if(len(res[ii])==0) : + for j in range(0,4) : + res[ii].append(sign*rTemp[ii][0][0,j]) + else : + for j in range(0,4) : + res[ii][j] += sign*rTemp[ii][0][0,j] + else : + print "Size problem adding results A",sign,rTemp[ii].shape + raise SkipThisVertex() + # spinor + elif(rTemp[ii][0].shape[0]==4 and rTemp[ii][0].shape[1]==1 ) : + if(len(res[ii])==0) : + for j in range(0,4) : + res[ii].append(sign*rTemp[ii][0][j,0]) + else : + for j in range(0,4) : + res[ii][j] += sign*rTemp[ii][0][j,0] + else : + print "Size problem adding results A",sign,rTemp[ii][0].shape + raise SkipThisVertex() + # 2 spin chains, should only be for a vertex + else : + for j1 in range(0,2) : + for j2 in range (0,2) : + val = sign*rTemp[j1][0]*rTemp[j2][1] + if(len(res[3])==0) : + res[2*j1+j2].append(val[0,0]) + else : + res[2*j1+j2][0] += val[0,0] + +def calculateDirac2(expr,start,end,startT,endT,sind,lind,Symbols,defns, + iloc,unContracted,spins,lorentz) : + tDot="" + # output + sVal={} + # no of chains + nchain=len(expr) + # now deal with the uncontracted cases + contracted={} + # sort out contracted and uncontracted indices + keys = unContracted.keys() + for key in keys: + # summed dummy index + if key.type=="D" : + contracted[key]=0 + del unContracted[key] + # RS index + elif key.type =="R" : + contracted[key]=0 + del unContracted[key] + # tensor index + elif key.type == "T1" or key.type=="T2" : + contracted[key]=0 + del unContracted[key] + # external index + elif key.type == "O" : + continue + # uncontracted vector index + elif key.type=="E" or key.type=="Q": + continue + else : + print 'Unknown type of uncontracted index',key + raise SkipThisVertex() + # check the lorentz structures + for lstruct in lorentz : + if(lstruct.name=="Epsilon" or + lstruct.name=="Vector") : + for index in lstruct.lorentz : + if(index.type=="E" and index.value==iloc) : + unContracted[index]=0 + elif(index.type=="P" or index.type=="E" + or index.type=="R" or index.type=="D") : + contracted[index]=0 + else : + print 'Unknown index',index, 'in ',lstruct + raise SkipThisVertex() + elif(lstruct.name=="Tensor") : + if(iloc==lstruct.value) : + Symbols += momCom.substitute({"v": "P%s"%lstruct.value}) + Symbols += "OM%s = Symbol(\"OM%s\")\n" % (lstruct.value,lstruct.value) + Symbols += "M%s2 = Symbol(\"M%s2\")\n" % (lstruct.value,lstruct.value) + Symbols += "p2 = Symbol(\"p2\")\n" + for ival in range(1,3) : + newIndex=LorentzIndex(ival) + newIndex.type="O" + newIndex.dimension=0 + lstruct.lorentz.append(newIndex) + unContracted[newIndex]=0 + # contracted with self + if(len(lstruct.lorentz)==0) : + pass + # both indices uncontracted, deal with later + elif lstruct.lorentz[0].type=="T1" and lstruct.lorentz[1].type=="T2": + pass + elif lstruct.lorentz[0].type=="T1": + pIndex = LorentzIndex(lstruct.value) + pIndex.dimension=1 + pIndex.type="P" + (tDot,dtemp) = constructDotProduct(pIndex,lstruct.lorentz[1],defns) + Symbols+="%s = Symbol(\"%s\")\n" %(tDot,tDot) + Symbols += momCom.substitute({"v": lstruct.lorentz[1]}) + elif lstruct.lorentz[1].type=="T2" : + pIndex = LorentzIndex(lstruct.value) + pIndex.dimension=1 + pIndex.type="P" + (tDot,dtemp) = constructDotProduct(pIndex,lstruct.lorentz[0],defns) + Symbols+="%s = Symbol(\"%s\")\n" %(tDot,tDot) + Symbols += momCom.substitute({"v": lstruct.lorentz[0]}) + # both indices still to be contracted + else : + contracted[lstruct.lorentz[0].type]=0 + contracted[lstruct.lorentz[1].type]=0 + else : + print 'Unknown lorentz object in calculateDirac2',lstruct,iloc + raise SkipThisVertex() + # iterate over the uncontracted indices + while True : + # loop over the unContracted indices + res = [] + for i in range(0,nchain) : + res.append([]) + res.append([]) + # loop over the contracted indices + while True : + # sign from metric tensor in contractions + sign = 1 + for key,val in contracted.iteritems() : + if(val>0) : sign *=-1 + eTemp =[] + sTemp =[] + fTemp =[] + sTTemp=[] + fTTemp=[] + # make the necessary replacements for remaining indices + for ichain in range(0,nchain) : + # compute the main expression + eTemp.append([]) + for val in expr[ichain] : + # already a matrix + if(val.name=="M") : + eTemp[ichain].append(val) + # gamma(mu), replace with correct dirac matrix + elif(val.name=="GMU") : + if(val.index in contracted) : + eTemp[ichain].append(dirac[contracted[val.index]]) + elif(val.index in unContracted) : + eTemp[ichain].append(dirac[unContracted[val.index]]) + else : + print 'Unknown index for gamma matrix',val + raise SkipThisVertex() + # unknown to be sorted out + else : + print 'Unknown type in expr',val + raise SkipThisVertex() + # start and end + # start + if(start[ichain].name=="S" or start[ichain].name=="M" ) : + sTemp.append(start[ichain].value) + elif(start[ichain].name=="RS") : + if(start[ichain].index in contracted) : + sTemp.append(start[ichain].value.substitute({"L" : imap[ contracted[start[ichain].index]] })) + else : + sTemp.append(start[ichain].value.substitute({"L" : imap[unContracted[start[ichain].index]] })) + elif(start[ichain].name=="RQ") : + i1 = unContracted[start[ichain].index] + sTemp.append(start[ichain].value.substitute({"A" : imap[i1], "DA" : dirac[i1] })) + elif(start[ichain].name=="RP") : + i1 = unContracted[start[ichain].index[0]] + i2 = contracted[start[ichain].index[1]] + eta=0 + if(i1==i2) : + if(i1==0) : eta = 1 + else : eta = -1 + sTemp.append(start[ichain].value.substitute({"eta" : eta, "A":imap[i1] , "B":imap[i2] , + "DA": dirac[i1], "DB": dirac[i2]})) + else : + print 'Barred spinor not a spinor',start[ichain] + raise SkipThisVertex() + if(startT[ichain].name=="S" or startT[ichain].name=="M" ) : + sTTemp.append(startT[ichain].value) + elif(startT[ichain].name=="RS") : + if(startT[ichain].index in contracted) : + sTTemp.append(startT[ichain].value.substitute({"L" : imap[ contracted[startT[ichain].index]] })) + else : + sTTemp.append(startT[ichain].value.substitute({"L" : imap[unContracted[startT[ichain].index]] })) + elif(startT[ichain].name=="RQ") : + i1 = unContracted[startT[ichain].index] + sTTemp.append(startT[ichain].value.substitute({"A" : imap[i1], "DA" : dirac[i1] })) + elif(startT[ichain].name=="RP") : + i1 = unContracted[startT[ichain].index[0]] + i2 = contracted[startT[ichain].index[1]] + eta=0 + if(i1==i2) : + if(i1==0) : eta = 1 + else : eta = -1 + sTTemp.append(startT[ichain].value.substitute({"eta" : eta, "A":imap[i1] , "B":imap[i2] , + "DA": dirac[i1], "DB": dirac[i2]})) + else : + print 'barred spinorT not a spinor',startT[ichain] + raise SkipThisVertex() + # end + if(end[ichain].name=="S" or end[ichain].name=="M" ) : + fTemp.append(end[ichain].value) + elif(end[ichain].name=="RS") : + if(end[ichain].index in contracted) : + fTemp.append(end[ichain].value.substitute({"L" : imap[ contracted[end[ichain].index]] })) + else : + fTemp.append(end[ichain].value.substitute({"L" : imap[unContracted[end[ichain].index]] })) + elif(end[ichain].name=="RQ") : + i1 = unContracted[end[ichain].index] + fTemp.append(end[ichain].value.substitute({"B" : imap[i1], "DB": dirac[i1] })) + elif(end[ichain].name=="RP") : + i1 = contracted[end[ichain].index[0]] + i2 = unContracted[end[ichain].index[1]] + eta=0 + if(i1==i2) : + if(i1==0) : eta = 1 + else : eta = -1 + fTemp.append(end[ichain].value.substitute({"eta" : eta, "A":imap[i1] , "B":imap[i2] , + "DA": dirac[i1], "DB": dirac[i2]})) + else : + print 'spinor not a spinor',end[ichain] + raise SkipThisVertex() + if(endT[ichain].name=="S" or endT[ichain].name=="M" ) : + fTTemp.append(endT[ichain].value) + elif(endT[ichain].name=="RS") : + if(endT[ichain].index in contracted) : + fTTemp.append(endT[ichain].value.substitute({"L" : imap[ contracted[endT[ichain].index]] })) + else : + fTTemp.append(endT[ichain].value.substitute({"L" : imap[unContracted[endT[ichain].index]] })) + elif(endT[ichain].name=="RQ") : + i1 = unContracted[endT[ichain].index] + fTTemp.append(endT[ichain].value.substitute({"B" : imap[i1], "DB": dirac[i1] })) + elif(endT[ichain].name=="RP") : + i1 = contracted[endT[ichain].index[0]] + i2 = unContracted[endT[ichain].index[1]] + eta=0 + if(i1==i2) : + if(i1==0) : eta = 1 + else : eta = -1 + fTTemp.append(endT[ichain].value.substitute({"eta" : eta, "A":imap[i1] , "B":imap[i2] , + "DA": dirac[i1], "DB": dirac[i2]})) + else : + print 'spinorT not a spinor',endT[ichain] + raise SkipThisVertex() + # and none dirac lorentz structures + isZero = False + for li in lorentz: + # uncontracted vector + if(li.name=="Vector") : + index = unContracted[li.lorentz[0]] + Symbols += momCom.substitute({"v":li.value}) + for ichain in range(0,nchain) : + eTemp[ichain].append("%s%s"% (li.value,imap[index]) ) + elif(li.name=="Epsilon") : + value="" + ival=[] + for index in li.lorentz : + if(index in contracted) : + if(index.type=="P" or index.type=="E") : + value += "*%s%s" % (index,imap[contracted[index]]) + ival.append(contracted[index]) + elif(index.type=="R" or index.type=="D") : + ival.append(contracted[index]) + else : + print 'Unknown index in Epsilon Tensor',index + raise SkipThisVertex() + elif(index in unContracted) : + ival.append(unContracted[index]) + if(len(value)!=0 and value[0]=="*") : + value = value[1:] + eVal = epsValue[ival[0]][ival[1]][ival[2]][ival[3]] + if(eVal==0) : + isZero = True + else : + for ichain in range(0,nchain) : + eTemp[ichain].append("(%s*%s)"% (eVal,value) ) + elif(li.name=="Tensor") : + if(li.lorentz[0] in unContracted and li.lorentz[1] in unContracted) : + value='0.5*(%s)'%tPropA[unContracted[li.lorentz[0]]][unContracted[li.lorentz[0]]].substitute({"iloc" : li.value}) + for ichain in range(0,nchain) : + eTemp[ichain].append("(%s)"% (value) ) + elif(len(li.lorentz)==4) : + if li.lorentz[0].type=="T1" and li.lorentz[1].type=="T2" : + value='0.5*(%s)'%tPropC[unContracted[li.lorentz[2]]][unContracted[li.lorentz[3]]][contracted[li.lorentz[0]]][contracted[li.lorentz[1]]].substitute({"iloc" : li.value}) + elif li.lorentz[0].type=="T1": + value='0.5*(%s)'%tPropB[unContracted[li.lorentz[2]]][unContracted[li.lorentz[3]]][contracted[li.lorentz[0]]].substitute({"iloc" : li.value, + "V" : li.lorentz[1], + "dot" : tDot}) + elif li.lorentz[1].type=="T2" : + value= '0.5*(%s)'%tPropB[unContracted[li.lorentz[2]]][unContracted[li.lorentz[3]]][contracted[li.lorentz[1]]].substitute({"iloc" : li.value, + "V" : li.lorentz[0], + "dot" : tDot}) + else : + print 'Both contracted tensor indices contracted' + raise SkipThisVertex() + for ichain in range(0,nchain) : + eTemp[ichain].append("(%s)"% (value) ) + else : + print 'Uncontracted on-shell tensor' + raise SkipThisVertex() + # unknown + else : + print 'Unknown expression in lorentz loop',li + raise SkipThisVertex() + # now evaluate the result + if(not isZero) : + rTemp =[[],[]] + for ichain in range(0,nchain) : + core = "*".join(str(x) for x in eTemp[ichain]) + temp={} + exec("import sympy\nfrom sympy import Symbol,Matrix\n"+Symbols+"result="+ + ( "(%s)*(%s)*(%s)" %(sTemp[ichain],core,fTemp[ichain]))) in temp + rTemp[0].append(temp["result"]) + temp={} + exec("import sympy\nfrom sympy import Symbol,Matrix,Transpose\n"+Symbols+"result="+ + ( "(%s)*(%s)*(Transpose(%s))*(%s)*(%s)" %(sTTemp[ichain],CC,core,CD,fTTemp[ichain]))) in temp + rTemp[1].append(temp["result"]) + # and add it to the output + addToOutput(res,nchain,sign,rTemp) + #### END OF THE CONTRACTED LOOP ##### + # increment the indices being summed over + keys=contracted.keys() + ii = len(keys)-1 + while ii >=0 : + if(contracted[keys[ii]]<3) : + contracted[keys[ii]]+=1 + break + else : + contracted[keys[ii]]=0 + ii-=1 + nZero=0 + for (key,val) in contracted.iteritems() : + if(val==0) : nZero+=1 + if(nZero==len(contracted)) : break + ###### END OF THE UNCONTRACTED LOOP ###### + # no uncontracted indices + if(len(unContracted)==0) : + if(len(res[0])==1) : + # scalar + if(len(res)==2) : + sVal["s" ] = res[0] + sVal["sT"] = res[1] + # 4 fermion + else : + sVal["s" ] = res[0] + sVal["sT2" ] = res[1] + sVal["sT1" ] = res[2] + sVal["sT12"] = res[3] + # spinor + elif(len(res[0])==4) : + for k in range(0,4) : + sVal[ "s%s" % (k+1) ] = res[0][k] + sVal[ "sT%s" % (k+1) ] = res[1][k] + else : + print 'Sum problem',len(res),len(res[0]) + raise SkipThisVertex() + break + # uncontracted indices + else : + istring = "" + for (key,val) in unContracted.iteritems() : + istring +=imap[val] + if(len(istring)>2) : + print 'Index problem',istring + raise SkipThisVertex() + sVal[istring] = res[0] + sVal[istring+"T"] = res[1] + # increment the unsummed indices + keys=unContracted.keys() + ii = len(keys)-1 + while ii >=0 : + if(unContracted[keys[ii]]<3) : + unContracted[keys[ii]]+=1 + break + else : + unContracted[keys[ii]]=0 + ii-=1 + nZero=0 + for (key,val) in unContracted.iteritems() : + if(val==0) : nZero+=1 + if(nZero==len(unContracted)) : break + # handle the vector case + if( "tt" in sVal) : + if(len(sVal)==32 and "tt" in sVal and len(sVal["tt"])==1) : + for key in sVal: + sVal[key] = sVal[key][0] + else : + print 'Tensor sum problem',len(sVal) + raise SkipThisVertex() + elif( "t" in sVal ) : + # deal with pure vectors + if(len(sVal)==8 and "t" in sVal and len(sVal["t"])==1) : + pass + # RS spinors + elif(len(sVal)==8 and "t" in sVal and len(sVal["t"])==4) : + pass + else : + print 'Value problem',len(sVal) + raise SkipThisVertex() + else : + if("s" in sVal) : + for key in sVal: + sVal[key] = sVal[key][0] + return sVal + +def convertDiracStructure(parsed,output,dimension,defns,iloc,L,lorentztag,vertex) : + # get the spins of the particles + spins = vertex.lorentz[0].spins + # check if we have one or two spin chains + nchain = (lorentztag.count("F")+lorentztag.count("R"))/2 + # storage of the intermediate results + expr =[] + start =[] + end =[] + startT=[] + endT =[] + sind=[0]*nchain + lind=[0]*nchain + unContracted={} + Symbols="" + dtemp=[0,0,0] + # parse the dirac matrix strings + for ichain in range(0,nchain) : + expr .append([]) + start .append("") + startT.append("") + end .append("") + endT .append("") + sind[ichain],lind[ichain],expr[ichain],start[ichain],startT[ichain],end[ichain],endT[ichain],Symbols =\ + processChain(dtemp,parsed,spins,Symbols,unContracted,defns,iloc) + # clean up parsed + # check we've dealt with everything + parsed = [x for x in parsed if x != ""] + lorentz=[] + if(len(parsed)!=0) : + for i in range(0,len(parsed)) : + if(parsed[i].name=="Metric") : + found = False + for ll in parsed[i].lorentz : + if(ll.type=="E" and ll.value==iloc) : + found = True + un=ll + else : + lo=ll + if(found) : + lstruct = LorentzStructure() + lstruct.name="Vector" + lstruct.value=lo + lstruct.lorentz=[un] + lstruct.spin=[] + lorentz.append(lstruct) + parsed[i]="" + unContracted[un]=0 + dimension[2] += lo.dimension + elif(parsed[i].name=="Epsilon") : + lstruct = LorentzStructure() + lstruct.name="Epsilon" + lstruct.lorentz=parsed[i].lorentz + lstruct.value=0 + lstruct.spin=[] + for index in lstruct.lorentz: + if(index.type=="P") : + dimension[2]+=1 + if( not index in defns) : + defns[(index,)]=["",""] + if(index.type=="P" or + (index.type=="E" and index.value!=iloc)) : + Symbols += momCom.substitute( {"v": index} ) + lorentz.append(lstruct) + parsed[i]="" + elif(parsed[i].name=="Tensor") : + lstruct = LorentzStructure() + lstruct.name="Tensor" + lstruct.value=parsed[i].value + lstruct.lorentz=parsed[i].lorentz + lstruct.spin=[] + for index in parsed[i].lorentz: + dimension[2] += index.dimension + parsed[i]="" + lorentz.append(lstruct) + else : + print 'Unknown lorentz structure',parsed[i] + raise SkipThisVertex() + + parsed = [x for x in parsed if x != ""] + if(len(parsed)!=0) : + print "Can't parse ",parsed,iloc + raise SkipThisVertex() + sVal ={} + dimension = list(map(lambda x, y: x + y, dtemp, dimension)) + # deal with the simplest case first + if len(unContracted) == 0 and len(lorentz) == 0: + sVal = calculateDirac(expr,start,end,startT,endT,sind,lind,Symbols,iloc) + else : + sVal = calculateDirac2(expr,start,end,startT,endT,sind,lind,Symbols,defns, + iloc,unContracted,spins,lorentz) + # set up the output + old = output + if(nchain==1) : + output = [old,sVal,(lind[0],sind[0])] + else : + output = [old,sVal,(lind[0],sind[0],lind[1],sind[1])] + return (output,dimension,defns) + +def convertLorentz(Lstruct,lorentztag,order,vertex,iloc,defns,evalVertex) : + eps = False + # split the structure into individual terms + structures=Lstruct.structure.split() + parsed=[] + # parse structures and convert lorentz contractions to dot products + for struct in structures : + ptemp = parse_structure(struct,Lstruct.spins) + parsed.append(contract(ptemp)) + # now in a position to generate the code + vals=generateVertex(iloc,Lstruct,parsed,lorentztag,vertex,defns) + evalVertex.append((vals[0],vals[1])) + if(vals[2]) : eps=True + return eps + +def swapOrder(vertex,iloc,momenta,fIndex) : + names=['','sca','sp','v'] + waves=['','sca','' ,'E'] + output="" + for i in range(1,4) : + ns = vertex.lorentz[0].spins.count(i) + if((ns<=1 and i!=2) or (ns<=2 and i==2)) : continue + if(i!=3 and i!=1) : + print 'Swap problem',i + raise SkipThisVertex() + sloc=[] + for j in range(0,len(vertex.lorentz[0].spins)) : + if(vertex.lorentz[0].spins[j]==i) : sloc.append(j+1) + if iloc in sloc : sloc.remove(iloc) + if(len(sloc)==1) : continue + for j in range(0,len(sloc)) : + output += " long id%s = %sW%s.id();\n" % (sloc[j],names[i],sloc[j]) + for j in range(0,len(sloc)) : + for k in range(j+1,len(sloc)) : + code = vertex.particles[sloc[j]-1].pdg_code + output += " if(id%s!=%s) {\n" % (sloc[j],code) + output += " swap(id%s,id%s);\n" % (sloc[j],sloc[k]) + output += " swap(%s%s,%s%s);\n" % (waves[i],sloc[j],waves[i],sloc[k]) + if(momenta[sloc[j]-1][0] or momenta[sloc[k]-1][0]) : + momenta[sloc[j]-1][0] = True + momenta[sloc[k]-1][0] = True + output += " swap(P%s,P%s);\n" % (sloc[j],sloc[k]) + output += " };\n" + return output + +def swapOrderFFFF(vertex,iloc,fIndex) : + output="" + for j in range(0,len(fIndex)) : + if(j%2==0) : + output += " SpinorWaveFunction s%s = sW%s;\n" % (fIndex[j],fIndex[j]) + else : + output += " SpinorBarWaveFunction sbar%s = sbarW%s;\n" % (fIndex[j],fIndex[j]) + + for j in range(0,len(fIndex)) : + if(j%2==0) : + output += " long id%s = sW%s.id();\n" % (fIndex[j],fIndex[j]) + else : + output += " long id%s = sbarW%s.id();\n" % (fIndex[j],fIndex[j]) + + for j in range(0,2) : + code = vertex.particles[fIndex[j]-1].pdg_code + output += " if(id%s!=%s) {\n" % (fIndex[j],code) + output += " swap(id%s,id%s);\n" % (fIndex[j],fIndex[j+2]) + wave="s" + if(j==1) : wave = "sbar" + output += " swap(%s%s,%s%s);\n" % (wave,fIndex[j],wave,fIndex[j+2]) + output += " };\n" + return output + +def constructSignature(vertex,order,iloc,decls,momenta,waves,fIndex) : + nf=0 + poff="" + offType="Complex" + for i in order : + spin = vertex.lorentz[0].spins[i-1] + if(i==iloc) : + if(spin==1) : + offType="ScalarWaveFunction" + elif(spin==2) : + if(i%2==1) : + offType="SpinorBarWaveFunction" + else : + offType="SpinorWaveFunction" + nf+=1 + elif(spin==4) : + if(i%2==1) : + offType="RSSpinorBarWaveFunction" + else : + offType="RSSpinorWaveFunction" + nf+=1 + elif(spin==3) : + offType="VectorWaveFunction" + elif(spin==5) : + offType="TensorWaveFunction" + else : + print 'Unknown spin',spin + raise SkipThisVertex() + momenta.append([False,""]) + else : + if(spin==1) : + decls.append("ScalarWaveFunction & scaW%s" % (i)) + momenta.append([False,"Lorentz5Momentum P%s =-scaW%s.momentum();" % (i,i)]) + waves.append("Complex sca%s = scaW%s.wave();" % (i,i)) + elif(spin==2) : + if(i%2==1) : + decls.append("SpinorWaveFunction & sW%s" % (fIndex[i-1])) + momenta.append([False,"Lorentz5Momentum P%s =-sW%s.momentum();" % (fIndex[i-1],fIndex[i-1])]) + waves.append("LorentzSpinor s%s = sW%s.wave();" % (fIndex[i-1],fIndex[i-1])) + nf+=1 + else : + decls.append("SpinorBarWaveFunction & sbarW%s" % (fIndex[i-1])) + momenta.append([False,"Lorentz5Momentum P%s =-sbarW%s.momentum();" % (fIndex[i-1],fIndex[i-1])]) + waves.append("LorentzSpinorBar sbar%s = sbarW%s.wave();" % (fIndex[i-1],fIndex[i-1])) + nf+=1 + elif(spin==3) : + decls.append("VectorWaveFunction & vW%s" % (i)) + momenta.append([False,"Lorentz5Momentum P%s =-vW%s.momentum();" % (i,i)]) + waves.append("LorentzPolarizationVector E%s = vW%s.wave();" % (i,i)) + elif(spin==4) : + if(i%2==1) : + decls.append("RSSpinorWaveFunction & RsW%s" % (i)) + momenta.append([False,"Lorentz5Momentum P%s =-RsW%s.momentum();" % (i,i)]) + waves.append("LorentzRSSpinor Rs%s = RsW%s.wave();" % (i,i)) + nf+=1 + else : + decls.append("RSSpinorBarWaveFunction & RsbarW%s" % (i)) + momenta.append([False,"Lorentz5Momentum P%s =-RsbarW%s.momentum();" % (i,i)]) + waves.append("LorentzRSSpinorBar Rsbar%s = RsbarW%s.wave();" % (i,i)) + nf+=1 + elif(spin==5) : + decls.append("TensorWaveFunction & tW%s" % (i)) + momenta.append([False,"Lorentz5Momentum P%s =-tW%s.momentum();" % (i,i)]) + waves.append("LorentzTensor T%s = tW%s.wave();" % (i,i)) + else : + print 'Unknown spin',spin + raise SkipThisVertex() + poff += "-P%s" % (i) + # ensure unbarred spinor first + ibar=-1 + isp=-1 + for i in range(0,len(decls)) : + if(decls[i].find("Bar")>0 and ibar==-1) : + ibar=i + elif(decls[i].find("Spinor")>=0 and isp==-1) : + isp=i + if(isp!=-1 and ibar!=-1 and isp>ibar) : + decls[ibar],decls[isp] = decls[isp],decls[ibar] + # constrct the signature + poff = ("Lorentz5Momentum P%s = " % iloc ) + poff + sig="" + if(iloc==0) : + sig="%s evaluate(Energy2, const %s)" % (offType,", const ".join(decls)) + # special for VVT vertex + if(len(vertex.lorentz[0].spins)==3 and vertex.lorentz[0].spins.count(3)==2 and + vertex.lorentz[0].spins.count(5)==1) : + sig = sig[0:-1] + ", Energy vmass=-GeV)" + else : + sig="%s evaluate(Energy2, int iopt, tcPDPtr out, const %s, complex mass=-GeV, complex width=-GeV)" % (offType,", const ".join(decls)) + momenta.append([True,poff+";"]) + # special for VVT vertex + if(len(vertex.lorentz[0].spins)==3 and vertex.lorentz[0].spins.count(3)==2 and + vertex.lorentz[0].spins.count(5)==1 and vertex.lorentz[0].spins[iloc-1]==5) : + sig=sig.replace("complex mass=-GeV","Energy vmass=-GeV, complex mass=-GeV") + for i in range(0,len(momenta)) : momenta[i][0]=True + return offType,nf,poff,sig + +def combineResult(res,nf,ispin,vertex) : + # extract the vals and dimensions + (vals,dim) = res + # construct the output structure + # vertex and off-shell scalars + if(ispin<=1) : + otype={'res':""} + # spins + elif(ispin==2) : + otype={'s1':"",'s2':"",'s3':"",'s4':""} + # vectors + elif(ispin==3) : + if( "t" in vals[0][1] ) : + otype={'t':"",'x':"",'y':"",'z':""} + else : + otype={"res":""} + # RS spinors + elif(ispin==4) : + otype={} + for i1 in imap : + for i in range(1,5) : + otype["%ss%s"% (i1,i)]="" + # off-shell tensors + elif(ispin==5) : + otype={} + for i1 in imap : + for i2 in imap : + otype["%s%s"%(i1,i2)]="" + else : + print 'Unknown spin',ispin + raise SkipThisVertex() + expr=[otype] + for i in range(0,nf-1) : + expr.append(copy.copy(otype)) + # dimension for checking + dimCheck=dim[0] + for i in range(0,len(vals)) : + # simple signs + if(vals[i]=="+" or vals[i]=="-") : + for ii in range(0,len(expr)) : + for(key,val) in expr[ii].iteritems() : + expr[ii][key] = expr[ii][key]+vals[i] + continue + # check the dimensions + if(dimCheck[0]!=dim[i][0] or dimCheck[1]!=dim[i][1] or + dimCheck[2]!=dim[i][2]) : + print "Dimension problem in result",i,dimCheck,dim,vertex + print vertex.lorentz + for j in range(0,len(vals)) : + print j,dim[j],vals[j] + raise SkipThisVertex() + # simplest case + if(isinstance(vals[i], basestring)) : + for ii in range(0,len(expr)) : + for(key,val) in expr[ii].iteritems() : + expr[ii][key] = expr[ii][key]+vals[i] + continue + # more complex structures + pre = vals[i][0] + if(pre=="(1.0)") : pre="" + if(not isinstance(vals[i][1],dict)) : + print 'must be a dict here' + raise SkipThisVertex() + # tensors + if("tt" in vals[i][1]) : + for i1 in imap : + for i2 in imap : + key="%s%s"%(i1,i2) + if(pre=="") : + expr[0][key] += "(%s)" % vals[i][1][key] + else : + expr[0][key] += "%s*(%s)" % (pre,vals[i][1][key]) + if(len(expr)==2) : + if(pre=="") : + expr[1][key] +="(%s)" % vals[i][1][key+"T"] + else : + expr[1][key] +="%s*(%s)" % (pre,vals[i][1][key+"T"]) + # standard fermion vertex case + elif(len(vals[i][1])==2 and "s" in vals[i][1] and "sT" in vals[i][1]) : + if(pre=="") : + expr[0]["res"] += "(%s)" % vals[i][1]["s"] + expr[1]["res"] += "(%s)" % vals[i][1]["sT"] + else : + expr[0]["res"] += "%s*(%s)" % (pre,vals[i][1]["s"]) + expr[1]["res"] += "%s*(%s)" % (pre,vals[i][1]["sT"]) + # spinor case + elif(len(vals[i][1])==8 and "s1" in vals[i][1]) : + for jj in range(1,5) : + if(pre=="") : + expr[0]["s%s" % jj] += "(%s)" % vals[i][1]["s%s" % jj] + expr[1]["s%s" % jj] += "(%s)" % vals[i][1]["sT%s" % jj] + else : + expr[0]["s%s" % jj] += "%s*(%s)" % (pre,vals[i][1]["s%s" % jj]) + expr[1]["s%s" % jj] += "%s*(%s)" % (pre,vals[i][1]["sT%s" % jj]) + # vector + elif(len(vals[i][1])%4==0 and "t" in vals[i][1] and len(vals[i][1]["t"])==1 ) : + for i1 in imap : + if(pre=="") : + expr[0][i1] += "(%s)" % vals[i][1][i1][0] + else : + expr[0][i1] += "%s*(%s)" % (pre,vals[i][1][i1][0]) + if(len(expr)==2) : + if(pre=="") : + expr[1][i1] +="(%s)" % vals[i][1][i1+"T"][0] + else : + expr[1][i1] +="%s*(%s)" % (pre,vals[i][1][i1+"T"][0]) + # 4 fermion vertex case + elif(len(vals[i][1])==4 and "sT12" in vals[i][1]) : + if(pre=="") : + expr[0]["res"] += "(%s)" % vals[i][1]["s"] + expr[1]["res"] += "(%s)" % vals[i][1]["sT2"] + expr[2]["res"] += "(%s)" % vals[i][1]["sT1"] + expr[3]["res"] += "(%s)" % vals[i][1]["sT12"] + else : + expr[0]["res"] += "%s*(%s)" % (pre,vals[i][1]["s"]) + expr[1]["res"] += "%s*(%s)" % (pre,vals[i][1]["sT2"]) + expr[2]["res"] += "(%s)" % vals[i][1]["sT1"] + expr[3]["res"] += "(%s)" % vals[i][1]["sT12"] + # RS spinor + elif(len(vals[i][1])%4==0 and "t" in vals[i][1] and len(vals[i][1]["t"])==4 ) : + for i1 in imap : + for k in range(1,5) : + key = "%ss%s" % (i1,k) + if(pre=="") : + expr[0][key] += "(%s)" % vals[i][1][i1][k-1] + expr[1][key] += "(%s)" % vals[i][1][i1+"T"][k-1] + else : + expr[0][key] += "%s*(%s)" % (pre,vals[i][1][i1][k-1]) + expr[1][key] += "%s*(%s)" % (pre,vals[i][1][i1+"T"][k-1]) + else : + print 'problem with type',vals[i] + raise SkipThisVertex() + # no of particles in the vertex + vDim = len(vertex.lorentz[0].spins) + # compute the unit and apply it + unit = computeUnit2(dimCheck,vDim) + if(unit!="") : + for ii in range(0,len(expr)) : + for (key,val) in expr[ii].iteritems() : + expr[ii][key] = "(%s)*(%s)" % (val,unit) + return expr + +def headerReplace(inval) : + return inval.replace("virtual","").replace("ScalarWaveFunction","").replace("SpinorWaveFunction","") \ + .replace("SpinorBarWaveFunction","").replace("VectorWaveFunction","").replace("TensorWaveFunction","") \ + .replace("Energy2","q2").replace("int","").replace("complex","").replace("Energy","").replace("=-GeV","") \ + .replace("const &","").replace("tcPDPtr","").replace(" "," ").replace("Complex","") + +def combineComponents(result,offType,RS) : + for i in range(0,len(result)) : + for (key,value) in result[i].iteritems() : + output=py2cpp(value.strip(),True) + result[i][key]=output[0] + # simplest case, just a value + if(len(result[0])==1 and "res" in result[0]) : + for i in range(0,len(result)) : + result[i] = result[i]["res"] + result[i]=result[i].replace("1j","ii") + return + # calculate the substitutions + if(not isinstance(result[0],basestring)) : + subs=[] + for ii in range(0,len(result)) : + subs.append({}) + for (key,val) in result[ii].iteritems() : + subs[ii]["out%s" % key]= val + # spinors + if("s1" in result[0]) : + stype = "LorentzSpinor" + sbtype = "LorentzSpinorBar" + if(offType.find("Bar")>0) : (stype,sbtype)=(sbtype,stype) + subs[0]["type"] = stype + result[0] = SpinorTemplate.substitute(subs[0]) + subs[1]["type"] = sbtype + result[1] = SpinorTemplate.substitute(subs[1]) + # tensors + elif("tt" in result[0]) : + for ii in range(0,len(result)) : + result[ii] = Template("LorentzTensor(${outxx},\n${outxy},\n${outxz},\n${outxt},\n${outyx},\n${outyy},\n${outyz},\n${outyt},\n${outzx},\n${outzy},\n${outzz},\n${outzt},\n${outtx},\n${outty},\n${outtz},\n${outtt})").substitute(subs[ii]) + result[ii]=result[ii].replace("(+","(") + # vectors + elif("t" in result[0]) : + for ii in range(0,len(result)) : + result[ii] = Template("LorentzVector(${outx},\n${outy},\n${outz},\n${outt})").substitute(subs[ii]) + result[ii]=result[ii].replace("(+","(") + # RS spinors + elif("ts1" in result[0]) : + stype = "LorentzRSSpinor" + sbtype = "LorentzRSSpinorBar" + if(offType.find("Bar")>0) : (stype,sbtype)=(sbtype,stype) + subs[0]["type"] = stype + result[0] = RSSpinorTemplate.substitute(subs[0]) + subs[1]["type"] = sbtype + result[1] = RSSpinorTemplate.substitute(subs[1]) + else : + print 'Type not implemented',result + raise SkipThisVertex() + for i in range(0,len(result)) : + result[i]=result[i].replace("1j","ii") + +def generateEvaluateFunction(model,vertex,iloc,values,defns,vertexEval,cf,order) : + RS = "R" in vertex.lorentz[0].name + FM = "F" in vertex.lorentz[0].name + # extract the start and end of the spin chains + if( RS or FM ) : + fIndex = vertexEval[0][0][0][2] + else : + fIndex=0 + # first construct the signature of the function + decls=[] + momenta=[] + waves=[] + offType,nf,poff,sig = constructSignature(vertex,order,iloc,decls,momenta,waves,fIndex) + # combine the different terms in the result + symbols=set() + localCouplings=[] + result=[] + ispin = 0 + if(iloc!=0) : + ispin = vertex.lorentz[0].spins[iloc-1] + # put the lorentz structures and couplings together + for j in range(0,len(vertexEval)) : + # get the lorentz structure piece + expr = combineResult(vertexEval[j],nf,ispin,vertex) + # get the coupling for this bit + val, sym = py2cpp(values[j]) + localCouplings.append("Complex local_C%s = %s;\n" % (j,val)) + symbols |=sym + # put them together + vtype="Complex" + if("res" in expr[0] and offType=="VectorWaveFunction") : + vtype="LorentzPolarizationVector" + if(len(result)==0) : + for ii in range(0,len(expr)) : + result.append({}) + for (key,val) in expr[ii].iteritems() : + result[ii][key] = " %s((local_C%s)*(%s)) " % (vtype,j,val) + else : + for ii in range(0,len(expr)) : + for (key,val) in expr[ii].iteritems(): + result[ii][key] += " + %s((local_C%s)*(%s)) " % (vtype,j,val) + # for more complex types merge the spin/lorentz components + combineComponents(result,offType,RS) + # multiple by scalar wavefunctions + scalars="" + for i in range (0,len(vertex.lorentz[0].spins)) : + if(vertex.lorentz[0].spins[i]==1 and i+1!=iloc) : + scalars += "sca%s*" % (i+1) + if(scalars!="") : + for ii in range(0,len(result)) : + result[ii] = "(%s)*(%s)" % (result[ii],scalars[0:-1]) + # vertex, just return the answer + if(iloc==0) : + result[0] = "return (%s)*(%s);\n" % (result[0],py2cpp(cf)[0]) + if(FM or RS) : + for i in range(1,len(result)) : + result[i] = "return (%s)*(%s);\n" % (result[i],py2cpp(cf)[0]) + # off-shell particle + else : + # off-shell scalar + if(vertex.lorentz[0].spins[iloc-1] == 1 ) : + result[0] = scaTemplate.format(iloc=iloc,cf=py2cpp(cf[0])[0],res=result[0]) + if(FM or RS) : + result[1] = scaTemplate.format(iloc=iloc,cf=py2cpp(cf[0])[0],res=result[1]) + # off-shell fermion + elif(vertex.lorentz[0].spins[iloc-1] == 2 ) : + result[0] = sTemplate.format(iloc=iloc,cf=py2cpp(cf[0])[0],offTypeA=offType.replace("WaveFunction",""), + res=result[0].replace( "M%s" % iloc, "mass" ),offTypeB=offType) + if(FM or RS) : + if(offType.find("Bar")>0) : + offTypeT=offType.replace("Bar","") + else : + offTypeT=offType.replace("Spinor","SpinorBar") + result[1] = sTemplate.format(iloc=iloc,cf=py2cpp(cf[0])[0],offTypeA=offTypeT.replace("WaveFunction",""), + res=result[1].replace( "M%s" % iloc, "mass" ),offTypeB=offTypeT) + # off-shell vector + elif(vertex.lorentz[0].spins[iloc-1] == 3 ) : + result[0] = vecTemplate.format(iloc=iloc,res=result[0],cf=py2cpp(cf)[0]) + if(FM or RS) : + result[1] = vecTemplate.format(iloc=iloc,cf=py2cpp(cf[0])[0],res=result[1]) + elif(vertex.lorentz[0].spins[iloc-1] == 4 ) : + if(offType.find("Bar")>0) : + offTypeT=offType.replace("Bar","") + else : + offTypeT=offType.replace("Spinor","SpinorBar") + result[1] = RSTemplate.format(iloc=iloc,cf=py2cpp(cf[0])[0],offTypeA=offTypeT.replace("WaveFunction",""), + res=result[1].replace( "M%s" % iloc, "mass" ),offTypeB=offTypeT) + result[0] = RSTemplate.format(iloc=iloc,cf=py2cpp(cf[0])[0],offTypeA=offType.replace("WaveFunction",""), + res=result[0].replace( "M%s" % iloc, "mass" ),offTypeB=offType) + # tensors + elif(vertex.lorentz[0].spins[iloc-1]) : + if(RS) : + print "RS spinors and tensors not handled" + raise SkipThisVertex() + result[0] = tenTemplate.format(iloc=iloc,cf=py2cpp(cf)[0],res=result[0]) + if(FM or RS) : + result[1] = tenTemplate.format(iloc=iloc,cf=py2cpp(cf)[0],res=result[1]) + else : + print 'Unknown spin for off-shell particle',vertex.lorentz[0].spins[iloc-1] + raise SkipThisVertex() + # check if momenta defns needed to clean up compile of code + for (key,val) in defns.iteritems() : + if( isinstance(key, basestring)) : + if(key.find("vvP")==0) : + momenta[int(key[3])-1][0] = True + else : + for vals in key : + if(vals.type=="P") : + momenta[vals.value-1][0] = True + # cat the definitions + defString="" + for (key,value) in defns.iteritems() : + if(value[0]=="") : continue + if(value[0][0]=="V" or value[0][0]=="T") : + defString+=" %s\n" %value[1] + for (key,value) in defns.iteritems() : + if(value[0]=="") : continue + if(value[0][0]!="V" and value[0][0]!="T") : + defString+=" %s\n" %value[1] + if(len(result)<=2) : + sorder=swapOrder(vertex,iloc,momenta,fIndex) + else : + sorder="" + momentastring="" + for i in range(0,len(momenta)) : + if(momenta[i][0] and momenta[i][1]!="") : + momentastring+=momenta[i][1]+"\n " + # special for 4-point VVVV + if(vertex.lorentz[0].spins.count(3)==4 and iloc==0) : + sig=sig.replace("Energy2","Energy2,int") + + header="virtual %s" % sig + sig=sig.replace("=-GeV","") + symboldefs = [ def_from_model(model,s) for s in symbols ] + function = evaluateTemplate.format(decl=sig,momenta=momentastring,defns=defString, + waves="\n ".join(waves),symbols='\n '.join(symboldefs), + couplings="\n ".join(localCouplings), + result=result[0],swap=sorder) + + # special for transpose + if(FM or RS) : + h2=header + if(not RS) : + h2=header.replace("evaluate","evaluateN") + function=function.replace("evaluate(","evaluateN(") + headers=[] + newHeader="" + for ifunction in range(1,len(result)) : + waveNew=[] + momentastring="" + htemp = header.split(",") + irs=-1 + isp=-1 + # RS case + if(RS) : + # sort out the wavefunctions + for i in range(0,len(waves)) : + if(waves[i].find("Spinor")<0) : + waveNew.append(waves[i]) + continue + if(waves[i].find("Bar")>0) : + waveNew.append(waves[i].replace("Bar","").replace("bar","")) + else : + waveNew.append(waves[i].replace("Spinor","SpinorBar").replace(" s"," sbar").replace("Rs","Rsbar")) + # sort out the momenta definitions + for i in range(0,len(momenta)) : + if(momenta[i][0] and momenta[i][1]!="") : + if(momenta[i][1].find("barW")>0) : + momentastring+=momenta[i][1].replace("barW","W")+"\n " + elif(momenta[i][1].find("sW")>0) : + momentastring+=momenta[i][1].replace("sW","sbarW")+"\n " + else : + momentastring+=momenta[i][1]+"\n " + # header string + for i in range(0,len(htemp)) : + if(htemp[i].find("RS")>0) : + if(htemp[i].find("Bar")>0) : + htemp[i]=htemp[i].replace("Bar","").replace("RsbarW","RsW") + else : + htemp[i]=htemp[i].replace("Spinor","SpinorBar").replace("RsW","RsbarW") + if(i>0) : irs=i + elif(htemp[i].find("Spinor")>0) : + if(htemp[i].find("Bar")>0) : + htemp[i]=htemp[i].replace("Bar","").replace("sbarW","sW") + else : + htemp[i]=htemp[i].replace("Spinor","SpinorBar").replace("sW","sbarW") + if(i>0) : isp=i + if(irs>0 and isp >0) : + htemp[irs],htemp[isp] = htemp[isp],htemp[irs] + # fermion case + else : + htemp2 = header.split(",") + # which fermions to exchange + if(len(fIndex)==2) : + isp = (fIndex[0],) + ibar = (fIndex[1],) + else : + if(ifunction==1) : + isp = (fIndex[2],) + ibar = (fIndex[3],) + elif(ifunction==2) : + isp = (fIndex[0],) + ibar = (fIndex[1],) + elif(ifunction==3) : + isp = (fIndex[0],fIndex[2]) + ibar = (fIndex[1],fIndex[3]) + # wavefunctions + for i in range(0,len(waves)) : + if(waves[i].find("Spinor")<0) : + waveNew.append(waves[i]) + continue + if(waves[i].find("Bar")>0) : + found=False + for itest in range(0,len(ibar)) : + if(waves[i].find("sbarW%s"%ibar[itest])>=0) : + waveNew.append(waves[i].replace("Bar","").replace("bar","")) + found=True + break + if(not found) : waveNew.append(waves[i]) + else : + found=False + for itest in range(0,len(isp)) : + if(waves[i].find("sW%s"%isp[itest])>=0) : + waveNew.append(waves[i].replace("Spinor","SpinorBar").replace(" s"," sbar")) + found=True + break + if(not found) : waveNew.append(waves[i]) + # momenta definitions + for i in range(0,len(momenta)) : + if(momenta[i][0] and momenta[i][1]!="") : + if(momenta[i][1].find("barW")>0) : + found = False + for itest in range(0,len(ibar)) : + if(momenta[i][1].find("barW%s"%ibar[itest])>=0) : + momentastring+=momenta[i][1].replace("barW","W")+"\n " + found=True + break + if(not found) : + momentastring+=momenta[i][1]+"\n " + elif(momenta[i][1].find("sW")>0) : + found=False + for itest in range(0,len(isp)) : + if(momenta[i][1].find("sW%s"%isp[itest])>=0) : + momentastring+=momenta[i][1].replace("sW","sbarW")+"\n " + found=True + break + if(not found) : + momentastring+=momenta[i][1]+"\n " + else : + momentastring+=momenta[i][1]+"\n " + # header + for i in range(0,len(htemp)) : + if(htemp[i].find("Spinor")<0) : continue + if(htemp[i].find("Bar")>0) : + if(i==0) : + htemp[i] =htemp [i].replace("Bar","") + htemp2[i]=htemp2[i].replace("Bar","") + continue + for itest in range(0,len(ibar)) : + if(htemp[i].find("sbarW%s"%ibar[itest])>=0) : + htemp[i] =htemp [i].replace("Bar","").replace("sbarW","sW") + htemp2[i]=htemp2[i].replace("Bar","").replace("sbarW%s"%ibar[itest],"sW%s"%isp[itest]) + break + else : + if(i==0) : + htemp [i]=htemp [i].replace("Spinor","SpinorBar") + htemp2[i]=htemp2[i].replace("Spinor","SpinorBar") + continue + for itest in range(0,len(isp)) : + if(htemp[i].find("sW%s"%isp[itest])>=0) : + htemp [i]=htemp [i].replace("Spinor","SpinorBar").replace("sW","sbarW") + htemp2[i]=htemp2[i].replace("Spinor","SpinorBar").replace("sW%s"%isp[itest],"sbarW%s"%ibar[itest]) + break + # header for transposed function + hnew = ','.join(htemp) + hnew = hnew.replace("virtual ","").replace("=-GeV","") + if(not RS) : + theader = ','.join(htemp2) + theader = theader.replace("virtual ","").replace("=-GeV","") + if(len(result)==2) : + hnew =hnew .replace("evaluate","evaluateT") + theader=theader.replace("evaluate","evaluateT") + else : + hnew =hnew .replace("evaluate","evaluateT%s" % ifunction) + theader=theader.replace("evaluate","evaluateT%s" % ifunction) + if(iloc not in fIndex) : + theader = headerReplace(theader) + else : + theader = headerReplace(h2).replace("evaluateN","evaluateT") + headers.append(theader) + newHeader += hnew +";\n" + else : + newHeader += hnew + fnew = evaluateTemplate.format(decl=hnew,momenta=momentastring,defns=defString, + waves="\n ".join(waveNew),symbols='\n '.join(symboldefs), + couplings="\n ".join(localCouplings), + result=result[ifunction],swap=sorder) + function +="\n" + fnew + + + if(FM and not RS) : + if(len(result)==2) : + if(iloc!=fIndex[1]) : + fi=1 + stype="sbar" + else : + fi=0 + stype="s" + header = vTemplateT.format(header=header.replace("Energy2,","Energy2 q2,"), + normal=headerReplace(h2), + transpose=theader,type=stype, + iloc=fIndex[fi],id=vertex.particles[fIndex[fi]-1].pdg_code) \ + +newHeader+h2.replace("virtual","") + else : + sorder = swapOrderFFFF(vertex,iloc,fIndex) + header = vTemplate4.format(header=header.replace("Energy2,","Energy2 q2,"), + iloc1=fIndex[1],iloc2=fIndex[3],swap=sorder, + id1=vertex.particles[fIndex[1]-1].pdg_code, + id2=vertex.particles[fIndex[3]-1].pdg_code, + cf=py2cpp(cf)[0], + res1=headerReplace(h2).replace("W",""), + res2=headers[0].replace("W",""), + res3=headers[1].replace("W",""), + res4=headers[2].replace("W",""))\ + +newHeader+h2.replace("virtual","") + else : + header=header + ";\n" + newHeader + return (header,function) + + +evaluateMultiple = """\ +{decl} {{ +{code} +}} +""" + +def multipleEvaluate(vertex,spin,defns) : + if(spin==1) : + name="scaW" + elif(spin==3) : + name="vW" + else : + print 'Evaluate multiple problem',spin + raise SkipThisVertex() + if(len(defns)==0) : return ("","") + header = defns[0] + ccdefn = header.replace("=-GeV","").replace("virtual ","").replace("Energy2","Energy2 q2") + code="" + spins=vertex.lorentz[0].spins + iloc=1 + waves=[] + for i in range(0,len(spins)) : + if(spins[i]==spin) : + waves.append("%s%s" %(name,i+1)) + for i in range(0,len(spins)) : + if(spins[i]==spin) : + if(iloc==1) : el="" + else : el="else " + call = headerReplace(defns[iloc]) + if(iloc!=1) : + call = call.replace(waves[0],waves[iloc-1]) + pdgid = vertex.particles[i].pdg_code + code += " %sif(out->id()==%s) return %s;\n" % (el,pdgid,call) + iloc+=1 + code+=" else assert(false);\n" + return (header,evaluateMultiple.format(decl=ccdefn,code=code)) + + diff --git a/Models/Feynrules/python/ufo2peg/helpers.py b/Models/Feynrules/python/ufo2peg/helpers.py --- a/Models/Feynrules/python/ufo2peg/helpers.py +++ b/Models/Feynrules/python/ufo2peg/helpers.py @@ -1,273 +1,266 @@ from string import Template from os import path import sys,cmath import re """ Helper functions for the Herwig Feynrules converter """ class CheckUnique: """Uniqueness checker. An object of this class remembers the value it was called with first. Any subsequent call to it will only succeed if the same value is passed again. For example, >>> f = CheckUnique() >>> f(5) >>> f(5) >>> f(4) Traceback (most recent call last): ... AssertionError """ def __init__(self): self.val = None def __call__(self,val): """Store value on first call, then compare.""" if self.val is None: self.val = val else: assert( val == self.val ) def is_number(s): """Check if a value is a number.""" try: float(s) except ValueError: return False return True def getTemplate(name): """Create a python string template from a file.""" templatename = '{name}.template'.format(name=name) # assumes the template files sit next to this script moduledir = path.dirname(path.abspath(__file__)) templatepath = path.join(moduledir,templatename) with open(templatepath, 'r') as f: templateText = f.read() return Template( templateText ) - def writeFile(filename, text): """Write text to a filename.""" with open(filename,'w') as f: f.write(text) - - - - -def qcd_qed_orders(vertex, coupling): +def coupling_orders(vertex, coupling, defns): # if more than one take QCD over QED and then lowest order in QED if type(coupling) is list: + print 'not sure this happens' + quit() qed = 0 qcd = 0 for coup in coupling : qed1 = coup.order.get('QED',0) qcd1 = coup.order.get('QCD',0) if qcd1 != 0: if qcd == 0 or (qcd1 != 0 and qcd1 < qcd): qcd=qcd1 qed=qed1 else: if qed == 0 or (qed1 != 0 and qed1 < qed): qed=qed1 else: - qed = coupling.order.get('QED',0) - qcd = coupling.order.get('QCD',0) - # WARNING: FIX FOR CASES WHEN BOTH ARE ZERO - # Is there a better way to treat this? - if qed + qcd + 2 != len(vertex.particles): - qed = len(vertex.particles) - qcd - 2 - - return qcd, qed + output={} + for ctype in defns : + output[ctype]=coupling.order.get(ctype,0) + return output def def_from_model(FR,s): """Return a C++ line that defines parameter s as coming from the model file.""" if("hw_kine" in s) :return "" stype = typemap(getattr(FR.parameters,s).type) return '{t} {s} = model_->{s}();'.format(t=stype,s=s) _typemap = {'complex':'Complex', 'real':'double'} def typemap(s): return _typemap[s] def add_brackets(expr, syms): result = expr for s in syms: pattern = r'({symb})(\W|$)'.format(symb=s) result = re.sub(pattern, r'\1()\2', result) return result def banner(): return """\ =============================================================================================================== ______ ______ _ __ _ _ _ | ___| | ___ \ | | / /| | | | (_) _ _ | |_ ___ _ _ _ __ | |_/ /_ _ | | ___ ___ / / | |_| | ___ _ __ __ __ _ __ _ _| |_ _| |_ | _|/ _ \| | | || \_ \ | /| | | || | / _ \/ __| / / | _ | / _ \| \__|\ \ /\ / /| | / _` ||_ _||_ _| | | | __/| |_| || | | || |\ \| |_| || || __/\__ \ / / | | | || __/| | \ V V / | || (_| | |_| |_| \_| \___| \__, ||_| |_|\_| \_|\__,_||_| \___||___//_/ \_| |_/ \___||_| \_/\_/ |_| \__, | __/ | __/ | |___/ |___/ =============================================================================================================== generating model/vertex/.model/.in files please be patient! =============================================================================================================== """ #################### ??? ####################### # function that replaces alphaS (aS)-dependent variables # with their explicit form which also contains strongCoupling def aStoStrongCoup(stringin, paramstoreplace, paramstoreplace_expressions): #print stringin for xx in range(0,len(paramstoreplace)): #print paramstoreplace[xx], paramstoreplace_expressions[xx] stringout = stringin.replace(paramstoreplace[xx], '(' + PyMathToThePEGMath(paramstoreplace_expressions[xx],allparams) + ')') stringout = stringout.replace('aS', '(sqr(strongCoupling(q2))/(4.0*Constants::pi))') #print 'resulting string', stringout return stringout # function that replaces alphaEW (aEW)-dependent variables # with their explicit form which also contains weakCoupling def aEWtoWeakCoup(stringin, paramstoreplace, paramstoreplace_expressions): #print stringin for xx in range(0,len(paramstoreplace)): #print paramstoreplace[xx], paramstoreplace_expressions[xx] stringout = stringin.replace(paramstoreplace[xx], '(' + PyMathToThePEGMath(paramstoreplace_expressions[xx],allparams) + ')') stringout = stringout.replace('aEWM1', '(1/(sqr(electroMagneticCoupling(q2))/(4.0*Constants::pi)))') #print 'resulting string', stringout return stringout if __name__ == "__main__": import doctest doctest.testmod() if False: # Check if the Vertex is self-conjugate or not pdgcode = [0,0,0,0] notsmvertex = False vhasw = 0 vhasz = 0 vhasf = 0 vhasg = 0 vhash = 0 vhasp = 0 # print 'printing particles in vertex' for i in range(len(v.particles)): # print v.particles[i].pdg_code pdgcode[i] = v.particles[i].pdg_code if pdgcode[i] == 23: vhasz += 1 if pdgcode[i] == 22: vhasp += 1 if pdgcode[i] == 25: vhash += 1 if pdgcode[i] == 21: vhasg += 1 if pdgcode[i] == 24: vhasw += 1 if abs(pdgcode[i]) < 7 or (abs(pdgcode[i]) > 10 and abs(pdgcode[i]) < 17): vhasf += 1 if pdgcode[i] not in SMPARTICLES: notsmvertex = True # treat replacement of SM vertices with BSM vertices? if notsmvertex == False: if( (vhasf == 2 and vhasz == 1) or (vhasf == 2 and vhasw == 1) or (vhasf == 2 and vhash == 1) or (vhasf == 2 and vhasg == 1) or (vhasf == 2 and vhasp == 0) or (vhasg == 3) or (vhasg == 4) or (vhasw == 2 and vhash == 1) or (vhasw == 3) or (vhasw == 4) or (vhash == 1 and vhasg == 2) or (vhash == 1 and vhasp == 2)): #print 'VERTEX INCLUDED IN STANDARD MODEL!' v.include = 0 notincluded += 1 #continue selfconjugate = 0 for j in range(len(pdgcode)): for k in range(len(pdgcode)): if j != k and j != 0 and abs(pdgcode[j]) == abs(pdgcode[k]): selfconjugate = 1 #print 'self-conjugate vertex' # print pdgcode[j] # if the Vertex is not self-conjugate, then add the conjugate vertex # automatically scfac = [1,1,1,1] if selfconjugate == 0: #first find the self-conjugate particles for u in range(len(v.particles)): if v.particles[u].selfconjugate == 0: scfac[u] = -1 # print 'particle ', v.particles[u].pdg_code, ' found not to be self-conjugate' if selfconjugate == 0: plistarray[1] += str(scfac[1] * v.particles[1].pdg_code) + ',' + str(scfac[0] * v.particles[0].pdg_code) + ',' + str(scfac[2] * v.particles[2].pdg_code) if len(v.particles) is 4: plistarray[1] += ',' + str(scfac[3] * v.particles[3].pdg_code) #print 'Conjugate vertex:', plistarray[1] class SkipThisVertex(Exception): pass def extractAntiSymmetricIndices(instring,funct) : terms = instring.strip(funct).strip(")").split(",") sign=1. for iy in range(0,len(terms)) : for ix in range(-1,-len(terms)+iy,-1) : swap = False if(len(terms[ix])==1 and len(terms[ix-1])==1) : swap = int(terms[ix])x1 W- d 'SSS' : '-complex(0,1)', # ok 'VVSS' : '-complex(0,1)', # ok 'VVT' : 'complex(0,2)', 'VVVT' : '-complex(0,2)', 'SSSS' : '-complex(0,1)', # ok 'FFS' : '-complex(0,1)', # ok 'SST' : 'complex(0,2)', 'FFT' : '-complex(0,8)', 'FFVT' : '-complex(0,4)', 'RFS' : 'complex(0,1)', 'RFV' : 'complex(0,1)', } +genericVertices=['FFFF','FFVV','FFSS','FFVS','VVVV','VVVT','FFVT', + 'RFVV','RFVS','RFSS','SSST','VVST','FFST'] + +skipped5Point=False + # template for the header for a vertex VERTEXHEADER = """\ #include "ThePEG/Helicity/Vertex/{spindirectory}/{lorentztag}Vertex.h" """ +GENERALVERTEXHEADER = """\ +#include "ThePEG/Helicity/Vertex/Abstract{lorentztag}Vertex.h" +""" # template for the implmentation for a vertex VERTEXCLASS = getTemplate('Vertex_class') +GENERALVERTEXCLASS = getTemplate('GeneralVertex_class') # template for the .cc file for vertices VERTEX = getTemplate('Vertex.cc') vertexline = """\ -create Herwig::{modelname}V_{vname} /Herwig/{modelname}/V_{vname} -insert {modelname}:ExtraVertices 0 /Herwig/{modelname}/V_{vname} +create Herwig::FRModel{classname} /Herwig/{modelname}/{classname} +insert {modelname}:ExtraVertices 0 /Herwig/{modelname}/{classname} """ - def get_lorentztag(spin): """Produce a ThePEG spin tag for the given numeric FR spins.""" spins = { 1 : 'S', 2 : 'F', 3 : 'V', 4 : 'R', 5 : 'T', -1 : 'U' } result=[] for i in range(0,len(spin)) : result.append((spins[spin[i]],i+1)) def spinsort(a,b): """Helper function for ThePEG's FVST spin tag ordering.""" (a1,a2) = a (b1,b2) = b if a1 == b1: return 0 for letter in 'URFVST': if a1 == letter: return -1 if b1 == letter: return 1 result = sorted(result, cmp=spinsort) order=[] output="" for i in range(0,len(result)) : (a,b) = result[i] order.append(b) output+=a return (output,order) def unique_lorentztag(vertex): """Check and return the Lorentz tag of the vertex.""" unique = CheckUnique() for l in vertex.lorentz: (lorentztag,order) = get_lorentztag(l.spins) unique( lorentztag ) lname = l.name[:len(lorentztag)] if sorted(lorentztag) != sorted(lname): raise Exception("Lorentztags: %s is not %s in %s" % (lorentztag,lname,vertex)) return (lorentztag,order) def colors(vertex) : try: unique = CheckUnique() for pl in vertex.particles_list: struct = [ p.color for p in pl ] unique(struct) except: struct = [ p.color for p in vertex.particles ] pos = colorpositions(struct) L = len(struct) return (L,pos) +def coloursort(a,b) : + if a == b: return 0 + i1=int(a[4]) + i2=int(b[4]) + if(i1==i2) : return 0 + elif(i1id()=={id1} && p2->id()=={id3} && p3->id()=={id2}) || (p1->id()=={id2} && p2->id()=={id1} && p3->id()=={id3}) || (p1->id()=={id3} && p2->id()=={id2} && p3->id()=={id1})) {{ sign *= -1.; }} norm(norm()*sign); """ if(not "p1" in couplingptrs[0]) : couplingptrs[0] += ' p1' if(not "p2" in couplingptrs[1]) : couplingptrs[1] += ' p2' if(not "p3" in couplingptrs[2]) : couplingptrs[2] += ' p3' if("Bar" not in vertex.color[0]) : order,sign = extractAntiSymmetricIndices(vertex.color[0],"Epsilon(") else : order,sign = extractAntiSymmetricIndices(vertex.color[0],"EpsilonBar(") subs = {"id1" : vertex.particles[int(order[0])-1].pdg_code, "id2" : vertex.particles[int(order[1])-1].pdg_code, "id3" : vertex.particles[int(order[2])-1].pdg_code, "epssign" : sign } append+=EPSSIGN.format(**subs) return couplingptrs,append class VertexConverter: 'Convert the vertices in a FR model to extract the information ThePEG needs.' - def __init__(self,model,parmsubs) : + def __init__(self,model,parmsubs,defns) : 'Initialize the parameters' - self.ONE_EACH=True self.verbose=False self.vertex_skipped=False self.ignore_skipped=False self.model=model self.all_vertices= [] + self.vertex_names = {} self.modelname="" - self.globalsign=self.global_sign() self.no_generic_loop_vertices = False self.parmsubs = parmsubs - - def global_sign(self): - 'Initial pass to find global sign at the moment does nothing' - return 1.0 - # for v in self.model.all_vertices: - # pids = sorted([ p.pdg_code for p in v.particles ]) - # if pids != [-11,11,22]: continue - # coup = v.couplings - # assert( len(coup) == 1 ) - # val = coup.values()[0].value - # val = evaluate(val) - # assert( val.real == 0 ) - # return 1 if val.imag > 0 else -1 + self.couplingDefns = defns + self.genericTensors = False def readArgs(self,args) : 'Extract the relevant command line arguments' self.ignore_skipped = args.ignore_skipped self.verbose = args.verbose self.modelname = args.name self.no_generic_loop_vertices = args.no_generic_loop_vertices - + self.include_generic = args.include_generic + self.genericTensors = args.use_generic_for_tensors + def should_print(self) : 'Check if we should output the results' return not self.vertex_skipped or self.ignore_skipped def convert(self) : 'Convert the vertices' if(self.verbose) : print 'verbose mode on: printing all vertices' print '-'*60 labels = ('vertex', 'particles', 'Lorentz', 'C_L', 'C_R', 'norm') pprint.pprint(labels) - # check if we should merge vertices - if(self.ONE_EACH) : - self.all_vertices = self.model.all_vertices - else: - self.all_vertices = collapse_vertices(self.model.all_vertices) + # extract the vertices + self.all_vertices = self.model.all_vertices # convert the vertices vertexclasses, vertexheaders = [], set() + ifile=1 + icount=0 for vertexnumber,vertex in enumerate(self.all_vertices,1) : # process the vertex (skip,vertexClass,vertexHeader) = \ self.processVertex(vertexnumber,vertex) # check it can be handled if(skip) : continue # add to the list + icount +=1 vertexclasses.append(vertexClass) vertexheaders.add(vertexHeader) WRAP = 25 - if vertexnumber % WRAP == 0: - write_vertex_file({'vertexnumber' : vertexnumber//WRAP, + if icount % WRAP == 0 or vertexHeader.find("Abstract")>=0: + write_vertex_file({'vertexnumber' : ifile, 'vertexclasses' : '\n'.join(vertexclasses), 'vertexheaders' : ''.join(vertexheaders), 'ModelName' : self.modelname}) vertexclasses = [] vertexheaders = set() + icount=0 + ifile+=1 # exit if there's vertices we can't handle if not self.should_print(): sys.stderr.write( """ Error: The conversion was unsuccessful, some vertices could not be generated. If you think the missing vertices are not important and want to go ahead anyway, use --ignore-skipped. Herwig may not give correct results, though. """ ) sys.exit(1) # if still stuff to output it do it if vertexclasses: - write_vertex_file({'vertexnumber' : vertexnumber//WRAP + 1, + write_vertex_file({'vertexnumber' : ifile + 1, 'vertexclasses' : '\n'.join(vertexclasses), 'vertexheaders' : ''.join(vertexheaders), 'ModelName' : self.modelname}) print '='*60 def setCouplingPtrs(self,lorentztag,qcd,append,prepend) : couplingptrs = [',tcPDPtr']*len(lorentztag) if lorentztag == 'VSS': couplingptrs[1] += ' p2' elif lorentztag == 'FFV': couplingptrs[0] += ' p1' elif (lorentztag == 'VVV' or lorentztag == 'VVVS' or lorentztag == "SSS" or lorentztag == "VVVT" ) \ and (append or prepend ) : couplingptrs[0] += ' p1' couplingptrs[1] += ' p2' couplingptrs[2] += ' p3' - elif (lorentztag == 'VVVV' and qcd != 2) or\ + elif (lorentztag == 'VVVV' and qcd < 2) or\ (lorentztag == "SSSS" and prepend ): couplingptrs[0] += ' p1' couplingptrs[1] += ' p2' couplingptrs[2] += ' p3' couplingptrs[3] += ' p4' return couplingptrs def processVertex(self,vertexnumber,vertex) : + global skipped5Point # get the Lorentz tag for the vertex lorentztag,order = unique_lorentztag(vertex) # check if we should skip the vertex vertex.herwig_skip_vertex = checkGhostGoldstoneVertex(lorentztag,vertex) + # check the order of the vertex and skip 5 points + if(len(lorentztag)>=5) : + vertex.herwig_skip_vertex = True + if(not skipped5Point) : + skipped5Point = True + print "Skipping 5 point vertices which aren\'t used in Herwig7" + if(vertex.herwig_skip_vertex) : return (True,"","") - # get the factor for the vertex - try: - lf = lfactors[lorentztag] - except KeyError: + # check if we support this at all + if( lorentztag not in lfactors and + lorentztag not in genericVertices) : msg = 'Warning: Lorentz structure {tag} ( {ps} ) in {name} ' \ 'is not supported.\n'.format(tag=lorentztag, name=vertex.name, ps=' '.join(map(str,vertex.particles))) sys.stderr.write(msg) vertex.herwig_skip_vertex = True self.vertex_skipped=True return (True,"","") + # get the factor for the vertex + generic = False + try: + lf = lfactors[lorentztag] + if( self.genericTensors and "T" in lorentztag) : + raise KeyError() + except KeyError: + if(not self.include_generic) : + msg = 'Warning: Lorentz structure {tag} ( {ps} ) in {name} ' \ + 'is not supported.\n'.format(tag=lorentztag, name=vertex.name, + ps=' '.join(map(str,vertex.particles))) + sys.stderr.write(msg) + vertex.herwig_skip_vertex = True + self.vertex_skipped=True + return (True,"","") + else : + lf=1. + generic=True # get the ids of the particles at the vertex - if self.ONE_EACH: - plistarray = [ ','.join([ str(vertex.particles[o-1].pdg_code) for o in order ]) ] - else: - plistarray = [ ','.join([ str(p.pdg_code) for p in pl ]) - for pl in vertex.particles_list ] + plistarray = [ ','.join([ str(vertex.particles[o-1].pdg_code) for o in order ]) ] # parse the colour structure for the vertex try: L,pos = colors(vertex) - cf = colorfactor(vertex,L,pos,lorentztag) + cs,cf = colorfactor(vertex,L,pos,lorentztag) except SkipThisVertex: msg = 'Warning: Color structure for vertex ( {ps} ) in {name} ' \ 'is not supported.\n'.format(tag=lorentztag, name=vertex.name, ps=' '.join(map(str,vertex.particles))) sys.stderr.write(msg) vertex.herwig_skip_vertex = True self.vertex_skipped=True return (True,"","") - ### classname classname = 'V_%s' % vertex.name - # try to extract the couplings - try: - (all_couplings,header,qcd,qed,prepend,append) = \ - self.extractCouplings(lorentztag,pos,lf,cf,vertex,order) - except SkipThisVertex: - msg = 'Warning: Lorentz structure {tag} ( {ps} ) in {name} ' \ - 'is not supported, may have a non-perturbative form.\n'.format(tag=lorentztag, name=vertex.name, - ps=' '.join(map(str,vertex.particles))) - sys.stderr.write(msg) - vertex.herwig_skip_vertex = True - self.vertex_skipped=True - return (True,"","") - - # set the coupling ptrs in the setCoupling call - couplingptrs = self.setCouplingPtrs(lorentztag,qcd,append != '',prepend != '') - - # final processing of the couplings - try : + if(not generic) : + try : + return self.extractGeneric(vertex,order,lorentztag,classname,plistarray,pos,lf,cf,cs) + except SkipThisVertex: + if(not self.include_generic) : + msg = 'Warning: Lorentz structure {tag} ( {ps} ) in {name} ' \ + 'is not supported, may have a non-perturbative form.\n'.format(tag=lorentztag, name=vertex.name, + ps=' '.join(map(str,vertex.particles))) + + sys.stderr.write(msg) + vertex.herwig_skip_vertex = True + self.vertex_skipped=True + return (True,"","") + else : + try : + return self.extractGeneral(vertex,order,lorentztag,classname,plistarray,pos,cf,cs) + except SkipThisVertex: + msg = 'Warning: Lorentz structure {tag} ( {ps} ) in {name} ' \ + 'is not supported, may have a non-perturbative form.\n'.format(tag=lorentztag, name=vertex.name, + ps=' '.join(map(str,vertex.particles))) + + sys.stderr.write(msg) + vertex.herwig_skip_vertex = True + self.vertex_skipped=True + return (True,"","") + else : + try : + return self.extractGeneral(vertex,order,lorentztag,classname,plistarray,pos,cf,cs) + except SkipThisVertex: + msg = 'Warning: Lorentz structure {tag} ( {ps} ) in {name} ' \ + 'is not supported, may have a non-perturbative form.\n'.format(tag=lorentztag, name=vertex.name, + ps=' '.join(map(str,vertex.particles))) + + sys.stderr.write(msg) + vertex.herwig_skip_vertex = True + self.vertex_skipped=True + return (True,"","") + + + def extractGeneric(self,vertex,order,lorentztag,classname,plistarray,pos,lf,cf,cs) : + classes="" + headers="" + # identify the maximum colour flow and orders of the couplings + maxColour=0 + couplingOrders=[] + self.vertex_names[vertex.name] = [classname] + for (color_idx,lorentz_idx),coupling in vertex.couplings.iteritems(): + maxColour=max(maxColour,color_idx) + orders = coupling_orders(vertex, coupling, self.couplingDefns) + if(orders not in couplingOrders) : couplingOrders.append(orders) + # loop the order of the couplings + iorder = 0 + for corder in couplingOrders : + iorder +=1 + cname=classname + if(iorder!=1) : + cname= "%s_%s" % (classname,iorder) + self.vertex_names[vertex.name].append(cname) + header = "" + prepend="" + append="" + all_couplings=[] + for ix in range(0,maxColour+1) : + all_couplings.append([]) + # loop over the colour structures + for colour in range(0,maxColour+1) : + for (color_idx,lorentz_idx),coupling in vertex.couplings.iteritems() : + # check colour structure and coupling order + if(color_idx!=colour) : continue + if(coupling_orders(vertex, coupling, self.couplingDefns)!=corder) : continue + # get the prefactor for the lorentz structure + L = vertex.lorentz[lorentz_idx] + prefactors = calculatePrefactor(lf,cf[color_idx]) + # calculate the value of the coupling + value = couplingValue(coupling) + # handling of the different types of couplings + if lorentztag in ['FFS','FFV']: + all_couplings[color_idx] = fermionCouplings(value,prefactors,L,all_couplings[color_idx],order) + elif 'T' in lorentztag : + append, all_couplings[color_idx] = tensorCouplings(vertex,value,prefactors,L,lorentztag,pos, + all_couplings[color_idx],order) + elif 'R' in lorentztag : + all_couplings[color_idx] = RSCouplings(value,prefactors,L,all_couplings[color_idx],order) + elif lorentztag == 'VVS' or lorentztag == "VVSS" or lorentztag == "VSS" : + all_couplings[color_idx] = scalarVectorCouplings(value,prefactors,L,lorentztag, + all_couplings[color_idx],order) + elif lorentztag == "SSS" or lorentztag == "SSSS" : + prepend, header, all_couplings[color_idx] = scalarCouplings(vertex,value,prefactors,L,lorentztag, + all_couplings[color_idx],prepend,header) + elif "VVV" in lorentztag : + all_couplings[color_idx],append = vectorCouplings(vertex,value,prefactors,L,lorentztag,pos, + all_couplings[color_idx],append,corder["QCD"],order) + else: + raise SkipThisVertex() + # set the coupling ptrs in the setCoupling call + couplingptrs = self.setCouplingPtrs(lorentztag,corder["QCD"],append != '',prepend != '') + # final processing of the couplings symbols = set() if(lorentztag in ['FFS','FFV']) : (normcontent,leftcontent,rightcontent,append) = processFermionCouplings(lorentztag,vertex, self.model,self.parmsubs, - all_couplings) + all_couplings,order) elif('T' in lorentztag) : (leftcontent,rightcontent,normcontent) = processTensorCouplings(lorentztag,vertex,self.model, - self.parmsubs,all_couplings) + self.parmsubs,all_couplings,order) elif(lorentztag=="SSS" or lorentztag=="SSSS") : normcontent = processScalarCouplings(self.model,self.parmsubs,all_couplings) elif(lorentztag=="VVS" or lorentztag =="VVSS" or lorentztag=="VSS") : normcontent,append,lorentztag,header,sym = processScalarVectorCouplings(lorentztag,vertex, self.model,self.parmsubs, all_couplings,header,order) symbols |=sym elif("VVV" in lorentztag) : normcontent,append,header =\ processVectorCouplings(lorentztag,vertex,self.model,self.parmsubs,all_couplings,append,header) else : SkipThisVertex() - except SkipThisVertex: - msg = 'Warning: Lorentz structure {tag} ( {ps} ) in {name} ' \ - 'is not supported, may have a non-perturbative form.\n'.format(tag=lorentztag, name=vertex.name, - ps=' '.join(map(str,vertex.particles))) + ### do we need left/right? + if 'FF' in lorentztag and lorentztag != "FFT": + #leftcalc = aStoStrongCoup(py2cpp(leftcontent)[0], paramstoreplace_, paramstoreplace_expressions_) + #rightcalc = aStoStrongCoup(py2cpp(rightcontent)[0], paramstoreplace_, paramstoreplace_expressions_) + leftcalc, sym = py2cpp(leftcontent) + symbols |= sym + rightcalc, sym = py2cpp(rightcontent) + symbols |= sym + left = 'left(' + leftcalc + ');' + right = 'right(' + rightcalc + ');' + else: + left = '' + right = '' + leftcalc = '' + rightcalc = '' + #normcalc = aStoStrongCoup(py2cpp(normcontent)[0], paramstoreplace_, paramstoreplace_expressions_) + normcalc, sym = py2cpp(normcontent) + symbols |= sym + # UFO is GeV by default + if lorentztag in ['VVS','SSS']: + normcalc = 'Complex((%s) * GeV / UnitRemoval::E)' % normcalc + elif lorentztag in ['GeneralVVS']: + normcalc = 'Complex(-(%s) * UnitRemoval::E / GeV )' % normcalc + elif lorentztag in ['FFT','VVT', 'SST', 'FFVT', 'VVVT' , 'VVVS' ]: + normcalc = 'Complex((%s) / GeV * UnitRemoval::E)' % normcalc + norm = 'norm(' + normcalc + ');' + # finally special handling for eps tensors + if(len(vertex.color)==1 and vertex.color[0].find("Epsilon")>=0) : + couplingptrs, append = epsilonSign(vertex,couplingptrs,append) + # define unkown symbols from the model + symboldefs = [ def_from_model(self.model,s) for s in symbols ] + couplingOrder="" + for coupName,coupVal in corder.iteritems() : + couplingOrder+=" orderInCoupling(CouplingType::%s,%s);\n" %(coupName,coupVal) + ### assemble dictionary and fill template + subs = { 'lorentztag' : lorentztag, # ok + 'classname' : cname, # ok + 'symbolrefs' : '\n '.join(symboldefs), + 'left' : left, # doesn't always exist in base + 'right' : right, # doesn't always exist in base + 'norm' : norm, # needs norm, too + 'addToPlist' : '\n'.join([ 'addToList(%s);'%s for s in plistarray]), + 'parameters' : '', + 'couplingOrders' : couplingOrder, + 'colourStructure' : cs, + 'couplingptrs' : ''.join(couplingptrs), + 'spindirectory' : spindirectory(lorentztag), + 'ModelName' : self.modelname, + 'prepend' : prepend, + 'append' : append, + 'header' : header + } # ok + + # print info if required + if self.verbose: + print '-'*60 + pprint.pprint(( classname, plistarray, leftcalc, rightcalc, normcalc )) + headers+=VERTEXHEADER.format(**subs) + classes+=VERTEXCLASS.substitute(subs) + return (False,classes,headers) + + def extractGeneral(self,vertex,order,lorentztag,classname,plistarray,pos,cf,cs) : + eps=False + classes="" + headers="" + # check the colour flows, three cases supported either 1 flow or 3 in gggg + # or multiple wierd ones in FFFF + cidx=-1 + gluon4point = (len(pos[8])==4 and vertex.lorentz[0].spins.count(3)==4) + FFFF = (len(pos[3])==2 and len(pos[-3])==2 and vertex.lorentz[0].spins.count(2)==4) + couplingOrders=[] + colours={} + + for (color_idx,lorentz_idx),coupling in vertex.couplings.iteritems() : + orders = coupling_orders(vertex, coupling, self.couplingDefns) + if(orders not in couplingOrders) : couplingOrders.append(orders) + if(gluon4point) : + color = vertex.color[color_idx] + f = color.split("*") + (o1,s1) = extractAntiSymmetricIndices(f[0],"f(") + (o2,s2) = extractAntiSymmetricIndices(f[1],"f(") + if(o2[0]=0) : - couplingptrs, append = epsilonSign(vertex,couplingptrs,append) - # define unkown symbols from the model - symboldefs = [ def_from_model(self.model,s) for s in symbols ] - ### assemble dictionary and fill template - subs = { 'lorentztag' : lorentztag, # ok - 'classname' : classname, # ok - 'symbolrefs' : '\n '.join(symboldefs), - 'left' : left, # doesn't always exist in base - 'right' : right, # doesn't always exist in base - 'norm' : norm, # needs norm, too - - #################### need survey which different setter methods exist in base classes - - 'addToPlist' : '\n'.join([ 'addToList(%s);'%s for s in plistarray]), - 'parameters' : '', - 'setCouplings' : '', - 'qedorder' : qed, - 'qcdorder' : qcd, - 'couplingptrs' : ''.join(couplingptrs), - 'spindirectory' : spindirectory(lorentztag), - 'ModelName' : self.modelname, - 'prepend' : prepend, - 'append' : append, - 'header' : header - } # ok - - # print info if required - if self.verbose: - print '-'*60 - pprint.pprint(( classname, plistarray, leftcalc, rightcalc, normcalc )) - - return (False,VERTEXCLASS.substitute(subs),VERTEXHEADER.format(**subs)) + # loop over the different orders in the couplings + # and colour structures + iorder=0 + self.vertex_names[vertex.name]=[classname] + for corder in couplingOrders : + for (cidx,(cstruct,cfactor)) in colours.iteritems() : + iorder +=1 + cname=classname + if(iorder!=1) : + cname= "%s_%s" % (classname,iorder) + self.vertex_names[vertex.name].append(cname) + defns=[] + vertexEval=[] + values=[] + imax = len(vertex.particles)+1 + if lorentztag in genericVertices : + imax=1 + for (color_idx,lorentz_idx),coupling in vertex.couplings.iteritems() : + # only the colour structre and coupling order we want + if(color_idx != cidx) : continue + if(coupling_orders(vertex, coupling, self.couplingDefns)!=corder) : continue + # calculate the value of the coupling + values.append(couplingValue(coupling)) + # now to convert the spin structures + for i in range(0,imax) : + if(len(defns)1 and i!=2) : mult[i] = [] + for i in range(0,imax) : + (evalHeader,evalCC) = generateEvaluateFunction(self.model,vertex,i,values,defns[i],vertexEval[i],cfactor,order) + if(i!=0 and spins[i-1] in mult) : + if(len(mult[spins[i-1]])==0) : mult[spins[i-1]].append(evalHeader) + evalHeader=evalHeader.replace("evaluate(","evaluate%s(" % i) + evalCC =evalCC .replace("evaluate(","evaluate%s(" % i) + mult[spins[i-1]].append(evalHeader) + header+=" "+evalHeader+";\n" + impls+=evalCC + # combine the multiple defn if needed + for (key,val) in mult.iteritems() : + (evalHeader,evalCC) = multipleEvaluate(vertex,key,val) + if(evalHeader!="") : header += " "+evalHeader+";\n" + if(evalCC!="") : impls += evalCC + impls=impls.replace("evaluate", "FRModel%s::evaluate" % cname) + couplingOrder="" + for coupName,coupVal in corder.iteritems() : + couplingOrder+=" orderInCoupling(CouplingType::%s,%s);\n" %(coupName,coupVal) + ### assemble dictionary and fill template + subs = { 'lorentztag' : lorentztag, + 'classname' : cname, + 'addToPlist' : '\n'.join([ 'addToList(%s);'%s for s in plistarray]), + 'ModelName' : self.modelname, + 'couplingOrders' : couplingOrder, + 'colourStructure' : cstruct, + 'evaldefs' : header, + 'evalimpls' : impls} + newHeader = GENERALVERTEXHEADER.format(**subs) + if(eps) : newHeader +="#include \"ThePEG/Helicity/epsilon.h\"\n" + headers+=newHeader + classes+=GENERALVERTEXCLASS.substitute(subs) + return (False,classes,headers) def get_vertices(self,libname): vlist = ['library %s\n' % libname] for v in self.all_vertices: if v.herwig_skip_vertex: continue - vlist.append( vertexline.format(modelname=self.modelname, vname=v.name) ) + for name in self.vertex_names[v.name] : + vlist.append( vertexline.format(modelname=self.modelname, classname=name) ) if( not self.no_generic_loop_vertices) : vlist.append('insert {modelname}:ExtraVertices 0 /Herwig/{modelname}/V_GenericHPP\n'.format(modelname=self.modelname) ) vlist.append('insert {modelname}:ExtraVertices 0 /Herwig/{modelname}/V_GenericHGG\n'.format(modelname=self.modelname) ) return ''.join(vlist) - def extractCouplings(self,lorentztag,pos,lf,cf,vertex,order) : - coup_left = [] - coup_right = [] - coup_norm = [] - header = "" - qcd=0 - qed=0 - prepend="" - append="" - unique_qcd = CheckUnique() - unique_qed = CheckUnique() - maxColour=0 - for (color_idx,lorentz_idx),coupling in vertex.couplings.iteritems(): - maxColour=max(maxColour,color_idx) - all_couplings=[] - for ix in range(0,maxColour+1) : - all_couplings.append([]) - for colour in range(0,maxColour+1) : - for (color_idx,lorentz_idx),coupling in vertex.couplings.iteritems() : - if(color_idx!=colour) : continue - qcd, qed = qcd_qed_orders(vertex, coupling) - try : - unique_qcd( qcd ) - unique_qed( qed ) - except : - msg = 'Different powers of QCD and QED couplings for the same vertex'\ - ' is not currently supported for {ps} in {name}.\n'.format(tag=lorentztag, name=vertex.name, - ps=' '.join(map(str,vertex.particles))) - sys.stderr.write(msg) - raise SkipThisVertex() - L = vertex.lorentz[lorentz_idx] - prefactors = calculatePrefactor(self.globalsign,lorentztag,lf,cf[color_idx]) - # calculate the value of the coupling - value = couplingValue(coupling) - # handling of the different types of couplings - if lorentztag in ['FFS','FFV']: - all_couplings[color_idx] = fermionCouplings(value,prefactors,L,all_couplings[color_idx],order) - elif 'T' in lorentztag : - append, all_couplings[color_idx] = tensorCouplings(vertex,value,prefactors,L,lorentztag,pos, - all_couplings[color_idx],order) - elif 'R' in lorentztag : - all_couplings[color_idx] = RSCouplings(value,prefactors,L,all_couplings[color_idx],order) - elif lorentztag == 'VVS' or lorentztag == "VVSS" or lorentztag == "VSS" : - all_couplings[color_idx] = scalarVectorCouplings(value,prefactors,L,lorentztag, - all_couplings[color_idx],order) - elif lorentztag == "SSS" or lorentztag == "SSSS" : - prepend, header, all_couplings[color_idx] = scalarCouplings(vertex,value,prefactors,L,lorentztag, - all_couplings[color_idx],prepend,header) - elif "VVV" in lorentztag : - all_couplings[color_idx],append = vectorCouplings(vertex,value,prefactors,L,lorentztag,pos, - all_couplings[color_idx],append,qcd,order) - else: - raise SkipThisVertex() - - # return the result - return (all_couplings,header,qcd,qed,prepend,append) diff --git a/Models/General/BSMWidthGenerator.cc b/Models/General/BSMWidthGenerator.cc --- a/Models/General/BSMWidthGenerator.cc +++ b/Models/General/BSMWidthGenerator.cc @@ -1,74 +1,78 @@ // -*- C++ -*- // // BSMWidthGenerator.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 BSMWidthGenerator class. // #include "BSMWidthGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/Decay/General/GeneralTwoBodyDecayer.h" using namespace Herwig; IBPtr BSMWidthGenerator::clone() const { return new_ptr(*this); } IBPtr BSMWidthGenerator::fullclone() const { return new_ptr(*this); } void BSMWidthGenerator::persistentOutput(PersistentOStream & os) const { os << theModes; } void BSMWidthGenerator::persistentInput(PersistentIStream & is, int) { is >> theModes; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigBSMWidthGenerator("Herwig::BSMWidthGenerator", "Herwig.so"); void BSMWidthGenerator::Init() { static ClassDocumentation documentation ("A width generator for BSM particles."); } void BSMWidthGenerator::setupMode(tcDMPtr mode, tDecayIntegratorPtr decayer, unsigned int) { tcGeneralTwoBodyDecayerPtr dec = dynamic_ptr_cast(decayer); theModes.push_back(make_pair(mode, dec)); } Energy BSMWidthGenerator::partial2BodyWidth(int iloc, Energy m0, Energy m1, Energy m2) const { if( m0 < (m1 + m2) ) return ZERO; //need pointers to particles involved tcDMPtr dm = theModes[iloc].first; ParticleMSet::const_iterator pit = dm->products().begin(); tcPDPtr parta = *pit; ++pit; tcPDPtr partb = *pit; int dummya(0); double dummyb(0.); - if( !theModes[iloc].second->twoBodyMEcode(*dm, dummya, dummyb) ) - swap(parta, partb); - return theModes[iloc].second->partialWidth(make_pair(dm->parent(), m0), - make_pair(parta, m1), - make_pair(partb, m2)); + if(theModes[iloc].second) { + if( !theModes[iloc].second->twoBodyMEcode(*dm, dummya, dummyb) ) + swap(parta, partb); + return theModes[iloc].second->partialWidth(make_pair(dm->parent(), m0), + make_pair(parta, m1), + make_pair(partb, m2)); + } + else + return ZERO; } diff --git a/Models/General/GenericHGGVertex.cc b/Models/General/GenericHGGVertex.cc --- a/Models/General/GenericHGGVertex.cc +++ b/Models/General/GenericHGGVertex.cc @@ -1,169 +1,170 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the GenericHGGVertex class. // #include "GenericHGGVertex.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "Herwig/Models/StandardModel/StandardModel.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/Looptools/clooptools.h" using namespace Herwig; GenericHGGVertex::GenericHGGVertex() : setup_(false), q2Last_(ZERO), coupLast_(0.), idLast_(0) { orderInGs(2); orderInGem(1); + colourStructure(ColourStructure::DELTA); } IBPtr GenericHGGVertex::clone() const { return new_ptr(*this); } IBPtr GenericHGGVertex::fullclone() const { return new_ptr(*this); } void GenericHGGVertex::persistentOutput(PersistentOStream & os) const { os << bosons_ << setup_ << vertices_ << model_; } void GenericHGGVertex::persistentInput(PersistentIStream & is, int) { is >> bosons_ >> setup_ >> vertices_ >> model_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigGenericHGGVertex("Herwig::GenericHGGVertex", "Herwig.so"); void GenericHGGVertex::Init() { static ClassDocumentation documentation ("The GenericHGGVertex class implements the coupling of" " the Higgs bosons to gluons in a generic model."); static RefVector interfaceBosons ("Bosons", "The Higgs bosons in the model.", &GenericHGGVertex::bosons_, -1, false, false, true, false, false); } void GenericHGGVertex::doinit() { for(unsigned int ix=0;ixid()); } VVSLoopVertex::doinit(); if(loopToolsInitialized()) Looptools::ltexi(); } void GenericHGGVertex::setCoupling (Energy2 q2, tcPDPtr part1, tcPDPtr part2, tcPDPtr part3) { if(!setup_) initializeVertex(); assert(part1->id()==ParticleID::g && part2->id()==ParticleID::g); // find the particles in the loop map >::iterator it = vertices_.find(part3); // check there are some if(it==vertices_.end()) { norm(0.); return; } Looptools::clearcache(); // overall factor if( q2 != q2Last_ || coupLast_ == 0. || part3->id() != idLast_ ) { q2Last_ = q2; idLast_ = part3->id(); coupLast_ = sqr(strongCoupling(q2)); // loop over the loop particles masses.clear(); type.clear(); couplings.clear(); setNParticles(it->second.size()); for(unsigned int ix=0;ixsecond.size();++ix) { masses.push_back(model_->mass(q2,it->second[ix].particle)); if(it->second[ix].particle->iSpin()==PDT::Spin0) { type.push_back(PDT::Spin0); it->second[ix].scalar->setCoupling(q2,part3,it->second[ix].particle,it->second[ix].particle->CC()); couplings.push_back(make_pair(0.5*it->second[ix].scalar->norm(),0.5*it->second[ix].scalar->norm())); } else if(it->second[ix].particle->iSpin()==PDT::Spin1Half) { type.push_back(PDT::Spin1Half); assert(it->second[ix].fermion); it->second[ix].fermion->setCoupling(q2,it->second[ix].particle,it->second[ix].particle->CC(),part3); Complex coupling = it->second[ix].fermion->norm(); Complex lc = it->second[ix].fermion->left (); Complex rc = it->second[ix].fermion->right(); couplings.push_back(make_pair(0.5*coupling*lc,0.5*coupling*rc)); } else assert(false); } VVSLoopVertex::setCoupling(q2, part1, part2, part3); } norm(coupLast_); } void GenericHGGVertex::initializeVertex() { // get the model model_ = dynamic_ptr_cast(generator()->standardModel()); if(!model_) throw InitException(); // loop over all the vertices unsigned int nv(model_->numberOfVertices()); for(unsigned int ib=0;ibvertex(iv)->getNpoint()>3) continue; if( !model_->vertex(iv)->isIncoming(bosons_[ib])) continue; for(unsigned int il = 0; il < 3; ++il) { tPDVector decaylist = model_->vertex(iv)->search(il, bosons_[ib]); tPDVector::size_type nd = decaylist.size(); for( tPDVector::size_type i = 0; i < nd; i += 3 ) { tPDPtr pa(decaylist[i]), pb(decaylist[i + 1]), pc(decaylist[i + 2]); if( pb->id() == bosons_[ib]->id() ) swap(pa, pb); if( pc->id() == bosons_[ib]->id() ) swap(pa, pc); // check coloured and particle antiparticle if( pb->CC() != pc || !pb->coloured() || !pc->coloured()) continue; // only know how to deal with triplets assert(pb->iColour()==PDT::Colour3 || pb->iColour()==PDT::Colour3bar); // scalar loop if(pb->iSpin()==PDT::Spin0) { SSSVertexPtr vertex = dynamic_ptr_cast(model_->vertex(iv)); if(!vertex) continue; map >::iterator it = vertices_.find(bosons_[ib]); if(it!=vertices_.end()) { it->second.push_back(Interaction(pb->id()>0?pb:pc,vertex,FFSVertexPtr())); } else { vertices_.insert(make_pair(bosons_[ib],vector(1,Interaction(pb->id()>0?pb:pc,vertex,FFSVertexPtr())))); } } // fermion loop else if(pb->iSpin()==PDT::Spin1Half) { FFSVertexPtr vertex = dynamic_ptr_cast(model_->vertex(iv)); if(!vertex) continue; map >::iterator it = vertices_.find(bosons_[ib]); if(it!=vertices_.end()) { it->second.push_back(Interaction(pb->id()>0?pb:pc,SSSVertexPtr(),vertex)); } else { vertices_.insert(make_pair(bosons_[ib],vector(1,Interaction(pb->id()>0?pb:pc,SSSVertexPtr(),vertex)))); } } else assert(false); } } } } // set up now setup_ = true; } diff --git a/Models/General/GenericHPPVertex.cc b/Models/General/GenericHPPVertex.cc --- a/Models/General/GenericHPPVertex.cc +++ b/Models/General/GenericHPPVertex.cc @@ -1,205 +1,206 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the GenericHPPVertex class. // #include "GenericHPPVertex.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "Herwig/Models/StandardModel/StandardModel.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/Looptools/clooptools.h" using namespace Herwig; GenericHPPVertex::GenericHPPVertex() : setup_(false), q2Last_(ZERO), coupLast_(0.), idLast_(0) { orderInGs(0); orderInGem(3); + colourStructure(ColourStructure::SINGLET); } IBPtr GenericHPPVertex::clone() const { return new_ptr(*this); } IBPtr GenericHPPVertex::fullclone() const { return new_ptr(*this); } void GenericHPPVertex::persistentOutput(PersistentOStream & os) const { os << bosons_ << setup_ << vertices_ << model_; } void GenericHPPVertex::persistentInput(PersistentIStream & is, int) { is >> bosons_ >> setup_ >> vertices_ >> model_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigGenericHPPVertex("Herwig::GenericHPPVertex", "Herwig.so"); void GenericHPPVertex::Init() { static ClassDocumentation documentation ("The GenericHPPVertex class implements the coupling of" " the Higgs bosons to gluons in a generic model."); static RefVector interfaceBosons ("Bosons", "The Higgs bosons in the model.", &GenericHPPVertex::bosons_, -1, false, false, true, false, false); } void GenericHPPVertex::doinit() { for(unsigned int ix=0;ixid()); } VVSLoopVertex::doinit(); if(loopToolsInitialized()) Looptools::ltexi(); } void GenericHPPVertex::setCoupling (Energy2 q2, tcPDPtr part1, tcPDPtr part2, tcPDPtr part3) { if(!setup_) initializeVertex(); assert(part1->id()==ParticleID::gamma && part2->id()==ParticleID::gamma); // find the particles in the loop map >::iterator it = vertices_.find(part3); // check there are some if(it==vertices_.end()) { norm(0.); return; } Looptools::clearcache(); // overall factor if( q2 != q2Last_ || coupLast_ == 0. || part3->id() != idLast_ ) { q2Last_ = q2; idLast_ = part3->id(); coupLast_ = sqr(electroMagneticCoupling(q2)); // loop over the loop particles masses.clear(); type.clear(); couplings.clear(); setNParticles(it->second.size()); for(unsigned int ix=0;ixsecond.size();++ix) { masses.push_back(model_->mass(q2,it->second[ix].particle)); // charge and colour factor double fact(1.); fact *= sqr(double(it->second[ix].particle->iCharge())/3.); if(it->second[ix].particle->iColour()==PDT::Colour3|| it->second[ix].particle->iColour()==PDT::Colour3bar) fact *=3.; else if(it->second[ix].particle->iColour()==PDT::Colour0) fact *= 1.; else { assert(false); } // spin-0 if(it->second[ix].particle->iSpin()==PDT::Spin0) { type.push_back(PDT::Spin0); it->second[ix].scalar->setCoupling(q2,part3,it->second[ix].particle,it->second[ix].particle->CC()); couplings.push_back(make_pair(fact*it->second[ix].scalar->norm(), fact*it->second[ix].scalar->norm())); } else if(it->second[ix].particle->iSpin()==PDT::Spin1Half) { type.push_back(PDT::Spin1Half); assert(it->second[ix].fermion); it->second[ix].fermion->setCoupling(q2,it->second[ix].particle,it->second[ix].particle->CC(),part3); Complex coupling = fact*it->second[ix].fermion->norm(); Complex lc = it->second[ix].fermion->left (); Complex rc = it->second[ix].fermion->right(); couplings.push_back(make_pair(coupling*lc,coupling*rc)); } else if(it->second[ix].particle->iSpin()==PDT::Spin1) { type.push_back(PDT::Spin1); assert(it->second[ix].vector); it->second[ix].vector->setCoupling(q2,it->second[ix].particle,it->second[ix].particle->CC(),part3); couplings.push_back(make_pair(fact*it->second[ix].vector->norm(), fact*it->second[ix].vector->norm())); } else assert(false); } VVSLoopVertex::setCoupling(q2, part1, part2, part3); } norm(coupLast_); } void GenericHPPVertex::initializeVertex() { // get the model model_ = dynamic_ptr_cast(generator()->standardModel()); if(!model_) throw InitException(); // loop over all the vertices unsigned int nv(model_->numberOfVertices()); for(unsigned int ib=0;ibvertex(iv)->getNpoint()>3) continue; if( !model_->vertex(iv)->isIncoming(bosons_[ib])) continue; for(unsigned int il = 0; il < 3; ++il) { tPDVector decaylist = model_->vertex(iv)->search(il, bosons_[ib]); tPDVector::size_type nd = decaylist.size(); for( tPDVector::size_type i = 0; i < nd; i += 3 ) { tPDPtr pa(decaylist[i]), pb(decaylist[i + 1]), pc(decaylist[i + 2]); if( pb->id() == bosons_[ib]->id() ) swap(pa, pb); if( pc->id() == bosons_[ib]->id() ) swap(pa, pc); // check coloured and particle antiparticle if( pb->CC() != pc || !pb->charged() || !pc->charged()) continue; // // scalar loop if(pb->iSpin()==PDT::Spin0) { SSSVertexPtr vertex = dynamic_ptr_cast(model_->vertex(iv)); if(!vertex) continue; map >::iterator it = vertices_.find(bosons_[ib]); if(it!=vertices_.end()) { it->second.push_back(Interaction(pb->id()>0?pb:pc,vertex,FFSVertexPtr(),VVSVertexPtr())); } else { vertices_.insert(make_pair(bosons_[ib], vector(1,Interaction(pb->id()>0?pb:pc,vertex, FFSVertexPtr(),VVSVertexPtr())))); } } // fermion loop else if(pb->iSpin()==PDT::Spin1Half) { FFSVertexPtr vertex = dynamic_ptr_cast(model_->vertex(iv)); if(!vertex) continue; map >::iterator it = vertices_.find(bosons_[ib]); if(it!=vertices_.end()) { it->second.push_back(Interaction(pb->id()>0?pb:pc,SSSVertexPtr(),vertex,VVSVertexPtr())); } else { vertices_.insert(make_pair(bosons_[ib], vector(1,Interaction(pb->id()>0?pb:pc,SSSVertexPtr(), vertex,VVSVertexPtr())))); } } // vector loop else if(pb->iSpin()==PDT::Spin1) { VVSVertexPtr vertex = dynamic_ptr_cast(model_->vertex(iv)); if(!vertex) continue; map >::iterator it = vertices_.find(bosons_[ib]); if(it!=vertices_.end()) { it->second.push_back(Interaction(pb->id()>0?pb:pc,SSSVertexPtr(),FFSVertexPtr(),vertex)); } else { vertices_.insert(make_pair(bosons_[ib], vector(1,Interaction(pb->id()>0?pb:pc,SSSVertexPtr(), FFSVertexPtr(),vertex)))); } } else assert(false); } } } } // set up now setup_ = true; } diff --git a/Models/General/HardProcessConstructor.cc b/Models/General/HardProcessConstructor.cc --- a/Models/General/HardProcessConstructor.cc +++ b/Models/General/HardProcessConstructor.cc @@ -1,813 +1,957 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the HardProcessConstructor class. // #include "HardProcessConstructor.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; void HardProcessConstructor::persistentOutput(PersistentOStream & os) const { os << debug_ << subProcess_ << model_; } void HardProcessConstructor::persistentInput(PersistentIStream & is, int) { is >> debug_ >> subProcess_ >> model_; } // The following static variable is needed for the type // description system in ThePEG. DescribeAbstractClass describeHerwigHardProcessConstructor("Herwig::HardProcessConstructor", "Herwig.so"); void HardProcessConstructor::Init() { static ClassDocumentation documentation ("Base class for implementation of the automatic generation of hard processes"); static Switch interfaceDebugME ("DebugME", "Print comparison with analytical ME", &HardProcessConstructor::debug_, false, false, false); static SwitchOption interfaceDebugMEYes (interfaceDebugME, "Yes", "Print the debug information", true); static SwitchOption interfaceDebugMENo (interfaceDebugME, "No", "Do not print the debug information", false); } void HardProcessConstructor::doinit() { Interfaced::doinit(); EGPtr eg = generator(); model_ = dynamic_ptr_cast(eg->standardModel()); if(!model_) throw InitException() << "HardProcessConstructor:: doinit() - " << "The model pointer is null!" << Exception::abortnow; if(!eg->eventHandler()) { throw InitException() << "HardProcessConstructor:: doinit() - " << "The eventHandler pointer was null therefore " << "could not get SubProcessHandler pointer " << Exception::abortnow; } string subProcessName = eg->preinitInterface(eg->eventHandler(), "SubProcessHandlers", "get",""); subProcess_ = eg->getObject(subProcessName); if(!subProcess_) { ostringstream s; s << "HardProcessConstructor:: doinit() - " << "There was an error getting the SubProcessHandler " << "from the current event handler. "; generator()->logWarning( Exception(s.str(), Exception::warning) ); } } GeneralHardME::ColourStructure HardProcessConstructor:: colourFlow(const tcPDVector & extpart) const { PDT::Colour ina = extpart[0]->iColour(); PDT::Colour inb = extpart[1]->iColour(); PDT::Colour outa = extpart[2]->iColour(); PDT::Colour outb = extpart[3]->iColour(); // incoming colour neutral if(ina == PDT::Colour0 && inb == PDT::Colour0) { if( outa == PDT::Colour0 && outb == PDT::Colour0 ) { return GeneralHardME::Colour11to11; } else if( outa == PDT::Colour3 && outb == PDT::Colour3bar ) { return GeneralHardME::Colour11to33bar; } else if( outa == PDT::Colour8 && outb == PDT::Colour8 ) { return GeneralHardME::Colour11to88; } else assert(false); } // incoming 3 3 else if(ina == PDT::Colour3 && inb == PDT::Colour3 ) { if( outa == PDT::Colour3 && outb == PDT::Colour3 ) { return GeneralHardME::Colour33to33; } else if( outa == PDT::Colour6 && outb == PDT::Colour0 ) { return GeneralHardME::Colour33to61; } else if( outa == PDT::Colour0 && outb == PDT::Colour6 ) { return GeneralHardME::Colour33to16; } else if ( outa == PDT::Colour0 && outb == PDT::Colour3bar) { return GeneralHardME::Colour33to13bar; } else if ( outb == PDT::Colour0 && outa == PDT::Colour3bar) { return GeneralHardME::Colour33to3bar1; } else if ( outa == PDT::Colour8 && outb == PDT::Colour3bar) { return GeneralHardME::Colour33to83bar; } else if ( outb == PDT::Colour8 && outa == PDT::Colour3bar) { return GeneralHardME::Colour33to3bar8; } else assert(false); } // incoming 3bar 3bar else if(ina == PDT::Colour3bar && inb == PDT::Colour3bar ) { if( outa == PDT::Colour3bar && outb == PDT::Colour3bar ) { return GeneralHardME::Colour3bar3barto3bar3bar; } else if( outa == PDT::Colour6bar && outb == PDT::Colour0) { return GeneralHardME::Colour3bar3barto6bar1; } else if ( outa == PDT::Colour0 && outb == PDT::Colour6bar ) { return GeneralHardME::Colour3bar3barto16bar; } else if ( outa == PDT::Colour0 && outb == PDT::Colour3) { return GeneralHardME::Colour3bar3barto13; } else if ( outb == PDT::Colour0 && outa == PDT::Colour3) { return GeneralHardME::Colour3bar3barto31; } else if ( outa == PDT::Colour8 && outb == PDT::Colour3) { return GeneralHardME::Colour3bar3barto83; } else if ( outb == PDT::Colour8 && outa == PDT::Colour3) { return GeneralHardME::Colour3bar3barto38; } else assert(false); } // incoming 3 3bar else if(ina == PDT::Colour3 && inb == PDT::Colour3bar ) { if( outa == PDT::Colour0 && outb == PDT::Colour0 ) { return GeneralHardME::Colour33barto11; } else if( outa == PDT::Colour3 && outb == PDT::Colour3bar ) { return GeneralHardME::Colour33barto33bar; } else if( outa == PDT::Colour8 && outb == PDT::Colour8 ) { return GeneralHardME::Colour33barto88; } else if( outa == PDT::Colour8 && outb == PDT::Colour0 ) { return GeneralHardME::Colour33barto81; } else if( outa == PDT::Colour0 && outb == PDT::Colour8 ) { return GeneralHardME::Colour33barto18; } else if( outa == PDT::Colour6 && outb == PDT::Colour6bar) { return GeneralHardME::Colour33barto66bar; } else if( outa == PDT::Colour6bar && outb == PDT::Colour6) { return GeneralHardME::Colour33barto6bar6; } else assert(false); } // incoming 88 else if(ina == PDT::Colour8 && inb == PDT::Colour8 ) { if( outa == PDT::Colour0 && outb == PDT::Colour0 ) { return GeneralHardME::Colour88to11; } else if( outa == PDT::Colour3 && outb == PDT::Colour3bar ) { return GeneralHardME::Colour88to33bar; } else if( outa == PDT::Colour8 && outb == PDT::Colour8 ) { return GeneralHardME::Colour88to88; } else if( outa == PDT::Colour8 && outb == PDT::Colour0 ) { return GeneralHardME::Colour88to81; } else if( outa == PDT::Colour0 && outb == PDT::Colour8 ) { return GeneralHardME::Colour88to18; } else if( outa == PDT::Colour6 && outb == PDT::Colour6bar ) { return GeneralHardME::Colour88to66bar; } else assert(false); } // incoming 38 else if(ina == PDT::Colour3 && inb == PDT::Colour8 ) { if(outa == PDT::Colour3 && outb == PDT::Colour0) { return GeneralHardME::Colour38to31; } else if(outa == PDT::Colour0 && outb == PDT::Colour3) { return GeneralHardME::Colour38to13; } else if(outa == PDT::Colour3 && outb == PDT::Colour8) { return GeneralHardME::Colour38to38; } else if(outa == PDT::Colour8 && outb == PDT::Colour3) { return GeneralHardME::Colour38to83; } else if(outa == PDT::Colour3bar && outb == PDT::Colour6){ return GeneralHardME::Colour38to3bar6; } else if(outa == PDT::Colour6 && outb == PDT::Colour3bar) { return GeneralHardME::Colour38to63bar; } else if(outa == PDT::Colour3bar && outb == PDT::Colour3bar) { return GeneralHardME::Colour38to3bar3bar; } else assert(false); } // incoming 3bar8 else if(ina == PDT::Colour3bar && inb == PDT::Colour8 ) { if(outa == PDT::Colour3bar && outb == PDT::Colour0 ) { return GeneralHardME::Colour3bar8to3bar1; } else if(outa == PDT::Colour0 && outb == PDT::Colour3bar) { return GeneralHardME::Colour3bar8to13bar; } else if(outa == PDT::Colour3bar && outb == PDT::Colour8 ) { return GeneralHardME::Colour3bar8to3bar8; } else if(outa == PDT::Colour8 && outb == PDT::Colour3bar) { return GeneralHardME::Colour3bar8to83bar; } else if(outa == PDT::Colour3 && outb == PDT::Colour3) { return GeneralHardME::Colour3bar8to33; } else assert(false); } // unknown colour flow else assert(false); return GeneralHardME::UNDEFINED; } void HardProcessConstructor::fixFSOrder(HPDiagram & diag) { tcPDPtr psa = getParticleData(diag.incoming.first); tcPDPtr psb = getParticleData(diag.incoming.second); tcPDPtr psc = getParticleData(diag.outgoing.first); tcPDPtr psd = getParticleData(diag.outgoing.second); //fix a spin order if( psc->iSpin() < psd->iSpin() ) { swap(diag.outgoing.first, diag.outgoing.second); if(diag.channelType == HPDiagram::tChannel) { diag.ordered.second = !diag.ordered.second; } return; } if( psc->iSpin() == psd->iSpin() && psc->id() < 0 && psd->id() > 0 ) { swap(diag.outgoing.first, diag.outgoing.second); if(diag.channelType == HPDiagram::tChannel) { diag.ordered.second = !diag.ordered.second; } return; } } void HardProcessConstructor::assignToCF(HPDiagram & diag) { if(diag.channelType == HPDiagram::tChannel) { if(diag.ordered.second) tChannelCF(diag); else uChannelCF(diag); } else if(diag.channelType == HPDiagram::sChannel) { sChannelCF(diag); } else if (diag.channelType == HPDiagram::fourPoint) { fourPointCF(diag); } else assert(false); } void HardProcessConstructor::tChannelCF(HPDiagram & diag) { tcPDPtr ia = getParticleData(diag.incoming.first ); tcPDPtr ib = getParticleData(diag.incoming.second); tcPDPtr oa = getParticleData(diag.outgoing.first ); tcPDPtr ob = getParticleData(diag.outgoing.second); PDT::Colour ina = ia->iColour(); PDT::Colour inb = ib->iColour(); PDT::Colour outa = oa->iColour(); PDT::Colour outb = ob->iColour(); vector cfv(1, make_pair(0, 1.)); if(diag.intermediate->iColour() == PDT::Colour0) { if(ina==PDT::Colour0) { cfv[0] = make_pair(0, 1); } else if(ina==PDT::Colour3 || ina==PDT::Colour3bar) { if( inb == PDT::Colour0 ) { cfv[0] = make_pair(0, 1); } else if(inb==PDT::Colour3 || outb==PDT::Colour3bar) { cfv[0] = make_pair(2, 1); } else if(inb==PDT::Colour8) { cfv[0] = make_pair(2, 1); } } else if(ina==PDT::Colour8) { if( inb == PDT::Colour0 ) { cfv[0] = make_pair(0, 1); } else if(inb==PDT::Colour3 || outb==PDT::Colour3bar) { cfv[0] = make_pair(2, 1); } else if(inb==PDT::Colour8) { - cfv[0] = make_pair(7, 1); + cfv[0] = make_pair(7, -1); } } } else if(diag.intermediate->iColour() == PDT::Colour8) { if(ina==PDT::Colour8&&outa==PDT::Colour8&& inb==PDT::Colour8&&outb==PDT::Colour8) { cfv[0]=make_pair(2, 2.); cfv.push_back(make_pair(3, -2.)); cfv.push_back(make_pair(1, -2.)); cfv.push_back(make_pair(4, 2.)); } else if(ina==PDT::Colour8&&outa==PDT::Colour0&& inb==PDT::Colour8&&outb==PDT::Colour8&& - oa->iSpin()==PDT::Spin0) { + (oa->iSpin()==PDT::Spin0||oa->iSpin()==PDT::Spin1Half|| + oa->iSpin()==PDT::Spin3Half)) { cfv[0] = make_pair(0,-1); } else if(ina==PDT::Colour8&&outa==PDT::Colour8&& inb==PDT::Colour8&&outb==PDT::Colour0&& - ob->iSpin()==PDT::Spin0) { + (ob->iSpin()==PDT::Spin0||ob->iSpin()==PDT::Spin1Half|| + ob->iSpin()==PDT::Spin3Half)) { cfv[0] = make_pair(0,-1); } } else if(diag.intermediate->iColour() == PDT::Colour3 || diag.intermediate->iColour() == PDT::Colour3bar) { if(outa == PDT::Colour0 || outb == PDT::Colour0) { - if( outa != PDT::Colour6 && outb != PDT::Colour6 && - outa != PDT::Colour6bar && outb != PDT::Colour6bar) { + if( outa == PDT::Colour6 || outb == PDT::Colour6 || + outa == PDT::Colour6bar || outb == PDT::Colour6bar) { + cfv[0] = make_pair(0,0.5); + cfv.push_back(make_pair(1,0.5)); + } + else if ((ina==PDT::Colour3 && inb == PDT::Colour3 && + (outa == PDT::Colour3bar || outb == PDT::Colour3bar))|| + (ina==PDT::Colour3bar && inb == PDT::Colour3bar && + (outa == PDT::Colour3 || outb == PDT::Colour3 ))) { cfv[0] = make_pair(0,1.); } else { - cfv[0] = make_pair(0,0.5); - cfv.push_back(make_pair(1,0.5)); + cfv[0] = make_pair(0,1.); } } else if(outa==PDT::Colour6 && outb==PDT::Colour3bar) { cfv[0] = make_pair(4,1.); cfv.push_back(make_pair(5,1.)); } else if(outa==PDT::Colour6 && outb==PDT::Colour6bar) { cfv[0] = make_pair(4, 1.); for(unsigned int ix=5;ix<8;++ix) cfv.push_back(make_pair(ix,1.)); } else if(outa==PDT::Colour6 || outa ==PDT::Colour6bar || outb==PDT::Colour6 || outb ==PDT::Colour6bar ) { assert(false); } else if(ina==PDT::Colour3 && inb==PDT::Colour3 ) { if((outa==PDT::Colour0 && outb==PDT::Colour3bar)|| (outb==PDT::Colour0 && outa==PDT::Colour3bar)) cfv[0] = make_pair(0,1.); else if((outa==PDT::Colour8 && outb==PDT::Colour3bar)|| - (outb==PDT::Colour8 && outa==PDT::Colour3bar)) + (outb==PDT::Colour8 && outa==PDT::Colour3bar)) { cfv[0] = make_pair(1,1.); + } } else if(ina==PDT::Colour3bar && inb==PDT::Colour3bar ) { if((outa==PDT::Colour0 && outb==PDT::Colour3)|| (outb==PDT::Colour0 && outa==PDT::Colour3)) cfv[0] = make_pair(0,1.); else if((outa==PDT::Colour8 && outb==PDT::Colour3)|| - (outb==PDT::Colour8 && outa==PDT::Colour3)) - cfv[0] = make_pair(1,1.); + (outb==PDT::Colour8 && outa==PDT::Colour3)) { + double sign = diag.intermediate->iSpin()==PDT::Spin0 ? -1. : 1.; + cfv[0] = make_pair(1,sign); + } } else if((ina==PDT::Colour3 && inb==PDT::Colour8) || (ina==PDT::Colour3bar && inb==PDT::Colour8) || (inb==PDT::Colour3 && ina==PDT::Colour8) || (inb==PDT::Colour3bar && ina==PDT::Colour8) ) { if((outa==PDT::Colour3 && outb==PDT::Colour3 ) || (outa==PDT::Colour3bar && outb==PDT::Colour3bar)) { cfv[0] = make_pair(1,1.); } } } else if(diag.intermediate->iColour() == PDT::Colour6 || diag.intermediate->iColour() == PDT::Colour6bar) { if(ina==PDT::Colour8 && inb==PDT::Colour8) { cfv[0] = make_pair(0, 1.); for(unsigned int ix=1;ix<4;++ix) cfv.push_back(make_pair(ix,1.)); for(unsigned int ix=4;ix<8;++ix) cfv.push_back(make_pair(ix,1.)); } else if(outa==PDT::Colour3bar && outb==PDT::Colour6) { cfv[0] = make_pair(0,1.); for(unsigned int ix=1;ix<4;++ix) cfv.push_back(make_pair(ix,1.)); } else if(outa==PDT::Colour6 && outb==PDT::Colour3bar) { cfv[0] = make_pair(4,1.); cfv.push_back(make_pair(5,1.)); } } diag.colourFlow = cfv; } void HardProcessConstructor::uChannelCF(HPDiagram & diag) { + tcPDPtr ia = getParticleData(diag.incoming.first ); + tcPDPtr ib = getParticleData(diag.incoming.second); + tcPDPtr oa = getParticleData(diag.outgoing.first ); + tcPDPtr ob = getParticleData(diag.outgoing.second); + PDT::Colour ina = ia->iColour(); + PDT::Colour inb = ib->iColour(); + PDT::Colour outa = oa->iColour(); + PDT::Colour outb = ob->iColour(); PDT::Colour offshell = diag.intermediate->iColour(); - PDT::Colour ina = getParticleData(diag.incoming.first )->iColour(); - PDT::Colour inb = getParticleData(diag.incoming.second)->iColour(); - PDT::Colour outa = getParticleData(diag.outgoing.first )->iColour(); - PDT::Colour outb = getParticleData(diag.outgoing.second)->iColour(); vector cfv(1, make_pair(1, 1.)); if(offshell == PDT::Colour8) { if(outa == PDT::Colour0 && outb == PDT::Colour0) { cfv[0].first = 0; } else if( outa != outb ) { if(outa == PDT::Colour0 || outb == PDT::Colour0) { cfv[0].first = 0; } else if(ina == PDT::Colour3 && inb == PDT::Colour8 && outb == PDT::Colour3 && outa == PDT::Colour8) { tPDPtr off = diag.intermediate; if(off->CC()) off=off->CC(); if(off->iSpin()!=PDT::Spin1Half || diag.vertices.second->allowed(off->id(),diag.outgoing.first,diag.incoming.second)) { cfv[0].first = 0; cfv.push_back(make_pair(1, -1.)); } else { cfv[0].first = 1; cfv.push_back(make_pair(0, -1.)); } } else if(ina == PDT::Colour3bar && inb == PDT::Colour8 && outb == PDT::Colour3bar && outa == PDT::Colour8) { tPDPtr off = diag.intermediate; if(off->CC()) off=off->CC(); if(off->iSpin()!=PDT::Spin1Half || diag.vertices.second->allowed(diag.outgoing.first,off->id(),diag.incoming.second)) { cfv[0].first = 0; cfv.push_back(make_pair(1, -1.)); } else { cfv[0].first = 1; cfv.push_back(make_pair(0, -1.)); } } else { cfv[0].first = 0; cfv.push_back(make_pair(1, -1.)); } } else if(outa==PDT::Colour8&&ina==PDT::Colour8) { cfv[0]=make_pair(4, 2.); cfv.push_back(make_pair(5, -2.)); cfv.push_back(make_pair(0, -2.)); cfv.push_back(make_pair(2, 2.)); } } else if(offshell == PDT::Colour3 || offshell == PDT::Colour3bar) { if( outa == PDT::Colour0 || outb == PDT::Colour0 ) { - if( outa != PDT::Colour6 && outb != PDT::Colour6 && - outa != PDT::Colour6bar && outb != PDT::Colour6bar) { - cfv[0] = make_pair(0,1.); + if( outa == PDT::Colour6 || outb == PDT::Colour6 || + outa == PDT::Colour6bar || outb == PDT::Colour6bar) { + cfv[0] = make_pair(0,0.5); + cfv.push_back(make_pair(1,0.5)); + } + else if ((ina==PDT::Colour3 && inb == PDT::Colour3 && + (outa == PDT::Colour3bar || outb == PDT::Colour3bar))|| + (ina==PDT::Colour3bar && inb == PDT::Colour3bar && + (outa == PDT::Colour3 || outb == PDT::Colour3 ))) { + double sign = diag.intermediate->iSpin()==PDT::Spin0 ? -1. : 1.; + cfv[0] = make_pair(0,sign); } else { - cfv[0] = make_pair(0,0.5); - cfv.push_back(make_pair(1,0.5)); + cfv[0] = make_pair(0,1.); } } else if(outa==PDT::Colour3bar && outb==PDT::Colour6) { cfv[0] = make_pair(4,1.); cfv.push_back(make_pair(5,1.)); } else if(outa==PDT::Colour6 && outb==PDT::Colour3bar) { cfv[0] = make_pair(0,1.); for(int ix=0; ix<4;++ix) cfv.push_back(make_pair(ix,1.)); } else if(outa==PDT::Colour6bar && outb==PDT::Colour6) { cfv[0] = make_pair(4,1.); for(int ix=5; ix<8;++ix) cfv.push_back(make_pair(ix,1.)); } else if(ina==PDT::Colour0 && inb==PDT::Colour0) { cfv[0] = make_pair(0,1.); } else if(ina==PDT::Colour3 && inb==PDT::Colour3 ) { if((outa==PDT::Colour0 && outb==PDT::Colour3bar)|| (outb==PDT::Colour0 && outa==PDT::Colour3bar)) cfv[0] = make_pair(0,1.); else if((outa==PDT::Colour8 && outb==PDT::Colour3bar)|| - (outb==PDT::Colour8 && outa==PDT::Colour3bar)) - cfv[0] = make_pair(2,1.); + (outb==PDT::Colour8 && outa==PDT::Colour3bar)) { + double sign = diag.intermediate->iSpin()==PDT::Spin0 ? -1. : 1.; + cfv[0] = make_pair(2,sign); + } } else if(ina==PDT::Colour3bar && inb==PDT::Colour3bar ) { if((outa==PDT::Colour0 && outb==PDT::Colour3)|| (outb==PDT::Colour0 && outa==PDT::Colour3)) cfv[0] = make_pair(0,1.); else if((outa==PDT::Colour8 && outb==PDT::Colour3)|| - (outb==PDT::Colour8 && outa==PDT::Colour3)) + (outb==PDT::Colour8 && outa==PDT::Colour3)) { cfv[0] = make_pair(2,1.); + } } else if(((ina==PDT::Colour3 && inb==PDT::Colour8) || (ina==PDT::Colour3bar && inb==PDT::Colour8) || (inb==PDT::Colour3 && ina==PDT::Colour8) || (inb==PDT::Colour3bar && ina==PDT::Colour8)) && ((outa==PDT::Colour3 && outb==PDT::Colour3 ) || (outa==PDT::Colour3bar && outb==PDT::Colour3bar))) { cfv[0] = make_pair(2, 1.); } else if(( ina==PDT::Colour3 && inb==PDT::Colour3bar && outa==PDT::Colour3 && outb==PDT::Colour3bar)) { cfv[0] = make_pair(2, 1.); cfv.push_back(make_pair(3,-1.)); } } else if( offshell == PDT::Colour0 ) { if(ina==PDT::Colour0) { cfv[0] = make_pair(0, 1); } else if(ina==PDT::Colour3 || ina==PDT::Colour3bar) { if( inb == PDT::Colour0 ) { cfv[0] = make_pair(0, 1); } - else if(inb==PDT::Colour3 || outb==PDT::Colour3bar) { + else if(inb==PDT::Colour3 || inb==PDT::Colour3bar) { cfv[0] = make_pair(3, 1); } else if(inb==PDT::Colour8) { cfv[0] = make_pair(2, 1); } } else if(ina==PDT::Colour8) { if( inb == PDT::Colour0 ) { cfv[0] = make_pair(0, 1); } else if(inb==PDT::Colour3 || outb==PDT::Colour3bar) { cfv[0] = make_pair(2, 1); } else if(inb==PDT::Colour8) { - cfv[0] = make_pair(8, 1); + cfv[0] = make_pair(8, -1); } } } else if(diag.intermediate->iColour() == PDT::Colour6 || diag.intermediate->iColour() == PDT::Colour6bar) { if(ina==PDT::Colour8 && inb==PDT::Colour8) { cfv[0] = make_pair(0, 1.); for(unsigned int ix=1;ix<4;++ix) cfv.push_back(make_pair(ix,1.)); for(unsigned int ix=8;ix<12;++ix) cfv.push_back(make_pair(ix,1.)); } else if(outa==PDT::Colour3bar && outa==PDT::Colour6) { cfv[0] = make_pair(4, 1.); cfv.push_back(make_pair(5,1.)); } else if(outa==PDT::Colour6 && outa==PDT::Colour3bar) { cfv[0] = make_pair(0, 1.); for(unsigned int ix=1;ix<4;++ix) cfv.push_back(make_pair(ix,1.)); } } diag.colourFlow = cfv; } void HardProcessConstructor::sChannelCF(HPDiagram & diag) { tcPDPtr pa = getParticleData(diag.incoming.first); tcPDPtr pb = getParticleData(diag.incoming.second); PDT::Colour ina = pa->iColour(); PDT::Colour inb = pb->iColour(); PDT::Colour offshell = diag.intermediate->iColour(); tcPDPtr pc = getParticleData(diag.outgoing.first); tcPDPtr pd = getParticleData(diag.outgoing.second); PDT::Colour outa = pc->iColour(); PDT::Colour outb = pd->iColour(); vector cfv(1); if(offshell == PDT::Colour8) { if(ina == PDT::Colour0 || inb == PDT::Colour0 || outa == PDT::Colour0 || outb == PDT::Colour0) { cfv[0] = make_pair(0, 1); } else { bool incol = ina == PDT::Colour8 && inb == PDT::Colour8; bool outcol = outa == PDT::Colour8 && outb == PDT::Colour8; bool intrip = ina == PDT::Colour3 && inb == PDT::Colour3bar; bool outtrip = outa == PDT::Colour3 && outb == PDT::Colour3bar; bool outsex = outa == PDT::Colour6 && outb == PDT::Colour6bar; bool outsexb = outa == PDT::Colour6bar && outb == PDT::Colour6; if(incol || outcol) { // Require an additional minus sign for a scalar/fermion // 33bar final state due to the way the vertex rules are defined. int prefact(1); if( ((pc->iSpin() == PDT::Spin1Half && pd->iSpin() == PDT::Spin1Half) || (pc->iSpin() == PDT::Spin0 && pd->iSpin() == PDT::Spin0 )) && (outa == PDT::Colour3 && outb == PDT::Colour3bar) ) prefact = -1; if(incol && outcol) { cfv[0] = make_pair(0, -2.); cfv.push_back(make_pair(1, 2.)); cfv.push_back(make_pair(3, 2.)); cfv.push_back(make_pair(5, -2.)); } else if(incol && outsex) { cfv[0].first = 4; cfv[0].second = prefact; for(unsigned int ix=1;ix<4;++ix) cfv.push_back(make_pair(4+ix, prefact)); for(unsigned int ix=0;ix<4;++ix) cfv.push_back(make_pair(8+ix,-prefact)); } else { cfv[0].first = 0; cfv[0].second = -prefact; cfv.push_back(make_pair(1, prefact)); } } else if( ( intrip && !outtrip ) || ( !intrip && outtrip ) ) { if(!outsex) cfv[0] = make_pair(0, 1); else { cfv[0] = make_pair(0, 1.); for(unsigned int ix=0;ix<3;++ix) cfv.push_back(make_pair(ix+1, 1.)); } } else if((intrip && outsex) || (intrip && outsexb)) { cfv[0] = make_pair(0,1.); for(int ix=1; ix<4; ++ix) cfv.push_back(make_pair(ix,1.)); } else cfv[0] = make_pair(1, 1); } } else if(offshell == PDT::Colour0) { if( ina == PDT::Colour0 ) { cfv[0] = make_pair(0, 1); } else if(ina==PDT::Colour3 || ina==PDT::Colour3bar) { if( outa == PDT::Colour0 ) { cfv[0] = make_pair(0, 1); } else if(outa==PDT::Colour3 || outa==PDT::Colour3bar) { cfv[0] = make_pair(3, 1); } else if(outa==PDT::Colour8) { cfv[0] = make_pair(2, 1); } else if(outa==PDT::Colour6 || outa==PDT::Colour6bar) { cfv[0] = make_pair(8, 1.); cfv.push_back(make_pair(9,1.)); } else assert(false); } else if(ina==PDT::Colour8) { if( outa == PDT::Colour0 ) { cfv[0] = make_pair(0, 1); } else if(outa==PDT::Colour3 || outb==PDT::Colour3bar) { cfv[0] = make_pair(2, 1); } else if(outa==PDT::Colour8) { cfv[0] = make_pair(6, 1); } } } else if(offshell == PDT::Colour3 || offshell == PDT::Colour3bar) { if(outa == PDT::Colour6 || outa == PDT::Colour6bar || outb == PDT::Colour6bar || outb == PDT::Colour6) { cfv[0] = make_pair(6, 1.); cfv.push_back(make_pair(7,1.)); } else if((ina == PDT::Colour3 && inb == PDT::Colour3) || (ina == PDT::Colour3bar && inb == PDT::Colour3bar)) { if((outa == PDT::Colour3 && outb == PDT::Colour3 ) || (outa == PDT::Colour3bar && outb == PDT::Colour3bar)) { cfv[0] = make_pair(2, 1.); cfv.push_back(make_pair(3,-1.)); } else cfv[0] = make_pair(0,1.); } else if(((ina==PDT::Colour3 && inb==PDT::Colour8) || (ina==PDT::Colour3bar && inb==PDT::Colour8) || (inb==PDT::Colour3 && ina==PDT::Colour8) || (inb==PDT::Colour3bar && ina==PDT::Colour8) ) && ((outa==PDT::Colour3 && outb==PDT::Colour3 ) || (outa==PDT::Colour3bar && outb==PDT::Colour3bar))) { cfv[0] = make_pair(0,1.); } else { if(outa == PDT::Colour0 || outb == PDT::Colour0) cfv[0] = make_pair(0, 1); else cfv[0] = make_pair(1, 1); } } else if( offshell == PDT::Colour6 || offshell == PDT::Colour6bar) { if((ina == PDT::Colour3 && inb == PDT::Colour3 && outa == PDT::Colour3 && outb == PDT::Colour3 ) || (ina == PDT::Colour3bar && inb == PDT::Colour3bar && outa == PDT::Colour3bar && outb == PDT::Colour3bar)) { cfv[0] = make_pair(2,0.5); cfv.push_back(make_pair(3,0.5)); } else if((ina == PDT::Colour3 && inb == PDT::Colour3 && ((outa == PDT::Colour6 && outb == PDT::Colour0)|| (outb == PDT::Colour6 && outa == PDT::Colour0))) || (ina == PDT::Colour3bar && inb == PDT::Colour3bar && ((outa == PDT::Colour6bar && outb == PDT::Colour0)|| (outb == PDT::Colour6bar && outa == PDT::Colour0)))) { cfv[0] = make_pair(0,0.5); cfv.push_back(make_pair(1,0.5)); } else assert(false); } else { if(outa == PDT::Colour0 || outb == PDT::Colour0) cfv[0] = make_pair(0, 1); else cfv[0] = make_pair(1, 1); } diag.colourFlow = cfv; } void HardProcessConstructor::fourPointCF(HPDiagram & diag) { + using namespace ThePEG::Helicity; // count the colours - unsigned int noct(0),ntri(0),nsng(0),nsex(0); + unsigned int noct(0),ntri(0),nsng(0),nsex(0),nf(0); + vector particles; for(unsigned int ix=0;ix<4;++ix) { - PDT::Colour col = getParticleData(diag.ids[ix])->iColour(); + particles.push_back(getParticleData(diag.ids[ix])); + PDT::Colour col = particles.back()->iColour(); if(col==PDT::Colour0) ++nsng; else if(col==PDT::Colour3||col==PDT::Colour3bar) ++ntri; else if(col==PDT::Colour8) ++noct; else if(col==PDT::Colour6||col==PDT::Colour6bar) ++nsex; + if(particles.back()->iSpin()==2) nf+=1; } if(nsng==4 || (ntri==2&&nsng==2) || (noct==3 && nsng==1) || - (ntri==2 && noct==1 && nsng==1) ) { + (ntri==2 && noct==1 && nsng==1) || + (noct == 2 && nsng == 2) ) { vector cfv(1,make_pair(0,1)); diag.colourFlow = cfv; } else if(noct==4) { // flows for SSVV, VVVV is handled in me class vector cfv(6); cfv[0] = make_pair(0, -2.); cfv[1] = make_pair(1, -2.); cfv[2] = make_pair(2, +4.); cfv[3] = make_pair(3, -2.); cfv[4] = make_pair(4, +4.); cfv[5] = make_pair(5, -2.); diag.colourFlow = cfv; } else if(ntri==2&&noct==2) { vector cfv(2); cfv[0] = make_pair(0, 1); cfv[1] = make_pair(1, 1); + if(nf==2) cfv[1].second = -1.; diag.colourFlow = cfv; } else if(nsex==2&&noct==2) { vector cfv; for(unsigned int ix=0;ix<4;++ix) cfv.push_back(make_pair(ix ,2.)); for(unsigned int ix=0;ix<8;++ix) cfv.push_back(make_pair(4+ix,1.)); diag.colourFlow = cfv; } - else + else if(ntri==4) { + // get the order from the vertex + vector temp; + for(unsigned int ix=0;ix<4;++ix) { + temp = diag.vertices.first->search(ix,diag.outgoing.first); + if(!temp.empty()) break; + } + // compute the mapping + vector ids; + ids.push_back( particles[0]->CC() ? -diag.incoming.first : diag.incoming.first ); + ids.push_back( particles[1]->CC() ? -diag.incoming.second : diag.incoming.second); + ids.push_back( diag.outgoing.first ); + ids.push_back( diag.outgoing.second); + vector order = {0,1,2,3}; + vector matched(4,false); + for(unsigned int ix=0;ix 3 3 + if((particles[0]->iColour()==PDT::Colour3 && + particles[1]->iColour()==PDT::Colour3) || + (particles[0]->iColour()==PDT::Colour3bar && + particles[1]->iColour()==PDT::Colour3bar) ) { + if(diag.vertices.first->colourStructure()==ColourStructure::SU3I12I34) { + if( (order[0]==0 && order[1]==2) || (order[2]==0 && order[3]==2) || + (order[0]==2 && order[1]==0) || (order[2]==2 && order[3]==0)) + diag.colourFlow = vector(1,make_pair(2,1.)); + else + diag.colourFlow = vector(1,make_pair(3,1.)); + } + else if(diag.vertices.first->colourStructure()==ColourStructure::SU3I14I23) { + if( (order[0]==0 && order[3]==2) || (order[1]==0 && order[2]==2) || + (order[0]==2 && order[3]==0) || (order[1]==2 && order[2]==0)) + diag.colourFlow = vector(1,make_pair(2,1.)); + else + diag.colourFlow = vector(1,make_pair(3,1.)); + } + else if(diag.vertices.first->colourStructure()==ColourStructure::SU3T21T43) { + if( (order[1]==0 && order[0]==2) || (order[3]==0 && order[2]==2) || + (order[1]==2 && order[0]==0) || (order[3]==2 && order[2]==0)) + diag.colourFlow = vector(1,make_pair(0,1.)); + else + diag.colourFlow = vector(1,make_pair(1,1.)); + } + else if(diag.vertices.first->colourStructure()==ColourStructure::SU3T23T41) { + if( (order[1]==0 && order[2]==2) || (order[3]==0 && order[0]==2) || + (order[1]==2 && order[2]==0) || (order[3]==2 && order[0]==0)) + diag.colourFlow = vector(1,make_pair(0,1.)); + else + diag.colourFlow = vector(1,make_pair(1,1.)); + } + else + assert(false); + } + else if((particles[0]->iColour()==PDT::Colour3 && + particles[1]->iColour()==PDT::Colour3bar) | + (particles[0]->iColour()==PDT::Colour3bar && + particles[1]->iColour()==PDT::Colour3)) { + if(diag.vertices.first->colourStructure()==ColourStructure::SU3I12I34) { + if( (order[0]==0 && order[1]==1) || (order[2]==0 && order[3]==0) || + (order[0]==1 && order[1]==0) || (order[2]==1 && order[3]==1)) + diag.colourFlow = vector(1,make_pair(3,1.)); + else + diag.colourFlow = vector(1,make_pair(2,1.)); + } + else if(diag.vertices.first->colourStructure()==ColourStructure::SU3I14I23) { + if( (order[0]==0 && order[3]==1) || (order[0]==2 && order[3]==3) || + (order[0]==1 && order[3]==0) || (order[0]==3 && order[3]==2)) + diag.colourFlow = vector(1,make_pair(3,1.)); + else + diag.colourFlow = vector(1,make_pair(2,1.)); + } + else if(diag.vertices.first->colourStructure()==ColourStructure::SU3T21T43) { + if( (order[1]==0 && order[0]==1) || (order[3]==0 && order[2]==1) || + (order[1]==1 && order[0]==0) || (order[3]==1 && order[2]==0)) + diag.colourFlow = vector(1,make_pair(1,1.)); + else + diag.colourFlow = vector(1,make_pair(0,1.)); + } + else if(diag.vertices.first->colourStructure()==ColourStructure::SU3T23T41) { + if( (order[1]==0 && order[2]==1) || (order[1]==1 && order[2]==0) || + (order[1]==3 && order[2]==2) || (order[1]==2 && order[2]==3)) + diag.colourFlow = vector(1,make_pair(1,1.)); + else + diag.colourFlow = vector(1,make_pair(2,1.)); + } + else + assert(false); + } + else { + assert(false); + } + } + else { assert(false); + } } namespace { // Helper functor for find_if in duplicate function. class SameDiagramAs { public: SameDiagramAs(const HPDiagram & diag) : a(diag) {} bool operator()(const HPDiagram & b) const { return a == b; } private: HPDiagram a; }; } bool HardProcessConstructor::duplicate(const HPDiagram & diag, const HPDVector & group) const { //find if a duplicate diagram exists HPDVector::const_iterator it = find_if(group.begin(), group.end(), SameDiagramAs(diag)); return it != group.end(); } + +bool HardProcessConstructor::checkOrder(const HPDiagram & diag) const { + for(map >::const_iterator it=model_->couplings().begin(); + it!=model_->couplings().end();++it) { + int order=0; + if(diag.vertices.first ) order += diag.vertices.first ->orderInCoupling(it->second.first); + if(diag.vertices.second&&diag.vertices.first->getNpoint()==3) + order += diag.vertices.second->orderInCoupling(it->second.first); + if(order>it->second.second) return false; + } + return true; +} diff --git a/Models/General/HardProcessConstructor.h b/Models/General/HardProcessConstructor.h --- a/Models/General/HardProcessConstructor.h +++ b/Models/General/HardProcessConstructor.h @@ -1,211 +1,216 @@ // -*- C++ -*- #ifndef HERWIG_HardProcessConstructor_H #define HERWIG_HardProcessConstructor_H // // This is the declaration of the HardProcessConstructor class. // #include "ThePEG/Interface/Interfaced.h" #include "HPDiagram.h" #include "Herwig/Models/StandardModel/StandardModel.h" #include "ThePEG/Handlers/SubProcessHandler.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Handlers/StandardEventHandler.h" #include "Herwig/MatrixElement/General/GeneralHardME.h" #include "HardProcessConstructor.fh" namespace Herwig { using namespace ThePEG; /** * Here is the documentation of the HardProcessConstructor class. * * @see \ref HardProcessConstructorInterfaces "The interfaces" * defined for HardProcessConstructor. */ class HardProcessConstructor: public Interfaced { public: /** Vector of HPDiagrams. */ typedef vector HPDVector; public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ HardProcessConstructor() : debug_(false) {} //@} /** * The main function to create diagrams etc for the processes */ virtual void constructDiagrams() = 0; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** Functions to set up colour flows and matrix elements. */ //@{ /** * Determine whether the ordering of the outgoing states is the same * as the ordering in the matrix elements * @param diag The diagram to question */ void fixFSOrder(HPDiagram & diag); /** * Assign a diagram to the appropriate colour flow(s). * @param diag The diagram to assign */ void assignToCF(HPDiagram & diag); /** * Assign a $s$-channel diagram to the appropriate colour flow(s). * @param diag The diagram to assign */ void sChannelCF(HPDiagram & diag); /** * Assign a $t$-channel diagram to the appropriate colour flow(s). * @param diag The diagram to assign */ void tChannelCF(HPDiagram & diag); /** * Assign a $u$-channel diagram to the appropriate colour flow(s). * @param diag The diagram to assign */ void uChannelCF(HPDiagram & diag); /** * Assign a $u$-channel diagram to the appropriate colour flow(s). * @param diag The diagram to assign */ void fourPointCF(HPDiagram & diag); //@} /** * Pointer to the model being used */ tHwSMPtr model() const {return model_;} /** * Pointer to the sub process handler */ tSubHdlPtr subProcess() const {return subProcess_;} /** * Whether to print the debug information with the matrix * element. This is here solely so it can be passed to * a matrix element that is created here. */ bool debug() const {return debug_;} /** * Get the correct colour factor matrix. * @param extpart Vector of external ParticleData pointers */ GeneralHardME::ColourStructure colourFlow(const tcPDVector & extpart) const; /** * Search for a diagram that has already been created * @param diagram The diagram to search for * @param group The group of diagrams to search through */ bool duplicate(const HPDiagram & diagram, const HPDVector & group) const; + /** + * check the order of a diagram + */ + bool checkOrder(const HPDiagram & diag) 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. */ HardProcessConstructor & operator=(const HardProcessConstructor &); private: /** * Pointer to the model being used */ tHwSMPtr model_; /** * Pointer to the sub process handler */ tSubHdlPtr subProcess_; /** * Whether to print the debug information with the matrix * element. This is here solely so it can be passed to * a matrix element that is created here. */ bool debug_; }; namespace HPC_helper { // Helper functor for find_if in duplicate function. class SameIncomingAs { public: SameIncomingAs(tPDPair in) : a(in.first->id()), b(in.second->id()) {} bool operator()(tPDPair ppair) const { long id1(ppair.first->id()), id2(ppair.second->id()); return ( id1 == a && id2 == b ) || ( id1 == b && id2 == a ); } private: long a, b; }; inline bool duplicateIncoming(tPDPair ppair,const vector &incPairs) { vector::const_iterator it = find_if( incPairs.begin(), incPairs.end(), SameIncomingAs(ppair) ); return it != incPairs.end(); } } } #endif /* HERWIG_HardProcessConstructor_H */ diff --git a/Models/General/ModelGenerator.cc b/Models/General/ModelGenerator.cc --- a/Models/General/ModelGenerator.cc +++ b/Models/General/ModelGenerator.cc @@ -1,556 +1,555 @@ // -*- C++ -*- // // ModelGenerator.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 ModelGenerator class. // #include "ModelGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/Repository/CurrentGenerator.h" #include "BSMWidthGenerator.h" #include "Herwig/PDT/GenericMassGenerator.h" #include "Herwig/Decay/DecayIntegrator.h" #include "ThePEG/Repository/BaseRepository.h" using namespace Herwig; IBPtr ModelGenerator::clone() const { return new_ptr(*this); } IBPtr ModelGenerator::fullclone() const { return new_ptr(*this); } void ModelGenerator::persistentOutput(PersistentOStream & os) const { os << hardProcessConstructors_ << _theDecayConstructor << particles_ << offshell_ << Offsel_ << BRnorm_ << twoBodyOnly_ << howOffShell_ << Npoints_ << Iorder_ << BWshape_ << brMin_ << decayOutput_; } void ModelGenerator::persistentInput(PersistentIStream & is, int) { is >> hardProcessConstructors_ >> _theDecayConstructor >> particles_ >> offshell_ >> Offsel_ >> BRnorm_ >> twoBodyOnly_ >> howOffShell_ >> Npoints_ >> Iorder_ >> BWshape_ >> brMin_ >> decayOutput_; } // Static variable needed for the type description system in ThePEG. DescribeClass describeThePEGModelGenerator("Herwig::ModelGenerator", "Herwig.so"); void ModelGenerator::Init() { static ClassDocumentation documentation ("This class controls the the use of BSM physics.", "BSM physics was produced using the algorithm of " "\\cite{Gigg:2007cr,Gigg:2008yc}", "\\bibitem{Gigg:2007cr} M.~Gigg and P.~Richardson, \n" "Eur.\\ Phys.\\ J.\\ C {\\bf 51} (2007) 989.\n" "%%CITATION = EPHJA,C51,989;%%\n" " %\\cite{Gigg:2008yc}\n" "\\bibitem{Gigg:2008yc}\n" " M.~A.~Gigg and P.~Richardson,\n" " %``Simulation of Finite Width Effects in Physics Beyond the Standard Model,''\n" " arXiv:0805.3037 [hep-ph].\n" " %%CITATION = ARXIV:0805.3037;%%\n" ); static RefVector interfaceHardProcessConstructors ("HardProcessConstructors", "The objects to construct hard processes", &ModelGenerator::hardProcessConstructors_, -1, false, false, true, false, false); static Reference interfaceDecayConstructor ("DecayConstructor", "Pointer to DecayConstructor helper class", &ModelGenerator::_theDecayConstructor, false, false, true, false); static RefVector interfaceModelParticles ("DecayParticles", "ParticleData pointers to the particles requiring spin correlation " "decayers. If decay modes do not exist they will also be created.", &ModelGenerator::particles_, -1, false, false, true, false); static RefVector interfaceOffshell ("Offshell", "The particles to treat as off-shell", &ModelGenerator::offshell_, -1, false, false, true, false); static Switch interfaceWhichOffshell ("WhichOffshell", "A switch to determine which particles to create mass and width " "generators for.", &ModelGenerator::Offsel_, 0, false, false); static SwitchOption interfaceWhichOffshellSelected (interfaceWhichOffshell, "Selected", "Only create mass and width generators for the particles specified", 0); static SwitchOption interfaceWhichOffshellAll (interfaceWhichOffshell, "All", "Treat all particles specified in the DecayParticles " "list as off-shell", 1); static Switch interfaceBRNormalize ("BRNormalize", "Whether to normalize the partial widths to BR*total width for an " "on-shell particle", &ModelGenerator::BRnorm_, true, false, false); static SwitchOption interfaceBRNormalizeNormalize (interfaceBRNormalize, "Yes", "Normalize the partial widths", true); static SwitchOption interfaceBRNormalizeNoNormalize (interfaceBRNormalize, "No", "Do not normalize the partial widths", false); static Parameter interfacePoints ("InterpolationPoints", "Number of points to use for interpolation tables when needed", &ModelGenerator::Npoints_, 10, 5, 1000, false, false, true); static Parameter interfaceInterpolationOrder ("InterpolationOrder", "The interpolation order for the tables", &ModelGenerator::Iorder_, 1, 1, 5, false, false, Interface::limited); static Switch interfaceBreitWignerShape ("BreitWignerShape", "Controls the shape of the mass distribution generated", &ModelGenerator::BWshape_, 0, false, false); static SwitchOption interfaceBreitWignerShapeDefault (interfaceBreitWignerShape, "Default", "Running width with q in numerator and denominator width factor", 0); static SwitchOption interfaceBreitWignerShapeFixedWidth (interfaceBreitWignerShape, "FixedWidth", "Use a fixed width", 1); static SwitchOption interfaceBreitWignerShapeNoq (interfaceBreitWignerShape, "Noq", "Use M rather than q in the numerator and denominator width factor", 2); static SwitchOption interfaceBreitWignerShapeNoNumerator (interfaceBreitWignerShape, "NoNumerator", "Neglect the numerator factors", 3); static Switch interfaceTwoBodyOnly ("TwoBodyOnly", "Whether to use only two-body or all modes in the running width calculation", &ModelGenerator::twoBodyOnly_, false, false, false); static SwitchOption interfaceTwoBodyOnlyYes (interfaceTwoBodyOnly, "Yes", "Only use two-body modes", true); static SwitchOption interfaceTwoBodyOnlyNo (interfaceTwoBodyOnly, "No", "Use all modes", false); static Parameter interfaceMinimumBR ("MinimumBR", "The minimum branching fraction to include", &ModelGenerator::brMin_, 1e-6, 0.0, 1.0, false, false, Interface::limited); static Switch interfaceDecayOutput ("DecayOutput", "Option to control the output of the decay mode information", &ModelGenerator::decayOutput_, 1, false, false); static SwitchOption interfaceDecayOutputNone (interfaceDecayOutput, "None", "No output", 0); static SwitchOption interfaceDecayOutputPlain (interfaceDecayOutput, "Plain", "Default plain text output", 1); static SwitchOption interfaceDecayOutputSLHA (interfaceDecayOutput, "SLHA", "Output in the Susy Les Houches Accord format", 2); static Parameter interfaceMinimumWidthFraction ("MinimumWidthFraction", "Minimum fraction of the particle's mass the width can be" " for the off-shell treatment.", &ModelGenerator::minWidth_, 1e-6, 1e-15, 1., false, false, Interface::limited); static Parameter interfaceHowMuchOffShell ("HowMuchOffShell", "The multiple of the particle's width by which it is allowed to be off-shell", &ModelGenerator::howOffShell_, 5., 0.0, 100., false, false, Interface::limited); } namespace { /// Helper function for sorting by mass inline bool massIsLess(tcPDPtr a, tcPDPtr b) { return a->mass() < b->mass(); } // Helper function to find minimum possible mass of a particle inline Energy minimumMass(tcPDPtr parent) { Energy output(Constants::MaxEnergy); for(set::const_iterator dit = parent->decayModes().begin(); dit != parent->decayModes().end(); ++dit) { Energy outMass(ZERO); for(unsigned int ix=0;ix<(**dit).orderedProducts().size();++ix) { outMass += (**dit).orderedProducts()[ix]->massMin(); } output = min(output,outMass); } return output; } } void ModelGenerator::doinit() { useMe(); Interfaced::doinit(); // make sure the model is initialized Ptr::pointer model = dynamic_ptr_cast::pointer>(generator()->standardModel()); model->init(); // and the vertices for(size_t iv = 0; iv < model->numberOfVertices(); ++iv) model->vertex(iv)->init(); // uniq and sort DecayParticles list by mass set tmp(particles_.begin(),particles_.end()); particles_.assign(tmp.begin(),tmp.end()); sort(particles_.begin(),particles_.end(),massIsLess); //create decayers and decaymodes (if necessary) if( _theDecayConstructor ) { _theDecayConstructor->init(); _theDecayConstructor->createDecayers(particles_,brMin_); } // write out decays with spin correlations ostream & os = CurrentGenerator::current().misc(); ofstream ofs; if ( decayOutput_ > 1 ) { string filename = CurrentGenerator::current().filename() + "-BR.spc"; ofs.open(filename.c_str()); } - if(decayOutput_!=0) { if(decayOutput_==1) { os << "# The decay modes listed below will have spin\n" << "# correlations included when they are generated.\n#\n#"; } else { ofs << "# Herwig decay tables in SUSY Les Houches accord format\n"; ofs << "Block DCINFO # Program information\n"; ofs << "1 Herwig # Decay Calculator\n"; ofs << "2 " << generator()->strategy()->versionstring() << " # Version number\n"; } } //create mass and width generators for the requested particles set offShell; if( Offsel_ == 0 ) offShell = set(offshell_.begin() ,offshell_.end() ); else offShell = set(particles_.begin(),particles_.end()); for(PDVector::iterator pit = particles_.begin(); pit != particles_.end(); ++pit) { tPDPtr parent = *pit; // Check decays for ones where quarks cannot be put on constituent // mass-shell checkDecays(parent); parent->reset(); // Now switch off the modes if needed for(DecaySet::const_iterator it=parent->decayModes().begin(); it!=parent->decayModes().end();++it) { if( _theDecayConstructor->disableDecayMode((**it).tag()) ) { DMPtr mode = *it; generator()->preinitInterface(mode, "Active", "set", "No"); if(mode->CC()) { DMPtr CCmode = mode->CC(); generator()->preinitInterface(CCmode, "Active", "set", "No"); } } } parent->update(); if( parent->CC() ) parent->CC()->synchronize(); if( parent->decaySelector().empty() ) { parent->stable(true); parent->width(ZERO); parent->widthCut(ZERO); parent->massGenerator(tGenericMassGeneratorPtr()); parent->widthGenerator(tGenericWidthGeneratorPtr()); } else { if(parent->mass()*minWidth_>parent->width()) { parent->massGenerator(tGenericMassGeneratorPtr()); parent->widthGenerator(tGenericWidthGeneratorPtr()); } else { if( offShell.find(*pit) != offShell.end() ) { createWidthGenerator(*pit); } else { parent->massGenerator(tGenericMassGeneratorPtr()); parent->widthGenerator(tGenericWidthGeneratorPtr()); } } } if( parent->massGenerator() ) { Energy minMass = minimumMass(parent); Energy offShellNess = howOffShell_*parent->width(); if(minMass>parent->mass()-offShellNess) { offShellNess = parent->mass()-minMass; } parent->widthCut(offShellNess); parent->massGenerator()->reset(); if(decayOutput_==1) os << "# " <PDGName() << " will be considered off-shell.\n#\n"; } if( parent->widthGenerator() ) parent->widthGenerator()->reset(); } // loop again to initialise mass and width generators // switch off modes and write output for(PDVector::iterator pit = particles_.begin(); pit != particles_.end(); ++pit) { tPDPtr parent = *pit; if(parent->widthGenerator()) parent->widthGenerator()->init(); if(parent->massGenerator()) parent->massGenerator()->init(); // output the modes if needed if( !parent->decaySelector().empty() ) { if ( decayOutput_ == 2 ) writeDecayModes(ofs, parent); else writeDecayModes(os, parent); } } //Now construct hard processes given that we know which //objects have running widths for(unsigned int ix=0;ixinit(); hardProcessConstructors_[ix]->constructDiagrams(); } } void ModelGenerator::checkDecays(PDPtr parent) { if( parent->stable() ) { if(parent->coloured()) cerr << "Warning: No decays for coloured particle " << parent->PDGName() << "\n\n" << "have been calcluated in BSM model.\n" << "This may cause problems in the hadronization phase.\n" << "You may have forgotten to switch on the decay mode calculation using\n" << " set TwoBodyDC:CreateDecayModes Yes\n" << " set ThreeBodyDC:CreateDecayModes Yes\n" << " set WeakDecayConstructor:CreateDecayModes Yes\n" << "or the decays of this particle are missing from your\n" << "input spectrum and decay file in the SLHA format.\n\n"; return; } DecaySet::iterator dit = parent->decayModes().begin(); DecaySet::iterator dend = parent->decayModes().end(); Energy oldwidth(parent->width()), newwidth(ZERO); bool rescalebrat(false); double brsum(0.); for(; dit != dend; ++dit ) { if( !(**dit).on() ) continue; Energy release((**dit).parent()->mass()); tPDVector::const_iterator pit = (**dit).orderedProducts().begin(); tPDVector::const_iterator pend =(**dit).orderedProducts().end(); for( ; pit != pend; ++pit ) { release -= (**pit).constituentMass(); } if( (**dit).brat() < brMin_ || release < ZERO ) { if( release < ZERO ) cerr << "Warning: The shower cannot be generated using this decay " << (**dit).tag() << " because it is too close to threshold.\nIt " << "will be switched off and the branching fractions of the " << "remaining modes rescaled.\n"; rescalebrat = true; generator()->preinitInterface(*dit, "Active", "set", "No"); generator()->preinitInterface(*dit, "BranchingRatio", "set", "0.0"); DecayIntegratorPtr decayer = dynamic_ptr_cast((**dit).decayer()); if(decayer) { generator()->preinitInterface(decayer->fullName(), "Initialize", "set","0"); } } else { brsum += (**dit).brat(); newwidth += (**dit).brat()*oldwidth; } } // if no modes left set stable if(newwidth==ZERO) { parent->stable(true); parent->width(ZERO); parent->widthCut(ZERO); parent->massGenerator(tGenericMassGeneratorPtr()); parent->widthGenerator(tGenericWidthGeneratorPtr()); } // otherwise rescale if needed else if( ( rescalebrat || abs(brsum - 1.) > 1e-12 ) && !parent->decayModes().empty()) { dit = parent->decayModes().begin(); dend = parent->decayModes().end(); double factor = oldwidth/newwidth; brsum = 0.; for( ; dit != dend; ++dit ) { if( !(**dit).on() ) continue; double newbrat = ((**dit).brat())*factor; brsum += newbrat; ostringstream brf; brf << setprecision(13) << newbrat; generator()->preinitInterface(*dit, "BranchingRatio", "set", brf.str()); } parent->width(newwidth); if( newwidth > ZERO ) parent->cTau(hbarc/newwidth); } } namespace { struct DecayModeOrdering { bool operator()(tcDMPtr m1, tcDMPtr m2) { if(m1->brat()!=m2->brat()) { return m1->brat()>m2->brat(); } else { if(m1->products().size()==m2->products().size()) { ParticleMSet::const_iterator it1=m1->products().begin(); ParticleMSet::const_iterator it2=m2->products().begin(); do { if((**it1).id()!=(**it2).id()) { return (**it1).id()>(**it2).id(); } ++it1; ++it2; } while(it1!=m1->products().end()&& it2!=m2->products().end()); assert(false); } else return m1->products().size()products().size(); } return false; } }; } void ModelGenerator::writeDecayModes(ostream & os, tcPDPtr parent) const { if(decayOutput_==0) return; set modes(parent->decayModes().begin(), parent->decayModes().end()); if(decayOutput_==1) { os << " Parent: " << parent->PDGName() << " Mass (GeV): " << parent->mass()/GeV << " Total Width (GeV): " << parent->width()/GeV << endl; os << std::left << std::setw(40) << '#' << std::left << std::setw(20) << "Partial Width/GeV" << std::left << std::setw(20) << "BR" << "Yes/No\n"; for(set::iterator dit=modes.begin(); dit!=modes.end();++dit) os << std::left << std::setw(40) << (**dit).tag() << std::left << std::setw(20) << (**dit).brat()*parent->width()/GeV << std::left << std::setw(20) << (**dit).brat() << ((**dit).on() ? "Yes" : "No" ) << '\n'; os << "#\n#"; } else if(decayOutput_==2) { os << "# \t PDG \t Width\n"; os << "DECAY\t" << parent->id() << "\t" << parent->width()/GeV << "\t # " << parent->PDGName() << "\n"; for(set::iterator dit=modes.begin(); dit!=modes.end();++dit) { os << "\t" << std::left << std::setw(10) << (**dit).brat() << "\t" << (**dit).orderedProducts().size() << "\t"; for(unsigned int ix=0;ix<(**dit).orderedProducts().size();++ix) os << std::right << std::setw(10) << (**dit).orderedProducts()[ix]->id() ; for(unsigned int ix=(**dit).orderedProducts().size();ix<4;++ix) os << "\t"; os << "# " << (**dit).tag() << "\n"; } } } void ModelGenerator::createWidthGenerator(tPDPtr p) { string wn = p->fullName() + string("-WGen"); string mn = p->fullName() + string("-MGen"); GenericMassGeneratorPtr mgen = dynamic_ptr_cast (generator()->preinitCreate("Herwig::GenericMassGenerator", mn)); BSMWidthGeneratorPtr wgen = dynamic_ptr_cast (generator()->preinitCreate("Herwig::BSMWidthGenerator", wn)); //set the particle interface mgen->particle(p); wgen->particle(p); //set the generator interfaces in the ParticleData object generator()->preinitInterface(p, "Mass_generator","set", mn); generator()->preinitInterface(p, "Width_generator","set", wn); //allow the branching fraction of this particle type to vary p->variableRatio(true); if( p->CC() ) p->CC()->variableRatio(true); //initialize the generators generator()->preinitInterface(mgen, "Initialize", "set", "Yes"); generator()->preinitInterface(wgen, "Initialize", "set", "Yes"); string norm = BRnorm_ ? "Yes" : "No"; generator()->preinitInterface(wgen, "BRNormalize", "set", norm); string twob = twoBodyOnly_ ? "Yes" : "No"; generator()->preinitInterface(wgen, "TwoBodyOnly", "set", twob); ostringstream os; os << Npoints_; generator()->preinitInterface(wgen, "Points", "set", os.str()); os.str(""); os << Iorder_; generator()->preinitInterface(wgen, "InterpolationOrder", "set", os.str()); os.str(""); os << BWshape_; generator()->preinitInterface(mgen, "BreitWignerShape", "set", os.str()); } diff --git a/Models/General/NBodyDecayConstructorBase.h b/Models/General/NBodyDecayConstructorBase.h --- a/Models/General/NBodyDecayConstructorBase.h +++ b/Models/General/NBodyDecayConstructorBase.h @@ -1,340 +1,340 @@ // -*- C++ -*- // // NBodyDecayConstructorBase.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_NBodyDecayConstructorBase_H #define HERWIG_NBodyDecayConstructorBase_H // // This is the declaration of the NBodyDecayConstructorBase class. // #include "ThePEG/Interface/Interfaced.h" #include "ThePEG/Utilities/Exception.h" #include "ThePEG/PDT/ParticleData.h" #include "NBodyDecayConstructorBase.fh" #include "PrototypeVertex.h" #include "DecayConstructor.fh" namespace Herwig { using namespace ThePEG; /** * This is the base class for NBodyDecayConstructors. An N-body * decay constructor should inherit from this and implement the * DecayList virtual funtcion to create the decays and decayers. * * @see \ref NBodyDecayConstructorBaseInterfaces "The interfaces" * defined for NBodyDecayConstructor. */ class NBodyDecayConstructorBase: public Interfaced { public: /** * The default constructor. */ NBodyDecayConstructorBase() : init_(true),iteration_(1), points_(1000), info_(false), createModes_(true), removeOnShell_(1), excludeEffective_(true), minReleaseFraction_(1e-3), maxBoson_(1), maxList_(1), includeTopOnShell_(false ), removeFlavourChangingVertices_(false), removeSmallVertices_(false), minVertexNorm_(1e-8) {} /** * Function used to determine allowed decaymodes, to be implemented * in derived class. * @param particles vector of ParticleData pointers containing * particles in model */ virtual void DecayList(const set & particles); /** * Number of outgoing lines. Required for correct ordering. */ virtual unsigned int numBodies() const = 0; /** * Set the pointer to the DecayConstrcutor */ void decayConstructor(tDecayConstructorPtr d) { decayConstructor_ = d; } /** * Remove flavour changing vertices ? */ bool removeFlavourChangingVertices() const { return removeFlavourChangingVertices_; } /** * Remove small vertices ? */ bool removeSmallVertices() const { return removeSmallVertices_; } /** * Minimum norm for vertex removal */ double minVertexNorm() const { return minVertexNorm_; } protected: /** * Method to set up the decay mode, should be overidden in inheriting class */ virtual void createDecayMode(vector & mode, bool possibleOnShell, double symfac); /** * Set the branching ratio of this mode. This requires * calculating a new width for the decaying particle and reweighting * the current branching fractions. * @param dm The decaymode for which to set the branching ratio * @param pwidth The calculated width of the mode */ void setBranchingRatio(tDMPtr dm, Energy pwidth); /** * Set the interfaces of the decayers depending on the flags stored. * @param name Fullname of the decayer in the EventGenerator * including the path */ void setDecayerInterfaces(string name) const; /** * Whether to initialize decayers or not */ bool initialize() const { return init_; } /** * Number of iterations if initializing (default 1) */ int iteration() const { return iteration_; } /** * Number of points to do in initialization */ int points() const { return points_; } /** * Whether to output information on the decayers */ bool info() const { return info_; } /** * Whether to create the DecayModes as well as the Decayer objects */ bool createDecayModes() const { return createModes_; } /** * Maximum number of electroweak gauge bosons */ unsigned int maximumGaugeBosons() const { return maxBoson_;} /** * Maximum number of particles from the list whose decays we are calculating */ unsigned int maximumList() const { return maxList_;} /** * Minimum energy release fraction */ double minimumReleaseFraction() const {return minReleaseFraction_;} /** * Get the pointer to the DecayConstructor object */ tDecayConstructorPtr decayConstructor() const { return decayConstructor_; } /** * Option for on-shell particles */ unsigned int removeOnShell() const { return removeOnShell_; } /** * Check if a vertex is excluded */ bool excluded(VertexBasePtr vertex) const { // skip an effective vertex if( excludeEffective_ && - int(vertex->orderInGs() + vertex->orderInGem()) != int(vertex->getNpoint())-2) + vertex->orderInAllCouplings() != int(vertex->getNpoint())-2) return true; // check if explicitly forbidden return excludedVerticesSet_.find(vertex)!=excludedVerticesSet_.end(); } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ NBodyDecayConstructorBase & operator=(const NBodyDecayConstructorBase &); private: /** * Whether to initialize decayers or not */ bool init_; /** * Number of iterations if initializing (default 1) */ int iteration_; /** * Number of points to do in initialization */ int points_; /** * Whether to output information on the decayers */ bool info_; /** * Whether to create the DecayModes as well as the Decayer objects */ bool createModes_; /** * Whether or not to remove on-shell diagrams */ unsigned int removeOnShell_; /** * Excluded Vertices */ vector excludedVerticesVector_; /** * Excluded Vertices */ set excludedVerticesSet_; /** * Excluded Particles */ vector excludedParticlesVector_; /** * Excluded Particles */ set excludedParticlesSet_; /** * Whether or not to exclude effective vertices */ bool excludeEffective_; /** * A pointer to the DecayConstructor object */ tDecayConstructorPtr decayConstructor_; /** * The minimum energy release for a three-body decay as a * fraction of the parent mass */ double minReleaseFraction_; /** * Maximum number of EW gauge bosons */ unsigned int maxBoson_; /** * Maximum number of particles from the decaying particle list */ unsigned int maxList_; /** * Include on-shell for \f$t\to b W\f$ */ bool includeTopOnShell_; /** * Remove flavour changing vertices ? */ bool removeFlavourChangingVertices_; /** * Remove small vertices ? */ bool removeSmallVertices_; /** * Minimum norm for vertex removal */ double minVertexNorm_; }; /** An Exception class that can be used by all inheriting classes to * indicate a setup problem. */ class NBodyDecayConstructorError : public Exception { public: NBodyDecayConstructorError() : Exception() {} NBodyDecayConstructorError(const string & str, Severity sev) : Exception(str,sev) {} }; } #endif /* HERWIG_NBodyDecayConstructorBase_H */ diff --git a/Models/General/ResonantProcessConstructor.cc b/Models/General/ResonantProcessConstructor.cc --- a/Models/General/ResonantProcessConstructor.cc +++ b/Models/General/ResonantProcessConstructor.cc @@ -1,390 +1,390 @@ // -*- C++ -*- // // ResonantProcessConstructor.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 ResonantProcessConstructor class. // #include "ResonantProcessConstructor.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" using namespace Herwig; IBPtr ResonantProcessConstructor::clone() const { return new_ptr(*this); } IBPtr ResonantProcessConstructor::fullclone() const { return new_ptr(*this); } void ResonantProcessConstructor::persistentOutput(PersistentOStream & os) const { os << incoming_ << intermediates_ << outgoing_ << processOption_ << scaleChoice_ << scaleFactor_; } void ResonantProcessConstructor::persistentInput(PersistentIStream & is, int) { is >> incoming_ >> intermediates_ >> outgoing_ >> processOption_ >> scaleChoice_ >> scaleFactor_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigResonantProcessConstructor("Herwig::ResonantProcessConstructor", "Herwig.so"); void ResonantProcessConstructor::Init() { static ClassDocumentation documentation ("This class is designed solely to contruct resonant processes using" "a provided set of intermediate particles"); static RefVector interfaceOffshell ("Intermediates", "A vector of offshell particles for resonant diagrams", &ResonantProcessConstructor::intermediates_, -1, false, false, true, false); static RefVector interfaceIncoming ("Incoming", "A vector of incoming particles for resonant diagrams", &ResonantProcessConstructor::incoming_, -1, false, false, true, false); static RefVector interfaceOutgoing ("Outgoing", "A vector of outgoing particles for resonant diagrams", &ResonantProcessConstructor::outgoing_, -1, false, false, true, false); static Switch interfaceProcesses ("Processes", "Whether to generate inclusive or exclusive processes", &ResonantProcessConstructor::processOption_, 0, false, false); static SwitchOption interfaceProcessesSingleParticleInclusive (interfaceProcesses, "SingleParticleInclusive", "Require at least one particle from the list of outgoing particles" " in the hard process", 0); static SwitchOption interfaceProcessesTwoParticleInclusive (interfaceProcesses, "TwoParticleInclusive", "Require that both the particles in the hard processes are in the" " list of outgoing particles", 1); static SwitchOption interfaceProcessesExclusive (interfaceProcesses, "Exclusive", "Require that both the particles in the hard processes are in the" " list of outgoing particles in every hard process", 2); static SwitchOption interfaceProcessesInclusive (interfaceProcesses, "Inclusive", "Generate all modes which are allowed for the on-shell intermediate particle", 3); static SwitchOption interfaceProcessesVeryExclusive (interfaceProcesses, "VeryExclusive", "Require that both the incoming and outgoing particles in the hard processes are in the" " list of outgoing particles in every hard process", 4); static Switch interfaceScaleChoice ("ScaleChoice", "&ResonantProcessConstructor::scaleChoice_", &ResonantProcessConstructor::scaleChoice_, 1, false, false); static SwitchOption interfaceScaleChoicesHat (interfaceScaleChoice, "sHat", "Always use sHat", 1); static SwitchOption interfaceScaleChoiceTransverseMass (interfaceScaleChoice, "TransverseMass", "Always use the transverse mass", 2); static SwitchOption interfaceScaleChoiceGeometicMean (interfaceScaleChoice, "MaxMT", "Use the maximum of m^2+p_T^2 for the two particles", 3); static Parameter interfaceScaleFactor ("ScaleFactor", "The prefactor used in the scale calculation. The scale used is" " sHat multiplied by this prefactor", &ResonantProcessConstructor::scaleFactor_, 1.0, 0.0, 10.0, false, false, Interface::limited); } void ResonantProcessConstructor::doinit() { HardProcessConstructor::doinit(); if((processOption_==2 || processOption_==4) && outgoing_.size()!=2) throw InitException() << "Exclusive processes require exactly" << " two outgoing particles but " << outgoing_.size() << "have been inserted in ResonantProcessConstructor::doinit()." << Exception::runerror; if(processOption_==4 && incoming_.size()!=2) throw InitException() << "Exclusive processes require exactly" << " two incoming particles but " << incoming_.size() << "have been inserted in ResonantProcessConstructor::doinit()." << Exception::runerror; } void ResonantProcessConstructor::constructDiagrams() { size_t ninc = incoming_.size() , ninter = intermediates_.size(); if(ninc == 0 || ninter == 0 || !subProcess() ) return; // find the incoming particle pairs vector incPairs; for(PDVector::size_type i = 0; i < ninc; ++i) { for(PDVector::size_type j = 0; j < ninc; ++j) { tPDPair inc = make_pair(incoming_[i], incoming_[j]); if( (inc.first->iSpin() > inc.second->iSpin()) || (inc.first->iSpin() == inc.second->iSpin() && inc.first->id() < inc.second->id()) ) swap(inc.first, inc.second); if( !HPC_helper::duplicateIncoming(inc,incPairs) ) { incPairs.push_back(inc); } } } size_t nvertices = model()->numberOfVertices(); //To construct resonant diagrams loop over the incoming particles, intermediates //and vertices to find allowed diagrams. Need to exclude the diagrams that have //the intermediate as an external particle as well for(vector::size_type is = 0; is < incPairs.size(); ++is) { tPDPair ppi = incPairs[is]; for(vector::size_type ik = 0; ik < ninter ; ++ik) { long ipart = intermediates_[ik]->id(); for(size_t iv = 0; iv < nvertices; ++iv) { VBPtr vertex = model()->vertex(iv); if(vertex->getNpoint() > 3) continue; long part1 = ppi.first->CC() ? -ppi.first->id() : ppi.first->id(); long part2 = ppi.second->CC() ? -ppi.second->id() : ppi.second->id(); if(vertex->allowed(part1, part2, ipart) || vertex->allowed(part1, ipart, part2) || vertex->allowed(part2, part1, ipart) || vertex->allowed(part2, ipart, part1) || vertex->allowed(ipart, part1, part2) || vertex->allowed(ipart, part2, part1) ) { constructVertex2(make_pair(ppi.first->id(), ppi.second->id()), vertex, intermediates_[ik]); } } } } //Create matrix element for each process const HPDVector::size_type ndiags = diagrams_.size(); for(HPDVector::size_type ix = 0; ix < ndiags; ++ix) createMatrixElement(diagrams_[ix]); } void ResonantProcessConstructor:: constructVertex2(IDPair in, VertexBasePtr vertex, PDPtr partc) { //We have the left hand part of the diagram, just need all the possibilities //for the RHS size_t nvertices = model()->numberOfVertices(); if(processOption_!=3) { for(size_t io = 0; io < outgoing_.size(); ++io) { tcPDPtr outa = outgoing_[io]; for(size_t iv = 0; iv < nvertices; ++iv) { VBPtr vertex2 = model()->vertex(iv); if(vertex2->getNpoint() > 3) continue; tPDSet outb = search(vertex2, partc->id(), incoming, outa->id(), outgoing, outgoing); for(tPDSet::const_iterator ita = outb.begin(); ita != outb.end(); ++ita) makeResonantDiagram(in, partc, outa->id(),(**ita).id(), make_pair(vertex, vertex2)); } } } else { long idRes = !partc->CC() ? partc->id() : partc->CC()->id(); for(size_t iv = 0; iv < nvertices; ++iv) { VBPtr vertex2 = model()->vertex(iv); if(vertex2->getNpoint() > 3) continue; for(unsigned int ix = 0;ix < 3; ++ix) { vector pdlist = vertex2->search(ix, idRes); for(unsigned int iy=0;iymass() < getParticleData(out1)->mass() + getParticleData(out2)->mass()) continue; makeResonantDiagram(in, partc, out1, out2, make_pair(vertex, vertex2)); } } } } } void ResonantProcessConstructor:: makeResonantDiagram(IDPair in, PDPtr offshell, long outa, long outb, VBPair vertpair) { assert(vertpair.first && vertpair.second); if( abs(outa) == abs(offshell->id()) || abs(outb) == abs(offshell->id())) return; HPDiagram newdiag(in,make_pair(outa,outb)); newdiag.intermediate = offshell; newdiag.vertices = vertpair; newdiag.channelType = HPDiagram::sChannel; fixFSOrder(newdiag); assignToCF(newdiag); if(duplicate(newdiag,diagrams_)) return; // if inclusive enforce the exclusivity if(processOption_==1) { PDVector::const_iterator loc = std::find(outgoing_.begin(),outgoing_.end(), getParticleData(newdiag.outgoing. first)); if(loc==outgoing_.end()) return; loc = std::find(outgoing_.begin(),outgoing_.end(), getParticleData(newdiag.outgoing.second)); if(loc==outgoing_.end()) return; } else if(processOption_==2 || processOption_==4 ) { if(!((newdiag.outgoing. first==outgoing_[0]->id()&& newdiag.outgoing.second==outgoing_[1]->id())|| (newdiag.outgoing. first==outgoing_[1]->id()&& newdiag.outgoing.second==outgoing_[0]->id()))) return; if(processOption_==4) { if(!((newdiag.incoming. first==incoming_[0]->id()&& newdiag.incoming.second==incoming_[1]->id())|| (newdiag.incoming. first==incoming_[1]->id()&& newdiag.incoming.second==incoming_[0]->id()))) return; } } // add to the list - diagrams_.push_back(newdiag); + if(checkOrder(newdiag)) diagrams_.push_back(newdiag); } set ResonantProcessConstructor::search(VBPtr vertex, long part1, direction d1, long part2, direction d2, direction d3) { if(d1 == incoming && getParticleData(part1)->CC()) part1 = -part1; if(d2 == incoming && getParticleData(part2)->CC()) part2 = -part2; vector ext; tPDSet third; for(unsigned int ix = 0;ix < 3; ++ix) { vector pdlist = vertex->search(ix, part1); ext.insert(ext.end(), pdlist.begin(), pdlist.end()); } for(unsigned int ix = 0; ix < ext.size(); ix += 3) { long id0 = ext.at(ix); long id1 = ext.at(ix+1); long id2 = ext.at(ix+2); int pos; if((id0 == part1 && id1 == part2) || (id0 == part2 && id1 == part1)) pos = ix + 2; else if((id0 == part1 && id2 == part2) || (id0 == part2 && id2 == part1)) pos = ix + 1; else if((id1 == part1 && id2 == part2) || (id1 == part2 && id2 == part1)) pos = ix; else pos = -1; if(pos >= 0) { tPDPtr p = getParticleData(ext[pos]); if(d3 == incoming && p->CC()) p = p->CC(); third.insert(p); } } return third; } IDPair ResonantProcessConstructor:: find(long part, const vector & out) const { vector::size_type iloc(0); bool found(false); do { if(out[iloc]->id() == part) found = true; else ++iloc; } while(found == false && iloc < out.size()); //found offshell IDPair outids; if(iloc == 0) outids = make_pair(out[1]->id(), out[2]->id()); else if(iloc == 1) outids = make_pair(out[0]->id(), out[2]->id()); else outids = make_pair(out[0]->id(), out[1]->id()); return outids; } void ResonantProcessConstructor:: createMatrixElement(const HPDiagram & diag) const { vector extpart(4); extpart[0] = getParticleData(diag.incoming.first); extpart[1] = getParticleData(diag.incoming.second); extpart[2] = getParticleData(diag.outgoing.first); extpart[3] = getParticleData(diag.outgoing.second); string objectname ("/Herwig/MatrixElements/"); string classname = MEClassname(extpart, diag.intermediate, objectname); GeneralHardMEPtr matrixElement = dynamic_ptr_cast (generator()->preinitCreate(classname, objectname)); if( !matrixElement ) { throw RPConstructorError() << "ResonantProcessConstructor::createMatrixElement " << "- No matrix element object could be created for " << "the process " << extpart[0]->PDGName() << " " << extpart[0]->iSpin() << "," << extpart[1]->PDGName() << " " << extpart[1]->iSpin() << "->" << extpart[2]->PDGName() << " " << extpart[2]->iSpin() << "," << extpart[3]->PDGName() << " " << extpart[3]->iSpin() << ". Constructed class name: \"" << classname << "\"\n" << Exception::warning; return; } matrixElement->setProcessInfo(HPDVector(1, diag), colourFlow(extpart), debug(),scaleChoice_-1,scaleFactor_); generator()->preinitInterface(subProcess(), "MatrixElements", subProcess()->MEs().size(), "insert", matrixElement->fullName()); } string ResonantProcessConstructor:: MEClassname(const vector & extpart, tcPDPtr inter, string & objname) const { string classname("Herwig::ME"); for(vector::size_type ix = 0; ix < extpart.size(); ++ix) { if(ix == 2) classname += "2"; if(extpart[ix]->iSpin() == PDT::Spin0) classname += "s"; else if(extpart[ix]->iSpin() == PDT::Spin1) classname += "v"; else if(extpart[ix]->iSpin() == PDT::Spin1Half) classname += "f"; else if(extpart[ix]->iSpin() == PDT::Spin2) classname += "t"; else throw RPConstructorError() << "MEClassname() : Encountered an unknown spin for " << extpart[ix]->PDGName() << " while constructing MatrixElement " << "classname " << extpart[ix]->iSpin() << Exception::warning; } objname += "ME" + extpart[0]->PDGName() + extpart[1]->PDGName() + "2" + inter->PDGName() + "2" + extpart[2]->PDGName() + extpart[3]->PDGName(); return classname; } diff --git a/Models/General/ThreeBodyDecayConstructor.cc b/Models/General/ThreeBodyDecayConstructor.cc --- a/Models/General/ThreeBodyDecayConstructor.cc +++ b/Models/General/ThreeBodyDecayConstructor.cc @@ -1,373 +1,374 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the ThreeBodyDecayConstructor class. // #include "ThreeBodyDecayConstructor.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Utilities/Debug.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/Models/StandardModel/StandardModel.h" #include "Herwig/Decay/General/GeneralThreeBodyDecayer.h" #include "Herwig/Decay/DecayPhaseSpaceMode.h" #include "Herwig/PDT/ThreeBodyAllOnCalculator.h" #include "ThePEG/PDT/StandardMatchers.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Utilities/Throw.h" #include "DecayConstructor.h" #include "WeakCurrentDecayConstructor.h" using namespace Herwig; IBPtr ThreeBodyDecayConstructor::clone() const { return new_ptr(*this); } IBPtr ThreeBodyDecayConstructor::fullclone() const { return new_ptr(*this); } void ThreeBodyDecayConstructor::persistentOutput(PersistentOStream & os) const { os << interOpt_ << widthOpt_ << intOpt_ << relErr_ << includeIntermediatePhotons_; } void ThreeBodyDecayConstructor::persistentInput(PersistentIStream & is, int) { is >> interOpt_ >> widthOpt_ >> intOpt_ >> relErr_ >> includeIntermediatePhotons_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigThreeBodyDecayConstructor("Herwig::ThreeBodyDecayConstructor", "Herwig.so"); void ThreeBodyDecayConstructor::Init() { static ClassDocumentation documentation ("The ThreeBodyDecayConstructor class constructs the three body decay modes"); static Switch interfaceIncludeIntermediatePhotons ("IncludeIntermediatePhotons", "Whether or not ot allow intermediate photons", &ThreeBodyDecayConstructor::includeIntermediatePhotons_, false, false, false); static SwitchOption interfaceIncludeIntermediatePhotonsYes (interfaceIncludeIntermediatePhotons, "Yes", "Include them", true); static SwitchOption interfaceIncludeIntermediatePhotonsNo (interfaceIncludeIntermediatePhotons, "No", "Don't include them", false); static Switch interfaceWidthOption ("WidthOption", "Option for the treatment of the widths of the intermediates", &ThreeBodyDecayConstructor::widthOpt_, 1, false, false); static SwitchOption interfaceWidthOptionFixed (interfaceWidthOption, "Fixed", "Use fixed widths", 1); static SwitchOption interfaceWidthOptionRunning (interfaceWidthOption, "Running", "Use running widths", 2); static SwitchOption interfaceWidthOptionZero (interfaceWidthOption, "Zero", "Set the widths to zero", 3); static Switch interfaceIntermediateOption ("IntermediateOption", "Option for the inclusion of intermediates in the event", &ThreeBodyDecayConstructor::interOpt_, 0, false, false); static SwitchOption interfaceIntermediateOptionAlways (interfaceIntermediateOption, "Always", "Always include the intermediates", 1); static SwitchOption interfaceIntermediateOptionNever (interfaceIntermediateOption, "Never", "Never include the intermediates", 2); static SwitchOption interfaceIntermediateOptionOnlyIfOnShell (interfaceIntermediateOption, "OnlyIfOnShell", "Only if there are on-shell diagrams", 0); static Switch interfaceIntegrationOption ("IntegrationOption", "Option for the integration of the partial width", &ThreeBodyDecayConstructor::intOpt_, 1, false, false); static SwitchOption interfaceIntegrationOptionAllPoles (interfaceIntegrationOption, "AllPoles", "Include all potential poles", 0); static SwitchOption interfaceIntegrationOptionShallowestPole (interfaceIntegrationOption, "ShallowestPole", "Only include the shallowest pole", 1); static Parameter interfaceRelativeError ("RelativeError", "The relative error for the GQ integration", &ThreeBodyDecayConstructor::relErr_, 1e-2, 1e-10, 1., false, false, Interface::limited); } void ThreeBodyDecayConstructor::DecayList(const set & particles) { if( particles.empty() ) return; // special for weak decays for(unsigned int ix=0;ixdecayConstructors().size();++ix) { Ptr::pointer weak = dynamic_ptr_cast::pointer > (decayConstructor()->decayConstructors()[ix]); if(!weak) continue; weakMassCut_ = max(weakMassCut_,weak->massCut()); } NBodyDecayConstructorBase::DecayList(particles); } GeneralThreeBodyDecayerPtr ThreeBodyDecayConstructor:: createDecayer(vector & diagrams, bool inter, double symfac) const { if(diagrams.empty()) return GeneralThreeBodyDecayerPtr(); // extract the external particles for the process PDPtr incoming = getParticleData(diagrams[0].incoming); // outgoing particles OrderedParticles outgoing; outgoing.insert(getParticleData(diagrams[0].outgoing )); outgoing.insert(getParticleData(diagrams[0].outgoingPair.first )); outgoing.insert(getParticleData(diagrams[0].outgoingPair.second)); // get the object name string objectname ("/Herwig/Decays/"); string classname = DecayerClassName(incoming, outgoing, objectname); if(classname=="") return GeneralThreeBodyDecayerPtr(); // create the object GeneralThreeBodyDecayerPtr decayer = dynamic_ptr_cast (generator()->preinitCreate(classname, objectname)); // set up the decayer and return if doesn't work vector outVector(outgoing.begin(),outgoing.end()); if(!decayer->setDecayInfo(incoming,outVector,diagrams,symfac)) return GeneralThreeBodyDecayerPtr(); // set decayer options from base class setDecayerInterfaces(objectname); // options for partial width integration ostringstream value; value << intOpt_; generator()->preinitInterface(objectname, "PartialWidthIntegration", "set", value.str()); value.str(""); value << relErr_; generator()->preinitInterface(objectname, "RelativeError", "set", value.str()); // set the width option value.str(""); value << widthOpt_; generator()->preinitInterface(objectname, "WidthOption", "set", value.str()); // set the intermediates option value.str(""); value << inter; generator()->preinitInterface(objectname, "GenerateIntermediates", "set", value.str()); // initialize the decayer decayer->init(); // return the decayer return decayer; } string ThreeBodyDecayConstructor:: DecayerClassName(tcPDPtr incoming, const OrderedParticles & outgoing, string & objname) const { string classname("Herwig::"); // spins of the outgoing particles unsigned int ns(0),nf(0),nv(0); objname += incoming->PDGName() + "2"; for(OrderedParticles::const_iterator it=outgoing.begin(); it!=outgoing.end();++it) { if ((**it).iSpin()==PDT::Spin0 ) ++ns; else if((**it).iSpin()==PDT::Spin1Half) ++nf; else if((**it).iSpin()==PDT::Spin1 ) ++nv; objname += (**it).PDGName(); } objname += "Decayer"; if(incoming->iSpin()==PDT::Spin0) { if(ns==1&&nf==2) classname += "StoSFFDecayer"; else if(nf==2&&nv==1) classname += "StoFFVDecayer"; else classname = ""; } else if(incoming->iSpin()==PDT::Spin1Half) { if(nf==3) classname += "FtoFFFDecayer"; else if(nf==1&&nv==2) classname += "FtoFVVDecayer"; else classname = ""; } else if(incoming->iSpin()==PDT::Spin1) { if(nf==2&&nv==1) classname += "VtoFFVDecayer"; else classname = ""; } else { classname=""; } return classname; } void ThreeBodyDecayConstructor:: createDecayMode(vector & mode, bool possibleOnShell, double symfac) { // convert the diagrams from the general to the three body structure vector diagrams; for(unsigned int iy=0;iyZERO && diagrams.back().intermediate && abs(diagrams.back().intermediate->id())==ParticleID::Wplus) { Energy deltaM = getParticleData(diagrams.back().incoming)->mass() - getParticleData(diagrams.back().outgoing)->mass(); if(deltaMid())==ParticleID::gamma) diagrams.pop_back(); } if(diagrams.empty()) return; // check if possible on-shell internal particles bool inter = interOpt_ == 1 || (interOpt_ == 0 && possibleOnShell); // incoming particle tPDPtr inpart = getParticleData(diagrams[0].incoming); // outgoing particles OrderedParticles outgoing; outgoing.insert(getParticleData(diagrams[0].outgoing)); outgoing.insert(getParticleData(diagrams[0].outgoingPair.first )); outgoing.insert(getParticleData(diagrams[0].outgoingPair.second)); // sort out ordering and labeling of diagrams vector outVector(outgoing.begin(),outgoing.end()); for(unsigned int ix=0;ixid() != diagrams[ix].outgoingPair.first) || ( diagrams[ix].channelType == TBDiagram::channel13 && outVector[0]->id() != diagrams[ix].outgoingPair.first) || ( diagrams[ix].channelType == TBDiagram::channel12 && outVector[0]->id() != diagrams[ix].outgoingPair.first) ) swap(diagrams[ix].outgoingPair.first, diagrams[ix].outgoingPair.second); } // construct the tag for the decay mode string tag = inpart->name() + "->"; unsigned int iprod=0; for(OrderedParticles::const_iterator it = outgoing.begin(); it != outgoing.end(); ++it) { ++iprod; tag += (**it).name(); if(iprod != 3) tag += ","; } tag += ";"; tDMPtr dm = generator()->findDecayMode(tag); // create mode if needed if( createDecayModes() && (!dm || inpart->id() == ParticleID::h0) ) { // create the decayer GeneralThreeBodyDecayerPtr decayer = createDecayer(diagrams,inter,symfac); if(!decayer) { if(Debug::level > 1 ) generator()->log() << "Can't create the decayer for " << tag << " so mode not created\n"; return; } tDMPtr ndm = generator()->preinitCreateDecayMode(tag); if(ndm) { generator()->preinitInterface(ndm, "Decayer", "set", decayer->fullName()); generator()->preinitInterface(ndm, "Active", "set", "Yes"); if(!ndm->decayer()) { generator()->log() << "Can't set the decayer for " << tag << " so mode not created \n"; return; } OrderedParticles::const_iterator pit=outgoing.begin(); tPDPtr pa = *pit; ++pit; tPDPtr pb = *pit; ++pit; tPDPtr pc = *pit; Energy width = decayer->partialWidth(make_pair(inpart,inpart->mass()), make_pair(pa,pa->mass()) , make_pair(pb,pb->mass()) , make_pair(pc,pc->mass())); if ( Debug::level > 1 ) generator()->log() << "Partial width is: " << width / GeV << " GeV\n"; setBranchingRatio(ndm, width); if(ndm->brat()minimumBR()) { generator()->preinitInterface(decayer->fullName(), "Initialize", "set","0"); } // incoming particle is now unstable inpart->stable(false); if(Debug::level > 1 ) { generator()->log() << "Calculated partial width for mode " << tag << " is " << width/GeV << "\n"; } } else throw NBodyDecayConstructorError() << "ThreeBodyDecayConstructor::createDecayMode - Needed to create " << "new decaymode but one could not be created for the tag " << tag << Exception::warning; } else if( dm ) { if(dm->brat()minimumBR()) { return; } if((dm->decayer()->fullName()).find("Mambo") != string::npos) { // create the decayer GeneralThreeBodyDecayerPtr decayer = createDecayer(diagrams,inter,symfac); if(decayer) { generator()->preinitInterface(dm, "Decayer", "set", decayer->fullName()); // check not zero OrderedParticles::const_iterator pit=outgoing.begin(); tPDPtr pa = *pit; ++pit; tPDPtr pb = *pit; ++pit; tPDPtr pc = *pit; Energy width = decayer->partialWidth(make_pair(inpart,inpart->mass()), make_pair(pa,pa->mass()) , make_pair(pb,pb->mass()) , make_pair(pc,pc->mass())); if(width/(dm->brat()*inpart->width())<1e-10) { string message = "Herwig calculation of the partial width for the decay mode " + inpart->PDGName() + " -> " + pa->PDGName() + " " + pb->PDGName() + " " + pc->PDGName() + " is zero.\n This will cause problems with the calculation of" + " spin correlations.\n It is probably due to inconsistent parameters" + " and decay modes being passed to Herwig via the SLHA file.\n" + " Zeroing the branching ratio for this mode."; setBranchingRatio(dm,ZERO); generator()->logWarning(NBodyDecayConstructorError(message,Exception::warning)); } } // incoming particle is now unstable inpart->stable(false); } } //update CC mode if it exists if( inpart->CC() ) inpart->CC()->synchronize(); } diff --git a/Models/General/TwoBodyDecay.h b/Models/General/TwoBodyDecay.h --- a/Models/General/TwoBodyDecay.h +++ b/Models/General/TwoBodyDecay.h @@ -1,80 +1,89 @@ // -*- C++ -*- // // TwoBodyDecay.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_TwoBodyDecay_H #define HERWIG_TwoBodyDecay_H // // This is the declaration of the TwoBodyDecay struct. // namespace Herwig { using namespace ThePEG; using Helicity::tVertexBasePtr; /** * Struct for the prototype of a two-body decay mode */ struct TwoBodyDecay { public: /** * Constructor * @param pa Decaying particle * @param pb First decay product * @param pc Second decay product */ TwoBodyDecay(tPDPtr pa, tPDPtr pb, tPDPtr pc, tVertexBasePtr vertex) : parent_(pa), vertex_(vertex) { ParticleOrdering order; if( order(pb, pc) ) { children_.first = pb; children_.second = pc; } else { children_.first = pc; children_.second = pb; } } /** * The parent */ tPDPtr parent_; /** * The children */ tPDPair children_; /** * Vertex */ tVertexBasePtr vertex_; private: TwoBodyDecay(); }; /** * Test whether one TwoBodyDecay is less than another */ inline bool operator<(const TwoBodyDecay & x, const TwoBodyDecay & y) { if(x.parent_->id()!=y.parent_->id()) return x.parent_->id()id(); if(x.children_.first->id()!=y.children_.first->id()) return x.children_.first->id() < y.children_.first->id(); if(x.children_.second->id()!=y.children_.second->id()) return x.children_.second->id() < y.children_.second->id(); - return x.vertex_id()!=y.parent_->id()) + return false; + if(x.children_.first->id()!=y.children_.first->id()) + return false; + if(x.children_.second->id()!=y.children_.second->id()) + return false; + return true; } } #endif /* HERWIG_TwoBodyDecay_H */ diff --git a/Models/General/TwoBodyDecayConstructor.cc b/Models/General/TwoBodyDecayConstructor.cc --- a/Models/General/TwoBodyDecayConstructor.cc +++ b/Models/General/TwoBodyDecayConstructor.cc @@ -1,422 +1,432 @@ // -*- C++ -*- // // TwoBodyDecayConstructor.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 TwoBodyDecayConstructor class. // #include "TwoBodyDecayConstructor.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Switch.h" #include "Herwig/Decay/General/GeneralTwoBodyDecayer.h" #include "Herwig/Models/StandardModel/StandardModel.h" #include "ThePEG/PDT/EnumParticles.h" #include "DecayConstructor.h" #include "ThePEG/Utilities/Throw.h" #include "ThePEG/Utilities/EnumIO.h" #include "ThePEG/Helicity/Vertex/AbstractFFVVertex.fh" #include "ThePEG/Helicity/Vertex/AbstractFFSVertex.fh" #include "ThePEG/Helicity/Vertex/AbstractVVSVertex.fh" #include "ThePEG/Helicity/Vertex/AbstractVSSVertex.fh" #include "ThePEG/Helicity/Vertex/AbstractVVTVertex.fh" #include "ThePEG/Helicity/Vertex/AbstractFFTVertex.fh" #include "ThePEG/Helicity/Vertex/AbstractSSTVertex.fh" #include "ThePEG/Helicity/Vertex/AbstractSSSVertex.fh" #include "ThePEG/Helicity/Vertex/AbstractVVVVertex.fh" #include "ThePEG/Helicity/Vertex/AbstractRFSVertex.fh" #include "ThePEG/Helicity/Vertex/AbstractRFVVertex.fh" using namespace Herwig; using ThePEG::Helicity::VertexBasePtr; IBPtr TwoBodyDecayConstructor::clone() const { return new_ptr(*this); } IBPtr TwoBodyDecayConstructor::fullclone() const { return new_ptr(*this); } void TwoBodyDecayConstructor::persistentOutput(PersistentOStream & os) const { os << alphaQCD_ << alphaQED_ << oenum(inter_); } void TwoBodyDecayConstructor::persistentInput(PersistentIStream & is, int) { is >> alphaQCD_ >> alphaQED_>> ienum(inter_); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigTwoBodyDecayConstructor("Herwig::TwoBodyDecayConstructor", "Herwig.so"); void TwoBodyDecayConstructor::Init() { static ClassDocumentation documentation ("The TwoBodyDecayConstructor implements to creation of 2 body decaymodes " "and decayers that do not already exist for the given set of vertices."); static Reference interfaceShowerAlphaQCD ("AlphaQCD", "The coupling for QCD corrections", &TwoBodyDecayConstructor::alphaQCD_, false, false, true, false, false); static Reference interfaceShowerAlphaQED ("AlphaQED", "The coupling for QED corrections", &TwoBodyDecayConstructor::alphaQED_, false, false, true, false, false); static Switch interfaceInteractions ("Interactions", "which interactions to include for the hard corrections", &TwoBodyDecayConstructor::inter_, ShowerInteraction::QCD, false, false); static SwitchOption interfaceInteractionsQCD (interfaceInteractions, "QCD", "QCD Only", ShowerInteraction::QCD); static SwitchOption interfaceInteractionsQED (interfaceInteractions, "QED", "QED only", ShowerInteraction::QED); static SwitchOption interfaceInteractionsQCDandQED (interfaceInteractions, "QCDandQED", "Both QCD and QED", ShowerInteraction::Both); } void TwoBodyDecayConstructor::DecayList(const set & particles) { if( particles.empty() ) return; tHwSMPtr model = dynamic_ptr_cast(generator()->standardModel()); unsigned int nv(model->numberOfVertices()); for(set::const_iterator ip=particles.begin(); ip!=particles.end();++ip) { tPDPtr parent = *ip; if ( Debug::level > 0 ) Repository::cout() << "Constructing 2-body decays for " << parent->PDGName() << '\n'; + multiset decays; for(unsigned int iv = 0; iv < nv; ++iv) { if(excluded(model->vertex(iv)) || model->vertex(iv)->getNpoint()>3) continue; - for(unsigned int il = 0; il < 3; ++il) { - set decays = - createModes(parent, model->vertex(iv), il); - if( !decays.empty() ) createDecayMode(decays); - } + for(unsigned int il = 0; il < 3; ++il) + createModes(parent, model->vertex(iv), il,decays); } + if( !decays.empty() ) createDecayMode(decays); } } -set TwoBodyDecayConstructor:: +void TwoBodyDecayConstructor:: createModes(tPDPtr inpart, VertexBasePtr vertex, - unsigned int list) { + unsigned int list, multiset & modes) { if( !vertex->isIncoming(inpart) || vertex->getNpoint() != 3 ) - return set(); + return; Energy m1(inpart->mass()); tPDPtr ccpart = inpart->CC() ? inpart->CC() : inpart; long id = ccpart->id(); tPDVector decaylist = vertex->search(list, ccpart); - set decays; tPDVector::size_type nd = decaylist.size(); for( tPDVector::size_type i = 0; i < nd; i += 3 ) { tPDPtr pa(decaylist[i]), pb(decaylist[i + 1]), pc(decaylist[i + 2]); if( pb->id() == id ) swap(pa, pb); if( pc->id() == id ) swap(pa, pc); //allowed on-shell decay? if( m1 <= pb->mass() + pc->mass() ) continue; //vertices are defined with all particles incoming - decays.insert( TwoBodyDecay(inpart,pb, pc, vertex) ); + modes.insert( TwoBodyDecay(inpart,pb, pc, vertex) ); } - return decays; } -GeneralTwoBodyDecayerPtr TwoBodyDecayConstructor::createDecayer(TwoBodyDecay decay) { +GeneralTwoBodyDecayerPtr +TwoBodyDecayConstructor::createDecayer(TwoBodyDecay decay, + vector vertices) { string name; using namespace Helicity::VertexType; PDT::Spin in = decay.parent_->iSpin(); // PDT::Spin out1 = decay.children_.first ->iSpin(); PDT::Spin out2 = decay.children_.second->iSpin(); switch(decay.vertex_->getName()) { case FFV : if(in == PDT::Spin1Half) { name = "FFVDecayer"; if(out2==PDT::Spin1Half) swap(decay.children_.first,decay.children_.second); } else { name = "VFFDecayer"; } break; case FFS : if(in == PDT::Spin1Half) { name = "FFSDecayer"; if(out2==PDT::Spin1Half) swap(decay.children_.first,decay.children_.second); } else { name = "SFFDecayer"; } break; case VVS : if(in == PDT::Spin1) { name = "VVSDecayer"; if(out2==PDT::Spin1) swap(decay.children_.first,decay.children_.second); } else { name = "SVVDecayer"; } break; case VSS : if(in == PDT::Spin1) { name = "VSSDecayer"; } else { name = "SSVDecayer"; if(out2==PDT::Spin0) swap(decay.children_.first,decay.children_.second); } break; case VVT : name = in==PDT::Spin2 ? "TVVDecayer" : "Unknown"; break; case FFT : name = in==PDT::Spin2 ? "TFFDecayer" : "Unknown"; break; case SST : name = in==PDT::Spin2 ? "TSSDecayer" : "Unknown"; break; case SSS : name = "SSSDecayer"; break; case VVV : name = "VVVDecayer"; break; case RFS : if(in==PDT::Spin1Half) { name = "FRSDecayer"; if(out2==PDT::Spin3Half) swap(decay.children_.first,decay.children_.second); } else if(in==PDT::Spin0) { name = "SRFDecayer"; if(out2==PDT::Spin3Half) swap(decay.children_.first,decay.children_.second); } else { name = "Unknown"; } break; case RFV : if(in==PDT::Spin1Half) { name = "FRVDecayer"; if(out2==PDT::Spin3Half) swap(decay.children_.first,decay.children_.second); } else name = "Unknown"; break; default : Throw() << "Error: Cannot assign " << decay.vertex_->fullName() << " to a decayer. " << "Decay is " << decay.parent_->PDGName() << " -> " << decay.children_.first ->PDGName() << " " << decay.children_.second->PDGName() << Exception::runerror; } if(name=="Unknown") Throw() << "Error: Cannot assign " << decay.vertex_->fullName() << " to a decayer. " << "Decay is " << decay.parent_->PDGName() << " -> " << decay.children_.first ->PDGName() << " " << decay.children_.second->PDGName() << Exception::runerror; ostringstream fullname; fullname << "/Herwig/Decays/" << name << "_" << decay.parent_->PDGName() << "_" << decay.children_.first ->PDGName() << "_" << decay.children_.second->PDGName(); string classname = "Herwig::" + name; GeneralTwoBodyDecayerPtr decayer; decayer = dynamic_ptr_cast (generator()->preinitCreate(classname,fullname.str())); if(!decayer) Throw() << "Error: Cannot assign " << decay.vertex_->fullName() << " to a decayer. " << "Decay is " << decay.parent_->PDGName() << " -> " << decay.children_.first ->PDGName() << " " << decay.children_.second->PDGName() << Exception::runerror; // set the strong coupling for radiation generator()->preinitInterface(decayer, "AlphaS" , "set", alphaQCD_->fullName()); // set the EM coupling for radiation generator()->preinitInterface(decayer, "AlphaEM", "set", alphaQED_->fullName()); // set the type of interactions for the correction if(inter_==ShowerInteraction::QCD) generator()->preinitInterface(decayer, "Interactions", "set", "QCD"); else if(inter_==ShowerInteraction::QED) generator()->preinitInterface(decayer, "Interactions", "set", "QED"); else generator()->preinitInterface(decayer, "Interactions", "set", "QCDandQED"); // get the vertices for radiation from the external legs map inRad,fourRad; vector > outRad(2); vector itemp={ShowerInteraction::QCD,ShowerInteraction::QED}; for(auto & inter : itemp) { inRad[inter] = radiationVertex(decay.parent_,inter); outRad[0][inter] = radiationVertex(decay.children_.first ,inter); outRad[1][inter] = radiationVertex(decay.children_.second,inter); // get any contributing 4 point vertices fourRad[inter] = radiationVertex(decay.parent_,inter, decay.children_); } // set info on decay - decayer->setDecayInfo(decay.parent_,decay.children_,decay.vertex_, + decayer->setDecayInfo(decay.parent_,decay.children_,vertices, inRad,outRad,fourRad); // initialised the decayer setDecayerInterfaces(fullname.str()); decayer->init(); return decayer; } void TwoBodyDecayConstructor:: -createDecayMode(set & decays) { +createDecayMode(multiset & decays) { tPDPtr inpart = decays.begin()->parent_; - set::iterator dend = decays.end(); - for( set::iterator dit = decays.begin(); - dit != dend; ++dit ) { - tPDPtr pb((*dit).children_.first), pc((*dit).children_.second); + for( multiset::iterator dit = decays.begin(); + dit != decays.end(); ) { + TwoBodyDecay mode = *dit; + // get all the moees with the same in and outgoing particles + pair::iterator, + multiset::iterator> range = decays.equal_range(mode); + // construct the decay mode + tPDPtr pb((mode).children_.first), pc((mode).children_.second); string tag = inpart->name() + "->" + pb->name() + "," + pc->name() + ";"; // Does it exist already ? tDMPtr dm = generator()->findDecayMode(tag); + // find the vertices + vector vertices; + for ( multiset::iterator dit2 = range.first; + dit2 != range.second; ++dit2) { + vertices.push_back(dit2->vertex_); + } + dit=range.second; // now create DecayMode objects that do not already exist if( createDecayModes() && (!dm || inpart->id() == ParticleID::h0) ) { tDMPtr ndm = generator()->preinitCreateDecayMode(tag); if(ndm) { inpart->stable(false); - GeneralTwoBodyDecayerPtr decayer=createDecayer(*dit); + GeneralTwoBodyDecayerPtr decayer=createDecayer(mode,vertices); if(!decayer) continue; generator()->preinitInterface(ndm, "Decayer", "set", decayer->fullName()); generator()->preinitInterface(ndm, "Active", "set", "Yes"); Energy width = decayer->partialWidth(make_pair(inpart,inpart->mass()), make_pair(pb,pb->mass()) , make_pair(pc,pc->mass())); setBranchingRatio(ndm, width); if(width==ZERO || ndm->brat()minimumBR()) { generator()->preinitInterface(decayer->fullName(), "Initialize", "set","0"); } } else Throw() << "TwoBodyDecayConstructor::createDecayMode - Needed to create " << "new decaymode but one could not be created for the tag " << tag << Exception::warning; } else if( dm ) { if(dm->brat()minimumBR()) { continue; } if((dm->decayer()->fullName()).find("Mambo") != string::npos) { inpart->stable(false); - GeneralTwoBodyDecayerPtr decayer=createDecayer(*dit); + GeneralTwoBodyDecayerPtr decayer=createDecayer(mode,vertices); if(!decayer) continue; generator()->preinitInterface(dm, "Decayer", "set", decayer->fullName()); Energy width = decayer->partialWidth(make_pair(inpart,inpart->mass()), make_pair(pb,pb->mass()) , make_pair(pc,pc->mass())); if(width/(dm->brat()*inpart->width())<1e-10) { string message = "Herwig calculation of the partial width for the decay mode " + inpart->PDGName() + " -> " + pb->PDGName() + " " + pc->PDGName() + " is zero.\n This will cause problems with the calculation of" + " spin correlations.\n It is probably due to inconsistent parameters" + " and decay modes being passed to Herwig via the SLHA file.\n" + " Zeroing the branching ratio for this mode."; setBranchingRatio(dm,ZERO); generator()->logWarning(NBodyDecayConstructorError(message,Exception::warning)); } } } } // update CC mode if it exists if( inpart->CC() ) inpart->CC()->synchronize(); } VertexBasePtr TwoBodyDecayConstructor::radiationVertex(tPDPtr particle, ShowerInteraction inter, tPDPair children) { tHwSMPtr model = dynamic_ptr_cast(generator()->standardModel()); map::iterator rit = radiationVertices_[inter].find(particle); tPDPtr cc = particle->CC() ? particle->CC() : particle; if(children==tPDPair() && rit!=radiationVertices_[inter].end()) return rit->second; unsigned int nv(model->numberOfVertices()); long bosonID = inter==ShowerInteraction::QCD ? ParticleID::g : ParticleID::gamma; tPDPtr gluon = getParticleData(bosonID); // look for radiation vertices for incoming and outgoing particles for(unsigned int iv=0;ivvertex(iv); // look for 3 point vertices if (children==tPDPair()){ if( !vertex->isIncoming(particle) || vertex->getNpoint() != 3 || !vertex->isOutgoing(particle) || !vertex->isOutgoing(gluon)) continue; for(unsigned int list=0;list<3;++list) { tPDVector decaylist = vertex->search(list, particle); for( tPDVector::size_type i = 0; i < decaylist.size(); i += 3 ) { tPDPtr pa(decaylist[i]), pb(decaylist[i + 1]), pc(decaylist[i + 2]); if( pb->id() == bosonID ) swap(pa, pb); if( pc->id() == bosonID ) swap(pa, pc); if( pb->id() != particle->id()) swap(pb, pc); if( pa->id() != bosonID) continue; if( pb != particle) continue; if( pc != cc) continue; radiationVertices_[inter][particle] = vertex; return vertex; } } } // look for 4 point vertex including a gluon else { if( !vertex->isIncoming(particle) || vertex->getNpoint()!=4 || !vertex->isOutgoing(children.first) || !vertex->isOutgoing(children.second) || !vertex->isOutgoing(gluon)) continue; for(unsigned int list=0;list<4;++list) { tPDVector decaylist = vertex->search(list, particle); for( tPDVector::size_type i = 0; i < decaylist.size(); i += 4 ) { tPDPtr pa(decaylist[i]), pb(decaylist[i+1]), pc(decaylist[i+2]), pd(decaylist[i+3]); // order so that a = g, b = parent if( pb->id() == bosonID ) swap(pa, pb); if( pc->id() == bosonID ) swap(pa, pc); if( pd->id() == bosonID ) swap(pa, pd); if( pc->id() == particle->id()) swap(pb, pc); if( pd->id() == particle->id()) swap(pb, pd); if( pa->id() != bosonID) continue; if( pb->id() != particle->id()) continue; if( !((abs(pd->id()) == abs(children. first->id()) && abs(pc->id()) == abs(children.second->id())) || (abs(pc->id()) == abs(children. first->id()) && abs(pd->id()) == abs(children.second->id())))) continue; return vertex; } } } } return VertexBasePtr(); } diff --git a/Models/General/TwoBodyDecayConstructor.h b/Models/General/TwoBodyDecayConstructor.h --- a/Models/General/TwoBodyDecayConstructor.h +++ b/Models/General/TwoBodyDecayConstructor.h @@ -1,175 +1,177 @@ // -*- C++ -*- // // TwoBodyDecayConstructor.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_TwoBodyDecayConstructor_H #define HERWIG_TwoBodyDecayConstructor_H // // This is the declaration of the TwoBodyDecayConstructor class. // #include "NBodyDecayConstructorBase.h" #include "ThePEG/Helicity/Vertex/VertexBase.h" #include "Herwig/Decay/General/GeneralTwoBodyDecayer.fh" #include "Herwig/Shower/ShowerAlpha.h" #include "TwoBodyDecay.h" namespace Herwig { using namespace ThePEG; using Helicity::VertexBasePtr; using Helicity::tVertexBasePtr; /** * The TwoBodyDecayConstructor class inherits from the dummy base class * NBodyDecayConstructorBase and implements the necessary functions in * order to create the 2 body decay modes for a given set of vertices * stored in a Model class. * * @see \ref TwoBodyDecayConstructorInterfaces "The interfaces" * defined for TwoBodyDecayConstructor. * @see NBodyDecayConstructor **/ class TwoBodyDecayConstructor: public NBodyDecayConstructorBase { public: /** * The default constructor. */ TwoBodyDecayConstructor() : inter_(ShowerInteraction::Both) { radiationVertices_[ShowerInteraction::QCD] = map(); radiationVertices_[ShowerInteraction::QED] = map(); } /** * Function used to determine allowed decaymodes *@param part vector of ParticleData pointers containing particles in model */ virtual void DecayList(const set & part); /** * Number of outgoing lines. Required for correct ordering. */ virtual unsigned int numBodies() const { return 2; } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ TwoBodyDecayConstructor & operator=(const TwoBodyDecayConstructor &); private: /** @name Functions to create decayers and decaymodes. */ //@{ /** * Function to create decays * @param inpart Incoming particle * @param vert The vertex to create decays for * @param ilist Which list to search * @param iv Row number in _theExistingDecayers member * @return A vector a decay modes */ - set createModes(tPDPtr inpart, VertexBasePtr vert, - unsigned int ilist); + void createModes(tPDPtr inpart, VertexBasePtr vert, + unsigned int ilist, + multiset & modes); /** * Function to create decayer for specific vertex * @param decay decay mode for this decay * member variable */ - GeneralTwoBodyDecayerPtr createDecayer(TwoBodyDecay decay); + GeneralTwoBodyDecayerPtr createDecayer(TwoBodyDecay decay, + vector ); /** * Create decay mode(s) from given part and decay modes * @param decays The vector of decay modes * @param decayer The decayer responsible for this decay */ - void createDecayMode(set & decays); + void createDecayMode(multiset & decays); //@} /** * Get the vertex for QED/QCD radiation */ VertexBasePtr radiationVertex(tPDPtr particle,ShowerInteraction inter, tPDPair children = tPDPair ()); private: /** * Map of particles and the vertices which generate their QCD * radiation */ map > radiationVertices_; /** * Default choice for the strong coupling object for hard QCD radiation */ ShowerAlphaPtr alphaQCD_; /** * Default choice for the strong coupling object for hard QED radiation */ ShowerAlphaPtr alphaQED_; /** * Which type of corrections to the decays to include */ ShowerInteraction inter_; }; } #endif /* HERWIG_TwoBodyDecayConstructor_H */ diff --git a/Models/General/TwoToTwoProcessConstructor.cc b/Models/General/TwoToTwoProcessConstructor.cc --- a/Models/General/TwoToTwoProcessConstructor.cc +++ b/Models/General/TwoToTwoProcessConstructor.cc @@ -1,641 +1,644 @@ // -*- C++ -*- // // TwoToTwoProcessConstructor.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 TwoToTwoProcessConstructor class. // #include "TwoToTwoProcessConstructor.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include using std::stringstream; using namespace Herwig; TwoToTwoProcessConstructor::TwoToTwoProcessConstructor() : Nout_(0), nv_(0), allDiagrams_(true), processOption_(0), scaleChoice_(0), scaleFactor_(1.) {} IBPtr TwoToTwoProcessConstructor::clone() const { return new_ptr(*this); } IBPtr TwoToTwoProcessConstructor::fullclone() const { return new_ptr(*this); } void TwoToTwoProcessConstructor::doinit() { HardProcessConstructor::doinit(); if((processOption_==2 || processOption_==4) && outgoing_.size()!=2) throw InitException() << "Exclusive processes require exactly" << " two outgoing particles but " << outgoing_.size() << "have been inserted in TwoToTwoProcessConstructor::doinit()." << Exception::runerror; if(processOption_==4 && incoming_.size()!=2) throw InitException() << "Exclusive processes require exactly" << " two incoming particles but " << incoming_.size() << "have been inserted in TwoToTwoProcessConstructor::doinit()." << Exception::runerror; Nout_ = outgoing_.size(); PDVector::size_type ninc = incoming_.size(); // exit if nothing to do if(Nout_==0||ninc==0) return; //create vector of initial-state pairs for(PDVector::size_type i = 0; i < ninc; ++i) { for(PDVector::size_type j = 0; j < ninc; ++j) { tPDPair inc = make_pair(incoming_[i], incoming_[j]); if( (inc.first->iSpin() > inc.second->iSpin()) || (inc.first->iSpin() == inc.second->iSpin() && inc.first->id() < inc.second->id()) ) swap(inc.first, inc.second); if( !HPC_helper::duplicateIncoming(inc,incPairs_) ) { incPairs_.push_back(inc); } } } // excluded vertices excludedVertexSet_ = set(excludedVertexVector_.begin(), excludedVertexVector_.end()); } void TwoToTwoProcessConstructor::persistentOutput(PersistentOStream & os) const { os << vertices_ << incoming_ << outgoing_ << allDiagrams_ << processOption_ << scaleChoice_ << scaleFactor_ << excluded_ << excludedExternal_ << excludedVertexVector_ << excludedVertexSet_; } void TwoToTwoProcessConstructor::persistentInput(PersistentIStream & is, int) { is >> vertices_ >> incoming_ >> outgoing_ >> allDiagrams_ >> processOption_ >> scaleChoice_ >> scaleFactor_ >> excluded_ >> excludedExternal_ >> excludedVertexVector_ >> excludedVertexSet_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigTwoToTwoProcessConstructor("Herwig::TwoToTwoProcessConstructor", "Herwig.so"); void TwoToTwoProcessConstructor::Init() { static ClassDocumentation documentation ("TwoToTwoProcessConstructor constructs the possible diagrams for " "a process given the external particles"); static RefVector interfaceIn ("Incoming", "Pointers to incoming particles", &TwoToTwoProcessConstructor::incoming_, -1, false, false, true, false); static RefVector interfaceOut ("Outgoing", "Pointers to incoming particles", &TwoToTwoProcessConstructor::outgoing_, -1, false, false, true, false); static Switch interfaceIncludeAllDiagrams ("IncludeEW", "Switch to decide which diagrams to include in ME calc.", &TwoToTwoProcessConstructor::allDiagrams_, true, false, false); static SwitchOption interfaceIncludeAllDiagramsNo (interfaceIncludeAllDiagrams, "No", "Only include QCD diagrams", false); static SwitchOption interfaceIncludeAllDiagramsYes (interfaceIncludeAllDiagrams, "Yes", "Include EW+QCD.", true); static Switch interfaceProcesses ("Processes", "Whether to generate inclusive or exclusive processes", &TwoToTwoProcessConstructor::processOption_, 0, false, false); static SwitchOption interfaceProcessesSingleParticleInclusive (interfaceProcesses, "SingleParticleInclusive", "Require at least one particle from the list of outgoing particles" " in the hard process", 0); static SwitchOption interfaceProcessesTwoParticleInclusive (interfaceProcesses, "TwoParticleInclusive", "Require that both the particles in the hard processes are in the" " list of outgoing particles", 1); static SwitchOption interfaceProcessesExclusive (interfaceProcesses, "Exclusive", "Require that both the particles in the hard processes are in the" " list of outgoing particles in every hard process", 2); static SwitchOption interfaceProcessesVeryExclusive (interfaceProcesses, "VeryExclusive", "Require that both the incoming and outgoing particles in the hard processes are in the" " list of outgoing particles in every hard process", 4); static Switch interfaceScaleChoice ("ScaleChoice", "&TwoToTwoProcessConstructor::scaleChoice_", &TwoToTwoProcessConstructor::scaleChoice_, 0, false, false); static SwitchOption interfaceScaleChoiceDefault (interfaceScaleChoice, "Default", "Use if sHat if intermediates all colour neutral, otherwise the transverse mass", 0); static SwitchOption interfaceScaleChoicesHat (interfaceScaleChoice, "sHat", "Always use sHat", 1); static SwitchOption interfaceScaleChoiceTransverseMass (interfaceScaleChoice, "TransverseMass", "Always use the transverse mass", 2); static SwitchOption interfaceScaleChoiceGeometicMean (interfaceScaleChoice, "MaxMT", "Use the maximum of m^2+p_T^2 for the two particles", 3); static Parameter interfaceScaleFactor ("ScaleFactor", "The prefactor used in the scale calculation. The scale used is" " that defined by scaleChoice multiplied by this prefactor", &TwoToTwoProcessConstructor::scaleFactor_, 1.0, 0.0, 10.0, false, false, Interface::limited); static RefVector interfaceExcluded ("Excluded", "Particles which are not allowed as intermediates", &TwoToTwoProcessConstructor::excluded_, -1, false, false, true, false, false); static RefVector interfaceExcludedExternal ("ExcludedExternal", "Particles which are not allowed as outgoing particles", &TwoToTwoProcessConstructor::excludedExternal_, -1, false, false, true, false, false); static RefVector interfaceExcludedVertices ("ExcludedVertices", "Vertices which are not included in the 2 -> 2 scatterings", &TwoToTwoProcessConstructor::excludedVertexVector_, -1, false, false, true, true, false); } void TwoToTwoProcessConstructor::constructDiagrams() { if(incPairs_.empty() || outgoing_.empty() || !subProcess() ) return; nv_ = model()->numberOfVertices(); //make sure vertices are initialised for(unsigned int ix = 0; ix < nv_; ++ix ) { VertexBasePtr vertex = model()->vertex(ix); if(excludedVertexSet_.find(vertex) != excludedVertexSet_.end()) continue; vertices_.push_back(vertex); } nv_ = vertices_.size(); //Create necessary diagrams vector::size_type is; PDVector::size_type os; for(is = 0; is < incPairs_.size(); ++is) { tPDPair ppi = incPairs_[is]; for(os = 0; os < Nout_; ++os) { long fs = outgoing_[os]->id(); for(size_t iv = 0; iv < nv_; ++iv) { tVertexBasePtr vertexA = vertices_[iv]; - //This skips an effective vertex and the EW ones if // we only want the strong diagrams if( !allDiagrams_ && vertexA->orderInGs() == 0 ) continue; if(vertexA->getNpoint() == 3) { //scattering diagrams createTChannels(ppi, fs, vertexA); //resonance diagrams if( vertexA->isIncoming(ppi.first) && vertexA->isIncoming(ppi.second) ) createSChannels(ppi, fs, vertexA); } - else + else { makeFourPointDiagrams(ppi.first->id(), ppi.second->id(), fs, vertexA); + } } } } // need to find all of the diagrams that relate to the same process // first insert them into a map which uses the '<' operator // to sort the diagrams multiset grouped; HPDVector::iterator dit = processes_.begin(); HPDVector::iterator dend = processes_.end(); for( ; dit != dend; ++dit) { grouped.insert(*dit); } assert( processes_.size() == grouped.size() ); processes_.clear(); typedef multiset::const_iterator set_iter; set_iter it = grouped.begin(), iend = grouped.end(); while( it != iend ) { pair range = grouped.equal_range(*it); set_iter itb = range.first; HPDVector process; for( ; itb != range.second; ++itb ) { process.push_back(*itb); } // if inclusive enforce the exclusivity if(processOption_==2 || processOption_==4) { if(!((process[0].outgoing. first==outgoing_[0]->id()&& process[0].outgoing.second==outgoing_[1]->id())|| (process[0].outgoing. first==outgoing_[1]->id()&& process[0].outgoing.second==outgoing_[0]->id()))) { process.clear(); it = range.second; continue; } if(processOption_==4) { if(!((process[0].incoming. first==incoming_[0]->id()&& process[0].incoming.second==incoming_[1]->id())|| (process[0].incoming. first==incoming_[1]->id()&& process[0].incoming.second==incoming_[0]->id()))) { process.clear(); it = range.second; continue; } } } // check no zero width s-channel intermediates for( dit=process.begin(); dit != process.end(); ++dit) { tPDPtr out1 = getParticleData(dit->outgoing.first ); tPDPtr out2 = getParticleData(dit->outgoing.second); if(dit->channelType == HPDiagram::sChannel && dit->intermediate->width()==ZERO && dit->intermediate->mass() > out1->mass()+ out2->mass()) { tPDPtr in1 = getParticleData(dit->incoming.first ); tPDPtr in2 = getParticleData(dit->incoming.second); throw Exception() << "Process with zero width resonant intermediates\n" << dit->intermediate->PDGName() << " can be on-shell in the process " << in1 ->PDGName() << " " << in2->PDGName() << " -> " << out1->PDGName() << " " << out2->PDGName() << " but has zero width.\nEither set the width, enable " << "calculation of its decays, and hence the width,\n" << "or disable it as a potential intermediate using\n" << "insert " << fullName() << ":Excluded 0 " << dit->intermediate->fullName() << "\n---\n" << Exception::runerror; } } if(find(excludedExternal_.begin(),excludedExternal_.end(), getParticleData(process[0].outgoing. first))!=excludedExternal_.end()) { process.clear(); it = range.second; continue; } if(find(excludedExternal_.begin(),excludedExternal_.end(), getParticleData(process[0].outgoing.second))!=excludedExternal_.end()) { process.clear(); it = range.second; continue; } // finally if the process is allow assign the colour flows for(unsigned int ix=0;ix inc = make_pair(inpp.first->id(), inpp.second->id()); tPDSet offshells = search(vertex, inpp.first->id(), incoming, inpp.second->id(), incoming, outgoing); tPDSet::const_iterator it; for(it = offshells.begin(); it != offshells.end(); ++it) { if(find(excluded_.begin(),excluded_.end(),*it)!=excluded_.end()) continue; for(size_t iv = 0; iv < nv_; ++iv) { tVertexBasePtr vertexB = vertices_[iv]; if( vertexB->getNpoint() != 3) continue; if( !allDiagrams_ && vertexB->orderInGs() == 0 ) continue; tPDSet final; if( vertexB->isOutgoing(getParticleData(fs)) && vertexB->isIncoming(*it) ) final = search(vertexB, (*it)->id(), incoming, fs, outgoing, outgoing); //Now make diagrams if(!final.empty()) makeDiagrams(inc, fs, final, *it, HPDiagram::sChannel, make_pair(vertex, vertexB), make_pair(true,true)); } } } void TwoToTwoProcessConstructor:: createTChannels(tPDPair inpp, long fs, tVertexBasePtr vertex) { pair inc = make_pair(inpp.first->id(), inpp.second->id()); //first try a with c tPDSet offshells = search(vertex, inpp.first->id(), incoming, fs, outgoing, outgoing); tPDSet::const_iterator it; for(it = offshells.begin(); it != offshells.end(); ++it) { if(find(excluded_.begin(),excluded_.end(),*it)!=excluded_.end()) continue; for(size_t iv = 0; iv < nv_; ++iv) { tVertexBasePtr vertexB = vertices_[iv]; if( vertexB->getNpoint() != 3 ) continue; if( !allDiagrams_ && vertexB->orderInGs() == 0 ) continue; tPDSet final; if( vertexB->isIncoming(inpp.second) ) final = search(vertexB, inc.second, incoming, (*it)->id(), incoming, outgoing); if( !final.empty() ) makeDiagrams(inc, fs, final, *it, HPDiagram::tChannel, make_pair(vertex, vertexB), make_pair(true,true)); } } //now try b with c offshells = search(vertex, inpp.second->id(), incoming, fs, outgoing, incoming); for(it = offshells.begin(); it != offshells.end(); ++it) { if(find(excluded_.begin(),excluded_.end(),*it)!=excluded_.end()) continue; for(size_t iv = 0; iv < nv_; ++iv) { tVertexBasePtr vertexB = vertices_[iv]; if( vertexB->getNpoint() != 3 ) continue; if( !allDiagrams_ && vertexB->orderInGs() == 0 ) continue; tPDSet final; if( vertexB->isIncoming(inpp.first) ) final = search(vertexB, inc.first, incoming, (*it)->id(), outgoing, outgoing); if( !final.empty() ) makeDiagrams(inc, fs, final, *it, HPDiagram::tChannel, make_pair(vertexB, vertex), make_pair(true, false)); } } } void TwoToTwoProcessConstructor::makeFourPointDiagrams(long parta, long partb, long partc, VBPtr vert) { if(processOption_>=1) { PDVector::const_iterator loc = find(outgoing_.begin(),outgoing_.end(), getParticleData(partc)); if(loc==outgoing_.end()) return; } tPDSet ext = search(vert, parta, incoming, partb,incoming, partc, outgoing); if( ext.empty() ) return; IDPair in(parta, partb); for(tPDSet::const_iterator iter=ext.begin(); iter!=ext.end(); ++iter) { if(processOption_>=1) { PDVector::const_iterator loc = find(outgoing_.begin(),outgoing_.end(), *iter); if(loc==outgoing_.end()) continue; } HPDiagram nhp(in,make_pair(partc, (*iter)->id())); nhp.vertices = make_pair(vert, vert); nhp.channelType = HPDiagram::fourPoint; fixFSOrder(nhp); + if(!checkOrder(nhp)) continue; if( !duplicate(nhp, processes_) ) processes_.push_back(nhp); } } void TwoToTwoProcessConstructor::makeDiagrams(IDPair in, long out1, const tPDSet & out2, PDPtr inter, HPDiagram::Channel chan, VBPair vertexpair, BPair cross) { if(processOption_>=1) { PDVector::const_iterator loc = find(outgoing_.begin(),outgoing_.end(), getParticleData(out1)); if(loc==outgoing_.end()) return; } for(tPDSet::const_iterator it = out2.begin(); it != out2.end(); ++it) { if(processOption_>=1) { PDVector::const_iterator loc = find(outgoing_.begin(),outgoing_.end(), *it); if(loc==outgoing_.end()) continue; } HPDiagram nhp( in,make_pair(out1, (*it)->id()) ); nhp.intermediate = inter; nhp.vertices = vertexpair; nhp.channelType = chan; nhp.ordered = cross; fixFSOrder(nhp); + if(!checkOrder(nhp)) continue; if( !duplicate(nhp, processes_) ) processes_.push_back(nhp); } } set TwoToTwoProcessConstructor::search(VBPtr vertex, long part1, direction d1, long part2, direction d2, direction d3) { if(vertex->getNpoint() != 3) return tPDSet(); if(d1 == incoming && getParticleData(part1)->CC()) part1 = -part1; if(d2 == incoming && getParticleData(part2)->CC()) part2 = -part2; vector ext; tPDSet third; for(unsigned int ix = 0;ix < 3; ++ix) { vector pdlist = vertex->search(ix, part1); ext.insert(ext.end(), pdlist.begin(), pdlist.end()); } for(unsigned int ix = 0; ix < ext.size(); ix += 3) { long id0 = ext.at(ix); long id1 = ext.at(ix+1); long id2 = ext.at(ix+2); int pos; if((id0 == part1 && id1 == part2) || (id0 == part2 && id1 == part1)) pos = ix + 2; else if((id0 == part1 && id2 == part2) || (id0 == part2 && id2 == part1)) pos = ix + 1; else if((id1 == part1 && id2 == part2) || (id1 == part2 && id2 == part1)) pos = ix; else pos = -1; if(pos >= 0) { tPDPtr p = getParticleData(ext[pos]); if(d3 == incoming && p->CC()) p = p->CC(); third.insert(p); } } return third; } set TwoToTwoProcessConstructor::search(VBPtr vertex, long part1, direction d1, long part2, direction d2, long part3, direction d3, direction d4) { if(vertex->getNpoint() != 4) return tPDSet(); if(d1 == incoming && getParticleData(part1)->CC()) part1 = -part1; if(d2 == incoming && getParticleData(part2)->CC()) part2 = -part2; if(d3 == incoming && getParticleData(part3)->CC()) part3 = -part3; vector ext; tPDSet fourth; for(unsigned int ix = 0;ix < 4; ++ix) { vector pdlist = vertex->search(ix, part1); ext.insert(ext.end(), pdlist.begin(), pdlist.end()); } for(unsigned int ix = 0;ix < ext.size(); ix += 4) { long id0 = ext.at(ix); long id1 = ext.at(ix + 1); long id2 = ext.at(ix + 2); long id3 = ext.at(ix + 3); int pos; if((id0 == part1 && id1 == part2 && id2 == part3) || (id0 == part1 && id1 == part3 && id2 == part2) || (id0 == part2 && id1 == part1 && id2 == part3) || (id0 == part2 && id1 == part3 && id2 == part1) || (id0 == part3 && id1 == part1 && id2 == part2) || (id0 == part3 && id1 == part2 && id2 == part1)) pos = ix + 3; else if((id0 == part1 && id1 == part2 && id3 == part3) || (id0 == part1 && id1 == part3 && id3 == part2) || (id0 == part2 && id1 == part1 && id3 == part3) || (id0 == part2 && id1 == part3 && id3 == part1) || (id0 == part3 && id1 == part1 && id3 == part2) || (id0 == part3 && id1 == part2 && id3 == part1)) pos = ix + 2; else if((id0 == part1 && id2 == part2 && id3 == part3) || (id0 == part1 && id2 == part3 && id3 == part2) || (id0 == part2 && id2 == part1 && id3 == part3) || (id0 == part2 && id2 == part3 && id3 == part1) || (id0 == part3 && id2 == part1 && id3 == part2) || (id0 == part3 && id2 == part2 && id3 == part1)) pos = ix + 1; else if((id1 == part1 && id2 == part2 && id3 == part3) || (id1 == part1 && id2 == part3 && id3 == part2) || (id1 == part2 && id2 == part1 && id3 == part3) || (id1 == part2 && id2 == part3 && id3 == part1) || (id1 == part3 && id2 == part1 && id3 == part2) || (id1 == part3 && id2 == part2 && id3 == part1)) pos = ix; else pos = -1; if(pos >= 0) { tPDPtr p = getParticleData(ext[pos]); if(d4 == incoming && p->CC()) p = p->CC(); fourth.insert(p); } } return fourth; } void TwoToTwoProcessConstructor::createMatrixElement(const HPDVector & process) const { if ( process.empty() ) return; // external particles tcPDVector extpart(4); extpart[0] = getParticleData(process[0].incoming.first); extpart[1] = getParticleData(process[0].incoming.second); extpart[2] = getParticleData(process[0].outgoing.first); extpart[3] = getParticleData(process[0].outgoing.second); // create the object string objectname ("/Herwig/MatrixElements/"); string classname = MEClassname(extpart, objectname); GeneralHardMEPtr matrixElement = dynamic_ptr_cast (generator()->preinitCreate(classname, objectname)); if( !matrixElement ) { std::stringstream message; message << "TwoToTwoProcessConstructor::createMatrixElement " << "- No matrix element object could be created for " << "the process " << extpart[0]->PDGName() << " " << extpart[0]->iSpin() << "," << extpart[1]->PDGName() << " " << extpart[1]->iSpin() << "->" << extpart[2]->PDGName() << " " << extpart[2]->iSpin() << "," << extpart[3]->PDGName() << " " << extpart[3]->iSpin() << ". Constructed class name: \"" << classname << "\""; generator()->logWarning(TwoToTwoProcessConstructorError(message.str(),Exception::warning)); return; } // choice for the scale unsigned int scale; if(scaleChoice_==0) { // check coloured initial and final state bool inColour = ( extpart[0]->coloured() || extpart[1]->coloured()); bool outColour = ( extpart[2]->coloured() || extpart[3]->coloured()); if(inColour&&outColour) { bool coloured = false; for(unsigned int ix=0;ixcoloured()) { coloured = true; break; } } scale = coloured ? 1 : 0; } else { scale = 0; } } else { scale = scaleChoice_-1; } // set the information matrixElement->setProcessInfo(process, colourFlow(extpart), debug(), scale, scaleFactor_); // insert it generator()->preinitInterface(subProcess(), "MatrixElements", subProcess()->MEs().size(), "insert", matrixElement->fullName()); } string TwoToTwoProcessConstructor::MEClassname(const vector & extpart, string & objname) const { string classname("Herwig::ME"); for(vector::size_type ix = 0; ix < extpart.size(); ++ix) { if(ix == 2) classname += "2"; if(extpart[ix]->iSpin() == PDT::Spin0) classname += "s"; else if(extpart[ix]->iSpin() == PDT::Spin1) classname += "v"; else if(extpart[ix]->iSpin() == PDT::Spin1Half) classname += "f"; + else if(extpart[ix]->iSpin() == PDT::Spin3Half) classname += "r"; else if(extpart[ix]->iSpin() == PDT::Spin2) classname += "t"; else { std::stringstream message; message << "MEClassname() : Encountered an unknown spin for " << extpart[ix]->PDGName() << " while constructing MatrixElement " << "classname " << extpart[ix]->iSpin(); generator()->logWarning(TwoToTwoProcessConstructorError(message.str(),Exception::warning)); } } objname += "ME" + extpart[0]->PDGName() + extpart[1]->PDGName() + "2" + extpart[2]->PDGName() + extpart[3]->PDGName(); return classname; } diff --git a/Models/LH/LHFFGVertex.cc b/Models/LH/LHFFGVertex.cc --- a/Models/LH/LHFFGVertex.cc +++ b/Models/LH/LHFFGVertex.cc @@ -1,53 +1,54 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the LHFFGVertex class. // #include "LHFFGVertex.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/StandardModel/StandardModelBase.h" using namespace Herwig; // Static variable needed for the type description system in ThePEG. DescribeNoPIOClass describeHerwigLHFFGVertex("Herwig::LHFFGVertex", "HwLHModel.so"); void LHFFGVertex::Init() { static ClassDocumentation documentation ("The LHFFGVertex class implements the coupling of the quarks" " to the gluon in the Little Higgs model"); } // coupling for FFG vertex void LHFFGVertex::setCoupling(Energy2 q2,tcPDPtr a,tcPDPtr,tcPDPtr) { // check allowed int iferm=abs(a->id()); assert((iferm>=1 && iferm<=6) || iferm==8); // first the overall normalisation if(q2!=_q2last) { _couplast = -strongCoupling(q2); _q2last=q2; } norm(_couplast); left(1.); right(1.); } void LHFFGVertex::doinit() { // PDG codes for the particles for(int ix=1;ix<7;++ix) { addToList(-ix, ix, 21); } addToList(-8, 8, 21); FFVVertex::doinit(); } LHFFGVertex::LHFFGVertex() : _couplast(0.), _q2last(0.*GeV2) { orderInGs(1); orderInGem(0); + colourStructure(ColourStructure::SU3TFUND); } diff --git a/Models/LH/LHFFHVertex.cc b/Models/LH/LHFFHVertex.cc --- a/Models/LH/LHFFHVertex.cc +++ b/Models/LH/LHFFHVertex.cc @@ -1,288 +1,289 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the LHFFHVertex class. // #include "LHFFHVertex.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; void LHFFHVertex::persistentOutput(PersistentOStream & os) const { os << ounit(_coup,1./GeV) << _model; } void LHFFHVertex::persistentInput(PersistentIStream & is, int) { is >> iunit(_coup,1./GeV) >> _model; } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigLHFFHVertex("Herwig::LHFFHVertex", "HwLHModel.so"); void LHFFHVertex::Init() { static ClassDocumentation documentation ("The LHFFHVertex class implements the interaction of the fermions" " and the Higgs bosons in the Little Higgs model"); } LHFFHVertex::LHFFHVertex() : _q2last(0.*GeV2) { orderInGem(1); orderInGs(0); _masslast[0] = 0.*GeV; _masslast[1] = 0.*GeV; _idlast[0] = 0; _idlast[1] = 0; + colourStructure(ColourStructure::DELTA); } void LHFFHVertex::doinit() { // SM like higgs for (int ix=1;ix<=6;++ix) { addToList( -ix, ix, 25); } addToList( -6, 8, 25); addToList( -8, 6, 25); addToList( -8, 8, 25); for(int ix=11;ix<16;ix+=2) { addToList( -ix, ix, 25); } // phi0 for (int ix=1;ix<=6;++ix) { addToList( -ix, ix, 35); } addToList( -6, 8, 35); addToList( -8, 6, 35); for(int ix=11;ix<16;ix+=2) { addToList( -ix, ix, 35); } // phiP for (int ix=1;ix<=6;++ix) { addToList( -ix, ix, 36); } addToList( -6, 8, 36); addToList( -8, 6, 36); for(int ix=11;ix<16;ix+=2) { addToList( -ix, ix, 36); } // phi +/- for(int ix=1;ix<6;ix+=2) { addToList( -ix-1, ix, 37); addToList( -ix , ix+1, -37); } addToList( -8 , 5, 37); addToList( -5 , 8, -37); for(int ix=11;ix<16;ix+=2) { addToList( -ix-1, ix, 37); addToList( -ix , ix+1, -37); } _model = dynamic_ptr_cast(generator()->standardModel()); if(!_model) throw InitException() << "Must be using the LHModel " << " in LHFFPVertex::doinit()" << Exception::runerror; _coup.resize(11); Energy v = _model->vev(); double s0 = _model->sinTheta0(); double sP = _model->sinThetaP(); double sPlus = _model->sinThetaPlus(); double s02 = sqr(s0); double vf = _model->vev()/_model->f(); double xL = sqr(_model->lambda1())/(sqr(_model->lambda1())+sqr(_model->lambda2())); double xR = sqr(_model->lambda1())/sqrt(sqr(_model->lambda1())+sqr(_model->lambda2())); Energy mT = getParticleData(8)->mass(); // lightest higgs couplings // coupling of light SM fermions _coup[0] = (1.-0.5*s02+vf*s0/sqrt(2.)-2./3.*sqr(vf))/v; // couplings to top quark _coup[1] = (1.-0.5*s02+vf*s0/sqrt(2.)-2./3.*sqr(vf)+sqr(vf)*xL*(1.+xL))/v; // couplings to the T quark _coup[2] =-xR*(1.+xL)*vf/mT; // couplings to tT _coup[3] = xR/mT; _coup[4] = vf/v*(1.+xL); // phi 0 // light particles _coup[5] = sqrt(0.5)/v*(vf-sqrt(2.)*s0); // mixed _coup[6] = sqrt(0.5)/v*(vf-sqrt(2.)*s0)*_model->lambda1()/_model->lambda2(); // phi P _coup[7] = Complex(0.,1.)*sqrt(0.5)/v*(vf-sqrt(2.)*sP); _coup[8] = Complex(0.,1.)*sqrt(0.5)/v*(vf-sqrt(2.)*sP)*_model->lambda1()/_model->lambda2(); // phi +/- _coup[9] = -sqrt(0.5)/v*(vf-2.*sPlus); _coup[9] = -sqrt(0.5)/v*(vf-2.*sPlus)*_model->lambda1()/_model->lambda2(); FFSVertex::doinit(); } void LHFFHVertex::setCoupling(Energy2 q2,tcPDPtr a,tcPDPtr b, tcPDPtr c) { int iferm=abs(a->id()); int ianti=abs(b->id()); // left and right couplings set to one left (1.); right(1.); // first the overall normalisation if(q2!=_q2last||_idlast[0]!=iferm||_idlast[1]!=ianti) { _q2last = q2; _idlast[0] = iferm; if(_idlast[0]==8) _idlast[0]=6; assert((_idlast[0]>=1 && _idlast[0]<=6 ) || (_idlast[0]>=11 && _idlast[0]<=16)); if(iferm==_idlast[0]) _masslast[0] = _model->mass(q2,a); else _masslast[0] = _model->mass(q2,getParticleData(ParticleID::t)); _idlast[1] = ianti; if(_idlast[1]==8) _idlast[1]=6; assert((_idlast[1]>=1 && _idlast[1]<=6 ) || (_idlast[1]>=11 && _idlast[1]<=16)); if(_idlast[0]!=_idlast[1]) { if(ianti==_idlast[1]) _masslast[1] = _model->mass(q2,a); else _masslast[1] = _model->mass(q2,getParticleData(ParticleID::t)); } else { _masslast[1] = _masslast[0]; } } // SM like higgs if(c->id()==ParticleID::h0) { if(iferm==ianti) { if((iferm>=1 && iferm<=5 ) || (iferm>=11 && iferm<=16)) { norm(-Complex(_coup[0]*_masslast[0])); } else if(iferm==6) { norm(-Complex(_coup[1]*_masslast[0])); } else if(iferm==8) { norm(-Complex(_coup[2]*a->mass())); } else assert(false); } else { assert( (iferm == 6 && ianti == 8 ) || (ianti == 6 && iferm == 8 )); Complex cleft,cright; if(iferm==6) { cleft = -_coup[3]*b->mass(); cright = -_coup[4]*_masslast[0]; } else { cleft = -_coup[3]*a->mass(); cright = -_coup[4]*_masslast[0]; } if(b->id()==ParticleID::tbar || c->id()==ParticleID::tbar) { cright = conj(cleft); cleft = 0.; } left (cleft ); right(cright); norm(1.); } } else if(c->id()==ParticleID::H0) { if(iferm==ianti) { if((iferm>=1 && iferm<=6 ) || (iferm>=11 && iferm<=16)) { norm(-Complex(_coup[5]*_masslast[0])); } else assert(false); } else { assert( (iferm == 6 && ianti == 8 ) || (iferm == 8 && ianti == 6 ) ); Complex cleft = Complex(_coup[6]*_masslast[0]); Complex cright = 0.; if(b->id()==ParticleID::tbar || c->id()==ParticleID::tbar) { cright = conj(cleft); cleft = 0.; } left (cleft ); right(cright); norm(1.); } } else if(c->id()==ParticleID::A0) { left(-1.); right(1.); if(iferm==ianti) { if((iferm>=1 && iferm<=6 ) || (iferm>=11 && iferm<=16)) { if(iferm%2==0) norm(-Complex( _coup[7]*_masslast[0])); else norm(-Complex(-_coup[7]*_masslast[0])); } else assert(false); } else { assert( (iferm == 6 && ianti == 8 ) || (iferm == 8 && ianti == 6 )); Complex cleft = Complex(_coup[8]*_masslast[0]); Complex cright = 0.; if(b->id()==ParticleID::tbar || c->id()==ParticleID::tbar) { cright = conj(cleft); cleft = 0.; } left (cleft ); right(cright); norm(1.); } } else if(c->id()==ParticleID::Hplus) { norm(1.); Complex cleft(0.),cright(0.); if(iferm%2==0) { if(iferm==ParticleID::t) { cleft = _masslast[0]*_coup[ 9]; } else { cleft = _masslast[0]*_coup[10]; cright = _masslast[1]*_coup[10]; } } else { if(ianti==ParticleID::t) { cleft = _masslast[1]*_coup[ 9]; } else { cleft = _masslast[1]*_coup[10]; cright = _masslast[0]*_coup[10]; } } left ( cleft); right(cright); } else if(c->id()==ParticleID::Hminus) { norm(1.); Complex cleft(0.),cright(0.); if(iferm%2==0) { if(iferm==ParticleID::t) { cright = _masslast[0]*_coup[ 9]; } else { cright = _masslast[0]*_coup[10]; cleft = _masslast[1]*_coup[10]; } } else { if(ianti==ParticleID::t) { cright = _masslast[1]*_coup[ 9]; } else { cright = _masslast[1]*_coup[10]; cleft = _masslast[0]*_coup[10]; } } left ( cleft); right(cright); } } diff --git a/Models/LH/LHFFPVertex.cc b/Models/LH/LHFFPVertex.cc --- a/Models/LH/LHFFPVertex.cc +++ b/Models/LH/LHFFPVertex.cc @@ -1,156 +1,157 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the LHFFPVertex class. // #include "LHFFPVertex.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; LHFFPVertex::LHFFPVertex() : _couplast(0.), _q2last(-1.*GeV2) { // order in strong and em coupling orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::DELTA); } void LHFFPVertex::persistentOutput(PersistentOStream & os) const { os << _charge << _gl << _gr; } void LHFFPVertex::persistentInput(PersistentIStream & is, int) { is >> _charge >> _gl >> _gr; } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigLHFFPVertex("Herwig::LHFFPVertex", "HwLHModel.so"); void LHFFPVertex::Init() { static ClassDocumentation documentation ("The LHFFPVertex class implements the couplings of the fermions to" " the photon and A_H in the Little Higgs model"); } void LHFFPVertex::doinit() { // the quarks for(int ix=1;ix<7;++ix) { addToList(-ix, ix, 22); addToList(-ix, ix, 32); } addToList( -8, 8, 22); addToList( -8, 8, 32); addToList( -6, 8, 32); addToList( -8, 6, 32); // the leptons for(int ix=11;ix<17;++ix) { if(ix%2!=0) addToList(-ix, ix, 22); addToList(-ix, ix, 32); } FFVVertex::doinit(); cLHModelPtr model = dynamic_ptr_cast(generator()->standardModel()); if(!model) throw InitException() << "Must be using the LHModel " << " in LHFFPVertex::doinit()" << Exception::runerror; // charges _charge.resize(17); for(int ix=1;ix<4;++ix) { _charge[2*ix-1] = model->ed(); _charge[2*ix ] = model->eu(); _charge[2*ix+9 ] = model->ee(); _charge[2*ix+10] = model->enu(); } _charge[8] = model->eu(); // couplings for the heavy photon taken from table IX double cw = sqrt(1.-sin2ThetaW()); double xL = sqr(model->lambda1())/(sqr(model->lambda1())+sqr(model->lambda2())); double cp2 = sqr(model->cosThetaPrime()); double yu = -0.4; double ye = 0.6; // prefactor after removal of -e double pre = -0.5/cw/model->cosThetaPrime()/model->sinThetaPrime(); // down type quarks double gvd = pre*(2.*yu+11./15.+cp2/6); double gad = pre*(-0.2+0.5*cp2); // up type quarks double gvu = pre*(2.*yu+17./15.-5./6.*cp2); double gau = pre*( 0.2-0.5*cp2); // charged leptons double gve = pre*(2.*ye-9./5.+1.5*cp2); double gae = pre*(-0.2+0.5*cp2); // neutrinos double gvv = pre*(-0.2+0.5*cp2); double gav = pre*( 0.2-0.5*cp2); // light top double gvtll = pre*(2.*yu+17./15.-5./6.*cp2-0.2*xL); double gatll = pre*(0.2-0.5*cp2-0.2*xL); // mixed top double gvtlh = pre*0.2*model->lambda1()*model->lambda2()/ (sqr(model->lambda1())+sqr(model->lambda2())); double gatlh = gvtlh; // heavy top double gvthh = pre*(2.*yu+14./15.-4./3.*cp2+0.2*xL); double gathh = pre*0.2*xL; _gl.resize(17); _gr.resize(17); for(unsigned int ix=1;ix<4;++ix) { _gr[2*ix-1] = gvd+gad; _gl[2*ix-1] = gvd-gad; _gr[2*ix ] = gvu+gau; _gl[2*ix ] = gvu-gau; _gr[2*ix+9 ] = gve+gae; _gl[2*ix+9 ] = gve-gae; _gr[2*ix+10] = gvv+gav; _gl[2*ix+10] = gvv-gav; } // light top _gr[6] = gvtll+gatll; _gl[6] = gvtll-gatll; // mixed top _gr[7] = gvtlh+gatlh; _gl[7] = gvtlh-gatlh; // heavy top _gr[8] = gvthh+gathh; _gl[8] = gvthh-gathh; } // coupling for FFP vertex void LHFFPVertex::setCoupling(Energy2 q2,tcPDPtr a,tcPDPtr b, tcPDPtr c) { int iferm=abs(a->id()); assert((iferm>=1 && iferm<=6)||(iferm>=11 &&iferm<=16)||iferm==8); // first the overall normalisation if(q2!=_q2last) { _couplast = -electroMagneticCoupling(q2); _q2last=q2; } norm(_couplast); // the left and right couplings // photon if(c->id()==ParticleID::gamma) { left (_charge[iferm]); right(_charge[iferm]); } // heavy photon else { assert(c->id()==32); int ianti = abs(b->id()); if(ianti==iferm) { left (_gl[iferm]); right(_gr[iferm]); } else { left (_gl[7]); right(_gr[7]); } } } diff --git a/Models/LH/LHFFWVertex.cc b/Models/LH/LHFFWVertex.cc --- a/Models/LH/LHFFWVertex.cc +++ b/Models/LH/LHFFWVertex.cc @@ -1,180 +1,181 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the LHFFWVertex class. // #include "LHFFWVertex.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/Models/StandardModel/StandardCKM.h" using namespace Herwig; LHFFWVertex::LHFFWVertex() : _ckm(3,vector(3,0.0)), _couplast(0.), _q2last(0.*GeV2), _corrL(0.),_corrH(0.),_tcorrL(0.),_tcorrH(0.),_tHcorrL(0.), _tHcorrH(0.) { // order of vertex in couplings orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::DELTA); } void LHFFWVertex::persistentOutput(PersistentOStream & os) const { os << _ckm << _corrL << _corrH << _tcorrL << _tcorrH << _tHcorrL << _tHcorrH; } void LHFFWVertex::persistentInput(PersistentIStream & is, int) { is >> _ckm >> _corrL >> _corrH >> _tcorrL >> _tcorrH >> _tHcorrL >> _tHcorrH; } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigLHFFWVertex("Herwig::LHFFWVertex", "HwLHModel.so"); void LHFFWVertex::Init() { static ClassDocumentation documentation ("The LHFFWVertex class implements the vertices for" " the coupling of the W and heavy W to the Standard Model " "fermions and the heavy top quark in the Little Higgs model"); } void LHFFWVertex::doinit() { // particles for outgoing W- // quarks for(int ix=1;ix<6;ix+=2) { for(int iy=2;iy<7;iy+=2) { addToList(-ix, iy, -24); addToList(-ix, iy, -34); } } // leptons for(int ix=11;ix<17;ix+=2) { addToList(-ix, ix+1, -24); addToList(-ix, ix+1, -34); } // particles for outgoing W+ // quarks for(int ix=2;ix<7;ix+=2) { for(int iy=1;iy<6;iy+=2) { addToList(-ix, iy, 24); addToList(-ix, iy, 34); } } // leptons for(int ix=11;ix<17;ix+=2) { addToList(-ix-1, ix, 24); addToList(-ix-1, ix, 34); } // couplings to new heavy quark addToList(-5, 8, -24); addToList(-5, 8, -34); addToList(-8, 5, 24); addToList(-8, 5, 34); ThePEG::Helicity::FFVVertex::doinit(); cLHModelPtr model = dynamic_ptr_cast(generator()->standardModel()); if(!model) throw InitException() << "Must be using the LHModel " << " in LHFFWVertex::doinit()" << Exception::runerror; // cast the CKM object to the HERWIG one ThePEG::Ptr::transient_const_pointer hwCKM=ThePEG::dynamic_ptr_cast< ThePEG::Ptr:: transient_const_pointer>(generator()->standardModel()->CKM()); if(!hwCKM) throw InitException() << "Must have access to the Herwig::StandardCKM object" << "for the CKM matrix in LHFFWVertex::doinit()" << Exception::runerror; _ckm = hwCKM->getUnsquaredMatrix(model->families()); // compute the correction factors double s2(sqr(model->sinTheta())),c2(sqr(model->cosTheta())); double vf(model->vev()/model->f()); double xL = sqr(model->lambda1())/(sqr(model->lambda1())+sqr(model->lambda2())); // from Table VIII with -sign to agree with our SM conventions _corrL = 1.-0.5*sqr(vf)*c2*(c2-s2); _corrH = -model->cosTheta()/model->sinTheta(); _tcorrL = 1.-0.5*sqr(vf)*(c2*(c2-s2)+sqr(xL)); _tcorrH = -model->cosTheta()/model->sinTheta(); _tHcorrL = -vf*xL; _tHcorrH = vf*xL*model->cosTheta()/model->sinTheta(); } void LHFFWVertex::setCoupling(Energy2 q2, tcPDPtr a, tcPDPtr b, tcPDPtr c) { // first the overall normalisation if(q2!=_q2last) { _couplast = -sqrt(0.5)*weakCoupling(q2); _q2last=q2; } norm(_couplast); right(0.); // the left and right couplings int iferm=abs(a->id()); int ianti=abs(b->id()); bool heavy(false); if(iferm==8) { iferm = 6; heavy = true; } if(ianti==8) { ianti = 6; heavy = true; } // quarks if(iferm>=1 && iferm <=6) { int iu,id; // up type first if(iferm%2==0) { iu = iferm/2; id = (ianti+1)/2; } // down type first else { iu = ianti/2; id = (iferm+1)/2; } assert( iu>=1 && iu<=3 && id>=1 && id<=3); left(_ckm[iu-1][id-1]); } // leptons else if(iferm>=11 && iferm <=16) { left(1.); } else assert(false); // correction factors // light W if(abs(c->id())==ParticleID::Wplus) { // light quarks or leptons if(iferm<6&&ianti<6) { left(_corrL*left()); } // light top quark else if(!heavy) { left(_tcorrL*left()); } // heavy top quark else { left(_tHcorrL*left()); } } // heavy W else { // light quarks or leptons if(iferm<6&&ianti<6) { left(_corrH*left()); } // light top quark else if(!heavy) { left(_tcorrH*left()); } // heavy top quark else { left(_tHcorrH*left()); } } } diff --git a/Models/LH/LHFFZVertex.cc b/Models/LH/LHFFZVertex.cc --- a/Models/LH/LHFFZVertex.cc +++ b/Models/LH/LHFFZVertex.cc @@ -1,181 +1,182 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the LHFFZVertex class. // #include "LHFFZVertex.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; void LHFFZVertex::persistentOutput(PersistentOStream & os) const { os << _gl << _gr << _glH << _grH; } void LHFFZVertex::persistentInput(PersistentIStream & is, int) { is >> _gl >> _gr >> _glH >> _grH; } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigLHFFZVertex("Herwig::LHFFZVertex", "HwLHModel.so"); void LHFFZVertex::Init() { static ClassDocumentation documentation ("The LHFFZVertex class implements the couplings of the Z and Z_H in" " the Little Higgs model to the fermions, both of the Standard Model" " and the additional heavy top."); } LHFFZVertex::LHFFZVertex() : _couplast(0.0), _q2last(0.*GeV2) { // set order in the couplings orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::DELTA); } void LHFFZVertex::doinit() { for(int ib=23;ib<34;ib+=10) { // the quarks for(int ix=1;ix<7;++ix) { addToList(-ix, ix, ib); } addToList( -8, 8, ib); addToList( -6, 8, ib); addToList( -8, 6, ib); // the leptons for(int ix=11;ix<17;++ix) { addToList(-ix, ix, ib); } } FFVVertex::doinit(); cLHModelPtr model = dynamic_ptr_cast(generator()->standardModel()); if(!model) throw InitException() << "Must be using the LHModel " << " in LHFFZVertex::doinit()" << Exception::runerror; double sw2(sin2ThetaW()); double sw(sqrt(sw2)),cw(sqrt(1.-sw2)); double pre =-0.5/sw/cw; double s (model->sinTheta() ),c (model->cosTheta() ); double sp(model->sinThetaPrime()),cp(model->cosThetaPrime()); double sp2(sqr(sp)),cp2(sqr(cp)); // from Eqn A35 double xW(-0.5/cw*s*c*(sqr(c)-sqr(s))); double xB(-2.5/sw*sp*cp*(cp2-sp2)); double yu = -0.4, ye = 0.6; double vf(model->vev()/model->f()); double xL(sqr(model->lambda1())/(sqr(model->lambda1())+sqr(model->lambda2()))); double vu = pre*( 0.5-4./3.*sw2-sqr(vf)*(+0.5*cw*xW*c/s +sw*xB/sp/cp*(2.*yu+7./15. -cp2/6.))); double vd = pre*(-0.5+2./3.*sw2-sqr(vf)*(-0.5*cw*xW*c/s +sw*xB/sp/cp*(2.*yu+11./15. +cp2/6.))); double ve = pre*(-0.5+2.* sw2-sqr(vf)*(-0.5*cw*xW*c/s +sw*xB/sp/cp*(2.*ye-9./5. +1.5*cp2))); double vv = pre*(+0.5 -sqr(vf)*(+0.5*cw*xW*c/s +sw*xB/sp/cp*( ye-4./5. +0.5*cp2))); double au = pre*(-0.5-sqr(vf)*(-0.5*cw*xW*c/s+sw*xB/sp/cp*(0.2-0.5*cp2))); double ad = pre*( 0.5-sqr(vf)*(+0.5*cw*xW*c/s-sw*xB/sp/cp*(0.2-0.5*cp2))); double ae = pre*( 0.5-sqr(vf)*(+0.5*cw*xW*c/s-sw*xB/sp/cp*(0.2-0.5*cp2))); double av = pre*(-0.5-sqr(vf)*(-0.5*cw*xW*c/s+sw*xB/sp/cp*(0.2-0.5*cp2))); double vtl = pre*( 0.5-4./3.*sw2-sqr(vf)*(-0.5*sqr(xL)+0.5*cw*xW*c/s +sw*xB/sp/cp*(2.*yu+9./5.-1.5*cp2 +(7./15.-2.*cp2/3.)*xL))); double atl = pre*(-0.5 -sqr(vf)*(+0.5*sqr(xL)-0.5*cw*xW*c/s +sw*xB/sp/cp*(+0.2-0.5*cp2-0.2*xL))); double vth = 2./3.*sw/cw; double ath = 0.; double vtm = 0.25*xL*vf/cw/sw; double atm = -vtm; _gl.resize(17); _gr.resize(17); for(unsigned ix=1;ix<4;++ix) { _gl[2*ix-1] = vd - ad; _gl[2*ix ] = vu - au; _gl[2*ix+9 ] = ve - ae; _gl[2*ix+10] = vv - av; _gr[2*ix-1] = vd + ad; _gr[2*ix ] = vu + au; _gr[2*ix+9 ] = ve + ae; _gr[2*ix+10] = vv + av; } _gl[6] = vtl - atl; _gr[6] = vtl + atl; _gl[7] = vtm - atm; _gr[7] = vtm + atm; _gl[8] = vth - ath; _gr[8] = vth + ath; // heavy Z double fact = 0.25*c/s/sw; vu = fact; vd = -fact; ve = -fact; vv = fact; au = -fact; ad = fact; ae = fact; av = -fact; vtl = fact; atl = -fact; vth = 0.; ath = 0.; vtm = -0.25*xL*vf*c/s/sw; atm = -vtm; _glH.resize(17); _grH.resize(17); for(unsigned ix=1;ix<4;++ix) { _glH[2*ix-1] = vd - ad; _glH[2*ix ] = vu - au; _glH[2*ix+9 ] = ve - ae; _glH[2*ix+10] = vv - av; _grH[2*ix-1] = vd + ad; _grH[2*ix ] = vu + au; _grH[2*ix+9 ] = ve + ae; _grH[2*ix+10] = vv + av; } _glH[6] = vtl - atl; _grH[6] = vtl + atl; _glH[7] = vtm - atm; _grH[7] = vtm + atm; _glH[8] = vth - ath; _grH[8] = vth + ath; } void LHFFZVertex::setCoupling(Energy2 q2,tcPDPtr a,tcPDPtr b,tcPDPtr c) { // first the overall normalisation if(q2!=_q2last) { _couplast = electroMagneticCoupling(q2); _q2last=q2; } norm(_couplast); // the left and right couplings int iferm = abs(a->id()); int ianti = abs(b->id()); assert((iferm>=1 && iferm<=6)||(iferm>=11 &&iferm<=16)|| iferm == 8); // Z0 if(c->id()==ParticleID::Z0) { if(ianti==iferm) { left (_gl[iferm]); right(_gr[iferm]); } else { left (_gl[7]); right(_gr[7]); } } else { if(ianti==iferm) { left (_glH[iferm]); right(_grH[iferm]); } else { left (_glH[7]); right(_grH[7]); } } } diff --git a/Models/LH/LHWHHVertex.cc b/Models/LH/LHWHHVertex.cc --- a/Models/LH/LHWHHVertex.cc +++ b/Models/LH/LHWHHVertex.cc @@ -1,286 +1,287 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the LHWHHVertex class. // #include "LHWHHVertex.h" #include "LHModel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; LHWHHVertex::LHWHHVertex() : couplast_(0.), q2last_(ZERO), coup_(24) { orderInGs(0); orderInGem(1); // neutral addToList( 22, 37,-37); addToList( 22, 38,-38); addToList( 32, 37,-37); addToList( 32, 38,-38); addToList( 23, 37,-37); addToList( 23, 38,-38); addToList( 33, 37,-37); addToList( 33, 38,-38); addToList( 32, 25, 36); addToList( 32, 35, 36); addToList( 23, 25, 36); addToList( 23, 35, 36); addToList( 33, 25, 36); addToList( 33, 35, 36); // W+ addToList( 24, 25,-37); addToList( 24, 35,-37); addToList( 24, 36,-37); addToList( 24, 37,-38); addToList( 34, 25,-37); addToList( 34, 35,-37); addToList( 34, 36,-37); addToList( 34, 37,-38); // W- addToList(-24, 25, 37); addToList(-24, 35, 37); addToList(-24, 36, 37); addToList(-24,-37, 38); addToList(-34, 25, 37); addToList(-34, 35, 37); addToList(-34, 36, 37); addToList(-34,-37, 38); + colourStructure(ColourStructure::SINGLET); } IBPtr LHWHHVertex::clone() const { return new_ptr(*this); } IBPtr LHWHHVertex::fullclone() const { return new_ptr(*this); } void LHWHHVertex::persistentOutput(PersistentOStream & os) const { os << coup_; } void LHWHHVertex::persistentInput(PersistentIStream & is, int) { is >> coup_; } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigLHWHHVertex("Herwig::LHWHHVertex", "HwLHModel.so"); void LHWHHVertex::Init() { static ClassDocumentation documentation ("The LHWHHVertex class implements the coupling of a pair of Higgs" " bosons to an electroweak gauge boson in the Little Higgs model."); } void LHWHHVertex::doinit() { VSSVertex::doinit(); // model cLHModelPtr model = dynamic_ptr_cast(generator()->standardModel()); if(!model) throw InitException() << "Must be using the LHModel " << " in LHWHHVertex::doinit()" << Exception::runerror; double sw2(sin2ThetaW()); double sw(sqrt(sw2)),cw(sqrt(1.-sw2)); double s (model->sinTheta() ),c (model->cosTheta() ); double sp(model->sinThetaPrime()),cp(model->cosThetaPrime()); double s0 (model->sinTheta0()); double sP (model->sinThetaP()); double sPlus(model->sinThetaPlus()); coup_[ 0] = 0.5/sw*(sqrt(2.)*s0-sPlus); coup_[ 1] = sqrt(0.5)/sw; coup_[ 2] = Complex(0.,1.)/sw*sqrt(0.5); coup_[ 3] = 1./sw; coup_[ 4] = 0.; coup_[ 5] = 0.; coup_[ 6] = 1.; coup_[ 7] = 2.; coup_[ 8] = Complex(0.,0.5)/cw/sw*(sP-2.*s0); coup_[ 9] =-Complex(0.,1.)/cw/sw; coup_[10] =-sw/cw; coup_[11] = (1.-2.*sw2)/cw/sw; coup_[12] =-0.25/sw*(sqr(c)-sqr(s))/s/c*(sqrt(2.)*s0-sPlus); coup_[13] =-sqrt(0.5)/sw*0.5*(sqr(c)-sqr(s))/s/c; coup_[14] =-Complex(0.,1.)*sqrt(0.5)*0.5*(sqr(c)-sqr(s))/s/c; coup_[15] =-0.5*(sqr(c)-sqr(s))/s/c/sw; coup_[16] =-Complex(0.,0.5)/cw*0.5*(sqr(cp)-sqr(sp))/sp/cp*(sP-2.*s0); coup_[17] = Complex(0.,1.)/cw*0.5*(sqr(cp)-sqr(sp))/sp/cp; coup_[18] =-0.5*(sqr(cp)-sqr(sp))/sp/cp/cw; coup_[19] =-0.5*(sqr(cp)-sqr(sp))/sp/cp/cw; coup_[20] =-Complex(0.,0.5)/sw*0.5*(sqr(c)-sqr(s))/s/c*(sP-2.*s0); coup_[21] = Complex(0.,1.)/sw*0.5*(sqr(c)-sqr(s))/s/c; coup_[22] = 0.; coup_[23] =-0.5/sw*(sqr(c)-sqr(s))/s/c; } void LHWHHVertex::setCoupling(Energy2 q2, tcPDPtr particle1, tcPDPtr particle2, tcPDPtr particle3) { if( q2 != q2last_ || couplast_==0.) { q2last_ = q2; couplast_ = -electroMagneticCoupling(q2); } int ibos = particle1->id(); int isc1 = particle2->id(); int isc2 = particle3->id(); if(ibos==ParticleID::gamma) { if(isc1==37) norm(coup_[6]*couplast_); else if(isc1==38) norm(coup_[7]*couplast_); else if(isc1==-37) norm(-coup_[6]*couplast_); else if(isc1==-38) norm(-coup_[7]*couplast_); else assert(false); } else if(ibos==32) { if(isc1==37) norm(coup_[18]*couplast_); else if(isc1==38) norm(coup_[19]*couplast_); else if(isc1==-37) norm(-coup_[18]*couplast_); else if(isc1==-38) norm(-coup_[19]*couplast_); else if(isc1==25) norm(coup_[16]*couplast_); else if(isc1==35) norm(coup_[17]*couplast_); else if(isc2==25) norm(-coup_[16]*couplast_); else if(isc2==35) norm(-coup_[17]*couplast_); else assert(false); } else if(ibos==ParticleID::Z0) { if(isc1==37) norm(coup_[10]*couplast_); else if(isc1==38) norm(coup_[11]*couplast_); else if(isc1==-37) norm(-coup_[10]*couplast_); else if(isc1==-38) norm(-coup_[11]*couplast_); else if(isc1==25) norm(coup_[8]*couplast_); else if(isc1==35) norm(coup_[9]*couplast_); else if(isc2==25) norm(-coup_[8]*couplast_); else if(isc2==35) norm(-coup_[9]*couplast_); else assert(false); } else if(ibos==33) { if(isc1==37) norm(coup_[22]*couplast_); else if(isc1==38) norm(coup_[23]*couplast_); else if(isc1==-37) norm(-coup_[22]*couplast_); else if(isc1==-38) norm(-coup_[23]*couplast_); else if(isc1==25) norm(coup_[20]*couplast_); else if(isc1==35) norm(coup_[21]*couplast_); else if(isc2==25) norm(-coup_[20]*couplast_); else if(isc2==35) norm(-coup_[21]*couplast_); else assert(false); } else if(ibos==ParticleID::Wplus) { if(isc1==25) norm(coup_[0]*couplast_); else if(isc1==35) norm(coup_[1]*couplast_); else if(isc1==36) norm(coup_[2]*couplast_); else if(isc1==37) norm(coup_[3]*couplast_); else if(isc2==25) norm(-coup_[0]*couplast_); else if(isc2==35) norm(-coup_[1]*couplast_); else if(isc2==36) norm(-coup_[2]*couplast_); else if(isc2==37) norm(-coup_[3]*couplast_); else assert(false); } else if(ibos==34) { if(isc1==25) norm(coup_[12]*couplast_); else if(isc1==35) norm(coup_[13]*couplast_); else if(isc1==36) norm(coup_[14]*couplast_); else if(isc1==37) norm(coup_[15]*couplast_); else if(isc2==25) norm(-coup_[12]*couplast_); else if(isc2==35) norm(-coup_[13]*couplast_); else if(isc2==36) norm(-coup_[14]*couplast_); else if(isc2==37) norm(-coup_[15]*couplast_); else assert(false); } else if(ibos==ParticleID::Wminus) { if(isc1==25) norm(conj(coup_[0])*couplast_); else if(isc1==35) norm(conj(coup_[1])*couplast_); else if(isc1==36) norm(conj(coup_[2])*couplast_); else if(isc1==37) norm(conj(coup_[3])*couplast_); else if(isc2==25) norm(-conj(coup_[0])*couplast_); else if(isc2==35) norm(-conj(coup_[1])*couplast_); else if(isc2==36) norm(-conj(coup_[2])*couplast_); else if(isc2==37) norm(-conj(coup_[3])*couplast_); else assert(false); } else if(ibos==-34) { if(isc1==25) norm(conj(coup_[12])*couplast_); else if(isc1==35) norm(conj(coup_[13])*couplast_); else if(isc1==36) norm(conj(coup_[14])*couplast_); else if(isc1==-37) norm(conj(coup_[15])*couplast_); else if(isc2==25) norm(-conj(coup_[12])*couplast_); else if(isc2==35) norm(-conj(coup_[13])*couplast_); else if(isc2==36) norm(-conj(coup_[14])*couplast_); else if(isc2==-37) norm(-conj(coup_[15])*couplast_); else assert(false); } } diff --git a/Models/LH/LHWWHHVertex.cc b/Models/LH/LHWWHHVertex.cc --- a/Models/LH/LHWWHHVertex.cc +++ b/Models/LH/LHWWHHVertex.cc @@ -1,496 +1,497 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the LHWWHHVertex class. // #include "LHWWHHVertex.h" #include "LHModel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; LHWWHHVertex::LHWWHHVertex() : couplast_(0.), q2last_(ZERO), coup_(107) { orderInGs(0); orderInGem(2); + colourStructure(ColourStructure::SINGLET); } IBPtr LHWWHHVertex::clone() const { return new_ptr(*this); } IBPtr LHWWHHVertex::fullclone() const { return new_ptr(*this); } void LHWWHHVertex::persistentOutput(PersistentOStream & os) const { os << coup_; } void LHWWHHVertex::persistentInput(PersistentIStream & is, int) { is >> coup_; } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigLHWWHHVertex("Herwig::LHWWHHVertex", "HwLHModel.so"); void LHWWHHVertex::Init() { static ClassDocumentation documentation ("The LHWWHHVertex class implements the couplings of a pair" " of electroweak gauge bosons and a pair of Higgs bosons in" " the Little Higgs model."); } void LHWWHHVertex::doinit() { // VVHH addToList( 24, -24, 25, 25); addToList( 23, 23, 25, 25); addToList( 24, -34, 25, 25); addToList( 34, -24, 25, 25); addToList( 23, 32, 25, 25); addToList( 34, -34, 25, 25); addToList( 33, 33, 25, 25); addToList( 32, 32, 25, 25); addToList( 23, 33, 25, 25); addToList( 32, 33, 25, 25); // VVH Phi_0 addToList( 24, -24, 25, 35); addToList( 23, 23, 25, 35); addToList( 24, -34, 25, 35); addToList( 34, -24, 25, 35); addToList( 23, 32, 25, 35); addToList( 34, -34, 25, 35); addToList( 33, 33, 25, 35); addToList( 32, 32, 25, 35); addToList( 23, 33, 25, 35); addToList( 32, 33, 25, 35); // VV Phi_0 Phi_0 addToList( 24, -24, 35, 35); addToList( 23, 23, 35, 35); addToList( 24, -34, 35, 35); addToList( 34, -24, 35, 35); addToList( 23, 32, 35, 35); addToList( 34, -34, 35, 35); addToList( 33, 33, 35, 35); addToList( 32, 32, 35, 35); addToList( 23, 33, 35, 35); addToList( 32, 33, 35, 35); // VV Phi_P Phi_P addToList( 24, -24, 36, 36); addToList( 23, 23, 36, 36); addToList( 24, -34, 36, 36); addToList( 34, -24, 36, 36); addToList( 23, 32, 36, 36); addToList( 34, -34, 36, 36); addToList( 33, 33, 36, 36); addToList( 32, 32, 36, 36); addToList( 23, 33, 36, 36); addToList( 32, 33, 36, 36); // VV Phi+ Phi- addToList( 24, -24, 37, -37); addToList( 23, 23, 37, -37); addToList( 22, 22, 37, -37); addToList( 22, 23, 37, -37); addToList( 24, -34, 37, -37); addToList( 34, -24, 37, -37); addToList( 34, -34, 37, -37); addToList( 33, 33, 37, -37); addToList( 32, 32, 37, -37); addToList( 32, 33, 37, -37); addToList( 22, 32, 37, -37); addToList( 23, 33, 37, -37); addToList( 23, 32, 37, -37); // VV Phi++ Phi-- addToList( 24, -24, 38, -38); addToList( 23, 23, 38, -38); addToList( 22, 22, 38, -38); addToList( 22, 23, 38, -38); addToList( 24, -34, 38, -38); addToList( 34, -24, 38, -38); addToList( 34, -34, 38, -38); addToList( 33, 33, 38, -38); addToList( 32, 32, 38, -38); addToList( 32, 33, 38, -38); addToList( 22, 32, 38, -38); addToList( 23, 33, 38, -38); addToList( 23, 32, 38, -38); // VV H phi- + cc addToList( 24, 22, 25, -37); addToList( 24, 23, 25, -37); addToList( 24, 32, 25, -37); addToList( 24, 33, 25, -37); addToList( 34, 22, 25, -37); addToList( 34, 23, 25, -37); addToList( 34, 32, 25, -37); addToList( 34, 33, 25, -37); addToList( -24, 22, 25, 37); addToList( -24, 23, 25, 37); addToList( -24, 32, 25, 37); addToList( -24, 33, 25, 37); addToList( -34, 22, 25, 37); addToList( -34, 23, 25, 37); addToList( -34, 32, 25, 37); addToList( -34, 33, 25, 37); // VV phi0 phi- + cc addToList( 24, 22, 35, -37); addToList( 24, 23, 35, -37); addToList( 24, 32, 35, -37); addToList( 24, 33, 35, -37); addToList( 34, 22, 35, -37); addToList( 34, 23, 35, -37); addToList( 34, 32, 35, -37); addToList( 34, 33, 35, -37); addToList( -24, 22, 35, 37); addToList( -24, 23, 35, 37); addToList( -24, 32, 35, 37); addToList( -24, 33, 35, 37); addToList( -34, 22, 35, 37); addToList( -34, 23, 35, 37); addToList( -34, 32, 35, 37); addToList( -34, 33, 35, 37); // VV phiP phi- + cc addToList( 24, 22, 36, -37); addToList( 24, 23, 36, -37); addToList( 24, 32, 36, -37); addToList( 24, 33, 36, -37); addToList( 34, 22, 36, -37); addToList( 34, 23, 36, -37); addToList( 34, 32, 36, -37); addToList( 34, 33, 36, -37); addToList( -24, 22, 36, 37); addToList( -24, 23, 36, 37); addToList( -24, 32, 36, 37); addToList( -24, 33, 36, 37); addToList( -34, 22, 36, 37); addToList( -34, 23, 36, 37); addToList( -34, 32, 36, 37); addToList( -34, 33, 36, 37); // VV phi+ phi -- + cc addToList( 24, 22, 37, -38); addToList( 24, 23, 37, -38); addToList( 24, 32, 37, -38); addToList( 24, 33, 37, -38); addToList( 34, 22, 37, -38); addToList( 34, 23, 37, -38); addToList( 34, 32, 37, -38); addToList( 34, 33, 37, -38); addToList( -24, 22, -37, 38); addToList( -24, 23, -37, 38); addToList( -24, 32, -37, 38); addToList( -24, 33, -37, 38); addToList( -34, 22, -37, 38); addToList( -34, 23, -37, 38); addToList( -34, 32, -37, 38); addToList( -34, 33, -37, 38); // VV H phi-- + cc addToList( 24, 24, 25, -38); addToList( -24, -24, 25, 38); addToList( 24, 34, 25, -38); addToList( -24, -34, 25, 38); addToList( 34, 34, 25, -38); addToList( -34, -34, 25, 38); // VV phi0 phi-- + cc addToList( 24, 24, 35, -38); addToList( -24, -24, 35, 38); addToList( 24, 34, 35, -38); addToList( -24, -34, 35, 38); addToList( 34, 34, 35, -38); addToList( -34, -34, 35, 38); // VV phiP phi-- + cc addToList( 24, 24, 36, -38); addToList( -24, -24, 36, 38); addToList( 24, 34, 36, -38); addToList( -24, -34, 36, 38); addToList( 34, 34, 36, -38); addToList( -34, -34, 36, 38); VVSSVertex::doinit(); // model cLHModelPtr model = dynamic_ptr_cast(generator()->standardModel()); if(!model) throw InitException() << "Must be using the LHModel " << " in LHWWWWVertex::doinit()" << Exception::runerror; double sw2(sin2ThetaW()),cw2(1.-sw2); double sw(sqrt(sw2)),cw(sqrt(cw2)); double s (model->sinTheta() ),c (model->cosTheta() ); double sp(model->sinThetaPrime()),cp(model->cosThetaPrime()); double s0 (model->sinTheta0()); double sPlus(model->sinThetaPlus()); // VV HH coup_[ 0] = 0.5/sw2; coup_[ 1] = 0.5/sw2/cw2; coup_[ 2] = 0.; coup_[ 3] =-0.25/sw2*(sqr(c)-sqr(s))/c/s; coup_[ 4] =-0.25/sw/cw2*(sqr(cp)-sqr(sp))/cp/sp; coup_[ 5] =-0.5/sw2; coup_[ 6] =-0.5/sw2; coup_[ 7] =-0.5/cw2; coup_[ 8] =-0.25/sw2/cw*(sqr(c)-sqr(s))/c/s; coup_[ 9] =-0.25/sw/cw*(sqr(c*sp)+sqr(s*cp))/c/s/sp/cp; // VV H Phi_0 coup_[ 10] = 0.5*s0/sw2; coup_[ 11] = 1.5*s0/sw2/cw2; coup_[ 12] = 0.; coup_[ 13] =-0.25/sw2*(sqr(c)-sqr(s))/c/s*s0; coup_[ 14] =-0.75/sw/cw2*(sqr(cp)-sqr(sp))/cp/sp*s0; coup_[ 15] = -0.5/sw2*s0; coup_[ 16] = 0.5/sw2*(1.+sqr(sqr(c)-sqr(s))/sqr(s*c))*s0; coup_[ 17] = 0.5/cw2*(1.+sqr(sqr(cp)-sqr(sp))/sqr(sp*cp))*s0; coup_[ 18] =-0.75/cw/sw2*(sqr(c)-sqr(s))/c/s*s0; coup_[ 19] = 0.25/sw/cw/c/s/sp/cp*((sqr(c*sp)+sqr(s*cp)) +2.*(sqr(c)-sqr(s))*(sqr(cp)-sqr(sp)))*s0; // VV phi0 phi0 coup_[ 20] = 1./sw2; coup_[ 21] = 2./cw2/sw2; coup_[ 22] = 0.; coup_[ 23] =-0.5/sw2*(sqr(c)-sqr(s))/c/s; coup_[ 24] =-1./sw/cw2*(sqr(cp)-sqr(sp))/cp/sp; coup_[ 25] =-1./sw2; coup_[ 26] = 0.5/sw2*sqr(sqr(c)-sqr(s))/sqr(s*c); coup_[ 26] = 0.5/cw2*sqr(sqr(cp)-sqr(sp))/sqr(sp*cp); coup_[ 28] =-1./cw/sw2*(sqr(c)-sqr(s))/c/s; coup_[ 29] = 0.5/cw/sw*(sqr(c)-sqr(s))*(sqr(cp)-sqr(sp))/s/c/sp/cp; // VV phi_P phi_P coup_[ 30] = 1./sw2; coup_[ 31] = 2./sw2/cw2; coup_[ 32] = 0.; coup_[ 33] =-0.5/sw2*(sqr(c)-sqr(s))/c/s; coup_[ 34] =-1./sw/cw2*(sqr(cp)-sqr(sp))/cp/sp; coup_[ 35] =-1./sw2; coup_[ 36] = 0.5/sw2*sqr(sqr(c)-sqr(s))/sqr(s*c); coup_[ 37] = 0.5/cw2*sqr(sqr(cp)-sqr(sp))/sqr(sp*cp); coup_[ 38] =-1./cw/sw2*(sqr(c)-sqr(s))/s/c; coup_[ 39] = 0.5/cw/sw*(sqr(c)-sqr(s))*(sqr(cp)-sqr(sp))/s/c/sp/cp; // VV phi+ phi- coup_[ 40] = 2./sw2; coup_[ 41] = 2.*sw2/cw2; coup_[ 42] = 2.; coup_[ 43] =-2.*sw/cw; coup_[ 44] =-1./sw2*(sqr(c)-sqr(s))/s/c; coup_[ 45] = 0.; coup_[ 46] = 0.5/sw2*sqr(sqr(c)-sqr(s))/sqr(s*c); coup_[ 47] =-0.5/sw2/sqr(s*c); coup_[ 48] = 0.5/cw2*sqr(sqr(cp)-sqr(sp))/sqr(sp*cp); coup_[ 49] = 0.; coup_[ 50] =-1./cw*(sqr(cp)-sqr(sp))/sp/cp; coup_[ 51] = 0.; coup_[ 52] = sw/cw2*(sqr(cp)-sqr(sp))/sp/cp; // VV phi++ phi-- coup_[ 53] = 1./sw2; coup_[ 54] = 2./cw2/sw2*sqr(1.-2.*sw2); coup_[ 55] = 8.; coup_[ 56] = 4./sw/cw*(1.-2.*sw2); coup_[ 57] =-0.5/sw2*(sqr(c)-sqr(s))/s/c; coup_[ 58] = 2./sw*(sqr(c)-sqr(s))/s/c; coup_[ 59] =-1./sw2; coup_[ 60] = 0.5/sw2*sqr(sqr(c)-sqr(s))/sqr(s*c); coup_[ 61] = 0.5/cw2*sqr(sqr(cp)-sqr(sp))/sqr(sp*cp); coup_[ 62] =-0.5/cw/sw*(sqr(c)-sqr(s))*(sqr(cp)-sqr(sp))/s/c/sp/cp; coup_[ 63] =-2./cw*(sqr(cp)-sqr(sp))/cp/sp; coup_[ 64] = 1./sw2/cw*(sqr(c )-sqr(s ))/s /c *(1.-2.*sw2); coup_[ 65] =-1./cw2/sw*(sqr(cp)-sqr(sp))/sp/cp*(1.-2.*sw2); // VV h phi- coup_[ 66] =-0.5/sw*(sPlus-sqrt(2.)*s0); coup_[ 67] = 0.5/cw/sw2*(sPlus*sw2-sqrt(2.)*s0*(1.+sw2)); coup_[ 68] =-0.25/sw/cw*(sqr(cp)-sqr(sp))/cp/sp*(sPlus-2.*sqrt(2.)*s0); coup_[ 69] = 0.25/sw2*(sqr(c)-sqr(s))/s/c*s0; coup_[ 70] = 0.25/sw*(sqr(c)-sqr(s))/s/c*(sPlus-sqrt(2.)*s0); coup_[ 71] =-0.25/sw2/cw*(sqr(c)-sqr(s))/s/c*(sPlus*sw2-sqrt(2.)*s0*(1.+sw2)); coup_[ 72] =-0.25/sw/cw/s/c/sp/cp*(sPlus*(sqr(c*sp)+sqr(s*cp)) +sqrt(2.)*(sqr(c)-sqr(s))*(sqr(cp)-sqr(sp))); coup_[ 73] =-0.25/sw2*s0*(pow(c,4)+pow(s,4))/sqr(s*c); // VV phi0 phi- coup_[ 74] =-sqrt(0.5)/sw; coup_[ 75] =-sqrt(0.5)/sw2/cw*(1.+sw2); coup_[ 76] = sqrt(0.5)/sw/cw*(sqr(cp)-sqr(sp))/sp/cp; coup_[ 77] = 0.5*sqrt(0.5)/sw2*(sqr(c)-sqr(s))/c/s; coup_[ 78] = 0.5*sqrt(0.5)/sw*(sqr(c)-sqr(s))/c/s; coup_[ 79] = 0.5*sqrt(0.5)/sw2/cw*(sqr(c)-sqr(s))/c/s*(1.+sw2); coup_[ 80] =-0.5*sqrt(0.5)/sw/cw*(sqr(cp)-sqr(sp))/cp/sp*(sqr(c)-sqr(s))/c/s; coup_[ 81] =-0.5*sqrt(0.5)/sw2*(pow(c,4)+pow(s,4))/sqr(s*c); // VV phi+ phi-- coup_[ 82] = 3./sw; coup_[ 83] = (1.-3.*sw2)/cw/sw2; coup_[ 84] = 1./sw/cw*(sqr(cp)-sqr(sp))/cp/sp; coup_[ 85] = Complex(0.,1.)*0.5*sqrt(0.5)/sw2*(sqr(c)-sqr(s))/s/c; coup_[ 86] =-3./sw*(sqr(c)-sqr(s))/s/c; coup_[ 87] =-0.5/sw2/cw*(sqr(c)-sqr(s))/s/c*(1.-3.*sw2); coup_[ 88] =-0.5/sw/cw*(sqr(c)-sqr(s))/s/c*(sqr(cp)-sqr(sp))/cp/sp; coup_[ 89] =-Complex(0.,1.)*0.5*sqrt(0.5)/sw2*(pow(c,4)+pow(s,4))/sqr(s*c); // VV phip phi- coup_[ 90] =-Complex(0.,1.)/sw*sqrt(0.5); coup_[ 91] =-Complex(0.,1.)/sw2/cw*(1.+sw2); coup_[ 92] = Complex(0.,1.)/sw/cw*sqrt(0.5)*(sqr(cp)-sqr(sp))/cp/sp; coup_[ 93] = Complex(0.,1.)/sw2*sqrt(0.5)*0.5*(sqr(c)-sqr(s))/s/c; coup_[ 94] =-Complex(0.,1.)*sqrt(0.5)*0.5/sw*(sqr(c)-sqr(s))/s/c; coup_[ 95] = Complex(0.,1.)*sqrt(0.5)*0.5/sw2/cw*(sqr(c)-sqr(s))/s/c*(1.+sw2); coup_[ 96] =-Complex(0.,1.)*sqrt(0.5)*0.5/sw/cw*(sqr(c )-sqr(s ))/s/c* (sqr(cp)-sqr(sp))/cp/sp; coup_[ 97] =-Complex(0.,1.)/sw2*sqrt(0.5)*0.5*(pow(c,4)+pow(s,4))/sqr(s*c); // VV H phi-- coup_[ 98] = sqrt(2.)/sw2*s0; coup_[ 99] =-sqrt(2.)/sw2*0.5*(sqr(c)-sqr(s))/s/c*s0; coup_[100] = sqrt(2.)/sw2*0.5*(pow(c,4)+pow(s,4))/sqr(s*c)*s0; // VV phi0 phi-- coup_[101] = sqrt(2.)/sw2; coup_[102] =-sqrt(2.)/sw2*0.5*(sqr(c)-sqr(s))/s/c; coup_[103] = sqrt(2.)/sw2*0.5*(pow(c,4)+pow(s,4))/sqr(s*c); // VV phip phi-- coup_[104] = Complex(0.,1.)*sqrt(2.)/sw2; coup_[105] =-Complex(0.,1.)*sqrt(2.)/sw2*0.5*(sqr(c)-sqr(s))/s/c; coup_[106] = Complex(0.,1.)*sqrt(2.)/sw2*0.5*(pow(c,4)+pow(s,4))/sqr(s*c); } void LHWWHHVertex::setCoupling(Energy2 q2, tcPDPtr part1,tcPDPtr part2, tcPDPtr part3,tcPDPtr part4) { if( q2 != q2last_ || couplast_==0.) { q2last_ = q2; couplast_ = sqr(electroMagneticCoupling(q2)); } int ibos1 = part1->id(); int ibos2 = part2->id(); int isca1 = part3->id(); int isca2 = part4->id(); if( isca1 == isca2 || (isca1==25&&isca2==35) || (isca1==35&&isca2==25)) { unsigned int ioff = 0; if (isca1!=isca2) ioff = 10; else if(isca1==35 ) ioff = 20; else if(isca1==36 ) ioff = 30; if(ibos1==23&&ibos2==23) norm(coup_[1+ioff]*couplast_); else if(ibos1==33&&ibos2==33) norm(coup_[6+ioff]*couplast_); else if(ibos1==33&&ibos2==33) norm(coup_[7+ioff]*couplast_); else if(abs(ibos1)==24&&abs(ibos2)==24) norm(coup_[0+ioff]*couplast_); else if(abs(ibos1)==34&&abs(ibos2)==34) norm(coup_[5+ioff]*couplast_); else if(( abs(ibos1) == 24 && abs(ibos2) == 34) || ( abs(ibos1) == 34 && abs(ibos2) == 24)) norm(coup_[3+ioff]*couplast_); else if(( ibos1 == 23 && ibos2 == 32) || ( ibos1 == 32 && ibos2 == 23)) norm(coup_[4+ioff]*couplast_); else if(( ibos1 == 23 && ibos2 == 33) || ( ibos1 == 33 && ibos2 == 23)) norm(coup_[8+ioff]*couplast_); else if(( ibos1 == 32 && ibos2 == 33) || ( ibos1 == 33 && ibos2 == 32)) norm(coup_[9+ioff]*couplast_); else assert(false); } else if(isca1==-isca2) { unsigned int ioff = abs(isca1) == 37 ? 40 : 53; if(abs(ibos1)==24&&abs(ibos2)==24) norm(coup_[0+ioff]*couplast_); else if(ibos1==23&&ibos2==23) norm(coup_[1+ioff]*couplast_); else if(ibos1==22&&ibos2==22) norm(coup_[2+ioff]*couplast_); else if(( ibos1 == 22 && ibos2 == 23) || ( ibos1 == 23 && ibos2 == 22)) norm(coup_[3+ioff]*couplast_); else if(( abs(ibos1) == 24 && abs(ibos2) == 34) || ( abs(ibos1) == 34 && abs(ibos2) == 24)) norm(coup_[4+ioff]*couplast_); else if(( ibos1 == 22 && ibos2 == 33) || ( ibos1 == 33 && ibos2 == 22)) norm(coup_[5+ioff]*couplast_); else if(abs(ibos1)==34&&abs(ibos2)==34) norm(coup_[6+ioff]*couplast_); else if(ibos1==33&&ibos2==33) norm(coup_[7+ioff]*couplast_); else if(ibos1==32&&ibos2==32) norm(coup_[8+ioff]*couplast_); else if(( ibos1 == 32 && ibos2 == 33) || ( ibos1 == 33 && ibos2 == 32)) norm(coup_[9+ioff]*couplast_); else if(( ibos1 == 22 && ibos2 == 32) || ( ibos1 == 32 && ibos2 == 22)) norm(coup_[10+ioff]*couplast_); else if(( ibos1 == 23 && ibos2 == 33) || ( ibos1 == 33 && ibos2 == 23)) norm(coup_[11+ioff]*couplast_); else if(( ibos1 == 23 && ibos2 == 32) || ( ibos1 == 32 && ibos2 == 23)) norm(coup_[12+ioff]*couplast_); else assert(false); } else if(((abs(ibos1) == 24 || abs(ibos1) == 34) && (abs(ibos2) != 24 && abs(ibos2) != 34)) || ((abs(ibos2) == 24 || abs(ibos2) == 34) && (abs(ibos1) != 24 && abs(ibos1) != 34))) { int iw,ineut; if(abs(ibos1) == 24 || abs(ibos1) == 34) { iw = abs(ibos1); ineut = ibos2; } else { iw = abs(ibos2); ineut = ibos1; } unsigned int ioff = 66; if((isca1 == 35 && abs(isca2) == 37) || (isca2 == 35 && abs(isca1) == 37)) { ioff += 8; } else if ((abs(isca1) == 37 && abs(isca2) == 38) || (abs(isca2) == 37 && abs(isca1) == 38)) { ioff += 16; } else if ((isca1 == 35 && abs(isca2) == 37) || (isca2 == 35 && abs(isca1) == 37)) { ioff += 24; } else assert(false); if(iw==34) ioff += 4; if(ineut==22) norm(coup_[0+ioff]*couplast_); else if(ineut==23) norm(coup_[1+ioff]*couplast_); else if(ineut==32) norm(coup_[2+ioff]*couplast_); else if(ineut==33) norm(coup_[3+ioff]*couplast_); else assert(false); } else { unsigned int ioff = 98; if(isca1==25||isca2==25) ioff += 0; else if(isca1==35||isca2==35) ioff += 3; else if(isca1==36||isca2==36) ioff += 6; else assert(false); if(ibos1==ibos2) { if(abs(ibos1)==24) { norm(coup_[0+ioff]*couplast_); } else if(abs(ibos1)==34) { norm(coup_[1+ioff]*couplast_); } else assert(false); } else { norm(coup_[2+ioff]*couplast_); } } } diff --git a/Models/LH/LHWWHVertex.cc b/Models/LH/LHWWHVertex.cc --- a/Models/LH/LHWWHVertex.cc +++ b/Models/LH/LHWWHVertex.cc @@ -1,224 +1,225 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the LHWWHVertex class. // #include "LHWWHVertex.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; void LHWWHVertex::persistentOutput(PersistentOStream & os) const { os << ounit(_coup,GeV); } void LHWWHVertex::persistentInput(PersistentIStream & is, int) { is >> iunit(_coup,GeV); } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigLHWWHVertex("Herwig::LHWWHVertex", "HwLHModel.so"); void LHWWHVertex::Init() { static ClassDocumentation documentation ("The LHWWHVertex class implements the coupling of two electroweak" " gauge bosons to a Higgs boson in the Little Higgs Model including the " "additional heavy photon, Z and W bosons and the triplet Higgs bosons."); } LHWWHVertex::LHWWHVertex() : _couplast(0.), _q2last(0.*GeV2) { // order in the couplings orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::SINGLET); } void LHWWHVertex::doinit() { // W_L W_L H addToList( 24, -24, 25); // Z_L Z_L H addToList( 23, 23, 25); // W_L W_H H addToList( 24, -34, 25); addToList( 34, -24, 25); // Z_L A_H H addToList( 23, 32, 25); // W_H W_H H addToList( 34, -34, 25); // Z_H Z_H H addToList( 33, 33, 25); // A_H A_H H addToList( 32, 32, 25); // Z_H Z_L H addToList( 23, 33, 25); // Z_H A_H H addToList( 33, 32, 25); // W_L W_L Phi0 addToList( 24, -24, 35); // W_L W_H Phi0 addToList( 24, -34, 35); addToList( 34, -24, 35); // Z_L Z_L Phi0 addToList( 23, 23, 35); // Z_L Z_H Phi0 addToList( 23, 33, 35); // W_H W_H Phi0 addToList( 34, -34, 35); // Z_H Z_H Phi0 addToList( 33, 33, 35); // A_H Z_H Phi0 addToList( 32, 33, 35); // A_H Z_L Phi0 addToList( 32, 23, 35); // A_H A_H Phi0 addToList( 32, 32, 35); // W_L Z_L Phi- addToList( 24, 23, -37); addToList( -24, 23, 37); // W_L A_H Phi- addToList( 24, 32, -37); addToList( -24, 32, 37); // W_L Z_H Phi- addToList( 24, 33, -37); addToList( -24, 33, 37); // W_H Z_L Phi- addToList( 34, 23, -37); addToList( -34, 23, 37); // W_H A_H Phi- addToList( 34, 32, -37); addToList( -34, 32, 37); // W_H Z_H Phi- addToList( 34, 33, -37); addToList( -34, 33, 37); // W_L W_L Phi-- addToList( 24, 24, -38); addToList( -24, -24, 38); // W_H W_H Phi-- addToList( 34, 34, -38); addToList( -34, -34, 38); // W_L W_H Phi-- addToList( 24, 34, -38); addToList( -24, -34, 38); // model cLHModelPtr model = dynamic_ptr_cast(generator()->standardModel()); if(!model) throw InitException() << "Must be using the LHModel " << " in LHWWHVertex::doinit()" << Exception::runerror; // base class VVSVertex::doinit(); // calculate the couplings for the different combinations of particles double sw(sqrt(sin2ThetaW())),cw(sqrt(1.-sin2ThetaW())); Energy fact = getParticleData(ParticleID::Wplus)->mass()/sw; double vf(sqr(model->vev()/model->f())); double vr(model->vevPrime()/model->vev()); double r2(sqrt(2.)); double s (model->sinTheta() ),c (model->cosTheta() ); double sp(model->sinThetaPrime()),cp(model->cosThetaPrime()); double sPlus(model->sinTheta0()); double s0(model->sinTheta0()); _coup.resize(27); // couplings to SM higgs _coup[ 0] = fact *(1.-vf/3.+0.5*vf* sqr(sqr(c)-sqr(s)) -0.5*sqr(s0)-2.*r2*s0*vr); _coup[ 1] = fact/sqr(cw)*(1.-vf/3.-0.5*vf*(sqr(sqr(c)-sqr(s))+5.*sqr(sqr(cp)-sqr(sp))) -0.5*sqr(s0)+4.*r2*s0*vr); _coup[ 2] =-fact; _coup[ 3] =-fact; _coup[ 4] =-fact*sqr(sw/cw); _coup[ 5] =-fact* 0.5*(sqr(c)-sqr(s))/s/c; _coup[ 6] =-fact/cw*0.5*(sqr(c)-sqr(s))/s/c; _coup[ 7] =-fact/sqr(cw)*sw*0.5*(sqr(cp)-sqr(sp))/sp/cp; _coup[ 8] =-fact/cw*sw*0.5/s/c/sp/cp*(sqr(c*sp)+sqr(s*cp)); _coup[ 9] =-fact*(s0-2.*r2*vr); _coup[10] = fact*(s0-2.*r2*vr); _coup[11] = fact*(s0-2.*r2*vr)*0.5*(sqr(c)-sqr(s))/s/c; _coup[12] =-fact/sqr(cw)*(s0-4.*r2*vr); _coup[13] = fact*(s0+sqr(sqr(c)-sqr(s))/sqr(s*c)*r2*vr); _coup[14] = fact/cw*0.5*(sqr(c)-sqr(s))/s/c*(s0-4.*r2*vr); _coup[15] = fact*sw/sqr(cw)*0.5*(sqr(cp)-sqr(sp))/sp/cp*(s0-4.*r2*vr); _coup[16] = fact*sw/cw*0.5/s/c/sp/cp*(s0*(sqr(c*sp)+sqr(s*cp)) +2.*r2*(sqr(c)-sqr(s))*(sqr(cp)-sqr(sp))*vr); _coup[17] = fact*sqr(sw/cw)*(s0+r2*vr*sqr(sqr(cp)-sqr(sp))/sqr(sp*cp)); _coup[18] =-2.*fact/cw*vr; _coup[19] = fact/cw*(sqr(c)-sqr(s))/s/c*vr; _coup[20] =-fact*sw/cw*0.5*(sqr(cp)-sqr(sp))/sp/cp*(sPlus-4.*vr); _coup[21] =-fact*sw/cw*(sqr(c*cp)+sqr(s*sp))/s/c/sp/cp*vr; _coup[22] = fact*(sqr(c)-sqr(s))/s/c*vr; _coup[23] =-fact*(pow(c,4)+pow(s,4))/sqr(s*c)*vr; _coup[24] = fact*4.*vr; _coup[25] = fact*2.*(pow(c,4)+pow(s,4))/sqr(s*c)*vr; _coup[26] =-fact*2.*vr*(sqr(c)-sqr(s))/s/c; } void LHWWHVertex::setCoupling(Energy2 q2,tcPDPtr a,tcPDPtr b, tcPDPtr c) { // first the overall normalisation if(q2!=_q2last) { _couplast = electroMagneticCoupling(q2); _q2last=q2; } int ih = abs(c->id()); long int ibos[2]={abs(a->id()),abs(b->id())}; if(ih==25) { if ( ibos[0]==24&&ibos[1]==24 ) norm(UnitRemoval::InvE *_couplast*_coup[0]); else if( ibos[0]==23&&ibos[1]==23 ) norm(UnitRemoval::InvE *_couplast*_coup[1]); else if( ibos[0]==34&&ibos[1]==34 ) norm(UnitRemoval::InvE *_couplast*_coup[2]); else if( ibos[0]==33&&ibos[1]==33 ) norm(UnitRemoval::InvE *_couplast*_coup[3]); else if( ibos[0]==32&&ibos[1]==32 ) norm(UnitRemoval::InvE *_couplast*_coup[4]); else if((ibos[0]==24&&ibos[1]==34) || (ibos[0]==34&&ibos[1]==24) ) norm(UnitRemoval::InvE *_couplast*_coup[5]); else if((ibos[0]==23&&ibos[1]==33) || (ibos[0]==33&&ibos[1]==23) ) norm(UnitRemoval::InvE *_couplast*_coup[6]); else if((ibos[0]==23&&ibos[1]==32) || (ibos[0]==32&&ibos[1]==23) ) norm(UnitRemoval::InvE *_couplast*_coup[7]); else if((ibos[0]==33&&ibos[1]==32) || (ibos[0]==32&&ibos[1]==33) ) norm(UnitRemoval::InvE *_couplast*_coup[8]); else assert(false); } else if(ih==35) { if ( ibos[0]==24&&ibos[1]==24 ) norm(UnitRemoval::InvE *_couplast*_coup[ 9]); else if( ibos[0]==34&&ibos[1]==34 ) norm(UnitRemoval::InvE *_couplast*_coup[10]); else if((ibos[0]==24&&ibos[1]==34) || (ibos[0]==34&&ibos[1]==24) ) norm(UnitRemoval::InvE *_couplast*_coup[11]); else if( ibos[0]==23&&ibos[1]==23 ) norm(UnitRemoval::InvE *_couplast*_coup[12]); else if( ibos[0]==33&&ibos[1]==33 ) norm(UnitRemoval::InvE *_couplast*_coup[13]); else if((ibos[0]==23&&ibos[1]==33) || (ibos[0]==33&&ibos[1]==23) ) norm(UnitRemoval::InvE *_couplast*_coup[14]); else if((ibos[0]==23&&ibos[1]==32) || (ibos[0]==32&&ibos[1]==23) ) norm(UnitRemoval::InvE *_couplast*_coup[15]); else if((ibos[0]==33&&ibos[1]==32) || (ibos[0]==32&&ibos[1]==33) ) norm(UnitRemoval::InvE *_couplast*_coup[16]); else if((ibos[0]==32&&ibos[1]==32) ) norm(UnitRemoval::InvE *_couplast*_coup[17]); else assert(false); } else if(ih==37) { if ((ibos[0]==24&&ibos[1]==23) || (ibos[0]==23&&ibos[1]==24) ) norm(UnitRemoval::InvE *_couplast*_coup[18]); else if((ibos[0]==34&&ibos[1]==23) || (ibos[0]==23&&ibos[1]==34) ) norm(UnitRemoval::InvE *_couplast*_coup[19]); else if((ibos[0]==24&&ibos[1]==32) || (ibos[0]==32&&ibos[1]==24) ) norm(UnitRemoval::InvE *_couplast*_coup[20]); else if((ibos[0]==34&&ibos[1]==32) || (ibos[0]==32&&ibos[1]==34) ) norm(UnitRemoval::InvE *_couplast*_coup[21]); else if((ibos[0]==24&&ibos[1]==33) || (ibos[0]==33&&ibos[1]==24) ) norm(UnitRemoval::InvE *_couplast*_coup[22]); else if((ibos[0]==34&&ibos[1]==33) || (ibos[0]==33&&ibos[1]==34) ) norm(UnitRemoval::InvE *_couplast*_coup[23]); else assert(false); } else if(ih==38) { if ((ibos[0]==24&&ibos[1]==24) ) norm(UnitRemoval::InvE *_couplast*_coup[24]); else if((ibos[0]==34&&ibos[1]==34) ) norm(UnitRemoval::InvE *_couplast*_coup[24]); else if((ibos[0]==34&&ibos[1]==24) || (ibos[0]==24&&ibos[1]==34) ) norm(UnitRemoval::InvE *_couplast*_coup[24]); else assert(false); } else assert(false); } diff --git a/Models/LH/LHWWWVertex.cc b/Models/LH/LHWWWVertex.cc --- a/Models/LH/LHWWWVertex.cc +++ b/Models/LH/LHWWWVertex.cc @@ -1,151 +1,152 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the LHWWWVertex class. // #include "LHWWWVertex.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; void LHWWWVertex::persistentOutput(PersistentOStream & os) const { os << _corr; } void LHWWWVertex::persistentInput(PersistentIStream & is, int) { is >> _corr; } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigLHWWWVertex("Herwig::LHWWWVertex", "HwLHModel.so"); void LHWWWVertex::Init() { static ClassDocumentation documentation ("The LHWWWVertex class implements the triple electroweak" " gauge boson couplings in the Little Higgs model."); } LHWWWVertex::LHWWWVertex() : _couplast(0.),_q2last(ZERO) { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::SINGLET); } void LHWWWVertex::doinit() { // particles addToList(24, -24, 22); addToList(24, -24, 23); addToList(24, -24, 32); addToList(24, -24, 33); addToList(34, -24, 23); addToList(34, -24, 32); addToList(34, -24, 33); addToList(24, -34, 23); addToList(24, -34, 32); addToList(24, -34, 33); addToList(34, -34, 22); addToList(34, -34, 23); addToList(34, -34, 32); addToList(34, -34, 33); // model cLHModelPtr model = dynamic_ptr_cast(generator()->standardModel()); if(!model) throw InitException() << "Must be using the LHModel " << " in LHWWWVertex::doinit()" << Exception::runerror; // correction factors for the different interactions double sw(sqrt(model->sin2ThetaW())),cw(sqrt(1.-model->sin2ThetaW())); double vf(sqr(model->vev()/model->f())); double s (model->sinTheta() ),c (model->cosTheta() ); double sp(model->sinThetaPrime()),cp(model->cosThetaPrime()); double xB(-2.5/sw*sp*cp*(sqr(cp)-sqr(sp))); double xH(2.5/sw/cw*s*c*sp*cp*(sqr(c*sp)+sqr(s*cp))/ (5.*sqr(sp*cp/sw)-sqr(s*c/cw))); double xW(-0.5/cw*s*c*(sqr(c)-sqr(s))); _corr.resize(12); // W_L W_L A_L _corr[ 0] = -1.; // W_L W_L A_H _corr[ 1] = cw/sw*vf*xB; // W_L W_H A_L _corr[ 2] = 0.; // W_L W_H A_H _corr[ 3] = -vf/sw*xH; // W_H W_H A_L _corr[ 4] = -1.; // W_H W_H A_H _corr[ 5] = vf/sw*(xH*(sqr(c)-sqr(s))/s/c+cw*xB); // W_L W_L Z_L _corr[ 6] = -cw/sw; // W_L W_L Z_H _corr[ 7] = vf/sw*(cw*xW+s*c*(sqr(c)-sqr(s))); // W_L W_H Z_L _corr[ 8] = -vf/sw*xW; // W_L W_H Z_H _corr[ 9] = -1./sw; // W_H W_H Z_L _corr[10] = -cw/sw; // W_H W_H Z_H _corr[11] = (sqr(c)-sqr(s))/s/c/sw; VVVVertex::doinit(); } // couplings for the WWW vertex void LHWWWVertex::setCoupling(Energy2 q2,tcPDPtr a,tcPDPtr b, tcPDPtr c) { // first the overall normalisation if(q2!=_q2last) { _couplast = electroMagneticCoupling(q2); _q2last=q2; } int ia(a->iCharge()/3),ib(b->iCharge()/3),ic(c->iCharge()/3); int ida(a->id()), idb(b->id()), idc(c->id()); // get the particles in the interaction int ineut,nh(0); if(ia==0) { ineut=ida; if(abs(idb)==34) ++nh; if(abs(idc)==34) ++nh; } else if(ib==0) { ineut=idb; if(abs(ida)==34) ++nh; if(abs(idc)==34) ++nh; } else { ineut=idc; if(abs(ida)==34) ++nh; if(abs(idb)==34) ++nh; } if(nh==0) { if (ineut==22) norm(_corr[ 0]*_couplast); else if(ineut==23) norm(_corr[ 6]*_couplast); else if(ineut==32) norm(_corr[ 1]*_couplast); else if(ineut==33) norm(_corr[ 7]*_couplast); } else if(nh==1) { if (ineut==22) norm(_corr[ 2]*_couplast); else if(ineut==23) norm(_corr[ 8]*_couplast); else if(ineut==32) norm(_corr[ 3]*_couplast); else if(ineut==33) norm(_corr[ 9]*_couplast); } else if(nh==2) { if (ineut==22) norm(_corr[ 4]*_couplast); else if(ineut==23) norm(_corr[10]*_couplast); else if(ineut==32) norm(_corr[ 5]*_couplast); else if(ineut==33) norm(_corr[11]*_couplast); } // check the order for the overall sign if((ia<0 && ib>0 && ic==0) || (ia==0 && ib<0 && ic>0 ) || (ia>0 && ib==0 && ic<0 ) ) norm(-norm()); } diff --git a/Models/LH/LHWWWWVertex.cc b/Models/LH/LHWWWWVertex.cc --- a/Models/LH/LHWWWWVertex.cc +++ b/Models/LH/LHWWWWVertex.cc @@ -1,309 +1,310 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the LHWWWWVertex class. // #include "LHWWWWVertex.h" #include "LHModel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; LHWWWWVertex::LHWWWWVertex() : _couplast(0.0), _q2last(sqr(Constants::MaxEnergy)), _coup(36,0.) { // order in the couplings orderInGem(2); orderInGs(0); + colourStructure(ColourStructure::SINGLET); } IBPtr LHWWWWVertex::clone() const { return new_ptr(*this); } IBPtr LHWWWWVertex::fullclone() const { return new_ptr(*this); } void LHWWWWVertex::persistentOutput(PersistentOStream & os) const { os << _coup; } void LHWWWWVertex::persistentInput(PersistentIStream & is, int) { is >> _coup; } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigLHWWWWVertex("Herwig::LHWWWWVertex", "HwLHModel.so"); void LHWWWWVertex::Init() { static ClassDocumentation documentation ("The LHWWWWVertex class implements the quartic electroweak" " boson couplings in the Little Higgs Model"); } void LHWWWWVertex::doinit() { // all charge W's addToList(24, -24, 24, -24); addToList(34, -34, 34, -34); addToList(24, -24, 34, -34); addToList(24, -24, 24, -34); addToList(24, -24, 34, -24); addToList(34, -24, 34, -24); addToList(24, -34, 24, -34); addToList(34, -34, 24, -34); addToList(34, -34, 34, -24); // two neutral and 2 W_L addToList(22, 24, 22, -24); addToList(23, 24, 23, -24); addToList(22, 24, 23, -24); addToList(22, 24, 32, -24); addToList(22, 24, 33, -24); addToList(23, 24, 33, -24); addToList(23, 24, 32, -24); addToList(33, 24, 33, -24); addToList(33, 24, 32, -24); // two neutral and 2 W_H addToList(22, 34, 22, -34); addToList(23, 34, 23, -34); addToList(22, 34, 23, -34); addToList(22, 34, 32, -34); addToList(22, 34, 33, -34); addToList(23, 34, 33, -34); addToList(23, 34, 32, -34); addToList(33, 34, 33, -34); addToList(33, 34, 32, -34); // two neutral W_L W_H addToList(23, 24, 23, -34); addToList(23, 24, 22, -34); addToList(22, 24, 32, -34); addToList(23, 24, 32, -34); addToList(33, 24, 33, -34); addToList(33, 24, 32, -34); addToList(22, 24, 33, -34); addToList(23, 24, 33, -34); addToList(23, 34, 23, -24); addToList(23, 34, 22, -24); addToList(22, 34, 32, -24); addToList(23, 34, 32, -24); addToList(33, 34, 33, -24); addToList(33, 34, 32, -24); addToList(22, 34, 33, -24); addToList(23, 34, 33, -24); // model cLHModelPtr model = dynamic_ptr_cast(generator()->standardModel()); if(!model) throw InitException() << "Must be using the LHModel " << " in LHWWWWVertex::doinit()" << Exception::runerror; // correction factors for the different interactions double sw2(sin2ThetaW()); double sw(sqrt(sw2)),cw(sqrt(1.-sw2)); double s (model->sinTheta() ),c (model->cosTheta() ); double sp(model->sinThetaPrime()),cp(model->cosThetaPrime()); double vf(sqr(model->vev()/model->f())); double xB(-2.5/sw*sp*cp*(sqr(cp)-sqr(sp))); double xW(-0.5/cw*s*c*(sqr(c)-sqr(s))); double xH(2.5/sw/cw*s*c*sp*cp*(sqr(c*sp)+sqr(s*cp))/ (5.*sqr(sp*cp/sw)-sqr(s*c/cw))); // 4 W's _coup[ 0] =-1./sw2; _coup[ 1] =-1./sw2; _coup[ 2] = 0.5/sw2*(sqr(c)-sqr(s))/c/s; _coup[ 3] =-0.25/sw2*vf*s*c*(sqr(c)-sqr(s)); _coup[ 4] =-0.25/sw2; _coup[ 5] =-1./sw2*(pow(c,6)+pow(s,c))/sqr(s*c); // 2 W_L _coup[ 6] = 1.; _coup[ 7] = sqr(cw/sw); _coup[ 8] = cw/sw; _coup[ 9] =-cw/sw*xB*vf; _coup[10] =-cw/sw*xW*vf+0.5/sw*s*c*(sqr(c)-sqr(s))*vf; _coup[11] =-(sqr(cw)-sw2)/sw2*xW*vf; _coup[12] =-sqr(cw/sw)*xB*vf; _coup[13] = 0.; _coup[14] = 1./sw2; _coup[15] = xH*vf/sw2; _coup[16] = 1.; _coup[17] = sqr(cw/sw); _coup[18] = cw/sw; _coup[19] =-cw/sw*xB*vf-xH/sw*vf*(sqr(c)-sqr(s))/s/c; _coup[20] =-1./sw*(sqr(c)-sqr(s))/s/c; _coup[21] =-cw/sw2*(sqr(c)-sqr(s))/s/c; _coup[22] =-sqr(cw/sw)*xB*vf-cw/sw2*xH*vf*(sqr(c)-sqr(s))/c/s; _coup[23] = 0.; _coup[24] = (pow(c,6)+pow(s,6))/sqr(s*c)/sw2; _coup[25] = xH/sw2*vf*(pow(c,6)+pow(s,6))/sqr(s*c) +cw/sw2*xB*vf*(sqr(c)-sqr(s))/s/c; _coup[26] = 0.; _coup[27] = 2.*cw/sw2*xW*vf; _coup[28] = 0.; _coup[29] = xH*vf/sw; _coup[30] = xH*vf*cw/sw2; _coup[31] = xW*vf/sw; _coup[32] =-(sqr(c)-sqr(s))/s/c/sw2; _coup[33] =-xH*vf*(sqr(c)-sqr(s))/s/c-cw/sw2*xB*vf; _coup[34] = 1./sw; _coup[35] = cw/sw2; VVVVVertex::doinit(); } void LHWWWWVertex::setCoupling(Energy2 q2,tcPDPtr a,tcPDPtr b, tcPDPtr c,tcPDPtr d) { // id's of the particles long int id[4]={a->id(),b->id(),c->id(),d->id()}; // order the particles int ngamma(0),nz(0); int iorder[4]; for(int ix=0;ix<4;++ix) { if (id[ix]==22||id[ix]==32) ++ngamma; else if (id[ix]==23||id[ix]==33) ++nz; } // if photons or Z's if(ngamma!=0 || nz!=0) { int iy=0; // put the photons first for(int ix=0;iyid()); else if(iorder[ix]==1) id[ix] = abs(b->id()); else if(iorder[ix]==2) id[ix] = abs(c->id()); else if(iorder[ix]==3) id[ix] = abs(d->id()); } if( ngamma == 0 && nz == 0 ) { if(id[0]==id[1]) { if(id[2]==id[3]) { if(id[0]==24&&id[2]==24) norm(_couplast*_coup[0]); else if(id[0]==34&&id[2]==34) norm(_couplast*_coup[5]); else norm(_couplast*_coup[1]); } else { if(id[0]==24) norm(_couplast*_coup[3]); else norm(_couplast*_coup[2]); } } else { if(id[2]==id[3]) { if(id[2]==24) norm(_couplast*_coup[3]); else norm(_couplast*_coup[2]); } else norm(_couplast*_coup[4]); } } else { if(id[2]==id[3]) { unsigned int ioff = id[2]==24 ? 0 : 10; if(id[0]==22&&id[1]==22) norm(_couplast*_coup[6+ioff]); else if(id[0]==23&&id[1]==23) norm(_couplast*_coup[7+ioff]); else if((id[0]==22&&id[1]==23) || (id[0]==23&&id[1]==22)) norm(_couplast*_coup[8+ioff]); else if((id[0]==22&&id[1]==32) || (id[0]==32&&id[1]==22)) norm(_couplast*_coup[9+ioff]); else if((id[0]==22&&id[1]==33) || (id[0]==33&&id[1]==22)) norm(_couplast*_coup[10+ioff]); else if((id[0]==23&&id[1]==33) || (id[0]==33&&id[1]==22)) norm(_couplast*_coup[11+ioff]); else if((id[0]==23&&id[1]==32) || (id[0]==32&&id[1]==23)) norm(_couplast*_coup[12+ioff]); else if( id[0]==33&&id[1]==33) norm(_couplast*_coup[14+ioff]); else if((id[0]==32&&id[1]==33) || (id[0]==33&&id[1]==32)) norm(_couplast*_coup[15+ioff]); else assert(false); } else { if(id[0]==23&&id[1]==23) norm(_couplast*_coup[27]); else if((id[0]==22&&id[1]==23) || (id[0]==23&&id[1]==22)) norm(_couplast*_coup[28]); else if((id[0]==22&&id[1]==32) || (id[0]==32&&id[1]==22)) norm(_couplast*_coup[29]); else if((id[0]==23&&id[1]==32) || (id[0]==32&&id[1]==23)) norm(_couplast*_coup[30]); else if( id[0]==33&&id[1]==33) norm(_couplast*_coup[31]); else if((id[0]==32&&id[1]==33) || (id[0]==33&&id[1]==32)) norm(_couplast*_coup[32]); else if((id[0]==22&&id[1]==33) || (id[0]==33&&id[1]==22)) norm(_couplast*_coup[33]); else if((id[0]==23&&id[1]==33) || (id[0]==33&&id[1]==22)) norm(_couplast*_coup[34]); else assert(false); } } } diff --git a/Models/LHTP/LHTPFFGVertex.cc b/Models/LHTP/LHTPFFGVertex.cc --- a/Models/LHTP/LHTPFFGVertex.cc +++ b/Models/LHTP/LHTPFFGVertex.cc @@ -1,73 +1,74 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the LHTPFFGVertex class. // #include "LHTPFFGVertex.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; IBPtr LHTPFFGVertex::clone() const { return new_ptr(*this); } IBPtr LHTPFFGVertex::fullclone() const { return new_ptr(*this); } // Static variable needed for the type description system in ThePEG. DescribeNoPIOClass describeHerwigLHTPFFGVertex("Herwig::LHTPFFGVertex", "HwLHTPModel.so"); void LHTPFFGVertex::Init() { static ClassDocumentation documentation ("The LHTPFFGVertex class implements the couples of the fermions " "to the gluons in the Little Higgs model with T-parity."); } LHTPFFGVertex::LHTPFFGVertex() : coupLast_(0.), q2Last_(0.*GeV2) { orderInGs(1); orderInGem(0); + colourStructure(ColourStructure::SU3TFUND); } void LHTPFFGVertex::doinit() { // SM quarks for(int ix = 1; ix < 7; ++ix) { addToList(-ix, ix, 21); } // additional top quark addToList(-8, 8, 21); // T odd quarks for(long ix = 4000001; ix <= 4000006; ++ix) { addToList(-ix, ix, 21); } addToList(-4000008, 4000008, 21); FFVVertex::doinit(); } // coupling for FFG vertex void LHTPFFGVertex::setCoupling(Energy2 q2,tcPDPtr a,tcPDPtr,tcPDPtr) { // first the overall normalisation if(q2!=q2Last_) { coupLast_ = -strongCoupling(q2); q2Last_=q2; } norm(coupLast_); // the left and right couplings int iferm=abs(a->id()); if( iferm > 8 ) iferm -= 4000000; if((iferm>=1 && iferm<=8)) { left (1.); right(1.); } else assert(false); } diff --git a/Models/LHTP/LHTPFFHVertex.cc b/Models/LHTP/LHTPFFHVertex.cc --- a/Models/LHTP/LHTPFFHVertex.cc +++ b/Models/LHTP/LHTPFFHVertex.cc @@ -1,387 +1,388 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the LHTPFFHVertex class. // #include "LHTPFFHVertex.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; void LHTPFFHVertex::persistentOutput(PersistentOStream & os) const { os << ounit(cL_,1./GeV) << ounit(cR_,1./GeV) << model_; } void LHTPFFHVertex::persistentInput(PersistentIStream & is, int) { is >> iunit(cL_,1./GeV) >> iunit(cR_,1./GeV) >> model_; } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigLHTPFFHVertex("Herwig::LHTPFFHVertex", "HwLHTPModel.so"); void LHTPFFHVertex::Init() { static ClassDocumentation documentation ("The LHTPFFHVertex class implements the interaction of the fermions" " and the Higgs bosons in the Little Higgs model with T-parity"); } LHTPFFHVertex::LHTPFFHVertex() : q2Last_(ZERO) { orderInGem(1); orderInGs(0); massLast_[0] = 0.*GeV; massLast_[1] = 0.*GeV; idLast_[0] = 0; idLast_[1] = 0; + colourStructure(ColourStructure::DELTA); } void LHTPFFHVertex::doinit() { // SM like higgs addToList( -3, 3, 25); addToList( -4, 4, 25); addToList( -5, 5, 25); addToList( -6, 6, 25); addToList( -6, 8, 25); addToList( -8, 6, 25); addToList( -8, 8, 25); addToList( -13, 13, 25); addToList( -15, 15, 25); addToList( -4000002, 4000002, 25); addToList( -4000004, 4000004, 25); addToList( -4000006, 4000006, 25); addToList( -4000012, 4000012, 25); addToList( -4000014, 4000014, 25); addToList( -4000016, 4000016, 25); // phi0 addToList( -3 , 4000003, 35); addToList( -4 , 4000004, 35); addToList( -5 , 4000005, 35); addToList( -4000003, 3, 35); addToList( -4000004, 4, 35); addToList( -4000005, 5, 35); addToList( -6 , 4000006, 35); addToList( -8 , 4000006, 35); addToList( -4000006, 6, 35); addToList( -4000006, 8, 35); // phiP addToList( -2 , 4000002, 36); addToList( -3 , 4000003, 36); addToList( -4 , 4000004, 36); addToList( -5 , 4000005, 36); addToList( -4000002, 2, 36); addToList( -4000003, 3, 36); addToList( -4000004, 4, 36); addToList( -4000005, 5, 36); addToList( -12 , 4000012, 36); addToList( -14 , 4000014, 36); addToList( -16 , 4000016, 36); addToList( -4000012, 12, 36); addToList( -4000014, 14, 36); addToList( -4000016, 16, 36); addToList( -6 , 4000006, 36); addToList( -6 , 4000008, 36); addToList( -8 , 4000006, 36); addToList( -8 , 4000008, 36); addToList( -4000006, 6, 36); addToList( -4000008, 6, 36); addToList( -4000006, 8, 36); addToList( -4000008, 8, 36); // phi +/- addToList( -1 , 4000002, -37); addToList( -3 , 4000004, -37); addToList( -5 , 4000006, -37); addToList( -4000001, 2, -37); addToList( -4000003, 4, -37); addToList( -4000005, 6, -37); addToList( -4000005, 8, -37); addToList( -4000002, 1, 37); addToList( -4000004, 3, 37); addToList( -4000006, 5, 37); addToList( -2 , 4000001, 37); addToList( -4 , 4000003, 37); addToList( -6 , 4000005, 37); addToList( -8 , 4000005, 37); addToList( -11 , 4000012, -37); addToList( -13 , 4000014, -37); addToList( -15 , 4000016, -37); addToList( -4000011, 12, -37); addToList( -4000013, 14, -37); addToList( -4000015, 16, -37); addToList( -4000012, 11 , 37); addToList( -4000014, 13 , 37); addToList( -4000016, 15 , 37); addToList( -12, 4000011, 37); addToList( -14, 4000013, 37); addToList( -16, 4000015, 37); model_ = dynamic_ptr_cast(generator()->standardModel()); if(!model_) throw InitException() << "Must be using the LHModel " << " in LHFFPVertex::doinit()" << Exception::runerror; cL_ .resize(18); cR_ .resize(18); Energy v = model_->vev(); Energy f = model_->f(); double vf = model_->vev()/model_->f(); double sa = model_->sinAlpha(); double ca = model_->cosAlpha(); // lightest higgs couplings // coupling of light SM fermions cL_[0] = cR_[0] = 1./v; // couplings to top quarks cL_[1] = cR_[1] = sa*ca/f; cL_[2] = -sa/ca/v; cR_[2] = sqr(ca)*vf/v; // couplings to T-odd quarks cL_[3] = cR_[3] = 0.5*sqrt(0.5)/f*model_->kappaQuark(); // couplings to T-odd leptons cL_[4] = cR_[4] = 0.5*sqrt(0.5)/f*model_->kappaLepton(); // Phi0 // quark, T-odd quark cL_[5] = sqrt(0.5)/f; cR_[5] = ZERO; // and top quarks cL_[6] = sqrt(0.5)*model_->cosThetaR()/f/ca; cR_[6] = ZERO; cL_[7] = sqrt(0.5)*model_->sinThetaR()/f/ca; cR_[7] = ZERO; // PhiP // quark, T-odd quark cL_[8] = vf/f*model_->kappaQuark()/12; cR_[8] = sqrt(0.5)/f; // lepton, T-odd lepton cL_[9] = vf/f*model_->kappaLepton()/12; cR_[9] = ZERO; // top, T_- cL_[10] = model_->cosThetaR()*sqrt(2.)*vf/f/ca/3; cR_[10] = ZERO; cL_[11] = model_->sinThetaR()*sqrt(2.)*vf/f/ca/3; cR_[11] = ZERO; // top, t_- cL_[12] = model_->cosThetaL()*vf/f/12.*model_->kappaQuark(); cR_[12] = model_->cosThetaR()*sqrt(0.5)/f/ca; cL_[13] = model_->sinThetaL()*vf/f/12.*model_->kappaQuark(); cR_[13] = model_->sinThetaR()*sqrt(0.5)/f/ca; // Phi +/- cL_[14] = vf/f*model_->kappaLepton()/24.; cR_[14] = ZERO; // quark T-odd quark cL_[15] = vf/f*model_->kappaQuark() /24.; cR_[15] =-vf*sqrt(0.5)/v; cL_[16] = model_->cosThetaL()*vf/f*model_->kappaQuark() /24.; cR_[16] =-model_->cosThetaR()*vf*sqrt(0.5)/v/ca; cL_[17] = model_->sinThetaL()*vf/f*model_->kappaQuark() /24.; cR_[17] =-model_->sinThetaR()*vf*sqrt(0.5)/v/ca; FFSVertex::doinit(); } void LHTPFFHVertex::setCoupling(Energy2 q2,tcPDPtr a,tcPDPtr b, tcPDPtr c) { norm(1.); int iferm=abs(a->id()); int ianti=abs(b->id()); // int ihigg=abs(c->id()); // left and right couplings set to one // SM like higgs if(c->id()==ParticleID::h0) { // to SM fermions and T if(iferm<=16&&ianti<=16) { // running masses if(q2!=q2Last_||idLast_[0]!=iferm||idLast_[1]!=ianti) { q2Last_ = q2; idLast_[0] = iferm; assert((idLast_[0]>=1 && idLast_[0]<=8 ) || (idLast_[0]>=11 && idLast_[0]<=16)); if(idLast_[0]!=8) massLast_[0] = model_->mass(q2,a); else massLast_[0] = model_->mass(q2,getParticleData(ParticleID::t)); idLast_[1] = ianti; assert((idLast_[1]>=1 && idLast_[1]<=8 ) || (idLast_[1]>=11 && idLast_[1]<=16)); if(idLast_[0]!=idLast_[1]) { if(idLast_[1]!=8) massLast_[1] = model_->mass(q2,a); else massLast_[1] = model_->mass(q2,getParticleData(ParticleID::t)); } else { massLast_[1] = massLast_[0]; } } if(iferm<6||iferm>8) { left (-Complex(cL_[0]*massLast_[0])); right(-Complex(cR_[0]*massLast_[0])); } else { if(iferm==8&&ianti==8) { left ( Complex(cL_[1]*massLast_[0])); right( Complex(cR_[1]*massLast_[0])); } else { if(a->id()==ParticleID::tbar||b->id()==ParticleID::tbar) { left (-Complex(cL_[2]*massLast_[0])); right(-Complex(cR_[2]*massLast_[0])); } else { left (-Complex(cR_[2]*massLast_[0])); right(-Complex(cL_[2]*massLast_[0])); } } } } else { if(iferm<=4000006) { left ( Complex(cL_[3]*model_->vev())); right( Complex(cR_[3]*model_->vev())); } else { left ( Complex(cL_[4]*model_->vev())); right( Complex(cR_[4]*model_->vev())); } } } // Phi0 else if(c->id()==ParticleID::H0 || c->id()==ParticleID::A0) { tcPDPtr ferm = a; if(iferm>4000000) { swap(iferm,ianti); ferm = b; } if(q2!=q2Last_||idLast_[0]!=iferm) { q2Last_ = q2; idLast_[0] = iferm; assert((idLast_[0]>=1 && idLast_[0]<=8 ) || (idLast_[0]>=11 && idLast_[0]<=16)); if(idLast_[0]!=8) massLast_[0] = model_->mass(q2,ferm); else massLast_[0] = model_->mass(q2,getParticleData(ParticleID::t)); } if(c->id()==ParticleID::H0 ) { unsigned int iloc = 5; if(iferm==6) iloc = 6; else if(iferm==8) iloc = 7; if( (a->id()>=1&&a->id()<=8) || (b->id()>=1&&b->id()<=8) ) { left ( Complex(cR_[iloc]*massLast_[0])); right( Complex(cL_[iloc]*massLast_[0])); } else { left ( Complex(cL_[iloc]*massLast_[0])); right( Complex(cR_[iloc]*massLast_[0])); } } // PhiP else if(c->id()==ParticleID::A0) { if(iferm<=5) { if( (a->id()>=1&&a->id()<=5) || (b->id()>=1&&b->id()<=5) ) { if(iferm%2==0) { right(Complex(0., 1.)*model_->vev()*cL_[8]); left (Complex(0.,-1.)*massLast_[0] *cR_[8]); } else { right(Complex(ZERO)); left (Complex(0., 1.)*massLast_[0] *cR_[8]); } } else { if(iferm%2==0) { left (Complex(0.,-1.)*model_->vev()*cL_[8]); right(Complex(0., 1.)*massLast_[0] *cR_[8]); } else { left (Complex(ZERO)); right(Complex(0.,-1.)*massLast_[0] *cR_[8]); } } } else if(iferm>=12) { if( (a->id()>=11&&a->id()<=16) || (b->id()>=11&&b->id()<=16) ) { right(Complex(0., 1.)*model_->vev()*cL_[9]); left (Complex(0.,-1.)*massLast_[0] *cR_[9]); } else { right(Complex(0.,-1.)*massLast_[0] *cR_[9]); left (Complex(0., 1.)*model_->vev()*cL_[9]); } } else { if(ianti==4000008) { unsigned int iloc = (iferm+14)/2; if( (a->id()==6||a->id()==8) || (b->id()==6||b->id()==8) ) { left (Complex(0., 1.)*massLast_[0]*cR_[iloc]); right(Complex(0., 1.)*massLast_[0]*cL_[iloc]); } else { left (Complex(0.,-1.)*massLast_[0]*cL_[iloc]); right(Complex(0.,-1.)*massLast_[0]*cR_[iloc]); } } else { unsigned int iloc = (iferm+18)/2; if( (a->id()==6||a->id()==8) || (b->id()==6||b->id()==8) ) { left (Complex(0., 1.)*model_->vev()*cL_[iloc]); right(Complex(0.,-1.)*massLast_[0] *cR_[iloc]); } else { left (Complex(0., 1.)*massLast_[0] *cR_[iloc]); right(Complex(0.,-1.)*model_->vev()*cL_[iloc]); } } } } } else if(abs(c->id())==ParticleID::Hplus) { tcPDPtr ferm = a; if(iferm>4000000) { swap(iferm,ianti); ferm = b; } if(q2!=q2Last_||idLast_[0]!=iferm) { q2Last_ = q2; idLast_[0] = iferm; assert((idLast_[0]>=1 && idLast_[0]<=8 ) || (idLast_[0]>=11 && idLast_[0]<=16)); if(idLast_[0]!=8) massLast_[0] = model_->mass(q2,ferm); else massLast_[0] = model_->mass(q2,getParticleData(ParticleID::t)); } Complex cleft(0.),cright(0.); // lepton and T-odd lepton if(iferm>=11&&iferm<=16) { cright = cR_[14]*massLast_[0]; cleft = cL_[14]*model_->vev(); } else if(iferm>=1&&iferm<=6) { cright = cR_[15]*massLast_[0]; cleft = cL_[15]*model_->vev(); } else if(iferm==6) { cright = cR_[16]*massLast_[0]; cleft = cL_[16]*model_->vev(); } else if(iferm==8) { cright = cR_[17]*massLast_[0]; cleft = cL_[17]*model_->vev(); } if((a->id()>=1&&a->id()<=16) ||(b->id()>=1&&b->id()<=16) ) { swap(cleft,cright); cleft *= -1.; cright *= -1.; } if(c->id()==ParticleID::Hminus) { cleft *= -1.; cright *= -1.; } left (cleft ); right(cright); } } diff --git a/Models/LHTP/LHTPFFPVertex.cc b/Models/LHTP/LHTPFFPVertex.cc --- a/Models/LHTP/LHTPFFPVertex.cc +++ b/Models/LHTP/LHTPFFPVertex.cc @@ -1,193 +1,194 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the LHTPFFPVertex class. // #include "LHTPFFPVertex.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Utilities/DescribeClass.h" #include "LHTPModel.h" using namespace Herwig; IBPtr LHTPFFPVertex::clone() const { return new_ptr(*this); } IBPtr LHTPFFPVertex::fullclone() const { return new_ptr(*this); } void LHTPFFPVertex::persistentOutput(PersistentOStream & os) const { os << charge_ << coupd_ << coupu_ << coupe_ << coupnu_ << TPreFactor_ << sL_ << cL_ << sR_ << cR_; } void LHTPFFPVertex::persistentInput(PersistentIStream & is, int) { is >> charge_ >> coupd_ >> coupu_ >> coupe_ >> coupnu_ >> TPreFactor_ >> sL_ >> cL_ >> sR_ >> cR_; } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigLHTPFFPVertex("Herwig::LHTPFFPVertex", "HwLHTPModel.so"); void LHTPFFPVertex::Init() { static ClassDocumentation documentation ("The LHTPFFPVertex class implements the coupling" " of the charged fermions to the photon in the Little Higgs" " model with T-parity."); } LHTPFFPVertex::LHTPFFPVertex() : charge_(37,0.0), coupLast_(0.), q2Last_(-1.*GeV2), coupd_(0.), coupu_(0.), coupe_(0.), coupnu_(0.), TPreFactor_(0.), sL_(0.), cL_(1.), sR_(0.), cR_(1.) { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::DELTA); } void LHTPFFPVertex::doinit() { // interactions with the photon // the quarks for(int ix = 1; ix < 7; ++ix) { addToList(-ix, ix, 22); } // the leptons for(int ix = 11; ix < 17; ix += 2) { addToList(-ix, ix, 22); } // extra top quark addToList(-8, 8, 22); // the T-odd quarks for(long ix = 4000001;ix < 4000007; ++ix) { addToList(-ix, ix, 22); } // the T-odd leptons for(long ix = 4000011; ix < 4000017; ix += 2) { addToList(-ix, ix, 22); } // extra top quark addToList(-4000008, 4000008, 22); // interactions with A_H // quarks and T-odd quark for(int ix = 1; ix < 7; ++ix) { addToList(-ix - 4000000, ix , 32); addToList(-ix , ix + 4000000, 32); } // leptons and T-odd leptons (both charged leptons and neutrinos) for(int ix = 11; ix < 17; ++ix ) { addToList(-ix - 4000000, ix , 32); addToList(-ix , ix + 4000000, 32); } // T+T-A_H addToList(-4000008, 8, 32); addToList( -8, 4000008, 32); // T-tA_H addToList(-4000008, 6, 32); addToList( -6, 4000008, 32); // T-tA_H addToList(-4000006, 8, 32); addToList( -8, 4000006, 32); // charges for(int ix = 1; ix < 16; ++ix) { tcPDPtr ptemp = getParticleData(ix); if(ptemp) charge_[ix] = double(ptemp->iCharge())/3.; } for(int ix = 4000001; ix < 4000016; ++ix) { tcPDPtr ptemp = getParticleData(ix); if(ptemp) charge_[ix-3999980] = double(ptemp->iCharge())/3.; } // couplings to A_H double sw = generator()->standardModel()->sin2ThetaW(); double cw = sqrt(1.-sw); sw = sqrt(sw); // model cLHTPModelPtr model = dynamic_ptr_cast(generator()->standardModel()); if(!model) throw InitException() << "Must be using the LHTPModel " << " in LHTPFFPVertex::doinit()" << Exception::runerror; double cH = model->cosThetaH(); double sH = model->sinThetaH(); sL_ = model->sinThetaL(); cL_ = model->cosThetaL(); sR_ = model->sinThetaR(); cR_ = model->cosThetaR(); // couplings of fermion T-odd fermion A_H coupd_ = -0.1*(cH/cw-5.*sH/sw); coupu_ = -0.1*(cH/cw+5.*sH/sw); coupe_ = -0.1*(cH/cw-5.*sH/sw); coupnu_ = -0.1*(cH/cw+5.*sH/sw); // couplings of T+T- A_H TPreFactor_ = 0.4*cH/cw; FFVVertex::doinit(); } // coupling for FFP vertex void LHTPFFPVertex::setCoupling(Energy2 q2,tcPDPtr a,tcPDPtr b,tcPDPtr c) { // first the overall normalisation if(q2!=q2Last_) { coupLast_ = -electroMagneticCoupling(q2); q2Last_=q2; } norm(coupLast_); // the left and right couplings long iferm=abs(a->id()),ibos(c->id()); if(ibos == ParticleID::gamma) { if(iferm < 20) { left (charge_[iferm]); right(charge_[iferm]); } else { iferm-=3999980; left (charge_[iferm]); right(charge_[iferm]); } } else if(ibos == 32) { long ianti = abs(b->id()); if(iferm>4000000) swap(iferm,ianti); assert(iferm<4000000&&ianti>4000000); if( iferm == 6 || iferm == 8 ) { if (iferm==6&&ianti==4000006) { left (cL_*coupu_); right(0.); } else if(iferm==6&&ianti==4000008) { left (-TPreFactor_*sL_); right(-TPreFactor_*sR_); } else if(iferm==8&&ianti==4000006) { left (sL_*coupu_); right(0.); } else if(iferm==8&&ianti==4000008) { left ( TPreFactor_*cL_); right( TPreFactor_*cR_); } else assert(false); } // quarks (inclding top) else if(iferm <= 5) { if(iferm % 2 == 0) left(coupu_); else left(coupd_); right(0.); } // leptons else { if(iferm %2 == 0) left(coupnu_); else left(coupe_ ); right(0.); } } else assert(false); } diff --git a/Models/LHTP/LHTPFFWVertex.cc b/Models/LHTP/LHTPFFWVertex.cc --- a/Models/LHTP/LHTPFFWVertex.cc +++ b/Models/LHTP/LHTPFFWVertex.cc @@ -1,199 +1,200 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the LHTPFFWVertex class. // #include "LHTPFFWVertex.h" #include "LHTPModel.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/StandardModel/CKMBase.h" #include "Herwig/Models/StandardModel/StandardCKM.h" using namespace Herwig; IBPtr LHTPFFWVertex::clone() const { return new_ptr(*this); } IBPtr LHTPFFWVertex::fullclone() const { return new_ptr(*this); } void LHTPFFWVertex::persistentOutput(PersistentOStream & os) const { os << ckm_ << sL_ << cL_; } void LHTPFFWVertex::persistentInput(PersistentIStream & is, int) { is >> ckm_ >> sL_ >> cL_; } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigLHTPFFWVertex("Herwig::LHTPFFWVertex", "HwLHTPModel.so"); void LHTPFFWVertex::Init() { static ClassDocumentation documentation ("The LHTPFFWVertex class implements the couplings of the W" " and W_H bosons of the Little Higgss model with T-parity to the fermions."); } void LHTPFFWVertex::doinit() { // particles for outgoing W- // quarks for(int ix = 1; ix < 6; ix += 2) { for(int iy = 2; iy < 7; iy += 2) { addToList(-ix, iy, -24); } } // additional T quark addToList(-5, 8, -24); // leptons for(int ix = 11; ix < 17; ix += 2) { addToList(-ix, ix + 1, -24); } // T-odd quarks for(long ix = 4000002; ix < 4000007; ix += 2) { addToList(-ix + 1, ix, -24); } // T-odd leptons for(long ix = 4000011; ix < 4000017; ix += 2) { addToList(-ix, ix + 1, -24); } // particles for outgoing W+ // quarks for(int ix = 2; ix < 7; ix += 2) { for(int iy = 1; iy < 6; iy += 2) { addToList(-ix, iy, 24); } } // additional T quark addToList(-8, 5, 24); // leptons for(int ix = 11; ix < 17; ix += 2) { addToList(-ix - 1, ix, 24); } // T-odd quarks for(long ix = 4000002; ix < 4000009; ix += 2) { addToList(-ix, ix-1, 24); } // T-odd leptons for(long ix = 4000011; ix < 4000017; ix += 2) { addToList(-ix-1, ix, 24); } // particles for W_H- // quark and T-odd quark for(int ix = 1; ix < 6; ix += 2) { addToList(-ix-4000000, ix+1, -34); addToList(-ix, ix+1+4000000, -34); } addToList(-4000005, 8, -34); // lepton and T-odd lepton for(int ix = 11;ix < 17; ix += 2) { addToList(-ix-4000000, ix+1, -34); addToList(-ix, ix+1+4000000, -34); } // particles for w_h+ // quark and T-odd quark for(int ix = 1;ix < 6;ix += 2) { addToList(ix + 4000000, -ix - 1, 34); addToList(ix, -ix - 4000001, 34); } addToList(4000005, -8, 34); // leptons and T-odd lepton for(int ix = 11; ix < 17; ix += 2) { addToList(-ix - 4000001, ix, 34); addToList(-ix - 1, ix + 4000000, 34); } ThePEG::Helicity::FFVVertex::doinit(); Ptr::transient_pointer CKM = generator()->standardModel()->CKM(); // cast the CKM object to the HERWIG one ThePEG::Ptr::transient_const_pointer hwCKM = ThePEG::dynamic_ptr_cast< ThePEG::Ptr:: transient_const_pointer>(CKM); if(hwCKM) { vector< vector > CKM; CKM = hwCKM->getUnsquaredMatrix(generator()->standardModel()->families()); for(unsigned int ix=0;ix<3;++ix) { for(unsigned int iy=0;iy<3;++iy) { ckm_[ix][iy]=CKM[ix][iy]; } } } else { throw InitException() << "Must have access to the Herwig::StandardCKM object" << "for the CKM matrix in LHTPFFWVertex::doinit()" << Exception::runerror; } // model cLHTPModelPtr model = dynamic_ptr_cast(generator()->standardModel()); if(!model) throw InitException() << "Must be using the LHTPModel " << " in LHTPFFWVertex::doinit()" << Exception::runerror; sL_ = model->sinThetaL(); cL_ = model->cosThetaL(); } LHTPFFWVertex::LHTPFFWVertex() : sL_(0.), cL_(1.), ckm_(3,vector(3,0.0)), coupLast_(0.),q2Last_(ZERO) { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::DELTA); } // coupling for FFW vertex void LHTPFFWVertex::setCoupling(Energy2 q2, tcPDPtr a, tcPDPtr b, tcPDPtr c) { // first the overall normalisation if(q2!=q2Last_) { coupLast_ = -sqrt(0.5)*weakCoupling(q2); q2Last_ = q2; } norm(coupLast_); long ia(abs(a->id())),ib(abs(b->id())); // SM W boson if(abs(c->id())==ParticleID::Wplus) { // quarks if(ia >= 1 && ia <= 8 && ib >= 1 && ib <= 8 ) { int iu,id; // up type first if(ia % 2 == 0) { iu = ia/2; id = (ib+1)/2; } // down type first else { iu = ib/2; id = (ia+1)/2; } if(iu==4) iu=3; assert( iu>=1 && iu<=3 && id>=1 && id<=3); if ( ia==6 || ib==6 ) left(ckm_[iu-1][id-1]*cL_); else if ( ia==8 || ib==8 ) left(ckm_[iu-1][id-1]*sL_); else left(ckm_[iu-1][id-1] ); right(0.); } // leptons else if( ia >= 11 && ia <= 16) { left(1.); right(0.); } else { left (1.); right(1.); } } else { if(ia==6||ib==6) left(-cL_); else if(ia==8||ib==8) left(-sL_); else left(-1. ); right(0.); } } diff --git a/Models/LHTP/LHTPFFZVertex.cc b/Models/LHTP/LHTPFFZVertex.cc --- a/Models/LHTP/LHTPFFZVertex.cc +++ b/Models/LHTP/LHTPFFZVertex.cc @@ -1,232 +1,233 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the LHTPFFZVertex class. // #include "LHTPFFZVertex.h" #include "LHTPModel.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; IBPtr LHTPFFZVertex::clone() const { return new_ptr(*this); } IBPtr LHTPFFZVertex::fullclone() const { return new_ptr(*this); } void LHTPFFZVertex::persistentOutput(PersistentOStream & os) const { os << gl_ << gr_ << tl_ << tr_ << coupd_ << coupu_ << coupe_ << coupnu_ << sL_ << cL_ << sR_ << cR_; } void LHTPFFZVertex::persistentInput(PersistentIStream & is, int) { is >> gl_ >> gr_ >> tl_ >> tr_ >> coupd_ >> coupu_ >> coupe_ >> coupnu_ >> sL_ >> cL_ >> sR_ >> cR_; } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigLHTPFFZVertex("Herwig::LHTPFFZVertex", "HwLHTPModel.so"); void LHTPFFZVertex::Init() { static ClassDocumentation documentation ("The LHTPFFZVertex class implements the couplings of " "the fermions to the Z boson and its heavy partner in the" " Little Higgs model with T-parity."); } LHTPFFZVertex::LHTPFFZVertex() : gl_(37,0.0), gr_(37,0.0), tl_( 6,0.0), tr_( 6,0.0), coupd_(0.), coupu_(0.), coupe_(0.), coupnu_(0.), sL_(0.), cL_(1.), sR_(0.), cR_(1.), coupLast_(0.0), q2Last_(0.*GeV2) { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::DELTA); } void LHTPFFZVertex::doinit() { // Z // the quarks for(int ix = 1; ix < 7; ++ix) { addToList(-ix, ix, 23); } // T+T+ addToList(-8, +8, 23); //T+t addToList(-6, +8, 23); addToList(-8, +6, 23); // the leptons for(int ix = 11; ix < 17; ++ix) { addToList(-ix, ix, 23); } // the T-odd quarks for(long ix = 4000001; ix < 4000007; ++ix) { addToList(-ix, ix, 23); } addToList(-4000008, +4000008, 23); // the T-odd leptons for(long ix = 11;ix<17;++ix) { addToList(-ix-4000000, ix+4000000, 23); } // Z_H // the quarks for(int ix=1;ix<7;++ix) { addToList(-ix-4000000, ix, 33); addToList(-ix, ix+4000000, 33); } addToList( -8, +4000008, 33); addToList( 8, -4000008, 33); addToList( -6, +4000008, 33); addToList( 6, -4000008, 33); // the leptons for(int ix=11;ix<17;++ix) { addToList(-ix-4000000, ix, 33); addToList(-ix, ix+4000000, 33); } // model cLHTPModelPtr model = dynamic_ptr_cast(generator()->standardModel()); if(!model) throw InitException() << "Must be using the LHTPModel " << " in LHTPFFPVertex::doinit()" << Exception::runerror; double sw = model->sin2ThetaW(); double cw = sqrt(1.-sw); sw = sqrt(sw); double fact = 0.25/sw/cw; for(int ix=1;ix<4;++ix) { // SM fermions gl_[2*ix-1] = fact*(model->vd() + model->ad() ); gl_[2*ix ] = fact*(model->vu() + model->au() ); gl_[2*ix+9 ] = fact*(model->ve() + model->ae() ); gl_[2*ix+10] = fact*(model->vnu() + model->anu()); gr_[2*ix-1] = fact*(model->vd() - model->ad() ); gr_[2*ix ] = fact*(model->vu() - model->au() ); gr_[2*ix+9 ] = fact*(model->ve() - model->ae() ); gr_[2*ix+10] = fact*(model->vnu() - model->anu()); // T-odd fermions gl_[2*ix-1 +20] = fact*(model->vd() + model->ad() ); gl_[2*ix +20] = fact*(model->vu() + model->au() ); gl_[2*ix+9 +20] = fact*(model->ve() + model->ae() ); gl_[2*ix+10+20] = fact*(model->vnu() + model->anu()); gr_[2*ix-1 +20] = gl_[2*ix-1 +20]; gr_[2*ix +20] = gl_[2*ix +20]; gr_[2*ix+9 +20] = gl_[2*ix+9 +20]; gr_[2*ix+10+20] = gl_[2*ix+10+20]; } // couplngis to Z for extended top sector tl_[0] = (0.5*sqr(model->cosThetaL())-2./3.*sqr(sw))/cw/sw; tr_[0] = -2./3.*sw/cw; tl_[1] = (0.5*sqr(model->sinThetaL())-2./3.*sqr(sw))/cw/sw; tr_[1] = -2./3.*sw/cw; tl_[2] = 0.5/sw/cw*model->sinThetaL()*model->cosThetaL(); tr_[2] = 0.; // couplings to the Z_H of T-odd fermions double cH = model->cosThetaH(); double sH = model->sinThetaH(); sL_ = model->sinThetaL(); cL_ = model->cosThetaL(); sR_ = model->sinThetaR(); cR_ = model->cosThetaR(); coupd_ = 0.1*(sH/cw+5.*cH/sw); coupu_ = 0.1*(sH/cw-5.*cH/sw); coupe_ = 0.1*(sH/cw+5.*cH/sw); coupnu_ = 0.1*(sH/cw-5.*cH/sw); tl_[5] = -2./3.*sw/cw; tr_[5] = -2./3.*sw/cw; // couplings of T-odd top to the Z_H tl_[3] = 0.4*sH*sL_/cw; tr_[3] = 0.4*sH*sR_/cw; tl_[4] =-0.4*sH*cL_/cw; tr_[4] =-0.4*sH*cR_/cw; // base class initialisation FFVVertex::doinit(); } void LHTPFFZVertex::setCoupling(Energy2 q2,tcPDPtr a,tcPDPtr b,tcPDPtr c) { // first the overall normalisation if(q2!=q2Last_) { coupLast_ = -electroMagneticCoupling(q2); q2Last_=q2; } norm(coupLast_); // the left and right couplings long iferm = abs(a->id()); long ianti = abs(b->id()); long ibos = c->id(); if(ibos == ParticleID::Z0) { if(iferm == 8 || iferm == 6) { if(iferm == 6 && ianti == 6) { left (tl_[0]); right(tr_[0]); } else if(iferm == 8 && ianti == 8) { left (tl_[1]); right(tr_[1]); } else { left (tl_[2]); right(tr_[2]); } } else if(iferm == 4000008) { left (tl_[5]); right(tr_[5]); } else if((iferm >= 1 && iferm <= 6)|| (iferm >= 11 && iferm <= 16)) { left (gl_[iferm]); right(gr_[iferm]); } else { iferm = (iferm % 4000000) + 20; left (gl_[iferm]); right(gr_[iferm]); } } else if(ibos == 33) { if(iferm>4000000) swap(iferm,ianti); assert(iferm<4000000&&ianti>4000000); if( iferm == 6 || iferm == 8 ) { if (iferm==6&&ianti==4000006) { left (cL_*coupu_); right(0.); } else if(iferm==6&&ianti==4000008) { left (tl_[3]); right(tr_[3]); } else if(iferm==8&&ianti==4000006) { left (sL_*coupu_); right(0.); } else if(iferm==8&&ianti==4000008) { left ( tl_[4]); right( tr_[4]); } else assert(false); } else { right(0.); if(iferm <= 6) { if(iferm % 2 == 0) left( coupu_ ); else left( coupd_ ); } else { if(iferm % 2 == 0) left( coupnu_ ); else left( coupe_ ); } } } else assert(false); } diff --git a/Models/LHTP/LHTPHHHVertex.cc b/Models/LHTP/LHTPHHHVertex.cc --- a/Models/LHTP/LHTPHHHVertex.cc +++ b/Models/LHTP/LHTPHHHVertex.cc @@ -1,75 +1,76 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the LHTPHHHVertex class. // #include "LHTPHHHVertex.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; LHTPHHHVertex::LHTPHHHVertex() : ratio_(ZERO), coupLast_(0.), q2Last_(ZERO) { orderInGem(1); orderInGs (0); + colourStructure(ColourStructure::SINGLET); } IBPtr LHTPHHHVertex::clone() const { return new_ptr(*this); } IBPtr LHTPHHHVertex::fullclone() const { return new_ptr(*this); } void LHTPHHHVertex::persistentOutput(PersistentOStream & os) const { os << ounit(ratio_,GeV); } void LHTPHHHVertex::persistentInput(PersistentIStream & is, int) { is >> iunit(ratio_,GeV); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigLHTPHHHVertex("Herwig::LHTPHHHVertex", "HwLHTPModel.so"); void LHTPHHHVertex::Init() { static ClassDocumentation documentation ("The LHTPHHHVertex class implements the trilinear Higgs boson" " self couplings in the Little Higgs model with T-parity"); } void LHTPHHHVertex::doinit() { addToList(25,25, 25); addToList(25,35, 35); addToList(25,36, 36); addToList(25,37,-37); SSSVertex::doinit(); ratio_ = sqr(getParticleData(ParticleID::h0)->mass())/ getParticleData(ParticleID::Wplus)->mass(); } void LHTPHHHVertex::setCoupling(Energy2 q2,tcPDPtr part1,tcPDPtr part2,tcPDPtr) { if(q2!=q2Last_||coupLast_==0.) { coupLast_ = weakCoupling(q2)*ratio_*UnitRemoval::InvE; q2Last_=q2; } long id = part2->id()!=ParticleID::h0 ? abs(part2->id()) : abs(part1->id()); if(id==ParticleID::h0) norm( -coupLast_); else if(id==35) norm( 3.*coupLast_); else if(id==36) norm( 3.*coupLast_); else if(id==37) norm(1.5*coupLast_); else assert(false); } diff --git a/Models/LHTP/LHTPWHHVertex.cc b/Models/LHTP/LHTPWHHVertex.cc --- a/Models/LHTP/LHTPWHHVertex.cc +++ b/Models/LHTP/LHTPWHHVertex.cc @@ -1,201 +1,202 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the LHTPWHHVertex class. // #include "LHTPWHHVertex.h" #include "LHTPModel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; LHTPWHHVertex::LHTPWHHVertex() : coupLast_(0.), q2Last_(ZERO), coup_(11) { orderInGs(0); orderInGem(1); + colourStructure(ColourStructure::SINGLET); } IBPtr LHTPWHHVertex::clone() const { return new_ptr(*this); } IBPtr LHTPWHHVertex::fullclone() const { return new_ptr(*this); } void LHTPWHHVertex::persistentOutput(PersistentOStream & os) const { os << coup_; } void LHTPWHHVertex::persistentInput(PersistentIStream & is, int) { is >> coup_; } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigLHTPWHHVertex("Herwig::LHTPWHHVertex", "HwLHTPModel.so"); void LHTPWHHVertex::Init() { static ClassDocumentation documentation ("The LHTPWHHVertex class implements the coupling of a pair of Higgs" " bosons to an electroweak gauge boson in the Little" " Higgs model with T-parity."); } void LHTPWHHVertex::doinit() { // photon addToList( 22, 37,-37); addToList( 22, 38,-38); // Z0 addToList( 23, 37,-37); addToList( 23, 38,-38); addToList( 23, 35, 36); // W+ addToList( 24, 35,-37); addToList( 24, 36,-37); addToList( 24, 37,-38); // W- addToList(-24, 35, 37); addToList(-24, 36, 37); addToList(-24,-37, 38); // A_H addToList( 32, 25, 36); // Z_H addToList( 33, 25, 36); // W_H addToList( 34, 25,-37); addToList(-34, 25, 37); VSSVertex::doinit(); // model cLHTPModelPtr model = dynamic_ptr_cast(generator()->standardModel()); if(!model) throw InitException() << "Must be using the LHModel " << " in LHWWWWVertex::doinit()" << Exception::runerror; double sw2(sin2ThetaW()); double sw(sqrt(sw2)),cw(sqrt(1.-sw2)); double vf(model->vev()/model->f()); coup_[ 0] = 1.; coup_[ 1] = 2.; coup_[ 2] =-sw/cw; coup_[ 3] = (1.-2.*sw2)/cw/sw; coup_[ 4] =-Complex(0.,1.)/cw/sw; coup_[ 5] = sqrt(0.5)/sw; coup_[ 6] = Complex(0.,1.)/sw*sqrt(0.5); coup_[ 7] = 1./sw; coup_[ 8] = Complex(0.,1)*sqrt(0.5)*vf/3./cw; coup_[ 9] = Complex(0.,1)*sqrt(0.5)*vf/3./sw; coup_[10] =-vf/6./sw; } void LHTPWHHVertex::setCoupling(Energy2 q2, tcPDPtr particle1, tcPDPtr particle2, tcPDPtr particle3) { if( q2 != q2Last_ || coupLast_==0.) { q2Last_ = q2; coupLast_ = electroMagneticCoupling(q2); } int ibos = particle1->id(); int isc1 = particle2->id(); int isc2 = particle3->id(); if(ibos==ParticleID::gamma) { if(isc1==37) norm(coup_[0]*coupLast_); else if(isc1==38) norm(coup_[1]*coupLast_); else if(isc1==-37) norm(-coup_[0]*coupLast_); else if(isc1==-38) norm(-coup_[1]*coupLast_); else assert(false); } else if(ibos==ParticleID::Z0) { if(isc1==37) norm(coup_[2]*coupLast_); else if(isc1==38) norm(coup_[3]*coupLast_); else if(isc1==-37) norm(-coup_[2]*coupLast_); else if(isc1==-38) norm(-coup_[3]*coupLast_); else if(isc1==35) norm(coup_[4]*coupLast_); else if(isc2==35) norm(-coup_[4]*coupLast_); else assert(false); } else if(ibos==ParticleID::Wplus) { if(isc1==35) norm(coup_[5]*coupLast_); else if(isc1==36) norm(coup_[6]*coupLast_); else if(isc1==-38) norm(-coup_[7]*coupLast_); else if(isc2==35) norm(-coup_[5]*coupLast_); else if(isc2==36) norm(-coup_[6]*coupLast_); else if(isc2==-38) norm( coup_[7]*coupLast_); else assert(false); } else if(ibos==ParticleID::Wminus) { if(isc1==35) norm(conj(coup_[5])*coupLast_); else if(isc1==36) norm(conj(coup_[6])*coupLast_); else if(isc1==38) norm(-conj(coup_[7])*coupLast_); else if(isc2==35) norm(-conj(coup_[5])*coupLast_); else if(isc2==36) norm(-conj(coup_[6])*coupLast_); else if(isc2==38) norm( conj(coup_[7])*coupLast_); else assert(false); } else if(ibos==32) { if(isc1==25) norm( coup_[8]*coupLast_); else if(isc2==25) norm(-coup_[8]*coupLast_); else assert(false); } else if(ibos==33) { if(isc1==25) norm( coup_[9]*coupLast_); else if(isc2==25) norm(-coup_[9]*coupLast_); else assert(false); } else if(ibos==34) { if(isc1==25) norm( coup_[10]*coupLast_); else if(isc2==25) norm(-coup_[10]*coupLast_); else assert(false); } else if(ibos==-34) { if(isc1==25) norm( conj(coup_[10])*coupLast_); else if(isc2==25) norm(-conj(coup_[10])*coupLast_); else assert(false); } else assert(false); } diff --git a/Models/LHTP/LHTPWWHVertex.cc b/Models/LHTP/LHTPWWHVertex.cc --- a/Models/LHTP/LHTPWWHVertex.cc +++ b/Models/LHTP/LHTPWWHVertex.cc @@ -1,188 +1,189 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the LHTPWWHVertex class. // #include "LHTPWWHVertex.h" #include "LHTPModel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; IBPtr LHTPWWHVertex::clone() const { return new_ptr(*this); } IBPtr LHTPWWHVertex::fullclone() const { return new_ptr(*this); } void LHTPWWHVertex::persistentOutput(PersistentOStream & os) const { os << ounit(coup_,GeV); } void LHTPWWHVertex::persistentInput(PersistentIStream & is, int) { is >> iunit(coup_,GeV); } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigLHTPWWHVertex("Herwig::LHTPWWHVertex", "HwLHTPModel.so"); void LHTPWWHVertex::Init() { static ClassDocumentation documentation ("The LHTPWWHVertex class implements the coupling of two electroweak" " gauge bosons to a Higgs boson in the Little Higgs Model with T-Parity" "including the additional heavy photon, Z and W bosons and the " "triplet Higgs bosons."); } LHTPWWHVertex::LHTPWWHVertex() : coupLast_(0.), q2Last_(0.*GeV2) { // order in the couplings orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::SINGLET); } void LHTPWWHVertex::doinit() { // W_L W_L H addToList( 24, -24, 25); // Z_L Z_L H addToList( 23, 23, 25); // W_H W_H H addToList( 34, -34, 25); // Z_H Z_H H addToList( 33, 33, 25); // A_H A_H H addToList( 32, 32, 25); // Z_H A_H H addToList( 33, 32, 25); // Z_L Z_H Phi0 addToList( 23, 33, 35); // A_H Z_L Phi0 addToList( 32, 23, 35); // W_L W_H PhiP addToList( 24, -34, 36); addToList( 34, -24, 36); // W_H Z_L Phi+/- addToList( 34, 23, -37); addToList( -34, 23, 37); // W_L A_H Phi+/- addToList( 24, 32, -37); addToList( -24, 32, 37); // W_L Z_H Phi+/- addToList( 24, 33, -37); addToList( -24, 33, 37); // W_H A_L Phi+/- addToList( 34, 22, -37); addToList( -34, 22, 37); // W_L W_H Phi --/++ addToList( 24, 34, -38); addToList( -24, -34, 38); // model cLHTPModelPtr model = dynamic_ptr_cast(generator()->standardModel()); if(!model) throw InitException() << "Must be using the LHTPModel " << " in LHTPWWHVertex::doinit()" << Exception::runerror; // base class VVSVertex::doinit(); // calculate the couplings for the different combinations of particles Energy fact = 0.5*model->vev()/model->sin2ThetaW(); double sw(sqrt(model->sin2ThetaW())),cw(sqrt(1.-model->sin2ThetaW())); double vf(model->vev()/model->f()); double r2(sqrt(2.)); coup_.resize(14); // H coup_[ 0] = fact *(1.-sqr(vf)/3.); coup_[ 1] = fact/sqr(cw)*(1.-sqr(vf)/3.); coup_[ 2] =-fact; coup_[ 3] =-fact; coup_[ 4] =-fact*sqr(sw/cw); coup_[ 5] =-fact/cw*sw; // PhiP coup_[ 6] = r2*fact*vf/3.; // Phi0 coup_[ 7] =-fact*vf/r2/cw; coup_[ 8] = fact*vf/r2*sw/sqr(cw); // Phi+ coup_[ 9] = fact*vf/6./cw*(1.+2.*sqr(sw)); coup_[10] = fact*vf*sw/cw*0.5; coup_[11] = fact*vf*5./6.; coup_[12] =-fact*vf*sw/3.; // Phi++ coup_[13] =-fact*vf; } void LHTPWWHVertex::setCoupling(Energy2 q2,tcPDPtr a, tcPDPtr b, tcPDPtr c) { // first the overall normalisation if(q2!=q2Last_) { coupLast_ = sqr(electroMagneticCoupling(q2)); q2Last_=q2; } long ih = abs(c->id()); long ibos[2]={abs(a->id()),abs(b->id())}; if(ih == 25) { if( ibos[0] == 24 && ibos[1] == 24) norm(UnitRemoval::InvE *coupLast_*coup_[0]); else if( ibos[0] == 23 && ibos[1] == 23 ) norm(UnitRemoval::InvE *coupLast_*coup_[1]); else if( ibos[0] == 34 && ibos[1] == 34 ) norm(UnitRemoval::InvE *coupLast_*coup_[2]); else if( ibos[0] == 33 && ibos[1] == 33 ) norm(UnitRemoval::InvE *coupLast_*coup_[3]); else if( ibos[0] == 32 && ibos[1] == 32 ) norm(UnitRemoval::InvE *coupLast_*coup_[4]); else if((ibos[0] == 33 && ibos[1] == 32) || (ibos[0] == 32 && ibos[1] == 33) ) norm(UnitRemoval::InvE *coupLast_*coup_[5]); else assert(false); } else if(ih == 36) { if( a->id() == 34 || b->id() == 34) norm( Complex(0.,1.)*UnitRemoval::InvE *coupLast_*coup_[6]); else norm(-Complex(0.,1.)*UnitRemoval::InvE *coupLast_*coup_[6]); } else if(ih == 35) { if((ibos[0] == 23 && ibos[1] == 33) || (ibos[0] == 33 && ibos[1] == 23) ) norm(UnitRemoval::InvE *coupLast_*coup_[7]); else if((ibos[0] == 23 && ibos[1] == 32) || (ibos[0] == 32 && ibos[1] == 23) ) norm(UnitRemoval::InvE *coupLast_*coup_[8]); else assert(false); } else if(ih == 37) { if((ibos[0] == 34 && ibos[1] == 23) || (ibos[0] == 23 && ibos[1] == 34) ) { norm(UnitRemoval::InvE *coupLast_*coup_[ 9]); } else if((ibos[0] == 24 && ibos[1] == 32) || (ibos[0] == 32 && ibos[1] == 24) ) norm(UnitRemoval::InvE *coupLast_*coup_[10]); else if((ibos[0] == 24 && ibos[1] == 33) || (ibos[0] == 33 && ibos[1] == 24) ) norm(UnitRemoval::InvE *coupLast_*coup_[11]); else if((ibos[0] == 34 && ibos[1] == 22) || (ibos[0] == 22 && ibos[1] == 34) ) norm(UnitRemoval::InvE *coupLast_*coup_[12]); else assert(false); } else if(ih == 38) { norm(UnitRemoval::InvE *coupLast_*coup_[13]); } else assert(false); } diff --git a/Models/LHTP/LHTPWWWVertex.cc b/Models/LHTP/LHTPWWWVertex.cc --- a/Models/LHTP/LHTPWWWVertex.cc +++ b/Models/LHTP/LHTPWWWVertex.cc @@ -1,140 +1,141 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the LHTPWWWVertex class. // #include "LHTPWWWVertex.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "LHTPModel.h" using namespace Herwig; LHTPWWWVertex::LHTPWWWVertex() : coupLast_(0.), q2Last_(ZERO), couplings_(3 ,0.) { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::SINGLET); } void LHTPWWWVertex::persistentOutput(PersistentOStream & os) const { os << couplings_; } void LHTPWWWVertex::persistentInput(PersistentIStream & is, int) { is >> couplings_; } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigLHTPWWWVertex("Herwig::LHTPWWWVertex", "HwLHTPModel.so"); void LHTPWWWVertex::Init() { static ClassDocumentation documentation ("The LHTPWWWVertex class implements the coupling of three " "electroweak gauge bosons and their heavy partners in the " "Little Higgs model with T-parity."); } void LHTPWWWVertex::doinit() { //SM interactions addToList( 24, -24, 22); addToList( 24, -24, 23); //LHTP //W_H W_H A_L addToList( 34, -34, 22); //W_H W_H Z_L addToList( 34, -34, 23); //W_H W_L A_H addToList( 34, -24, 32); addToList( 24, -34, 32); //W_H W_L Z_H addToList( 34, -24, 33); addToList( 24, -34, 33); VVVVertex::doinit(); cLHTPModelPtr model = dynamic_ptr_cast(generator()->standardModel()); if( !model ) throw InitException() << "LHTPWWWVertex::doinit() - Model pointer must be of LHTPModel" << "type, cannot continue without this." << Exception::abortnow; double sw(sqrt(model->sin2ThetaW())); double cw(sqrt(1. - model->sin2ThetaW())); //W W Z couplings_[0] = cw/sw; //W_L W_H A_H couplings_[1] = model->sinThetaH()/sw; //W_L W_H Z_H couplings_[2] = 1./sw; } void LHTPWWWVertex::setCoupling(Energy2 q2,tcPDPtr a,tcPDPtr b,tcPDPtr c) { if(q2 != q2Last_) { coupLast_ = electroMagneticCoupling(q2); q2Last_ = q2; } int ida=a->id(); int idb=b->id(); int idc=c->id(); // get the PDG code for the neutral boson long boson(0); if(!a->charged()) { boson = ida; ida = 22; } else if(abs(ida) !=ParticleID::Wplus) { ida = ida > 0 ? 24 : -24; } if(!b->charged()) { boson = idb; idb = 22; } else if(abs(idb) !=ParticleID::Wplus) { idb = idb > 0 ? 24 : -24; } if(!c->charged()) { boson = idc; idc = 22; } else if(abs(idc) !=ParticleID::Wplus) { idc = idc > 0 ? 24 : -24; } assert( boson ==22 || boson==23 || boson==32 || boson==33); // get the prefactor double pre(0.); switch (boson) { case 22: pre = 1.; break; case 23: pre = couplings_[0]; break; case 32: pre = couplings_[1]; break; case 33: pre = couplings_[2]; break; default: assert(false); }; // W- W+ photon and cylic perms if((ida==-24 && idb== 24 && idc== 22) || (ida== 22 && idb==-24 && idc== 24) || (ida== 24 && idb== 22 && idc==-24) ) norm( coupLast_*pre); // W+ W- photon (anticylic perms of above) else if((ida== 24 && idb==-24 && idc== 22) || (ida== 22 && idb== 24 && idc==-24) || (ida==-24 && idb== 22 && idc== 24) ) norm(-coupLast_*pre); else throw Helicity::HelicityConsistencyError() << "LHTPWWWVertex::setCoupling - Incorrect particles in LHTPWWWVertex. " << a->id() << " " << b->id() << " " << c->id() << '\n' << Exception::runerror; } diff --git a/Models/Leptoquarks/LeptoquarkModelSLQFFVertex.cc b/Models/Leptoquarks/LeptoquarkModelSLQFFVertex.cc --- a/Models/Leptoquarks/LeptoquarkModelSLQFFVertex.cc +++ b/Models/Leptoquarks/LeptoquarkModelSLQFFVertex.cc @@ -1,346 +1,347 @@ // -*- C++ -*- // // LeptoquarkModelSLQFFVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 LeptoquarkModelSLQFFVertex class. // #include "LeptoquarkModelSLQFFVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Config/Constants.h" using namespace Herwig; IBPtr LeptoquarkModelSLQFFVertex::clone() const { return new_ptr(*this); } IBPtr LeptoquarkModelSLQFFVertex::fullclone() const { return new_ptr(*this); } LeptoquarkModelSLQFFVertex::LeptoquarkModelSLQFFVertex() { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::DELTA); } void LeptoquarkModelSLQFFVertex::doinit() { //S0 addToList( 15, 6,-9911561); addToList(-15,-6, 9911561); addToList(-16,-5, 9911561); addToList( 16, 5,-9911561); //~S0 addToList(-15,-5, 9921551); addToList( 15, 5,-9921551); //S1 triplet //S1p addToList(-15,-5, 9931551); addToList( 15, 5,-9931551); //S1z addToList(-15,-6, 9931561); addToList( 15, 6,-9931561); addToList(-16,-5, 9931561); addToList( 16, 5,-9931561); //S1m addToList(-16,-6, 9931661); addToList( 16, 6,-9931661); //S1/2 doublet addToList( 15,-6, 9941561); addToList(-15, 6,-9941561); addToList(-15, 5,-9941551); addToList(-16, 6,-9941551); addToList( 15,-5, 9941551); addToList( 16,-6, 9941551); //S1/2 tilde doublet addToList( 5,-16,-9951651); addToList(-5, 16, 9951651); addToList(-5, 15, 9951551); addToList( 5,-15,-9951551); //dS0 addToList( 15,-5, 9961551); addToList(-15, 5,-9961551); addToList( 16,-6, 9961551); addToList(-16, 6,-9961551); //~dS0 addToList( 15,-6, 9971561); addToList(-15, 6,-9971561); //dS1 triplet //dS1p addToList( 15,-6, 9981561); addToList(-15, 6,-9981561); //dS1z addToList( 16,-6, 9981551); addToList(-16, 6,-9981551); addToList( 15,-5, 9981551); addToList(-15, 5,-9981551); //dS1m addToList( 16,-5, 9981651); addToList(-16, 5,-9981651); //dS1/2 doublet addToList(-15,-5, 9991551); addToList( 15, 5,-9991551); addToList(-15,-6, 9991561); addToList( 15, 6,-9991561); addToList(-16,-5, 9991561); addToList( 16, 5,-9991561); //dS1/2 tilde doublet addToList(-15,-6, 9901561); addToList( 15, 6,-9901561); addToList(-16,-6, 9901661); addToList( 16, 6,-9901661); _theModel = generator()->standardModel(); tcHwLeptoquarkPtr hwLeptoquark=dynamic_ptr_cast(_theModel); if(hwLeptoquark){ _CFF=hwLeptoquark->cfermion(); _cL0 =hwLeptoquark->cleft(); _cR0 =hwLeptoquark->cright(); _cR0t = hwLeptoquark->crighttilde(); _cL1 =hwLeptoquark->cleft1(); _cL12 =hwLeptoquark->cleft12(); _cR12 =hwLeptoquark->cright12(); _cL12t =hwLeptoquark->cleft12tilde(); _derivscale = hwLeptoquark->fscale(); _dcL0 =hwLeptoquark->dcleft(); _dcR0 =hwLeptoquark->dcright(); _dcR0t = hwLeptoquark->dcrighttilde(); _dcL1 =hwLeptoquark->dcleft1(); _dcL12 =hwLeptoquark->dcleft12(); _dcR12 =hwLeptoquark->dcright12(); _dcL12t =hwLeptoquark->dcleft12tilde(); } FFSVertex::doinit(); } void LeptoquarkModelSLQFFVertex::persistentOutput(PersistentOStream & os) const { os << _CFF << _cL0 << _cR0 << _cR0t << _cL1 << _cL12 << _cR12 << _cL12t << _dcL0 << _dcR0 << _dcR0t << _dcL1 << _dcL12 << _dcR12 << _dcL12t << ounit(_derivscale,GeV); } void LeptoquarkModelSLQFFVertex::persistentInput(PersistentIStream & is, int) { is >> _CFF >> _cL0 >> _cR0 >> _cR0t >> _cL1 >> _cL12 >> _cR12 >> _cL12t >>_dcL0 >> _dcR0 >> _dcR0t >> _dcL1 >> _dcL12 >> _dcR12 >> _dcL12t >> iunit(_derivscale,GeV); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigLeptoquarkModelSLQFFVertex("Herwig::LeptoquarkModelSLQFFVertex", "Herwig.so"); void LeptoquarkModelSLQFFVertex::Init() { static ClassDocumentation documentation ("The LeptoquarkModelSLQFFVertex class is the implementation" " of the helicity amplitude calculation of the Leptoquark" " quark-lepton vertex."); } void LeptoquarkModelSLQFFVertex::setCoupling(Energy2,tcPDPtr aa ,tcPDPtr bb, tcPDPtr cc) { long isc(cc->id()), ism(aa->id()), ichg(bb->id()); long lqid = isc; long smid_1 = ism; long smid_2 = ichg; if(abs(lqid) < 9900000) { lqid = ism; smid_1 = ichg; smid_2 = isc; } if(abs(lqid) < 9900000) { smid_1 = ism; smid_2 = isc; } if( abs(smid_1) > abs(smid_2) ) { swap(smid_1, smid_2); } const Energy denom = sqrt(2.) * _derivscale; const double mtop = getParticleData(ParticleID::t)->mass() / denom; const double mbot = getParticleData(ParticleID::b)->mass() / denom; const double mtau = getParticleData(ParticleID::tauminus)->mass() / denom; //set the couplings to left and right //S0 if( abs(isc) == 9911561 || abs(ism) == 9911561 || abs(ichg) == 9911561 ) { if(abs(isc) == 5 || abs(ism) == 5 || abs(ichg) == 5) { _cL = -_cL0; _cR = Complex(0.); } if(abs(isc) == 6 || abs(ism) == 6 || abs(ichg) == 6) { _cL = _cL0; _cR = _cR0; } } //~S0 if( abs(isc) == 9921551 || abs(ism) == 9921551 || abs(ichg) == 9921551 ) { _cL = Complex(0.); _cR = _cR0t; } //S1 triplet //Q = + 4/3 if( abs(isc) == 9931551 || abs(ism) == 9931551 || abs(ichg) == 9931551 ) { _cL = sqrt(2.)* _cL1; _cR = Complex(0.); } //Q = + 1/3 if( abs(isc) == 9931561 || abs(ism) == 9931561 || abs(ichg) == 9931561 ) { _cL = - _cL1; _cR = Complex(0.); } //Q = - 2/3 if( abs(isc) == 9931661 || abs(ism) == 9931661 || abs(ichg) == 9931661 ) { _cL = sqrt(2.) * _cL1; _cR = Complex(0.); } //S1/2 doublet //Q = + 5/3 if( abs(isc) == 9941561 || abs(ism) == 9941561 || abs(ichg) == 9941561 ) { _cR = _cL12; _cL = _cR12; } //Q = + 2/3 if( abs(isc) == 9941551 || abs(ism) == 9941551 || abs(ichg) == 9941551 ) { if(abs(isc) == 5 || abs(ism) == 5 || abs(ichg) == 5) { _cR = Complex(0.); _cL = - _cR12; } if(abs(isc) == 6 || abs(ism) == 6 || abs(ichg) == 6) { _cL = Complex(0.); _cR = _cL12; } } //S1/2 tilde doublet //Q = + 2/3 if( abs(isc) == 9951551 || abs(ism) == 9951551 || abs(ichg) == 9951551 ) { _cR = _cL12t; _cL = Complex(0.); } //Q = - 1/3 if( abs(isc) == 9951651 || abs(ism) == 9951651 || abs(ichg) == 9951651 ) { _cR = _cL12t; _cL = Complex(0.); } //dS0 if( abs(isc) == 9961551 || abs(ism) == 9961551 || abs(ichg) == 9961551) { if(abs(isc) == 5 || abs(ism) == 5 || abs(ichg) == 5) { _cR = _dcL0 * mbot +_dcR0 * mtau; _cL = _dcR0 * mbot + _dcL0 * mtau; } if(abs(isc) == 6 || abs(ism) == 6 || abs(ichg) == 6) { _cR = _dcL0 * mtop; _cL = Complex(0.); } } //d~S0 if( abs(isc) == 9971561 || abs(ism) == 9971561 || abs(ichg) == 9971561) { _cR = _dcR0t * mtau; _cL = _dcR0t * mtop; } //dS1 triplet if( abs(isc) == 9981561 || abs(ism) == 9981561 || abs(ichg) == 9981561) { _cR = sqrt(2.) * _dcL1 * mtop; _cL = sqrt(2.) * _dcL1 * mtau; } if( abs(isc) == 9981551 || abs(ism) == 9981551 || abs(ichg) == 9981551) { if(abs(isc) == 5 || abs(ism) == 5 || abs(ichg) == 5) { _cR = -_dcL1 * mbot; _cL = -_dcL1 * mtau; } if(abs(isc) == 6 || abs(ism) == 6 || abs(ichg) == 6) { _cR = _dcL1 * mtop; _cL = Complex(0.); } } if( abs(isc) == 9981651 || abs(ism) == 9981651 || abs(ichg) == 9981651) { _cL = sqrt(2.) * _dcL1 * mbot; _cR = Complex(0.); } //dS1/2 doublet if( abs(isc) == 9991551 || abs(ism) == 9991551 || abs(ichg) == 9991551 ) { _cL = _dcL12 * mbot + _dcR12 * mtau; _cR = _dcR12 * mbot + _dcL12 * mtau; } if( abs(isc) == 9991561 || abs(ism) == 9991561 || abs(ichg) == 9991561 ) { if(abs(isc) == 6 || abs(ism) == 6 || abs(ichg) == 6) { _cL = _dcR12 * mtau; _cR = _dcR12 * mtop; } if(abs(isc) == 5 || abs(ism) == 5 || abs(ichg) == 5) { _cL = _dcL12 * mbot; } } //dS1/2 tilde doublet if( abs(isc) == 9901561 || abs(ism) == 9901561 || abs(ichg) == 9901561 ) { _cL = _dcL12t * mtop; _cR = _dcL12t * mtau; } if( abs(isc) == 9901661 || abs(ism) == 9901661 || abs(ichg) == 9901661 ) { _cL = _dcL12t * mtop; _cR = Complex(0.); } if(smid_1 > 0) { left(conj(_cR)); right(conj(_cL)); } else { left(_cL); right(_cR); } norm(_CFF); } diff --git a/Models/Leptoquarks/LeptoquarkModelSLQSLQGGVertex.cc b/Models/Leptoquarks/LeptoquarkModelSLQSLQGGVertex.cc --- a/Models/Leptoquarks/LeptoquarkModelSLQSLQGGVertex.cc +++ b/Models/Leptoquarks/LeptoquarkModelSLQSLQGGVertex.cc @@ -1,71 +1,72 @@ // -*- C++ -*- // // LeptoquarkModelSLQSLQGGVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 LeptoquarkModelSLQSLQGGVertex class. // #include "LeptoquarkModelSLQSLQGGVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace Herwig; using namespace ThePEG; LeptoquarkModelSLQSLQGGVertex::LeptoquarkModelSLQSLQGGVertex() : q2last_(ZERO), couplast_(0.) { orderInGs(2); orderInGem(0); + colourStructure(ColourStructure::SU3TTFUNDS); } void LeptoquarkModelSLQSLQGGVertex::doinit() { addToList(21,21,9941551,-9941551); addToList(21,21,9911561,-9911561); addToList(21,21,9921551,-9921551); addToList(21,21,9931561,-9931561); addToList(21,21,9931551,-9931551); addToList(21,21,9931661,-9931661); addToList(21,21,9941561,-9941561); addToList(21,21,9951551,-9951551); addToList(21,21,9951651,-9951651); addToList(21,21,9961551,-9961551); addToList(21,21,9971561,-9971561); addToList(21,21,9981561,-9981561); addToList(21,21,9981551,-9981551); addToList(21,21,9981651,-9981651); addToList(21,21,9991551,-9991551); addToList(21,21,9991561,-9991561); addToList(21,21,9901561,-9901561); addToList(21,21,9901661,-9901661); VVSSVertex::doinit(); } // The following static variable is needed for the type // description system in ThePEG. DescribeNoPIOClass describeHerwigLeptoquarkModelSLQSLQGGVertex("Herwig::LeptoquarkModelSLQSLQGGVertex", "HwLeptoquarkModel.so"); void LeptoquarkModelSLQSLQGGVertex::Init() { static ClassDocumentation documentation ("The LeptoquarkModelSLQSLQGGVertex class is the implementation of" " the LeptoquarkModel scalar LQ-scalar LQ-gluon-gluon vertex"); } void LeptoquarkModelSLQSLQGGVertex::setCoupling(Energy2 q2,tcPDPtr ,tcPDPtr ,tcPDPtr, tcPDPtr ) { if(q2 != q2last_ || couplast_ == 0.) { couplast_ = sqr(strongCoupling(q2)); q2last_ = q2; } norm(couplast_); } diff --git a/Models/Leptoquarks/LeptoquarkModelSLQSLQGVertex.cc b/Models/Leptoquarks/LeptoquarkModelSLQSLQGVertex.cc --- a/Models/Leptoquarks/LeptoquarkModelSLQSLQGVertex.cc +++ b/Models/Leptoquarks/LeptoquarkModelSLQSLQGVertex.cc @@ -1,73 +1,74 @@ // -*- C++ -*- // // LeptoquarkModelSLQSLQGVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 LeptoquarkModelSLQSLQGVertex class. // #include "LeptoquarkModelSLQSLQGVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; using namespace ThePEG; LeptoquarkModelSLQSLQGVertex::LeptoquarkModelSLQSLQGVertex() : q2last_(ZERO), couplast_(0.) { orderInGs(1); orderInGem(0); + colourStructure(ColourStructure::SU3TFUND); } void LeptoquarkModelSLQSLQGVertex::doinit() { addToList(21,9941551,-9941551); addToList(21,9911561,-9911561); addToList(21,9921551,-9921551); addToList(21,9931561,-9931561); addToList(21,9931551,-9931551); addToList(21,9931661,-9931661); addToList(21,9941561,-9941561); addToList(21,9951551,-9951551); addToList(21,9951651,-9951651); addToList(21,9961551,-9961551); addToList(21,9971561,-9971561); addToList(21,9981561,-9981561); addToList(21,9981551,-9981551); addToList(21,9981651,-9981651); addToList(21,9991551,-9991551); addToList(21,9991561,-9991561); addToList(21,9901561,-9901561); addToList(21,9901661,-9901661); VSSVertex::doinit(); } // The following static variable is needed for the type // description system in ThePEG. DescribeNoPIOClass describeHerwigLeptoquarkModelSLQSLQGVertex("Herwig::LeptoquarkModelSLQSLQGVertex", "HwLeptoquarkModel.so"); void LeptoquarkModelSLQSLQGVertex::Init() { static ClassDocumentation documentation ("The LeptoquarkModelSLQSLQGVertex class is the implementation of" " the LeptoquarkModel scalar LQ-scalar LQ-gluon vertex"); } void LeptoquarkModelSLQSLQGVertex::setCoupling(Energy2 q2,tcPDPtr ,tcPDPtr p2,tcPDPtr ) { if(q2 != q2last_ || couplast_ == 0.) { couplast_ = strongCoupling(q2); q2last_ = q2; } if(p2->id()<0) norm( couplast_); else norm(-couplast_); } diff --git a/Models/Makefile.am b/Models/Makefile.am --- a/Models/Makefile.am +++ b/Models/Makefile.am @@ -1,181 +1,181 @@ SUBDIRS = RSModel StandardModel General Susy UED Zprime \ Transplanckian ADD Leptoquarks Sextet TTbAsymm \ LH LHTP Feynrules noinst_LTLIBRARIES = libHwStandardModel.la nodist_libHwStandardModel_la_SOURCES = \ StandardModel/SM__all.cc libHwStandardModel_la_CPPFLAGS = \ $(AM_CPPFLAGS) -I$(srcdir)/StandardModel noinst_LTLIBRARIES += libHwModelGenerator.la nodist_libHwModelGenerator_la_SOURCES = \ General/ModelGenerator__all.cc libHwModelGenerator_la_CPPFLAGS = \ $(AM_CPPFLAGS) -I$(srcdir)/General if WANT_BSM pkglib_LTLIBRARIES = \ HwRSModel.la \ HwUED.la \ HwSusy.la \ HwNMSSM.la \ HwRPV.la \ HwZprimeModel.la \ HwTransplanck.la \ HwADDModel.la \ HwLeptoquarkModel.la \ HwSextetModel.la \ HwTTbAModel.la \ HwLHModel.la \ HwLHTPModel.la endif ############# HwRSModel_la_LDFLAGS = \ $(AM_LDFLAGS) -module -version-info 10:0:0 HwRSModel_la_CPPFLAGS = \ $(AM_CPPFLAGS) -I$(srcdir)/RSModel nodist_HwRSModel_la_SOURCES = \ RSModel/RS__all.cc ############# HwUED_la_LDFLAGS = \ -$(AM_LDFLAGS) -module -version-info 10:0:0 +$(AM_LDFLAGS) -module -version-info 10:1:0 HwUED_la_CPPFLAGS = \ $(AM_CPPFLAGS) -I$(srcdir)/UED nodist_HwUED_la_SOURCES = \ UED/UED__all.cc ############# HwSusy_la_LDFLAGS = \ -$(AM_LDFLAGS) -module -version-info 13:0:0 +$(AM_LDFLAGS) -module -version-info 13:1:0 HwSusy_la_CPPFLAGS = \ $(AM_CPPFLAGS) -I$(srcdir)/Susy nodist_HwSusy_la_SOURCES = \ Susy/Susy__all.cc ############# HwNMSSM_la_LDFLAGS = \ $(AM_LDFLAGS) -module -version-info 5:0:0 HwNMSSM_la_CPPFLAGS = \ $(AM_CPPFLAGS) -I$(srcdir)/Susy/NMSSM nodist_HwNMSSM_la_SOURCES = \ Susy/NMSSM/NMSSM__all.cc ############# HwRPV_la_LDFLAGS = \ $(AM_LDFLAGS) -module -version-info 3:0:0 HwRPV_la_CPPFLAGS = \ $(AM_CPPFLAGS) -I$(srcdir)/Susy/RPV nodist_HwRPV_la_SOURCES = \ Susy/RPV/RPV__all.cc ############# HwZprimeModel_la_LDFLAGS = \ $(AM_LDFLAGS) -module -version-info 3:0:0 HwZprimeModel_la_SOURCES = \ Zprime/ZprimeModel.cc Zprime/ZprimeModelZPQQVertex.cc ############# HwTransplanck_la_LDFLAGS = \ -$(AM_LDFLAGS) -module -version-info 4:0:0 +$(AM_LDFLAGS) -module -version-info 4:1:0 HwTransplanck_la_SOURCES = \ Transplanckian/METRP2to2.cc ############# HwADDModel_la_LDFLAGS = \ $(AM_LDFLAGS) -module -version-info 4:0:0 HwADDModel_la_CPPFLAGS = \ $(AM_CPPFLAGS) -I$(srcdir)/ADD nodist_HwADDModel_la_SOURCES = \ ADD/ADD__all.cc ############# HwLeptoquarkModel_la_LDFLAGS = \ $(AM_LDFLAGS) -module -version-info 5:0:0 HwLeptoquarkModel_la_CPPFLAGS = \ $(AM_CPPFLAGS) -I$(srcdir)/Leptoquarks nodist_HwLeptoquarkModel_la_SOURCES = \ Leptoquarks/Leptoquark__all.cc ############# HwSextetModel_la_LDFLAGS = \ $(AM_LDFLAGS) -module -version-info 3:0:0 HwSextetModel_la_CPPFLAGS = \ $(AM_CPPFLAGS) -I$(srcdir)/Sextet nodist_HwSextetModel_la_SOURCES = \ Sextet/Sextet__all.cc ############# HwTTbAModel_la_LDFLAGS = \ $(AM_LDFLAGS) -module -version-info 3:0:0 HwTTbAModel_la_CPPFLAGS = \ $(AM_CPPFLAGS) -I$(srcdir)/TTbAsymm nodist_HwTTbAModel_la_SOURCES = \ TTbAsymm/TTbA__all.cc ############# HwLHModel_la_LDFLAGS = \ $(AM_LDFLAGS) -module -version-info 5:0:0 HwLHModel_la_CPPFLAGS = \ $(AM_CPPFLAGS) -I$(srcdir)/LH nodist_HwLHModel_la_SOURCES = \ LH/LH__all.cc ############# HwLHTPModel_la_LDFLAGS = \ $(AM_LDFLAGS) -module -version-info 5:0:0 HwLHTPModel_la_LIBADD = \ $(GSLLIBS) HwLHTPModel_la_CPPFLAGS = \ $(AM_CPPFLAGS) $(GSLINCLUDE) -I$(srcdir)/LHTP nodist_HwLHTPModel_la_SOURCES = \ LHTP/LHTP__all.cc ############# diff --git a/Models/RSModel/RSModelFFGGRVertex.cc b/Models/RSModel/RSModelFFGGRVertex.cc --- a/Models/RSModel/RSModelFFGGRVertex.cc +++ b/Models/RSModel/RSModelFFGGRVertex.cc @@ -1,80 +1,81 @@ // -*- C++ -*- // // RSModelFFGGRVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 RSModelFFGGRVertex class. // #include "RSModelFFGGRVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; using namespace ThePEG; RSModelFFGGRVertex::RSModelFFGGRVertex() : couplast_(0.), q2last_(ZERO), kappa_(ZERO) { orderInGem(1); orderInGs (1); + colourStructure(ColourStructure::SU3TFUND); } void RSModelFFGGRVertex::doinit() { for(int ix=1;ix<7;++ix) { addToList(-ix,ix,21,39); } FFVTVertex::doinit(); tcHwRSPtr hwRS=dynamic_ptr_cast(generator()->standardModel()); if(!hwRS) throw Exception() << "Must have RSModel in RSModelFFGGRVertex::doinit()" << Exception::runerror; kappa_ = 2./hwRS->lambda_pi(); } void RSModelFFGGRVertex::persistentOutput(PersistentOStream & os) const { os << ounit(kappa_,InvGeV); } void RSModelFFGGRVertex::persistentInput(PersistentIStream & is, int) { is >> iunit(kappa_,InvGeV); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigRSModelFFGGRVertex("Herwig::RSModelFFGGRVertex", "HwRSModel.so"); void RSModelFFGGRVertex::Init() { static ClassDocumentation documentation ("The RSModelFFGGRVertexxs class is the implementation" " of the two fermion vector coupling for the RS model."); } // FFGGR coupling #ifndef NDEBUG void RSModelFFGGRVertex::setCoupling(Energy2 q2,tcPDPtr aa,tcPDPtr, tcPDPtr cc, tcPDPtr) { #else void RSModelFFGGRVertex::setCoupling(Energy2 q2,tcPDPtr,tcPDPtr, tcPDPtr, tcPDPtr) { #endif // work out the particles assert(cc->id()==ParticleID::g && abs(aa->id()) <=6 ); // overall factor if(q2last_ != q2 || couplast_ == 0. ) { couplast_ = strongCoupling(q2); q2last_ = q2; } left (1.); right(1.); // set the coupling norm( UnitRemoval::E * kappa_ * couplast_); } diff --git a/Models/RSModel/RSModelFFGRVertex.cc b/Models/RSModel/RSModelFFGRVertex.cc --- a/Models/RSModel/RSModelFFGRVertex.cc +++ b/Models/RSModel/RSModelFFGRVertex.cc @@ -1,64 +1,65 @@ // -*- C++ -*- // // RSModelFFGRVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 RSModelFFGRVertex class. // #include "RSModelFFGRVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; using namespace ThePEG; void RSModelFFGRVertex::persistentOutput(PersistentOStream & os) const { os << ounit(kappa_,InvGeV); } void RSModelFFGRVertex::persistentInput(PersistentIStream & is, int) { is >> iunit(kappa_,InvGeV); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigRSModelFFGRVertex("Herwig::RSModelFFGRVertex", "HwRSModel.so"); void RSModelFFGRVertex::Init() { static ClassDocumentation documentation ("The RSModelFFGRVertex class is the RSModel calculation" " of the fermion-antifermion-graviton vertex"); } void RSModelFFGRVertex::setCoupling(Energy2,tcPDPtr,tcPDPtr, tcPDPtr) { norm(Complex(kappa_ * UnitRemoval::E)); } RSModelFFGRVertex::RSModelFFGRVertex() : kappa_(ZERO) { orderInGem(1); orderInGs (0); + colourStructure(ColourStructure::DELTA); } void RSModelFFGRVertex::doinit() { // PDG codes for the particles // the quarks for (int ix=1;ix<7;++ix) addToList(-ix,ix,39); // the leptons for (int ix=11;ix<17;++ix) addToList(-ix,ix,39); FFTVertex::doinit(); tcHwRSPtr hwRS=dynamic_ptr_cast(generator()->standardModel()); if(!hwRS) throw Exception() << "Must have RSModel in RSModelFFGRVertex::doinit()" << Exception::runerror; kappa_=2./hwRS->lambda_pi(); } diff --git a/Models/RSModel/RSModelFFWGRVertex.cc b/Models/RSModel/RSModelFFWGRVertex.cc --- a/Models/RSModel/RSModelFFWGRVertex.cc +++ b/Models/RSModel/RSModelFFWGRVertex.cc @@ -1,190 +1,191 @@ // -*- C++ -*- // // RSModelFFWGRVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 RSModelFFWGRVertex class. // #include "RSModelFFWGRVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/Models/StandardModel/StandardCKM.h" using namespace Herwig; using namespace ThePEG; RSModelFFWGRVertex::RSModelFFWGRVertex() : charge_(17,0.), gl_(17,0.), gr_(17,0.), ckm_(3,vector(3,0.0)), couplast_(0.), q2last_(ZERO), kappa_(ZERO) { orderInGem(2); orderInGs (0); + colourStructure(ColourStructure::DELTA); } void RSModelFFWGRVertex::doinit() { for(int ix=11;ix<17;++ix) { addToList(-ix,ix,22,39); addToList(-ix,ix,23,39); } for(int ix=1;ix<7;++ix) { addToList(-ix,ix,22,39); addToList(-ix,ix,23,39); } // particles for outgoing W- // quarks for(int ix=1;ix<6;ix+=2) { for(int iy=2;iy<7;iy+=2) { addToList(-ix, iy, -24,39); } } // leptons for(int ix=11;ix<17;ix+=2) { addToList(-ix, ix+1, -24,39); } // particles for outgoing W+ // quarks for(int ix=2;ix<7;ix+=2) { for(int iy=1;iy<6;iy+=2) { addToList(-ix, iy, 24,39); } } // leptons for(int ix=11;ix<17;ix+=2) { addToList(-ix-1, ix, 24,39); } FFVTVertex::doinit(); tcHwRSPtr hwRS=dynamic_ptr_cast(generator()->standardModel()); if(!hwRS) throw Exception() << "Must have RSModel in RSModelFFWGRVertex::doinit()" << Exception::runerror; double sw2 = sin2ThetaW(); double fact = 0.25/sqrt(sw2*(1.-sw2)); for(int ix=1;ix<4;++ix) { charge_[2*ix-1] = hwRS->ed(); charge_[2*ix ] = hwRS->eu(); charge_[2*ix+9 ] = hwRS->ee(); charge_[2*ix+10] = hwRS->enu(); gl_[2*ix-1] = fact*(hwRS->vd() + hwRS->ad() ); gl_[2*ix ] = fact*(hwRS->vu() + hwRS->au() ); gl_[2*ix+9 ] = fact*(hwRS->ve() + hwRS->ae() ); gl_[2*ix+10] = fact*(hwRS->vnu() + hwRS->anu()); gr_[2*ix-1] = fact*(hwRS->vd() - hwRS->ad() ); gr_[2*ix ] = fact*(hwRS->vu() - hwRS->au() ); gr_[2*ix+9 ] = fact*(hwRS->ve() - hwRS->ae() ); gr_[2*ix+10] = fact*(hwRS->vnu() - hwRS->anu()); } kappa_ = 2./hwRS->lambda_pi(); Ptr::transient_pointer CKM = generator()->standardModel()->CKM(); // cast the CKM object to the HERWIG one ThePEG::Ptr::transient_const_pointer hwCKM = ThePEG::dynamic_ptr_cast< ThePEG::Ptr:: transient_const_pointer>(CKM); if(hwCKM) { vector< vector > CKM; CKM = hwCKM->getUnsquaredMatrix(generator()->standardModel()->families()); for(unsigned int ix=0;ix<3;++ix) { for(unsigned int iy=0;iy<3;++iy) { ckm_[ix][iy]=CKM[ix][iy]; } } } else { throw Exception() << "Must have access to the Herwig::StandardCKM object" << "for the CKM matrix in SMFFWVertex::doinit()" << Exception::runerror; } } void RSModelFFWGRVertex::persistentOutput(PersistentOStream & os) const { os << charge_ << gl_ << gr_ << ounit(kappa_,InvGeV) << ckm_; } void RSModelFFWGRVertex::persistentInput(PersistentIStream & is, int) { is >> charge_ >> gl_ >> gr_ >> iunit(kappa_,InvGeV) >> ckm_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigRSModelFFWGRVertex("Herwig::RSModelFFWGRVertex", "HwRSModel.so"); void RSModelFFWGRVertex::Init() { static ClassDocumentation documentation ("The RSModelFFWGRVertexxs class is the implementation" " of the two fermion vector coupling for the RS model."); } // FFWGR coupling void RSModelFFWGRVertex::setCoupling(Energy2 q2,tcPDPtr aa,tcPDPtr bb, tcPDPtr cc, tcPDPtr) { // work out the particles int iferm= abs(aa->id()); int ibos = abs(cc->id()); Complex coup; // overall factor assert( ibos >= 22 && ibos <= 24 ); if( q2last_ != q2 || couplast_ == 0. ) { couplast_ = electroMagneticCoupling(q2); q2last_ = q2; } // photon if(ibos==22) { // alpha coup = UnitRemoval::E * kappa_ * couplast_; // _charge of particle assert((iferm>=1 && iferm<=6)||(iferm>=11 &&iferm<=16)); coup *= charge_[iferm]; left (1.); right(1.); } // Z boson else if(ibos==23) { coup = UnitRemoval::E * kappa_ * couplast_; // _charge of particle assert((iferm>=1 && iferm<=6)||(iferm>=11 &&iferm<=16)); left (gl_[iferm]); right(gr_[iferm]); } else if(ibos==24) { coup = UnitRemoval::E * kappa_ * couplast_ * sqrt(0.5) / sqrt(sin2ThetaW()); // the left and right couplings int iferm=abs(aa->id()); int ianti=abs(bb->id()); // quarks if(iferm>=1 && iferm <=6) { int iu,id; // up type first if(iferm%2==0) { iu = iferm/2; id = (ianti+1)/2; } // down type first else { iu = ianti/2; id = (iferm+1)/2; } assert( iu>=1 && iu<=3 && id>=1 && id<=3); left(ckm_[iu-1][id-1]); right(0.); } // leptons else if(iferm>=11 && iferm <=16) { left(1.); right(0.); } else assert(false); } // set the coupling norm(coup); } diff --git a/Models/RSModel/RSModelGGGGRVertex.cc b/Models/RSModel/RSModelGGGGRVertex.cc --- a/Models/RSModel/RSModelGGGGRVertex.cc +++ b/Models/RSModel/RSModelGGGGRVertex.cc @@ -1,76 +1,77 @@ // -*- C++ -*- // // RSModelGGGGRVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 RSModelGGGGRVertex class. // #include "RSModelGGGGRVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; using namespace ThePEG; RSModelGGGGRVertex::RSModelGGGGRVertex() : kappa_(ZERO), _couplast(0.), _q2last(ZERO) { orderInGem(1); orderInGs (1); + colourStructure(ColourStructure::SU3FF); } void RSModelGGGGRVertex::doinit() { addToList(21, 21, 21, 39); VVVTVertex::doinit(); // set the graviton coupling tcHwRSPtr hwRS=dynamic_ptr_cast(generator()->standardModel()); if(!hwRS) throw Exception() << "Must have RSModel in RSModelGGGGRVertex::doinit()" << Exception::runerror; kappa_=2./hwRS->lambda_pi(); } void RSModelGGGGRVertex::persistentOutput(PersistentOStream & os) const { os << ounit(kappa_,InvGeV); } void RSModelGGGGRVertex::persistentInput(PersistentIStream & is, int) { is >> iunit(kappa_,InvGeV); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigRSModelGGGGRVertex("Herwig::RSModelGGGGRVertex", "HwRSModel.so"); void RSModelGGGGRVertex::Init() { static ClassDocumentation documentation ("The RSModelGGGGRVertex class is the four point coupling" " of three vector bosons and a graviton in the Randell-Sundrum model."); } // couplings for the GGGGR vertex #ifndef NDEBUG void RSModelGGGGRVertex::setCoupling(Energy2 q2,tcPDPtr a,tcPDPtr b, tcPDPtr c, tcPDPtr) { #else void RSModelGGGGRVertex::setCoupling(Energy2 q2,tcPDPtr,tcPDPtr, tcPDPtr, tcPDPtr) { #endif assert(a->id() == ParticleID::g && b->id() == ParticleID::g && c->id() == ParticleID::g); if(q2!=_q2last||_couplast==0.) { _couplast = strongCoupling(q2); _q2last=q2; } norm(Complex(_couplast*kappa_*UnitRemoval::E)); } diff --git a/Models/RSModel/RSModelSSGRVertex.cc b/Models/RSModel/RSModelSSGRVertex.cc --- a/Models/RSModel/RSModelSSGRVertex.cc +++ b/Models/RSModel/RSModelSSGRVertex.cc @@ -1,60 +1,61 @@ // -*- C++ -*- // // RSModelSSGRVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 RSModelSSGRVertex class. // #include "RSModelSSGRVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; using namespace ThePEG; RSModelSSGRVertex::RSModelSSGRVertex() : kappa_(ZERO) { orderInGem(1); orderInGs (0); + colourStructure(ColourStructure::SINGLET); } void RSModelSSGRVertex::doinit() { addToList(25,25,39); SSTVertex::doinit(); tcHwRSPtr hwRS=dynamic_ptr_cast(generator()->standardModel()); if(!hwRS) throw Exception() << "Must have RSModel in RSModelSSGRVertex::doinit()" << Exception::runerror; kappa_=2./hwRS->lambda_pi(); } void RSModelSSGRVertex::persistentOutput(PersistentOStream & os) const { os << ounit(kappa_,InvGeV); } void RSModelSSGRVertex::persistentInput(PersistentIStream & is, int) { is >> iunit(kappa_,InvGeV); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigRSModelSSGRVertex("Herwig::RSModelSSGRVertex", "HwRSModel.so"); void RSModelSSGRVertex::Init() { static ClassDocumentation documentation ("The RSModelSSGRVertex class is the implementation of" " the RSModel scalar-scalar-graviton vertex"); } void RSModelSSGRVertex::setCoupling(Energy2,tcPDPtr,tcPDPtr, tcPDPtr) { norm(Complex(kappa_ * UnitRemoval::E)); } diff --git a/Models/RSModel/RSModelVVGRVertex.cc b/Models/RSModel/RSModelVVGRVertex.cc --- a/Models/RSModel/RSModelVVGRVertex.cc +++ b/Models/RSModel/RSModelVVGRVertex.cc @@ -1,63 +1,64 @@ // -*- C++ -*- // // RSModelVVGRVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 RSModelVVGRVertex class. // #include "RSModelVVGRVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; using namespace ThePEG; void RSModelVVGRVertex::persistentOutput(PersistentOStream & os) const { os << ounit(kappa_,InvGeV); } void RSModelVVGRVertex::persistentInput(PersistentIStream & is, int) { is >> iunit(kappa_,InvGeV); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigRSModelVVGRVertex("Herwig::RSModelVVGRVertex", "HwRSModel.so"); void RSModelVVGRVertex::Init() { static ClassDocumentation documentation ("The RSModelVVGRVertex class is the implementation" " of the RSModel vector-vector-graviton vertex"); } void RSModelVVGRVertex::setCoupling(Energy2,tcPDPtr,tcPDPtr, tcPDPtr) { norm(Complex(UnitRemoval::E * kappa_)); } RSModelVVGRVertex::RSModelVVGRVertex() : kappa_(ZERO) { orderInGem(1); orderInGs (0); + colourStructure(ColourStructure::DELTA); } void RSModelVVGRVertex::doinit() { addToList(23,23,39); addToList(22,22,39); addToList(24,-24,39); addToList(21,21,39); VVTVertex::doinit(); tcHwRSPtr hwRS=dynamic_ptr_cast(generator()->standardModel()); if(!hwRS) throw Exception() << "Must be RSModel in RSModelVVGRVertex::doinit()" << Exception::runerror; kappa_=2./hwRS->lambda_pi(); } diff --git a/Models/RSModel/RSModelWWWGRVertex.cc b/Models/RSModel/RSModelWWWGRVertex.cc --- a/Models/RSModel/RSModelWWWGRVertex.cc +++ b/Models/RSModel/RSModelWWWGRVertex.cc @@ -1,97 +1,98 @@ // -*- C++ -*- // // RSModelVVVGRVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 RSModelWWWGRVertex class. // #include "RSModelWWWGRVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; using namespace ThePEG; RSModelWWWGRVertex::RSModelWWWGRVertex() : kappa_(ZERO), _couplast(0.), _q2last(ZERO), _zfact(0.) { // order in the couplings orderInGem(2); orderInGs (0); + colourStructure(ColourStructure::SINGLET); } void RSModelWWWGRVertex::doinit() { addToList(24,-24, 22, 39); addToList(24,-24, 23, 39); VVVTVertex::doinit(); _zfact = sqrt((1.-sin2ThetaW())/sin2ThetaW()); // set the graviton coupling tcHwRSPtr hwRS=dynamic_ptr_cast(generator()->standardModel()); if(!hwRS) throw Exception() << "Must have RSModel in RSModelWWWGRVertex::doinit()" << Exception::runerror; kappa_=2./hwRS->lambda_pi(); } void RSModelWWWGRVertex::persistentOutput(PersistentOStream & os) const { os << ounit(kappa_,InvGeV) << _zfact; } void RSModelWWWGRVertex::persistentInput(PersistentIStream & is, int) { is >> iunit(kappa_,InvGeV) >> _zfact; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigRSModelWWWGRVertex("Herwig::RSModelWWWGRVertex", "HwRSModel.so"); void RSModelWWWGRVertex::Init() { static ClassDocumentation documentation ("The RSModelWWWGRVertex class is the four point coupling" " of three vector bosons and a graviton in the Randell-Sundrum model."); } // couplings for the WWWGR vertex void RSModelWWWGRVertex::setCoupling(Energy2 q2,tcPDPtr a,tcPDPtr b, tcPDPtr c, tcPDPtr) { int ida=a->id(); int idb=b->id(); int idc=c->id(); // first the overall normalisation if(q2!=_q2last||_couplast==0.) { _couplast = electroMagneticCoupling(q2); _q2last=q2; } // W- W+ photon and cylic perms if((ida==-24 && idb== 24 && idc== 22) || (ida== 22 && idb==-24 && idc== 24) || (ida== 24 && idb== 22 && idc==-24) ) norm(Complex(_couplast*kappa_*UnitRemoval::E)); // W+ W- photon (anticylic perms of above) else if((ida== 24 && idb==-24 && idc== 22) || (ida== 22 && idb== 24 && idc==-24) || (ida==-24 && idb== 22 && idc== 24) ) norm(-Complex(_couplast*kappa_*UnitRemoval::E)); // W- W+ Z and cylic perms else if((ida==-24 && idb== 24 && idc== 23) || (ida== 23 && idb==-24 && idc== 24) || (ida== 24 && idb== 23 && idc==-24) ) norm(Complex(_couplast*_zfact*kappa_*UnitRemoval::E)); // W+ W- Z (anticylic perms of above) else if((ida== 24 && idb==-24 && idc== 23) || (ida== 23 && idb== 24 && idc==-24) || (ida==-24 && idb== 23 && idc== 24) ) norm(-Complex(_couplast*_zfact*kappa_*UnitRemoval::E)); else assert(false); } diff --git a/Models/Sextet/SextetFFSVertex.h b/Models/Sextet/SextetFFSVertex.h --- a/Models/Sextet/SextetFFSVertex.h +++ b/Models/Sextet/SextetFFSVertex.h @@ -1,138 +1,140 @@ // -*- C++ -*- #ifndef HERWIG_SextetFFSVertex_H #define HERWIG_SextetFFSVertex_H // // This is the declaration of the SextetFFSVertex class. // #include "ThePEG/Helicity/Vertex/Scalar/FFSVertex.h" namespace Herwig { using namespace ThePEG; /** * Here is the documentation of the SextetFFSVertex class. * * @see \ref SextetFFSVertexInterfaces "The interfaces" * defined for SextetFFSVertex. */ class SextetFFSVertex: public Helicity::FFSVertex { public: /** * The default constructor. */ - SextetFFSVertex() {} + SextetFFSVertex() { + colourStructure(ColourStructure::SU3K6); + } /** * 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. */ SextetFFSVertex & operator=(const SextetFFSVertex &); private: /** * The various couplings */ //@{ /** * The \f$SU(2)\f$ quark-doublet coupling to \f$\Phi_{6,1,1/3}\f$ */ vector g1L_; /** * The \f$SU(2)\f$ singlet coupling to \f$\Phi_{6,1,1/3}\f$ */ vector g1R_; /** * The \f$SU(2)\f$ singlet coupling to \f$\Phi_{6,1,-2/3}\f$ */ vector g1pR_; /** * The \f$SU(2)\f$ singlet coupling to \f$\Phi_{6,1,4/3}\f$ */ vector g1ppR_; /** * Coupling to \f$\Phi_{6,3,1/3}\f$ */ vector g3L_; //@} }; } #endif /* HERWIG_SextetFFSVertex_H */ diff --git a/Models/Sextet/SextetFFVVertex.h b/Models/Sextet/SextetFFVVertex.h --- a/Models/Sextet/SextetFFVVertex.h +++ b/Models/Sextet/SextetFFVVertex.h @@ -1,124 +1,126 @@ // -*- C++ -*- #ifndef HERWIG_SextetFFVVertex_H #define HERWIG_SextetFFVVertex_H // // This is the declaration of the SextetFFVVertex class. // #include "ThePEG/Helicity/Vertex/Vector/FFVVertex.h" namespace Herwig { using namespace ThePEG; /** * Here is the documentation of the SextetFFVVertex class. * * @see \ref SextetFFVVertexInterfaces "The interfaces" * defined for SextetFFVVertex. */ class SextetFFVVertex: public Helicity::FFVVertex { public: /** * The default constructor. */ - SextetFFVVertex() {} + SextetFFVVertex() { + colourStructure(ColourStructure::SU3K6); + } /** * 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. */ SextetFFVVertex & operator=(const SextetFFVVertex &); private: /** * The various couplings */ //@{ /** * The \f$SU(2)\f$ quark-doublet coupling to \f$\Phi_{6,2,-1/6}\f$ */ vector g2_; /** * The \f$SU(2)\f$ singlet coupling to \f$\Phi_{6,2,5/6}\f$ */ vector g2p_; //@} }; } #endif /* HERWIG_SextetFFVVertex_H */ diff --git a/Models/Sextet/SextetGGSSVertex.cc b/Models/Sextet/SextetGGSSVertex.cc --- a/Models/Sextet/SextetGGSSVertex.cc +++ b/Models/Sextet/SextetGGSSVertex.cc @@ -1,78 +1,79 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the SextetGGSSVertex class. // #include "SextetGGSSVertex.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "SextetModel.h" #include "SextetParticles.h" using namespace Herwig; -SextetGGSSVertex::SextetGGSSVertex() : q2last_(), couplast_() -{} +SextetGGSSVertex::SextetGGSSVertex() : q2last_(), couplast_() { + colourStructure(ColourStructure::SU3TT6); +} IBPtr SextetGGSSVertex::clone() const { return new_ptr(*this); } IBPtr SextetGGSSVertex::fullclone() const { return new_ptr(*this); } // The following static variable is needed for the type // description system in ThePEG. DescribeNoPIOClass describeSextetGGSSVertex("Herwig::SextetGGSSVertex", "HwSextetModel.so"); void SextetGGSSVertex::Init() { static ClassDocumentation documentation ("The SextetGGSSVertex class implements the coupling of two gluons to two" " scalar sextets"); } void SextetGGSSVertex::setCoupling(Energy2 q2, tcPDPtr, tcPDPtr, tcPDPtr, tcPDPtr) { if(q2 != q2last_ || couplast_ == 0.) { couplast_ = sqr(strongCoupling(q2)); q2last_ = q2; } norm(couplast_); } void SextetGGSSVertex::doinit() { orderInGs(2); orderInGem(0); SextetModelPtr model = dynamic_ptr_cast(generator()->standardModel()); if(!model) throw Exception() << "Must be using the SextetModel" << " in SextetGSSVertex::doinit()" << Exception::runerror; // add the enabled particles if(model->ScalarSingletY43Enabled()) addToList(21,21,ParticleID::ScalarDQSingletY43, ParticleID::ScalarDQSingletY43bar); if(model->ScalarSingletY13Enabled()) addToList(21,21,ParticleID::ScalarDQSingletY13, ParticleID::ScalarDQSingletY13bar); if(model->ScalarSingletY23Enabled()) addToList(21,21,ParticleID::ScalarDQSingletY23, ParticleID::ScalarDQSingletY23bar); if(model->ScalarTripletY13Enabled()) { addToList(21,21,ParticleID::ScalarDQTripletP, ParticleID::ScalarDQTripletPbar); addToList(21,21,ParticleID::ScalarDQTriplet0, ParticleID::ScalarDQTriplet0bar); addToList(21,21,ParticleID::ScalarDQTripletM, ParticleID::ScalarDQTripletMbar); } VVSSVertex::doinit(); } diff --git a/Models/Sextet/SextetGGVVVertex.h b/Models/Sextet/SextetGGVVVertex.h --- a/Models/Sextet/SextetGGVVVertex.h +++ b/Models/Sextet/SextetGGVVVertex.h @@ -1,102 +1,104 @@ // -*- C++ -*- #ifndef HERWIG_SextetGGVVVertex_H #define HERWIG_SextetGGVVVertex_H // // This is the declaration of the SextetGGVVVertex class. // #include "ThePEG/Helicity/Vertex/Vector/VVVVVertex.h" namespace Herwig { using namespace ThePEG; /** * Here is the documentation of the SextetGGVVVertex class. * * @see \ref SextetGGVVVertexInterfaces "The interfaces" * defined for SextetGGVVVertex. */ class SextetGGVVVertex: public Helicity::VVVVVertex { public: /** * The default constructor. */ - SextetGGVVVertex() {} + SextetGGVVVertex() { + colourStructure(ColourStructure::SU3TT6); + } /** Calculate the coupling *@param q2 The scale at which to evaluate the coupling *@param part1 The first interacting particle *@param part2 The second interacting particle *@param part3 The third interacting particle *@param part4 The fourth interacting particle */ virtual void setCoupling(Energy2 q2, tcPDPtr part1, tcPDPtr part2, tcPDPtr part3, tcPDPtr part4); 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(); 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. */ SextetGGVVVertex & operator=(const SextetGGVVVertex &); private: /** * The scale at which the coupling was last evaluated */ Energy2 q2Last_; /** * The value of the coupling when it was last evaluated */ Complex coupLast_; }; } #endif /* HERWIG_SextetGGVVVertex_H */ diff --git a/Models/Sextet/SextetGSSVertex.h b/Models/Sextet/SextetGSSVertex.h --- a/Models/Sextet/SextetGSSVertex.h +++ b/Models/Sextet/SextetGSSVertex.h @@ -1,102 +1,104 @@ // -*- C++ -*- #ifndef HERWIG_SextetGSSVertex_H #define HERWIG_SextetGSSVertex_H // // This is the declaration of the SextetGSSVertex class. // #include "ThePEG/Helicity/Vertex/Scalar/VSSVertex.h" namespace Herwig { using namespace ThePEG; /** * Here is the documentation of the SextetGSSVertex class. * * @see \ref SextetGSSVertexInterfaces "The interfaces" * defined for SextetGSSVertex. */ class SextetGSSVertex: public Helicity::VSSVertex { public: /** * The default constructor. */ - SextetGSSVertex() {} + SextetGSSVertex() { + colourStructure(ColourStructure::SU3T6); + } /** * 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: /** * 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. */ SextetGSSVertex & operator=(const SextetGSSVertex &); private: /** * Store the value of the coupling when last evaluated */ Complex coupLast_; /** * Store the scale at which coupling was last evaluated */ Energy2 q2Last_; }; } #endif /* HERWIG_SextetGSSVertex_H */ diff --git a/Models/Sextet/SextetGVVVertex.h b/Models/Sextet/SextetGVVVertex.h --- a/Models/Sextet/SextetGVVVertex.h +++ b/Models/Sextet/SextetGVVVertex.h @@ -1,100 +1,102 @@ // -*- C++ -*- #ifndef THEPEG_SextetGVVVertex_H #define THEPEG_SextetGVVVertex_H // // This is the declaration of the SextetGVVVertex class. // #include "ThePEG/Helicity/Vertex/Vector/VVVVertex.h" namespace Herwig { using namespace ThePEG; /** * Here is the documentation of the SextetGVVVertex class. * * @see \ref SextetGVVVertexInterfaces "The interfaces" * defined for SextetGVVVertex. */ class SextetGVVVertex: public Helicity::VVVVertex { public: /** * The default constructor. */ - SextetGVVVertex() {} + SextetGVVVertex() { + colourStructure(ColourStructure::SU3T6); + } /** Calculate the coupling *@param q2 The scale at which to evaluate the coupling *@param part1 The first interacting particle *@param part2 The second interacting particle *@param part3 The third interacting particle */ virtual void setCoupling(Energy2 q2,tcPDPtr part1, tcPDPtr part2,tcPDPtr part3); 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(); 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. */ SextetGVVVertex & operator=(const SextetGVVVertex &); private: /** * Store the value of the coupling when last evaluated */ Complex coupLast_; /** * Store the scale at which coupling was last evaluated */ Energy2 q2Last_; }; } #endif /* THEPEG_SextetGVVVertex_H */ diff --git a/Models/Sextet/SextetPSSVertex.h b/Models/Sextet/SextetPSSVertex.h --- a/Models/Sextet/SextetPSSVertex.h +++ b/Models/Sextet/SextetPSSVertex.h @@ -1,102 +1,104 @@ // -*- C++ -*- #ifndef HERWIG_SextetPSSVertex_H #define HERWIG_SextetPSSVertex_H // // This is the declaration of the SextetPSSVertex class. // #include "ThePEG/Helicity/Vertex/Scalar/VSSVertex.h" namespace Herwig { using namespace ThePEG; /** * Here is the documentation of the SextetPSSVertex class. * * @see \ref SextetPSSVertexInterfaces "The interfaces" * defined for SextetPSSVertex. */ class SextetPSSVertex: public Helicity::VSSVertex { public: /** * The default constructor. */ - SextetPSSVertex() {} + SextetPSSVertex() { + colourStructure(ColourStructure::DELTA); + } /** * 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: /** * 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. */ SextetPSSVertex & operator=(const SextetPSSVertex &); private: /** * Store the value of the coupling when last evaluated */ Complex coupLast_; /** * Store the scale at which coupling was last evaluated */ Energy2 q2Last_; }; } #endif /* HERWIG_SextetPSSVertex_H */ diff --git a/Models/Sextet/SextetPVVVertex.h b/Models/Sextet/SextetPVVVertex.h --- a/Models/Sextet/SextetPVVVertex.h +++ b/Models/Sextet/SextetPVVVertex.h @@ -1,100 +1,102 @@ // -*- C++ -*- #ifndef THEPEG_SextetPVVVertex_H #define THEPEG_SextetPVVVertex_H // // This is the declaration of the SextetPVVVertex class. // #include "ThePEG/Helicity/Vertex/Vector/VVVVertex.h" namespace Herwig { using namespace ThePEG; /** * Here is the documentation of the SextetPVVVertex class. * * @see \ref SextetPVVVertexInterfaces "The interfaces" * defined for SextetPVVVertex. */ class SextetPVVVertex: public Helicity::VVVVertex { public: /** * The default constructor. */ - SextetPVVVertex() {} + SextetPVVVertex() { + colourStructure(ColourStructure::DELTA); + } /** Calculate the coupling *@param q2 The scale at which to evaluate the coupling *@param part1 The first interacting particle *@param part2 The second interacting particle *@param part3 The third interacting particle */ virtual void setCoupling(Energy2 q2,tcPDPtr part1, tcPDPtr part2,tcPDPtr part3); 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(); 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. */ SextetPVVVertex & operator=(const SextetPVVVertex &); private: /** * Store the value of the coupling when last evaluated */ Complex coupLast_; /** * Store the scale at which coupling was last evaluated */ Energy2 q2Last_; }; } #endif /* THEPEG_SextetPVVVertex_H */ diff --git a/Models/StandardModel/SMFFGVertex.cc b/Models/StandardModel/SMFFGVertex.cc --- a/Models/StandardModel/SMFFGVertex.cc +++ b/Models/StandardModel/SMFFGVertex.cc @@ -1,70 +1,71 @@ // -*- C++ -*- // // SMFFGVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 StandardModelFFGVertex class. // #include "SMFFGVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/StandardModel/StandardModelBase.h" using namespace Herwig; using namespace ThePEG; // The following static variable is needed for the type // description system in ThePEG. DescribeNoPIOClass describeHerwigSMFFGVertex("Herwig::SMFFGVertex", "Herwig.so"); void SMFFGVertex::Init() { static ClassDocumentation documentation ("The SMFFGVertex class is the implementation of" "the coupling of the gluon to the Standard Model fermions"); } // coupling for FFG vertex #ifndef NDEBUG void SMFFGVertex::setCoupling(Energy2 q2,tcPDPtr aa,tcPDPtr bb,tcPDPtr) { #else void SMFFGVertex::setCoupling(Energy2 q2,tcPDPtr aa,tcPDPtr,tcPDPtr) { #endif // first the overall normalisation if(q2!=_q2last||_couplast==0.) { _couplast = -strongCoupling(q2); _q2last=q2; } // the left and right couplings assert( abs(aa->id()) >= 1 && abs(aa->id()) <= 6 ); assert( aa->id()==-bb->id()); if(aa->id()<0) norm( _couplast); else norm(-_couplast); left(1.); right(1.); } SMFFGVertex::SMFFGVertex() : _couplast(0.), _q2last(ZERO) { orderInGs(1); orderInGem(0); + colourStructure(ColourStructure::SU3TFUND); } void SMFFGVertex::doinit() { // PDG codes for the particles for(int ix=1;ix<7;++ix) { addToList(-ix,ix,21); } FFVVertex::doinit(); } diff --git a/Models/StandardModel/SMFFHVertex.cc b/Models/StandardModel/SMFFHVertex.cc --- a/Models/StandardModel/SMFFHVertex.cc +++ b/Models/StandardModel/SMFFHVertex.cc @@ -1,113 +1,114 @@ // -*- C++ -*- // // SMFFHVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SMFFHVertex class. // #include "SMFFHVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Config/Constants.h" using namespace Herwig; IBPtr SMFFHVertex::clone() const { return new_ptr(*this); } IBPtr SMFFHVertex::fullclone() const { return new_ptr(*this); } SMFFHVertex::SMFFHVertex() { // set up for the couplings _couplast=InvEnergy(); _idlast=0; _q2last=ZERO; _masslast=ZERO; _mw=ZERO; _fermion = 0; orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::DELTA); } void SMFFHVertex::doinit() { if ( !_fermion ) { // PDG codes for the particles // the quarks for(int ix=1;ix<7;++ix) { addToList(-ix, ix, 25); } // the leptons for(int ix=11;ix<17;ix+=2) { addToList(-ix, ix, 25); } } else { addToList(-_fermion,_fermion,25); } _theSM = dynamic_ptr_cast(generator()->standardModel()); if (!_theSM) throw InitException(); _mw= getParticleData(ThePEG::ParticleID::Wplus)->mass(); FFSVertex::doinit(); } void SMFFHVertex::persistentOutput(PersistentOStream & os) const { os << _theSM << ounit(_mw,GeV) << _fermion; } void SMFFHVertex::persistentInput(PersistentIStream & is, int) { is >> _theSM >> iunit(_mw,GeV) >> _fermion; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigSMFFHVertex("Herwig::SMFFHVertex", "Herwig.so"); void SMFFHVertex::Init() { static ClassDocumentation documentation ("The SMFFHVertex class is the implementation" " of the helicity amplitude calculation of the Standard Model Higgs" " fermion-antiferiom vertex."); static Parameter interfaceFermion ("Fermion", "The fermion to couple to. If not set all fermions are considered.", &SMFFHVertex::_fermion, 0, 0, 16, false, false, Interface::limited); } void SMFFHVertex::setCoupling(Energy2 q2,tcPDPtr aa,tcPDPtr, tcPDPtr) { int iferm=abs(aa->id()); // left and right couplings set to one left (1.); right(1.); // first the overall normalisation if(q2!=_q2last||_couplast==complex()) { _couplast = -0.5*weakCoupling(q2)/_mw; _q2last=q2; _idlast=iferm; assert((iferm>=1 && iferm<=6)||(iferm>=11 &&iferm<=16)); _masslast=_theSM->mass(q2,aa); } else if(iferm!=_idlast) { _idlast=iferm; assert((iferm>=1 && iferm<=6)||(iferm>=11 &&iferm<=16)); _masslast=_theSM->mass(q2,aa); } norm(_couplast*_masslast); } diff --git a/Models/StandardModel/SMFFPVertex.cc b/Models/StandardModel/SMFFPVertex.cc --- a/Models/StandardModel/SMFFPVertex.cc +++ b/Models/StandardModel/SMFFPVertex.cc @@ -1,89 +1,90 @@ // -*- C++ -*- // // SMFFPVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 StandardModelFFPVertex class. // #include "SMFFPVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; using namespace ThePEG; SMFFPVertex::SMFFPVertex() : _charge(17,0.0), _couplast(0.), _q2last(0.*GeV2) { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::DELTA); } void SMFFPVertex::doinit() { // PDG codes for the particles // the quarks for(int ix=1;ix<7;++ix) { addToList(-ix, ix, 22); } // the leptons for(int ix=11;ix<17;ix+=2) { addToList(-ix, ix, 22); } for(int ix=1;ix<4;++ix) { _charge[2*ix-1] = generator()->standardModel()->ed(); _charge[2*ix ] = generator()->standardModel()->eu(); _charge[2*ix+9 ] = generator()->standardModel()->ee(); _charge[2*ix+10] = generator()->standardModel()->enu(); } FFVVertex::doinit(); } void SMFFPVertex::persistentOutput(PersistentOStream & os) const { os << _charge; } void SMFFPVertex::persistentInput(PersistentIStream & is, int) { is >> _charge; } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigSMFFPVertex("Herwig::SMFFPVertex", "Herwig.so"); void SMFFPVertex::Init() { static ClassDocumentation documentation ("The SMFFPVertex class is the implementation of" "the coupling of the photon to the Standard Model fermions"); } // coupling for FFP vertex #ifndef NDEBUG void SMFFPVertex::setCoupling(Energy2 q2,tcPDPtr aa,tcPDPtr bb,tcPDPtr) { #else void SMFFPVertex::setCoupling(Energy2 q2,tcPDPtr aa,tcPDPtr,tcPDPtr) { #endif // first the overall normalisation if(q2!=_q2last||_couplast==0.) { _couplast = -electroMagneticCoupling(q2); _q2last=q2; } norm(_couplast); // the left and right couplings int iferm=abs(aa->id()); assert((iferm>=1 && iferm<=6)||(iferm>=11 &&iferm<=16)); assert(aa->id()==-bb->id()); if(aa->id()<0) { left(_charge[iferm]); right(_charge[iferm]); } else { left(-_charge[iferm]); right(-_charge[iferm]); } } diff --git a/Models/StandardModel/SMFFWVertex.cc b/Models/StandardModel/SMFFWVertex.cc --- a/Models/StandardModel/SMFFWVertex.cc +++ b/Models/StandardModel/SMFFWVertex.cc @@ -1,165 +1,166 @@ // -*- C++ -*- // // SMFFWVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SMFFWVertex class. // #include "SMFFWVertex.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "Herwig/Models/StandardModel/StandardCKM.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; using namespace ThePEG; SMFFWVertex::SMFFWVertex() : _diagonal(false), _ckm(3,vector(3,0.0)), _couplast(0.), _q2last(ZERO) { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::DELTA); } void SMFFWVertex::persistentOutput(PersistentOStream & os) const { os << _diagonal << _ckm; } void SMFFWVertex::persistentInput(PersistentIStream & is, int) { is >> _diagonal >> _ckm; } void SMFFWVertex::doinit() { // particles for outgoing W- // quarks for(int ix=1;ix<6;ix+=2) { for(int iy=2;iy<7;iy+=2) { bool isOff = iy/2 != (ix+1)/2; if ( isOff && _diagonal ) continue; addToList(-ix, iy, -24); } } // leptons for(int ix=11;ix<17;ix+=2) { addToList(-ix, ix+1, -24); } // particles for outgoing W+ // quarks for(int ix=2;ix<7;ix+=2) { for(int iy=1;iy<6;iy+=2) { bool isOff = ix/2 != (iy+1)/2; if ( isOff && _diagonal ) continue; addToList(-ix, iy, 24); } } // leptons for(int ix=11;ix<17;ix+=2) { addToList(-ix-1, ix, 24); } ThePEG::Helicity::FFVVertex::doinit(); if ( !_diagonal ) { Ptr::transient_pointer CKM = generator()->standardModel()->CKM(); // cast the CKM object to the HERWIG one ThePEG::Ptr::transient_const_pointer hwCKM = ThePEG::dynamic_ptr_cast< ThePEG::Ptr:: transient_const_pointer>(CKM); if(hwCKM) { vector< vector > CKM; CKM = hwCKM->getUnsquaredMatrix(generator()->standardModel()->families()); for(unsigned int ix=0;ix<3;++ix) { for(unsigned int iy=0;iy<3;++iy) { _ckm[ix][iy]=CKM[ix][iy]; } } } else { throw Exception() << "Must have access to the Herwig::StandardCKM object" << "for the CKM matrix in SMFFWVertex::doinit()" << Exception::runerror; } } else { _ckm = vector< vector >(3,vector(3,1.0)); } } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigSMFFWVertex("Herwig::SMFFWVertex", "Herwig.so"); void SMFFWVertex::Init() { static ClassDocumentation documentation ("The SMFFZVertex class is the implementation of" "the coupling of the W boson to the Standard Model fermions"); static Switch interfaceDiagonal ("Diagonal", "Use a diagonal CKM matrix (ignoring the CKM object of the StandardModel).", &SMFFWVertex::_diagonal, false, false, false); static SwitchOption interfaceDiagonalYes (interfaceDiagonal, "Yes", "Use a diagonal CKM matrix.", true); static SwitchOption interfaceDiagonalNo (interfaceDiagonal, "No", "Use the CKM object as used by the StandardModel.", false); } // coupling for FFW vertex void SMFFWVertex::setCoupling(Energy2 q2, tcPDPtr aa, tcPDPtr bb, tcPDPtr) { // first the overall normalisation if(q2!=_q2last||_couplast==0.) { _couplast = -sqrt(0.5)*weakCoupling(q2); _q2last=q2; } norm(_couplast); // the left and right couplings int iferm=abs(aa->id()); int ianti=abs(bb->id()); // quarks if(iferm>=1 && iferm <=6) { int iu,id; // up type first if(iferm%2==0) { iu = iferm/2; id = (ianti+1)/2; } // down type first else { iu = ianti/2; id = (iferm+1)/2; } assert( iu>=1 && iu<=3 && id>=1 && id<=3); left(_ckm[iu-1][id-1]); right(0.); } // leptons else if(iferm>=11 && iferm <=16) { left(1.); right(0.); } else assert(false); } diff --git a/Models/StandardModel/SMFFZVertex.cc b/Models/StandardModel/SMFFZVertex.cc --- a/Models/StandardModel/SMFFZVertex.cc +++ b/Models/StandardModel/SMFFZVertex.cc @@ -1,90 +1,91 @@ // -*- C++ -*- // // SMFFZVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SMFFZVertex class. // #include "SMFFZVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; using namespace ThePEG; void SMFFZVertex::persistentOutput(PersistentOStream & os) const { os << _gl << _gr; } void SMFFZVertex::persistentInput(PersistentIStream & is, int) { is >> _gl >> _gr; } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigSMFFZVertex("Herwig::SMFFZVertex", "Herwig.so"); void SMFFZVertex::Init() { static ClassDocumentation documentation ("The SMFFZVertex class is the implementation of" "the coupling of the Z boson to the Standard Model fermions"); } void SMFFZVertex::setCoupling(Energy2 q2,tcPDPtr aa,tcPDPtr,tcPDPtr) { // first the overall normalisation if(q2!=_q2last||_couplast==0.) { _couplast = -electroMagneticCoupling(q2); _q2last=q2; } norm(_couplast); // the left and right couplings int iferm=abs(aa->id()); if((iferm>=1 && iferm<=6)||(iferm>=11 &&iferm<=16)) { left(_gl[iferm]); right(_gr[iferm]); } else throw HelicityConsistencyError() << "SMFFZVertex::setCoupling " << "Unknown particle in Z vertex" << Exception::runerror; } SMFFZVertex::SMFFZVertex() : _gl(17,0.0), _gr(17,0.0), _couplast(0.0), _q2last(ZERO) { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::DELTA); } void SMFFZVertex::doinit() { // PDG codes for the particles // the quarks for(int ix=1;ix<7;++ix) { addToList(-ix, ix, 23); } // the leptons for(int ix=11;ix<17;++ix) { addToList(-ix, ix, 23); } tcSMPtr sm = generator()->standardModel(); double sw2 = sin2ThetaW(); double fact = 0.25/sqrt(sw2*(1.-sw2)); for(int ix=1;ix<4;++ix) { _gl[2*ix-1] = fact*(sm->vd() + sm->ad() ); _gl[2*ix ] = fact*(sm->vu() + sm->au() ); _gl[2*ix+9 ] = fact*(sm->ve() + sm->ae() ); _gl[2*ix+10] = fact*(sm->vnu() + sm->anu()); _gr[2*ix-1] = fact*(sm->vd() - sm->ad() ); _gr[2*ix ] = fact*(sm->vu() - sm->au() ); _gr[2*ix+9 ] = fact*(sm->ve() - sm->ae() ); _gr[2*ix+10] = fact*(sm->vnu() - sm->anu()); } FFVVertex::doinit(); } diff --git a/Models/StandardModel/SMGGGGVertex.cc b/Models/StandardModel/SMGGGGVertex.cc --- a/Models/StandardModel/SMGGGGVertex.cc +++ b/Models/StandardModel/SMGGGGVertex.cc @@ -1,60 +1,61 @@ // -*- C++ -*- // // SMGGGGVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SMGGGGVertex class. // #include "SMGGGGVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; using namespace ThePEG; SMGGGGVertex::SMGGGGVertex() : _couplast(0.),_q2last() { orderInGs(2); orderInGem(0); + colourStructure(ColourStructure::SU3FF); } void SMGGGGVertex::doinit() { // particles addToList(21,21,21,21); VVVVVertex::doinit(); } // The following static variable is needed for the type // description system in ThePEG. DescribeNoPIOClass describeHerwigSMGGGGVertex("Herwig::SMGGGGVertex", "Herwig.so"); void SMGGGGVertex::Init() { static ClassDocumentation documentation ("The SMGGGGVertex class is the implementation of the" " Standard Model quartic gluon coupling"); } // couplings for the GGGG vertex void SMGGGGVertex::setCoupling(Energy2 q2,tcPDPtr,tcPDPtr, tcPDPtr,tcPDPtr) { // set the order and type setType(1); setOrder(0,1,2,3); // first the overall normalisation if(q2!=_q2last||_couplast==0.) { _couplast = sqr(strongCoupling(q2)); _q2last=q2; } norm(_couplast); } diff --git a/Models/StandardModel/SMGGGVertex.cc b/Models/StandardModel/SMGGGVertex.cc --- a/Models/StandardModel/SMGGGVertex.cc +++ b/Models/StandardModel/SMGGGVertex.cc @@ -1,54 +1,55 @@ // -*- C++ -*- // // SMGGGVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SMGGGVertex class. // #include "SMGGGVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; using namespace ThePEG; SMGGGVertex::SMGGGVertex() : _couplast(0.), _q2last(0.*GeV2) { orderInGs(1); orderInGem(0); + colourStructure(ColourStructure::SU3F); } void SMGGGVertex::doinit() { // the particles addToList(21,21,21); VVVVertex::doinit(); } // The following static variable is needed for the type // description system in ThePEG. DescribeNoPIOClass describeHerwigSMGGGVertex("Herwig::SMGGGVertex", "Herwig.so"); void SMGGGVertex::Init() { static ClassDocumentation documentation ("The SMGGGVertex class is the implementation" " of the Standard Model triple gluon vertex."); } // couplings for the GGG vertex void SMGGGVertex::setCoupling(Energy2 q2,tcPDPtr,tcPDPtr, tcPDPtr) { // first the overall normalisation if(q2!=_q2last||_couplast==0.) { _couplast = strongCoupling(q2); _q2last=q2; } norm(_couplast); } diff --git a/Models/StandardModel/SMHGGVertex.cc b/Models/StandardModel/SMHGGVertex.cc --- a/Models/StandardModel/SMHGGVertex.cc +++ b/Models/StandardModel/SMHGGVertex.cc @@ -1,225 +1,226 @@ // -*- C++ -*- // // SMHGGVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SMHGGVertex class. // #include "SMHGGVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/Looptools/clooptools.h" using namespace Herwig; using namespace ThePEG; SMHGGVertex::SMHGGVertex() :_couplast(0.),_q2last(ZERO),_mw(),massopt(1),_minloop(6), _maxloop(6),_CoefRepresentation(1) { orderInGs(2); orderInGem(1); + colourStructure(ColourStructure::DELTA); } void SMHGGVertex::doinit() { //PDG codes for particles at vertices addToList(21,21,25); _theSM = dynamic_ptr_cast(generator()->standardModel()); if(!_theSM) throw InitException(); _mw = getParticleData(ThePEG::ParticleID::Wplus)->mass(); VVSLoopVertex::doinit(); // code to test the partial width // Energy mh = getParticleData(25)->mass(); // Complex I(0.); // for(long ix=int(_minloop);ix<=int(_maxloop);++ix) { // tcPDPtr qrk = getParticleData(ix); // Energy mt = (2 == massopt) ? _theSM->mass(sqr(mh),qrk) : qrk->mass(); // double lambda = sqr(mt/mh); // Complex fl; // if(lambda>=0.25) { // fl = -2.*sqr(asin(0.5/sqrt(lambda))); // } // else { // double etap = 0.5+sqrt(0.25-lambda); // double etam = 0.5-sqrt(0.25-lambda); // fl = 0.5*sqr(log(etap/etam))-0.5*sqr(Constants::pi) // -Complex(0.,1.)*Constants::pi*log(etap/etam); // } // I += 3.*(2.*lambda+lambda*(4.*lambda-1)*fl); // } // Energy width = sqr(weakCoupling(sqr(mh))*sqr(strongCoupling(sqr(mh))))/36./8.*sqr(mh/_mw)*mh // /sqr(4.*sqr(Constants::pi))*std::norm(I)/Constants::pi; // cerr << "testing anal " << width/GeV << "\n"; if(loopToolsInitialized()) Looptools::ltexi(); } void SMHGGVertex::persistentOutput(PersistentOStream & os) const { os << _theSM << ounit(_mw,GeV) << massopt << _minloop << _maxloop << _CoefRepresentation; } void SMHGGVertex::persistentInput(PersistentIStream & is, int) { is >> _theSM >> iunit(_mw,GeV) >> massopt >> _minloop >> _maxloop >> _CoefRepresentation; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigSMHGGVertex("Herwig::SMHGGVertex", "Herwig.so"); void SMHGGVertex::Init() { static ClassDocumentation documentation ("This class implements the h->g,g vertex"); static Parameter interfaceMinQuarkInLoop ("MinQuarkInLoop", "The minimum flavour of the quarks to include in the loops", &SMHGGVertex::_minloop, 6, 1, 6, false, false, Interface::limited); static Parameter interfaceMaxQuarkInLoop ("MaxQuarkInLoop", "The maximum flavour of the quarks to include in the loops", &SMHGGVertex::_maxloop, 6, 1, 6, false, false, Interface::limited); static Switch interfaceMassOption ("LoopMassScheme", "Switch for the treatment of the masses in the loops ", &SMHGGVertex::massopt, 1, false, false); static SwitchOption interfaceHeavyMass (interfaceMassOption, "PoleMasses", "The loop is calculcated with the pole quark masses", 1); static SwitchOption interfaceNormalMass (interfaceMassOption, "RunningMasses", "running quark masses are taken in the loop", 2); static SwitchOption interfaceInfiniteTopMass (interfaceMassOption, "InfiniteTopMass", "the loop consists of an infinitely massive top quark", 3); static Switch interfaceScheme ("CoefficientScheme", "Which scheme for the tensor coefficients is applied", &SMHGGVertex::_CoefRepresentation, 1, false, false); static SwitchOption interfaceSchemeSimplified (interfaceScheme, "Simplified", "Represection suitable for the simplified the H-g-g and H-gamma-gamma vertices", 1); static SwitchOption interfaceSchemeGeneral (interfaceScheme, "General", "Represection suitable for the Passarino-Veltman tensor reduction scheme", 2); } void SMHGGVertex::setCoupling(Energy2 q2, tcPDPtr part2, tcPDPtr part3, tcPDPtr part1) { assert(part1 && part2 && part3); assert(part1->id() == ParticleID::h0 && part2->id() == ParticleID::g && part3->id() == ParticleID::g ); int Qminloop = _minloop; int Qmaxloop = _maxloop; if (_maxloop < _minloop) { Qmaxloop=_minloop; Qminloop=_maxloop; } if(massopt==3) { if(q2 != _q2last) { double g = weakCoupling(q2); double gs2 = sqr(strongCoupling(q2)); _couplast = UnitRemoval::E * gs2 * g / 16. / _mw/ sqr(Constants::pi); _q2last = q2; } norm(_couplast); Complex loop(2./3.); a00( loop); a11(0.0); a12(0.0); a21(-loop); a22(0.0); aEp(0.0); return; } switch (_CoefRepresentation) { case 1: { if(q2 != _q2last||_couplast==0.) { double g = weakCoupling(q2); double gs2 = sqr(strongCoupling(q2)); _couplast = UnitRemoval::E * gs2 * g / 16. / _mw/ sqr(Constants::pi); _q2last = q2; } norm(_couplast); Complex loop(0.); for ( int i = Qminloop; i <= Qmaxloop; ++i ) { tcPDPtr qrk = getParticleData(i); Energy mass = (2 == massopt) ? _theSM->mass(q2,qrk) : qrk->mass(); loop += Af(sqr(mass)/invariant(0,0)); } a00(loop); a11(0.0); a12(0.0); a21(-loop); a22(0.0); aEp(0.0); break; } case 2: { if (q2 != _q2last) { Looptools::clearcache(); _couplast = 0.25*sqr(strongCoupling(q2))*weakCoupling(q2); _q2last = q2; } norm(_couplast); int delta = Qmaxloop - Qminloop + 1; type.resize(delta,PDT::SpinUnknown); masses.resize(delta,ZERO); couplings.clear(); for (int i = 0; i < delta; ++i) { tcPDPtr q = getParticleData(_minloop+i); type[i] = PDT::Spin1Half; masses[i] = (2 == massopt) ? _theSM->mass(q2,q) : q->mass(); const double ratio = masses[i]/_mw; couplings.push_back(make_pair(ratio, ratio)); } setNParticles(delta); VVSLoopVertex::setCoupling(q2, part1, part2, part3); break; } } } Complex SMHGGVertex::Af(double tau) const { return tau*(4.- W2(tau)*(1.-4.*tau)); } Complex SMHGGVertex::W2(double lambda) const { double pi = Constants::pi; if (0.0 == lambda) return 0.0; else if (lambda < 0.0) return 4.*sqr(asinh(0.5*sqrt(-1./lambda))); double root(0.5*sqrt(1./lambda)); Complex ac(0.); // formulae from NPB297,221 if(root < 1.) { ac = -sqr(asin(root)); } else { double ex = acosh(root); ac = sqr(ex) - 0.25*sqr(pi) - pi*ex*Complex(0.,1.); } return 4.*ac; } diff --git a/Models/StandardModel/SMHHHVertex.cc b/Models/StandardModel/SMHHHVertex.cc --- a/Models/StandardModel/SMHHHVertex.cc +++ b/Models/StandardModel/SMHHHVertex.cc @@ -1,71 +1,72 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the SMHHHVertex class. // #include "SMHHHVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; SMHHHVertex::SMHHHVertex() : ratio_(ZERO), couplast_(0.), q2last_(ZERO) { orderInGem(1); orderInGs (0); + colourStructure(ColourStructure::SINGLET); } IBPtr SMHHHVertex::clone() const { return new_ptr(*this); } IBPtr SMHHHVertex::fullclone() const { return new_ptr(*this); } void SMHHHVertex::persistentOutput(PersistentOStream & os) const { os << ounit(ratio_,GeV); } void SMHHHVertex::persistentInput(PersistentIStream & is, int) { is >> iunit(ratio_,GeV); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigSMHHHVertex("Herwig::SMHHHVertex", "Herwig.so"); void SMHHHVertex::Init() { static ClassDocumentation documentation ("The SMHHHVertex class implements the triple Higgs" " coupling in the Standard Model."); } void SMHHHVertex::doinit() { addToList(25,25,25); SSSVertex::doinit(); ratio_ = -1.5*sqr(getParticleData(ParticleID::h0)->mass())/ getParticleData(ParticleID::Wplus)->mass(); } #ifndef NDEBUG void SMHHHVertex::setCoupling(Energy2 q2,tcPDPtr part1,tcPDPtr part2,tcPDPtr part3) { #else void SMHHHVertex::setCoupling(Energy2 q2,tcPDPtr,tcPDPtr,tcPDPtr) { #endif assert(part1->id()==ParticleID::h0 && part2->id()==ParticleID::h0 && part3->id()==ParticleID::h0 ); if(q2!=q2last_||couplast_==0.) { couplast_ = weakCoupling(q2)*ratio_*UnitRemoval::InvE; q2last_=q2; } norm(couplast_); } diff --git a/Models/StandardModel/SMHPPVertex.cc b/Models/StandardModel/SMHPPVertex.cc --- a/Models/StandardModel/SMHPPVertex.cc +++ b/Models/StandardModel/SMHPPVertex.cc @@ -1,285 +1,286 @@ // -*- C++ -*- // // SMHPPVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SMHPPVertex class. // #include "SMHPPVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include "Herwig/Looptools/clooptools.h" using namespace Herwig; using namespace ThePEG; void SMHPPVertex::persistentOutput(PersistentOStream & os) const { os << _theSM << ounit(_mw,GeV) << _massopt << _minloop << _maxloop << _CoefRepresentation; } void SMHPPVertex::persistentInput(PersistentIStream & is, int) { is >> _theSM >> iunit(_mw, GeV) >> _massopt >> _minloop >> _maxloop >> _CoefRepresentation; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigSMHPPVertex("Herwig::SMHPPVertex", "Herwig.so"); void SMHPPVertex::Init() { static ClassDocumentation documentation ("This class implements the h0->gamma,gamma vertex."); static Parameter interfaceMinQuarkInLoop ("MinQuarkInLoop", "The minimum flavour of the quarks to include in the loops", &SMHPPVertex::_minloop, 6, 1, 6, false, false, Interface::limited); static Parameter interfaceMaxQuarkInLoop ("MaxQuarkInLoop", "The maximum flavour of the quarks to include in the loops", &SMHPPVertex::_maxloop, 6, 1, 6, false, false, Interface::limited); static Switch interfaceMassOption ("LoopMassScheme", "Switch for the treatment of the masses in the loops ", &SMHPPVertex::_massopt, 2, false, false); static SwitchOption interfaceHeavyMass (interfaceMassOption, "PoleMasses", "The loop is calculcated with the pole quark masses", 1); static SwitchOption interfaceNormalMass (interfaceMassOption, "RunningMasses", "running quark masses are taken in the loop", 2); static Switch interfaceScheme ("CoefficientScheme", "Which scheme for the tensor coefficients is applied", &SMHPPVertex::_CoefRepresentation, 1, false, false); static SwitchOption interfaceSchemeSimplified (interfaceScheme, "Simplified", "Represection suitable for the simplified the H-g-g and H-gamma-gamma vertices", 1); static SwitchOption interfaceSchemeGeneral (interfaceScheme, "General", "Represection suitable for the Passarino-Veltman tensor reduction scheme", 2); } void SMHPPVertex::setCoupling(Energy2 q2, tcPDPtr part2, tcPDPtr part3, tcPDPtr part1) { assert( part1->id() == ParticleID::h0 && part2->id() == ParticleID::gamma && part3->id() == ParticleID::gamma ); int Qminloop = _minloop; int Qmaxloop = _maxloop; if (_maxloop < _minloop) { Qmaxloop=_minloop; Qminloop=_maxloop; } switch (_CoefRepresentation) { case 1: { if(q2 != _q2last||_couplast==0.) { double g = weakCoupling(q2); double e2 = sqr(electroMagneticCoupling(q2)); _couplast = UnitRemoval::E * e2 * g / 8. / _mw/ sqr(Constants::pi); _q2last = q2; } norm(_couplast); Complex loop(0.); // quark loops for ( int i = Qminloop; i <= Qmaxloop; ++i ) { tcPDPtr qrk = getParticleData(i); Energy mass = (2 == _massopt) ? _theSM->mass(q2,qrk) : qrk->mass(); Charge charge = qrk->charge(); loop += 3.*sqr(charge/ThePEG::Units::eplus) * Af(sqr(mass)/invariant(0,0)); } // lepton loops int Lminloop = 3; // still fixed value int Lmaxloop = 3; // still fixed value for (int i = Lminloop; i <= Lmaxloop; ++i) { tcPDPtr lpt = getParticleData(9 + 2*i); Energy mass = (2 == _massopt) ? _theSM->mass(q2,lpt) : lpt->mass(); Charge charge = lpt->charge(); loop += sqr(charge/ThePEG::Units::eplus) * Af(sqr(mass)/invariant(0,0)); } // W loop loop += Aw(sqr(_mw)/invariant(0,0)); a00(loop); a11(0.0); a12(0.0); a21(-loop); a22(0.0); aEp(0.0); break; } case 2: { if(q2 != _q2last||_couplast==0.) { Looptools::clearcache(); double e = electroMagneticCoupling(q2); _couplast = pow(e,3)/sqrt(sin2ThetaW()); _q2last = q2; } norm(_couplast); // quarks int delta = Qmaxloop - Qminloop + 1; type.resize(delta,PDT::SpinUnknown); masses.resize(delta,ZERO); for (int i = 0; i < delta; ++i) { tcPDPtr q = getParticleData(_minloop+i); type[i] = PDT::Spin1Half; masses[i] = (2 == _massopt) ? _theSM->mass(q2,q) : q->mass(); double copl = -masses[i]*3.*sqr(q->iCharge()/3.)/_mw/2.; couplings.push_back(make_pair(copl, copl)); } // tau type.push_back(PDT::Spin1Half); tcPDPtr tau = getParticleData(ParticleID::tauminus); masses.push_back(_theSM->mass(q2,tau)); double copl = -masses.back()*sqr(tau->iCharge()/3.)/_mw/2.; couplings.push_back(make_pair(copl, copl)); // W type.push_back(PDT::Spin1); masses.push_back(_mw); const double mw = UnitRemoval::InvE*_mw; couplings.push_back(make_pair(mw,mw)); setNParticles(delta+2); VVSLoopVertex::setCoupling(q2, part1, part2, part3); break; } } } Complex SMHPPVertex::Af(const double tau) const { return tau*(4. - W2(tau)*(1. - 4.*tau)); } Complex SMHPPVertex::Aw(const double tau) const { return 0.5*(-3.*W2(tau)*tau*(4.*tau - 2.) - 12.*tau - 2.); } Complex SMHPPVertex::W2(double lambda) const { double pi = Constants::pi; if (0.0 == lambda) return 0.0; if (lambda < 0.0) return 4.*sqr(asinh(0.5*sqrt(-1./lambda))); double root(0.5*sqrt(1./lambda)); Complex ac(0.); // formulae from NPB297,221 if(root < 1.) { ac = -sqr(asin(root)); } else { double ex = acosh(root); ac = sqr(ex) - 0.25*sqr(pi) - pi*ex*Complex(0.,1.); } return 4.*ac; } SMHPPVertex::SMHPPVertex() :_couplast(0.),_q2last(),_mw(),_massopt(1), _minloop(6),_maxloop(6),_CoefRepresentation(1) { orderInGs(0); orderInGem(3); + colourStructure(ColourStructure::SINGLET); } // functions for loops for testing // namespace { // Complex F0(double tau) { // Complex ft; // if(tau>=1.) // ft = sqr(asin(1./sqrt(tau))); // else { // double etap = 1.+sqrt(1.-tau); // double etam = 1.-sqrt(1.-tau); // ft = -0.25*sqr(log(etap/etam)-Constants::pi*Complex(0.,1.)); // } // return tau*(1.-tau*ft); // } // Complex FHalf(double tau,double eta) { // Complex ft; // if(tau>=1.) // ft = sqr(asin(1./sqrt(tau))); // else { // double etap = 1.+sqrt(1.-tau); // double etam = 1.-sqrt(1.-tau); // ft = -0.25*sqr(log(etap/etam)-Constants::pi*Complex(0.,1.)); // } // return -2.*tau*(eta+(1.-tau*eta)*ft); // } // Complex F1(double tau) { // Complex ft; // if(tau>=1.) // ft = sqr(asin(1./sqrt(tau))); // else { // double etap = 1.+sqrt(1.-tau); // double etam = 1.-sqrt(1.-tau); // ft = -0.25*sqr(log(etap/etam)-Constants::pi*Complex(0.,1.)); // } // return 2.+3.*tau+3.*tau*(2.-tau)*ft; // } // } void SMHPPVertex::doinit() { //PDG codes for particles at vertices addToList(22,22,25); _theSM = dynamic_ptr_cast(generator()->standardModel()); if( !_theSM ) throw InitException() << "SMHGGVertex::doinit() - The pointer to the SM object is null." << Exception::abortnow; _mw = getParticleData(ThePEG::ParticleID::Wplus)->mass(); VVSLoopVertex::doinit(); // // code to test the partial width // Energy mh = getParticleData(25)->mass(); // Complex I(0.); // for(long ix=int(_minloop);ix<=int(_maxloop);++ix) { // tcPDPtr qrk = getParticleData(ix); // Energy mt = (2 == _massopt) ? _theSM->mass(sqr(mh),qrk) : qrk->mass(); // double tau = sqr(2.*mt/mh); // I += 3.*sqr(double(qrk->iCharge())/3.)*FHalf(tau,1.); // cerr << "testing half " << FHalf(tau,1) << " " << Af(0.25*tau) << "\n"; // } // for(long ix=15;ix<=15;++ix) { // tcPDPtr qrk = getParticleData(ix); // Energy mt = (2 == _massopt) ? _theSM->mass(sqr(mh),qrk) : qrk->mass(); // double tau = sqr(2.*mt/mh); // I += sqr(double(qrk->iCharge())/3.)*FHalf(tau,1.); // } // I += F1(sqr(2.*_mw/mh)); // Energy width = sqr(weakCoupling(sqr(mh))*sqr(electroMagneticCoupling(sqr(mh)))) // /1024./pow(Constants::pi,5)/16.*sqr(mh/_mw)*mh*std::norm(I); // cerr << "testing anal " << width/GeV << "\n"; if(loopToolsInitialized()) Looptools::ltexi(); } diff --git a/Models/StandardModel/SMHZPVertex.cc b/Models/StandardModel/SMHZPVertex.cc --- a/Models/StandardModel/SMHZPVertex.cc +++ b/Models/StandardModel/SMHZPVertex.cc @@ -1,187 +1,188 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the SMHZPVertex class. // #include "SMHZPVertex.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; SMHZPVertex::SMHZPVertex() :_couplast(0.),_q2last(),_mw(),_mz(),_massopt(1), _minloop(6),_maxloop(6) { orderInGs(0); orderInGem(3); kinematics(true); + colourStructure(ColourStructure::SINGLET); } IBPtr SMHZPVertex::clone() const { return new_ptr(*this); } IBPtr SMHZPVertex::fullclone() const { return new_ptr(*this); } void SMHZPVertex::doinit() { GeneralVVSVertex::doinit(); //PDG codes for particles at vertices addToList(23,22,25); _theSM = dynamic_ptr_cast(generator()->standardModel()); if( !_theSM ) throw InitException() << "SMHGGVertex::doinit() - The pointer to the SM object is null." << Exception::abortnow; _mw = getParticleData(ThePEG::ParticleID::Wplus)->mass(); _mz = getParticleData(ThePEG::ParticleID::Z0)->mass(); GeneralVVSVertex::doinit(); } void SMHZPVertex::persistentOutput(PersistentOStream & os) const { os << _theSM << ounit(_mw,GeV) << ounit(_mz,GeV) << _massopt << _minloop << _maxloop; } void SMHZPVertex::persistentInput(PersistentIStream & is, int) { is >> _theSM >> iunit(_mw, GeV) >> iunit(_mz,GeV) >> _massopt >> _minloop >> _maxloop; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigSMHZPVertex("Herwig::SMHZPVertex", "libHerwig.so"); void SMHZPVertex::Init() { static ClassDocumentation documentation ("The SMHZPVertex class provides a simple implementation of the " "Higgs-Z-Photon loop looping to allow the calculation of the " "associated Higgs decay mode H -> Z gamma."); static Parameter interfaceMinQuarkInLoop ("MinQuarkInLoop", "The minimum flavour of the quarks to include in the loops", &SMHZPVertex::_minloop, 6, 1, 6, false, false, Interface::limited); static Parameter interfaceMaxQuarkInLoop ("MaxQuarkInLoop", "The maximum flavour of the quarks to include in the loops", &SMHZPVertex::_maxloop, 6, 1, 6, false, false, Interface::limited); static Switch interfaceMassOption ("LoopMassScheme", "Switch for the treatment of the masses in the loops ", &SMHZPVertex::_massopt, 2, false, false); static SwitchOption interfaceHeavyMass (interfaceMassOption, "PoleMasses", "The loop is calculcated with the pole quark masses", 1); static SwitchOption interfaceNormalMass (interfaceMassOption, "RunningMasses", "running quark masses are taken in the loop", 2); } void SMHZPVertex::setCoupling(Energy2 q2, tcPDPtr part2, tcPDPtr part3, tcPDPtr part1) { if(part3->id()==ParticleID::Z0) swap(part2,part3); assert( part1->id() == ParticleID::h0 && part2->id() == ParticleID::Z0 && part3->id() == ParticleID::gamma ); int Qminloop = _minloop; int Qmaxloop = _maxloop; if (_maxloop < _minloop) swap(Qmaxloop,Qminloop); double cw = sqrt(1.-sin2ThetaW()),sw=sqrt(sin2ThetaW()),tw = sw/cw; if(q2 != _q2last||_couplast==0.) { double g = weakCoupling(q2); double e2 = sqr(electroMagneticCoupling(q2)); _couplast = UnitRemoval::E * e2 * g / 16. / _mw/ sqr(Constants::pi); _q2last = q2; } norm(_couplast); Complex loop(0.); // quark loops for ( int i = Qminloop; i <= Qmaxloop; ++i ) { tcPDPtr qrk = getParticleData(i); Energy mass = (2 == _massopt) ? _theSM->mass(q2,qrk) : qrk->mass(); double charge = i%2==0 ? generator()->standardModel()->eu() : generator()->standardModel()->ed(); double gv = i%2==0 ? generator()->standardModel()->vu() : generator()->standardModel()->vd(); double tau = 0.25*invariant(0,0)/sqr(mass), lambda(0.25*sqr(_mz/mass)); loop += 3.*charge*gv *(I1(tau,lambda)-I2(tau,lambda))/(sw*cw); } // lepton loops int Lminloop = 3; // still fixed value int Lmaxloop = 3; // still fixed value for (int i = Lminloop; i <= Lmaxloop; ++i) { tcPDPtr lpt = getParticleData(9 + 2*i); Energy mass = (2 == _massopt) ? _theSM->mass(q2,lpt) : lpt->mass(); double charge = generator()->standardModel()->ee(); double gv = generator()->standardModel()->ve(); double tau = 0.25*invariant(0,0)/sqr(mass), lambda(0.25*sqr(_mz/mass)); loop += charge*gv*(I1(tau,lambda)-I2(tau,lambda))/(sw*cw); } // W loop double tau = 0.25*invariant(0,0)/sqr(_mw), lambda(0.25*sqr(_mz/_mw)); loop += ( 4.*(3.-sqr(tw))*I2(tau,lambda) + ((1.+2.*tau)*sqr(tw)-(5.+2.*tau))*I1(tau,lambda))/tw; a00(loop); a11(0.0); a12(0.0); a21(-loop); a22(0.0); aEp(0.0); // test of the width calculation // Energy mh = getParticleData(25)->mass(); // Energy pre = sqr(weakCoupling(q2))*pow(electroMagneticCoupling(q2),4)*mh*sqr(mh/_mw) // /128./16./pow(Constants::pi,5)*pow(double(1.-sqr(_mz/mh)),3)* // std::real(std::norm(loop)); } Complex SMHZPVertex::I1(double tau,double lambda) const { return (-0.5+0.5/(tau-lambda)*(f(tau)-f(lambda))+ lambda/(tau-lambda)*(g(tau)-g(lambda)))/(tau-lambda); } Complex SMHZPVertex::I2(double tau,double lambda) const { return 0.5/(tau-lambda)*(f(tau)-f(lambda)); } Complex SMHZPVertex::f(double tau) const { if(tau>0 && tau<= 1.) { return sqr(asin(sqrt(tau))); } else if(tau>1.) { double lx = log(sqrt(tau)+sqrt(tau-1)); return -sqr(lx)+0.25*sqr(Constants::pi)+Complex(0.,1.)*Constants::pi*lx; } else assert(false); } Complex SMHZPVertex::g(double tau) const { if(tau>0 && tau<= 1.) { return sqrt((1.-tau)/tau)*asin(sqrt(tau)); } else if(tau>1.) { double lx = log(sqrt(tau)+sqrt(tau-1)); double root = sqrt((tau-1.)/tau); return root*(lx-0.5*Complex(0,1)*Constants::pi); } else assert(false); } diff --git a/Models/StandardModel/SMWWHHVertex.cc b/Models/StandardModel/SMWWHHVertex.cc --- a/Models/StandardModel/SMWWHHVertex.cc +++ b/Models/StandardModel/SMWWHHVertex.cc @@ -1,74 +1,75 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the SMWWHHVertex class. // #include "SMWWHHVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; SMWWHHVertex::SMWWHHVertex() : ratio_(0.), couplast_(0.), q2last_(ZERO) { orderInGem(2); orderInGs (0); + colourStructure(ColourStructure::SINGLET); } IBPtr SMWWHHVertex::clone() const { return new_ptr(*this); } IBPtr SMWWHHVertex::fullclone() const { return new_ptr(*this); } void SMWWHHVertex::persistentOutput(PersistentOStream & os) const { os << ratio_; } void SMWWHHVertex::persistentInput(PersistentIStream & is, int) { is >> ratio_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigSMWWHHVertex("Herwig::SMWWHHVertex", "Herwig.so"); void SMWWHHVertex::Init() { static ClassDocumentation documentation ("The SMWWHHVertex class implements the coupling of two electroweeak" " gauge bosons and the Higgs boson in the Standard Model."); } void SMWWHHVertex::doinit() { addToList( 23, 23, 25, 25); addToList( 24,-24, 25, 25); VVSSVertex::doinit(); ratio_ = 1./(1.-sin2ThetaW()); } void SMWWHHVertex::setCoupling(Energy2 q2, tcPDPtr part1,tcPDPtr, #ifndef NDEBUG tcPDPtr part3,tcPDPtr part4) { #else tcPDPtr,tcPDPtr) { #endif assert(part3->id()==ParticleID::h0 && part4->id()==ParticleID::h0 ); if(q2!=q2last_||couplast_==0.) { couplast_ = sqr(weakCoupling(q2)); q2last_=q2; } if(part1->id()==ParticleID::Z0) { norm(0.5*couplast_*ratio_); } else { norm(0.5*couplast_); } } diff --git a/Models/StandardModel/SMWWHVertex.cc b/Models/StandardModel/SMWWHVertex.cc --- a/Models/StandardModel/SMWWHVertex.cc +++ b/Models/StandardModel/SMWWHVertex.cc @@ -1,71 +1,72 @@ // -*- C++ -*- // // SMWWHVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 WWHVertex class. // #include "SMWWHVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; using namespace ThePEG::Helicity; SMWWHVertex::SMWWHVertex() : _couplast(0.), _q2last(ZERO), _mw(ZERO), _zfact(0.) { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::SINGLET); } void SMWWHVertex::doinit() { addToList(24,-24, 25); addToList(23, 23, 25); // parameters _mw = getParticleData(ThePEG::ParticleID::Wplus)->mass(); _zfact = 1./(1.-sin2ThetaW()); // base class VVSVertex::doinit(); } void SMWWHVertex::persistentOutput(PersistentOStream & os) const { os << ounit(_mw,GeV) << _zfact; } void SMWWHVertex::persistentInput(PersistentIStream & is, int) { is >> iunit(_mw,GeV) >> _zfact; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigSMWWHVertex("Herwig::SMWWHVertex", "Herwig.so"); void SMWWHVertex::Init() { static ClassDocumentation documentation ("The SMWWHVertex class is the implementation" " of the helicity amplitude calculation for the coupling of the Standard" " Model electroweak gauge bosons to the Higgs."); } void SMWWHVertex::setCoupling(Energy2 q2,tcPDPtr aa,tcPDPtr, tcPDPtr) { int ibos=abs(aa->id()); // first the overall normalisation if(q2!=_q2last||_couplast==0.) { _couplast = weakCoupling(q2) * UnitRemoval::InvE * _mw; _q2last=q2; } if(ibos==24) norm(_couplast); else if(ibos==23) norm(_couplast*_zfact); else throw HelicityConsistencyError() << "SMWWHVertex::setCoupling " << "Invalid particles in WWH Vertex" << Exception::runerror; } diff --git a/Models/StandardModel/SMWWWVertex.cc b/Models/StandardModel/SMWWWVertex.cc --- a/Models/StandardModel/SMWWWVertex.cc +++ b/Models/StandardModel/SMWWWVertex.cc @@ -1,89 +1,90 @@ // -*- C++ -*- // // SMWWWVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SMWWWVertex class. // #include "SMWWWVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; void SMWWWVertex::persistentOutput(PersistentOStream & os) const { os << _zfact; } void SMWWWVertex::persistentInput(PersistentIStream & is, int) { is >> _zfact; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigSMWWWVertex("Herwig::SMWWWVertex", "Herwig.so"); void SMWWWVertex::Init() { static ClassDocumentation documentation ("The SMWWWVertex class is the implementation of the " "Standard Model triple electroweak boson coupling."); } // couplings for the WWW vertex void SMWWWVertex::setCoupling(Energy2 q2,tcPDPtr a,tcPDPtr b, tcPDPtr c) { int ida=a->id(); int idb=b->id(); int idc=c->id(); // first the overall normalisation if(q2!=_q2last||_couplast==0.) { _couplast = electroMagneticCoupling(q2); _q2last=q2; } // W- W+ photon and cylic perms if((ida==-24 && idb== 24 && idc== 22) || (ida== 22 && idb==-24 && idc== 24) || (ida== 24 && idb== 22 && idc==-24) ) norm(_couplast); // W+ W- photon (anticylic perms of above) else if((ida== 24 && idb==-24 && idc== 22) || (ida== 22 && idb== 24 && idc==-24) || (ida==-24 && idb== 22 && idc== 24) ) norm(-_couplast); // W- W+ Z and cylic perms else if((ida==-24 && idb== 24 && idc== 23) || (ida== 23 && idb==-24 && idc== 24) || (ida== 24 && idb== 23 && idc==-24) ) norm(_couplast*_zfact); // W+ W- Z (anticylic perms of above) else if((ida== 24 && idb==-24 && idc== 23) || (ida== 23 && idb== 24 && idc==-24) || (ida==-24 && idb== 23 && idc== 24) ) norm(-_couplast*_zfact); else throw Helicity::HelicityConsistencyError() << "SMWWWVertex::setCoupling " << "Invalid particles in WWW Vertex" << a->PDGName() << " " << b->PDGName() << " " << c->PDGName() << Exception::runerror; } SMWWWVertex::SMWWWVertex() : _zfact(0.),_couplast(0.), _q2last(sqr(Constants::MaxEnergy)) { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::SINGLET); } void SMWWWVertex::doinit() { addToList(24, -24, 22); addToList(24, -24, 23); VVVVertex::doinit(); // factor for the Z vertex double sw2=sin2ThetaW(); _zfact = sqrt((1.-sw2)/sw2); } diff --git a/Models/StandardModel/SMWWWWVertex.cc b/Models/StandardModel/SMWWWWVertex.cc --- a/Models/StandardModel/SMWWWWVertex.cc +++ b/Models/StandardModel/SMWWWWVertex.cc @@ -1,167 +1,168 @@ // -*- C++ -*- // // SMWWWWVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SMWWWWVertex class. // #include "SMWWWWVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; using namespace ThePEG; SMWWWWVertex::SMWWWWVertex() : _couplast(0.0), _q2last(sqr(Constants::MaxEnergy)), _vfact(4,0.0), _sw2(0.), _cw2(0.) { orderInGem(2); orderInGs(0); + colourStructure(ColourStructure::SINGLET); } void SMWWWWVertex::doinit() { // particles addToList(24, -24, 24, -24); addToList(23, 24, 23, -24); addToList(22, 24, 22, -24); addToList(22, 24, 23, -24); VVVVVertex::doinit(); // couplings _sw2 = sin2ThetaW(); _cw2 = 1.-_sw2; double sw = sqrt(_sw2); double cw = sqrt(_cw2); _vfact[0] = -1./_sw2; _vfact[1] = _cw2/_sw2; _vfact[2] = 1.; _vfact[3] = cw/sw; // pointer for intermediate particles _gamma = getParticleData(ThePEG::ParticleID::gamma); _Z0 = getParticleData(ThePEG::ParticleID::Z0); _wplus = getParticleData(ThePEG::ParticleID::Wplus); _wminus = getParticleData(ThePEG::ParticleID::Wminus); } void SMWWWWVertex::persistentOutput(PersistentOStream & os) const { os << _gamma << _Z0 << _wplus << _wminus << _vfact << _sw2 << _cw2; } void SMWWWWVertex::persistentInput(PersistentIStream & is, int) { is >> _gamma >> _Z0 >> _wplus >> _wminus >> _vfact >> _sw2 >> _cw2; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigSMWWWWVertex("Herwig::SMWWWWVertex", "Herwig.so"); void SMWWWWVertex::Init() { static ClassDocumentation documentation ("The SMWWWWVertex class is the implementation of the" " Standard Model quartic electroweka gauge boson coupling."); } // couplings for the WWWW vertex void SMWWWWVertex::setCoupling(Energy2 q2,tcPDPtr a,tcPDPtr b, tcPDPtr c,tcPDPtr d) { // id's of the particles long id[4]={a->id(),b->id(),c->id(),d->id()}; // order the particles int ngamma(0),nz(0); int iorder[4]; for(int ix=0;ix<4;++ix) { if (id[ix]==22) ++ngamma; else if (id[ix]==23) ++nz; } // if photons or Z's if(ngamma!=0 || nz!=0) { int iy=0; // put the photons first for(int ix=0;iyid()); else if(iorder[0]==1) ida = abs(b->id()); else if(iorder[0]==2) ida = abs(c->id()); else if(iorder[0]==3) ida = abs(d->id()); if(iorder[1]==0) idb = abs(a->id()); else if(iorder[1]==1) idb = abs(b->id()); else if(iorder[1]==2) idb = abs(c->id()); else if(iorder[1]==3) idb = abs(d->id()); // WWWW coupling if(ida==24) norm(_vfact[0]*_couplast); // ZZWW coupling else if(ida==23&&idb==23) norm(_vfact[1]*_couplast); // gamma gamma WW coupling else if(ida==22&&idb==22) norm(_couplast); // gamma Z WW coupling else if(ida==22&&idb==23) norm(_vfact[3]*_couplast); else assert(false); } diff --git a/Models/StandardModel/StandardModel.cc b/Models/StandardModel/StandardModel.cc --- a/Models/StandardModel/StandardModel.cc +++ b/Models/StandardModel/StandardModel.cc @@ -1,200 +1,207 @@ // -*- C++ -*- // // StandardModel.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 StandardModel class. // #include "StandardModel.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/Models/General/ModelGenerator.h" #include "ThePEG/Repository/BaseRepository.h" using namespace Herwig; StandardModel::StandardModel() {} StandardModel::~StandardModel() {} StandardModel::StandardModel(const StandardModel & x) : StandardModelBase(x), FFZVertex_ (x.FFZVertex_), FFPVertex_ (x.FFPVertex_) , FFGVertex_ (x.FFGVertex_) , FFWVertex_ (x.FFWVertex_) , FFHVertex_ (x.FFHVertex_) , WWHVertex_ (x.WWHVertex_) , GGGVertex_ (x.GGGVertex_) , WWWVertex_ (x.WWWVertex_) , GGGGVertex_(x.GGGGVertex_), WWWWVertex_(x.WWWWVertex_), HGGVertex_ (x.HGGVertex_) , HPPVertex_ (x.HPPVertex_) , HHHVertex_ (x.HHHVertex_) , WWHHVertex_ (x.WWHHVertex_) , vertexList_(x.vertexList_), extraVertices_(x.extraVertices_), - runningMass_(x.runningMass_),modelGenerator_(x.modelGenerator_) + runningMass_(x.runningMass_),modelGenerator_(x.modelGenerator_), + couplings_(x.couplings_) {} IBPtr StandardModel::clone() const { return new_ptr(*this); } IBPtr StandardModel::fullclone() const { return new_ptr(*this); } void StandardModel::doinit() { if(runningMass_) { runningMass_->init(); } //add Standard Model vertices if ( registerDefaultVertices() ) { addVertex(FFZVertex_); addVertex(FFPVertex_); addVertex(FFGVertex_); addVertex(FFWVertex_); addVertex(vertexFFH()); addVertex(vertexWWH()); addVertex(GGGVertex_); addVertex(WWWVertex_); addVertex(GGGGVertex_); addVertex(WWWWVertex_); addVertex(vertexHGG()); addVertex(HPPVertex_); if(HHHVertex_ ) addVertex(HHHVertex_); if(WWHHVertex_) addVertex(WWHHVertex_); } + if(couplings_.find("QED")==couplings_.end()) { + couplings_["QED"] = make_pair(1,99); + } + if(couplings_.find("QCD")==couplings_.end()) { + couplings_["QCD"] = make_pair(2,99); + } StandardModelBase::doinit(); } void StandardModel::persistentOutput(PersistentOStream & os) const { os << FFZVertex_ <> FFZVertex_ >> FFPVertex_ >> FFGVertex_ >> FFWVertex_ >> FFHVertex_ >> WWHVertex_ >> GGGGVertex_ >> WWWWVertex_ >> GGGVertex_ >> WWWVertex_ >> HGGVertex_ >> HPPVertex_ >> HHHVertex_ >> WWHHVertex_ >> runningMass_ >> vertexList_ >> extraVertices_ >> modelGenerator_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigStandardModel("Herwig::StandardModel", "Herwig.so"); void StandardModel::Init() { static Reference interfaceVertexFFZ ("Vertex/FFZ", "Reference to the Standard Model FFZ Vertex", &StandardModel::FFZVertex_, false, false, true, false); static Reference interfaceVertexFFP ("Vertex/FFP", "Reference to the Standard Model FFP Vertex", &StandardModel::FFPVertex_, false, false, true, false); static Reference interfaceVertexFFG ("Vertex/FFG", "Reference to the Standard Model FFG Vertex", &StandardModel::FFGVertex_, false, false, true, false); static Reference interfaceVertexFFW ("Vertex/FFW", "Reference to the Standard Model FFW Vertex", &StandardModel::FFWVertex_, false, false, true, false); static Reference interfaceVertexFFH ("Vertex/FFH", "Reference to the Standard Model FFH Vertex.", &StandardModel::FFHVertex_, false, false, true, false); static Reference interfaceVertexGGG ("Vertex/GGG", "Reference to the Standard Model GGG Vertex", &StandardModel::GGGVertex_, false, false, true, false); static Reference interfaceVertexWWW ("Vertex/WWW", "Reference to the Standard Model WWW Vertex", &StandardModel::WWWVertex_, false, false, true, false); static Reference interfaceVertexWWH ("Vertex/WWH", "Reference to the Standard Model WWH Vertex", &StandardModel::WWHVertex_, false, false, true, false); static Reference interfaceVertexWWWW ("Vertex/WWWW", "Reference to the Standard Model WWWW Vertex", &StandardModel::WWWWVertex_, false, false, true, false); static Reference interfaceVertexGGGG ("Vertex/GGGG", "Reference to the Standard Model GGGG Vertex", &StandardModel::GGGGVertex_, false, false, true, false); static Reference interfaceVertexHGG ("Vertex/HGG", "Reference to the StandardModel HGG Vertex", &StandardModel::HGGVertex_, false, false, true, false); static Reference interfaceVertexHPP ("Vertex/HPP", "Reference to StandardModel HPPVertex", &StandardModel::HPPVertex_, false, false, true, false); static Reference interfaceVertexHHH ("Vertex/HHH", "Reference to the Standard Model HHHVertex", &StandardModel::HHHVertex_, false, false, true, true); static Reference interfaceVertexWWHH ("Vertex/WWHH", "Reference to the Standard Model WWHHVertex", &StandardModel::WWHHVertex_, false, false, true, true); static RefVector interfaceExtraVertices ("ExtraVertices", "Additional vertices to be considered in automatic ME construction.", &StandardModel::extraVertices_, -1, true, false, true, false, false); static Reference interfaceRunningMass ("RunningMass", "Reference to the running mass object", &StandardModel::runningMass_, false, false, true, false); static Reference interfaceModelGenerator ("ModelGenerator", "Pointer to ModelGenerator class", &StandardModel::modelGenerator_, false, false, true, true); static ClassDocumentation documentation ("The StandardModel class inherits from StandardModelBase" "and supplies additional couplings and access to the StandardModel" "vertices for helicity amplitude calculations" ); } void StandardModel::resetMass(long id, Energy mass,tPDPtr part) { if(!part) part = getParticleData(id); if(!part) return; const InterfaceBase * ifb = BaseRepository::FindInterface(part, "NominalMass"); ostringstream os; os << setprecision(12) << abs(mass/GeV); ifb->exec(*part, "set", os.str()); } diff --git a/Models/StandardModel/StandardModel.h b/Models/StandardModel/StandardModel.h --- a/Models/StandardModel/StandardModel.h +++ b/Models/StandardModel/StandardModel.h @@ -1,458 +1,478 @@ // -*- C++ -*- // // StandardModel.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_StandardModel_H #define HERWIG_StandardModel_H // // This is the declaration of the StandardModel class. #include "ThePEG/StandardModel/StandardModelBase.h" #include "Herwig/Models/StandardModel/RunningMassBase.h" #include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVVVVertex.h" #include "ThePEG/Helicity/Vertex/AbstractFFSVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVVSVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVVVVVertex.h" #include "ThePEG/Helicity/Vertex/AbstractSSSVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVVSSVertex.h" #include "ThePEG/Helicity/Vertex/AbstractSSSSVertex.h" #include "Herwig/Models/General/ModelGenerator.fh" #include "StandardModel.fh" namespace Herwig { using namespace ThePEG; using namespace ThePEG::Helicity; /** \ingroup Models * * This is the Herwig StandardModel class which inherits from ThePEG * Standard Model class and implements additional Standard Model couplings, * access to vertices for helicity amplitude calculations etc. * * @see StandardModelBase */ class StandardModel: public StandardModelBase { /** * Some typedefs for the pointers. */ //@{ /** * Pointer to the RunningMassBase object */ typedef Ptr::pointer runPtr; /** * Transient pointer to the RunningMassBase object */ typedef Ptr::transient_pointer trunPtr; //@} public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor */ StandardModel(); /** * Copy-constructor. */ StandardModel(const StandardModel &); /** * Destructor */ virtual ~StandardModel(); //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interfaces. */ static void Init(); protected: /** * Should the default vertices be considered for generic diagrams */ virtual bool registerDefaultVertices() const { return true; } public: /** * The left and right couplings of the Z^0 including sin and cos theta_W. */ //@{ /** * The left-handed coupling of a neutrino */ double lnu() const { return 0.25/sqrt(sin2ThetaW()*(1.-sin2ThetaW()))*(vnu()+anu()); } /** * The left-handed coupling of a charged lepton. */ double le() const { return 0.25/sqrt(sin2ThetaW()*(1.-sin2ThetaW()))*(ve()+ae()); } /** * The left-handed coupling of an up type quark. */ double lu() const { return 0.25/sqrt(sin2ThetaW()*(1.-sin2ThetaW()))*(vu()+au()); } /** * The left-handed coupling of a down type quark. */ double ld() const { return 0.25/sqrt(sin2ThetaW()*(1.-sin2ThetaW()))*(vd()+ad()); } /** * The right-handed coupling of a neutrino */ double rnu() const { return 0.25/sqrt(sin2ThetaW()*(1.-sin2ThetaW()))*(vnu()-anu()); } /** * The right-handed coupling of a charged lepton. */ double re() const { return 0.25/sqrt(sin2ThetaW()*(1.-sin2ThetaW()))*(ve()-ae()); } /** * The right-handed coupling of an up type quark. */ double ru() const { return 0.25/sqrt(sin2ThetaW()*(1.-sin2ThetaW()))*(vu()-au()); } /** * The right-handed coupling of a down type quark. */ double rd() const { return 0.25/sqrt(sin2ThetaW()*(1.-sin2ThetaW()))*(vd()-ad()); } //@} /** * Pointers to the objects handling the vertices. */ //@{ /** * Pointer to the fermion-fermion-Z vertex */ virtual tAbstractFFVVertexPtr vertexFFZ() const { return FFZVertex_; } /** * Pointer to the fermion-fermion-photon vertex */ virtual tAbstractFFVVertexPtr vertexFFP() const { return FFPVertex_; } /** * Pointer to the fermion-fermion-gluon vertex */ virtual tAbstractFFVVertexPtr vertexFFG() const { return FFGVertex_; } /** * Pointer to the fermion-fermion-W vertex */ virtual tAbstractFFVVertexPtr vertexFFW() const { return FFWVertex_; } /** * Pointer to the fermion-fermion-Higgs vertex */ virtual tAbstractFFSVertexPtr vertexFFH() const { return FFHVertex_; } /** * Pointer to the triple gluon vertex */ virtual tAbstractVVVVertexPtr vertexGGG() const { return GGGVertex_; } /** * Pointer to the triple electroweak gauge boson vertex. */ virtual tAbstractVVVVertexPtr vertexWWW() const { return WWWVertex_; } /** * Pointer to the two electroweak gauge boson Higgs vertex. */ virtual tAbstractVVSVertexPtr vertexWWH() const { return WWHVertex_; } /** * Pointer to the quartic electroweak gauge boson vertex. */ virtual tAbstractVVVVVertexPtr vertexWWWW() const { return WWWWVertex_; } /** * Pointer to the quartic gluon vertex */ virtual tAbstractVVVVVertexPtr vertexGGGG() const { return GGGGVertex_; } /** * Pointer to the quartic gluon vertex */ virtual tAbstractVVSVertexPtr vertexHGG() const { return HGGVertex_; } /** * Pointer to the quartic gluon vertex */ virtual tAbstractVVSVertexPtr vertexHPP() const { return HPPVertex_; } /** * Pointer to the triple Higgs vertex */ virtual tAbstractSSSVertexPtr vertexHHH() const { return HHHVertex_; } /** * Pointer to the WWHH vertex */ virtual tAbstractVVSSVertexPtr vertexWWHH() const { return WWHHVertex_; } /** * Total number of vertices */ unsigned int numberOfVertices() const { return vertexList_.size() + extraVertices_.size(); } /** * Access to a vertex from the list */ tVertexBasePtr vertex(size_t ix) const { const size_t S = vertexList_.size(); if ( ix < S ) return vertexList_[ix]; else return extraVertices_[ix - S]; } //@} /** * Return the running mass for a given scale \f$q^2\f$ and particle type. * @param scale The scale \f$q^2\f$. * @param part The ParticleData object for the particle */ Energy mass(Energy2 scale,tcPDPtr part) const { return runningMass_->value(scale,part); } /** * Return a pointer to the object handling the running mass. */ trunPtr massPtr() const { return runningMass_; } + + /** + * Set the couplings in the model + */ + const map > & couplings() const { + return couplings_; + } 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: /** * 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(); //@} protected: /** * Add a vertex to the list */ void addVertex(VertexBasePtr in) { if ( in ) vertexList_.push_back(in); } /** * Helper function to reset the mass of a ParticleData object * in BSM models. */ void resetMass(long id, Energy mass,tPDPtr particle=tPDPtr()); +protected: + + /** + * Set the couplings in the model + */ + void setCouplings(string name,pair vals) { + couplings_[name] = vals; + } + private: /** * Private and non-existent assignment operator. */ StandardModel & operator=(const StandardModel &); private: /** * Pointers to the vertices for Standard Model helicity amplitude * calculations. */ //@{ /** * Pointer to the fermion-fermion-Z vertex */ AbstractFFVVertexPtr FFZVertex_; /** * Pointer to the fermion-fermion-photon vertex */ AbstractFFVVertexPtr FFPVertex_; /** * Pointer to the fermion-fermion-gluon vertex */ AbstractFFVVertexPtr FFGVertex_; /** * Pointer to the fermion-fermion-W vertex */ AbstractFFVVertexPtr FFWVertex_; /** * Pointer to the fermion-fermion-Higgs vertex */ AbstractFFSVertexPtr FFHVertex_; /** * Pointer to the two electroweak gauge boson Higgs vertex. */ AbstractVVSVertexPtr WWHVertex_; /** * Pointer to the triple gluon vertex */ AbstractVVVVertexPtr GGGVertex_; /** * Pointer to the triple electroweak gauge boson vertex. */ AbstractVVVVertexPtr WWWVertex_; /** * Pointer to the quartic gluon vertex */ AbstractVVVVVertexPtr GGGGVertex_; /** * Pointer to the quartic electroweak gauge boson vertex. */ AbstractVVVVVertexPtr WWWWVertex_; /** * Pointer to higgs-gluon-gluon vertex */ AbstractVVSVertexPtr HGGVertex_; /** * Pointer to higgs-gamma-gamma vertex */ AbstractVVSVertexPtr HPPVertex_; /** * Pointer to triple Higgs vertex */ AbstractSSSVertexPtr HHHVertex_; /** * Pointer to WWHH vertex */ AbstractVVSSVertexPtr WWHHVertex_; /** * Full list of vertices as a vector to allow searching */ vector vertexList_; /** * Additional vertices to be considered in automatic ME construction */ vector extraVertices_; //@} /** * The running mass. */ runPtr runningMass_; /** * Pointer to ModelGenerator Class */ ModelGeneratorPtr modelGenerator_; + /** + * Couplings in the model + */ + map > couplings_; }; } #endif /* HERWIG_StandardModel_H */ diff --git a/Models/Susy/NMSSM/NMSSMFFHVertex.cc b/Models/Susy/NMSSM/NMSSMFFHVertex.cc --- a/Models/Susy/NMSSM/NMSSMFFHVertex.cc +++ b/Models/Susy/NMSSM/NMSSMFFHVertex.cc @@ -1,164 +1,165 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the NMSSMFFHVertex class. // #include "NMSSMFFHVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include "NMSSM.h" using namespace Herwig; using namespace ThePEG::Helicity; NMSSMFFHVertex::NMSSMFFHVertex() : _mw(0.*MeV), _sinb(0.), _cosb(0.), _tanb(0.), _idlast(make_pair(0,0)), _q2last(0.*MeV2), _masslast(make_pair(0.*MeV,0*MeV)), _couplast(0.) { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::DELTA); } void NMSSMFFHVertex::persistentOutput(PersistentOStream & os) const { os << _mixS << _mixP << ounit(_mw,GeV) << _sinb << _cosb << _tanb << _sw << _theSM; } void NMSSMFFHVertex::persistentInput(PersistentIStream & is, int) { is >> _mixS >> _mixP >> iunit(_mw,GeV) >> _sinb >> _cosb >> _tanb >> _sw >> _theSM; } void NMSSMFFHVertex::doinit() { // the quarks and neutral higgs int in[5]={25,35,45,36,46}; for(unsigned int iy=0;iy<5;++iy) for(int ix=1;ix<7;++ix) addToList( -ix, ix, in[iy] ); // leptons and neutral higgs for(unsigned int iy=0;iy<5;++iy) for(int ix=11;ix<17;ix+=2) addToList( -ix, ix, in[iy] ); // the quarks and the charged higgs //H- for(int ix=0;ix<3;++ix) addToList(2*ix+2, -2*ix-1, -37); //H+ for(int ix=0;ix<3;++ix) addToList(-(2*ix+2), 2*ix+1, 37); // the leptons and the charged higgs //H- for(int ix=0;ix<3;++ix) addToList( 2*ix+12, -2*ix-11, -37 ); //H+ for(int ix=0;ix<3;++ix) addToList( -(2*ix+12), 2*ix+11, 37 ); // cast to NMSSM model tcNMSSMPtr model=dynamic_ptr_cast(generator()->standardModel()); if(!model) throw InitException() << "Must have the NMSSM Model in NMSSMFFHVertex::doinit()" << Exception::runerror; _theSM = model; // sin theta_W double sw2=_theSM->sin2ThetaW(); _sw = sqrt(sw2); // get the mixing matrices _mixS=model->CPevenHiggsMix(); if(!_mixS) throw InitException() << "Mixing matrix for CP-even neutral Higgs" << " bosons is not set in NMSSMFFHVertex::doinit()" << Exception::runerror; _mixP=model->CPoddHiggsMix(); if(!_mixP) throw InitException() << "Mixing matrix for CP-odd neutral Higgs" << " bosons is not set in NMSSMFFHVertex::doinit()" << Exception::runerror; // Mass of the W boson _mw=getParticleData(ParticleID::Wplus)->mass(); // sin and cos beta _tanb = model->tanBeta(); double beta = atan(_tanb); _sinb=sin(beta); _cosb=cos(beta); // base class FFSVertex::doinit(); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigNMSSMFFHVertex("Herwig::NMSSMFFHVertex", "HwSusy.so HwNMSSM.so"); void NMSSMFFHVertex::Init() { static ClassDocumentation documentation ("The NMSSMFFHVertex class implements the vertex for the couplings" " of the Higgs bosons of the NMSSM to Standard Model fermions"); } //calulate the couplings void NMSSMFFHVertex::setCoupling(Energy2 q2,tcPDPtr a,tcPDPtr b, tcPDPtr c) { int ihiggs=c->id(); int id(abs(a->id())); Complex output(1.); // neutral Higgs if(ihiggs==25||ihiggs==35||ihiggs==45||ihiggs==36||ihiggs==46) { if(_idlast.first!=id||q2!=_q2last) { _idlast.first=id; _masslast.first = _theSM->mass(q2,a); } output = _masslast.first/_mw; // CP-even if(ihiggs==25||ihiggs==35||ihiggs==45) { int iloc = (ihiggs-25)/10; output *= (id%2==0) ? (*_mixS)(iloc,1)/_sinb : (*_mixS)(iloc,0)/_cosb; left(1.); right(1.); } // CP-odd else { int iloc = (ihiggs-36)/10; output *= (id%2==0) ? (*_mixP)(iloc,1)/_sinb : (*_mixP)(iloc,0)/_cosb; left(1.); right(-1.); output *= Complex(0., 1.); } } // Charged higgs else if(abs(ihiggs)==37) { output *= -sqrt(2.); int id2=abs(b->id()); if(id2mass(q2,a); _masslast.second = _theSM->mass(q2,b); } double rgt = _masslast.first *_tanb/_mw; double lft = _masslast.second/_tanb/_mw; if(ihiggs>0) swap(lft,rgt); right(rgt); left (lft); } else { throw Exception() << "Unknown Higgs boson, PDG code = " << ihiggs << "in NMSSMFFHVertex::setCoupling()" << Exception::runerror; } // prefactor if(q2!=_q2last) { _couplast = 0.5*weakCoupling(q2); _q2last=q2; } norm(-_couplast*output); } diff --git a/Models/Susy/NMSSM/NMSSMGGHVertex.cc b/Models/Susy/NMSSM/NMSSMGGHVertex.cc --- a/Models/Susy/NMSSM/NMSSMGGHVertex.cc +++ b/Models/Susy/NMSSM/NMSSMGGHVertex.cc @@ -1,208 +1,209 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the NMSSMGGHVertex class. // #include "NMSSMGGHVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/Models/Susy/NMSSM/NMSSM.h" #include "Herwig/Looptools/clooptools.h" using namespace Herwig; NMSSMGGHVertex::NMSSMGGHVertex() : _sw(0.), _cw(0.), _mw(0.*MeV), _mz(0.*MeV),_lambdaVEV(0.*MeV), _lambda(0.), _v1(0.*MeV), _v2(0.*MeV), _triTp(0.*MeV), _triBt(0.*MeV), _sb(0.), _cb(0.), _masslast(make_pair(0.*MeV,0.*MeV)), _q2last(0.*MeV2), _couplast(0.), _coup(0.), _hlast(0), _recalc(true) { orderInGem(1); orderInGs(2); + colourStructure(ColourStructure::DELTA); } void NMSSMGGHVertex::doinit() { addToList(21,21,25); addToList(21,21,35); addToList(21,21,36); addToList(21,21,45); addToList(21,21,46); _theSM = dynamic_ptr_cast(generator()->standardModel()); if( !_theSM ) { throw InitException() << "NMSSMGGHVertex::doinit - The SM pointer is null!" << Exception::abortnow; } // SM parameters _sw = sqrt(sin2ThetaW()); _cw = sqrt(1. - sin2ThetaW()); _mw = getParticleData(24)->mass(); _mz = getParticleData(23)->mass(); _top = getParticleData(6); _bt = getParticleData(5); //NMSSM parameters tcNMSSMPtr nmssm = dynamic_ptr_cast(_theSM); _mixS = nmssm->CPevenHiggsMix(); _mixP = nmssm->CPoddHiggsMix(); _mixQt = nmssm->stopMix(); _mixQb = nmssm->sbottomMix(); double beta = atan(nmssm->tanBeta()); _sb = sin(beta); _cb = cos(beta); _v1 = sqrt(2.)*_mw*_cb; _v2 = sqrt(2.)*_mw*_sb; _lambda = nmssm->lambda(); _lambdaVEV = nmssm->lambdaVEV(); _triTp = nmssm->topTrilinear(); _triBt = nmssm->bottomTrilinear(); // resize vectors here and use setNParticles method // to the set the actual number in the loop. // Also only the top mass hass to be calculated at runtime masses.resize(6, Energy()); masses[0] = getParticleData(6)->mass(); masses[1] = getParticleData(5)->mass(); masses[2] = getParticleData(1000005)->mass(); masses[3] = getParticleData(2000005)->mass(); masses[4] = getParticleData(1000006)->mass(); masses[5] = getParticleData(2000006)->mass(); type.resize(6, PDT::Spin0); type[0] = PDT::Spin1Half; type[1] = PDT::Spin1Half; couplings.resize(6); VVSLoopVertex::doinit(); if(loopToolsInitialized()) Looptools::ltexi(); } void NMSSMGGHVertex::persistentOutput(PersistentOStream & os) const { os << _theSM << _sw << _cw << ounit(_mw, GeV) << ounit(_mz, GeV) << ounit(_lambdaVEV,GeV) << _lambda << ounit(_v1,GeV) << ounit(_v2,GeV) << ounit(_triTp,GeV) << ounit(_triBt,GeV) << _top << _bt << _mixS << _mixP << _mixQt << _mixQb << _sb << _cb; } void NMSSMGGHVertex::persistentInput(PersistentIStream & is, int) { is >> _theSM >> _sw >> _cw >> iunit(_mw, GeV) >> iunit(_mz, GeV) >> iunit(_lambdaVEV,GeV) >> _lambda >> iunit(_v1,GeV) >> iunit(_v2,GeV) >> iunit(_triTp,GeV) >> iunit(_triBt,GeV) >> _top >> _bt >> _mixS >> _mixP >> _mixQt >> _mixQb >> _sb >> _cb; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigNMSSMGGHVertex("Herwig::NMSSMGGHVertex", "HwSusy.so HwNMSSM.so"); void NMSSMGGHVertex::Init() { static ClassDocumentation documentation ("The effective coupling of a higgs to a pair of gluons in the " "NMSSM."); } void NMSSMGGHVertex::setCoupling(Energy2 q2, tcPDPtr p1, tcPDPtr p2, tcPDPtr p3) { long hid(p3->id()); if( q2 != _q2last ) { Looptools::clearcache(); _couplast = sqr(strongCoupling(q2)); _coup = weakCoupling(q2); _q2last = q2; _recalc = true; } norm(_couplast*_coup); // scalar higgs bosons if( hid != _hlast ) { _hlast = hid; _recalc = true; if( hid % 5 == 0 ) { // location of the higgs int iloc = (hid - 25)/10; // 6 particles in the loop setNParticles(6); // top and bottom quark masses Energy mt = _theSM->mass(q2, _top); Energy mb = _theSM->mass(q2, _bt); Complex c(0.); // couplings for the top quark loop c = -0.25*mt*(*_mixS)(iloc, 1)/_sb/_mw; couplings[0] = make_pair(c,c); masses[0] = mt; // couplings for the bottom quark loop c = -0.25*mb*(*_mixS)(iloc, 0)/_cb/_mw; couplings[1] = make_pair(c,c); masses[1] = mb; // sbottoms double f1 = mb/_mw/_cb; complex f2 = 0.5*_mz/_cw* ( - _cb*(*_mixS)(iloc,0) + _sb*(*_mixS)(iloc,1)); complex cpl; for(unsigned int ix=0;ix<2;++ix) { cpl = -f2*( (1. - 2.*sqr(_sw)/3.)*(*_mixQb)(ix, 0)*(*_mixQb)(ix, 0) + 2.*sqr(_sw)*(*_mixQb)(ix, 1)*(*_mixQb)(ix, 1)/3.) - f1*mb*(*_mixS)(iloc,0) *((*_mixQb)(ix, 0)*(*_mixQb)(ix, 0) + (*_mixQb)(ix, 1)*(*_mixQb)(ix, 1)) - 0.5*f1*(-_lambdaVEV*(*_mixS)(iloc,1) - _lambda*_v2*(*_mixS)(iloc,2)/_coup + _triBt*(*_mixS)(iloc,0))*((*_mixQb)(ix, 1)*(*_mixQb)(ix, 0) + (*_mixQb)(ix, 0)*(*_mixQb)(ix, 1)); couplings[2+ix] = make_pair(0.5*cpl*UnitRemoval::InvE,0.5*cpl*UnitRemoval::InvE); } // stop f1 = mt/_mw/_sb; for(unsigned int ix=0;ix<2;++ix) { cpl =+f2*( (1. - 4.*sqr(_sw)/3.)*(*_mixQt)(ix, 0)*(*_mixQt)(ix, 0) + 4.*sqr(_sw)*(*_mixQt)(ix, 1)*(*_mixQt)(ix, 1)/3.) - f1*mt*(*_mixS)(iloc,1) *((*_mixQt)(ix, 0)*(*_mixQt)(ix, 0) + (*_mixQt)(ix, 1)*(*_mixQt)(ix, 1)) - 0.5*f1*(-_lambdaVEV*(*_mixS)(iloc,0) - _lambda*_v1*(*_mixS)(iloc,2)/_coup + _triTp*(*_mixS)(iloc,1))*((*_mixQt)(ix, 1)*(*_mixQt)(ix, 0) + (*_mixQt)(ix, 0)*(*_mixQt)(ix, 1)); couplings[4+ix] = make_pair(0.5*cpl*UnitRemoval::InvE,0.5*cpl*UnitRemoval::InvE); } } // pseudoscalar higgs bosons else { // location of the higgs int iloc = (hid - 36)/10; // 2 particles in the loop setNParticles(2); // top and bottom quark masses Energy mt = _theSM->mass(q2, _top); Energy mb = _theSM->mass(q2, _bt); Complex c(0.); // top quark couplings c = Complex(0.,-1.)*0.25*mt*(*_mixP)(iloc, 1)/_sb/_mw; couplings[0] = make_pair(-c,c); masses[0] = mt; // bottom quark couplings c = Complex(0., -1.)*0.25*mb*(*_mixP)(iloc, 0)/_cb/_mw; couplings[1] = make_pair(-c,c); masses[1] = mb; } } if( _recalc ) { VVSLoopVertex::setCoupling(q2, p1, p2, p3); _recalc = false; } } diff --git a/Models/Susy/NMSSM/NMSSMGOGOHVertex.cc b/Models/Susy/NMSSM/NMSSMGOGOHVertex.cc --- a/Models/Susy/NMSSM/NMSSMGOGOHVertex.cc +++ b/Models/Susy/NMSSM/NMSSMGOGOHVertex.cc @@ -1,292 +1,293 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the NMSSMGOGOHVertex class. // #include "NMSSMGOGOHVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "NMSSM.h" using namespace Herwig; using namespace ThePEG::Helicity; NMSSMGOGOHVertex::NMSSMGOGOHVertex() : _lambda(0.), _kappa(0.), _sinb(0.), _cosb(0.), _sw(0.), _cw(0.), _q2last(0.*MeV2), _couplast(0.) { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::SINGLET); } void NMSSMGOGOHVertex::persistentOutput(PersistentOStream & os) const { os << _mixV << _mixU << _mixN << _mixS << _mixP << _lambda << _kappa << _sinb << _cosb << _sw << _cw; } void NMSSMGOGOHVertex::persistentInput(PersistentIStream & is, int) { is >> _mixV >> _mixU >> _mixN >> _mixS >> _mixP >> _lambda >> _kappa >> _sinb >> _cosb >> _sw >> _cw; } void NMSSMGOGOHVertex::doinit() { int ieven[3]={25,35,45}; int iodd [2]={36,46}; long ichar[2]={1000024,1000037}; long ineut[5]={1000022,1000023,1000025,1000035,1000045}; // CP-even charginos for(unsigned int ix=0;ix<2;++ix) { for(unsigned int iy=0;iy<2;++iy) { for(unsigned int iz=0;iz<3;++iz) { addToList(-ichar[ix], ichar[iy], ieven[iz]); } } } // CP-odd charginos for(unsigned int ix=0;ix<2;++ix) { for(unsigned int iy=0;iy<2;++iy) { for(unsigned int iz=0;iz<2;++iz) { addToList(-ichar[ix], ichar[iy], iodd [iz]); } } } // CP-even neutralinos for(unsigned int ix=0;ix<5;++ix) { for(unsigned int iy=0;iy<5;++iy) { for(unsigned int iz=0;iz<3;++iz) { addToList( ineut[ix], ineut[iy], ieven[iz]); } } } // CP-odd neutralinos for(unsigned int ix=0;ix<5;++ix) { for(unsigned int iy=0;iy<5;++iy) { for(unsigned int iz=0;iz<2;++iz) { addToList( ineut[ix], ineut[iy], iodd[iz]); } } } // charged higgs for(unsigned int ix=0;ix<5;++ix) { for(unsigned int iy=0;iy<2;++iy) { addToList(ineut[ix], -ichar[iy], 37); addToList(ineut[ix], ichar[iy], -37); } } tcNMSSMPtr model=dynamic_ptr_cast(generator()->standardModel()); // SM parameters // sin theta_W double sw2=sin2ThetaW(); _cw=sqrt(1.0 - sw2); _sw=sqrt(sw2); if(!model) throw InitException() << "Must have the NMSSM Model in " << "NMSSMGOGOHVertex::doinit()" << Exception::runerror; // get the mixing matrices // higgs _mixS=model->CPevenHiggsMix(); if(!_mixS) throw InitException() << "Mixing matrix for CP-even neutral Higgs" << " bosons is not set in NMSSMGOGOHVertex::doinit()" << Exception::runerror; _mixP=model->CPoddHiggsMix(); if(!_mixP) throw InitException() << "Mixing matrix for CP-odd neutral Higgs" << " bosons is not set in NMSSMGOGOHVertex::doinit()" << Exception::runerror; // charginos _mixU = model->charginoUMix(); _mixV = model->charginoVMix(); if(!_mixU || !_mixV) throw InitException() << "NMSSMGOGOHVertex::doinit - " << "A mixing matrix pointer is null. U: " << _mixU << " V: " << _mixV << Exception::abortnow; // neutralinos _mixN = model->neutralinoMix(); if(!_mixN) throw InitException() << "NMSSMGOGOHVertex::doinit - The neutralino " << "mixing matrix pointer is null." << Exception::abortnow; // kappa and lambda couplings _lambda = model->lambda(); _kappa = model->kappa(); // sin and cos beta double beta = atan(model->tanBeta()); _sinb=sin(beta); _cosb=cos(beta); FFSVertex::doinit(); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigNMSSMGOGOHVertex("Herwig::NMSSMGOGOHVertex", "HwSusy.so HwNMSSM.so"); void NMSSMGOGOHVertex::Init() { static ClassDocumentation documentation ("The NMSSMGOGOHVertex class implements the couplings of the Higgs bosons" " of the NMSSM and the electroweak gauginos"); } void NMSSMGOGOHVertex::setCoupling(Energy2 q2,tcPDPtr part1,tcPDPtr part2, tcPDPtr part3) { long id1(part1->id()), id2(part2->id()), id3(part3->id()), ihigg(0), ig1(0), ig2(0); if( abs(id1) == 25 || abs(id1) == 35 || abs(id1) == 45 || abs(id1) == 36 || abs(id1) == 46 || abs(id1) == 37 ) { ihigg = id1; ig1 = id2; ig2 = id3; } else if( abs(id2) == 25 || abs(id2) == 35 || abs(id2) == 45 ||abs(id2) == 36 ||abs(id2) == 46 || abs(id2) == 37 ) { ihigg = id2; ig1 = id1; ig2 = id3; } else if( abs(id3) ==25 || abs(id3) == 35 || abs(id3) == 45 ||abs(id3) == 36 ||abs(id3) == 46 || abs(id3) == 37 ) { ihigg = id3; ig1 = id1; ig2 = id2; } else { throw HelicityConsistencyError() << "NMSSMGOGOHVertex::setCoupling - There is no higgs particle in " << "this vertex. Particles: " << id1 << " " << id2 << " " << id3 << Exception::runerror; return; } // weak coupling if(q2!=_q2last) { _couplast = weakCoupling(q2); _q2last = q2; } double rt = sqrt(0.5); // CP-even neutral higgs if(ihigg == 25 || ihigg == 35 || ihigg == 45) { int iloc = (ihigg - 25)/10; // chargino if(abs(ig1) == 1000024 || abs(ig1) == 1000037) { if( ig1 < 0 ) swap(ig1, ig2); int ic1 = abs(ig1)==1000024 ? 0 : 1; int ic2 = abs(ig2)==1000024 ? 0 : 1; Complex coupL = -_lambda*rt*conj((*_mixS)(iloc,2)*(*_mixU)(ic1,1)*(*_mixV)(ic2,1)) -_couplast*rt*(conj((*_mixS)(iloc,0)*(*_mixU)(ic1,1)*(*_mixV)(ic2,0) + (*_mixS)(iloc,1)*(*_mixU)(ic1,0)*(*_mixV)(ic2,1))); Complex coupR = -_lambda*rt*(*_mixS)(iloc,2)*(*_mixU)(ic2,1)*(*_mixV)(ic1,1) -_couplast*rt*((*_mixS)(iloc,0)*(*_mixU)(ic2,1)*(*_mixV)(ic1,0)+ (*_mixS)(iloc,1)*(*_mixU)(ic2,0)*(*_mixV)(ic1,1)); left(coupL); right(coupR); norm(1.0); } // neutralino else { int in1 = (ig1 < 1000024) ? (ig1 - 1000022) : (ig1 - 1000005)/10; int in2 = (ig2 < 1000024) ? (ig2 - 1000022) : (ig2 - 1000005)/10; Complex us1 = (*_mixS)(iloc, 0), us2 = (*_mixS)(iloc, 1); Complex us3 = (*_mixS)(iloc, 2); Complex ni1 = (*_mixN)(in1,0), nj1 = (*_mixN)(in2,0); Complex ni2 = (*_mixN)(in1,1), nj2 = (*_mixN)(in2,1); Complex ni3 = (*_mixN)(in1,3), nj3 = (*_mixN)(in2,3); Complex ni4 = (*_mixN)(in1,2), nj4 = (*_mixN)(in2,2); Complex ni5 = (*_mixN)(in1,4), nj5 = (*_mixN)(in2,4); Complex YL = - _lambda*rt*(us2*(ni4*nj5 + ni5*nj4) + us1*(ni3*nj5 + ni5*nj3) + us3*(ni3*nj4 + ni4*nj3)) + sqrt(2.)*_kappa*us3*ni5*nj5 - _couplast*0.5*(us2*(ni2*nj3 + ni3*nj2) - us1*(ni2*nj4 + ni4*nj2)) + _couplast*0.5*_sw*(us2*(ni1*nj3 + ni3*nj1) - us1*(ni1*nj4 + ni4*nj1) )/_cw; left(-conj(YL)); right(-YL); norm(1.0); } } // CP-odd neutral higgs else if(ihigg==36||ihigg==46) { int iloc = (ihigg-36)/10; // chargino if(abs(ig1)==1000024||abs(ig1)==1000037) { if( ig1 < 0 ) swap(ig1, ig2); int ic1 = abs(ig1)==1000024 ? 0 : 1; int ic2 = abs(ig2)==1000024 ? 0 : 1; Complex QL = Complex(0,-1.0)* (_lambda*rt*conj((*_mixP)(iloc,2)*(*_mixU)(ic1,1)*(*_mixV)(ic2,1)) -_couplast*rt*conj(((*_mixP)(iloc,0)*(*_mixU)(ic1,1)*(*_mixV)(ic2,0) + (*_mixP)(iloc,1)*(*_mixU)(ic1,0)*(*_mixV)(ic2,1)))); Complex QR = Complex(0,-1.0)* (_lambda*rt*(*_mixP)(iloc,2)*(*_mixU)(ic2,1)*(*_mixV)(ic1,1) -_couplast*rt*((*_mixP)(iloc,0)*(*_mixU)(ic2,1)*(*_mixV)(ic1,0) + (*_mixP)(iloc,1)*(*_mixU)(ic2,0)*(*_mixV)(ic1,1))); left(QL); right(-QR); norm(1.); } // neutralino else { int in1 = (ig1 < 1000024) ? (ig1 - 1000022) : (ig1 - 1000005)/10; int in2 = (ig2 < 1000024) ? (ig2 - 1000022) : (ig2 - 1000005)/10; Complex up1 = (*_mixP)(iloc, 0), up2 = (*_mixP)(iloc, 1); Complex up3 = (*_mixP)(iloc, 2); Complex ni1 = (*_mixN)(in1,0), nj1 = (*_mixN)(in2,0); Complex ni2 = (*_mixN)(in1,1), nj2 = (*_mixN)(in2,1); Complex ni3 = (*_mixN)(in1,2), nj3 = (*_mixN)(in2,2); Complex ni4 = (*_mixN)(in1,3), nj4 = (*_mixN)(in2,3); Complex ni5 = (*_mixN)(in1,4), nj5 = (*_mixN)(in2,4); Complex AL = _lambda*rt*(up2*(ni3*nj5 + ni5*nj3) + up1*(ni4*nj5 + ni5*nj4) + up3*(ni3*nj4 + ni4*nj3)) - sqrt(2.)*_kappa*up3*ni5*nj5 - _couplast*0.5*(up2*(ni2*nj4 + ni4*nj2) - up1*(ni2*nj3 + ni3*nj2)) + _couplast*0.5*_sw*(up2*(ni1*nj4 + ni4*nj1) - up1*(ni1*nj3 + ni3*nj1))/_cw; AL *= Complex(0.0, -1.0); left(conj(AL)); right(AL); norm(1.); } } // charged higgs else { if (abs(ig1) == 1000024 || abs(ig1) == 1000037) swap (ig1,ig2); int in = (abs(ig1) < 1000024) ? (ig1-1000022) : (ig1-1000005)/10; int ic = (abs(ig2) == 1000024) ? 0 : 1; Complex QpR = _lambda*_cosb*(*_mixU)(ic,1)*(*_mixN)(in,4) -_sinb*_couplast*(rt*(*_mixU)(ic,1)*(_sw*(*_mixN)(in,0)/_cw + (*_mixN)(in,1)) - (*_mixU)(ic,0)*(*_mixN)(in,2)); Complex QpL = _lambda*_sinb*(*_mixV)(ic,1)*(*_mixN)(in,4) + _couplast*_cosb*(rt*(*_mixV)(ic,1) *(_sw*(*_mixN)(in,0)/_cw + (*_mixN)(in,1)) + (*_mixV)(ic,0)*(*_mixN)(in,3)); QpL = conj(QpL); if(ihigg > 0) { left (QpL); right(QpR); norm(-1.); } else { left (conj(QpR)); right(conj(QpL)); norm(-1.); } } } diff --git a/Models/Susy/NMSSM/NMSSMHHHVertex.cc b/Models/Susy/NMSSM/NMSSMHHHVertex.cc --- a/Models/Susy/NMSSM/NMSSMHHHVertex.cc +++ b/Models/Susy/NMSSM/NMSSMHHHVertex.cc @@ -1,277 +1,278 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the NMSSMHHHVertex class. // #include "NMSSMHHHVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include "NMSSM.h" using namespace Herwig; using namespace ThePEG::Helicity; NMSSMHHHVertex::NMSSMHHHVertex() : _mw(0.*MeV), _mz(0.*MeV), _sw2(0.), _cw(0.), _lambda(0.), _kappa(0.) , _lambdaVEV(0.*MeV), _theAl(0.*MeV), _theAk(0.*MeV), _sb(0.), _cb(0.), _s2b(0.), _c2b(0.), _vu(0.*MeV), _vd(0.*MeV), _s(0.*MeV), _q2last(0.*MeV2), _glast(0.), _MQ3(0.*MeV), _MU2(0.*MeV), _includeRadiative(false) { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::SINGLET); } void NMSSMHHHVertex::doinit() { // PDG codes for the particles in vertex _vd //CP-even Higgs addToList(25, 35, 45); for( unsigned int i = 25; i <= 45; i += 10 ) { addToList(i, i, 25); addToList(i, i, 35); addToList(i, i, 45); //Charged Higgs addToList(i, 37, -37); //CP-odd Higgs addToList(i, 36, 36); addToList(i, 36, 46); addToList(i, 46, 36); addToList(i, 46, 46); } _theSM = dynamic_ptr_cast(generator()->standardModel()); tcNMSSMPtr nmssm = dynamic_ptr_cast(_theSM); if( !nmssm ) throw InitException() << "NMSSMHHHVertex::doinit - The model object is" << "not the NMSSM object." << Exception::runerror; //SM parameters _mw = getParticleData(24)->mass(); _mz = getParticleData(23)->mass(); _sw2 = sin2ThetaW(); _cw = sqrt(1. - _sw2); //NMSSM parameters _mixS = nmssm->CPevenHiggsMix(); _mixP = nmssm->CPoddHiggsMix(); if( !_mixS || !_mixP ) throw InitException() << "NMSSMHHHVertex::doinit - One of the mixing matrix " << "pointers is null, cannot continue. S: " << _mixS << " P: " << _mixP << Exception::runerror; _lambda = nmssm->lambda(); _kappa = nmssm->kappa(); _lambdaVEV = nmssm->lambdaVEV(); _theAl = nmssm->trilinearLambda(); _theAk = nmssm->trilinearKappa(); _MQ3 = nmssm->MQ3(); _MU2 = nmssm->MU2(); double beta = atan(nmssm->tanBeta()); _sb = sin(beta); _cb = cos(beta); _vd = sqrt(2)*_mw*_cb; _vu = sqrt(2)*_mw*_sb; _s = _lambdaVEV/_lambda; SSSVertex::doinit(); } void NMSSMHHHVertex::persistentOutput(PersistentOStream & os) const { os << ounit(_mw, GeV) << ounit(_mz,GeV) << _sw2 << _cw << _lambda << _includeRadiative << _kappa << ounit(_lambdaVEV,GeV) << ounit(_theAl, GeV) << ounit(_theAk,GeV) << _sb << _cb << _s2b << _c2b << ounit(_vu,GeV) << ounit(_vd,GeV) << ounit(_s,GeV) << _mixS << _mixP << ounit(_MQ3,GeV) << ounit(_MU2,GeV) << _theSM; } void NMSSMHHHVertex::persistentInput(PersistentIStream & is, int) { is >> iunit(_mw, GeV) >> iunit(_mz,GeV) >> _sw2 >> _cw >> _lambda >> _includeRadiative >> _kappa >> iunit(_lambdaVEV,GeV) >> iunit(_theAl, GeV) >> iunit(_theAk,GeV) >> _sb >> _cb >> _s2b >> _c2b >> iunit(_vu,GeV) >> iunit(_vd,GeV) >> iunit(_s,GeV)>> _mixS >> _mixP >> iunit(_MQ3,GeV) >> iunit(_MU2,GeV) >> _theSM; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigNMSSMHHHVertex("Herwig::NMSSMHHHVertex", "HwSusy.so HwNMSSM.so"); void NMSSMHHHVertex::Init() { static ClassDocumentation documentation ("This is the triple Higgs coupling in the NMSSM."); static Switch interfaceIncludeRadiativeCorrections ("IncludeRadiativeCorrections", "Include radiative corrections in the vertex", &NMSSMHHHVertex::_includeRadiative, false, false, false); static SwitchOption interfaceIncludeRadiativeCorrectionsYes (interfaceIncludeRadiativeCorrections, "Yes", "Include the radiative terms", true); static SwitchOption interfaceIncludeRadiativeCorrectionsNo (interfaceIncludeRadiativeCorrections, "No", "Don't include them", false); } //calulate couplings void NMSSMHHHVertex::setCoupling(Energy2 q2,tcPDPtr p1,tcPDPtr p2, tcPDPtr p3) { using Constants::pi; long higgs[3] = {p1->id(), p2->id(), p3->id()}; unsigned int ns(0), np(0), nc(0); for( int i = 0; i < 3; ++i ) { if( higgs[i] == 25 || higgs[i] == 35 || higgs[i] == 45 ) ++ns; else if( higgs[i] == 36 || higgs[i] == 46 ) ++np; else if( abs(higgs[i]) == 37 ) ++nc; } //check three Higgs in vertex assert( ns + np + nc == 3 ); if( q2 != _q2last ) { _q2last = q2; _glast = weakCoupling(q2); _mb = _theSM->mass(q2,getParticleData(5)); _mt = _theSM->mass(q2,getParticleData(6)); } //define VEV's double rt = sqrt(0.5); Energy _mtpole = getParticleData(6)->mass(); Energy2 Qstsb = _MQ3*_MU2; double radlog(0.); if(_includeRadiative) { radlog = Qstsb/sqr(_mtpole); assert(radlog!=0.); radlog = log(radlog); } complex coupling; //CP even Higgs if( ns == 3 ) { unsigned int a = (higgs[0] - 25)/10; unsigned int b = (higgs[1] - 25)/10; unsigned int c = (higgs[2] - 25)/10; coupling = sqr(_lambda)*rt*(_vu*(usMix(a,b,c,1,0,0) + usMix(a,b,c,1,2,2))/_glast + _vd*(usMix(a,b,c,0,1,1) + usMix(a,b,c,0,2,2))/_glast + _s *(usMix(a,b,c,2,1,1) + usMix(a,b,c,2,0,0))) - _lambda*_kappa*rt*(_vu*usMix(a,b,c,0,2,2)/_glast + _vd*usMix(a,b,c,2,1,2)/_glast + 2.*_s*usMix(a,b,c,1,0,2)) + sqr(_kappa)/rt*_s*usMix(a,b,c,2,2,2) - _lambda*_theAl*rt*usMix(a,b,c,1,0,2) + _kappa*_theAk*rt/3.*usMix(a,b,c,2,2,2) + sqr(_glast)*0.25*rt/sqr(_cw)*(_vu*(usMix(a,b,c,1,1,1) - usMix(a,b,c,1,0,0))/_glast - _vd*(usMix(a,b,c,0,1,1) - usMix(a,b,c,0,0,0))/_glast); // additional radiative terms if(_includeRadiative) { complex radtop = usMix(a,b,c,1,1,1)*3.0*sqrt(2.0)*radlog *sqr(_mt)*sqr(_mt)*sqr(_glast)*_glast/ (16.0*sqr(pi)*_vu*_vu*_vu); complex radbot= usMix(a,b,c,0,0,0)*3.0*sqrt(2.0)*radlog *sqr(_mb)*sqr(_mb)*sqr(_glast)*_glast /(16.0*sqr(pi)*_vd*_vd*_vd); coupling += radbot + radtop; } } //CP even, CP odd Vertex else if(ns == 1 && np == 2) { unsigned int a(0), b(0), c(0); if( higgs[0] == 25 || higgs[0] == 35 || higgs[0] == 45 ) { a = (higgs[0] - 25)/10; b = (higgs[1] - 36)/10; c = (higgs[2] - 36)/10; } else if(higgs[1] == 25 || higgs[1] == 35 || higgs[1] == 45 ) { a = (higgs[1] - 25)/10; b = (higgs[0] - 36)/10; c = (higgs[2] - 36)/10; } else { a = (higgs[2] - 25)/10; b = (higgs[0] - 36)/10; c = (higgs[1] - 36)/10; } coupling = sqr(_lambda)*rt*(_vu*(upMix(a,b,c,1,0,0) + upMix(a,b,c,1,2,2))/_glast + _vd*(upMix(a,b,c,0,1,1) + upMix(a,b,c,0,2,2))/_glast + _s *(upMix(a,b,c,2,1,1) + upMix(a,b,c,2,0,0))) + _lambda*_kappa*rt*(_vu*(upMix(a,b,c,0,2,2) - 2.*upMix(a,b,c,2,0,2))/_glast + _vd*(upMix(a,b,c,1,2,2) - 2.*upMix(a,b,c,2,1,2))/_glast + 2.*_s*(upMix(a,b,c,2,1,0) - upMix(a,b,c,1,0,2) - upMix(a,b,c,0,1,2))) + sqr(_kappa)/rt*_s*upMix(a,b,c,2,2,2) +_lambda*_theAl*rt*(upMix(a,b,c,1,0,2) + upMix(a,b,c,0,1,2) + upMix(a,b,c,2,1,0)) - _kappa*_theAk*rt*upMix(a,b,c,2,2,2) + sqr(_glast)*0.25*rt/sqr(_cw)*(_vu*(upMix(a,b,c,1,1,1) - upMix(a,b,c,1,0,0))/_glast - _vd*(upMix(a,b,c,0,1,1) - upMix(a,b,c,0,0,0))/_glast); if(_includeRadiative) { complex radtop = upMix(a,b,c,1,1,1)*3.0*sqrt(2.0)*radlog* sqr(_mt)*sqr(_mt)*sqr(_glast)*_glast/ (16.0*sqr(pi)*_vu*_vu*_vu); complex radbot= upMix(a,b,c,0,0,0)*3.0*sqrt(2.0)*radlog* sqr(_mb)*sqr(_mb)*sqr(_glast)*_glast /(16.0*sqr(pi)*_vd*_vd*_vd); coupling += radbot + radtop; } } //Charged Higgs else { unsigned int a(0); if( higgs[0] == 25 || higgs[0] == 35 || higgs[0] == 45 ) a = (higgs[0] - 25)/10; else if(higgs[1] == 25 || higgs[1] == 35 || higgs[1] == 45 ) a = (higgs[1] - 25)/10; else a = (higgs[2] - 25)/10; coupling = sqr(_lambda)*rt*2.*(_s*((*_mixS)(a,2)*sqr(_cb) + (*_mixS)(a,2)*sqr(_sb)) - (_vu*(*_mixS)(a,0)/_glast + _vd*(*_mixS)(a,1)/_glast)*_sb*_cb) +_lambda*_sb*_cb*2.*(*_mixS)(a,2)*(_kappa*_s/rt + rt*_theAl) + sqr(_glast)*0.5*rt*_sw2/sqr(_cw)*((_vu*(*_mixS)(a,1)/_glast - _vd*(*_mixS)(a,0)/_glast)*sqr(_cb) + (_vd*(*_mixS)(a,0)/_glast - _vu*(*_mixS)(a,1)/_glast)*sqr(_sb)) + sqr(_glast)*0.5*rt*(_vu*((*_mixS)(a,1)*sqr(_cb) + (*_mixS)(a,1)*sqr(_sb) + 2.*(*_mixS)(a,0)*_cb*_sb)/_glast + _vd*((*_mixS)(a,0)*sqr(_cb) + (*_mixS)(a,0)*sqr(_sb) + 2.*(*_mixS)(a,1)*_sb*_cb)/_glast); if(_includeRadiative) { complex radtop =(*_mixS)(a,1)*sqr(_sb)*6.0*sqrt(2.0)*radlog* sqr(_mt)*sqr(_mt)*sqr(_glast)*_glast/ (16.0*sqr(pi)*_vu*_vu*_vu); complex radbot=(*_mixS)(a,0)*sqr(_cb)*6.0*sqrt(2.0)*radlog* sqr(_mb)*sqr(_mb)*sqr(_glast)*_glast /(16.0*sqr(pi)*_vd*_vd*_vd); complex temp2 = _vu*((*_mixS)(a,1)*sqr(_cb) + (*_mixS)(a,0)*_sb*_cb)/_glast+ _vd*((*_mixS)(a,1)*_sb*_cb + (*_mixS)(a,0)*sqr(_sb))/_glast; complex radtopbot= temp2*6.0*sqrt(2.0)*radlog* sqr(_mt)*sqr(_mb)*sqr(_glast)*sqr(_glast) /(16.0*sqr(pi)*sqr(_vu)*sqr(_vd)); coupling += radbot + radtop + radtopbot; } } norm(-coupling * UnitRemoval::InvE); } diff --git a/Models/Susy/NMSSM/NMSSMHSFSFVertex.cc b/Models/Susy/NMSSM/NMSSMHSFSFVertex.cc --- a/Models/Susy/NMSSM/NMSSMHSFSFVertex.cc +++ b/Models/Susy/NMSSM/NMSSMHSFSFVertex.cc @@ -1,388 +1,389 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the NMSSMHSFSFVertex class. // #include "NMSSMHSFSFVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "NMSSM.h" using namespace Herwig; using namespace ThePEG::Helicity; NMSSMHSFSFVertex::NMSSMHSFSFVertex() : _triTp(0.*MeV), _triBt(0.*MeV), _triTa(0.*MeV), _lambda(0.), _lambdaVEV(0.*MeV), _v1(0.*MeV), _v2(0.*MeV), _sw(0.), _cw(0.), _mw(0.*MeV), _mz(0.*MeV), _sb(0.), _cb(0.), _tb(0.), _q2last(0.*MeV2), _couplast(0.), _masslast(make_pair(0.*MeV,0.*MeV)), _idlast(make_pair(0,0)) { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::DELTA); } void NMSSMHSFSFVertex::persistentOutput(PersistentOStream & os) const { os << _theSM << _mixS << _mixP << _mixTp << _mixBt << _mixTa << ounit(_triTp,GeV) << ounit(_triBt,GeV) << ounit(_triTa,GeV) << _lambda << ounit(_lambdaVEV,GeV) << ounit(_v1,GeV) << ounit(_v2,GeV) << _sw << _cw << ounit(_mw,GeV) << ounit(_mz,GeV) << _sb << _cb << _tb; } void NMSSMHSFSFVertex::persistentInput(PersistentIStream & is, int) { is >> _theSM >> _mixS >> _mixP >> _mixTp >> _mixBt >> _mixTa >> iunit(_triTp,GeV) >> iunit(_triBt,GeV) >> iunit(_triTa,GeV) >> _lambda >> iunit(_lambdaVEV,GeV) >> iunit(_v1,GeV) >> iunit(_v2,GeV) >> _sw >> _cw >> iunit(_mw,GeV) >> iunit(_mz,GeV) >> _sb >> _cb >> _tb; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigNMSSMHSFSFVertex("Herwig::NMSSMHSFSFVertex", "HwSusy.so HwNMSSM.so"); void NMSSMHSFSFVertex::Init() { static ClassDocumentation documentation ("The coupling of Higgs bosons to sfermions in the MSSM."); } void NMSSMHSFSFVertex::doinit() { //CP even int even[3] = {25, 35, 45}; for(size_t h = 0; h < 3; ++h ) { //squarks for(long q = 1; q < 7; ++q) { //11 addToList(even[h], -1000000 - q, 1000000 + q); //22 addToList(even[h], -2000000 - q, 2000000 + q); //12 addToList(even[h], -1000000 - q, 2000000 + q); //21 addToList(even[h], -2000000 - q, 1000000 + q); } //sleptons for(long l = 11; l < 17; ++l) { //11 addToList(even[h], -1000000 - l, 1000000 + l); //no right handed sneutrinos if( l % 2 != 0 ) { //22 addToList(even[h], -2000000 - l, 2000000 + l); //12 addToList(even[h], -1000000 - l, 2000000 + l); //21 addToList(even[h], -2000000 - l, 1000000 + l); } } } //CP odd int odd[2] = {36, 46}; for(size_t h = 0; h < 2; ++h ) { //squarks for(long q = 1; q < 7; ++q) { //12 addToList(odd[h], -1000000 - q, 2000000 + q); //21 addToList(odd[h], -2000000 - q, 1000000 + q); } //sleptons for(long l = 11; l < 16; l += 2) { //12 addToList(odd[h], -1000000 - l, 2000000 + l); //21 addToList(odd[h], -2000000 - l, 1000000 + l); } } //charged higgs //squarks for(long q = 1; q < 4; ++q ) { //H- //LL addToList(-37, -2*q - 999999, 2*q + 1000000); //RR addToList(-37, -2*q - 1999999, 2*q + 2000000); //LR addToList(-37, -2*q - 999999, 2*q + 2000000); //RL addToList(-37, -2*q - 1999999, 2*q + 1000000); //H+ //LL addToList(37, -2*q - 1000000, 2*q + 999999); //RR addToList(37, -2*q - 2000000, 2*q + 1999999); //LR addToList(37, -2*q - 1000000, 2*q + 1999999); //RL addToList(37, -2*q - 2000000, 2*q + 999999); } //sleptons //easier as there are no right handed sneutrinos for(long l = 11; l <= 15; l +=2 ) { //H- //LL addToList(-37, -l - 1000000, l + 1000001); //RL addToList(-37, -l - 2000000, l + 1000001); //H+ //LL addToList(+37, -l - 1000001, l + 1000000); //RL addToList(+37, -l - 1000001, l + 2000000); } _theSM = dynamic_ptr_cast(generator()->standardModel()); tcNMSSMPtr nmssm = dynamic_ptr_cast(_theSM); if( !nmssm ) throw InitException() << "NMSSMHSFSFVertex::doinit() - The model pointer " << "in this vertex is not an NMSSM one as it " << "should be." << Exception::runerror; _mixS = nmssm->CPevenHiggsMix(); _mixP = nmssm->CPoddHiggsMix(); _mixTp = nmssm->stopMix(); _mixBt = nmssm->sbottomMix(); _mixTa = nmssm->stauMix(); if( !_mixS || !_mixP || !_mixTp || !_mixBt || !_mixTa ) throw InitException() << "NMSSMHSFSFVertex::doinit() - One of the mixing matrix pointers is " << "null, cannot continue. CP-even: " << _mixS << " CP-odd: " << _mixP << " ~t: " << _mixTp << " ~b: " << _mixBt << " ~tau: " << _mixTa << Exception::runerror; _triTp = nmssm->topTrilinear(); _triBt = nmssm->bottomTrilinear(); _triTa = nmssm->tauTrilinear(); _lambda = nmssm->lambda(); _lambdaVEV = nmssm->lambdaVEV(); _sw = sin2ThetaW(); _cw = sqrt( 1. - _sw); _sw = sqrt(_sw); _mw = getParticleData(24)->mass(); _mz = getParticleData(23)->mass(); _tb = nmssm->tanBeta(); double beta = atan(_tb); _sb = sin(beta); _cb = cos(beta); _v1 = sqrt(2.)*_mw*_cb; _v2 = sqrt(2.)*_mw*_sb; SSSVertex::doinit(); } void NMSSMHSFSFVertex::setCoupling(Energy2 q2,tcPDPtr part1, tcPDPtr part2, tcPDPtr part3) { // extract particle ids long higgs(part1->id()), isf1(part2->id()), isf2(part3->id()); // higgs first if(abs(isf1)<100) swap(higgs,isf1); if(abs(isf2)<100) swap(higgs,isf2); // squark second if(isf1<0) swap(isf1,isf2); // check higgs assert( higgs == 25 || higgs == 35 || higgs == 45 || higgs == 36 || higgs == 46 || abs(higgs) == 37 ); // abs of antisquark and check isf2 *=-1; assert(isf1>0&&isf2>0); // running coupling if( q2 != _q2last ) { _q2last = q2; _couplast = weakCoupling(q2); } //charged higgs if( abs(higgs) == 37 ) { norm(_couplast*chargedHiggs(q2, isf1, isf2)); return; } // neutral higgs // L/R states of the sfermions unsigned int alpha = ( isf1 > 2000000 ) ? 1 : 0; unsigned int beta = ( isf2 > 2000000 ) ? 1 : 0; // id nad mass of corresponding SM fermion long smid = ( alpha == 0 ) ? isf1 - 1000000 : isf1 - 2000000; if( q2 != _q2last || smid != _idlast.first) { _idlast.first = smid; _masslast.first = _theSM->mass(q2, getParticleData(smid)); } double f1 = _masslast.first/_mw; complex af(ZERO); Complex m1a(0.), m1b(0.), m2a(0.), m2b(0.); // mixing for down type squarks and charged sleptons if( smid % 2 != 0 ) { f1 /= _cb; // sbottom if( smid == 5 ) { m1a = (*_mixBt)(alpha, 0); m1b = (*_mixBt)(alpha, 1); m2a = (*_mixBt)(beta , 0) ; m2b = (*_mixBt)(beta , 1); af = _triBt; } // stau else if( smid == 15 ) { m1a = (*_mixTa)(alpha, 0); m1b = (*_mixTa)(alpha, 1); m2a = (*_mixTa)(beta , 0) ; m2b = (*_mixTa)(beta , 1); af = _triTa; } // 1st 2 generations else { m1a = (alpha == 0) ? 1. : 0.; m1b = (alpha == 0) ? 0. : 1.; m2a = (beta == 0) ? 1. : 0.; m2b = (beta == 0) ? 0. : 1.; af = ZERO; } } // mixing for up type squarks and sneutrions else { f1 /= _sb; // stop if( smid == 6 ) { m1a = (*_mixTp)(alpha, 0); m1b = (*_mixTp)(alpha, 1); m2a = (*_mixTp)(beta , 0); m2b = (*_mixTp)(beta , 1); af = _triTp; } // everything else else { m1a = (alpha == 0) ? 1. : 0.; m1b = (alpha == 0) ? 0. : 1.; m2a = (beta == 0) ? 1. : 0.; m2b = (beta == 0) ? 0. : 1.; af = 0.*MeV; } } // scalar higgs bosons complex fact(ZERO); if( higgs == 25 || higgs == 35 || higgs == 45 ) { int iloc = (higgs - 25)/10; complex f2 = 0.5*_mz*( - _cb*(*_mixS)(iloc,0) + _sb*(*_mixS)(iloc,1))/_cw; // down type squarks and charged sleptons if( smid % 2 != 0 ) { double ef = (smid < 7) ? -1./3. : -1.; fact = - f2*( (1. + 2.*ef*sqr(_sw))*m1a*m2a - 2.*ef*sqr(_sw)*m1b*m2b) - f1*_masslast.first*(*_mixS)(iloc,0)*(m1a*m2a + m1b*m2b) - 0.5*f1*(( - _lambdaVEV*(*_mixS)(iloc,1) - _lambda*_v2*(*_mixS)(iloc,2)/_couplast + af*(*_mixS)(iloc,0)) * (m2a*m1b + m1a*m2b) ); } // up type squarks and sneutrinos else { double ef = (smid < 7) ? 2./3. : 0.; fact = +f2*( (1. - 2.*ef*sqr(_sw))*m1a*m2a + 2.*ef*sqr(_sw)*m1b*m2b ) - f1*_masslast.first*(*_mixS)(iloc,1)*(m1a*m2a + m1b*m2b) - 0.5*f1*(( - _lambdaVEV*(*_mixS)(iloc,0) - _lambda*_v1*(*_mixS)(iloc,2)/_couplast + af*(*_mixS)(iloc,1) ) * (m2a*m1b + m1a*m2b)); } } // pseudo scalar else if( higgs == 36 || higgs == 46 ) { int iloc = (higgs - 36)/10; // down type squarks and charged sleptons if( smid % 2 != 0 ) { fact = -0.5*f1*Complex(0.0,1.0)* ( _lambdaVEV*(*_mixP)(iloc,1) + _lambda*_v2*(*_mixP)(iloc,2)/_couplast + af*(*_mixP)(iloc,0) ); } // up-type squarks and sneutrinos else { fact =-0.5*f1*Complex(0.0,1.0)* ( _lambdaVEV *(*_mixP)(iloc,0) + _lambda*_v1*(*_mixP)(iloc,2)/_couplast + af*(*_mixP)(iloc,1)); } if(alphamass(q2, getParticleData(utype) ); _masslast.second = _theSM->mass(q2, getParticleData(dtype) ); } Energy2 facta = 2.*sqr(_mw)*_sb*_cb; complex coupling(ZERO); // sleptons if( dtype == 11 || dtype == 13 || dtype == 15) { Complex l1b = 0., l2b = 0.; complex tri(ZERO); // 1st 2 generations if (dtype == 11 || dtype == 13) { l1b = (beta == 0) ? 1.0 : 0.0; l2b = (beta == 0) ? 0.0 : 1.0; } // stau else { l1b = (*_mixTa)(beta, 0) ; l2b = (*_mixTa)(beta, 1); tri = _triTa; } coupling = ( l1b*(sqr(_masslast.second)*_tb - facta) + l2b*_masslast.second*(tri*_tb + _lambdaVEV) ); } // squarks else { Complex q1a(0.0), q1b(0.0), q2a(0.0), q2b(0.0); complex triD(ZERO), triU(ZERO); // up-type bit // stop if(utype == 6){ q1a = (*_mixTp)(alpha, 0) ; q2a = (*_mixTp)(alpha, 1); triU = _triTp; } // light else{ q1a = (alpha == 0) ? 1.0 : 0.0; q2a = (alpha == 0) ? 0.0 : 1.0; } // down-type bit // sbottom if(dtype == 5){ q1b = (*_mixBt)(beta, 0) ; q2b = (*_mixBt)(beta, 1); triD = _triBt; } // light else{ q1b = (beta == 0) ? 1.0 : 0.0; q2b = (beta == 0) ? 0.0 : 1.0; } Energy mfu = _masslast.first; Energy mfd = _masslast.second; coupling = ( q1a*q1b*((sqr(mfd)*_tb + sqr(mfu)/_tb) - facta) + q2a*q2b*mfu*mfd*(_tb + (1./_tb)) + q1a*q2b*mfd*(triD*_tb + _lambdaVEV) + q2a*q1b*mfu*(triU/_tb + _lambdaVEV)); } return coupling * UnitRemoval::InvE/_mw/sqrt(2.); } diff --git a/Models/Susy/NMSSM/NMSSMPPHVertex.cc b/Models/Susy/NMSSM/NMSSMPPHVertex.cc --- a/Models/Susy/NMSSM/NMSSMPPHVertex.cc +++ b/Models/Susy/NMSSM/NMSSMPPHVertex.cc @@ -1,283 +1,284 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the NMSSMPPHVertex class. // #include "NMSSMPPHVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include "Herwig/Models/Susy/NMSSM/NMSSM.h" #include "Herwig/Looptools/clooptools.h" using namespace Herwig; NMSSMPPHVertex::NMSSMPPHVertex() : _sw(0.), _cw(0.), _mw(0.*MeV), _mz(0.*MeV),_lambdaVEV(0.*MeV), _lambda(0.), _triTp(0.*MeV), _triBt(0.*MeV), _sb(0.), _cb(0.), _kappa(0.),_vu(ZERO),_vd(ZERO),_s(ZERO),_theAl(ZERO), _masslast(make_pair(0.*MeV,0.*MeV)),_q2last(0.*MeV2), _couplast(0.), _coup(0.), _hlast(0), _recalc(true) { orderInGem(3); orderInGs(0); + colourStructure(ColourStructure::SINGLET); } void NMSSMPPHVertex::doinit() { addToList(22,22,25); addToList(22,22,35); addToList(22,22,36); addToList(22,22,45); addToList(22,22,46); _theSM = dynamic_ptr_cast(generator()->standardModel()); if( !_theSM ) { throw InitException() << "NMSSMPPHVertex::doinit - The SM pointer is null!" << Exception::abortnow; } // SM parameters _sw = sqrt(sin2ThetaW()); _cw = sqrt(1. - sin2ThetaW()); _mw = getParticleData(24)->mass(); _mz = getParticleData(23)->mass(); _top = getParticleData(6); _bt = getParticleData(5); _tau = getParticleData(15); //NMSSM parameters tcNMSSMPtr nmssm = dynamic_ptr_cast(_theSM); _mixS = nmssm->CPevenHiggsMix(); _mixP = nmssm->CPoddHiggsMix(); _mixQt = nmssm->stopMix(); _mixQb = nmssm->sbottomMix(); _mixLt = nmssm->stauMix(); double beta = atan(nmssm->tanBeta()); _sb = sin(beta); _cb = cos(beta); _lambda = nmssm->lambda(); _lambdaVEV = nmssm->lambdaVEV(); _triTp = nmssm->topTrilinear(); _triBt = nmssm->bottomTrilinear(); _triTa = nmssm->tauTrilinear(); _vd = sqrt(2)*_mw*_cb; _vu = sqrt(2)*_mw*_sb; _s = _lambdaVEV/_lambda; _theAl = nmssm->trilinearLambda(); _kappa = nmssm->kappa(); _mixU = nmssm->charginoUMix(); _mixV = nmssm->charginoVMix(); // resize vectors here and use setNParticles method // to the set the actual number in the loop. // Also only the top mass hass to be calculated at runtime masses.resize(13, Energy()); masses[ 0] = getParticleData( 6)->mass(); masses[ 1] = getParticleData( 5)->mass(); masses[ 2] = getParticleData(15)->mass(); masses[ 3] = getParticleData(ParticleID::SUSY_chi_1plus)->mass(); masses[ 4] = getParticleData(ParticleID::SUSY_chi_2plus)->mass(); masses[ 5] = _mw; masses[ 6] = getParticleData(ParticleID::Hplus)->mass(); masses[ 7] = getParticleData(1000005)->mass(); masses[ 8] = getParticleData(2000005)->mass(); masses[ 9] = getParticleData(1000006)->mass(); masses[10] = getParticleData(2000006)->mass(); masses[11] = getParticleData(1000015)->mass(); masses[12] = getParticleData(2000015)->mass(); type.resize(13, PDT::Spin0); type[0] = PDT::Spin1Half; type[1] = PDT::Spin1Half; type[2] = PDT::Spin1Half; type[3] = PDT::Spin1Half; type[4] = PDT::Spin1Half; type[5] = PDT::Spin1; couplings.resize(13); VVSLoopVertex::doinit(); if(loopToolsInitialized()) Looptools::ltexi(); } void NMSSMPPHVertex::persistentOutput(PersistentOStream & os) const { os << _theSM << _sw << _cw << ounit(_mw, GeV) << ounit(_mz, GeV) << ounit(_lambdaVEV,GeV) << _lambda << ounit(_triTp,GeV) << ounit(_triBt,GeV) << ounit(_triTa,GeV) << _top << _bt << _tau << _mixS << _mixP << _mixU << _mixV << _mixQt << _mixQb << _mixLt << _sb << _cb << _kappa << ounit(_vu,GeV) << ounit(_vd,GeV) << ounit(_s,GeV) << ounit(_theAl,GeV); } void NMSSMPPHVertex::persistentInput(PersistentIStream & is, int) { is >> _theSM >> _sw >> _cw >> iunit(_mw, GeV) >> iunit(_mz, GeV) >> iunit(_lambdaVEV,GeV) >> _lambda >> iunit(_triTp,GeV) >> iunit(_triBt,GeV) >> iunit(_triTa,GeV) >> _top >> _bt >> _tau >> _mixS >> _mixP >> _mixU >> _mixV >> _mixQt >> _mixQb >> _mixLt >> _sb >> _cb >> _kappa >> iunit(_vu,GeV) >> iunit(_vd,GeV) >> iunit(_s,GeV) >> iunit(_theAl,GeV); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigNMSSMPPHVertex("Herwig::NMSSMPPHVertex", "HwSusy.so HwNMSSM.so"); void NMSSMPPHVertex::Init() { static ClassDocumentation documentation ("The effective coupling of a higgs to a pair of gluons in the " "NMSSM."); } void NMSSMPPHVertex::setCoupling(Energy2 q2, tcPDPtr p1, tcPDPtr p2, tcPDPtr p3) { long hid(p3->id()); double rt = sqrt(0.5); if( q2 != _q2last ) { Looptools::clearcache(); _couplast = sqr(electroMagneticCoupling(q2)); _coup = weakCoupling(q2); _q2last = q2; _recalc = true; } norm(_couplast*_coup); // scalar higgs bosons if( hid != _hlast ) { _hlast = hid; _recalc = true; // top and bottom quark masses Energy mt = _theSM->mass(q2, _top); Energy mb = _theSM->mass(q2, _bt); Energy mtau = _theSM->mass(q2, _tau); // scalar if( hid % 5 == 0 ) { // location of the higgs int iloc = (hid - 25)/10; // 6 particles in the loop setNParticles(13); Complex c(0.); // couplings for the top quark loop c = -1.5*sqr(_theSM->eu())* mt*(*_mixS)(iloc, 1)/_sb/_mw; couplings[0] = make_pair(c,c); masses[0] = mt; // couplings for the bottom quark loop c = -1.5*sqr(_theSM->ed())* mb*(*_mixS)(iloc, 0)/_cb/_mw; couplings[1] = make_pair(c,c); masses[1] = mb; // couplings for the tau lepton loop c = -0.5*sqr(_theSM->ee())*mtau*(*_mixS)(iloc, 0)/_cb/_mw; couplings[2] = make_pair(c,c); masses[2] = mtau; // charginos for(unsigned int ic=0;ic<2;++ic) { c = -_lambda/_coup*rt*(*_mixS)(iloc,2)*(*_mixU)(ic,1)*(*_mixV)(ic,1) -rt*((*_mixS)(iloc,0)*(*_mixU)(ic,1)*(*_mixV)(ic,0) + (*_mixS)(iloc,1)*(*_mixU)(ic,0)*(*_mixV)(ic,1)); couplings[3+ic] = make_pair(c,c); } // W boson c = UnitRemoval::InvE*_mw* (_cb*(*_mixS)(iloc,0)+_sb*(*_mixS)(iloc,1)); couplings[5] = make_pair(c,c); // charged Higgs complex cpl; cpl = sqr(_lambda)*rt*2.*(_s*((*_mixS)(iloc,2)*sqr(_cb) + (*_mixS)(iloc,2)*sqr(_sb)) - (_vu*(*_mixS)(iloc,0)/_coup + _vd*(*_mixS)(iloc,1)/_coup)*_sb*_cb) +_lambda*_sb*_cb*2*(*_mixS)(iloc,2)*(_kappa*_s/rt + rt*_theAl) + sqr(_coup)*0.5*rt*sqr(_sw)/sqr(_cw)*((_vu*(*_mixS)(iloc,1)/_coup - _vd*(*_mixS)(iloc,0)/_coup)*sqr(_cb) + (_vd*(*_mixS)(iloc,0)/_coup - _vu*(*_mixS)(iloc,1)/_coup)*sqr(_sb)) + sqr(_coup)*0.5*rt*(_vu*((*_mixS)(iloc,1)*sqr(_cb) + (*_mixS)(iloc,1)*sqr(_sb) + 2.*(*_mixS)(iloc,0)*_cb*_sb)/_coup + _vd*((*_mixS)(iloc,0)*sqr(_cb) + (*_mixS)(iloc,0)*sqr(_sb) + 2.*(*_mixS)(iloc,1)*_sb*_cb)/_coup); cpl /= -_coup; couplings[6] = make_pair(cpl*UnitRemoval::InvE,cpl*UnitRemoval::InvE); // sbottoms double f1 = mb/_mw/_cb; complex f2 = 0.5*_mz/_cw* ( - _cb*(*_mixS)(iloc,0) + _sb*(*_mixS)(iloc,1)); for(unsigned int ix=0;ix<2;++ix) { cpl = -f2*( (1. - 2.*sqr(_sw)/3.)*(*_mixQb)(ix, 0)*(*_mixQb)(ix, 0) + 2.*sqr(_sw)*(*_mixQb)(ix, 1)*(*_mixQb)(ix, 1)/3.) - f1*mb*(*_mixS)(iloc,0) *((*_mixQb)(ix, 0)*(*_mixQb)(ix, 0) + (*_mixQb)(ix, 1)*(*_mixQb)(ix, 1)) - 0.5*f1*(-_lambdaVEV*(*_mixS)(iloc,1) - _lambda*_vu*(*_mixS)(iloc,2)/_coup + _triBt*(*_mixS)(iloc,0))*((*_mixQb)(ix, 1)*(*_mixQb)(ix, 0) + (*_mixQb)(ix, 0)*(*_mixQb)(ix, 1)); cpl *= 3.*sqr(_theSM->ed()); couplings[7+ix] = make_pair(cpl*UnitRemoval::InvE,cpl*UnitRemoval::InvE); } // stop f1 = mt/_mw/_sb; for(unsigned int ix=0;ix<2;++ix) { cpl =+f2*( (1. - 4.*sqr(_sw)/3.)*(*_mixQt)(ix, 0)*(*_mixQt)(ix, 0) + 4.*sqr(_sw)*(*_mixQt)(ix, 1)*(*_mixQt)(ix, 1)/3.) - f1*mt*(*_mixS)(iloc,1) *((*_mixQt)(ix, 0)*(*_mixQt)(ix, 0) + (*_mixQt)(ix, 1)*(*_mixQt)(ix, 1)) - 0.5*f1*(-_lambdaVEV*(*_mixS)(iloc,0) - _lambda*_vd*(*_mixS)(iloc,2)/_coup + _triTp*(*_mixS)(iloc,1))*((*_mixQt)(ix, 1)*(*_mixQt)(ix, 0) + (*_mixQt)(ix, 0)*(*_mixQt)(ix, 1)); cpl *= 3.*sqr(_theSM->eu()); couplings[9+ix] = make_pair(cpl*UnitRemoval::InvE,cpl*UnitRemoval::InvE); } // sbottoms f1 = mtau/_mw/_cb; for(unsigned int ix=0;ix<2;++ix) { cpl = -f2*( (1. - 2.*sqr(_sw))*(*_mixLt)(ix, 0)*(*_mixLt)(ix, 0) + 2.*sqr(_sw)*(*_mixLt)(ix, 1)*(*_mixLt)(ix, 1)) - f1*mtau*(*_mixS)(iloc,0) *((*_mixLt)(ix, 0)*(*_mixLt)(ix, 0) + (*_mixLt)(ix, 1)*(*_mixLt)(ix, 1)) - 0.5*f1*(-_lambdaVEV*(*_mixS)(iloc,1) - _lambda*_vu*(*_mixS)(iloc,2)/_coup + _triTa*(*_mixS)(iloc,0))*((*_mixLt)(ix, 1)*(*_mixLt)(ix, 0) + (*_mixLt)(ix, 0)*(*_mixLt)(ix, 1)); cpl *= sqr(_theSM->ee()); couplings[11+ix] = make_pair(cpl*UnitRemoval::InvE,cpl*UnitRemoval::InvE); } } // pseudoscalar higgs bosons else { // location of the higgs int iloc = (hid - 36)/10; // 2 particles in the loop setNParticles(5); Complex c(0.); // top quark couplings c = Complex(0., 1.)*1.5*sqr(_theSM->eu())* mt*(*_mixP)(iloc, 1)/_sb/_mw; couplings[0] = make_pair(c,-c); masses[0] = mt; // bottom quark couplings c = Complex(0., 1.)*1.5*sqr(_theSM->ed())* mb*(*_mixP)(iloc, 0)/_cb/_mw; couplings[1] = make_pair(c,-c); masses[1] = mb; // tau lepton couplings c = Complex(0., 1.)*0.5*sqr(_theSM->ee())*mtau*(*_mixP)(iloc, 0)/_cb/_mw; couplings[2] = make_pair(c,-c); masses[2] = mtau; // charginos for(unsigned int ic=0;ic<2;++ic) { c = Complex(0,-1.0)* (_lambda/_coup*rt*(*_mixP)(iloc,2)*(*_mixU)(ic,1)*(*_mixV)(ic,1) -rt*((*_mixP)(iloc,0)*(*_mixU)(ic,1)*(*_mixV)(ic,0) + (*_mixP)(iloc,1)*(*_mixU)(ic,0)*(*_mixV)(ic,1))); couplings[3+ic] = make_pair(-c,c); } } } if( _recalc ) { VVSLoopVertex::setCoupling(q2, p1, p2, p3); _recalc = false; } } diff --git a/Models/Susy/NMSSM/NMSSMWHHVertex.cc b/Models/Susy/NMSSM/NMSSMWHHVertex.cc --- a/Models/Susy/NMSSM/NMSSMWHHVertex.cc +++ b/Models/Susy/NMSSM/NMSSMWHHVertex.cc @@ -1,157 +1,158 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the NMSSMWHHVertex class. // #include "NMSSMWHHVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "NMSSM.h" using namespace Herwig; using namespace ThePEG::Helicity; NMSSMWHHVertex::NMSSMWHHVertex() : _sinb(0.), _cosb(0.), _sw(0.), _cw(0.), _q2last(0.*MeV2), _couplast(0.) { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::SINGLET); } void NMSSMWHHVertex::doinit() { // codes for the neutral higgs //CP even int ieven[3]={25,35,45}; //CP odd int iodd [2]={36,46}; // Z CP even CP odd for(unsigned int ix=0;ix<3;++ix) for(unsigned int iy=0;iy<2;++iy) addToList( 23, ieven[ix], iodd[iy] ); // W H+ CP even for(unsigned int ix=0;ix<3;++ix) addToList( -24, 37, ieven[ix] ); // W+ H- CP even for(unsigned int ix=0;ix<3;++ix) addToList( 24, -37, ieven[ix] ); // W H+ CP odd for(unsigned int ix=0;ix<2;++ix) addToList( -24, 37, iodd[ix] ); //W+ H- CP odd for(unsigned int ix=0;ix<2;++ix) addToList( 24, -37, iodd[ix] ); // Charged higgs Z/gamma addToList( 22, 37, -37 ); addToList( 23, 37, -37 ); // cast to NMSSM model tcNMSSMPtr model=dynamic_ptr_cast(generator()->standardModel()); if(!model) throw InitException() << "Must have the NMSSM Model in NMSSMFFHVertex::doinit()" << Exception::runerror; // sin theta_W double sw2 = sin2ThetaW(); _sw = sqrt(sw2); _cw = sqrt(1.-sw2); // get the mixing matrices _mixS=model->CPevenHiggsMix(); if(!_mixS) throw InitException() << "Mixing matrix for CP-even neutral Higgs" << " bosons is not set in NMSSMWHHVertex::doinit()" << Exception::runerror; _mixP=model->CPoddHiggsMix(); if(!_mixP) throw InitException() << "Mixing matrix for CP-odd neutral Higgs" << " bosons is not set in NMSSMWHHVertex::doinit()" << Exception::runerror; // sin and cos beta double beta = atan(model->tanBeta()); _sinb = sin(beta); _cosb = cos(beta); // base class VSSVertex::doinit(); } void NMSSMWHHVertex::persistentOutput(PersistentOStream & os) const { os << _sinb << _cosb << _sw << _cw << _mixS << _mixP; } void NMSSMWHHVertex::persistentInput(PersistentIStream & is, int) { is >> _sinb >> _cosb >> _sw >> _cw >> _mixS >> _mixP; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigNMSSMWHHVertex("Herwig::NMSSMWHHVertex", "HwSusy.so HwNMSSM.so"); void NMSSMWHHVertex::Init() { static ClassDocumentation documentation ("The NMSSMWHHVertex class implements the coupling of an electroweak" " gauge boson with two Higgs bosons in the NMSSM."); } //calulate the couplings void NMSSMWHHVertex::setCoupling(Energy2 q2,tcPDPtr a,tcPDPtr b,tcPDPtr c) { // weak coupling if(q2!=_q2last) { _couplast = weakCoupling(q2); _q2last=q2; } // gauge bosons int ibos= a->id(); int ih1 = b->id(); int ih2 = c->id(); Complex fact; if(ibos==ParticleID::Z0) { fact = 0.5/_cw; // Z H+ H- if(abs(ih1)==37) { fact *= (sqr(_cw)-sqr(_sw)); if(ih1<0) fact *=-1.; } // Z CP even CP odd else { if(ih1%10==6) { fact *= -1.; swap(ih1,ih2); } int is = (ih1-25)/10; int ip = (ih2-36)/10; fact *= Complex(0.,1.)*((*_mixS)(is,1)*(*_mixP)(ip,1)- (*_mixS)(is,0)*(*_mixP)(ip,0)); } } // gamma CP even CP odd else if(ibos==ParticleID::gamma) { fact = ih1>0 ? _sw : -_sw; } // W boson else { fact = 0.5; if(abs(ih2)==37) { swap(ih1,ih2); fact*=-1; } // H+ CP even if(ih2%5==0) { int is = (ih2-25)/10; fact *= (_cosb*(*_mixS)(is,1)-_sinb*(*_mixS)(is,0)); if(ibos<0) fact*=-1; } // H+ CP odd else { int ip = (ih2-36)/10; fact *=-Complex(0.,1.)*(_cosb*(*_mixP)(ip,1)+_sinb*(*_mixP)(ip,0)); } } //output the coupling norm(_couplast*fact); } diff --git a/Models/Susy/NMSSM/NMSSMWWHHVertex.cc b/Models/Susy/NMSSM/NMSSMWWHHVertex.cc --- a/Models/Susy/NMSSM/NMSSMWWHHVertex.cc +++ b/Models/Susy/NMSSM/NMSSMWWHHVertex.cc @@ -1,175 +1,176 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the NMSSMWWHHVertex class. // #include "NMSSMWWHHVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "NMSSM.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; NMSSMWWHHVertex::NMSSMWWHHVertex() : couplast_(0.),q2last_(ZERO), sw_(0.), cw_(0.), sb_(0.), cb_(0.) { orderInGem(2); orderInGs (0); + colourStructure(ColourStructure::SINGLET); } IBPtr NMSSMWWHHVertex::clone() const { return new_ptr(*this); } IBPtr NMSSMWWHHVertex::fullclone() const { return new_ptr(*this); } void NMSSMWWHHVertex::persistentOutput(PersistentOStream & os) const { os << sw_ << cw_ << sb_ << cb_ << mixS_ << mixP_; } void NMSSMWWHHVertex::persistentInput(PersistentIStream & is, int) { is >> sw_ >> cw_ >> sb_ >> cb_ >> mixS_ >> mixP_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigNMSSMWWHHVertex("Herwig::NMSSMWWHHVertex", "NMSSMWWHHVertex.so"); void NMSSMWWHHVertex::Init() { static ClassDocumentation documentation ("The NMSSMWWHHVertex class implements the coupling of" " two electroweak and two Higgs bosons in the NMSSM."); } void NMSSMWWHHVertex::doinit() { int scalar[3]={25,35,45}; int pseudo[2]={36,46}; // scalar higgs bosons for(unsigned int i=0;i<3;++i) { // pair of scalars for(unsigned int j=0;j<3;++j) { addToList( 24,-24,scalar[i],scalar[j]); addToList( 23, 23,scalar[i],scalar[j]); } // scalar charged addToList( 22, 24,scalar[i],-37); addToList( 22,-24,scalar[i], 37); addToList( 23, 24,scalar[i],-37); addToList( 23,-24,scalar[i], 37); } // pair of pseudoscalars for(unsigned int i=0;i<2;++i) { for(unsigned int j=0;j<2;++j) { addToList( 24,-24,pseudo[i],pseudo[j]); addToList( 23, 23,pseudo[i],pseudo[j]); } // pseudo charged addToList( 22, 24,pseudo[i],-37); addToList( 22,-24,pseudo[i], 37); addToList( 23, 24,pseudo[i],-37); addToList( 23,-24,pseudo[i], 37); } addToList( 24,-24, 37,-37); addToList( 23, 23, 37,-37); addToList( 22, 23, 37,-37); addToList( 22, 22, 37,-37); // cast to NMSSM model tcNMSSMPtr model=dynamic_ptr_cast(generator()->standardModel()); if(!model) throw InitException() << "Must have the NMSSM Model in NMSSMWWHHVertex::doinit()" << Exception::runerror; // sin and cos theta_W sw_ = sqrt( sin2ThetaW()); cw_ = sqrt(1.-sin2ThetaW()); // get the mixing matrices mixS_ = model->CPevenHiggsMix(); if(!mixS_) throw InitException() << "Mixing matrix for CP-even neutral Higgs" << " bosons is not set in NMSSMWWHHVertex::doinit()" << Exception::runerror; mixP_ = model->CPoddHiggsMix(); if(!mixP_) throw InitException() << "Mixing matrix for CP-odd neutral Higgs" << " bosons is not set in NMSSMWWHHVertex::doinit()" << Exception::runerror; // sin and cos beta double beta = atan(model->tanBeta()); sb_ = sin(beta); cb_ = cos(beta); // base class VVSSVertex::doinit(); } void NMSSMWWHHVertex::setCoupling(Energy2 q2,tcPDPtr part1,tcPDPtr part2, tcPDPtr part3, tcPDPtr part4) { if(q2!=q2last_||couplast_==0.) { couplast_ = sqr(electroMagneticCoupling(q2)); q2last_=q2; } int ibos1 = part1->id(), ibos2 = part2->id(); int isca1 = part3->id(), isca2 = part4->id(); Complex fact(1.); if(abs(ibos1)==abs(ibos2)) { fact *= 0.5/sqr(sw_); if(ibos1==ParticleID::Z0) fact /= sqr(cw_); // charged if(abs(isca1)==37) { if(ibos1==ParticleID::Z0) fact *= sqr(sqr(cw_)-sqr(sw_)); else if(ibos1==ParticleID::gamma) fact = 2.; } // pair of scalars else if((isca1-5)%10==0) { unsigned int i = (isca1-25)/10; unsigned int j = (isca2-25)/10; fact *= (*mixS_)(i,0)*(*mixS_)(j,0)+(*mixS_)(i,1)*(*mixS_)(j,1); } // pair of pseudoscalars else if((isca1-6)%10==0) { unsigned int i = (isca1-36)/10; unsigned int j = (isca2-36)/10; fact *= (*mixP_)(i,0)*(*mixP_)(j,0)+(*mixP_)(i,1)*(*mixP_)(j,1); } else assert(false); } else if(abs(ibos1)==ParticleID::Wplus || abs(ibos2)==ParticleID::Wplus) { if(abs(ibos1)==ParticleID::gamma || abs(ibos2)==ParticleID::gamma) { fact *= -0.5/sw_; } else { fact *= 0.5/cw_; } if((isca1-5)%10==0) { unsigned int i = (isca1-25)/10; fact *= sb_*(*mixS_)(i,0) - cb_*(*mixS_)(i,1); } else if((isca2-5)%10==0) { unsigned int i = (isca2-25)/10; fact *= sb_*(*mixS_)(i,0) - cb_*(*mixS_)(i,1); } else if((isca1-6)%10==0) { unsigned int i = (isca1-36)/10; fact *= sb_*(*mixP_)(i,0) + cb_*(*mixP_)(i,1); fact *= isca2==ParticleID::Hplus ? -Complex(0.,1.) : Complex(0.,1.); } else if((isca2-6)%10==0) { unsigned int i = (isca2-36)/10; fact *= sb_*(*mixP_)(i,0) + cb_*(*mixP_)(i,1); fact *= isca1==ParticleID::Hplus ? -Complex(0.,1.) : Complex(0.,1.); } else assert(false); } else { fact = (sqr(cw_)-sqr(sw_))/cw_/sw_; } // set the coupling norm(couplast_*fact); } diff --git a/Models/Susy/NMSSM/NMSSMWWHVertex.cc b/Models/Susy/NMSSM/NMSSMWWHVertex.cc --- a/Models/Susy/NMSSM/NMSSMWWHVertex.cc +++ b/Models/Susy/NMSSM/NMSSMWWHVertex.cc @@ -1,92 +1,93 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the NMSSMWWHVertex class. // #include "NMSSMWWHVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "NMSSM.h" using namespace Herwig; using namespace ThePEG::Helicity; NMSSMWWHVertex::NMSSMWWHVertex() : _couplast(0.), _q2last(), _mw(), _zfact(0.), _sinb(0.),_cosb(0.) { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::SINGLET); } void NMSSMWWHVertex::doinit() { int id[3]={25,35,45}; // PDG codes for the particles in the vertex for(unsigned int ix=0;ix<3;++ix) { // Higgs WW addToList( 24, -24, id[ix] ); //Higgs ZZ addToList( 23, 23, id[ix] ); } // SM parameters _mw = getParticleData(ThePEG::ParticleID::Wplus)->mass(); double sw2 = sin2ThetaW(); _zfact = 1./(1.-sw2); // NMSSM parameters tcNMSSMPtr model=dynamic_ptr_cast(generator()->standardModel()); if(!model) throw InitException() << "Must have the NMSSM Model in NMSSMWWHVertex::doinit()" << Exception::runerror; // get the mixing matrices _mixS=model->CPevenHiggsMix(); if(!_mixS) throw InitException() << "Mixing matrix for CP-even neutral Higgs" << " bosons is not set in NMSSMWWHVertex::doinit()" << Exception::runerror; // sin and cos beta double beta = atan(model->tanBeta()); _sinb=sin(beta); _cosb=cos(beta); // base class VVSVertex::doinit(); } void NMSSMWWHVertex::persistentOutput(PersistentOStream & os) const { os << ounit(_mw,GeV) << _zfact << _sinb << _cosb << _mixS; } void NMSSMWWHVertex::persistentInput(PersistentIStream & is, int) { is >> iunit(_mw,GeV) >> _zfact >> _sinb >> _cosb >> _mixS; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigNMSSMWWHVertex("Herwig::NMSSMWWHVertex", "HwSusy.so HwNMSSM.so"); void NMSSMWWHVertex::Init() { static ClassDocumentation documentation ("The NMSSMWWHVertex class implements the coupling of two electroweak gauge" " bosons with the Higgs bosons of the NMSSM"); } //calulate couplings void NMSSMWWHVertex::setCoupling(Energy2 q2,tcPDPtr a,tcPDPtr, tcPDPtr c) { // ID of gauge bosons int ibos=abs(a->id()); // ID of Higgs int ihiggs = (c->id()-25)/10; // first the overall normalisation if(q2!=_q2last) { _couplast = weakCoupling(q2)*_mw*UnitRemoval::InvE; _q2last=q2; } // higgs mixing factor Complex hmix = _cosb*(*_mixS)(ihiggs,0)+_sinb*(*_mixS)(ihiggs,1); // couplings if(ibos==24) norm(_couplast*hmix); else if(ibos==23) norm(_couplast*hmix*_zfact); else assert(false); } diff --git a/Models/Susy/RPV/RPVFFSVertex.cc b/Models/Susy/RPV/RPVFFSVertex.cc --- a/Models/Susy/RPV/RPVFFSVertex.cc +++ b/Models/Susy/RPV/RPVFFSVertex.cc @@ -1,825 +1,826 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the RPVFFSVertex class. // #include "RPVFFSVertex.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; namespace { unsigned int neutralinoIndex(long id) { if(id> 1000000) return id<1000025 ? id-1000022 : (id-1000005)/10; else if(abs(id)<=16) return (abs(id)-4)/2; else return id-13; } unsigned int charginoIndex(long id) { return abs(id)>1000000 ? (abs(id)-1000024)/13 : (abs(id)-7)/2; } } RPVFFSVertex::RPVFFSVertex() : interactions_(0), mw_(ZERO), _q2last(ZERO), _couplast(0.), _leftlast(0.),_rightlast(0.), _id1last(0), _id2last(0), _id3last(0), yukawa_(true), _sw(0.), _cw(0.),_sb(0.), _cb(0.), vd_(ZERO), vu_(ZERO), _massLast(make_pair(ZERO,ZERO)) { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::DELTA); } IBPtr RPVFFSVertex::clone() const { return new_ptr(*this); } IBPtr RPVFFSVertex::fullclone() const { return new_ptr(*this); } void RPVFFSVertex::doinit() { // cast the model to the RPV one model_ = dynamic_ptr_cast(generator()->standardModel()); if( !model_ ) throw InitException() << "RPVFFSVertex::doinit() - " << "The pointer to the MSSM object is null!" << Exception::abortnow; // get the various mixing matrices _stop = model_->stopMix(); _sbot = model_->sbottomMix(); _stau = model_->stauMix(); _nmix = model_->neutralinoMix(); _umix = model_->charginoUMix(); _vmix = model_->charginoVMix(); _mixH = model_->CPevenHiggsMix(); _mixP = model_->CPoddHiggsMix(); _mixC = model_->ChargedHiggsMix(); if(!_stop || !_sbot ) throw InitException() << "RPVFFSVertex::doinit() - " << "A squark mixing matrix pointer is null." << " stop: " << _stop << " sbottom: " << _sbot << Exception::abortnow; if(!_nmix) throw InitException() << "RPVFFSVertex::doinit() - " << "A gaugino mixing matrix pointer is null." << " N: " << _nmix << " U: " << _umix << " V: " << _vmix << Exception::abortnow; if(! ( _stau || (!_stau&& _mixC->size().first>1))) throw InitException() << "RPVFFSVertex::doinit() - " << "Must have either the stau mixing matrix or it" << " must be part of the charged Higgs boson mixing." << Exception::abortnow; // various interactions // scalar Higgs bosons vector h0(2); h0[0] = 25; h0[1] = 35; if(_mixH&&_mixH->size().first>2) { h0.push_back(1000012); h0.push_back(1000014); h0.push_back(1000016); } // pseudoscalar Higgs bosons vector a0(1,36); if(_mixP&&_mixP->size().first>1) { a0.push_back(1000017); a0.push_back(1000018); a0.push_back(1000019); } // charged Higgs bosons vector hp(1,37); if(_mixC->size().first>1) { hp.push_back(-1000011); hp.push_back(-1000013); hp.push_back(-1000015); hp.push_back(-2000011); hp.push_back(-2000013); hp.push_back(-2000015); } // neutralinos vector neu(4); neu[0] = 1000022; neu[1] = 1000023; neu[2] = 1000025; neu[3] = 1000035; if(_nmix->size().first>4) { if(model_->majoranaNeutrinos()) { neu.push_back(17); neu.push_back(18); neu.push_back(19); } else { neu.push_back(12); neu.push_back(14); neu.push_back(16); } } // charginos vector chg(2); chg[0] = 1000024; chg[1] = 1000037; if(_umix->size().first>2) { chg.push_back(-11); chg.push_back(-13); chg.push_back(-15); } // FFH if(interactions_==0||interactions_==1) { // quarks neutral scalar for ( unsigned int h = 0; h < h0.size(); ++h ) { for(long ix=1;ix<7;++ix) addToList(-ix,ix,h0[h]); } // quarks neutral pseudoscalar for ( unsigned int h = 0; h < a0.size(); ++h ) { for(long ix=1;ix<7;++ix) addToList(-ix,ix,a0[h]); } // quarks charged higgs for(unsigned int h=0;hsize().first<=4) { for(unsigned int h=0;hsize().first<=4) { for(unsigned int nl = 0; nl < neu.size(); ++nl) { for(long ix=12;ix<17;ix+=2) { addToList( neu[nl], ix, -(1000000+ix) ); addToList( neu[nl], -ix, (1000000+ix) ); } } } // charged leptons no mixing if(!_mixC || _mixC->size().first==1) { for(unsigned int nl = 0; nl < neu.size(); ++nl) { for(long ix=11;ix<17;ix+=2) { addToList( neu[nl], ix, -(1000000+ix) ); addToList( neu[nl], -ix, (1000000+ix) ); addToList( neu[nl], ix, -(2000000+ix) ); addToList( neu[nl], -ix, (2000000+ix) ); } } } } // chargino sfermion if(interactions_==0||interactions_==4) { //quarks for(unsigned int ic = 0; ic < chg.size(); ++ic) { for(long ix = 1; ix < 7; ++ix) { if( ix % 2 == 0 ) { addToList(-chg[ic], ix,-( 999999+ix)); addToList(-chg[ic], ix,-(1999999+ix)); addToList( chg[ic],-ix, 999999+ix ); addToList( chg[ic],-ix, 1999999+ix ); } else { addToList(-chg[ic],-ix, 1000001+ix ); addToList(-chg[ic],-ix, 2000001+ix ); addToList( chg[ic], ix,-(1000001+ix)); addToList( chg[ic], ix,-(2000001+ix)); } } } // sneutrinos if(!_mixH || _mixH->size().first<=2) { for(unsigned int ic = 0; ic < chg.size(); ++ic) { for(long ix = 11; ix < 17; ix+=2) { addToList(-chg[ic],-ix,1000001+ix); addToList(chg[ic],ix,-(1000001+ix)); } } } // charged leptons if(!_mixC || _mixC->size().first==1) { for(unsigned int ic = 0; ic < chg.size(); ++ic) { for(long ix = 12; ix < 17; ix+=2) { addToList(-chg[ic], ix,-( 999999+ix)); addToList(-chg[ic], ix,-(1999999+ix)); addToList( chg[ic],-ix, ( 999999+ix)); addToList( chg[ic],-ix, (1999999+ix)); } } } } FFSVertex::doinit(); // various couplings and parameters mw_ = getParticleData(ParticleID::Wplus)->mass(); _sw = sqrt(sin2ThetaW()); double tb = model_->tanBeta(); _cw = sqrt(1. - sqr(_sw)); _sb = tb/sqrt(1 + sqr(tb)); _cb = sqrt(1 - sqr(_sb)); vector vnu = model_->sneutrinoVEVs(); double g = electroMagneticCoupling(sqr(mw_))/_sw; Energy v = 2.*mw_/g; vd_ = sqrt((sqr(v)-sqr(vnu[0])-sqr(vnu[1])-sqr(vnu[2]))/ (1.+sqr(tb))); vu_ = vd_*tb; // couplings of the neutral scalar Higgs to charginos Energy me = model_->mass(sqr(mw_),getParticleData(ParticleID::eminus )); Energy mmu = model_->mass(sqr(mw_),getParticleData(ParticleID::muminus )); Energy mtau = model_->mass(sqr(mw_),getParticleData(ParticleID::tauminus)); double h_E[3] = {sqrt(2.)*me/vd_/g,sqrt(2.)*mmu /vd_/g,sqrt(2.)*mtau/vd_/g}; for(unsigned int ih=0;ih<_mixH->size().first;++ih ) { OCCHL_.push_back(vector > (_umix->size().first,vector(_umix->size().first,0.))); for(unsigned int i=0;i<_umix->size().first;++i) { for(unsigned int j=0;j<_umix->size().first;++j) { OCCHL_[ih][i][j] = -sqrt(0.5)* ( (*_mixH)(ih,0)*(*_vmix)(i,0)*(*_umix)(j,1) + (*_mixH)(ih,1)*(*_vmix)(i,1)*(*_umix)(j,0)); for(unsigned int k=2;k<_umix->size().first;++k) { OCCHL_[ih][i][j] -= sqrt(0.5)*(+(*_mixH)(ih,k)*(*_vmix)(i,0)*(*_umix)(j,k) +h_E[k-2]*(*_umix)(j,k)*(*_vmix)(i,k)*(*_mixH)(ih,0) -h_E[k-2]*(*_umix)(j,1)*(*_vmix)(i,k)*(*_mixH)(ih,k)); } } } } // couplings of the neutral scalar Higgs to neutralinos double tw = _sw/_cw; for(unsigned int ih=0;ih<_mixH->size().first;++ih) { ONNHL_.push_back(vector > (_nmix->size().first,vector(_nmix->size().first,0.))); for(unsigned int i=0;i<_nmix->size().first;++i) { for(unsigned int j=0;j<_nmix->size().first;++j) { ONNHL_[ih][i][j] =0.; for(unsigned int in=2;in<_nmix->size().first;++in) { double sign = in!=3 ? 1. : -1.; ONNHL_[ih][i][j] += 0.5*sign*(*_mixH)(ih,in-2)* ( + (tw*(*_nmix)(i,0) - (*_nmix)(i,1) )*(*_nmix)(j,in) + (tw*(*_nmix)(j,0) - (*_nmix)(j,1) )*(*_nmix)(i,in) ); } } } } // couplings of the neutral pseudoscalar Higgs to neutralinos for(unsigned int ih=0;ih<_mixP->size().first;++ih) { ONNAL_.push_back(vector > (_nmix->size().first,vector(_nmix->size().first,0.))); for(unsigned int i=0;i<_nmix->size().first;++i) { for(unsigned int j=0;j<_nmix->size().first;++j) { ONNAL_[ih][i][j] =0.; for(unsigned int in=2;in<_nmix->size().first;++in) { double sign = in!=3 ? 1. : -1.; ONNAL_[ih][i][j] += -0.5*sign*(*_mixP)(ih,in-2)* ( + (tw*(*_nmix)(i,0) - (*_nmix)(i,1) )*(*_nmix)(j,in) + (tw*(*_nmix)(j,0) - (*_nmix)(j,1) )*(*_nmix)(i,in) ); } } } } // couplings of the neutral pseudoscalar higgs to charginos for(unsigned int ih=0;ih<_mixP->size().first;++ih) { OCCAL_.push_back(vector > (_umix->size().first,vector(_umix->size().first,0.))); for(unsigned int i=0;i<_umix->size().first;++i) { for(unsigned int j=0;j<_umix->size().first;++j) { OCCAL_[ih][i][j] = (*_mixP)(ih,0)*(*_vmix)(i,0)*(*_umix)(j,1)+ (*_mixP)(ih,1)*(*_vmix)(i,1)*(*_umix)(j,0); for(unsigned int k=2;k<_umix->size().first;++k) { OCCAL_[ih][i][j] += (*_mixP)(ih,k)*(*_vmix)(i,0)*(*_umix)(j,k) -h_E[k-2]*(*_umix)(j,k)*(*_vmix)(i,k)*(*_mixP)(ih,0) +h_E[k-2]*(*_umix)(j,1)*(*_vmix)(i,k)*(*_mixP)(ih,k); } OCCAL_[ih][i][j] *= sqrt(0.5); } } } // couplings for the charged higgs for(unsigned int ih=0;ih<_mixC->size().first;++ih) { OCNSL_.push_back(vector > (_nmix->size().first,vector(_umix->size().first,0.))); OCNSR_.push_back(vector > (_nmix->size().first,vector(_umix->size().first,0.))); for(unsigned int i = 0; i < _nmix->size().first; ++i) { for(unsigned int j=0;j<_umix->size().first;++j) { OCNSL_[ih][i][j] = (*_mixC)(ih,1)*conj((*_nmix)(i, 3)*(*_vmix)(j,0) +((*_nmix)(i,1) + (*_nmix)(i,0)*tw)*(*_vmix)(j,1)/sqrt(2)); OCNSR_[ih][i][j] = (*_mixC)(ih,0)* ((*_nmix)(i, 2)*(*_umix)(j,0) -((*_nmix)(i,1) + (*_nmix)(i,0)*tw)*(*_umix)(j,1)/sqrt(2)); for(unsigned int k=2;k<_umix->size().first;++k) { OCNSL_[ih][i][j] += -h_E[k-2]*(*_mixC)(ih,0)*conj((*_nmix)(i,2+k)*(*_vmix)(j,k)) +(*_mixC)(ih,k )*h_E[k-2]*conj((*_nmix)(i, 2)*(*_vmix)(j,k)) +(*_mixC)(ih,k+3)*tw*sqrt(2.)*conj((*_nmix)(i,0)*(*_vmix)(j,k)); OCNSR_[ih][i][j] += (*_mixC)(ih,k)*((*_nmix)(i,2+k)*(*_umix)(j,0) -((*_nmix)(i,1) + (*_nmix)(i,0)*tw)*(*_umix)(j,k)/sqrt(2)) -(*_mixC)(ih,k+3)*h_E[k-2]*((*_nmix)(i,k+2)*(*_umix)(j,1)-(*_nmix)(i,2)*(*_umix)(j,k)); } } } } } void RPVFFSVertex::persistentOutput(PersistentOStream & os) const { os << interactions_ << _stop << _sbot << _stau << _umix << _vmix << _nmix << _mixH << _mixP << _mixC << ounit(mw_,GeV) << yukawa_ << model_ << _sw << _cw << _sb << _cb << ounit(vd_,GeV) << ounit(vu_,GeV) << OCCHL_ << ONNHL_ << ONNAL_ << OCCAL_ << OCNSL_ << OCNSR_; } void RPVFFSVertex::persistentInput(PersistentIStream & is, int) { is >> interactions_ >> _stop >> _sbot >> _stau >> _umix >> _vmix >> _nmix >> _mixH >> _mixP >> _mixC >> iunit(mw_,GeV) >> yukawa_ >> model_ >> _sw >> _cw >> _sb >> _cb >> iunit(vd_,GeV) >> iunit(vu_,GeV) >> OCCHL_ >> ONNHL_ >> ONNAL_ >> OCCAL_ >> OCNSL_ >> OCNSR_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigRPVFFSVertex("Herwig::RPVFFSVertex", "HwSusy.so HwRPV.so"); void RPVFFSVertex::Init() { static ClassDocumentation documentation ("The RPVFFSVertex class implements all the couplings of fermion-antiferion to scalars" " in R-Parity violating models, including sfermion fermion gaugino, SM ferimon antiferimon Higgs " "and gaugino-gaugino Higgs."); static Switch interfaceInteractions ("Interactions", "Whice interactions to include", &RPVFFSVertex::interactions_, 0, false, false); static SwitchOption interfaceInteractionsAll (interfaceInteractions, "All", "Include all the interactions", 0); static SwitchOption interfaceInteractionsHiggsSMFermions (interfaceInteractions, "HiggsSMFermions", "Interactions of Higgs with SM fermions", 1); static SwitchOption interfaceInteractionsHiggsGaugino (interfaceInteractions, "HiggsGaugino", "Interactions of the Higgs with the gauginos", 2); static SwitchOption interfaceInteractionsNeutralinoSfermion (interfaceInteractions, "NeutralinoSfermion", "Include the neutralino sfermion interactions", 3); static SwitchOption interfaceInteractionsCharginoSfermions (interfaceInteractions, "CharginoSfermions", "Include the chargino sfermion interactions", 4); static Switch interfaceYukawa ("Yukawa", "Whether or not to include the Yukawa type couplings in neutralino/chargino interactions", &RPVFFSVertex::yukawa_, true, false, false); static SwitchOption interfaceYukawaYes (interfaceYukawa, "Yes", "Include the terms", true); static SwitchOption interfaceYukawaNo (interfaceYukawa, "No", "Don't include them", false); } void RPVFFSVertex::neutralinoSfermionCoupling(Energy2 q2, tcPDPtr fermion, tcPDPtr gaugino, tcPDPtr sfermion) { long ism(abs(fermion->id())),ig(abs(gaugino->id())),isc(sfermion->id()); if( ig != _id1last || ism != _id2last || isc != _id3last ) { _id1last = ig; _id2last = ism; _id3last = isc; // sfermion mass eigenstate unsigned int alpha(abs(isc)/1000000 - 1); // neutralino state unsigned int nl = neutralinoIndex(ig); assert(nl<=6); // common primed neutralino matrices Complex n2prime = (*_nmix)(nl,1)*_cw - (*_nmix)(nl,0)*_sw; //handle neutrinos first if( ism == 12 || ism == 14 || ism == 16 ) { _leftlast = Complex(0., 0.); _rightlast = -sqrt(0.5)*n2prime/_cw; } else { Complex n1prime = (*_nmix)(nl,0)*_cw + (*_nmix)(nl,1)*_sw; tcPDPtr smf = getParticleData(ism); double qf = smf->charge()/eplus; Complex bracketl = qf*_sw*( conj(n1prime) - _sw*conj(n2prime)/_cw ); double y = yukawa_ ? double(model_->mass(q2, smf)/2./mw_) : 0.; double lambda(0.); //neutralino mixing element Complex nlf(0.); if( ism % 2 == 0 ) { y /= _sb; lambda = -0.5 + qf*sqr(_sw); nlf = (*_nmix)(nl,3); } else { y /= _cb; lambda = 0.5 + qf*sqr(_sw); nlf = (*_nmix)(nl,2); } Complex bracketr = _sw*qf*n1prime - n2prime*lambda/_cw; //heavy quarks/sleptons if( ism == 5 || ism == 6 || ism == 15 ) { Complex ma1(0.), ma2(0.); if( ism == 5 ) { ma1 = (*_sbot)(alpha,0); ma2 = (*_sbot)(alpha,1); } else if( ism == 6 ) { ma1 = (*_stop)(alpha,0); ma2 = (*_stop)(alpha,1); } else { ma1 = (*_stau)(alpha,0); ma2 = (*_stau)(alpha,1); } _leftlast = y*conj(nlf)*ma1 - ma2*bracketl; _rightlast = y*nlf*ma2 + ma1*bracketr; } else { if( alpha == 0 ) { _leftlast = y*conj(nlf); _rightlast = bracketr; } else { _leftlast = -bracketl; _rightlast = y*nlf; } } _leftlast *= -sqrt(2.); _rightlast *= -sqrt(2.); } } //determine the helicity order of the vertex if( fermion->id() < 0 ) { left (conj(_rightlast)); right(conj( _leftlast)); } else { left ( _leftlast); right(_rightlast); } norm(_couplast); } void RPVFFSVertex::charginoSfermionCoupling(Energy2 q2, tcPDPtr fermion, tcPDPtr gaugino, tcPDPtr sfermion) { long ism(abs(fermion->id())),ig(abs(gaugino->id())),isc(sfermion->id()); if( ig != _id1last || ism != _id2last || isc != _id3last ) { _id1last = ig; _id2last = ism; _id3last = isc; // sfermion mass eigenstate unsigned int alpha(abs(isc)/1000000 - 1); // get the type of chargino unsigned int ch = charginoIndex(ig); assert(ch<=4); // various mixing matrix elements Complex ul1 = (*_umix)(ch,0), ul2 = (*_umix)(ch,1); Complex vl1 = (*_vmix)(ch,0), vl2 = (*_vmix)(ch,1); // lepton/slepton if( ism >= 11 && ism <= 16 ) { long lept = ( ism % 2 == 0 ) ? ism - 1 : ism; double y = yukawa_ ? double(model_->mass(q2, getParticleData(lept))/mw_/sqrt(2)/_cb) : 0.; if( ism == 12 || ism == 14 ) { _leftlast = 0.; _rightlast = alpha == 0 ? - ul1 : y*ul2; } else if( ism == 16 ) { _leftlast = 0.; _rightlast = -ul1*(*_stau)(alpha, 0) + y*(*_stau)(alpha,1)*ul2; } else if( ism == 11 || ism == 13 || ism == 15 ) { _leftlast = y*conj(ul2); _rightlast = -vl1; } } // squark/quark else { double yd(0.), yu(0.); if(yukawa_) { if( ism % 2 == 0) { yu = model_->mass(q2, getParticleData(ism))/mw_/sqrt(2)/_sb; yd = model_->mass(q2, getParticleData(ism - 1))/mw_/sqrt(2)/_cb; } else { yu = model_->mass(q2, getParticleData(ism + 1))/mw_/sqrt(2)/_sb; yd = model_->mass(q2, getParticleData(ism))/mw_/sqrt(2)/_cb; } } //heavy quarks if( ism == 5 ) { _leftlast = yd*conj(ul2)*(*_stop)(alpha,0); _rightlast = -vl1*(*_stop)(alpha, 0) + yu*vl2*(*_stop)(alpha,1); } else if( ism == 6 ) { _leftlast = yu*conj(vl2)*(*_sbot)(alpha,0); _rightlast = -ul1*(*_sbot)(alpha, 0) + yd*ul2*(*_sbot)(alpha,1); } else { if( alpha == 0 ) { _leftlast = (ism % 2 == 0) ? yu*conj(vl2) : yd*conj(ul2); _rightlast = (ism % 2 == 0) ? -ul1 : -vl1; } else { _leftlast = 0.; _rightlast = (ism % 2 == 0) ? yd*ul2 : yu*vl2; } } } } //determine the helicity order of the vertex if( fermion->id() < 0 ) { left (conj(_rightlast)); right(conj( _leftlast)); } else { left ( _leftlast); right(_rightlast); } norm(_couplast); } void RPVFFSVertex::higgsFermionCoupling(Energy2 q2, tcPDPtr f1, tcPDPtr f2, tcPDPtr higgs) { long f1ID(f1->id()), f2ID(f2->id()), isc(higgs->id()); // running fermion masses if( q2 != _q2last || _id1last != f1ID) { _massLast.first = model_->mass(q2,f1); _id1last = f1ID; } if( q2 != _q2last || _id2last != f2ID) { _massLast.second = model_->mass(q2,f2); _id2last = f2ID; } if( q2 != _q2last) _id3last = isc; Complex fact(0.); // scalar neutral Higgs if(isc == ParticleID::h0 || isc == ParticleID::H0 || isc == ParticleID::SUSY_nu_eL || isc == ParticleID::SUSY_nu_muL || isc == ParticleID::SUSY_nu_tauL ) { unsigned int ih = isc < 1000000 ? (isc-25)/10 : (isc-1000008)/2; unsigned int id = abs(f1ID); fact = -_massLast.first* ((id%2==0) ? (*_mixH)(ih,1)/vu_ : (*_mixH)(ih,0)/vd_); left (1.); right(1.); } // pseudoscalar neutral Higgs else if(isc == ParticleID::A0 || isc == 1000017 || isc == 1000018 || isc == 1000019 ) { unsigned int ih = isc < 1000000 ? 0 : (isc-1000016); unsigned int id = abs(f1ID); if(_mixP) { fact = -Complex(0., 1.)*_massLast.first* ( (id%2==0) ? (*_mixP)(ih,1)/vu_ : (*_mixP)(ih,0)/vd_); } else { fact = -Complex(0., 1.)*_massLast.first* ( (id%2==0) ? _cb/vu_ : _sb/vd_); } left ( 1.); right(-1.); } // charged higgs else { if(!_mixC) { if( abs(f1ID) % 2 == 0 ) { _leftlast = _massLast.first /vu_*_cb; _rightlast = _massLast.second/vd_*_sb; } else { _leftlast = _massLast.second/vu_*_cb; _rightlast = _massLast.first /vd_*_sb; } } else { unsigned int ih; if(abs(isc)==ParticleID::Hplus) { ih = 0; } else { isc *= -1; ih = abs(isc)<2000000 ? (abs(isc)-1000009)/2 : (abs(isc)-2000003)/2; } if( abs(f1ID) % 2 == 0 ) { _leftlast = _massLast.first /vu_*(*_mixC)(ih,1); _rightlast = _massLast.second/vd_*(*_mixC)(ih,0); } else { _leftlast = _massLast.second/vu_*(*_mixC)(ih,1); _rightlast = _massLast.first /vd_*(*_mixC)(ih,0); } } if( isc > 0 ) swap(_leftlast,_rightlast); fact = sqrt(2.); left ( _leftlast); right(_rightlast); } norm(fact); } void RPVFFSVertex::higgsGauginoCoupling(Energy2, tcPDPtr f1, tcPDPtr f2, tcPDPtr higgs) { long f1ID(f1->id()), f2ID(f2->id()), isc(higgs->id()); if( isc == _id3last && f1ID == _id1last && f2ID == _id2last ) { left ( _leftlast); right(_rightlast); } else { _id1last = f1ID; _id2last = f2ID; _id3last = isc; // scalar neutral Higgs if(isc == ParticleID::h0 || isc == ParticleID::H0 || isc == ParticleID::SUSY_nu_eL || isc == ParticleID::SUSY_nu_muL || isc == ParticleID::SUSY_nu_tauL ) { unsigned int ih = isc < 1000000 ? (isc-25)/10 : (isc-1000008)/2; // charginos if(f1->charged()) { unsigned int ei = charginoIndex(f1ID); unsigned int ej = charginoIndex(f2ID); if (ei< 2&&f1ID>0) swap(ei,ej); else if(ei>=2&&f1ID<0) swap(ei,ej); _rightlast = conj(OCCHL_[ih][ej][ei]); _leftlast = OCCHL_[ih][ei][ej] ; } // neutralinos else { unsigned int ei = neutralinoIndex(f1ID); unsigned int ej = neutralinoIndex(f2ID); _leftlast = conj(ONNHL_[ih][ej][ei]); _rightlast = ONNHL_[ih][ei][ej] ; } } // pseudoscalar neutral Higgs else if(isc == ParticleID::A0 || isc == 1000017 || isc == 1000018 || isc == 1000019 ) { unsigned int ih = isc < 1000000 ? 0 : (isc-1000016); // charginos if(f1->charged()) { unsigned int ei = charginoIndex(f1ID); unsigned int ej = charginoIndex(f2ID); if (ei< 2&&f1ID>0) swap(ei,ej); else if(ei>=2&&f1ID<0) swap(ei,ej); _rightlast = -Complex(0.,1.)*conj(OCCAL_[ih][ej][ei]); _leftlast = Complex(0.,1.)* OCCAL_[ih][ei][ej] ; } // neutralinos else { unsigned int ei = neutralinoIndex(f1ID); unsigned int ej = neutralinoIndex(f2ID); _leftlast = Complex(0.,1.)*conj(ONNAL_[ih][ej][ei]); _rightlast = -Complex(0.,1.)* ONNAL_[ih][ei][ej] ; } } // charged higgs else { unsigned int ih = abs(isc) < 1000000 ? 0 : (abs(isc) < 2000000 ? (abs(isc)-1000009)/2 : (abs(isc)-2000003)/2); long chg(f2ID), neu(f1ID); if(f1->charged()) swap(chg, neu); unsigned int ei = neutralinoIndex(neu); unsigned int ej = charginoIndex(chg); _leftlast = -OCNSL_[ih][ei][ej]; _rightlast = -OCNSR_[ih][ei][ej]; bool chargedSwap = abs(isc)<1000000 ? isc<0 : isc>0; if( chargedSwap ) { Complex tmp = _leftlast; _leftlast = conj(_rightlast); _rightlast = conj(tmp); } } left ( _leftlast); right(_rightlast); } norm(_couplast); } void RPVFFSVertex::setCoupling(Energy2 q2, tcPDPtr part1, tcPDPtr part2,tcPDPtr part3) { // overall normalisation if(q2!=_q2last || _couplast==0.) { _couplast = weakCoupling(q2); _q2last=q2; } long f1ID(part1->id()), f2ID(part2->id()), isc(abs(part3->id())); // squark quark if(part3->coloured()) { tcPDPtr smfermion = part1, gaugino = part2; if(gaugino->coloured()) swap(smfermion,gaugino); if(gaugino->charged()) charginoSfermionCoupling(q2,smfermion,gaugino,part3); else neutralinoSfermionCoupling(q2,smfermion,gaugino,part3); } // slepton/lepton without mixing else if((( isc >= 1000011 && isc <= 1000016) || ( isc >= 2000011 && isc <= 2000016)) && (!_mixC || _mixC->size().first<=1 || !_mixP || _mixP->size().first<=1 )) { tcPDPtr smfermion = part1, gaugino = part2; if(abs(gaugino->id())<1000000) swap(smfermion,gaugino); if(gaugino->charged()) charginoSfermionCoupling(q2,smfermion,gaugino,part3); else neutralinoSfermionCoupling(q2,smfermion,gaugino,part3); } // SM quarks and Higgs else if((abs(f1ID) <= 6 && abs(f2ID) <= 6) || ((abs(f1ID) >= 11 && abs(f1ID) <= 16) && (abs(f2ID) >= 11 && abs(f2ID) <= 16) && _umix->size().first==2) ) { higgsFermionCoupling(q2,part1,part2,part3); } // gauginos and the Higgs (general case for sleptons) else { higgsGauginoCoupling(q2,part1,part2,part3); } } diff --git a/Models/Susy/RPV/RPVFFWVertex.cc b/Models/Susy/RPV/RPVFFWVertex.cc --- a/Models/Susy/RPV/RPVFFWVertex.cc +++ b/Models/Susy/RPV/RPVFFWVertex.cc @@ -1,267 +1,268 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the RPVFFWVertex class. // #include "RPVFFWVertex.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "Herwig/Models/StandardModel/StandardCKM.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "RPVhelper.h" using namespace Herwig; RPVFFWVertex::RPVFFWVertex() : _diagonal(false), _ckm(3,vector(3,0.0)), _sw(0.), _couplast(0.), _q2last(ZERO), _id1last(0), _id2last(0), _leftlast(0.), _rightlast(0.), _interactions(0) { orderInGs(0); orderInGem(1); + colourStructure(ColourStructure::DELTA); } IBPtr RPVFFWVertex::clone() const { return new_ptr(*this); } IBPtr RPVFFWVertex::fullclone() const { return new_ptr(*this); } void RPVFFWVertex::doinit() { // SUSY mixing matrices tSusyBasePtr model = dynamic_ptr_cast(generator()->standardModel()); if(!model) throw InitException() << "RPVFFWVertex::doinit() - The model pointer is null!" << Exception::abortnow; _theN = model->neutralinoMix(); _theU = model->charginoUMix(); _theV = model->charginoVMix(); if(!_theN || !_theU || ! _theV) throw InitException() << "RPVFFWVertex::doinit() - " << "A mixing matrix pointer is null." << " N: " << _theN << " U: " << _theU << " V: " << _theV << Exception::abortnow; // SM interactions if(_interactions==0 || _interactions==1) { // particles for outgoing W- // quarks for(int ix=1;ix<6;ix+=2) { for(int iy=2;iy<7;iy+=2) { bool isOff = iy/2 != (ix+1)/2; if ( isOff && _diagonal ) continue; addToList(-ix, iy, -24); } } // leptons for(int ix=11;ix<17;ix+=2) { int inu = model->majoranaNeutrinos() ? (ix+23)/2 : ix+1; addToList(-ix, inu, -24); } // particles for outgoing W+ // quarks for(int ix=2;ix<7;ix+=2) { for(int iy=1;iy<6;iy+=2) { bool isOff = ix/2 != (iy+1)/2; if ( isOff && _diagonal ) continue; addToList(-ix, iy, 24); } } // leptons for(int ix=11;ix<17;ix+=2) { int inu = model->majoranaNeutrinos() ? (ix+23)/2 : -ix-1; addToList(inu, ix, 24); } } // neutralino and chargino if(_interactions==0 || _interactions==2) { vector neu(4); neu[0] = 1000022; neu[1] = 1000023; neu[2] = 1000025; neu[3] = 1000035; if(_theN->size().first==7) { if(model->majoranaNeutrinos()) { neu.push_back(17); neu.push_back(18); neu.push_back(19); } else { neu.push_back(12); neu.push_back(14); neu.push_back(16); } } vector cha(2); cha[0] = 1000024; cha[1] = 1000037; if(_theV->size().first==5) { cha.push_back(-11); cha.push_back(-13); cha.push_back(-15); } // sign == -1 outgoing W-, sign == +1 outgoing W+ for(int sign = -1; sign < 2; sign += 2) { for(unsigned int ine = 0; ine < neu.size(); ++ine) { for(unsigned int ic = 0; ic < cha.size(); ++ic ) { if(ic>1&&ine>3&&ic==ine-2) continue; addToList(-sign*cha[ic], neu[ine], sign*24); } } } } Helicity::FFVVertex::doinit(); // CKM matric if ( !_diagonal ) { Ptr::transient_pointer CKM = model->CKM(); // cast the CKM object to the HERWIG one ThePEG::Ptr::transient_const_pointer hwCKM = ThePEG::dynamic_ptr_cast< ThePEG::Ptr:: transient_const_pointer>(CKM); if(hwCKM) { vector< vector > CKM; CKM = hwCKM->getUnsquaredMatrix(generator()->standardModel()->families()); for(unsigned int ix=0;ix<3;++ix) { for(unsigned int iy=0;iy<3;++iy) { _ckm[ix][iy]=CKM[ix][iy]; } } } else { throw Exception() << "Must have access to the Herwig::StandardCKM object" << "for the CKM matrix in RPVFFWVertex::doinit()" << Exception::runerror; } } _sw = sqrt(sin2ThetaW()); } void RPVFFWVertex::persistentOutput(PersistentOStream & os) const { os << _sw << _theN << _theU << _theV << _diagonal << _ckm << _interactions; } void RPVFFWVertex::persistentInput(PersistentIStream & is, int) { is >> _sw >> _theN >> _theU >> _theV >> _diagonal >> _ckm >> _interactions; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigRPVFFWVertex("Herwig::RPVFFWVertex", "HwSusy.so HwRPV.so"); void RPVFFWVertex::Init() { static ClassDocumentation documentation ("The couplings of the fermions to the W boson in the RPV model" " with bilinear R-parity violation"); static Switch interfaceInteractions ("Interactions", "Which interactions to include", &RPVFFWVertex::_interactions, 0, false, false); static SwitchOption interfaceInteractionsAll (interfaceInteractions, "All", "Include all the interactions", 0); static SwitchOption interfaceInteractionsSM (interfaceInteractions, "SM", "Only include the MS terms", 1); static SwitchOption interfaceInteractionsSUSY (interfaceInteractions, "SUSY", "Include the neutralino/chargino terms", 2); static Switch interfaceDiagonal ("Diagonal", "Use a diagonal CKM matrix (ignoring the CKM object of the StandardModel).", &RPVFFWVertex::_diagonal, false, false, false); static SwitchOption interfaceDiagonalYes (interfaceDiagonal, "Yes", "Use a diagonal CKM matrix.", true); static SwitchOption interfaceDiagonalNo (interfaceDiagonal, "No", "Use the CKM object as used by the StandardModel.", false); } void RPVFFWVertex::setCoupling(Energy2 q2,tcPDPtr part1, tcPDPtr part2,tcPDPtr part3) { assert(abs(part3->id()) == ParticleID::Wplus); // normalization // first the overall normalisation if(q2 != _q2last||_couplast==0.) { _couplast = weakCoupling(q2); _q2last=q2; } norm(_couplast); // left and right couplings for quarks if(abs(part1->id()) <= 6) { int iferm=abs(part1->id()); int ianti=abs(part2->id()); if(iferm%2!=0) swap(iferm,ianti); iferm = iferm/2; ianti = (ianti+1)/2; assert( iferm>=1 && iferm<=3 && ianti>=1 && ianti<=3); left(-sqrt(0.5)*_ckm[iferm-1][ianti-1]); right(0.); } else { long neu, cha; if(part1->charged()) { cha = part1->id(); neu = part2->id(); } else { cha = part2->id(); neu = part1->id(); } if(_theV->size().first==2&&abs(neu)<=16) { left(-sqrt(0.5)); right(0.); } else { if(cha != _id1last || neu != _id2last) { _id1last = cha; _id2last = neu; unsigned int eigc = RPV_helper::charginoIndex(cha); unsigned int eign = RPV_helper::neutralinoIndex(neu); _leftlast = (*_theN)(eign, 1)*conj((*_theV)(eigc, 0)) - ( (*_theN)(eign, 3)*conj((*_theV)(eigc, 1))/sqrt(2)); _rightlast = conj((*_theN)(eign, 1))*(*_theU)(eigc, 0) + ( conj((*_theN)(eign, 2))*(*_theU)(eigc, 1)/sqrt(2)); if(_theV->size().first==5) { for(unsigned int k=0;k<3;++k) _rightlast += ( conj((*_theN)(eign, 4+k))*(*_theU)(eigc, 2+k)/sqrt(2)); } } Complex ltemp = _leftlast; Complex rtemp = _rightlast; bool chapart = abs(cha)>1000000 ? cha>0 : cha<0; // conjugate if +ve chargino if(chapart) { ltemp = conj(ltemp); rtemp = conj(rtemp); } if((part1->id()==cha&&chapart)||(part2->id()==cha&&!chapart)) { Complex temp = ltemp; ltemp = -rtemp; rtemp = -temp; } left (ltemp); right(rtemp); } } } diff --git a/Models/Susy/RPV/RPVFFZVertex.cc b/Models/Susy/RPV/RPVFFZVertex.cc --- a/Models/Susy/RPV/RPVFFZVertex.cc +++ b/Models/Susy/RPV/RPVFFZVertex.cc @@ -1,295 +1,296 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the RPVFFZVertex class. // #include "RPVFFZVertex.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "RPVhelper.h" using namespace Herwig; RPVFFZVertex::RPVFFZVertex() : _sw(0.), _cw(0.), _id1last(0), _id2last(0), _q2last(), _couplast(0.), _leftlast(0.), _rightlast(0.), _gl(17,0.0), _gr(17,0.0), _gblast(0), _interactions(0) { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::DELTA); } IBPtr RPVFFZVertex::clone() const { return new_ptr(*this); } IBPtr RPVFFZVertex::fullclone() const { return new_ptr(*this); } void RPVFFZVertex::persistentOutput(PersistentOStream & os) const { os << _sw << _cw << _theN << _theU << _theV << _gl << _gr << _interactions; } void RPVFFZVertex::persistentInput(PersistentIStream & is, int) { is >> _sw >> _cw >> _theN >> _theU >> _theV >> _gl >> _gr >> _interactions; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigRPVFFZVertex("Herwig::RPVFFZVertex", "HwSusy.so HwRPV.so"); void RPVFFZVertex::Init() { static ClassDocumentation documentation ("The RPVFFZVertex class implements trhe coupling of the Z to all" " fermion-antifermion pairs in models with bilinear RPV."); static Switch interfaceInteractions ("Interactions", "Which interactions to include", &RPVFFZVertex::_interactions, 0, false, false); static SwitchOption interfaceInteractionsAll (interfaceInteractions, "All", "Include all the interactions", 0); static SwitchOption interfaceInteractionsSM (interfaceInteractions, "SM", "Only include what would have been the interactions with the SM" " fermions in the absence of mixing", 1); static SwitchOption interfaceInteractionsNeutralino (interfaceInteractions, "Neutralino", "Only include what would have been the interactions with the " "neutralinos in the absence of mixing", 2); static SwitchOption interfaceInteractionsChargino (interfaceInteractions, "Chargino", "Only include what would have been the interactions with the " "charginos in the absence of mixing", 3); } void RPVFFZVertex::doinit() { // extract the mixing matrices tSusyBasePtr model = dynamic_ptr_cast(generator()->standardModel()); if(!model) throw InitException() << "RPVFFZVertex::doinit() - " << "The model pointer is null." << Exception::abortnow; _theN = model->neutralinoMix(); _theU = model->charginoUMix(); _theV = model->charginoVMix(); if( !_theN || !_theU || !_theV ) throw InitException() << "RPVFFZVertex::doinit - " << "A mixing matrix pointer is null. U: " << _theU << " V: " << _theV << " N: " << _theN << Exception::abortnow; // Standard Model fermions if(_interactions==0||_interactions==1) { // PDG codes for the particles // the quarks for(int ix=1;ix<7;++ix) { addToList(-ix, ix, 23); } // the leptons for(int ix=11;ix<17;ix+=2) { addToList(-ix, ix, 23); } for(int ix=12;ix<17;ix+=2) { if(_theN->size().first==7) { long inu = (ix-12)/2+17; addToList( inu, inu, 23); } else addToList(-ix, ix, 23); } } // neutralinos if(_interactions==0||_interactions==2) { vector neu(4); neu[0] = 1000022; neu[1] = 1000023; neu[2] = 1000025; neu[3] = 1000035; if(_theN->size().first==7) { if(model->majoranaNeutrinos()) { neu.push_back(17); neu.push_back(18); neu.push_back(19); } else { neu.push_back(12); neu.push_back(14); neu.push_back(16); } } for(unsigned int i = 0; i < neu.size(); ++i) { for(unsigned int j = 0; j < neu.size(); ++j) { if(!(i>3&&i==j)) addToList(neu[i], neu[j], 23); } } } // charginos if(_interactions==0||_interactions==3) { addToList(-1000024, 1000024, 22); addToList(-1000037, 1000037, 22); vector cha(2); cha[0] = 1000024; cha[1] = 1000037; if(_theV->size().first==5) { cha.push_back(-11); cha.push_back(-13); cha.push_back(-15); } for(unsigned int i = 0; i < cha.size(); ++i) { for(unsigned int j = 0; j < cha.size(); ++j) { if(!(i>1&&i==j)) addToList(-cha[i], cha[j], 23); } } } Helicity::FFVVertex::doinit(); // weak mixing double sw2 = sin2ThetaW(); _cw = sqrt(1. - sw2); _sw = sqrt( sw2 ); // Standard Model couplings for(int ix=1;ix<4;++ix) { _gl[2*ix-1] = -0.25*(model->vd() + model->ad() ); _gl[2*ix ] = -0.25*(model->vu() + model->au() ); _gl[2*ix+9 ] = -0.25*(model->ve() + model->ae() ); _gl[2*ix+10] = -0.25*(model->vnu() + model->anu()); _gr[2*ix-1] = -0.25*(model->vd() - model->ad() ); _gr[2*ix ] = -0.25*(model->vu() - model->au() ); _gr[2*ix+9 ] = -0.25*(model->ve() - model->ae() ); _gr[2*ix+10] = -0.25*(model->vnu() - model->anu()); } } void RPVFFZVertex::setCoupling(Energy2 q2,tcPDPtr part1, tcPDPtr part2,tcPDPtr part3) { // first the overall normalisation if(q2!=_q2last||_couplast==0.) { _couplast = electroMagneticCoupling(q2); _q2last=q2; } long iferm1(part1->id()), iferm2(part2->id()), boson(part3->id()); long iferm = abs(iferm1); // chargino coupling to the photon if(part3->id()==ParticleID::gamma) { assert(iferm == abs(iferm2)); _gblast = boson; _id1last = iferm1; _id2last = iferm2; _leftlast = -1.; _rightlast = -1.; if(iferm1>0) { Complex temp = _leftlast; _leftlast = -_rightlast; _rightlast = -temp; } } // coupling to the Z else { assert(part3->id()==ParticleID::Z0); // quarks if(iferm<=6) { _leftlast = _gl[iferm]/(_sw*_cw); _rightlast = _gr[iferm]/(_sw*_cw); } // charged leptons and charginos else if(part1->iCharge()!=0) { if(boson != _gblast || iferm1 != _id1last || iferm2 != _id2last) { _gblast = boson; _id1last = iferm1; _id2last = iferm2; unsigned int ic1(0); if(_theV->size().first==2&&iferm<=16) { _leftlast = -_gr[iferm]; _rightlast = -_gl[iferm]; } else { ic1 = RPV_helper::charginoIndex(iferm1); unsigned int ic2 = RPV_helper::charginoIndex(iferm2); _leftlast = -(*_theV)(ic1, 0)*conj((*_theV)(ic2, 0)) - 0.5*(*_theV)(ic1, 1)*conj((*_theV)(ic2, 1)); _rightlast = -conj((*_theU)(ic1, 0))*(*_theU)(ic2, 0) - 0.5*conj((*_theU)(ic1, 1))*(*_theU)(ic2, 1); if(abs(iferm1) == abs(iferm2)) { _leftlast += sqr(_sw); _rightlast += sqr(_sw); } if(_theV->size().first==5) { for(unsigned int ix=0;ix<3;++ix) { _rightlast += -0.5*(*_theU)(ic1, 2+ix)*conj((*_theU)(ic2, 2+ix)); } } } if((ic1<2&&iferm1>0)||(ic1>=2&&iferm1<0)) { Complex temp = _leftlast; _leftlast = -_rightlast; _rightlast = -temp; } Complex temp = _leftlast; _leftlast = -_rightlast; _rightlast = -temp; _leftlast /= _sw*_cw; _rightlast /= _sw*_cw; } } // neutrinos and neutralinos else { // case where only 4x4 matrix and neutrino if(_theN->size().first==4&&iferm<=16) { assert(iferm==12||iferm==14||iferm==16); _leftlast = _gl[iferm]/(_sw*_cw); _rightlast = _gr[iferm]/(_sw*_cw); } // neutralino else { long ic1 = part2->id(); long ic2 = part1->id(); assert(ic1 == ParticleID::SUSY_chi_10 || ic1 == ParticleID::SUSY_chi_20 || ic1 == ParticleID::SUSY_chi_30 || ic1 == ParticleID::SUSY_chi_40 || abs(ic1) == 12 || abs(ic1) == 14 || abs(ic1) == 16 || abs(ic1) == 17 || abs(ic1) == 18 || abs(ic1) == 19 ); assert(ic2 == ParticleID::SUSY_chi_10 || ic2 == ParticleID::SUSY_chi_20 || ic2 == ParticleID::SUSY_chi_30 || ic2 == ParticleID::SUSY_chi_40 || abs(ic2) == 12 || abs(ic2) == 14 || abs(ic2) == 16 || abs(ic2) == 17 || abs(ic2) == 18 || abs(ic2) == 19 ); if(ic1 != _id1last || ic2 != _id2last) { _id1last = ic1; _id2last = ic2; unsigned int neu1 = RPV_helper::neutralinoIndex(ic1); unsigned int neu2 = RPV_helper::neutralinoIndex(ic2); _leftlast = 0.5*( (*_theN)(neu1, 3)*conj((*_theN)(neu2, 3)) - (*_theN)(neu1, 2)*conj((*_theN)(neu2, 2)) ); if(_theN->size().first>4) { for(unsigned int k=0;k<3;++k) _leftlast -= 0.5*(*_theN)(neu1, 4+k)*conj((*_theN)(neu2, 4+k)); } _rightlast = -conj(_leftlast); _leftlast /= _sw*_cw; _rightlast /= _sw*_cw; } } } } norm ( _couplast); left ( _leftlast); right(_rightlast); } diff --git a/Models/Susy/RPV/RPVLLEVertex.cc b/Models/Susy/RPV/RPVLLEVertex.cc --- a/Models/Susy/RPV/RPVLLEVertex.cc +++ b/Models/Susy/RPV/RPVLLEVertex.cc @@ -1,181 +1,182 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the RPVLLEVertex class. // #include "RPVLLEVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; RPVLLEVertex::RPVLLEVertex() { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::SINGLET); } IBPtr RPVLLEVertex::clone() const { return new_ptr(*this); } IBPtr RPVLLEVertex::fullclone() const { return new_ptr(*this); } void RPVLLEVertex::persistentOutput(PersistentOStream & os) const { os << lambda_ << stau_; } void RPVLLEVertex::persistentInput(PersistentIStream & is, int) { is >> lambda_ >> stau_; } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigRPVLLEVertex("Herwig::RPVLLEVertex", "HwSusy.so HwRPV.so"); void RPVLLEVertex::Init() { static ClassDocumentation documentation ("The RPVLLEVertex class implements the trilinear LLE" " coupling in R-parity violating models."); } void RPVLLEVertex::doinit() { RPVPtr rpv = dynamic_ptr_cast(generator()->standardModel()); if(!rpv) throw InitException() << "Must have the RPV model in" << " RPVLLEVertex::doinit()" << Exception::abortnow; // get the coupling lambda_ = rpv->lambdaLLE(); stau_ = rpv->stauMix(); // set the particles in the vertex if coupling non-zero for( int i=0;i<3;++i) { for( int j=0; j<3; ++j) { for( int k=0; k<3; ++k) { // continue if zero if(lambda_[i][j][k]==0.) continue; // particles in the vertex // sneutrino addToList( -2*i-11, 2*k+11, -1000012-2*j ); addToList( 2*i+11, -2*k-11, 1000012+2*j ); // left slepton addToList( -2*i-12, 2*k+11, -1000011-2*j ); addToList( 2*i+12, -2*k-11, +1000011+2*j ); if(j==2) { addToList( -2*i-12, 2*k+11, -2000011-2*j ); addToList( 2*i+12, -2*k-11, +2000011+2*j ); } // right slepton addToList( 2*i+12, 2*j+11, -2000011-2*k ); addToList( -2*i-12, -2*j-11, +2000011+2*k ); if(k==2) { addToList( 2*i+12, 2*j+11, -1000011-2*k ); addToList( -2*i-12, -2*j-11, +1000011+2*k ); } } } } FFSVertex::doinit(); } void RPVLLEVertex::setCoupling(Energy2, tcPDPtr part1, tcPDPtr part2, tcPDPtr part3) { int islep = part3->id(); int i(-1),j(-1),k(-1); Complex mix=1.; // sneutrino case if( abs(islep) == ParticleID::SUSY_nu_eL || abs(islep) == ParticleID::SUSY_nu_muL || abs(islep) == ParticleID::SUSY_nu_tauL) { j = (abs(islep) - 1000012)/2; i = (abs(part1->id())-11)/2; k = (abs(part2->id())-11)/2; if(part1->id()*islep<0) swap(i,k); if(islep<0) { left (1.); right(0.); } else { left (0.); right(1.); } } // charged slepton case else if( abs(islep) == ParticleID::SUSY_e_Lminus || abs(islep) == ParticleID::SUSY_mu_Lminus || abs(islep) == ParticleID::SUSY_e_Rminus || abs(islep) == ParticleID::SUSY_mu_Rminus || abs(islep) == ParticleID::SUSY_tau_1minus|| abs(islep) == ParticleID::SUSY_tau_2minus) { // right charged slepton if(part1->id()*part2->id()>0) { if(abs(part1->id())%2==0) { i = (abs(part1->id())-12)/2; j = (abs(part2->id())-11)/2; } else { i = (abs(part2->id())-12)/2; j = (abs(part1->id())-11)/2; } if(abs(islep)>2000000) { k = (abs(islep)-2000011)/2; if(k==2) mix = (*stau_)(1,1); } else { assert(abs(islep)==ParticleID::SUSY_tau_1minus); k = 2; mix = (*stau_)(0,1); } if(islep>0) { left (-1.); right(0.); } else { left (0.); right(-1.); } } // left charged else { if(abs(part1->id())%2==0) { i = (abs(part1->id())-12)/2; k = (abs(part2->id())-11)/2; } else { i = (abs(part2->id())-12)/2; k = (abs(part1->id())-11)/2; } if(abs(islep)<2000000) { j = (abs(islep)-1000011)/2; if(j==2) mix = (*stau_)(0,0); } else { assert(abs(islep)==ParticleID::SUSY_tau_2minus); j = 2; mix = (*stau_)(1,0); } if(islep<0) { left (-1.); right(0.); } else { left (0.); right(-1.); } } } else assert(false); assert( i>=0 && i<=2 && j>=0 && j<=2 && k>=0 && k<=2 ); norm(mix*lambda_[i][j][k]); } diff --git a/Models/Susy/RPV/RPVLQDVertex.cc b/Models/Susy/RPV/RPVLQDVertex.cc --- a/Models/Susy/RPV/RPVLQDVertex.cc +++ b/Models/Susy/RPV/RPVLQDVertex.cc @@ -1,281 +1,282 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the RPVLQDVertex class. // #include "RPVLQDVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; RPVLQDVertex::RPVLQDVertex() { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::DELTA); } IBPtr RPVLQDVertex::clone() const { return new_ptr(*this); } IBPtr RPVLQDVertex::fullclone() const { return new_ptr(*this); } void RPVLQDVertex::persistentOutput(PersistentOStream & os) const { os << lambda_ << stop_ << sbot_ << stau_; } void RPVLQDVertex::persistentInput(PersistentIStream & is, int) { is >> lambda_ >> stop_ >> sbot_ >> stau_; } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigRPVLQDVertex("Herwig::RPVLQDVertex", "HwSusy.so HwRPV.so"); void RPVLQDVertex::Init() { static ClassDocumentation documentation ("The RPVLQDVertex class implements the trilinear LQD" " coupling in R-parity violating models."); } void RPVLQDVertex::doinit() { RPVPtr rpv = dynamic_ptr_cast(generator()->standardModel()); if(!rpv) throw InitException() << "Must have the RPV model in" << " RPVLQDVertex::doinit()" << Exception::abortnow; // get the coupling lambda_ = rpv->lambdaLQD(); stop_ = rpv->stopMix(); sbot_ = rpv->sbottomMix(); stau_ = rpv->stauMix(); // set the particles in the vertex if coupling non-zero for( int i=0;i<3;++i) { for( int j=0; j<3; ++j) { for( int k=0; k<3; ++k) { // continue if zero if(lambda_[i][j][k]==0.) continue; // particles in the vertex // sneutrino addToList( -2*j-1 , 2*k+1 , -1000012-2*i ); addToList( 2*j+1 , -2*k-1 , 1000012+2*i ); // left slepton addToList( -2*j-2 , 2*k+1 , -1000011-2*i ); addToList( 2*j+2 , -2*k-1 , +1000011+2*i ); if(i==2) { addToList( -2*j-2 , 2*k+1 , -2000011-2*i ); addToList( 2*j+2 , -2*k-1 , +2000011+2*i ); } // up squark addToList( -2*i-11, 2*k+1 , -1000002-2*j ); addToList( 2*i+11, -2*k-1 , 1000002+2*j ); if(j==2) { addToList( -2*i-11, 2*k+1 , -2000002-2*j ); addToList( 2*i+11, -2*k-1 , 2000002+2*j ); } // left down squark addToList( -2*i-12, 2*k+1 , -1000001-2*j ); addToList( 2*i+12, -2*k-1 , 1000001+2*j ); if(j==2) { addToList( -2*i-12, 2*k+1 , -2000001-2*j ); addToList( 2*i+12, -2*k-1 , 2000001+2*j ); } // right down squark addToList( 2*i+12, 2*j+1 , -2000001-2*k ); addToList( -2*i-12, -2*j-1 , +2000001+2*k ); if(k==2) { addToList( 2*i+12, 2*j+1 , -1000001-2*k ); addToList( -2*i-12, -2*j-1 , +1000001+2*k ); } addToList( 2*i+11, 2*j+2 , -2000001-2*k ); addToList( -2*i-11, -2*j-2 , +2000001+2*k ); if(k==2) { addToList( 2*i+11, 2*j+2 , -1000001-2*k ); addToList( -2*i-11, -2*j-2 , +1000001+2*k ); } } } } FFSVertex::doinit(); } void RPVLQDVertex::setCoupling(Energy2, tcPDPtr part1, tcPDPtr part2, tcPDPtr part3) { int islep = part3->id(); int i(-1),j(-1),k(-1); Complex mix(1.); // sneutrino case if( abs(islep) == ParticleID::SUSY_nu_eL || abs(islep) == ParticleID::SUSY_nu_muL || abs(islep) == ParticleID::SUSY_nu_tauL) { i = (abs(islep)-1000012)/2; j = (abs(part1->id())-1)/2; k = (abs(part2->id())-1)/2; if( islep*part1->id() <0 ) swap(j,k); if(islep>0) { left ( 0.); right(-1.); } else { left (-1.); right( 0.); } } else if(abs(islep) == ParticleID::SUSY_e_Lminus|| abs(islep) == ParticleID::SUSY_mu_Lminus|| abs(islep) == ParticleID::SUSY_tau_1minus|| abs(islep) == ParticleID::SUSY_tau_2minus) { if(abs(islep)<2000000) { i = (abs(islep)-1000011)/2; if(i==2) mix = (*stau_)(0,0); } else { i = 2; mix = (*stau_)(1,0); assert(abs(islep)==ParticleID::SUSY_tau_2minus); } if(abs(part1->id())%2==1) { j = (abs(part2->id())-2)/2; k = (abs(part1->id())-1)/2; } else { j = (abs(part1->id())-2)/2; k = (abs(part2->id())-1)/2; } if(islep<0) { left ( 1.); right( 0.); } else { left ( 0.); right( 1.); } } // left up squark else if(abs(islep) == ParticleID::SUSY_u_L || abs(islep) == ParticleID::SUSY_c_L || abs(islep) == ParticleID::SUSY_t_1 || abs(islep) == ParticleID::SUSY_t_2) { if(abs(islep)<2000000) { j = (abs(islep)-1000002)/2; if(j==2) mix = (*stop_)(0,0); } else { j = 2; mix = (*stop_)(1,0); assert(abs(islep)==ParticleID::SUSY_t_2); } if(part1->coloured()) { i = (abs(part2->id())-11)/2; k = (abs(part1->id())- 1)/2; } else { i = (abs(part1->id())-11)/2; k = (abs(part2->id())- 1)/2; } if(islep<0) { left ( 1.); right( 0.); } else { left ( 0.); right( 1.); } } else if(abs(islep) == ParticleID::SUSY_d_L || abs(islep) == ParticleID::SUSY_s_L || abs(islep) == ParticleID::SUSY_b_1 || abs(islep) == ParticleID::SUSY_b_2 || abs(islep) == ParticleID::SUSY_d_R || abs(islep) == ParticleID::SUSY_s_R) { // right down squark if(part1->id()*part2->id()>0) { if(part1->coloured()) { if(abs(part1->id())%2==1) { i = (abs(part2->id())-12)/2; j = (abs(part1->id())-1 )/2; mix *= -1.; assert(i>=0); } else { i = (abs(part2->id())-11)/2; j = (abs(part1->id())-2 )/2; assert(i>=0); } } else { if(abs(part2->id())%2==1) { i = (abs(part1->id())-12)/2; j = (abs(part2->id())-1 )/2; mix *= -1.; assert(i>=0); } else { i = (abs(part1->id())-11)/2; j = (abs(part2->id())-2 )/2; assert(i>=0); } } if(abs(islep)>2000000) { k = (abs(islep)-2000001)/2; if(k==2) mix *= (*sbot_)(1,1); } else { k = 2; mix *= (*sbot_)(0,1); assert(abs(islep)==ParticleID::SUSY_b_1); } if(islep<0) { left ( 0.); right( 1.); } else { left ( 1.); right( 0.); } } // left down squark else { if(abs(islep)<2000000) { j = (abs(islep)-1000001)/2; if(j==2) mix = (*sbot_)(0,0); } else { j = 2; mix = (*sbot_)(1,0); assert(abs(islep)==ParticleID::SUSY_b_2); } if(part1->coloured()) { i = (abs(part2->id())-12)/2; k = (abs(part1->id())- 1)/2; } else { i = (abs(part1->id())-12)/2; k = (abs(part2->id())- 1)/2; } if(islep<0) { left (-1.); right( 0.); } else { left ( 0.); right(-1.); } assert(i>=0); } } else assert(false); assert( i>=0 && i<=2 && j>=0 && j<=2 && k>=0 && k<=2 ); norm(mix*lambda_[i][j][k]); } diff --git a/Models/Susy/RPV/RPVSSSVertex.cc b/Models/Susy/RPV/RPVSSSVertex.cc --- a/Models/Susy/RPV/RPVSSSVertex.cc +++ b/Models/Susy/RPV/RPVSSSVertex.cc @@ -1,876 +1,877 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the RPVSSSVertex class. // #include "RPVSSSVertex.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include "RPV.h" #include using namespace Herwig; using namespace ThePEG::Helicity; RPVSSSVertex::RPVSSSVertex() : interactions_(0), q2Last_(ZERO), gLast_(0.) { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::SINGLET); } IBPtr RPVSSSVertex::clone() const { return new_ptr(*this); } IBPtr RPVSSSVertex::fullclone() const { return new_ptr(*this); } void RPVSSSVertex::persistentOutput(PersistentOStream & os) const { os << interactions_ << stau_ << sbottom_ << stop_ << ounit(scalarScalarScalar_,GeV) << ounit(scalarPseudoPseudo_,GeV) << ounit(scalarSup_,GeV) << ounit(scalarSdown_,GeV) << ounit(scalarSneutrino_,GeV) << ounit(scalarSlepton_,GeV) << ounit(chargedSquark_,GeV) << ounit(chargedSlepton_,GeV) << ounit(scalarChargedCharged_,GeV) << ounit(pseudoChargedCharged_,GeV) << ounit(pseudoSup_,GeV) << ounit(pseudoSdown_,GeV) << ounit(pseudoSlepton_,GeV); } void RPVSSSVertex::persistentInput(PersistentIStream & is, int) { is >> interactions_ >> stau_ >> sbottom_ >> stop_ >> iunit(scalarScalarScalar_,GeV) >> iunit(scalarPseudoPseudo_,GeV) >> iunit(scalarSup_,GeV) >> iunit(scalarSdown_,GeV) >> iunit(scalarSneutrino_,GeV) >> iunit(scalarSlepton_,GeV) >> iunit(chargedSquark_,GeV) >> iunit(chargedSlepton_,GeV) >> iunit(scalarChargedCharged_,GeV) >> iunit(pseudoChargedCharged_,GeV) >> iunit(pseudoSup_,GeV) >> iunit(pseudoSdown_,GeV) >> iunit(pseudoSlepton_,GeV); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigRPVSSSVertex("Herwig::RPVSSSVertex", "HwRPV.so"); void RPVSSSVertex::Init() { static ClassDocumentation documentation ("The RPVSSSVertex class implements the coupling of three" " scalar particles in the RPV model"); static Switch interfaceInteractions ("Interactions", "Which interactions to include", &RPVSSSVertex::interactions_, 0, false, false); static SwitchOption interfaceInteractionsAll (interfaceInteractions, "All", "Include both triple Higgs and Higgs sfermion interactions", 0); static SwitchOption interfaceInteractionsHiggsHiggsHiggs (interfaceInteractions, "HiggsHiggsHiggs", "Only include triple Higgs boson interactions", 1); static SwitchOption interfaceInteractionsHiggsSfermions (interfaceInteractions, "HiggsSfermions", "Only include Higgs sfermion interactions", 2); } void RPVSSSVertex::doinit() { // extract the model tRPVPtr model = dynamic_ptr_cast(generator()->standardModel()); if( !model ) throw InitException() << "RPVSSSVertex::doinit() - The" << " pointer to the RPV object is null!" << Exception::abortnow; // get the Higgs mixing matrices MixingMatrixPtr mixH = model->CPevenHiggsMix() ; MixingMatrixPtr mixP = model->CPoddHiggsMix() ; MixingMatrixPtr mixC = model->ChargedHiggsMix(); // find the codes for the Higgs bosons vector pseudo(1,36); vector scalar(2); vector charged(1,37); scalar[0] = 25; scalar[1] = 35; if(mixH&&mixH->size().first>2) { scalar.push_back(1000012); scalar.push_back(1000014); scalar.push_back(1000016); } if(mixP&&mixP->size().first>1) { pseudo.push_back(1000017); pseudo.push_back(1000018); pseudo.push_back(1000019); } if(mixC&&mixC->size().first>2) { charged.push_back(-1000011); charged.push_back(-1000013); charged.push_back(-1000015); charged.push_back(-2000011); charged.push_back(-2000013); charged.push_back(-2000015); } // triple Higgs interactions if(interactions_==0||interactions_==1) { // three neutral scalar bosons for(unsigned int i1=0;i11000000&&abs(charged[i3])>1000000&& abs(charged[i2])%1000000==abs(charged[i3])%1000000)) addToList(scalar[i1],charged[i2],-charged[i3]); } } } // one pseudo scalar two charged scalars if(charged.size()>1) { for(unsigned int i1=0;i11000000&&abs(charged[i3])>1000000&& abs(charged[i2])%1000000==abs(charged[i3])%1000000)) addToList(pseudo[i1],charged[i2],-charged[i3]); } } } } } // sfermion interactions if(interactions_==0||interactions_==2) { // scalar neutral higgs sfermion sfermion for(unsigned int i = 0; i < scalar.size(); ++i) { // squarks for(unsigned int j = 1; j < 7; ++j) { long lj = 1000000 + j; long rj = 2000000 + j; //LLbar addToList(scalar[i],lj,-lj); //RRbar addToList(scalar[i],rj,-rj); //LRbar addToList(scalar[i],lj,-rj); //RLbar addToList(scalar[i],rj,-lj); } // sleptons for(unsigned int j = 11; j < 17; ++j) { long lj = 1000000 + j; long rj = 2000000 + j; if( j % 2 != 0) { // LL addToList(scalar[i],lj,-lj); // RR addToList(scalar[i],rj,-rj); //LRbar addToList(scalar[i],lj,-rj); //RLbar addToList(scalar[i],rj,-lj); } // sneutrino only if no mixing else if(scalar.size()==2) { addToList(scalar[i],lj,-lj); } } } // pseudoscalar sfermion sfermion for(unsigned int i = 0; i < pseudo.size(); ++i) { // squarks for(unsigned int j = 1; j < 7; ++j) { long lj = 1000000 + j; long rj = 2000000 + j; //LRbar addToList(pseudo[i],lj,-rj); //RLbar addToList(pseudo[i],rj,-lj); } // sleptons if(scalar.size()==2) { for(unsigned int j = 11; j < 17; j += 2) { long lj = 1000000 + j; long rj = 2000000 + j; addToList(36,lj,-rj); addToList(36,rj,-lj); } } } //outgoing H+ for(unsigned int i=0;istopMix(); sbottom_ = model->sbottomMix(); if(!stop_ || !sbottom_) throw InitException() << "RPVSSSVertex::doinit() - " << "A mixing matrix pointer is null." << " stop: " << stop_ << " sbottom: " << sbottom_ << Exception::abortnow; stau_ = model->stauMix(); if(!stau_ && (!mixC || mixC->size().first<2)) throw InitException() << "RPVSSSVertex::doinit() either the stau" << " mixing matrix must be set or the stau" << " included in mixing with the" << " charged Higgs bosons" << Exception::abortnow; // couplings of the neutral Higgs bosons Energy mw = getParticleData(ParticleID::Wplus)->mass(); double sw = sqrt(sin2ThetaW()); double cw = sqrt(1.-sin2ThetaW()); // extract the vevs vector vnu = model->sneutrinoVEVs(); double g = electroMagneticCoupling(sqr(mw))/sw; Energy v = 2.*mw/g; double tanb = model->tanBeta(); vector vevs(5); vevs[0] = sqrt((sqr(v)-sqr(vnu[0])-sqr(vnu[1])-sqr(vnu[2]))/ (1.+sqr(tanb))); vevs[1] = vevs[0]*tanb; for(unsigned int ix=0;ix > > (scalar.size(),vector >(scalar.size(),complex(ZERO)))); double delta[5]={1.,-1.,1.,1.,1.}; if(vevs.size()>scalar.size()) vevs.resize(scalar.size()); for(unsigned int i1=0;i1 > > (pseudo.size(),vector >(pseudo.size(),complex(ZERO)))); for(unsigned int i1=0;i1muParameter(); vector eps = model->epsilon(); scalarChargedCharged_.resize(scalar.size(),vector > > (charged.size(),vector >(charged.size(),complex(ZERO)))); double yl[3] = {sqrt(2.)*getParticleData(11)->mass()/vevs[1], sqrt(2.)*getParticleData(13)->mass()/vevs[1], sqrt(2.)*getParticleData(15)->mass()/vevs[1]}; complex Al[3] = {complex(ZERO),complex(ZERO),yl[2]*model->tauTrilinear()}; for(unsigned int i1=0;i1 umdi = vevs[0]*(*mixH)(i1,0)-vevs[1]*(*mixH)(i1,1)+vevs[2]*(*mixH)(i1,2)+ vevs[3]*(*mixH)(i1,3)+vevs[4]*(*mixH)(i1,4); scalarChargedCharged_[i1][i2][i3] = // HH term 0.25*sqr(g)*(-vevs[1]*((*mixH)(i1,1)*((*mixC)(i2,1)*(*mixC)(i3,1)+(*mixC)(i2,2)*(*mixC)(i3,2))+ (*mixH)(i1,0)*((*mixC)(i2,2)*(*mixC)(i3,1)+(*mixC)(i2,1)*(*mixC)(i3,2))) -vevs[0]*((*mixH)(i1,0)*((*mixC)(i2,1)*(*mixC)(i3,1)+(*mixC)(i2,2)*(*mixC)(i3,2))+ (*mixH)(i1,1)*((*mixC)(i2,2)*(*mixC)(i3,1)+(*mixC)(i2,1)*(*mixC)(i3,2))) +(vevs[2]*(*mixH)(i1,2)+vevs[3]*(*mixH)(i1,3)+vevs[4]*(*mixH)(i1,4))* ((*mixC)(i2,1)*(*mixC)(i3,1)-(*mixC)(i2,2)*(*mixC)(i3,2)))- 0.25*sqr(gp)*((*mixC)(i2,1)*(*mixC)(i3,1)-(*mixC)(i2,2)*(*mixC)(i3,2))*umdi -0.5*(*mixC)(i2,1)*(*mixC)(i3,1)*(yl[0]*vevs[2]*(*mixH)(i1,2)+yl[1]*vevs[3]*(*mixH)(i1,3)+yl[2]*vevs[4]*(*mixH)(i1,4)) // LL term +0.25*(sqr(g)-sqr(gp))*umdi*((*mixC)(i2,2)*(*mixC)(i3,2)+(*mixC)(i2,3)*(*mixC)(i3,3)+(*mixC)(i2,4)*(*mixC)(i3,4)) -vevs[0]*(*mixH)(i1,1)*(yl[0]*(*mixC)(i2,2)*(*mixC)(i3,2)+yl[1]*(*mixC)(i2,3)*(*mixC)(i3,3)+yl[2]*(*mixC)(i2,4)*(*mixC)(i3,4)) -0.25*sqr(g)*((vevs[2]*(*mixC)(i3,2)+vevs[3]*(*mixC)(i3,3)+vevs[4]*(*mixC)(i3,4))* ((*mixH)(i1,2)*(*mixC)(i2,2)+(*mixH)(i1,3)*(*mixC)(i2,3)+(*mixH)(i1,4)*(*mixC)(i2,4))+ (vevs[2]*(*mixC)(i2,2)+vevs[3]*(*mixC)(i2,3)+vevs[4]*(*mixC)(i2,4))* ((*mixH)(i1,2)*(*mixC)(i3,2)+(*mixH)(i1,3)*(*mixC)(i3,3)+(*mixH)(i1,4)*(*mixC)(i3,4))) // RR term +0.5*sqr(gp)*umdi*((*mixC)(i2,5)*(*mixC)(i3,5)+(*mixC)(i2,6)*(*mixC)(i3,6)+(*mixC)(i2,7)*(*mixC)(i3,7)) -vevs[0]*(*mixH)(i1,1)*(yl[0]*(*mixC)(i2,5)*(*mixC)(i3,5)+yl[1]*(*mixC)(i2,6)*(*mixC)(i3,6)+yl[2]*(*mixC)(i2,7)*(*mixC)(i3,7)) -0.5*((vevs[2]*yl[0]*(*mixC)(i2,5)+vevs[3]*yl[1]*(*mixC)(i2,6)+vevs[4]*yl[2]*(*mixC)(i2,7))* (yl[0]*(*mixH)(i1,2)*(*mixC)(i3,5)+yl[1]*(*mixH)(i1,3)*(*mixC)(i3,6)+yl[2]*(*mixH)(i1,4)*(*mixC)(i3,7))+ (vevs[2]*yl[0]*(*mixC)(i3,5)+vevs[3]*yl[1]*(*mixC)(i3,6)+vevs[4]*yl[2]*(*mixC)(i3,7))* (yl[0]*(*mixH)(i1,2)*(*mixC)(i2,5)+yl[1]*(*mixH)(i1,3)*(*mixC)(i2,6)+yl[2]*(*mixH)(i1,4)*(*mixC)(i2,7))) // LR -(*mixH)(i1,1)/sqrt(2.)*(Al[0]*(*mixC)(i2,2)*(*mixC)(i3,2)+Al[1]*(*mixC)(i2,3)*(*mixC)(i3,3)+Al[2]*(*mixC)(i2,4)*(*mixC)(i3,4)) +(*mixH)(i1,2)/sqrt(2.)*mu*(yl[0]*(*mixC)(i2,2)*(*mixC)(i3,2)+yl[1]*(*mixC)(i2,3)*(*mixC)(i3,3)+yl[2]*(*mixC)(i2,4)*(*mixC)(i3,4)) // RL -(*mixH)(i1,1)/sqrt(2.)*(Al[0]*(*mixC)(i3,2)*(*mixC)(i2,2)+Al[1]*(*mixC)(i3,3)*(*mixC)(i2,3)+Al[2]*(*mixC)(i3,4)*(*mixC)(i2,4)) +(*mixH)(i1,2)/sqrt(2.)*mu*(yl[0]*(*mixC)(i3,2)*(*mixC)(i2,2)+yl[1]*(*mixC)(i3,3)*(*mixC)(i2,3)+yl[2]*(*mixC)(i3,4)*(*mixC)(i2,4)) // HL -0.25*sqr(g)*(((*mixH)(i1,2)*(*mixC)(i3,2)+(*mixH)(i1,3)*(*mixC)(i3,3)+(*mixH)(i1,4)*(*mixC)(i3,4))* (vevs[0]*(*mixC)(i2,0)+vevs[1]*(*mixC)(i2,1)) +(vevs[2]*(*mixC)(i3,2)+vevs[3]*(*mixC)(i3,3)+vevs[4]*(*mixC)(i3,4))* ((*mixH)(i1,0)*(*mixC)(i2,0)+(*mixH)(i1,1)*(*mixC)(i2,1))) +0.5*(*mixH)(i1,0)*(*mixC)(i2,0)* (sqr(yl[0])*vevs[2]*(*mixC)(i3,2)+sqr(yl[1])*vevs[3]*(*mixC)(i3,3)+sqr(yl[2])*vevs[4]*(*mixC)(i3,4)) +0.5*vevs[0]*(*mixC)(i2,0)*(sqr(yl[0])*(*mixH)(i1,2)*(*mixC)(i3,2)+ sqr(yl[1])*(*mixH)(i1,3)*(*mixC)(i3,3)+ sqr(yl[2])*(*mixH)(i1,4)*(*mixC)(i3,4)) // LH -0.25*sqr(g)*(((*mixH)(i1,2)*(*mixC)(i2,2)+(*mixH)(i1,3)*(*mixC)(i2,3)+(*mixH)(i1,4)*(*mixC)(i2,4))* (vevs[0]*(*mixC)(i3,0)+vevs[1]*(*mixC)(i3,1)) +(vevs[2]*(*mixC)(i2,2)+vevs[3]*(*mixC)(i2,3)+vevs[4]*(*mixC)(i2,4))* ((*mixH)(i1,0)*(*mixC)(i3,0)+(*mixH)(i1,1)*(*mixC)(i3,1))) +0.5*(*mixH)(i1,0)*(*mixC)(i3,0)* (sqr(yl[0])*vevs[2]*(*mixC)(i2,2)+sqr(yl[1])*vevs[3]*(*mixC)(i2,3)+sqr(yl[2])*vevs[4]*(*mixC)(i2,4)) +0.5*vevs[0]*(*mixC)(i3,0)*(sqr(yl[0])*(*mixH)(i1,2)*(*mixC)(i2,2)+ sqr(yl[1])*(*mixH)(i1,3)*(*mixC)(i2,3)+ sqr(yl[2])*(*mixH)(i1,4)*(*mixC)(i2,4)) // HR +sqrt(0.5)*(eps[0]*yl[0]*(*mixC)(i3,5)+eps[1]*yl[1]*(*mixC)(i3,6)+eps[2]*yl[2]*(*mixC)(i3,7))* ((*mixH)(i1,0)*(*mixC)(i2,1)+(*mixH)(i1,1)*(*mixC)(i2,0)) +sqrt(0.5)*(*mixC)(i2,0)*(Al[0]*(*mixH)(i1,2)*(*mixC)(i3,5)+ Al[1]*(*mixH)(i1,2)*(*mixC)(i3,6)+Al[2]*(*mixH)(i1,2)*(*mixC)(i3,7)) +sqrt(0.5)*mu*(*mixC)(i2,1)*(yl[0]*(*mixH)(i1,2)*(*mixC)(i3,5)+ yl[1]*(*mixH)(i1,3)*(*mixC)(i3,6)+ yl[2]*(*mixH)(i1,4)*(*mixC)(i3,7)) // RH +sqrt(0.5)*(eps[0]*yl[0]*(*mixC)(i2,5)+eps[1]*yl[1]*(*mixC)(i2,6)+eps[2]*yl[2]*(*mixC)(i2,7))* ((*mixH)(i1,0)*(*mixC)(i3,1)+(*mixH)(i1,1)*(*mixC)(i3,0)) +sqrt(0.5)*(*mixC)(i3,0)*(Al[0]*(*mixH)(i1,2)*(*mixC)(i2,5)+ Al[1]*(*mixH)(i1,2)*(*mixC)(i2,6)+Al[2]*(*mixH)(i1,2)*(*mixC)(i2,7)) +sqrt(0.5)*mu*(*mixC)(i3,1)*(yl[0]*(*mixH)(i1,2)*(*mixC)(i2,5)+ yl[1]*(*mixH)(i1,3)*(*mixC)(i2,6)+ yl[2]*(*mixH)(i1,4)*(*mixC)(i2,7)); // normalization scalarChargedCharged_[i1][i2][i3] /= g; } } } // coupling of the pseudoscalar Higgs to two charged Higgs bosons pseudoChargedCharged_.resize(pseudo.size(),vector > > (charged.size(),vector >(charged.size(),complex(ZERO)))); if(charged.size()<5) { for(unsigned int i1=0;i1 > > > (3,vector > >(2,vector >(2,complex(ZERO))))); for(unsigned int iq=0;iq<3;++iq) { double y = sqrt(2.)*getParticleData(2*long(iq+1))->mass()/vevs[1]; complex A = iq!=2 ? complex(ZERO) : y*model->topTrilinear(); Complex mixing[2][2]; if(iq!=2) { mixing[0][0] = 1.; mixing[0][1] = 0.; mixing[1][0] = 0.; mixing[1][1] = 1.; } else { mixing[0][0] = (*stop_)(0,0); mixing[0][1] = (*stop_)(0,1); mixing[1][0] = (*stop_)(1,0); mixing[1][1] = (*stop_)(1,1); } // loop over Higgs for(unsigned int ix=0;ix<2;++ix) { for(unsigned int iy=0;iy<2;++iy) { for(unsigned int ih=0;ih factors[5]; for(unsigned int iz=0;iz<5;++iz) factors[iz] = delta[iz]*vevs[iz]*(LL1+RR1); factors[0] += y/sqrt(2.)*mu*( mixing[ix][0]*conj(mixing[iy][1]) + mixing[ix][1]*conj(mixing[iy][0]) ); factors[1] += -vevs[1]*sqr(y)*( mixing[ix][0]*conj(mixing[iy][0]) + mixing[ix][1]*conj(mixing[iy][1]) ) -A/sqrt(2.)*(mixing[ix][0]*conj(mixing[iy][1]) + mixing[ix][1]*conj(mixing[iy][0])); for(unsigned int iz=0;iz<3;++iz) { factors[iz+2] += -y*eps[iz]/sqrt(2.)*( mixing[ix][0]*conj(mixing[iy][1]) + mixing[ix][1]*conj(mixing[iy][0]) ); } for(unsigned int iz=0;iz >(3,complex(ZERO))); for(unsigned int iq=0;iq<3;++iq) { double y = sqrt(2.)*getParticleData(2*long(iq+1))->mass()/vevs[1]; complex A = iq!=2 ? complex(ZERO) : y*model->topTrilinear(); // loop over Higgs for(unsigned int ih=0;ih > > > (3,vector > >(2,vector >(2,complex(ZERO))))); for(unsigned int iq=0;iq<3;++iq) { double y = sqrt(2.)*getParticleData(2*long(iq+1)-1)->mass()/vevs[0]; Complex mixing[2][2]; complex A = iq!=2 ? complex(ZERO) : y*model->bottomTrilinear(); if(iq!=2) { mixing[0][0] = 1.; mixing[0][1] = 0.; mixing[1][0] = 0.; mixing[1][1] = 1.; } else { mixing[0][0] = (*sbottom_)(0,0); mixing[0][1] = (*sbottom_)(0,1); mixing[1][0] = (*sbottom_)(1,0); mixing[1][1] = (*sbottom_)(1,1); } for(unsigned int ix=0;ix<2;++ix) { for(unsigned int iy=0;iy<2;++iy) { for(unsigned int ih=0;ih factors[5]; for(unsigned int iz=0;iz<5;++iz) factors[iz] = delta[iz]*vevs[iz]*(LL1+RR1); factors[0] += -vevs[0]*sqr(y)*(mixing[ix][0]*conj(mixing[iy][0])+ mixing[ix][1]*conj(mixing[iy][1])) - A/sqrt(2.)*(mixing[ix][0]*conj(mixing[iy][1])+ mixing[ix][1]*conj(mixing[iy][0])); factors[1] += y/sqrt(2.)*mu*(mixing[ix][0]*conj(mixing[iy][1])+ mixing[ix][1]*conj(mixing[iy][0])); for(unsigned int iz=0;iz >(3,complex(ZERO))); for(unsigned int iq=0;iq<3;++iq) { double y = sqrt(2.)*getParticleData(2*long(iq+1)-1)->mass()/vevs[0]; complex A = iq!=2 ? complex(ZERO) : y*model->bottomTrilinear(); for(unsigned int ih=0;ih >(3,complex(ZERO))); for(unsigned int il=0;il<3;++il) { // loop over Higgs for(unsigned int ih=0;ih factors[5]; for(unsigned int iz=0;iz<5;++iz) factors[iz] = delta[iz]*vevs[iz]*LL1; for(unsigned int iz=0;iz > > > (3,vector > >(2,vector >(2,complex(ZERO))))); for(unsigned int il=0;il<3;++il) { double y = sqrt(2.)*getParticleData(2*long(il+6)-1)->mass()/vevs[0]; Complex mixing[2][2]; complex A = il!=2 ? complex(ZERO) : y*model->tauTrilinear(); if(il!=2) { mixing[0][0] = 1.; mixing[0][1] = 0.; mixing[1][0] = 0.; mixing[1][1] = 1.; } else { mixing[0][0] = (*stau_)(0,0); mixing[0][1] = (*stau_)(0,1); mixing[1][0] = (*stau_)(1,0); mixing[1][1] = (*stau_)(1,1); } for(unsigned int ix=0;ix<2;++ix) { for(unsigned int iy=0;iy<2;++iy) { for(unsigned int ih=0;ih factors[5]; for(unsigned int iz=0;iz<5;++iz) factors[iz] = delta[iz]*vevs[iz]*(LL1+RR1); factors[0] += -vevs[0]*sqr(y)*(mixing[ix][0]*conj(mixing[iy][0])+ mixing[ix][1]*conj(mixing[iy][1])) - A/sqrt(2.)*(mixing[ix][0]*conj(mixing[iy][1])+ mixing[ix][1]*conj(mixing[iy][0])); factors[1] += y/sqrt(2.)*mu*(mixing[ix][0]*conj(mixing[iy][1])+ mixing[ix][1]*conj(mixing[iy][0])); for(unsigned int iz=0;iz >(3,complex(ZERO))); for(unsigned int il=0;il<3;++il) { double y = sqrt(2.)*getParticleData(2*long(il+6)-1)->mass()/vevs[0]; complex A = il!=2 ? complex(ZERO) : y*model->tauTrilinear(); for(unsigned int ih=0;ih > > > (3,vector > >(2,vector >(2,complex(ZERO))))); for(unsigned int iq=0;iq<3;++iq) { double yd = sqrt(2.)*getParticleData(2*long(iq+1)-1)->mass()/vevs[0]; double yu = sqrt(2.)*getParticleData(2*long(iq+1))->mass()/vevs[1]; Complex mixd[2][2],mixu[2][2]; complex Ad = iq!=2 ? complex(ZERO) : yd*model->bottomTrilinear(); complex Au = iq!=2 ? complex(ZERO) : yu*model->topTrilinear(); if(iq!=2) { mixd[0][0] = mixu[0][0] = 1.; mixd[0][1] = mixu[0][1] = 0.; mixd[1][0] = mixu[1][0] = 0.; mixd[1][1] = mixu[1][1] = 1.; } else { mixd[0][0] = (*sbottom_)(0,0); mixd[0][1] = (*sbottom_)(0,1); mixd[1][0] = (*sbottom_)(1,0); mixd[1][1] = (*sbottom_)(1,1); mixu[0][0] = (*stop_)(0,0); mixu[0][1] = (*stop_)(0,1); mixu[1][0] = (*stop_)(1,0); mixu[1][1] = (*stop_)(1,1); } for(unsigned int ih=0;ih LL(ZERO); for(unsigned int iz=0;iz RR = yu*yd*(vevs[1]*(*mixC)(ih,0) + vevs[0]*(*mixC)(ih,1))/sqrt(2.); complex LR = (*mixC)(ih,0)*Ad+(*mixC)(ih,1)*yd*mu; complex RL = yu*mu*(*mixC)(ih,0) + Au*(*mixC)(ih,1); chargedSquark_[ih][iq][ix][iy] = mixu[ix][0]*mixd[iy][0]*LL + mixu[ix][1]*mixd[iy][1]*RR + mixu[ix][0]*mixd[iy][1]*LR + mixu[ix][1]*mixd[iy][0]*RL; chargedSquark_[ih][iq][ix][iy] /=g; } } } } // charged Higgs slepton if(charged.size()==1) { chargedSlepton_.resize(charged.size(),vector > > (3,vector >(2,complex(ZERO)))); for(unsigned int il=0;il<3;++il) { double y = sqrt(2.)*getParticleData(2*long(il+6)-1)->mass()/vevs[0]; Complex mixd[2][2]; complex Al = il!=2 ? complex(ZERO) : y*model->tauTrilinear(); if(il!=2) { mixd[0][0] = 1.; mixd[0][1] = 0.; mixd[1][0] = 0.; mixd[1][1] = 1.; } else { mixd[0][0] = (*stau_)(0,0); mixd[0][1] = (*stau_)(0,1); mixd[1][0] = (*stau_)(1,0); mixd[1][1] = (*stau_)(1,1); } for(unsigned int ih=0;ih LL(ZERO); for(unsigned int iz=0;iz LR = (*mixC)(ih,0)*Al+(*mixC)(ih,1)*y*mu; chargedSlepton_[ih][il][ix] = mixd[ix][0]*LL + mixd[ix][1]*LR; chargedSlepton_[ih][il][ix] /=g; } } } } } namespace { int scalarEigenState(long id) { if(id<1000000) return (id-25)/10; else return (id-1000008)/2; } int pseudoEigenState(long id) { if(id<1000000) return 0; else return (id-1000016); } int chargedEigenState(long id) { if(abs(id)<1000000) return 0; else if(abs(id)<2000000) return (abs(id)-1000009)/2; else return (abs(id)-2000003)/2; } } void RPVSSSVertex::setCoupling(Energy2 q2, tcPDPtr part1, tcPDPtr part2,tcPDPtr part3) { // prefactor if( q2 != q2Last_ || gLast_==0. ) { q2Last_ = q2; gLast_ = weakCoupling(q2); } // some ordering of the particles // sort in order of PDG codes, smallest first if(abs(part1->id())>abs(part2->id())) swap(part1,part2); if(abs(part1->id())>abs(part3->id())) swap(part1,part3); if(abs(part2->id())>abs(part3->id())) swap(part2,part3); // make sure squarks 2nd and 3rd if(abs(part1->id())%1000000<=6) swap(part1,part2); if(abs(part1->id())%1000000<=6) swap(part1,part3); // extract particle ids long sca1(part1->id()), sca2(part2->id()), sca3(part3->id()); // Higgs squark couplings if(abs(sca2)%1000000<=6) { // charged Higgs if( part1->charged() ) { int ih = chargedEigenState(sca1); if(abs(sca2)%2!=0) swap(sca2,sca3); unsigned int alpha = abs(sca2)/1000000-1; unsigned int beta = abs(sca3)/1000000-1; unsigned int iq = (abs(sca2)%1000000-2)/2; norm(gLast_*chargedSquark_[ih][iq][alpha][beta]*UnitRemoval::InvE); return; } // neutral Higgs else { long sm(0); // get the left/right light/heavy state unsigned int alpha(abs(sca2)/1000000 - 1), beta(abs(sca3)/1000000 - 1); sm = abs(sca2)%1000000; bool pseudo = sca1==36 || (sca1>=1000017&&sca1<=1000019); int higgs = pseudo ? pseudoEigenState(sca1) : scalarEigenState(sca1); complex coup; if(!pseudo) { if( sm % 2 == 0 ) { coup = scalarSup_ [higgs][(sm-2)/2][alpha][beta]; } else { coup = scalarSdown_[higgs][(sm-1)/2][alpha][beta]; } } else { if( sm % 2 == 0 ) { coup = pseudoSup_ [higgs][(sm-2)/2]; } else { coup = pseudoSdown_[higgs][(sm-1)/2]; } if((alpha==1&&sca2<0)||(beta==1&&sca3<0)) coup *=-1.; } // set coupling and return norm(gLast_*coup*UnitRemoval::InvE); return; } } // all neutral else if(!part1->charged()&&!part2->charged()&&!part3->charged()) { // neutral Higgs sneutrino if(scalarScalarScalar_.size()==2&&abs(sca2)>1000000) { assert(!(sca1==36 || (sca1>=1000017&&sca1<=1000019))); int il = (abs(sca2)-1000012)/2; norm(gLast_*scalarSneutrino_[scalarEigenState(sca1)][il]*UnitRemoval::InvE); return; } else { if(sca1==36 || (sca1>=1000017&&sca2<=1000019)) swap(sca1,sca2); if(sca1==36 || (sca1>=1000017&&sca2<=1000019)) swap(sca1,sca3); // 2 pseudoscalar 1 scale if(sca2==36 || (sca2>=1000017&&sca2<=1000019)) { norm(gLast_*scalarPseudoPseudo_[scalarEigenState(sca1)] [pseudoEigenState(sca2)][pseudoEigenState(sca3)]*UnitRemoval::InvE); return; } // 3 scalars else { norm(gLast_*scalarScalarScalar_[scalarEigenState(sca1)] [scalarEigenState(sca2)][scalarEigenState(sca3)]*UnitRemoval::InvE); return; } } } // two charged else { // put the charged last if(!part2->charged()) { swap(part1,part2); swap(sca1 ,sca2 ); } if(!part3->charged()) { swap(part1,part3); swap(sca1 ,sca3 ); } // sleptons if(scalarChargedCharged_[0].size()<5&&abs(sca2)>1000000) { // neutral Higgs charged sleptons if((abs(sca2)>=1000011&&abs(sca2)<=1000015&&abs(sca2)%2!=0)&& (abs(sca3)>=1000011&&abs(sca3)<=1000015&&abs(sca3)%2!=0)) { long sm(0); // get the left/right light/heavy state unsigned int alpha(abs(sca2)/1000000 - 1), beta(abs(sca3)/1000000 - 1); sm = (abs(sca2)%1000000-11)/2; bool pseudo = sca1==36 || (sca1>=1000017&&sca1<=1000019); int higgs = pseudo ? pseudoEigenState(sca1) : scalarEigenState(sca1); complex coup; if(!pseudo) { coup = scalarSlepton_[higgs][(sm-1)/2][alpha][beta]; } else { coup = pseudoSlepton_[higgs][(sm-1)/2]; if((alpha==1&&sca2<0)||(beta==1&&sca3<0)) coup *=-1.; } // set coupling and return norm(gLast_*coup*UnitRemoval::InvE); return; } // charged Higgs else { if(abs(sca2)<1000000) { swap(part1,part2); swap(sca1 ,sca2 ); } if(abs(sca3)<1000000) { swap(part1,part3); swap(sca1 ,sca3 ); } if(part3->charged()) { swap(part2,part3); swap(sca2 ,sca3 ); } unsigned int il = (abs(sca2)%1000000-11)/2; unsigned int alpha = abs(sca2)/1000000-1; norm(gLast_*chargedSlepton_[chargedEigenState(sca1)][il][alpha]*UnitRemoval::InvE); } } else { // pseudoscalar charged charged if(sca1==36 || (sca1>=1000017&&sca1<=1000019)) { if(sca2>0) swap(sca2,sca3); norm(gLast_*pseudoChargedCharged_[pseudoEigenState(sca1)] [chargedEigenState(sca2)][chargedEigenState(sca3)]*UnitRemoval::InvE); } // scalar charged charged else { norm(gLast_*scalarChargedCharged_[scalarEigenState(sca1)] [chargedEigenState(sca2)][chargedEigenState(sca3)]*UnitRemoval::InvE); } } return; } } diff --git a/Models/Susy/RPV/RPVUDDVertex.cc b/Models/Susy/RPV/RPVUDDVertex.cc --- a/Models/Susy/RPV/RPVUDDVertex.cc +++ b/Models/Susy/RPV/RPVUDDVertex.cc @@ -1,149 +1,150 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the UDDVertex class. // #include "RPVUDDVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; RPVUDDVertex::RPVUDDVertex() { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::EPS); } IBPtr RPVUDDVertex::clone() const { return new_ptr(*this); } IBPtr RPVUDDVertex::fullclone() const { return new_ptr(*this); } void RPVUDDVertex::persistentOutput(PersistentOStream & os) const { os << lambda_ << stop_ << sbot_; } void RPVUDDVertex::persistentInput(PersistentIStream & is, int) { is >> lambda_ >> stop_ >> sbot_; } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigRPVUDDVertex("Herwig::RPVUDDVertex", "HwSusy.so HwRPV.so"); void RPVUDDVertex::Init() { static ClassDocumentation documentation ("The RPVUDDVertex class implements the trilinear UDD" " coupling in R-parity violating models."); } void RPVUDDVertex::doinit() { RPVPtr rpv = dynamic_ptr_cast(generator()->standardModel()); if(!rpv) throw InitException() << "Must have the RPV model in" << " RPVUDDVertex::doinit()" << Exception::abortnow; // get the coupling lambda_ = rpv->lambdaUDD(); stop_ = rpv->stopMix(); sbot_ = rpv->sbottomMix(); // set the particles in the vertex if coupling non-zero for( int i=0;i<3;++i) { for( int j=0; j<3; ++j) { for( int k=0; k<3; ++k) { // continue if zero if(lambda_[i][j][k]==0.) continue; // particles in the vertex // right up squark if(jid(); int i(-1),j(-1),k(-1); Complex mix(1.); // left up squark if(abs(islep) == ParticleID::SUSY_u_R || abs(islep) == ParticleID::SUSY_c_R || abs(islep) == ParticleID::SUSY_t_1 || abs(islep) == ParticleID::SUSY_t_2) { if(abs(islep)>2000000) { i = (abs(islep)-2000002)/2; if(i==2) mix = (*stop_)(1,1); } else { i = 2; mix = (*stop_)(0,1); assert(abs(islep)==ParticleID::SUSY_t_1); } j = (abs(part1->id())- 1)/2; k = (abs(part2->id())- 1)/2; } else if(abs(islep) == ParticleID::SUSY_d_R || abs(islep) == ParticleID::SUSY_s_R || abs(islep) == ParticleID::SUSY_b_1 || abs(islep) == ParticleID::SUSY_b_2) { if(abs(islep)>2000000) { k = (abs(islep)-2000001)/2; if(k==2) mix = (*sbot_)(1,1); } else { k = 2; mix = (*sbot_)(0,1); assert(abs(islep)==ParticleID::SUSY_b_1); } if(abs(part1->id())%2==0) { i = (abs(part1->id())- 2)/2; j = (abs(part2->id())- 1)/2; } else { i = (abs(part2->id())- 2)/2; j = (abs(part1->id())- 1)/2; // mix *= -1.; } } else assert(false); assert( i>=0 && i<=2 && j>=0 && j<=2 && k>=0 && k<=2 ); if(islep>0) { left (1.); right(0.); } else { left (0.); right(1.); } norm(mix*lambda_[i][j][k]); } diff --git a/Models/Susy/RPV/RPVWSSVertex.cc b/Models/Susy/RPV/RPVWSSVertex.cc --- a/Models/Susy/RPV/RPVWSSVertex.cc +++ b/Models/Susy/RPV/RPVWSSVertex.cc @@ -1,439 +1,440 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the RPVWSSVertex class. // #include "RPVWSSVertex.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "RPV.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; RPVWSSVertex::RPVWSSVertex() :_sw(0.), _cw(0.), _s2w(0.), _c2w(0.), _interactions(0), _q2last(), _ulast(0), _dlast(0), _gblast(0), _factlast(0.), _couplast(0.) { orderInGs(0); orderInGem(1); + colourStructure(ColourStructure::DELTA); } IBPtr RPVWSSVertex::clone() const { return new_ptr(*this); } IBPtr RPVWSSVertex::fullclone() const { return new_ptr(*this); } void RPVWSSVertex::doinit() { // extract the model tRPVPtr model = dynamic_ptr_cast(generator()->standardModel()); if( !model ) throw InitException() << "RPVWSSVertex::doinit() - The" << " pointer to the RPV object is null!" << Exception::abortnow; // get the mixing matrices MixingMatrixPtr mixH = model->CPevenHiggsMix() ; MixingMatrixPtr mixP = model->CPoddHiggsMix() ; MixingMatrixPtr mixC = model->ChargedHiggsMix(); // find the codes for the Higgs bosons vector pseudo(1,36); vector scalar(2); vector charged(1,37); scalar[0] = 25; scalar[1] = 35; if(mixH&&mixH->size().first>2) { scalar.push_back(1000012); scalar.push_back(1000014); scalar.push_back(1000016); } if(mixP&&mixP->size().first>1) { pseudo.push_back(1000017); pseudo.push_back(1000018); pseudo.push_back(1000019); } if(mixC&&mixC->size().first>2) { charged.push_back(-1000011); charged.push_back(-1000013); charged.push_back(-1000015); charged.push_back(-2000011); charged.push_back(-2000013); charged.push_back(-2000015); } // sfermion interactions if(_interactions==0||_interactions==1) { // squarks //W- //LL-squarks for(long ix=1000001;ix<1000006;ix+=2) { addToList(-24,ix+1,-ix); } //1-2 stop sbottom addToList(-24,1000006,-2000005); //2-1 stop sbottom addToList(-24,2000006,-1000005); //2-2 stop sbottom addToList(-24,2000006,-2000005); //W+ for(long ix=1000001;ix<1000006;ix+=2) { addToList(24,-(ix+1),ix); } //1-2 stop sbottom addToList(24,-1000006,2000005); //2-1 stop sbottom addToList(24,-2000006,1000005); //2-2 stop sbottom addToList(24,-2000006,2000005); //LL squarks for(long ix=1000001;ix<1000007;++ix) { addToList(23,ix,-ix); } //RR squarks for(long ix=2000001;ix<2000007;++ix) { addToList(23,ix,-ix); } //L-Rbar stop addToList(23,1000006,-2000006); //Lbar-R stop addToList(23,-1000006,2000006); //L-Rbar sbottom addToList(23,1000005,-2000005); //Lbar-R sbottom addToList(23,-1000005,2000005); // gamma //squarks for(long ix=1000001;ix<1000007;++ix) { addToList(22,ix,-ix); } for(long ix=2000001;ix<2000007;++ix) { addToList(22,ix,-ix); } //sleptons // gamma for(long ix=1000011;ix<1000016;ix+=2) { addToList(22,ix,-ix); } for(long ix=2000011;ix<2000016;ix+=2) { addToList(22,ix,-ix); } // Z //LL-sleptons for(long ix=1000011;ix<1000017;ix+=2) { addToList(23,ix,-ix); } // RR-sleptons for(long ix=2000011;ix<2000016;ix+=2) { addToList(23,ix,-ix); } //L-Rbar stau addToList(23,1000015,-2000015); //Lbar-R stau addToList(23,-1000015,2000015); if(!(mixH&&mixH->size().first>2)) { for(long ix=1000012;ix<1000017;ix+=2) { // sneutrinos addToList(23,ix,-ix); } //LL-sleptons for(long ix=1000011;ix<1000016;ix+=2) { addToList(-24,-ix,ix+1); } //2-L stau addToList(-24,-2000015,1000016); //LL-sleptons for(long ix=1000011;ix<1000016;ix+=2) { addToList(24,ix,-ix-1); } //2-L stau addToList(24,2000015,-1000016); } } if(_interactions==0||_interactions==2) { // charged Higgs and photon addToList(22,37,-37); // charged Higgs and Z for(unsigned int ix=0;ix1000000&&abs(charged[iy])>100000 && ( charged[ix]==charged[iy] || (abs(charged[ix])%1000000==15&&abs(charged[iy])%1000000==15))) continue; addToList(23,charged[ix],-charged[iy]); } } // neutral Higgs and Z for(unsigned int ix=0;ixstopMix(); _sbottom = model->sbottomMix(); if(!_stop || !_sbottom) throw InitException() << "RPVWSSVertex::doinit() - " << "A mixing matrix pointer is null." << " stop: " << _stop << " sbottom: " << _sbottom << Exception::abortnow; _stau = model->stauMix(); if(!_stau && (!mixC || mixC->size().first<2)) throw InitException() << "RPVWSSVertex::doinit() either the stau" << " mixing matrix must be set or the stau" << " included in mixing with the" << " charged Higgs bosons" << Exception::abortnow; // weak mixing _sw = sqrt(sin2ThetaW()); _cw = sqrt( 1. - sin2ThetaW() ); _s2w = 2.*_cw*_sw; _c2w = 1. - 2.*sin2ThetaW(); // Coupling of Z to scalar and pseudoscalar Cijeo_.resize(pseudo.size(),vector(scalar.size(),0.)); for(unsigned int i=0;isize().second;++ix) { double sign = ix!=1 ? 1. : -1.; Cijeo_[i][j] += sign*(*mixP)(i,ix)*(*mixH)(j,ix); } } } // Coupling of W to scalar charged Cijec_.resize(scalar.size(),vector(charged.size(),0.)); for(unsigned int i=0;isize().second;++ix) { double sign = ix!=1 ? 1. : -1.; Cijec_[i][j] += sign*(*mixH)(i,ix)*(*mixC)(j,ix); } } } // Coupling of W to pseudopseudo charged Cijco_.resize(pseudo.size(),vector(charged.size(),0.)); for(unsigned int i=0;isize().second;++ix) { // not sure about this need it to get agreement with SPheno //double sign = ix!=1 ? 1. : -1.; double sign = 1.; Cijco_[i][j] += sign*(*mixP)(i,ix)*(*mixC)(j,ix); } } } // Coupling of Z to charged Higgs Cijc_.resize(charged.size(),vector(charged.size(),0.)); for(unsigned int i=0;isize().second;++ix) { Cijc_[i][j] += (*mixC)(i,ix)*(*mixC)(j,ix); } } } } void RPVWSSVertex::persistentOutput(PersistentOStream & os) const { os << _interactions << _sw << _cw << _stau << _stop << _sbottom << _s2w << _c2w << Cijeo_ << Cijec_ << Cijco_ << Cijc_; } void RPVWSSVertex::persistentInput(PersistentIStream & is, int) { is >> _interactions >> _sw >> _cw >> _stau >> _stop >> _sbottom >> _s2w >> _c2w >> Cijeo_ >> Cijec_ >> Cijco_ >> Cijc_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigRPVWSSVertex("Herwig::RPVWSSVertex", "HwSusy.so HwRPV.so"); void RPVWSSVertex::Init() { static ClassDocumentation documentation ("There is no documentation for the RPVWSSVertex class"); static Switch interfaceInteractions ("Interactions", "Which interactions to include", &RPVWSSVertex::_interactions, 0, false, false); static SwitchOption interfaceInteractionsAll (interfaceInteractions, "All", "Include both the interactions which would have been sfermion" " and Higgs bosons with the gauge bosons in the MSSM", 0); static SwitchOption interfaceInteractionsSfermions (interfaceInteractions, "Sfermions", "Include the sfermion interactions", 1); static SwitchOption interfaceInteractionsHiggs (interfaceInteractions, "Higgs", "Include the Higgs boson interactions", 2); } void RPVWSSVertex::setCoupling(Energy2 q2,tcPDPtr part1, tcPDPtr part2,tcPDPtr part3) { long gboson = part1->id(); assert( gboson == ParticleID::Z0 || gboson == ParticleID::gamma || abs(gboson) == ParticleID::Wplus ); long h1ID = part2->id(); long h2ID = part3->id(); // squarks and sleptons if(((abs(h1ID)>=1000001&&abs(h1ID)<=1000006)|| (abs(h1ID)>=2000001&&abs(h1ID)<=2000006)) || (((abs(h1ID)>=1000011&&abs(h1ID)<=1000016)|| (abs(h1ID)>=2000011&&abs(h1ID)<=2000016))&& Cijeo_.size()==1)) { long sf1(abs(part2->id())),sf2(abs(part3->id())); if( sf1 % 2 != 0 ) swap(sf1, sf2); if( sf1 != _ulast || sf2 != _dlast || gboson != _gblast) { _gblast = gboson; _ulast = sf1; _dlast = sf2; //photon is simplest if( gboson == ParticleID::gamma ) _factlast = getParticleData(sf1)->charge()/eplus; else { //determine which helicity state unsigned int alpha(sf1/1000000 - 1), beta(sf2/1000000 - 1); //mixing factors Complex m1a(0.), m1b(0.); if( sf1 == ParticleID::SUSY_t_1 || sf1 == ParticleID::SUSY_t_2 ) m1a = (*_stop)(alpha, 0); else if( sf1 == ParticleID::SUSY_b_1 || sf1 == ParticleID::SUSY_b_2 ) m1a = (*_sbottom)(alpha, 0); else if( sf1 == ParticleID::SUSY_tau_1minus || sf1 == ParticleID::SUSY_tau_2minus ) m1a = (*_stau)(alpha, 0); else m1a = (alpha == 0) ? Complex(1.) : Complex(0.); if( sf2 == ParticleID::SUSY_t_1 || sf2 == ParticleID::SUSY_t_2 ) m1b = (*_stop)(beta, 0); else if( sf2 == ParticleID::SUSY_b_1 || sf2 == ParticleID::SUSY_b_2 ) m1b = (*_sbottom)(beta, 0); else if( sf2 == ParticleID::SUSY_tau_1minus || sf2 == ParticleID::SUSY_tau_2minus ) m1b = (*_stau)(beta, 0); else m1b = (beta == 0) ? Complex(1.) : Complex(0.); //W boson if( abs(gboson) == ParticleID::Wplus ) { _factlast = m1a*m1b/sqrt(2)/_sw; } //Z boson else { if( sf1 == ParticleID::SUSY_nu_eL || sf1 == ParticleID::SUSY_nu_muL || sf1 == ParticleID::SUSY_nu_tauL ) { _factlast = 1./_cw/2./_sw; } else { double lmda(1.); if( sf2 % 2 == 0 ) lmda = -1.; _factlast = lmda*m1a*m1b; if( alpha == beta) { double ef = getParticleData(sf1)->charge()/eplus; _factlast += 2.*ef*sqr(_sw); } _factlast *= -1./2./_cw/_sw; } } } } } // Higgs bosons else { _gblast = gboson; _ulast = h1ID; _dlast = h2ID; _factlast = 0.; if( gboson == ParticleID::Z0 ) { if( part2->charged() ) { unsigned int c1 = abs(h1ID) < 1000000 ? 0 : (abs(h1ID) < 2000000 ? (abs(h1ID)-1000009)/2 : (abs(h1ID)-2000003)/2); unsigned int c2 = abs(h2ID) < 1000000 ? 0 : (abs(h2ID) < 2000000 ? (abs(h2ID)-1000009)/2 : (abs(h2ID)-2000003)/2); if(c1==c2) _factlast = (_c2w-Cijc_[c1][c2])/_s2w; else _factlast = -Cijc_[c1][c2]/_s2w; if(part2->iCharge()<0) _factlast *= -1.; } else { if(h1ID == ParticleID::h0 || h1ID == ParticleID::H0 || h1ID == ParticleID::SUSY_nu_eL || h1ID == ParticleID::SUSY_nu_muL || h1ID == ParticleID::SUSY_nu_tauL ) { unsigned int is = h1ID < 1000000 ? (h1ID-25)/10 : (h1ID-1000008)/2; unsigned int ip = h2ID < 1000000 ? 0 : (h2ID-1000016); _factlast = Complex(0.,1.)*Cijeo_[ip][is]/_s2w; } else { unsigned int is = h2ID < 1000000 ? (h2ID-25)/10 : (h2ID-1000008)/2; unsigned int ip = h1ID < 1000000 ? 0 : (h1ID-1000016); _factlast = -Complex(0.,1.)*Cijeo_[ip][is]/_s2w; } } } else if( gboson == ParticleID::gamma ) { _factlast = part2->iCharge()/3; } else { long scalar = part2->charged() ? h2ID : h1ID; long charged = part2->charged() ? h1ID : h2ID; unsigned int ic = abs(charged) < 1000000 ? 0 : (abs(charged) < 2000000 ? (abs(charged)-1000009)/2 : (abs(charged)-2000003)/2); if(scalar == ParticleID::h0 || scalar == ParticleID::H0 || scalar == ParticleID::SUSY_nu_eL || scalar == ParticleID::SUSY_nu_muL || scalar == ParticleID::SUSY_nu_tauL ) { unsigned int ih = scalar < 1000000 ? (scalar-25)/10 : (scalar-1000008)/2; _factlast = -0.5*Cijec_[ih][ic]/_sw; if(gboson<0) _factlast *= -1.; } else { unsigned int ih = scalar < 1000000 ? 0 : (scalar-1000016); _factlast = Complex(0., 0.5)*Cijco_[ih][ic]/_sw; } if(part3->charged()) _factlast *= -1.; } } if( q2 != _q2last || _couplast==0. ) { _q2last = q2; _couplast = electroMagneticCoupling(q2); } if(part2->id()>0) norm(-_couplast*_factlast); else norm(+_couplast*_factlast); } diff --git a/Models/Susy/RPV/RPVWWHVertex.cc b/Models/Susy/RPV/RPVWWHVertex.cc --- a/Models/Susy/RPV/RPVWWHVertex.cc +++ b/Models/Susy/RPV/RPVWWHVertex.cc @@ -1,109 +1,110 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the RPVWWHVertex class. // #include "RPVWWHVertex.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "RPV.h" using namespace Herwig; RPVWWHVertex::RPVWWHVertex() : coupLast_(ZERO), q2Last_(ZERO) { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::SINGLET); } void RPVWWHVertex::doinit() { // extract some models parameters to decide if we need sneutrinos tRPVPtr model = dynamic_ptr_cast(generator()->standardModel()); if( !model ) throw InitException() << "RPVWWHVertex::doinit() - " << "The pointer to the RPV object is null!" << Exception::abortnow; // get the Higgs mixing matrix MixingMatrixPtr mix = model->CPevenHiggsMix(); // possible interactions vector higgs(2); higgs[0] = 25; higgs[1] = 35; if(mix->size().first>2) { higgs.push_back(1000012); higgs.push_back(1000014); higgs.push_back(1000016); } for(unsigned int ix=0;ixmass(); Energy mz = getParticleData(ParticleID::Z0)->mass(); double sw = sqrt(sin2ThetaW()); double cw = sqrt(1.-sin2ThetaW()); vector vnu = model->sneutrinoVEVs(); Energy v = 2.*mw/electroMagneticCoupling(sqr(mw))*sw; double tanb = model->tanBeta(); Energy vd = sqrt((sqr(v)-sqr(vnu[0])-sqr(vnu[1])-sqr(vnu[2]))/ (1.+sqr(tanb))); Energy vu = vd*tanb; for(unsigned int ix=0;ix c = vd*(*mix)(ix,0)+vu*(*mix)(ix,1); for(size_t iy=2; iysize().second; ++iy) c += vnu[iy-2]*(*mix)(ix,iy); vector > coup(2); coup[0] = c/v*mw; coup[1] = c/v*mz/cw; couplings_.push_back(coup); } } IBPtr RPVWWHVertex::clone() const { return new_ptr(*this); } IBPtr RPVWWHVertex::fullclone() const { return new_ptr(*this); } void RPVWWHVertex::persistentOutput(PersistentOStream & os) const { os << ounit(couplings_,GeV); } void RPVWWHVertex::persistentInput(PersistentIStream & is, int) { is >> iunit(couplings_,GeV); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigRPVWWHVertex("Herwig::RPVWWHVertex", "HwSusy.so HwRPV.so"); void RPVWWHVertex::Init() { static ClassDocumentation documentation ("The RPVWWHVertex class implements the couplings of a pair of electroweak" " gauge bosons to the higgs boson in he R-parity violating MSSM."); } void RPVWWHVertex::setCoupling(Energy2 q2, tcPDPtr particle1, tcPDPtr, tcPDPtr particle3) { long bosonID = abs(particle1->id()); long higgsID = particle3->id(); assert( bosonID == ParticleID::Wplus || bosonID == ParticleID::Z0 ); int ihiggs = higgsID>1000000 ? (higgsID-1000008)/2 : (higgsID-25)/10; assert(ihiggs>=0 && ihiggs<=4); complex fact = bosonID==ParticleID::Wplus ? couplings_[ihiggs][0] : couplings_[ihiggs][1]; if( q2 != q2Last_ ) { q2Last_ = q2; coupLast_ = weakCoupling(q2); } norm(coupLast_*fact*UnitRemoval::InvE); } diff --git a/Models/Susy/SSCCZVertex.cc b/Models/Susy/SSCCZVertex.cc --- a/Models/Susy/SSCCZVertex.cc +++ b/Models/Susy/SSCCZVertex.cc @@ -1,127 +1,128 @@ // -*- C++ -*- // // SSCCZVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SSCCZVertex class. // #include "SSCCZVertex.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" using namespace ThePEG::Helicity; using namespace Herwig; SSCCZVertex::SSCCZVertex() : _sw2(0.), _cw(0.), _couplast(0.), _q2last(), _id1last(0), _id2last(0), _leftlast(0.), _rightlast(0.), _gblast(0) { orderInGs(0); orderInGem(1); + colourStructure(ColourStructure::SINGLET); } void SSCCZVertex::doinit() { addToList(-1000024, 1000024, 23); addToList(-1000024, 1000037, 23); addToList(-1000037, 1000024, 23); addToList(-1000037, 1000037, 23); //photon addToList(-1000024, 1000024, 22); addToList(-1000037, 1000037, 22); FFVVertex::doinit(); tSusyBasePtr theSS = dynamic_ptr_cast(generator()->standardModel()); if(!theSS) throw InitException() << "SSCCZVertex::doinit - The model pointer " << "is null! " << Exception::abortnow; _sw2 = sin2ThetaW(); _cw = sqrt(1. - _sw2); _theU = theSS->charginoUMix(); _theV = theSS->charginoVMix(); if(!_theU || !_theV) throw InitException() << "SSCCZVertex::doinit - " << "A mixing matrix pointer is null. U: " << _theU << " V: " << _theV << Exception::abortnow; } void SSCCZVertex::persistentOutput(PersistentOStream & os) const { os << _sw2 << _cw << _theU << _theV; } void SSCCZVertex::persistentInput(PersistentIStream & is, int) { is >> _sw2 >> _cw >> _theU >> _theV; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeSSCCZVertex("Herwig::SSCCZVertex", "HwSusy.so"); void SSCCZVertex::Init() { static ClassDocumentation documentation ("This class implements the coupling of a Z/gamma to a pair of" " charginos. "); } void SSCCZVertex::setCoupling(Energy2 q2, tcPDPtr part1, tcPDPtr part2, tcPDPtr part3) { long ichar1(part1->id()), ichar2(part2->id()), boson(part3->id()); assert( boson == ParticleID::gamma || boson == ParticleID::Z0); assert( abs(ichar1) == 1000024 || abs(ichar1) == 1000037); assert( abs(ichar2) == 1000024 || abs(ichar2) == 1000037); if(_q2last != q2||_couplast==0.) { _q2last = q2; _couplast = electroMagneticCoupling(q2); } norm(_couplast); if(boson != _gblast || ichar1 != _id1last || ichar2 != _id2last) { _gblast = boson; _id1last = ichar1; _id2last = ichar2; if( boson == ParticleID::Z0 ) { unsigned int ic1(0), ic2(0); if(abs(ichar1) == 1000037) ic1 = 1; if(abs(ichar2) == 1000037) ic2 = 1; _leftlast = -(*_theV)(ic1, 0)*conj((*_theV)(ic2, 0)) - 0.5*(*_theV)(ic1, 1)*conj((*_theV)(ic2, 1)); _rightlast = -conj((*_theU)(ic1, 0))*(*_theU)(ic2, 0) - 0.5*conj((*_theU)(ic1, 1))*(*_theU)(ic2, 1); if(abs(ichar1) == abs(ichar2)) { _leftlast += _sw2; _rightlast += _sw2; } _leftlast /= sqrt(_sw2)*_cw; _rightlast /= sqrt(_sw2)*_cw; } else { if(abs(ichar1) == abs(ichar2)) { _leftlast = -1.; _rightlast = -1.; } else { _leftlast = 0.; _rightlast = 0.; } } if(ichar1>0) { Complex temp = _leftlast; _leftlast = -_rightlast; _rightlast = -temp; } } left(_leftlast); right(_rightlast); } diff --git a/Models/Susy/SSCFSVertex.cc b/Models/Susy/SSCFSVertex.cc --- a/Models/Susy/SSCFSVertex.cc +++ b/Models/Susy/SSCFSVertex.cc @@ -1,237 +1,238 @@ // -*- C++ -*- // // SSCFSVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SSCFSVertex class. // #include "SSCFSVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG::Helicity; using namespace Herwig; SSCFSVertex::SSCFSVertex(): _sb(0.),_cb(0.),_mw(ZERO), _q2last(0.*GeV2), _couplast(0.), _leftlast(0.),_rightlast(0.), _id1last(0), _id2last(0), _id3last(0), yukawa_(1) { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::DELTA); } void SSCFSVertex::doinit() { long chargino[2] = {1000024, 1000037}; for(unsigned int ic = 0; ic < 2; ++ic) { //quarks for(long ix = 1; ix < 7; ++ix) { if( ix % 2 == 0 ) { addToList(-chargino[ic],ix,-(999999+ix)); addToList(-chargino[ic],ix,-(1999999+ix)); addToList(-ix,chargino[ic],(999999+ix)); addToList(-ix,chargino[ic],(1999999+ix)); } else { addToList(-chargino[ic],-ix,(1000001+ix)); addToList(-chargino[ic],-ix,2000001+ix); addToList(chargino[ic],ix,-(1000001+ix)); addToList(chargino[ic],ix,-(2000001+ix)); } } //leptons for(long ix = 11; ix < 17; ++ix) { if( ix % 2 == 0 ) { addToList(-chargino[ic],ix,-(999999+ix)); addToList(-chargino[ic],ix,-(1999999+ix)); addToList(-ix,chargino[ic],(999999+ix)); addToList(-ix,chargino[ic],(1999999+ix)); } else { addToList(-chargino[ic],-ix,1000001+ix); addToList(chargino[ic],ix,-(1000001+ix)); } } } FFSVertex::doinit(); _theSS = dynamic_ptr_cast(generator()->standardModel()); //mixing matrices _stop = _theSS->stopMix(); _sbot = _theSS->sbottomMix(); _stau = _theSS->stauMix(); _umix = _theSS->charginoUMix(); _vmix = _theSS->charginoVMix(); if(!_stop || !_stau || !_sbot || !_umix || !_vmix) throw InitException() << "SSCFSVertex:: doinit - " << "A mixing matrix pointer is null." << " stop: " << _stop << " sbottom: " << _sbot << " stau: " << _stau << " U: " << _umix << " V:" << _vmix << Exception::abortnow; _mw = getParticleData(24)->mass(); double tb = _theSS->tanBeta(); _sb = tb/sqrt(1 + sqr(tb)); _cb = sqrt(1.- sqr(_sb)); } void SSCFSVertex::persistentOutput(PersistentOStream & os) const { os << _theSS << _sb << _cb << ounit(_mw,GeV) << _stop << _sbot << _stau << _umix << _vmix << yukawa_; } void SSCFSVertex::persistentInput(PersistentIStream & is, int) { is >> _theSS >> _sb >> _cb >> iunit(_mw,GeV) >> _stop >> _sbot >> _stau >> _umix >> _vmix >> yukawa_; } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigSSCFSVertex("Herwig::SSCFSVertex", "HwSusy.so"); void SSCFSVertex::Init() { static ClassDocumentation documentation ("The implementation of the coupling of the charginos to fermion-" "sfermions."); static Switch interfaceYukawa ("Yukawa", "Whether or not to include the Yukawa type couplings", &SSCFSVertex::yukawa_, true, false, false); static SwitchOption interfaceYukawaYes (interfaceYukawa, "Yes", "Include the terms", 1); static SwitchOption interfaceYukawaNo (interfaceYukawa, "No", "Don't include them", 0); static SwitchOption interfaceYukawa3rdGen (interfaceYukawa, "ThirdGeneration", "Only include them for the third generation", 2); } void SSCFSVertex::setCoupling(Energy2 q2, tcPDPtr part1, tcPDPtr part2,tcPDPtr part3) { long isc(abs(part3->id())), ism(abs(part1->id())), ichg(abs(part2->id())); tcPDPtr smfermion = part1; if( ism / 1000000 == 1 ) { swap( ism, ichg); smfermion = part2; } //overall normalisation if(q2!=_q2last||_couplast==0.) { _q2last=q2; _couplast = -weakCoupling(q2); } norm(_couplast); if( ichg != _id1last || ism != _id2last || isc != _id3last ) { _id1last = ichg; _id2last = ism; _id3last = isc; // determine chargino and sfermion eigenstates unsigned int alpha(isc/1000000 - 1); unsigned int ch = (ichg == 1000024 ) ? 0 : 1; Complex ul1 = (*_umix)(ch,0); Complex ul2 = (*_umix)(ch,1); Complex vl1 = (*_vmix)(ch,0); Complex vl2 = (*_vmix)(ch,1); if( ism >= 11 && ism <= 16 ) { long lept = ( ism % 2 == 0 ) ? ism - 1 : ism; double y = 0.; if(yukawa_==1 || (lept==15 && yukawa_==2)) y = double(_theSS->mass(q2, getParticleData(lept))/_mw/sqrt(2)/_cb); if( ism == 12 || ism == 14 ) { _leftlast = Complex(0., 0.); if( alpha == 0 ) _rightlast = ul1; else _rightlast = -y*ul2; } else if( ism == 16 ) { _leftlast = Complex(0., 0.); _rightlast = ul1*(*_stau)(alpha, 0) - y*(*_stau)(alpha,1)*ul2; } else if( ism == 11 || ism == 13 || ism == 15 ) { _leftlast = -y*conj(ul2); _rightlast = vl1; } } else { double yd(0.), yu(0.); if(yukawa_==1 || ((ism==5 || ism==6 ) && yukawa_==2)) { if( ism % 2 == 0) { yu = _theSS->mass(q2, getParticleData(ism))/_mw/sqrt(2)/_sb; yd = _theSS->mass(q2, getParticleData(ism - 1))/_mw/sqrt(2)/_cb; } else { yu = _theSS->mass(q2, getParticleData(ism + 1))/_mw/sqrt(2)/_sb; yd = _theSS->mass(q2, getParticleData(ism))/_mw/sqrt(2)/_cb; } } //heavy quarks if( ism == 5 ) { _leftlast = -yd*conj(ul2)*(*_stop)(alpha,0); _rightlast = vl1*(*_stop)(alpha, 0) - yu*vl2*(*_stop)(alpha,1); } else if( ism == 6 ) { _leftlast = -yu*conj(vl2)*(*_sbot)(alpha,0); _rightlast = ul1*(*_sbot)(alpha, 0) - yd*ul2*(*_sbot)(alpha,1); } else { if( alpha == 0 ) { _leftlast = (ism % 2 == 0) ? -yu*conj(vl2) : -yd*conj(ul2); _rightlast = (ism % 2 == 0) ? ul1 : vl1; } else { _leftlast = Complex(0.); _rightlast = (ism % 2 == 0) ? -yd*ul2 : -yu*vl2; } } } }//end of coupling calculation //determine the helicity order of the vertex if( smfermion->id() < 0 ) { left(conj(_rightlast)); right(conj(_leftlast)); } else { left(_leftlast); right(_rightlast); } } diff --git a/Models/Susy/SSCNWVertex.cc b/Models/Susy/SSCNWVertex.cc --- a/Models/Susy/SSCNWVertex.cc +++ b/Models/Susy/SSCNWVertex.cc @@ -1,131 +1,132 @@ // -*- C++ -*- // // SSCNWVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SSCNWVertex class. // #include "SSCNWVertex.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" using namespace ThePEG::Helicity; using namespace Herwig; SSCNWVertex::SSCNWVertex() : _sw(0.), _couplast(0.), _q2last(ZERO), _id1last(0), _id2last(0), _leftlast(0.), _rightlast(0.) { orderInGs(0); orderInGem(1); + colourStructure(ColourStructure::SINGLET); } void SSCNWVertex::doinit() { long neu[] = { 1000022, 1000023, 1000025, 1000035, 1000045 }; long cha[] = { 1000024, 1000037 }; // sign == -1 outgoing W-, sign == +1 outgoing W+ for(int sign = -1; sign < 2; sign += 2) for(unsigned int ine = 0; ine < 5; ++ine) for(unsigned int ic = 0; ic < 2; ++ic) addToList(-sign*cha[ic], neu[ine], sign*24); FFVVertex::doinit(); tSusyBasePtr theSS = dynamic_ptr_cast(generator()->standardModel()); if(!theSS) throw InitException() << "SSCNWVertex::doinit() - The model pointer is null!" << Exception::abortnow; _sw = sqrt(sin2ThetaW()); _theN = theSS->neutralinoMix(); _theU = theSS->charginoUMix(); _theV = theSS->charginoVMix(); if(!_theN || !_theU || ! _theV) throw InitException() << "SSCNWVertex::doinit() - " << "A mixing matrix pointer is null." << " N: " << _theN << " U: " << _theU << " V: " << _theV << Exception::abortnow; } void SSCNWVertex::persistentOutput(PersistentOStream & os) const { os << _sw << _theN << _theU << _theV; } void SSCNWVertex::persistentInput(PersistentIStream & is, int) { is >> _sw >> _theN >> _theU >> _theV; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeSSCNWVertex("Herwig::SSCNWVertex", "HwSusy.so"); void SSCNWVertex::Init() { static ClassDocumentation documentation ("This class implements the coupling of a W boson to a " "neutralino and a chargino"); } void SSCNWVertex::setCoupling(Energy2 q2, tcPDPtr part1, tcPDPtr part2, #ifndef NDEBUG tcPDPtr part3) { #else tcPDPtr) { #endif assert(abs(part3->id()) == ParticleID::Wplus); long neu, cha; if(part1->charged()) { cha = part1->id(); neu = part2->id(); } else { cha = part2->id(); neu = part1->id(); } assert((abs(cha) == 1000024 || abs(cha) == 1000037) && (neu == 1000022 || neu == 1000023 || neu == 1000025 || neu == 1000035 || neu == 1000045) ); if(q2 != _q2last||_couplast==0.) { _q2last = q2; _couplast = weakCoupling(q2); } norm(_couplast); if(cha != _id1last || neu != _id2last) { _id1last = cha; _id2last = neu; unsigned int eigc = abs(cha) == 1000037 ? 1 : 0; unsigned int eign(0); if (neu == 1000023) eign = 1; else if(neu == 1000025) eign = 2; else if(neu == 1000035) eign = 3; else if(neu == 1000045) eign = 4; _leftlast = (*_theN)(eign, 1)*conj((*_theV)(eigc, 0)) - ( (*_theN)(eign, 3)*conj((*_theV)(eigc, 1))/sqrt(2)); _rightlast = conj((*_theN)(eign, 1))*(*_theU)(eigc, 0) + ( conj((*_theN)(eign, 2))*(*_theU)(eigc, 1)/sqrt(2)); } Complex ltemp = _leftlast; Complex rtemp = _rightlast; // conjugate if +ve chargino if(cha>0) { ltemp = conj(ltemp); rtemp = conj(rtemp); } if((part1->id()==cha&&cha>0)||(part2->id()==cha&&cha<0)) { Complex temp = ltemp; ltemp = -rtemp; rtemp = -temp; } left (ltemp); right(rtemp); } diff --git a/Models/Susy/SSFFHVertex.cc b/Models/Susy/SSFFHVertex.cc --- a/Models/Susy/SSFFHVertex.cc +++ b/Models/Susy/SSFFHVertex.cc @@ -1,159 +1,160 @@ // -*- C++ -*- // // SSFFHVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SSFFHVertex class. // #include "SSFFHVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include using namespace ThePEG::Helicity; using namespace Herwig; SSFFHVertex::SSFFHVertex() : thetanb(0.0), theMw(ZERO), theSa(0.0), theSb(0.0), theCa(0.0), theCb(0.0), theFLast(make_pair(0,0)), theGlast(0.), theq2last(), theMassLast(make_pair(ZERO,ZERO)) { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::DELTA); } void SSFFHVertex::doinit() { int higgs[] = { 25, 35, 36 }; for ( long h = 0; h < 3; ++h ) { //neutral higgs // quarks for(long ix=1;ix<7;++ix) addToList(-ix,ix,higgs[h]); // charged leptons for(long ix=11;ix<16;ix+=2) addToList(-ix,ix,higgs[h]); } for(long ix=1;ix<6;ix+=2) { //outgoing H+ addToList(-ix-1, ix, 37); //outgoing H- addToList(-ix ,ix+1,-37); } for(long ix=11;ix<16;ix+=2) { //outgoing H+ addToList(-ix-1, ix, 37); //outgoing H- addToList(-ix ,ix+1,-37); } theMSSM = dynamic_ptr_cast(generator()->standardModel()); if( !theMSSM ) throw InitException() << "SSFFHVertex::doinit() - The pointer to the MSSM object is null!" << Exception::abortnow; theMw = getParticleData(ParticleID::Wplus)->mass(); thetanb = theMSSM->tanBeta(); theSb = thetanb/sqrt(1. + sqr(thetanb)); theCb = sqrt( 1. - sqr(theSb) ); theSa = sin(theMSSM->higgsMixingAngle()); theCa = sqrt(1. - sqr(theSa)); FFSVertex::doinit(); } void SSFFHVertex::persistentOutput(PersistentOStream & os) const { os << theMSSM << thetanb << ounit(theMw,GeV) << theSa << theSb << theCa << theCb; } void SSFFHVertex::persistentInput(PersistentIStream & is, int) { is >> theMSSM >> thetanb >> iunit(theMw,GeV) >> theSa >> theSb >> theCa >> theCb; } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigSSFFHVertex("Herwig::SSFFHVertex", "HwSusy.so"); void SSFFHVertex::Init() { static ClassDocumentation documentation ("The coupling of the higgs bosons to SM fermions in the MSSM"); } void SSFFHVertex::setCoupling(Energy2 q2, tcPDPtr particle1, tcPDPtr particle2,tcPDPtr particle3) { long f1ID(abs(particle1->id())), f2ID(abs(particle2->id())), higgsID(particle3->id()); // check higgs assert( higgsID == ParticleID::h0 || higgsID == ParticleID::H0 || higgsID == ParticleID::A0 || abs(higgsID) == ParticleID::Hplus ); // check fermions assert(!( ((f1ID > 6 && f1ID < 11) || f1ID > 16 ) || ((f2ID > 6 && f1ID < 11) || f2ID > 16 ) )); if( q2 != theq2last || theGlast==0.) { theGlast = weakCoupling(q2); } if( q2 != theq2last || theFLast.first != f1ID) { theMassLast.first = theMSSM->mass(q2,particle1); theFLast.first = f1ID; } if( q2 != theq2last || theFLast.second != f2ID) { theMassLast.second = theMSSM->mass(q2,particle2); theFLast.second = f2ID; } theq2last = q2; Complex coup(0.); Complex lcoup(1.),rcoup(1.); if( higgsID == ParticleID::h0 || higgsID == ParticleID::H0 || higgsID == ParticleID::A0 ) { coup = 0.5*theMassLast.first/theMw; if( higgsID == ParticleID::h0 ) { if( f1ID % 2 == 0 ) coup *= -theCa/theSb; else coup *= theSa/theCb; } else if( higgsID == ParticleID::H0 ) { if( f1ID % 2 == 0 ) coup *= -theSa/theSb; else coup *= -theCa/theCb; } else { if( f1ID % 2 == 0 ) coup /= thetanb; else coup *= thetanb; coup *= Complex(0.,-1.); rcoup = -1.; } } //H+ else { if( f1ID % 2 == 0 ) { lcoup = theMassLast.first /thetanb/theMw; rcoup = theMassLast.second*thetanb/theMw; } else { lcoup = theMassLast.second/thetanb/theMw; rcoup = theMassLast.first *thetanb/theMw; } coup = sqrt(0.5); if( higgsID > 0 ) swap(lcoup,rcoup); } norm(theGlast*coup); left (lcoup); right(rcoup); } diff --git a/Models/Susy/SSGFSVertex.cc b/Models/Susy/SSGFSVertex.cc --- a/Models/Susy/SSGFSVertex.cc +++ b/Models/Susy/SSGFSVertex.cc @@ -1,147 +1,148 @@ // -*- C++ -*- // // SSGFSVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SSGFSVertex class. // #include "SSGFSVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG::Helicity; using namespace Herwig; SSGFSVertex::SSGFSVertex() :_q2last(0.*GeV2),_couplast(0.), _id1last(0), _id2last(0) { orderInGs(1); orderInGem(0); + colourStructure(ColourStructure::SU3TFUND); } void SSGFSVertex::persistentOutput(PersistentOStream & os) const { os << _stop << _sbottom << gluinoPhase_; } void SSGFSVertex::persistentInput(PersistentIStream & is, int) { is >> _stop >> _sbottom >> gluinoPhase_; } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigSSGFSVertex("Herwig::SSGFSVertex", "HwSusy.so"); void SSGFSVertex::Init() { static ClassDocumentation documentation ("The SSGFSVertex implements coupling of the gluinos to the " "squarks and quarks"); } void SSGFSVertex::setCoupling(Energy2 q2, tcPDPtr part1, tcPDPtr part2, tcPDPtr part3) { tcPDPtr ferm; long isc(0); if(abs(part1->id()) == 1000021) { if(part2->iSpin() == PDT::Spin1Half) { ferm = part2; isc = abs(part3->id()); } else { ferm = part3; isc = abs(part2->id()); } } else if(abs(part2->id()) == 1000021) { if(part1->iSpin() == PDT::Spin1Half) { ferm = part1; isc = abs(part3->id()); } else { ferm = part3; isc = abs(part1->id()); } } else if(abs(part3->id()) == 1000021) { if(part1->iSpin() == PDT::Spin1Half) { ferm = part1; isc = abs(part2->id()); } else { ferm = part2; isc = abs(part1->id()); } } else throw HelicityConsistencyError() << "SSGFSVertex::setCoupling() - There is no gluino in this vertex!" << part1->id() << " " << part2->id() << " " << part3->id() << Exception::runerror; long iferm = abs(ferm->id()); assert(iferm >=1 && iferm <=6); if(q2 != _q2last || _couplast==0.) { _couplast = -strongCoupling(q2)*sqrt(2.); _q2last = q2; } if(iferm != _id1last || isc != _id2last) { _id1last = iferm; _id2last = isc; unsigned int eig = (isc/1000000) - 1; if(iferm == 6) { _leftlast = -(*_stop)(eig,1)*conj(gluinoPhase_); _rightlast = (*_stop)(eig,0)* gluinoPhase_ ; } else if(iferm == 5){ _leftlast = -(*_sbottom)(eig,1)*conj(gluinoPhase_); _rightlast = (*_sbottom)(eig,0)* gluinoPhase_ ; } else { if(eig == 0) { _leftlast = 0.; _rightlast = gluinoPhase_; } else { _leftlast = -conj(gluinoPhase_); _rightlast = 0.; } } } norm(_couplast); //arrange l/r couplings if(ferm->id() < 0) { left(conj(_rightlast)); right(conj(_leftlast)); } else { left(_leftlast); right(_rightlast); } } void SSGFSVertex::doinit() { for(long ix=1;ix<7;++ix) { addToList(1000021, ix, -(ix+1000000)); addToList(1000021, ix, -(ix+2000000)); addToList(1000021, -ix, (ix+1000000)); addToList(1000021, -ix, (ix+2000000)); } FFSVertex::doinit(); tMSSMPtr model = dynamic_ptr_cast(generator()->standardModel()); _stop = model->stopMix(); _sbottom = model->sbottomMix(); gluinoPhase_ = model->gluinoPhase(); if(!_stop || !_sbottom) throw InitException() << "SSGFSVertex::doinit() - " << "There is a null mixing matrix pointer. " << "stop: " << _stop << " sbottom: " << _sbottom << Exception::abortnow; } diff --git a/Models/Susy/SSGGSQSQVertex.cc b/Models/Susy/SSGGSQSQVertex.cc --- a/Models/Susy/SSGGSQSQVertex.cc +++ b/Models/Susy/SSGGSQSQVertex.cc @@ -1,59 +1,60 @@ // -*- C++ -*- // // SSGGSQSQVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SSGGSQSQVertex class. // #include "SSGGSQSQVertex.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG::Helicity; using namespace Herwig; -SSGGSQSQVertex::SSGGSQSQVertex() : q2last_(),couplast_(0.) -{} +SSGGSQSQVertex::SSGGSQSQVertex() : q2last_(),couplast_(0.) { + colourStructure(ColourStructure::SU3TTFUNDS); +} // The following static variable is needed for the type // description system in ThePEG. DescribeNoPIOClass describeSSGGSQSQVertex("Herwig::SSGGSQSQVertex", "HwSusy.so"); void SSGGSQSQVertex::Init() { static ClassDocumentation documentation ("This implements the gluon-gluon-squark-squark vertex."); } void SSGGSQSQVertex::setCoupling(Energy2 q2, tcPDPtr, tcPDPtr, tcPDPtr, tcPDPtr) { if(q2 != q2last_ || couplast_ == 0.) { couplast_ = sqr(strongCoupling(q2)); q2last_ = q2; } norm(couplast_); } void SSGGSQSQVertex::doinit() { //L-L squarks for(long ix=1000001;ix<1000007;++ix) { addToList(21,21,ix,-ix); } //R-R squarks for(long ix=2000001;ix<2000007;++ix) { addToList(21,21,ix,-ix); } orderInGs(2); orderInGem(0); VVSSVertex::doinit(); } diff --git a/Models/Susy/SSGNGVertex.cc b/Models/Susy/SSGNGVertex.cc --- a/Models/Susy/SSGNGVertex.cc +++ b/Models/Susy/SSGNGVertex.cc @@ -1,304 +1,305 @@ // -*- C++ -*- // // SSGNGVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SSGNGVertex class. // #include "SSGNGVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/Models/Susy/MixingMatrix.h" #include "ThePEG/PDT/EnumParticles.h" #include "Herwig/Looptools/clooptools.h" using namespace ThePEG::Helicity; using namespace Herwig; namespace { unsigned int neutralinoIndex(long id) { if(id> 1000000) return id<1000025 ? id-1000022 : (id-1000005)/10; else if(abs(id)<=16) return (abs(id)-4)/2; else return id-13; } } SSGNGVertex::SSGNGVertex() : _includeOnShell(false), _realIntegral(false), _omitLightQuarkYukawas(false), _sw(0.), _cw(0.), _idlast(0), _q2last(ZERO), _couplast(0.), _leftlast(ZERO), _rightlast(ZERO), _initLoops(false) { orderInGem(1); orderInGs(2); + colourStructure(ColourStructure::DELTA); } void SSGNGVertex::doinit() { if(!_initLoops) { Looptools::ltini(); _initLoops = true; } tMSSMPtr model = dynamic_ptr_cast(generator()->standardModel()); if(!model) throw InitException() << "SSGNGVertex::doinit() - " << "The model pointer is null." << Exception::abortnow; _theN = model->neutralinoMix(); if(!_theN ) throw InitException() << "SSGNGVertex::doinit - The neutralino " << "mixing matrix pointer is null." << Exception::abortnow; vector ineu(4); ineu[0] = 1000022; ineu[1] = 1000023; ineu[2] = 1000025; ineu[3] = 1000035; if(_theN->size().first==5) ineu.push_back(1000045); else if(_theN->size().first==7) { if(model->majoranaNeutrinos()) { ineu.push_back(17); ineu.push_back(18); ineu.push_back(19); } else { ineu.push_back(12); ineu.push_back(14); ineu.push_back(16); } } for(unsigned int i = 0; i < ineu.size(); ++i) { addToList(1000021, ineu[i], 21); } GeneralFFVVertex::doinit(); _sw = sqrt(sin2ThetaW()); _cw = sqrt(1 - _sw*_sw); _mw = getParticleData(ParticleID::Wplus)->mass(); double tb = model->tanBeta(); _sb = tb/sqrt(1 + sqr(tb)); _cb = sqrt(1 - sqr(_sb)); _stop = model->stopMix(); _sbot = model->sbottomMix(); Looptools::ltexi(); } void SSGNGVertex::dofinish() { Looptools::ltexi(); GeneralFFVVertex::dofinish(); } void SSGNGVertex::doinitrun() { if(!_initLoops) { Looptools::ltini(); _initLoops = true; } GeneralFFVVertex::doinitrun(); } void SSGNGVertex::persistentOutput(PersistentOStream & os) const { os << _sw << _cw << _theN << ounit(_mw,GeV) << _sb << _cb << _stop << _sbot << _includeOnShell << _omitLightQuarkYukawas << _realIntegral; } void SSGNGVertex::persistentInput(PersistentIStream & is, int) { is >> _sw >> _cw >> _theN >> iunit(_mw,GeV) >> _sb >> _cb >> _stop >> _sbot >> _includeOnShell >> _omitLightQuarkYukawas >> _realIntegral; } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigSSGNGVertex("Herwig::SSGNGVertex", "HwSusy.so"); void SSGNGVertex::Init() { static ClassDocumentation documentation ("The loop-mediated coupling of the gluino to a gluon and a neutralino."); static Switch interfaceIncludeOnShellIntermediates ("IncludeOnShellIntermediates", "Whether or not to include on-shell intermediate states", &SSGNGVertex::_includeOnShell, false, false, false); static SwitchOption interfaceIncludeOnShellIntermediatesYes (interfaceIncludeOnShellIntermediates, "Yes", "Include them", true); static SwitchOption interfaceIncludeOnShellIntermediatesNo (interfaceIncludeOnShellIntermediates, "No", "Don't incldue them", false); static Switch interfaceOmitLightQuarkYukawas ("OmitLightQuarkYukawas", "Omit the yukawa type couplings for down, up, strange" " and charm quarks, mainly for testing vs ISAJET", &SSGNGVertex::_omitLightQuarkYukawas, false, false, false); static SwitchOption interfaceOmitLightQuarkYukawasNo (interfaceOmitLightQuarkYukawas, "No", "Include the Yukawas", false); static SwitchOption interfaceOmitLightQuarkYukawasYes (interfaceOmitLightQuarkYukawas, "Yes", "Omit Yukawas", true); static Switch interfaceRealIntegral ("RealIntegral", "Only include the real parts of the integrals", &SSGNGVertex::_realIntegral, false, false, false); static SwitchOption interfaceRealIntegralYes (interfaceRealIntegral, "Yes", "Only include the real part", true); static SwitchOption interfaceRealIntegralNo (interfaceRealIntegral, "No", "Don't include the real part", false); } void SSGNGVertex::setCoupling(Energy2 q2, tcPDPtr part1, #ifndef NDEBUG tcPDPtr part2,tcPDPtr part3) { #else tcPDPtr part2,tcPDPtr) { #endif int o[2]={1,0}; long in1 = part1->id(); long in2 = part2->id(); Energy Mj = part1->mass(); Energy Mi = part2->mass(); if(in1!=ParticleID::SUSY_g) { swap(in1,in2); swap(Mj,Mi); } // checks of the particle ids assert(part3->id()==ParticleID::g); assert(in1 == ParticleID::SUSY_g); assert(in2 == ParticleID::SUSY_chi_10 || in2 == ParticleID::SUSY_chi_20 || in2 == ParticleID::SUSY_chi_30 || in2 == ParticleID::SUSY_chi_40 || in2 == 1000045 || in2==12 || in2==14 || in2==16 || in2==17 || in2==18 || in2==19 ); // normal couplings are zero setLeft (0.); setRight(0.); if(in2 != _idlast || q2 !=_q2last) { if(!_initLoops) { Looptools::ltini(); _initLoops = true; } Looptools::clearcache(); _leftlast = ZERO; _rightlast = ZERO; _idlast = in2; unsigned int neu = neutralinoIndex(in2); Complex n1prime = (*_theN)(neu,0)*_cw + (*_theN)(neu,1)*_sw; Complex n2prime = (*_theN)(neu,1)*_cw - (*_theN)(neu,0)*_sw; // squark/quark loops for(long iferm=1;iferm<7;++iferm) { tcPDPtr smf = getParticleData(iferm); Energy mf = smf->mass(); double qf = smf->charge()/eplus; double y = (!(iferm<=4&&_omitLightQuarkYukawas)) ? 0.5*double(dynamic_ptr_cast(generator()->standardModel())->mass(q2,smf)/_mw) : 0.; Complex bracketl = qf*_sw*( conj(n1prime) - _sw*conj(n2prime)/_cw ); double lambda(0.); // neutralino mixing element Complex nlf(0.); if( iferm % 2 == 0 ) { y /= _sb; lambda = -0.5 + qf*sqr(_sw); nlf = (*_theN)(neu,3); } else { y /= _cb; lambda = 0.5 + qf*sqr(_sw); nlf = (*_theN)(neu,2); } Complex bracketr = _sw*qf*n1prime - n2prime*lambda/_cw; for(long iy=0;iy<2;++iy) { long isf = 1000000*(1+iy)+iferm; Energy msf = getParticleData(isf)->mass(); if(!_includeOnShell&&(mf+msf I,J,K,I2; loopIntegrals(Mi,Mj,msf,mf,I,J,K,I2); complex coup[2]; for(unsigned int ix=0;ix<2;++ix) { coup[ix] = Mj*(I2-K)*(g[0][ix]*g[1][o[ix]]-conj(g[0][o[ix]]*g[1][ix])) +Mi*K*(g[0][o[ix]]*g[1][ix]-conj(g[0][ix]*g[1][o[ix]])) +mf*I*(g[0][ix]*g[1][ix]-conj(g[0][o[ix]]*g[1][o[ix]])); } _leftlast += 2.*coup[0]; _rightlast += 2.*coup[1]; } } } if(q2 != _q2last || _couplast==0.) { _q2last = q2; _couplast = weakCoupling(q2)*sqr(strongCoupling(q2))/ 32./sqr(Constants::pi); } norm(_couplast); setLeftSigma ( _leftlast); setRightSigma(_rightlast); } void SSGNGVertex::loopIntegrals(Energy Mi, Energy Mj, Energy M, Energy m, complex & I, complex & J, complex & K, complex & I2) { Energy2 m2(sqr(m)),M2(sqr(M)),Mi2(sqr(Mi)),Mj2(sqr(Mj)); double min2 = Mj2*UnitRemoval::InvE2; double mout2 = Mi2*UnitRemoval::InvE2; double mf2 = m2 *UnitRemoval::InvE2; double ms2 = M2 *UnitRemoval::InvE2; I = Looptools::C0i(Looptools::cc0,min2,mout2,0.,mf2,ms2,mf2)*UnitRemoval::InvE2; J = Looptools::C0i(Looptools::cc0,min2,mout2,0.,ms2,mf2,ms2)*UnitRemoval::InvE2; I2 =-Looptools::C0i(Looptools::cc1,min2,mout2,0.,mf2,ms2,mf2)*UnitRemoval::InvE2; K = (1.+Complex(m2*I+M2*J-Mj2*I2))/(Mi2-Mj2); if(_realIntegral) { I = I .real(); J = J .real(); I2 = I2.real(); K = K .real(); } } diff --git a/Models/Susy/SSGOGOHVertex.cc b/Models/Susy/SSGOGOHVertex.cc --- a/Models/Susy/SSGOGOHVertex.cc +++ b/Models/Susy/SSGOGOHVertex.cc @@ -1,237 +1,238 @@ // -*- C++ -*- // // SSGOGOHVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SSGOGOHVertex class. // #include "SSGOGOHVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include using namespace ThePEG::Helicity; using namespace Herwig; -SSGOGOHVertex::SSGOGOHVertex() : theMw(), theSij(2, vector(2,0.0)), - theQij(2, vector(2,0.0)), - theQijLp(4, vector(2,0.0)), - theQijRp(4, vector(2,0.0)), - theSijdp(4, vector(4,0.0)), - theQijdp(4, vector(4,0.0)), +SSGOGOHVertex::SSGOGOHVertex() : theMw(), theSij(2, {0., 0.}), + theQij(2, {0., 0.}), + theQijLp(4, {0., 0.}), + theQijRp(4, {0., 0.}), + theSijdp(4, {0., 0., 0., 0.}), + theQijdp(4, {0., 0., 0., 0.}), theSa(0.0), theSb(0.0), theCa(0.0), theCb(0.0), theCoupLast(0.0), theLLast(0.0), theRLast(0.0), theHLast(0), theID1Last(0), theID2Last(0), theq2last() { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::SINGLET); } void SSGOGOHVertex::doinit() { long neu[4] = {1000022, 1000023, 1000025, 1000035}; long chg[2] = {1000024, 1000037}; long higgs[3] = {25, 35, 36}; for(unsigned int i = 0; i < 4; ++i) { //neutralinos for(unsigned int j = 0; j < 4; ++j) { for(unsigned int k = 0; k < 4; ++k) { if( i < 3 ) { if(k<=j) addToList(neu[j], neu[k], higgs[i]); //charginos if( j < 2 && k < 2 ) { addToList(-chg[j], chg[k], higgs[i]); } } else { if( k == 2 ) break; addToList(-chg[k], neu[j], 37); addToList( chg[k], neu[j],-37); } } } } FFSVertex::doinit(); tMSSMPtr theMSSM = dynamic_ptr_cast(generator()->standardModel()); if( !theMSSM ) throw InitException() << "SSGOGOHVertex::doinit() - The pointer to the MSSM object is null!" << Exception::abortnow; theMw = getParticleData(ParticleID::Wplus)->mass(); double theSw = sqrt(sin2ThetaW()); double tw = theSw/sqrt(1. - theSw*theSw); double tanb = theMSSM->tanBeta(); theSb = tanb/sqrt(1. + sqr(tanb)); theCb = sqrt( 1. - sqr(theSb) ); theSa = sin(theMSSM->higgsMixingAngle()); theCa = sqrt(1. - sqr(theSa)); MixingMatrix nmix = *theMSSM->neutralinoMix(); MixingMatrix umix = *theMSSM->charginoUMix(); MixingMatrix vmix = *theMSSM->charginoVMix(); for(unsigned int i = 0; i < 4; ++i) { for(unsigned int j = 0; j < 4; ++j) { if( i < 2 && j < 2 ) { theQij[i][j] = vmix(i,0)*umix(j,1)/sqrt(2); theSij[i][j] = vmix(i,1)*umix(j,0)/sqrt(2); } if( j < 2 ) { theQijLp[i][j] = conj(nmix(i, 3)*vmix(j,0) + (nmix(i,1) + nmix(i,0)*tw)*vmix(j,1)/sqrt(2)); theQijRp[i][j] = nmix(i, 2)*umix(j,0) - (nmix(i,1) + nmix(i,0)*tw)*umix(j,1)/sqrt(2); } theQijdp[i][j] = 0.5*( nmix(i,2)*( nmix(j,1) - tw*nmix(j,0) ) + nmix(j,2)*( nmix(i,1) - tw*nmix(i,0) ) ); theSijdp[i][j] = 0.5*( nmix(i,3)*( nmix(j,1) - tw*nmix(j,0) ) + nmix(j,3)*( nmix(i,1) - tw*nmix(i,0) ) ); } } } void SSGOGOHVertex::persistentOutput(PersistentOStream & os) const { os << theSij << theQij << theQijLp << theQijRp << theSijdp << theQijdp << ounit(theMw,GeV) << theSa << theSb << theCa << theCb; } void SSGOGOHVertex::persistentInput(PersistentIStream & is, int) { is >> theSij >> theQij >> theQijLp >> theQijRp >> theSijdp >> theQijdp >> iunit(theMw,GeV) >> theSa >> theSb >> theCa >> theCb; } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigSSGOGOHVertex("Herwig::SSGOGOHVertex", "HwSusy.so"); void SSGOGOHVertex::Init() { static ClassDocumentation documentation ("The coupling of the higgs bosons to SM fermions in the MSSM"); } /// \todo fixme void SSGOGOHVertex::setCoupling(Energy2 q2, tcPDPtr particle1, tcPDPtr particle2,tcPDPtr particle3) { long f1ID(particle1->id()), f2ID(particle2->id()), higgsID(particle3->id()); assert(higgsID == ParticleID::h0 || higgsID == ParticleID::H0 || higgsID == ParticleID::A0 || abs(higgsID) == ParticleID::Hplus); if( f1ID < 0 ) swap(f1ID, f2ID); if( q2 != theq2last || theCoupLast == 0. ) { theCoupLast = weakCoupling(q2); theq2last = q2; } if( higgsID == theHLast && f1ID == theID1Last && f2ID == theID2Last) { norm(theCoupLast); left(theLLast); right(theRLast); return; } theHLast = higgsID; theID1Last = f1ID; theID2Last = f2ID; if( higgsID == ParticleID::h0 ) { //charginos if( abs(f2ID) == ParticleID::SUSY_chi_1plus || abs(f2ID) == ParticleID::SUSY_chi_2plus ) { unsigned int ei = (abs(f1ID) == ParticleID::SUSY_chi_1plus) ? 0 : 1; unsigned int ej = (abs(f2ID) == ParticleID::SUSY_chi_1plus) ? 0 : 1; theLLast = conj(theQij[ej][ei])*theSa - conj(theSij[ej][ei])*theCa; theRLast = theQij[ei][ej]*theSa - theSij[ei][ej]*theCa; } //neutralinos else { unsigned int ei(f1ID - ParticleID::SUSY_chi_10), ej(f2ID - ParticleID::SUSY_chi_10); if( ei > 1 ) ei = ( ei == 13 ) ? 3 : 2; if( ej > 1 ) ej = ( ej == 13 ) ? 3 : 2; theLLast = conj(theQijdp[ej][ei])*theSa + conj(theSijdp[ej][ei])*theCa; theRLast = theQijdp[ei][ej]*theSa + theSijdp[ei][ej]*theCa ; } } else if( higgsID == ParticleID::H0 ) { //charginos if( abs(f2ID) == ParticleID::SUSY_chi_1plus || abs(f2ID) == ParticleID::SUSY_chi_2plus ) { unsigned int ei = (abs(f1ID) == ParticleID::SUSY_chi_1plus) ? 0 : 1; unsigned int ej = (abs(f2ID) == ParticleID::SUSY_chi_1plus) ? 0 : 1; theLLast = -conj(theQij[ej][ei])*theCa - conj(theSij[ej][ei])*theSa; theRLast = -theQij[ei][ej]*theCa - theSij[ei][ej]*theSa; } //neutralinos else { unsigned int ei(f1ID - ParticleID::SUSY_chi_10), ej(f2ID - ParticleID::SUSY_chi_10); if( ei > 1 ) ei = ( ei == 13 ) ? 3 : 2; if( ej > 1 ) ej = ( ej == 13 ) ? 3 : 2; theLLast = -conj(theQijdp[ej][ei])*theCa + conj(theSijdp[ej][ei])*theSa; theRLast = -theQijdp[ei][ej]*theCa + theSijdp[ei][ej]*theSa; } } else if( higgsID == ParticleID::A0 ) { if( abs(f2ID) == ParticleID::SUSY_chi_1plus || abs(f2ID) == ParticleID::SUSY_chi_2plus ) { unsigned int ei = (abs(f1ID) == ParticleID::SUSY_chi_1plus) ? 0 : 1; unsigned int ej = (abs(f2ID) == ParticleID::SUSY_chi_1plus) ? 0 : 1; theLLast = Complex(0.,1.)*( conj(theQij[ej][ei])*theSb + conj(theSij[ej][ei])*theCb ); theRLast = -Complex(0.,1.)*(theQij[ei][ej]*theSb + theSij[ei][ej]*theCb); } //neutralinos else { unsigned int ei(f1ID - ParticleID::SUSY_chi_10), ej(f2ID - ParticleID::SUSY_chi_10); if( ei > 1 ) ei = ( ei == 13 ) ? 3 : 2; if( ej > 1 ) ej = ( ej == 13 ) ? 3 : 2; theLLast = Complex(0.,1.)*( conj(theQijdp[ej][ei])*theSb - conj(theSijdp[ej][ei])*theCb ); theRLast = -Complex(0.,1.)*(theQijdp[ei][ej]*theSb - theSijdp[ei][ej]*theCb); } } //charged higgs else { unsigned int ei(0),ej(0); long chg(f2ID), neu(f1ID); if( abs(neu) == ParticleID::SUSY_chi_1plus || abs(neu) == ParticleID::SUSY_chi_2plus ) swap(chg, neu); ej = ( abs(chg) == ParticleID::SUSY_chi_1plus) ? 0 : 1; ei = neu - ParticleID::SUSY_chi_10; if( ei > 1 ) ei = ( ei == 13 ) ? 3 : 2; theLLast = -theQijLp[ei][ej]*theCb; theRLast = -theQijRp[ei][ej]*theSb; if( higgsID < 0 ) { Complex tmp = theLLast; theLLast = conj(theRLast); theRLast = conj(tmp); } } norm(theCoupLast); left(theLLast); right(theRLast); } diff --git a/Models/Susy/SSGSGSGVertex.cc b/Models/Susy/SSGSGSGVertex.cc --- a/Models/Susy/SSGSGSGVertex.cc +++ b/Models/Susy/SSGSGSGVertex.cc @@ -1,58 +1,59 @@ // -*- C++ -*- // // SSGSGSGVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SSGSGSGVertex class. // #include "SSGSGSGVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" using namespace ThePEG::Helicity; using namespace Herwig; SSGSGSGVertex::SSGSGSGVertex() : _couplast(0.),_q2last(ZERO) { orderInGs(1); orderInGem(0); + colourStructure(ColourStructure::SU3F); } // Static variable needed for the type description system in ThePEG. DescribeNoPIOClass describeHerwigSSGSGSGVertex("Herwig::SSGSGSGVertex", "HwSusy.so"); void SSGSGSGVertex::Init() { static ClassDocumentation documentation ("This class implements the gluon-gluino-gluino vertex"); } void SSGSGSGVertex::setCoupling(Energy2 q2,tcPDPtr part1, tcPDPtr part2,tcPDPtr part3) { assert(part1->id()==ParticleID::SUSY_g && part2->id()==ParticleID::SUSY_g && part3->id() == ParticleID::g); if(q2 != _q2last || _couplast==0.) { _couplast = strongCoupling(q2); _q2last = q2; } norm(_couplast); left(1.); right(1.); } void SSGSGSGVertex::doinit() { addToList(1000021, 1000021, 21); FFVVertex::doinit(); } diff --git a/Models/Susy/SSGSSVertex.cc b/Models/Susy/SSGSSVertex.cc --- a/Models/Susy/SSGSSVertex.cc +++ b/Models/Susy/SSGSSVertex.cc @@ -1,67 +1,68 @@ // -*- C++ -*- // // SSGSSVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SSGSSVertex class. // #include "SSGSSVertex.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" using namespace ThePEG::Helicity; using namespace Herwig; SSGSSVertex::SSGSSVertex() : _couplast(0.),_q2last(ZERO) { orderInGs(1); orderInGem(0); + colourStructure(ColourStructure::SU3TFUND); } void SSGSSVertex::doinit() { for(long ix=1000001;ix<1000007;++ix) { addToList(21,ix,-ix); } for(long ix=2000001;ix<2000007;++ix) { addToList(21,ix,-ix); } VSSVertex::doinit(); } // The following static variable is needed for the type // description system in ThePEG. DescribeNoPIOClass describeSSGSSVertex("Herwig::SSGSSVertex", "HwSusy.so"); void SSGSSVertex::Init() { static ClassDocumentation documentation ("The SSGSSVertex class implements the coupling" " of the gluon to the squarks"); } void SSGSSVertex::setCoupling(Energy2 q2, tcPDPtr part1, tcPDPtr part2, tcPDPtr part3) { assert(part1->id()==ParticleID::g); long isf = abs(part2->id()); assert( (isf >= 1000001 && isf <= 1000006) || (isf >= 2000001 && isf <= 2000006) ); assert(part2->id()==-part3->id()); if(q2 != _q2last || _couplast == 0.) { _couplast = strongCoupling(q2); _q2last = q2; } if(part2->id()>0) norm(-_couplast); else norm( _couplast); } diff --git a/Models/Susy/SSGVFSVertex.cc b/Models/Susy/SSGVFSVertex.cc --- a/Models/Susy/SSGVFSVertex.cc +++ b/Models/Susy/SSGVFSVertex.cc @@ -1,129 +1,130 @@ // -*- C++ -*- // // SSGVFSVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SSGVFSVertex class. // #include "SSGVFSVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG::Helicity; using namespace Herwig; SSGVFSVertex::SSGVFSVertex() : MPlanck_(2.4e18*GeV) { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::DELTA); } void SSGVFSVertex::persistentOutput(PersistentOStream & os) const { os << stop_ << sbot_ << stau_ << ounit(MPlanck_,GeV); } void SSGVFSVertex::persistentInput(PersistentIStream & is, int) { is >> stop_ >> sbot_ >> stau_ >> iunit(MPlanck_,GeV); } void SSGVFSVertex::doinit() { //quarks for(long ix=1;ix<7;++ix){ addToList( ParticleID::SUSY_Gravitino, ix, -(1000000+ix) ); addToList( ParticleID::SUSY_Gravitino, ix, -(2000000+ix) ); addToList( ParticleID::SUSY_Gravitino, -ix, (1000000+ix) ); addToList( ParticleID::SUSY_Gravitino, -ix, (2000000+ix) ); } //leptons for(long ix=11;ix<17;++ix) { addToList( ParticleID::SUSY_Gravitino, ix, -(1000000+ix) ); addToList( ParticleID::SUSY_Gravitino, -ix, (1000000+ix) ); if( ix % 2 != 0 ) { addToList( ParticleID::SUSY_Gravitino, ix, -(2000000+ix) ); addToList( ParticleID::SUSY_Gravitino, -ix, (2000000+ix) ); } } RFSVertex::doinit(); tMSSMPtr model = dynamic_ptr_cast(generator()->standardModel()); if( !model ) throw InitException() << "SSGVFSVertex::doinit() - " << "The model pointer is null." << Exception::abortnow; MPlanck_ = model->MPlanck(); stop_ = model->stopMix(); sbot_ = model->sbottomMix(); stau_ = model->stauMix(); } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigSSGVFSVertex("Herwig::SSGVFSVertex", "libHwSusy.so"); void SSGVFSVertex::Init() { static ClassDocumentation documentation ("The SSGVFSVertex implements the coupling of the gravitino to " "a fermion-sfermion"); } void SSGVFSVertex::setCoupling(Energy2 , #ifndef NDEBUG tcPDPtr part1, #else tcPDPtr, #endif tcPDPtr part2,tcPDPtr part3) { assert(part1->id()==ParticleID::SUSY_Gravitino); assert(part3->iSpin()==PDT::Spin0); norm(double(sqrt(2.)/MPlanck_*UnitRemoval::E)); // sfermion mass eigenstate unsigned int alpha(abs(part3->id())/1000000 - 1); unsigned int ism(abs(part2->id())); Complex lc,rc; //heavy quarks/sleptons if( ism == 5 || ism == 6 || ism == 15 ) { Complex ma1(0.), ma2(0.); if( ism == 5 ) { ma1 = (*sbot_)(alpha,0); ma2 = (*sbot_)(alpha,1); } else if( ism == 6 ) { ma1 = (*stop_)(alpha,0); ma2 = (*stop_)(alpha,1); } else { ma1 = (*stau_)(alpha,0); ma2 = (*stau_)(alpha,1); } lc = - ma2; rc = + ma1; } else { if( alpha == 0 ) { lc = 0.; rc = 1.; } else { lc = -1.; rc = 0.; } } // determine the helicity order of the vertex if( part2->id() < 0 ) { left (conj(rc)); right(conj(lc)); } else { left (lc); right(rc); } } diff --git a/Models/Susy/SSGVNHVertex.cc b/Models/Susy/SSGVNHVertex.cc --- a/Models/Susy/SSGVNHVertex.cc +++ b/Models/Susy/SSGVNHVertex.cc @@ -1,109 +1,110 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the SSGVNHVertex class. // #include "SSGVNHVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include "MSSM.h" using namespace Herwig; SSGVNHVertex::SSGVNHVertex() : sa_(0.), sb_(0.), ca_(0.), cb_(0.), MPlanck_(2.4e18*GeV) { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::SINGLET); } IBPtr SSGVNHVertex::clone() const { return new_ptr(*this); } IBPtr SSGVNHVertex::fullclone() const { return new_ptr(*this); } void SSGVNHVertex::persistentOutput(PersistentOStream & os) const { os << sa_ << sb_ << ca_ << cb_ << nmix_ << ounit(MPlanck_,GeV); } void SSGVNHVertex::persistentInput(PersistentIStream & is, int) { is >> sa_ >> sb_ >> ca_ >> cb_ >> nmix_ >> iunit(MPlanck_,GeV); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigSSGVNHVertex("Herwig::SSGVNHVertex", "HwSusy.so"); void SSGVNHVertex::Init() { static ClassDocumentation documentation ("The SSGVNHVertex class implments the coupling of the Higgs" " bosons to a gravitino and a neutralino"); } void SSGVNHVertex::doinit() { long neu[4] = {ParticleID::SUSY_chi_10, ParticleID::SUSY_chi_20, ParticleID::SUSY_chi_30, ParticleID::SUSY_chi_40}; long higgs[3] = {25, 35, 36}; for(unsigned int i = 0; i < 3; ++i) { for(unsigned int j = 0; j < 4; ++j) { addToList(ParticleID::SUSY_Gravitino, neu[j], higgs[i]); } } RFSVertex::doinit(); tMSSMPtr model = dynamic_ptr_cast(generator()->standardModel()); if( !model ) throw InitException() << "SSGVNHVertex::doinit() - The pointer to the MSSM object is null!" << Exception::abortnow; double tanb = model->tanBeta(); sb_ = tanb/sqrt(1. + sqr(tanb)); cb_ = sqrt( 1. - sqr(sb_) ); sa_ = sin(model->higgsMixingAngle()); ca_ = sqrt(1. - sqr(sa_)); nmix_ = model->neutralinoMix(); MPlanck_ = model->MPlanck(); } void SSGVNHVertex::setCoupling(Energy2 , #ifndef NDEBUG tcPDPtr part1, #else tcPDPtr, #endif tcPDPtr part2,tcPDPtr part3) { assert(part1->id()==ParticleID::SUSY_Gravitino); assert(part3->iSpin()==PDT::Spin0); unsigned int neut = part2->id() - ParticleID::SUSY_chi_10; if(neut>1) neut = ( neut == 13 ) ? 3 : 2; int hid = part3->id(); Complex coup; switch(hid) { case ParticleID::h0 : left (1.); right(1.); coup = -(*nmix_)(neut,2)*sa_+(*nmix_)(neut,3)*ca_; break; case ParticleID::H0 : left (1.); right(1.); coup = (*nmix_)(neut,2)*ca_+(*nmix_)(neut,3)*sa_; break; case ParticleID::A0 : left (Complex(0.,-1.)); right(Complex(0., 1.)); coup = (*nmix_)(neut,2)*sb_+(*nmix_)(neut,3)*cb_; break; default : assert(false); } norm(coup/MPlanck_*UnitRemoval::E); } diff --git a/Models/Susy/SSGVNVVertex.cc b/Models/Susy/SSGVNVVertex.cc --- a/Models/Susy/SSGVNVVertex.cc +++ b/Models/Susy/SSGVNVVertex.cc @@ -1,119 +1,120 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the SSGVNVVertex class. // #include "SSGVNVVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "MSSM.h" using namespace Herwig; SSGVNVVertex::SSGVNVVertex() : sw_(0.), cw_(0.), sb_(0.), cb_(0.), mz_(91.1876*GeV), MPlanck_(2.4e18*GeV) { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::SINGLET); } IBPtr SSGVNVVertex::clone() const { return new_ptr(*this); } IBPtr SSGVNVVertex::fullclone() const { return new_ptr(*this); } void SSGVNVVertex::persistentOutput(PersistentOStream & os) const { os << sw_ << cw_ << sb_ << cb_ << ounit(mz_,GeV) << nmix_ << ounit(MPlanck_,GeV); } void SSGVNVVertex::persistentInput(PersistentIStream & is, int) { is >> sw_ >> cw_ >> sb_ >> cb_ >> iunit(mz_,GeV) >> nmix_ >> iunit(MPlanck_,GeV); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigSSGVNVVertex("Herwig::SSGVNVVertex", "SSGVNVVertex.so"); void SSGVNVVertex::Init() { static ClassDocumentation documentation ("The SSGVNVVertex class implements the coupling of the gravitino" " to the neutralino and a photon or Z boson, or the gluino and gluon."); } void SSGVNVVertex::doinit() { long neu[4] = {ParticleID::SUSY_chi_10, ParticleID::SUSY_chi_20, ParticleID::SUSY_chi_30, ParticleID::SUSY_chi_40}; for(unsigned int j = 0; j < 4; ++j) { addToList(ParticleID::SUSY_Gravitino, neu[j], ParticleID::gamma); addToList(ParticleID::SUSY_Gravitino, neu[j], ParticleID::Z0); } addToList(ParticleID::SUSY_Gravitino, ParticleID::SUSY_g, ParticleID::g); RFVVertex::doinit(); tMSSMPtr model = dynamic_ptr_cast(generator()->standardModel()); if( !model ) throw InitException() << "SSGVNVVertex::doinit() - The pointer to the MSSM object is null!" << Exception::abortnow; double tanb = model->tanBeta(); sb_ = tanb/sqrt(1. + sqr(tanb)); cb_ = sqrt( 1. - sqr(sb_) ); sw_ = sqrt(sin2ThetaW()); cw_ = sqrt(1. - sin2ThetaW()); nmix_ = model->neutralinoMix(); MPlanck_ = model->MPlanck(); } void SSGVNVVertex::setCoupling(Energy2 , #ifndef NDEBUG tcPDPtr part1, #else tcPDPtr, #endif tcPDPtr part2,tcPDPtr part3) { assert(part1->id()==ParticleID::SUSY_Gravitino); assert(part3->iSpin()==PDT::Spin1); unsigned int neut = part2->id() - ParticleID::SUSY_chi_10; if(neut>1) neut = ( neut == 13 ) ? 3 : 2; int bid = part3->id(); Complex coup[2]; vector lV,rV; switch(bid) { case ParticleID::gamma : coup[0] = (*nmix_)(neut,0)*cw_+(*nmix_)(neut,1)*sw_; lV.push_back(-coup[0]*part2->mass()*UnitRemoval::InvE); lV.push_back( coup[0]); lV.push_back(0.); rV=lV; break; case ParticleID::Z0 : coup[0] = -(*nmix_)(neut,0)*sw_+(*nmix_)(neut,1)*cw_; coup[1] = -(*nmix_)(neut,2)*cb_+(*nmix_)(neut,3)*sb_; lV.push_back((-coup[0]*part2->mass()-mz_*coup[1])*UnitRemoval::InvE); lV.push_back( coup[0]); lV.push_back(0.); rV=lV; rV[0] = (-coup[0]*part2->mass()+mz_*coup[1])*UnitRemoval::InvE; break; case ParticleID::g : lV.push_back(-double(part2->mass()*UnitRemoval::InvE)); lV.push_back(1.); lV.push_back(0.); rV=lV; break; default : assert(false); } left (lV); right(rV); norm(double(1./MPlanck_*UnitRemoval::E)); } diff --git a/Models/Susy/SSHGGVertex.cc b/Models/Susy/SSHGGVertex.cc --- a/Models/Susy/SSHGGVertex.cc +++ b/Models/Susy/SSHGGVertex.cc @@ -1,292 +1,293 @@ // -*- C++ -*- // // SSHGGVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SSHGGVertex class. // #include "SSHGGVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include "Herwig/Looptools/clooptools.h" #include using namespace ThePEG::Helicity; using namespace Herwig; SSHGGVertex::SSHGGVertex() : theIncludeTriLinear(true), thePseudoScalarTreatment(false), theSw(0.), theMw(), theZfact(), theQt1L(0.), theQt1R(0.), theQt1LR(0.), theQt2L(0.), theQt2R(0.), theQt2LR(0.), theQb1L(0.), theQb1R(0.), theQb1LR(0.), theQb2L(0.), theQb2R(0.), theQb2LR(0.), theSqmass(4,ZERO), theTanB(0.),theSinA(0.), theCosA(0.), theSinB(0.), theCosB(0.), theSinApB(0.), theCosApB(0.), theCouplast(0.), theq2last(), theHaveCoeff(false), theLastID(0) { orderInGs(2); orderInGem(1); + colourStructure(ColourStructure::DELTA); } void SSHGGVertex::doinit() { //PDG codes for particles at vertices addToList(21,21,25); addToList(21,21,35); addToList(21,21,36); theMSSM = dynamic_ptr_cast(generator()->standardModel()); if( !theMSSM ) throw InitException() << "SSHGGVertex::doinit() - The pointer to the MSSM object is null!" << Exception::abortnow; theMw = getParticleData(ParticleID::Wplus)->mass(); thetop = getParticleData(ParticleID::t); thebot = getParticleData(ParticleID::b); theSw = sqrt(sin2ThetaW()); theZfact = getParticleData(ParticleID::Wplus)->mass()/(1. - sqr(theSw)); theSinA = sin(theMSSM->higgsMixingAngle()); theCosA = sqrt(1. - sqr(theSinA)); theTanB = theMSSM->tanBeta(); theSinB = theTanB/sqrt(1. + sqr(theTanB)); theCosB = sqrt( 1. - sqr(theSinB) ); theSinApB = theSinA*theCosB + theCosA*theSinB; theCosApB = theCosA*theCosB - theSinA*theSinB; MixingMatrixPtr stop = theMSSM->stopMix(); MixingMatrixPtr sbot = theMSSM->sbottomMix(); theQt1L = (*stop)(0,0)*(*stop)(0,0); theQt1R = (*stop)(0,1)*(*stop)(0,1); theQt1LR = (*stop)(0,1)*(*stop)(0,0) + (*stop)(0,1)*(*stop)(0,0); theQt2L = (*stop)(1,0)*(*stop)(1,0); theQt2R = (*stop)(1,1)*(*stop)(1,1); theQt2LR = (*stop)(1,1)*(*stop)(1,0) + (*stop)(1,0)*(*stop)(1,1); theQb1L = (*sbot)(0,0)*(*sbot)(0,0); theQb1R = (*sbot)(0,1)*(*sbot)(0,1); theQb1LR = (*sbot)(0,1)*(*sbot)(0,0) + (*sbot)(0,1)*(*sbot)(0,0); theQb2L = (*sbot)(1,0)*(*sbot)(1,0); theQb2R = (*sbot)(1,1)*(*sbot)(1,1); theQb2LR = (*sbot)(1,1)*(*sbot)(1,0) + (*sbot)(1,0)*(*sbot)(1,1); assert( theSqmass.size() == 4 ); theSqmass[0] = getParticleData(ParticleID::SUSY_b_1)->mass(); theSqmass[1] = getParticleData(ParticleID::SUSY_t_1)->mass(); theSqmass[2] = getParticleData(ParticleID::SUSY_b_2)->mass(); theSqmass[3] = getParticleData(ParticleID::SUSY_t_2)->mass(); VVSLoopVertex::doinit(); if(loopToolsInitialized()) Looptools::ltexi(); } void SSHGGVertex::persistentOutput(PersistentOStream & os) const { os << theMSSM << theSw << ounit(theMw,GeV) << ounit(theZfact,GeV) << theQt1L << theQt1R << theQt1LR << theQt2L << theQt2R << theQt2LR << theQb1L << theQb1R << theQb1LR << theQb2L << theQb2R << theQb2LR << thetop << thebot << theTanB << theIncludeTriLinear << theSinA << theCosA << theSinB << theCosB << theSinApB << theCosApB << ounit(theSqmass, GeV) << thePseudoScalarTreatment; } void SSHGGVertex::persistentInput(PersistentIStream & is, int) { is >> theMSSM >> theSw >> iunit(theMw,GeV) >> iunit(theZfact,GeV) >> theQt1L >> theQt1R >> theQt1LR >> theQt2L >> theQt2R >> theQt2LR >> theQb1L >> theQb1R >> theQb1LR >> theQb2L >> theQb2R >> theQb2LR >> thetop >> thebot >> theTanB >> theIncludeTriLinear >> theSinA >> theCosA >> theSinB >> theCosB >> theSinApB >> theCosApB >> iunit(theSqmass, GeV) >> thePseudoScalarTreatment; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigSSHGGVertex("Herwig::SSHGGVertex", "HwSusy.so"); void SSHGGVertex::Init() { static ClassDocumentation documentation ("This class implements the higgs-gluon-gluon effective " "vertex in the MSSM including stop, sbottom and top quarks " "loops."); static Switch interfaceIncludeTriLinear ("IncludeTriLinear", "Whether or not to include the A term squark trilinear couplings", &SSHGGVertex::theIncludeTriLinear, true, false, false); static SwitchOption interfaceIncludeTriLinearYes (interfaceIncludeTriLinear, "Yes", "Include them", true); static SwitchOption interfaceIncludeTriLinearNo (interfaceIncludeTriLinear, "No", "Don't include them", false); static Switch interfacePseudoScalarTreatment ("PseudoScalarTreatment", "Whether to treat the pseudoscalar as pseudoscalar or scalar, for testing only", &SSHGGVertex::thePseudoScalarTreatment, false, false, false); static SwitchOption interfacePseudoScalarTreatmentPseudoScalar (interfacePseudoScalarTreatment, "PseudoScalar", "Treat as a pseudoscalar, the right physics", false); static SwitchOption interfacePseudoScalarTreatmentScalar (interfacePseudoScalarTreatment, "Scalar", "Treat as a scalar for testing", true); } void SSHGGVertex::setCoupling(Energy2 q2, tcPDPtr particle2, tcPDPtr particle3, tcPDPtr particle1) { long higgs(abs(particle1->id())); assert( higgs == ParticleID::h0 || higgs == ParticleID::H0 || higgs == ParticleID::A0 ); assert(particle2->id() == ParticleID::g && particle3->id() == ParticleID::g ); if( q2 != theq2last || theCouplast == 0. || higgs != theLastID ) { Looptools::clearcache(); theCouplast = weakCoupling(q2)*sqr(strongCoupling(q2)); Energy mt = theMSSM->mass(q2, thetop); Energy mb = theMSSM->mass(q2, thebot); masses.clear(); type.clear(); if( higgs == ParticleID::h0 || higgs == ParticleID::H0 ) { setNParticles(6); masses.insert(masses.begin(), theSqmass.begin(), theSqmass.end()); masses.push_back(mt); masses.push_back(mb); type.resize(6, PDT::Spin0); type[4] = PDT::Spin1Half; type[5] = PDT::Spin1Half; couplings.resize(6, make_pair(0., 0.)); complex brac1 = theZfact*(0.5 + theMSSM->ed()*sqr(theSw)); complex brac2 = theZfact*(0.5 - theMSSM->eu()*sqr(theSw)); complex brac3 = theZfact*theMSSM->ed()*sqr(theSw); complex brac4 = theZfact*theMSSM->eu()*sqr(theSw); Energy Trib=theMSSM->bottomTrilinear().real(); Energy Trit=theMSSM->topTrilinear().real(); Energy theMu = theMSSM->muParameter(); if( higgs == ParticleID::h0 ) { // lightest sbottom complex trilinear = theIncludeTriLinear ? theQb1LR*0.5*mb/theMw*(Trib*theSinA + theMu*theCosA)/theCosB : Energy(); Complex coup = 0.5*UnitRemoval::InvE* (theQb1L *( sqr(mb)*theSinA/theMw/theCosB - theSinApB*brac1) + theQb1R *( sqr(mb)*theSinA/theMw/theCosB + theSinApB*brac3)+trilinear); couplings[0] = make_pair(coup, coup); // lightest stop trilinear = theIncludeTriLinear ? -theQt1LR*0.5*mt/theMw*(Trit*theCosA + theMu*theSinA)/theSinB : Energy(); coup = 0.5*UnitRemoval::InvE* (theQt1L *( - sqr(mt)*theCosA/theMw/theSinB + theSinApB*brac2) + theQt1R *( - sqr(mt)*theCosA/theMw/theSinB + theSinApB*brac4)+trilinear); couplings[1] = make_pair(coup, coup); // heavier sbottom trilinear = theIncludeTriLinear ? theQb2LR*0.5*mb/theMw*(Trib*theSinA + theMu*theCosA)/theCosB : Energy(); coup = 0.5*UnitRemoval::InvE* (theQb2L *( sqr(mb)*theSinA/theMw/theCosB - theSinApB*brac1) + theQb2R *( sqr(mb)*theSinA/theMw/theCosB + theSinApB*brac3)+trilinear); couplings[2] = make_pair(coup, coup); // heavier stop trilinear = theIncludeTriLinear ? -theQt2LR*0.5*mt/theMw*(Trit*theCosA + theMu*theSinA)/theSinB : Energy(); coup = 0.5*UnitRemoval::InvE* (theQt2L *( - sqr(mt)*theCosA/theMw/theSinB + theSinApB*brac2) + theQt2R *( - sqr(mt)*theCosA/theMw/theSinB + theSinApB*brac4)+trilinear); couplings[3] = make_pair(coup, coup); // top coup = -0.25*(mt*theCosA/theMw/theSinB); couplings[4] = make_pair(coup, coup); // bottom coup = +0.25*(mb*theSinA/theMw/theCosB); couplings[5] = make_pair(coup, coup); } else { // lightest sbottom complex trilinear = theIncludeTriLinear ? theQb1LR*0.5*mb/theMw*(theMu*theSinA - Trib*theCosA)/theCosB: Energy(); Complex coup = 0.5*UnitRemoval::InvE* (theQb1L *( - sqr(mb)*theCosA/theMw/theCosB + theCosApB*brac1) + theQb1R *( - sqr(mb)*theCosA/theMw/theCosB - theCosApB*brac3)+trilinear); couplings[0] = make_pair(coup, coup); // lightest stop trilinear = theIncludeTriLinear ? -theQt1LR*0.5*mt/theMw*(-theMu*theCosA + Trit*theSinA)/theSinB: Energy(); coup = 0.5*UnitRemoval::InvE* (theQt1L *( - sqr(mt)*theSinA/theMw/theSinB - theCosApB*brac2) + theQt1R *( - sqr(mt)*theSinA/theMw/theSinB - theCosApB*brac4)+trilinear); couplings[1] = make_pair(coup, coup); // heavier sbottom trilinear = theIncludeTriLinear ? theQb2LR*0.5*mb/theMw*(theMu*theSinA - Trib*theCosA)/theCosB: Energy(); coup = 0.5*UnitRemoval::InvE* (theQb2L *( - sqr(mb)*theCosA/theMw/theCosB + theCosApB*brac1) + theQb2R *( - sqr(mb)*theCosA/theMw/theCosB - theCosApB*brac3)+trilinear); couplings[2] = make_pair(coup, coup); // heavier stop trilinear = theIncludeTriLinear ? -theQt2LR*0.5*mt/theMw*(-theMu*theCosA + Trit*theSinA)/theSinB: Energy(); coup = 0.5*UnitRemoval::InvE* (theQt2L *( - sqr(mt)*theSinA/theMw/theSinB - theCosApB*brac2) + theQt2R *( - sqr(mt)*theSinA/theMw/theSinB - theCosApB*brac4)+trilinear); couplings[3] = make_pair(coup, coup); // top coup = -0.25*mt*theSinA/theMw/theSinB; couplings[4] = make_pair(coup, coup); // bottom coup = -0.25*mb*theCosA/theMw/theCosB; couplings[5] = make_pair(coup, coup); } } else { setNParticles(2); masses.resize(2); couplings.resize(2); masses[0] = mt; masses[1] = mb; type.resize(2,PDT::Spin1Half); Complex coup = 0.25*Complex(0., 1.)*mt/theMw/theTanB; couplings[0] = make_pair(coup, thePseudoScalarTreatment ? coup : -coup); coup = 0.25*Complex(0., 1.)*mb/theMw*theTanB; couplings[1] = make_pair(coup, thePseudoScalarTreatment ? coup : -coup); } theq2last = q2; theLastID = higgs; theHaveCoeff = false; } norm(theCouplast); //calculate tensor coefficients if( !theHaveCoeff ) { VVSLoopVertex::setCoupling(q2, particle2, particle3, particle1); theHaveCoeff = true; } } diff --git a/Models/Susy/SSHHHVertex.cc b/Models/Susy/SSHHHVertex.cc --- a/Models/Susy/SSHHHVertex.cc +++ b/Models/Susy/SSHHHVertex.cc @@ -1,148 +1,149 @@ // -*- C++ -*- // // SSHHHVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SSHHHVertex class. // #include "SSHHHVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include using namespace ThePEG::Helicity; using namespace Herwig; SSHHHVertex::SSHHHVertex() : theMw(ZERO), theZfact(ZERO), theSw(0.), theSbpa(0.), theCbpa(0.), theSbma(0.), theCbma(0.), theS2a(0.), theC2a(0.), theS2b(0.), theC2b(0.), theElast(0.), theq2last(ZERO) { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::SINGLET); } void SSHHHVertex::doinit() { long sec = 35; for(long h = 25; h < 36; h += 10) { //self-coupling addToList(h, h, h); //first-second addToList(h,sec,sec); //pseudo-scalar addToList(h, 36, 36); //charged higgs addToList(h, 37,-37); sec = 25; } SSSVertex::doinit(); tMSSMPtr theMSSM = dynamic_ptr_cast(generator()->standardModel()); if( !theMSSM ) throw InitException() << "SSHHHVertex::doinit() - The pointer to the MSSM object is null!" << Exception::abortnow; theMw = getParticleData(ParticleID::Wplus)->mass(); theSw = sqrt(sin2ThetaW()); theZfact = getParticleData(ParticleID::Z0)->mass()/2./ theSw/sqrt(1. - sqr(theSw)); double tanbeta = theMSSM->tanBeta(); double sinbeta = tanbeta/sqrt(1. + sqr(tanbeta)); double cosbeta = sqrt(1. - sqr(sinbeta)); double sinalpha = sin(theMSSM->higgsMixingAngle()); double cosalpha = sqrt( 1. - sqr(sinalpha) ); theS2a = 2.*sinalpha*cosalpha; theS2b = 2.*sinbeta*cosbeta; theC2a = cosalpha*cosalpha - sinalpha*sinalpha; theC2b = cosbeta*cosbeta - sinbeta*sinbeta; theSbpa = sinbeta*cosalpha + sinalpha*cosbeta; theCbpa = cosbeta*cosalpha - sinbeta*sinalpha; theSbma = sinbeta*cosalpha - sinalpha*cosbeta; theCbma = cosbeta*cosalpha + sinbeta*sinalpha; } void SSHHHVertex::persistentOutput(PersistentOStream & os) const { os << ounit(theMw,GeV) << ounit(theZfact,GeV) << theSw << theSbpa << theCbpa << theSbma << theCbma << theS2a << theC2a << theS2b << theC2b; } void SSHHHVertex::persistentInput(PersistentIStream & is, int) { is >> iunit(theMw,GeV) >> iunit(theZfact,GeV) >> theSw >> theSbpa >> theCbpa >> theSbma >> theCbma >> theS2a >> theC2a >> theS2b >> theC2b; } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigSSHHHVertex("Herwig::SSHHHVertex", "HwSusy.so"); void SSHHHVertex::Init() { static ClassDocumentation documentation ("This is the coupling of a higgs to a pair of higgs bosons " "in the MSSM."); } void SSHHHVertex::setCoupling(Energy2 q2, tcPDPtr particle1, tcPDPtr particle2,tcPDPtr particle3) { long ids[3] = { abs(particle1->id()), abs(particle2->id()), abs(particle3->id()) }; long h1(0), h2(0), h3(0), hc(0); for(unsigned int i = 0; i < 3; ++i) { if( ids[i] == ParticleID::h0) ++h1; else if( ids[i] == ParticleID::H0) ++h2; else if( ids[i] == ParticleID::A0) ++h3; else if( ids[i] == ParticleID::Hplus) ++hc; else assert(false); } assert(h1 + h2 + h3 + hc == 3); complex coupling; if( h1 == 3 || h2 == 3 ) { coupling = -3.*theZfact*theC2a; if( h1 == 3 ) coupling *= theSbpa; else coupling *= theCbpa; } else if( h1 == 1 ) { if( h2 == 2 ) coupling = theZfact*( 2.*theS2a*theCbpa + theSbpa*theC2a ); else if( h3 == 2 ) coupling = -theZfact*theC2b*theSbpa; else if( hc == 2 ) coupling = -theMw*theSbma/theSw - theZfact*theC2b*theSbpa; else assert(false); } else if( h2 == 1 ) { if( h1 == 2 ) coupling = -theZfact*( 2.*theS2a*theSbpa - theCbpa*theC2a ); else if( h3 == 2 ) coupling = theZfact*theC2b*theCbpa; else if( hc == 2 ) coupling = -theMw*theCbma/theSw + theZfact*theC2b*theCbpa; else assert(false); } if( q2 != theq2last || theElast==0. ) { theq2last = q2; theElast = electroMagneticCoupling(q2); } norm(theElast*coupling*UnitRemoval::InvE); } diff --git a/Models/Susy/SSHPPVertex.cc b/Models/Susy/SSHPPVertex.cc --- a/Models/Susy/SSHPPVertex.cc +++ b/Models/Susy/SSHPPVertex.cc @@ -1,633 +1,634 @@ // -*- C++ -*- // // SSHPPVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SSHPPVertex class. // #include "SSHPPVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include #include "Herwig/Looptools/clooptools.h" using namespace ThePEG::Helicity; using namespace Herwig; SSHPPVertex::SSHPPVertex() : theIncludeTriLinear(true), thePseudoScalarTreatment(false), theSw(0.), theMw(), theZfact(), theQt1L(0.), theQt1R(0.), theQt1LR(0.), theQt2L(0.), theQt2R(0.), theQt2LR(0.), theQb1L(0.), theQb1R(0.), theQb1LR(0.), theQb2L(0.), theQb2R(0.), theQb2LR(0.), theLt1L(0.), theLt1R(0.), theLt1LR(0.), theLt2L(0.), theLt2R(0.), theLt2LR(0.), theSfmass(6,ZERO), theTanB(0.),theSinA(0.), theCosA(0.), theSinB(0.), theCosB(0.), theSinApB(0.), theCosApB(0.), theSinBmA(0.), theCosBmA(0.), theCouplast(0.), theq2last(), theHaveCoeff(false), theLastID(0) { orderInGs(0); orderInGem(3); + colourStructure(ColourStructure::SINGLET); } void SSHPPVertex::persistentOutput(PersistentOStream & os) const { os << theMSSM << theSw << ounit(theMw,GeV) << ounit(theZfact,GeV) << theQt1L << theQt1R << theQt1LR << theQt2L << theQt2R << theQt2LR << theQb1L << theQb1R << theQb1LR << theQb2L << theQb2R << theQb2LR << theLt1L << theLt1R << theLt1LR << theLt2L << theLt2R << theLt2LR << thetop << thebot << thetau << theTanB << theIncludeTriLinear << theSinA << theCosA << theSinB << theCosB << theSinApB << theCosApB << theSinBmA << theCosBmA << thePseudoScalarTreatment << ounit(theSfmass, GeV) << theU << theV; } void SSHPPVertex::persistentInput(PersistentIStream & is, int) { is >> theMSSM >> theSw >> iunit(theMw,GeV) >> iunit(theZfact,GeV) >> theQt1L >> theQt1R >> theQt1LR >> theQt2L >> theQt2R >> theQt2LR >> theQb1L >> theQb1R >> theQb1LR >> theQb2L >> theQb2R >> theQb2LR >> theLt1L >> theLt1R >> theLt1LR >> theLt2L >> theLt2R >> theLt2LR >> thetop >> thebot >> thetau >> theTanB >> theIncludeTriLinear >> theSinA >> theCosA >> theSinB >> theCosB >> theSinApB >> theCosApB >> theSinBmA >> theCosBmA >> thePseudoScalarTreatment >> iunit(theSfmass, GeV) >> theU >> theV; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigSSHPPVertex("Herwig::SSHPPVertex", "HwSusy.so"); void SSHPPVertex::Init() { static ClassDocumentation documentation ("This class implements the higgs-gluon-gluon effective " "vertex in the MSSM including stop, sbottom and top quarks " "loops."); static Switch interfaceIncludeTriLinear ("IncludeTriLinear", "Whether or not to include the A term squark trilinear couplings", &SSHPPVertex::theIncludeTriLinear, true, false, false); static SwitchOption interfaceIncludeTriLinearYes (interfaceIncludeTriLinear, "Yes", "Include them", true); static SwitchOption interfaceIncludeTriLinearNo (interfaceIncludeTriLinear, "No", "Don't include them", false); static Switch interfacePseudoScalarTreatment ("PseudoScalarTreatment", "Whether to treat the pseudoscalar as pseudoscalar or scalar, for testing only", &SSHPPVertex::thePseudoScalarTreatment, false, false, false); static SwitchOption interfacePseudoScalarTreatmentPseudoScalar (interfacePseudoScalarTreatment, "PseudoScalar", "Treat as a pseudoscalar, the right physics", false); static SwitchOption interfacePseudoScalarTreatmentScalar (interfacePseudoScalarTreatment, "Scalar", "Treat as a scalar for testing", true); } void SSHPPVertex::setCoupling(Energy2 q2, tcPDPtr particle2, tcPDPtr particle3, tcPDPtr particle1) { long higgs(abs(particle1->id())); // check allowed assert ( higgs == ParticleID::h0 || higgs == ParticleID::H0 || higgs == ParticleID::A0 ); assert(particle2->id() == ParticleID::gamma && particle3->id() == ParticleID::gamma ); // couplings if( q2 != theq2last || theCouplast == 0. || higgs != theLastID ) { Looptools::clearcache(); theCouplast = sqr(electroMagneticCoupling(q2))*weakCoupling(q2); Energy mt = theMSSM->mass(q2, thetop); Energy mb = theMSSM->mass(q2, thebot); Energy mtau = theMSSM->mass(q2, thetau); masses.clear(); type.clear(); if( higgs == ParticleID::h0 || higgs == ParticleID::H0 ) { setNParticles(13); masses.insert(masses.begin(), theSfmass.begin(), theSfmass.end()); masses.push_back(mt); masses.push_back(mb); masses.push_back(mtau); masses.push_back(getParticleData(ParticleID::Hplus)->mass()); masses.push_back(theMw); masses.push_back(getParticleData(ParticleID::SUSY_chi_1plus)->mass()); masses.push_back(getParticleData(ParticleID::SUSY_chi_2plus)->mass()); type.resize(13, PDT::Spin0); type[6] = PDT::Spin1Half; type[7] = PDT::Spin1Half; type[8] = PDT::Spin1Half; type[9] = PDT::Spin0; type[10] = PDT::Spin1; type[11] = PDT::Spin1Half; type[12] = PDT::Spin1Half; couplings.resize(13, make_pair(0., 0.)); complex brac1 = theZfact*(0.5 + theMSSM->ed()*sqr(theSw)); complex brac2 = theZfact*(0.5 - theMSSM->eu()*sqr(theSw)); complex brac3 = theZfact*theMSSM->ed()*sqr(theSw); complex brac4 = theZfact*theMSSM->eu()*sqr(theSw); complex brac5 = theZfact*(0.5 + theMSSM->ee()*sqr(theSw)); complex brac6 = theZfact*theMSSM->ee()*sqr(theSw); Energy Trib=theMSSM->bottomTrilinear().real(); Energy Trit=theMSSM->topTrilinear().real(); Energy Trita=theMSSM->tauTrilinear().real(); Energy theMu = theMSSM->muParameter(); if( higgs == ParticleID::h0 ) { // lightest sbottom complex trilinear = theIncludeTriLinear ? theQb1LR*0.5*mb/theMw*(Trib*theSinA + theMu*theCosA)/theCosB : Energy(); Complex coup = 3.*UnitRemoval::InvE*sqr(theMSSM->ed())* (theQb1L *( sqr(mb)*theSinA/theMw/theCosB - theSinApB*brac1) + theQb1R *( sqr(mb)*theSinA/theMw/theCosB + theSinApB*brac3) + trilinear); couplings[0] = make_pair(coup, coup); // lightest stop trilinear = theIncludeTriLinear ? theQt1LR*0.5*mt/theMw*(Trit*theCosA + theMu*theSinA)/theSinB : Energy(); coup = 3.*UnitRemoval::InvE*sqr(theMSSM->eu())* (theQt1L *( - sqr(mt)*theCosA/theMw/theSinB + theSinApB*brac2) + theQt1R *( - sqr(mt)*theCosA/theMw/theSinB + theSinApB*brac4) - trilinear); couplings[1] = make_pair(coup, coup); // lightest stau trilinear = theIncludeTriLinear ? theLt1LR*0.5*mtau/theMw*(Trita*theSinA + theMu*theCosA)/theCosB : Energy(); coup = UnitRemoval::InvE*sqr(theMSSM->ee())* (theLt1L *( sqr(mtau)*theSinA/theMw/theCosB - theSinApB*brac5) + theLt1R *( sqr(mtau)*theSinA/theMw/theCosB + theSinApB*brac6) + trilinear); couplings[2] = make_pair(coup, coup); // heavier sbottom trilinear = theIncludeTriLinear ? theQb2LR*0.5*mb/theMw*(Trib*theSinA + theMu*theCosA)/theCosB : Energy(); coup = 3.*UnitRemoval::InvE*sqr(theMSSM->ed())* (theQb2L *( sqr(mb)*theSinA/theMw/theCosB - theSinApB*brac1) + theQb2R *( sqr(mb)*theSinA/theMw/theCosB + theSinApB*brac3) + trilinear); couplings[3] = make_pair(coup, coup); // heavier stop trilinear = theIncludeTriLinear ? theQt2LR*0.5*mt/theMw*(Trit*theCosA + theMu*theSinA)/theSinB : Energy(); coup = 3.*UnitRemoval::InvE*sqr(theMSSM->eu())* (theQt2L*( - sqr(mt)*theCosA/theMw/theSinB + theSinApB*brac2) + theQt2R*( - sqr(mt)*theCosA/theMw/theSinB + theSinApB*brac4) - trilinear); couplings[4] = make_pair(coup, coup); // heavier stau trilinear = theIncludeTriLinear ? theLt2LR*0.5*mtau/theMw*(Trita*theSinA + theMu*theCosA)/theCosB : Energy(); coup = UnitRemoval::InvE*sqr(theMSSM->ee())* (theLt2L *( sqr(mtau)*theSinA/theMw/theCosB - theSinApB*brac5) + theLt2R *( sqr(mtau)*theSinA/theMw/theCosB + theSinApB*brac6)+ trilinear); couplings[5] = make_pair(coup, coup); // top coup = - 3.*mt*sqr(theMSSM->eu())*theCosA/2./theMw/theSinB; couplings[6] = make_pair(coup, coup); // bottom coup = 3.*mb*sqr(theMSSM->ed())*theSinA/2./theMw/theCosB; couplings[7] = make_pair(coup, coup); // tau coup = mtau*sqr(theMSSM->ee())*theSinA/2./theMw/theCosB; couplings[8] = make_pair(coup, coup); // charged higgs coup = - UnitRemoval::InvE*theMw*(theSinBmA + 0.5/(1.-sqr(theSw))* (sqr(theCosB)-sqr(theSinB))*theSinApB); couplings[9] = make_pair(coup, coup); // W boson coup = UnitRemoval::InvE*theMw*theSinBmA; couplings[10] = make_pair(coup, coup); // charginos for(unsigned int ix=0;ix<2;++ix) { Complex Q = sqrt(0.5)*(*theV)(ix,0)*(*theU)(ix,1); Complex S = sqrt(0.5)*(*theV)(ix,1)*(*theU)(ix,0); coup = Q*theSinA-S*theCosA; couplings[11+ix] = make_pair(conj(coup), coup); } } else { // lightest sbottom complex trilinear = theIncludeTriLinear ? theQb1LR*0.5*mb/theMw*(theMu*theSinA - Trib*theCosA)/theCosB: Energy(); Complex coup = 3.*UnitRemoval::InvE*sqr(theMSSM->ed())* (theQb1L *( - sqr(mb)*theCosA/theMw/theCosB + theCosApB*brac1) + theQb1R *( - sqr(mb)*theCosA/theMw/theCosB - theCosApB*brac3)+trilinear); couplings[0] = make_pair(coup, coup); // lightest stop trilinear = theIncludeTriLinear ? -theQt1LR*0.5*mt/theMw*(-theMu*theCosA + Trit*theSinA)/theSinB: Energy(); coup = 3.*UnitRemoval::InvE*sqr(theMSSM->eu())* (theQt1L *( - sqr(mt)*theSinA/theMw/theSinB - theCosApB*brac2) + theQt1R *( - sqr(mt)*theSinA/theMw/theSinB - theCosApB*brac4)+trilinear); couplings[1] = make_pair(coup, coup); // lightest stau trilinear = theIncludeTriLinear ? theLt1LR*0.5*mtau/theMw*(theMu*theSinA - Trita*theCosA)/theCosB: Energy(); coup = UnitRemoval::InvE*sqr(theMSSM->ee())* (theLt1L *( - sqr(mtau)*theCosA/theMw/theCosB + theCosApB*brac5) + theLt1R *( - sqr(mtau)*theCosA/theMw/theCosB - theCosApB*brac6)+trilinear); couplings[2] = make_pair(coup, coup); // heavier sbottom trilinear = theIncludeTriLinear ? theQb2LR*0.5*mb/theMw*(theMu*theSinA - Trib*theCosA)/theCosB: Energy(); coup = 3.*UnitRemoval::InvE*sqr(theMSSM->ed())* (theQb2L *( - sqr(mb)*theCosA/theMw/theCosB + theCosApB*brac1) + theQb2R *( - sqr(mb)*theCosA/theMw/theCosB - theCosApB*brac3)+trilinear); couplings[3] = make_pair(coup, coup); // heavier stop trilinear = theIncludeTriLinear ? -theQt2LR*0.5*mt/theMw*(-theMu*theCosA + Trit*theSinA)/theSinB: Energy(); coup = 3.*UnitRemoval::InvE*sqr(theMSSM->eu())* (theQt2L *( - sqr(mt)*theSinA/theMw/theSinB - theCosApB*brac2) + theQt2R *( - sqr(mt)*theSinA/theMw/theSinB - theCosApB*brac4)+trilinear); couplings[4] = make_pair(coup, coup); // heavier stau trilinear = theIncludeTriLinear ? theLt2LR*0.5*mtau/theMw*(theMu*theSinA - Trita*theCosA)/theCosB: Energy(); coup = UnitRemoval::InvE*sqr(theMSSM->ee())* (theLt2L *( - sqr(mtau)*theCosA/theMw/theCosB + theCosApB*brac5) + theLt2R *( - sqr(mtau)*theCosA/theMw/theCosB - theCosApB*brac6)+trilinear); couplings[5] = make_pair(coup, coup); // top coup = -3.*mt*sqr(theMSSM->eu())*theSinA/2./theMw/theSinB; couplings[6] = make_pair(coup, coup); // bottom coup = -3.*mb*sqr(theMSSM->ed())*theCosA/2./theMw/theCosB; couplings[7] = make_pair(coup, coup); // tau coup = -mtau*sqr(theMSSM->ee())*theCosA/2./theMw/theCosB; couplings[8] = make_pair(coup, coup); // charged higgs coup = - UnitRemoval::InvE*theMw*(theCosBmA - 0.5/(1.-sqr(theSw))* (sqr(theCosB)-sqr(theSinB))*theCosApB); couplings[9] = make_pair(coup, coup); // W boson coup = UnitRemoval::InvE*theMw*theCosBmA; couplings[10] = make_pair(coup, coup); // charginos for(unsigned int ix=0;ix<2;++ix) { Complex Q = sqrt(0.5)*(*theV)(ix,0)*(*theU)(ix,1); Complex S = sqrt(0.5)*(*theV)(ix,1)*(*theU)(ix,0); coup = -Q*theCosA-S*theSinA; couplings[11+ix] = make_pair(conj(coup), coup); } } } else { setNParticles(5); masses.resize(5); couplings.resize(5); masses[0] = mt; masses[1] = mb; masses[2] = mtau; masses[3] = getParticleData(ParticleID::SUSY_chi_1plus)->mass(); masses[4] = getParticleData(ParticleID::SUSY_chi_2plus)->mass(); type.resize(5,PDT::Spin1Half); // top Complex coup = 3.*Complex(0., 1.)*sqr(theMSSM->eu())*mt/2./theMw/theTanB; couplings[0] = make_pair(coup, thePseudoScalarTreatment ? coup : -coup); // bottom coup = 3.*Complex(0., 1.)*sqr(theMSSM->ed())*mb/2./theMw*theTanB; couplings[1] = make_pair(coup, thePseudoScalarTreatment ? coup : -coup); // tau coup = Complex(0., 1.)*sqr(theMSSM->ee())*mtau/2./theMw*theTanB; couplings[2] = make_pair(coup, thePseudoScalarTreatment ? coup : -coup); // charginos for(unsigned int ix=0;ix<2;++ix) { Complex Q = sqrt(0.5)*(*theV)(ix,0)*(*theU)(ix,1); Complex S = sqrt(0.5)*(*theV)(ix,1)*(*theU)(ix,0); coup = - Complex(0., 1.)*(Q*theSinB+S*theCosB); couplings[3+ix] = make_pair(coup, thePseudoScalarTreatment ? coup : -coup); } } theq2last = q2; theLastID = higgs; theHaveCoeff = false; } norm(theCouplast); //calculate tensor coefficients if( !theHaveCoeff ) { VVSLoopVertex::setCoupling(q2, particle2, particle3, particle1); theHaveCoeff = true; } } // functions for loops for testing // namespace { // Complex F0(double tau) { // Complex ft; // if(tau>=1.) // ft = sqr(asin(1./sqrt(tau))); // else { // double etap = 1.+sqrt(1.-tau); // double etam = 1.-sqrt(1.-tau); // ft = -0.25*sqr(log(etap/etam)-Constants::pi*Complex(0.,1.)); // } // return tau*(1.-tau*ft); // } // Complex FHalf(double tau,double eta) { // Complex ft; // if(tau>=1.) // ft = sqr(asin(1./sqrt(tau))); // else { // double etap = 1.+sqrt(1.-tau); // double etam = 1.-sqrt(1.-tau); // ft = -0.25*sqr(log(etap/etam)-Constants::pi*Complex(0.,1.)); // } // return -2.*tau*(eta+(1.-tau*eta)*ft); // } // Complex F1(double tau) { // Complex ft; // if(tau>=1.) // ft = sqr(asin(1./sqrt(tau))); // else { // double etap = 1.+sqrt(1.-tau); // double etam = 1.-sqrt(1.-tau); // ft = -0.25*sqr(log(etap/etam)-Constants::pi*Complex(0.,1.)); // } // return 2.+3.*tau+3.*tau*(2.-tau)*ft; // } // } void SSHPPVertex::doinit() { //PDG codes for particles at vertices addToList(22,22,25); addToList(22,22,35); addToList(22,22,36); theMSSM = dynamic_ptr_cast(generator()->standardModel()); if( !theMSSM ) throw InitException() << "SSHPPVertex::doinit() - The pointer to the MSSM object is null!" << Exception::abortnow; theMw = getParticleData(ParticleID::Wplus)->mass(); thetop = getParticleData(ParticleID::t); thebot = getParticleData(ParticleID::b); thetau = getParticleData(ParticleID::tauminus); theSw = sqrt(sin2ThetaW()); theZfact = getParticleData(ParticleID::Wplus)->mass()/(1. - sqr(theSw)); theSinA = sin(theMSSM->higgsMixingAngle()); theCosA = sqrt(1. - sqr(theSinA)); theTanB = theMSSM->tanBeta(); theSinB = theTanB/sqrt(1. + sqr(theTanB)); theCosB = sqrt( 1. - sqr(theSinB) ); theSinApB = theSinA*theCosB + theCosA*theSinB; theCosApB = theCosA*theCosB - theSinA*theSinB; theSinBmA =-theSinA*theCosB + theCosA*theSinB; theCosBmA = theCosA*theCosB + theSinA*theSinB; MixingMatrix stop = *theMSSM->stopMix(); MixingMatrix sbot = *theMSSM->sbottomMix(); MixingMatrix stau = *theMSSM->stauMix(); theQt1L = stop(0,0)*stop(0,0); theQt1R = stop(0,1)*stop(0,1); theQt1LR = stop(0,1)*stop(0,0) + stop(0,1)*stop(0,0); theQt2L = stop(1,0)*stop(1,0); theQt2R = stop(1,1)*stop(1,1); theQt2LR = stop(1,1)*stop(1,0) + stop(1,0)*stop(1,1); theQb1L = sbot(0,0)*sbot(0,0); theQb1R = sbot(0,1)*sbot(0,1); theQb1LR = sbot(0,1)*sbot(0,0) + sbot(0,1)*sbot(0,0); theQb2L = sbot(1,0)*sbot(1,0); theQb2R = sbot(1,1)*sbot(1,1); theQb2LR = sbot(1,1)*sbot(1,0) + sbot(1,0)*sbot(1,1); theLt1L = stau(0,0)*stau(0,0); theLt1R = stau(0,1)*stau(0,1); theLt1LR = stau(0,1)*stau(0,0) + stau(0,1)*stau(0,0); theLt2L = stau(1,0)*stau(1,0); theLt2R = stau(1,1)*stau(1,1); theLt2LR = stau(1,1)*stau(1,0) + stau(1,0)*stau(1,1); theU = theMSSM->charginoUMix(); theV = theMSSM->charginoVMix(); assert( theSfmass.size() == 6 ); theSfmass[0] = getParticleData(ParticleID::SUSY_b_1)->mass(); theSfmass[1] = getParticleData(ParticleID::SUSY_t_1)->mass(); theSfmass[2] = getParticleData(ParticleID::SUSY_tau_1minus)->mass(); theSfmass[3] = getParticleData(ParticleID::SUSY_b_2)->mass(); theSfmass[4] = getParticleData(ParticleID::SUSY_t_2)->mass(); theSfmass[5] = getParticleData(ParticleID::SUSY_tau_2minus)->mass(); VVSLoopVertex::doinit(); // test calc of the width // for(unsigned int ix=0;ix<2;++ix) { // Energy mh = getParticleData(25+long(ix)*10)->mass(); // Energy mt = theMSSM->mass(sqr(mh ), thetop); // Energy mb = theMSSM->mass(sqr(mh ), thebot); // Energy mtau = theMSSM->mass(sqr(mh ), thetau); // Energy mhp = getParticleData(ParticleID::Hplus)->mass(); // Energy mc[2] = {getParticleData(ParticleID::SUSY_chi_1plus)->mass(), // getParticleData(ParticleID::SUSY_chi_2plus)->mass()}; // // sbottom // Complex rsb1,rsb2; // if(ix==0) { // rsb1 = // +theQb1L*(-sqr(mb/theMw)*(1.-sqr(theSw))*theSinA/theCosB // -(-0.5+sqr(theSw)/3.)*theSinApB) // +theQb1R*(-sqr(mb/theMw)*(1.-sqr(theSw))*theSinA/theCosB // +sqr(theSw)/3.*theSinApB); // rsb2 = // +theQb2L*(-sqr(mb/theMw)*(1.-sqr(theSw))*theSinA/theCosB // -(-0.5+sqr(theSw)/3.)*theSinApB) // +theQb2R*(-sqr(mb/theMw)*(1.-sqr(theSw))*theSinA/theCosB // +sqr(theSw)/3.*theSinApB); // } // else { // rsb1 = // +theQb1L*(+sqr(mb/theMw)*(1.-sqr(theSw))*theCosA/theCosB // +(-0.5+sqr(theSw)/3.)*theCosApB) // +theQb1R*(+sqr(mb/theMw)*(1.-sqr(theSw))*theCosA/theCosB // -sqr(theSw)/3.*theCosApB); // rsb2 = // +theQb2L*(+sqr(mb/theMw)*(1.-sqr(theSw))*theCosA/theCosB // +(-0.5+sqr(theSw)/3.)*theCosApB) // +theQb2R*(+sqr(mb/theMw)*(1.-sqr(theSw))*theCosA/theCosB // -sqr(theSw)/3.*theCosApB); // } // Complex Isb1 = 3.*sqr(1./3.)*rsb1*sqr(theMw/theSfmass[0])/(1.-sqr(theSw)) // *F0(sqr(2.*theSfmass[0]/mh)); // Complex Isb2 = 3.*sqr(1./3.)*rsb2*sqr(theMw/theSfmass[3])/(1.-sqr(theSw)) // *F0(sqr(2.*theSfmass[3]/mh)); // // stop // Complex rst1,rst2; // if(ix==0) { // rst1 = // +theQt1L*(+sqr(mt/theMw)*(1.-sqr(theSw))*theCosA/theSinB // -(+0.5-2.*sqr(theSw)/3.)*theSinApB) // +theQt1R*(+sqr(mt/theMw)*(1.-sqr(theSw))*theCosA/theSinB // -2.*sqr(theSw)/3.*theSinApB); // rst2 = // +theQt2L*(+sqr(mt/theMw)*(1.-sqr(theSw))*theCosA/theSinB // -(+0.5-2.*sqr(theSw)/3.)*theSinApB) // +theQt2R*(+sqr(mt/theMw)*(1.-sqr(theSw))*theCosA/theSinB // -2.*sqr(theSw)/3.*theSinApB); // } // else { // rst1 = // +theQt1L*(+sqr(mt/theMw)*(1.-sqr(theSw))*theSinA/theSinB // +(+0.5-2.*sqr(theSw)/3.)*theCosApB) // +theQt1R*(+sqr(mt/theMw)*(1.-sqr(theSw))*theSinA/theSinB // +2.*sqr(theSw)/3.*theCosApB); // rst2 = // +theQt2L*(+sqr(mt/theMw)*(1.-sqr(theSw))*theSinA/theSinB // +(+0.5-2.*sqr(theSw)/3.)*theCosApB) // +theQt2R*(+sqr(mt/theMw)*(1.-sqr(theSw))*theSinA/theSinB // +2.*sqr(theSw)/3.*theCosApB); // } // Complex Ist1 = 3.*sqr(2./3.)*rst1*sqr(theMw/theSfmass[1])/(1.-sqr(theSw)) // *F0(sqr(2.*theSfmass[1]/mh)); // Complex Ist2 = 3.*sqr(2./3.)*rst2*sqr(theMw/theSfmass[4])/(1.-sqr(theSw)) // *F0(sqr(2.*theSfmass[4]/mh)); // // stau // Complex rstau1,rstau2; // if(ix==0) { // rstau1 = // +theLt1L*(-sqr(mtau/theMw)*(1.-sqr(theSw))*theSinA/theCosB // -(-0.5+sqr(theSw))*theSinApB) // +theLt1R*(-sqr(mtau/theMw)*(1.-sqr(theSw))*theSinA/theCosB // +sqr(theSw)*theSinApB); // rstau2 = // +theLt2L*(-sqr(mtau/theMw)*(1.-sqr(theSw))*theSinA/theCosB // -(-0.5+sqr(theSw))*theSinApB) // +theLt2R*(-sqr(mtau/theMw)*(1.-sqr(theSw))*theSinA/theCosB // +sqr(theSw)*theSinApB); // } // else { // rstau1 = // +theLt1L*(+sqr(mtau/theMw)*(1.-sqr(theSw))*theCosA/theCosB // +(-0.5+sqr(theSw))*theCosApB) // +theLt1R*(+sqr(mtau/theMw)*(1.-sqr(theSw))*theCosA/theCosB // -sqr(theSw)*theCosApB); // rstau2 = // +theLt2L*(+sqr(mtau/theMw)*(1.-sqr(theSw))*theCosA/theCosB // +(-0.5+sqr(theSw))*theCosApB) // +theLt2R*(+sqr(mtau/theMw)*(1.-sqr(theSw))*theCosA/theCosB // -sqr(theSw)*theCosApB); // } // Complex Istau1 = rstau1*sqr(theMw/theSfmass[2])/(1.-sqr(theSw)) // *F0(sqr(2.*theSfmass[2]/mh)); // Complex Istau2 = rstau2*sqr(theMw/theSfmass[5])/(1.-sqr(theSw)) // *F0(sqr(2.*theSfmass[5]/mh)); // // charged higgs // Complex rh; // if(ix==0) { // rh = theSinBmA+0.5*(sqr(theCosB)-sqr(theSinB))*theSinApB/(1.-sqr(theSw)); // } // else { // rh = theCosBmA-0.5*(sqr(theCosB)-sqr(theSinB))*theCosApB/(1.-sqr(theSw)); // } // Complex Ih = rh*sqr(theMw/mhp)*F0(sqr(2.*mhp/mh)); // // W // Complex rw; // if(ix==0) { // rw = theSinBmA; // } // else { // rw = theCosBmA; // } // Complex IW = rw*F1(sqr(2.*theMw/mh)); // // top // Complex rt; // if(ix==0) { // rt = theCosA/theSinB; // } // else { // rt = theSinA/theSinB; // } // Complex Itop = 3.*sqr(2./3.)*rt*FHalf(sqr(2.*mt/mh),1.); // // bottom // Complex rb; // if(ix==0) { // rb =-theSinA/theCosB; // } // else { // rb = theCosA/theCosB; // } // Complex Ibot = 3.*sqr(1./3.)*rb*FHalf(sqr(2.*mb/mh),1.); // // tau // Complex rtau; // if(ix==0) { // rtau =-theSinA/theCosB; // } // else { // rtau = theCosA/theCosB; // } // Complex Itau = rtau*FHalf(sqr(2.*mtau/mh),1.); // // charginos // Complex rc[2],IC[2]; // for(unsigned int ic=0;ic<2;++ic) { // Complex Q = sqrt(0.5)*(*theV)(ic,0)*(*theU)(ic,1); // Complex S = sqrt(0.5)*(*theV)(ic,1)*(*theU)(ic,0); // if(ix==0) { // rc[ic] = 2.*(S*theCosA-Q*theSinA); // } // else { // rc[ic] = 2.*(S*theSinA+Q*theCosA); // } // IC[ic] = rc[ic]*FHalf(sqr(2.*mc[ic]/mh),1.)*theMw/mc[ic]; // } // Energy pre = sqr(mh/theMw)*mh/1024./pow(Constants::pi,3) // *sqr(weakCoupling(sqr(mh))*sqr(electroMagneticCoupling(sqr(mh)))/4./Constants::pi); // cerr << "testing lighter sbottom" << ix << " " // << pre*std::norm(Isb1)/GeV << "\n"; // cerr << "testing heavier sbottom" << ix << " " // << pre*std::norm(Istau2)/GeV << "\n"; // cerr << "testing lighter stop" << ix << " " // << pre*std::norm(Ist1)/GeV << "\n"; // cerr << "testing heavier stop" << ix << " " // << pre*std::norm(Ist2)/GeV << "\n"; // cerr << "testing lighter stau" << ix << " " // << pre*std::norm(Istau1)/GeV << "\n"; // cerr << "testing heavier stau" << ix << " " // << pre*std::norm(Isb2)/GeV << "\n"; // cerr << "testing top " << ix << " " // << pre*std::norm(Itop)/GeV << "\n"; // cerr << "testing bottom " << ix << " " // << pre*std::norm(Ibot)/GeV << "\n"; // cerr << "testing tau " << ix << " " // << pre*std::norm(Itau)/GeV << "\n"; // cerr << "testing higgs " << ix << " " // << pre*std::norm(Ih)/GeV << "\n"; // cerr << "testing W " << ix << " " // << pre*std::norm(IW)/GeV << "\n"; // cerr << "testing chi1 " << ix << " " // << pre*std::norm(IC[0])/GeV << "\n"; // cerr << "testing chi2 " << ix << " " // << pre*std::norm(IC[1])/GeV << "\n"; // cerr << "testing chi " << ix << " " // << pre*std::norm(IC[0]+IC[1])/GeV << "\n"; // cerr << "testing higgs width " << ix << " " // << pre*std::norm(Isb1+Isb2+Ist1+Ist2+Istau1+Istau2+ // Itop+Ibot+Itau+Ih+IW+IC[0]+IC[1])/GeV << "\n"; // } if(loopToolsInitialized()) Looptools::ltexi(); } diff --git a/Models/Susy/SSHSFSFVertex.cc b/Models/Susy/SSHSFSFVertex.cc --- a/Models/Susy/SSHSFSFVertex.cc +++ b/Models/Susy/SSHSFSFVertex.cc @@ -1,448 +1,449 @@ // -*- C++ -*- // // SSHSFSFVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SSHSFSFVertex class. // #include "SSHSFSFVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include using namespace ThePEG::Helicity; using namespace Herwig; SSHSFSFVertex::SSHSFSFVertex() : theMix(3), theTriC(9, complex(ZERO)), theSinA(0.0), theCosA(0.0), theSinB(0.0), theCosB(0.0), theTanB(0.0), theSinAB(0.0), theCosAB(0.0), theMw(ZERO), theMz(ZERO), theMu(ZERO), theSw(0.0), theCw(0.0), theCoupLast(ZERO), theq2Last(ZERO), theHLast(0), theSF1Last(0), theSF2Last(0) { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::DELTA); } void SSHSFSFVertex::doinit() { int higgs = 25; //h0,H0 for(unsigned int i = 0; i < 2; ++i) { if( i == 1 ) higgs = 35; //quarks for(unsigned int j = 1; j < 7; ++j) { long lj = 1000000 + j; long rj = 2000000 + j; //LLbar addToList(higgs,lj,-lj); //RRbar addToList(higgs,rj,-rj); //LRbar addToList(higgs,lj,-rj); //RLbar addToList(higgs,rj,-lj); } for(unsigned int j = 11; j < 17; ++j) { long lj = 1000000 + j; long rj = 2000000 + j; addToList(higgs,lj,-lj); if( j % 2 != 0) { addToList(higgs,rj,-rj); //LRbar addToList(higgs,lj,-rj); //RLbar addToList(higgs,rj,-lj); } } } //A0 for(unsigned int j = 1; j < 7; ++j) { long lj = 1000000 + j; long rj = 2000000 + j; //LRbar addToList(36,lj,-rj); //RLbar addToList(36,rj,-lj); } for(unsigned int j = 11; j < 17; j += 2) { long lj = 1000000 + j; long rj = 2000000 + j; addToList(36,lj,-rj); addToList(36,rj,-lj); } //outgoing H+ for(long ii = 2; ii < 7; ii += 2) { //LL addToList(37, 999999 + ii, -1000000 - ii); //RR addToList(37, 1999999 + ii, -2000000 - ii); //RL addToList(37, 1999999 + ii, -1000000 - ii); //LR addToList(37, 999999 + ii, -2000000 - ii); } for(long ii = 11; ii < 17; ii += 2) { addToList(37, 1000000 + ii, -1000001 - ii); addToList(37, 2000000 + ii, -1000001 - ii); } //outgoing H- for(long ii = 2; ii < 7; ii += 2) { //LL addToList(-37, 1000000 + ii, -999999 - ii); //RR addToList(-37, 2000000 + ii, -1999999 - ii); //RL addToList(-37, 1000000 + ii, -1999999 - ii); //LR addToList(-37, 2000000 + ii, -999999 - ii); } for(long ii = 11; ii < 17; ii += 2) { addToList(-37, 1000001 + ii, -1000000 - ii); addToList(-37, 1000001 + ii, -2000000 - ii);} SSSVertex::doinit(); theMSSM = dynamic_ptr_cast(generator()->standardModel()); if( !theMSSM ) throw InitException() << "SSHSFSFVertex::doinit - A problem occurred" << "while trying to cast the SM pointer to " << "a Susy one." << Exception::abortnow; //mixing vector should have been sized correctly already assert( theMix.size() == 3 ); theMix[0] = theMSSM->stopMix(); theMix[1] = theMSSM->sbottomMix(); theMix[2] = theMSSM->stauMix(); if(!theMix[0] || !theMix[1] || !theMix[2]) throw InitException() << "SSHSFSFVertex::doinit - " << "A null mixing matrix pointer. stop: " << theMix[0] << " sbottom: " << theMix[1] << " stau: " << theMix[2] << Exception::abortnow; //trilinear vector should have been sized correctly already assert( theTriC.size() == 9 ); //vector has been zeroed in constructor theTriC[4]=theMSSM->bottomTrilinear().real(); theTriC[5]=theMSSM->topTrilinear().real(); theTriC[8]=theMSSM->tauTrilinear().real(); //Masses theMw = getParticleData(ParticleID::Wplus)->mass(); theMz = getParticleData(ParticleID::Z0)->mass(); //parameters theSinA = sin(theMSSM->higgsMixingAngle()); theCosA = cos(theMSSM->higgsMixingAngle()); theTanB = theMSSM->tanBeta(); theMu = theMSSM->muParameter(); theSinB = theTanB/sqrt(1. + sqr(theTanB)); theCosB = sqrt( 1. - sqr(theSinB) ); theSinAB = theSinA*theCosB + theCosA*theSinB; theCosAB = theCosA*theCosB - theSinA*theSinB; theSw = sqrt(sin2ThetaW()); theCw = sqrt(1. - sin2ThetaW()); } void SSHSFSFVertex::persistentOutput(PersistentOStream & os) const { os << theMix << theSinA << theCosA << theSinB << theMSSM << theCosB << theTanB << ounit(theMu, GeV) << theSinAB << theCosAB << ounit(theMw,GeV) << ounit(theMz,GeV) << theSw << theCw << ounit(theTriC,GeV); } void SSHSFSFVertex::persistentInput(PersistentIStream & is, int) { is >> theMix >> theSinA >> theCosA >> theSinB >> theMSSM >> theCosB >> theTanB >> iunit(theMu, GeV) >> theSinAB >> theCosAB >> iunit(theMw,GeV) >> iunit(theMz,GeV) >> theSw >> theCw >> iunit(theTriC,GeV); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigSSHSFSFVertex("Herwig::SSHSFSFVertex", "HwSusy.so"); void SSHSFSFVertex::Init() { static ClassDocumentation documentation ("The coupling of an MSSM Higgs to a pair of sfermions."); } void SSHSFSFVertex::setCoupling(Energy2 q2, tcPDPtr part1, tcPDPtr part2, tcPDPtr part3) { // extract particle ids long higgs(part1->id()), sq1(part2->id()), sq2(part3->id()); // higgs first if(abs(sq1)<100) swap(higgs,sq1); if(abs(sq2)<100) swap(higgs,sq2); // squark second, antisquark third if(sq1<0) swap(sq1,sq2); assert( higgs == 25 || higgs == 35 || higgs == 36 || abs(higgs) == 37 ); sq2 *=-1; assert(sq1>0&&sq2>0); // running coupling if( q2 != theq2Last || thegLast==0.) { thegLast = weakCoupling(q2); theq2Last = q2; } if( higgs == theHLast && sq1 == theSF1Last && sq2 == theSF2Last) { norm(thegLast*theCoupLast*UnitRemoval::InvE); return; } theHLast = higgs; theSF1Last = sq1; theSF2Last = sq2; if( abs(higgs) == ParticleID::Hplus ) chargedHiggs(q2,sq1, sq2); else { long sm(0); unsigned int alpha(sq1/1000000 - 1), beta(sq2/1000000 - 1); if( sq1/1000000 == 2 ) sm = sq1 - 2000000; else sm = sq1 - 1000000; if( sm < 7 ) { if( sm % 2 == 0 ) upSF(q2,higgs, sm, alpha, beta); else downSF(q2,higgs, sm, alpha, beta); } else leptonSF(q2,higgs, sm, alpha, beta); } norm(thegLast*theCoupLast*UnitRemoval::InvE); } void SSHSFSFVertex::downSF(Energy2 q2, long higgs, long sm, unsigned int alpha, unsigned int beta) { assert( sm < 7 && sm % 2 != 0); Energy fmass = theMSSM->mass(q2,getParticleData(sm)); double mfacta = 0.5*fmass/theMw; if( higgs == ParticleID::A0 ) { theCoupLast = -Complex(0.,1.)*mfacta*(theTriC[sm - 1]*theTanB + theMu); if(sm == 5) { // do not revert to *=, breaks with XCode 5.1 theCoupLast = theCoupLast * ( (*theMix[1])(alpha, 1) * (*theMix[1])(beta , 0) - (*theMix[1])(alpha, 0) * (*theMix[1])(beta , 1) ); } else if(alphaed()*theSw*theSw; //mixing parameters Complex q1a(0.), q1b(0.), q2a(0.), q2b(0.); if( sm == 1 || sm == 3) { q1a = (alpha == 0) ? 1.0 : 0.0; q1b = (beta == 0) ? 1.0 : 0.0; q2a = (alpha == 0) ? 0.0 : 1.0; q2b = (beta == 0) ? 0.0 : 1.0; } else { q1a = (*theMix[1])(alpha, 0); q1b = (*theMix[1])(beta, 0); q2a = (*theMix[1])(alpha, 1); q2b = (*theMix[1])(beta, 1); } Complex fbrac = (q1a*q1b*(0.5 + factb) - factb*q2a*q2b); Complex sbrac = (q1a*q1b + q2a*q2b); Complex tbrac = (q2a*q1b + q1a*q2b); if( higgs == ParticleID::h0) { theCoupLast = -facta*theSinAB*fbrac + mfactb*theSinA*sbrac + mfacta*(theTriC[sm - 1]*theSinA + theMu*theCosA)*tbrac/theCosB; } else if( higgs == ParticleID::H0 ) { theCoupLast = facta*theCosAB*fbrac - mfactb*theCosA*sbrac + mfacta*(theMu*theSinA - theTriC[sm - 1]*theCosA)*tbrac/theCosB; } else throw HelicityConsistencyError() << "SSHSFSFVertex::downSF - Unrecognised higgs particle " << higgs << Exception::warning; } void SSHSFSFVertex::upSF(Energy2 q2, long higgs, long sm, unsigned int alpha, unsigned int beta) { assert( sm < 7 && sm % 2 == 0); Energy fmass = theMSSM->mass(q2,getParticleData(sm)); double mfacta = 0.5*fmass/theMw; if( higgs == ParticleID::A0 ){ theCoupLast = -Complex(0.,1.)*mfacta*(theTriC[sm - 1]/theTanB + theMu); if(sm == 6) { // do not revert to *=, breaks with XCode 5.1 theCoupLast = theCoupLast * ( (*theMix[0])(alpha, 1) * (*theMix[0])(beta , 0) - (*theMix[0])(alpha, 0) * (*theMix[0])(beta , 1) ); } else if(alphaeu()*sqr(theSw); //mixing parameters Complex q1a(0.), q1b(0.), q2a(0.), q2b(0.); if( sm == 2 || sm == 4) { q1a = (alpha == 0) ? 1.0 : 0.0; q1b = (beta == 0) ? 1.0 : 0.0; q2a = (alpha == 0) ? 0.0 : 1.0; q2b = (beta == 0) ? 0.0 : 1.0; } else { q1a = (*theMix[0])(alpha, 0); q1b = (*theMix[0])(beta , 0); q2a = (*theMix[0])(alpha, 1); q2b = (*theMix[0])(beta , 1); } Complex fbrac = (q1a*q1b*(0.5 - factb) + factb*q2a*q2b); Complex sbrac = (q1a*q1b + q2a*q2b); Complex tbrac = (q2a*q1b + q1a*q2b); if( higgs == ParticleID::h0) { theCoupLast = facta*theSinAB*fbrac - mfactb*theCosA*sbrac - mfacta*(theTriC[sm - 1]*theCosA + theMu*theSinA)*tbrac/theSinB; } else if( higgs == ParticleID::H0 ) { theCoupLast = -facta*theCosAB*fbrac - mfactb*theSinA*sbrac - mfacta*(theTriC[sm - 1]*theSinA - theMu*theCosA )*tbrac/theSinB; } else assert(false); } void SSHSFSFVertex::leptonSF(Energy2 q2, long higgs, long sm, unsigned int alpha, unsigned int beta) { assert( sm >= 11 && sm <= 16 ); Energy facta = theMz/theCw; if( sm % 2 == 0 ) { theCoupLast = complex(facta/2.); if( higgs == ParticleID::h0) theCoupLast *= theSinAB; else theCoupLast *= -theCosAB; return; } Energy fmass = theMSSM->mass(q2,getParticleData(sm)); double mfacta = fmass/2./theMw; if( higgs == ParticleID::A0 ) { theCoupLast = -Complex(0.,1.)*mfacta*(theTriC[(sm + 1)/2]*theTanB + theMu); if(sm == 15) { // do not revert to *=, breaks with XCode 5.1 theCoupLast = theCoupLast * ( (*theMix[2])(alpha, 1) * (*theMix[2])(beta , 0) - (*theMix[2])(alpha, 0) * (*theMix[2])(beta , 1) ); } else if(alphamass(q2,getParticleData(smd)); Energy2 facta = sqr(theMw)*2.*theSinB*theCosB; if( smd == 11 || smd == 13 || smd == 15) { Complex l1b = (beta == 0) ? 1.0 : 0.0; Complex l2b = (beta == 0) ? 0.0 : 1.0; if( smd == 15 ) { l1b = (*theMix[2])(beta, 0); l2b = (*theMix[2])(beta, 1); } theCoupLast = ( l1b*(mfd*mfd*theTanB - facta) + l2b*mfd*(theTriC[(smd + 1)/2]*theTanB + theMu) )/theMw/sqrt(2.); } else { unsigned int alpha(0); if( id1/1000000 == 2 ) alpha = 1; else alpha = 0; long smu = (alpha == 0) ? id1 - 1000000 : id1 - 2000000; Energy mfu = theMSSM->mass(q2,getParticleData(smu)); Complex q1a(0.0), q1b(0.0), q2a(0.0), q2b(0.0); if( smu == 2 || smu == 4 ) { q1a = (alpha == 0) ? 1.0 : 0.0; q2a = (alpha == 0) ? 0.0 : 1.0; } else { q1a = (*theMix[0])(alpha,0); q2a = (*theMix[0])(alpha,1); } if( smd == 1 || smd == 3 ) { q1b = (beta == 0) ? 1.0 : 0.0; q2b = (beta == 0) ? 0.0 : 1.0; } else { q1b = (*theMix[1])(beta,0); q2b = (*theMix[1])(beta,1); } theCoupLast = ( q1a*q1b*(mfd*mfd*theTanB + mfu*mfu/theTanB - facta) + q2a*q2b*mfu*mfd*(theTanB + (1./theTanB)) + q1a*q2b*mfd*(theTriC[smd - 1]*theTanB + theMu) + q2a*q1b*mfu*(theMu + theTriC[smu-1]/theTanB) )/theMw/sqrt(2.); } } diff --git a/Models/Susy/SSNCTVertex.cc b/Models/Susy/SSNCTVertex.cc --- a/Models/Susy/SSNCTVertex.cc +++ b/Models/Susy/SSNCTVertex.cc @@ -1,182 +1,183 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the SSNCTVertex class. // #include "SSNCTVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/Models/StandardModel/StandardCKM.h" using namespace Herwig; SSNCTVertex::SSNCTVertex() : MX_(2.e16*GeV), sw_(0.), cw_(0.), mw_(ZERO), sb_(0.), cb_(0.), q2last_(), couplast_(0.), leftlast_(0.), rightlast_(0.), idlast_(0), epsilon_(0.) { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::DELTA); } IBPtr SSNCTVertex::clone() const { return new_ptr(*this); } IBPtr SSNCTVertex::fullclone() const { return new_ptr(*this); } void SSNCTVertex::persistentOutput(PersistentOStream & os) const { os << ounit(MX_,GeV) << nmix_ << sw_ << cw_ << ounit(mw_,GeV) << sb_ << cb_ << ounit(q2last_,GeV2) << couplast_ << leftlast_ << rightlast_ << idlast_ << epsilon_; } void SSNCTVertex::persistentInput(PersistentIStream & is, int) { is >> iunit(MX_,GeV) >> nmix_ >> sw_ >> cw_ >> iunit(mw_,GeV) >> sb_ >> cb_ >> iunit(q2last_,GeV2) >> couplast_ >> leftlast_ >> rightlast_ >> idlast_ >> epsilon_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigSSNCTVertex("Herwig::SSNCTVertex", "HwSusy.so"); void SSNCTVertex::Init() { static ClassDocumentation documentation ("The SSNCTVertex class implements the flavour violating" " coupling of the top quark to a charm quark and a neutralino"); static Parameter interfaceMX ("MX", "Unification scale for the loop", &SSNCTVertex::MX_, GeV, 2.e16*GeV, 1.e14*GeV, 1.e20*GeV, false, false, Interface::limited); } void SSNCTVertex::doinit() { long neut[5] = {1000022, 1000023, 1000025, 1000035, 1000045}; for(unsigned int nl = 0; nl < 5; ++nl) { addToList( neut[nl], 4, -1000006 ); addToList( neut[nl], -4, 1000006 ); } FFSVertex::doinit(); // get the MSSM MSSMPtr model = dynamic_ptr_cast(generator()->standardModel()); if(!model) throw InitException() << "SSNCTVertex::doinit() - " << "The model pointer is null." << Exception::abortnow; // standard SUSY couplings // neutralino mixing nmix_ = model->neutralinoMix(); if(!nmix_) throw InitException() << "SSNCTVertex::doinit() " << "The neutralino mixing matrix pointer is null." << Exception::abortnow; sw_ = sqrt(sin2ThetaW()); mw_ = getParticleData(24)->mass(); double tb = model->tanBeta(); cw_ = sqrt(1. - sqr(sw_)); sb_ = tb/sqrt(1 + sqr(tb)); cb_ = sqrt(1 - sqr(sb_)); // susy breaking scale Energy mSUSY = sqrt(max(sqr(getParticleData(ParticleID::Z0)->mass()), model->Mq3L()*model->MtR())); // CKM factor ThePEG::Ptr::transient_const_pointer CKMptr = ThePEG::dynamic_ptr_cast< ThePEG::Ptr:: transient_const_pointer>(model->CKM()); if(!CKMptr) throw Exception() << "Must have access to the Herwig::StandardCKM object" << "for the CKM matrix in SSNCTVertex::doinit()" << Exception::runerror; vector< vector > CKM; CKM = CKMptr->getUnsquaredMatrix(generator()->standardModel()->families()); // SM masses Energy mb = getParticleData(ParticleID::b)->mass(); Energy mt = getParticleData(ParticleID::t)->mass(); // squark masses Energy mt1 = getParticleData(1000006)->mass(); Energy mcL = getParticleData(1000004)->mass(); // mixing parameter Complex pre = sqr(weakCoupling(sqr(mSUSY)))/16./sqr(Constants::pi)* log(MX_/mSUSY)*sqr(double(mb/mw_))/sqr(cb_)*conj(CKM[2][2])*CKM[1][2]; complex deltaL = -0.5*pre*(sqr(model->Mq2L())+sqr(model->Mq3L()) + 2.*model->Mh12()+2.*sqr(model->MbR()) + 2.*real( model->bottomTrilinear()* conj(model->bottomTrilinear()))); complex deltaR = pre*mt*conj(model->bottomTrilinear()); if(abs(mt1-mcL)/abs(mt1+mcL)<1e-10) { epsilon_ = 0.; } else { epsilon_ = (deltaL*(*model->stopMix())(0,0)- deltaR*(*model->stopMix())(0,1))/(sqr(mt1)-sqr(mcL)); } } void SSNCTVertex::setCoupling(Energy2 q2,tcPDPtr part1, tcPDPtr part2,tcPDPtr ) { long ism(abs(part1->id())), ineut(abs(part2->id())); tcPDPtr smfermion = part1; if( ism / 1000000 == 1 ) { swap( ism, ineut); smfermion = part2; } if(q2!= q2last_ || couplast_==0.) { couplast_ = -sqrt(2)*weakCoupling(q2); q2last_=q2; } norm(couplast_); if( ineut != idlast_) { idlast_ = ineut; // determine neutralino unsigned nl(0); switch( ineut ) { case 1000022 : nl = 0; break; case 1000023 : nl = 1; break; case 1000025 : nl = 2; break; case 1000035 : nl = 3; break; case 1000045 : nl = 4; break; default : assert(false); } // common primed neutralino matrices Complex n2prime = (*nmix_)(nl,1)*cw_ - (*nmix_)(nl,0)*sw_; Complex n1prime = (*nmix_)(nl,0)*cw_ + (*nmix_)(nl,1)*sw_; tcPDPtr smf = getParticleData(ism); double qf = smf->charge()/eplus; //Complex bracketl = qf*sw_*( conj(n1prime) - sw_*conj(n2prime)/cw_ ); double lambda(0.); //neutralino mixing element Complex nlf(0.); lambda = -0.5 + qf*sqr(sw_); nlf = (*nmix_)(nl,3); Complex bracketr = sw_*qf*n1prime - n2prime*lambda/cw_; leftlast_ = 0.; rightlast_ = epsilon_*bracketr; } //determine the helicity order of the vertex if( smfermion->id() < 0 ) { left(conj(rightlast_)); right(conj(leftlast_)); } else { left(leftlast_); right(rightlast_); } } diff --git a/Models/Susy/SSNFSVertex.cc b/Models/Susy/SSNFSVertex.cc --- a/Models/Susy/SSNFSVertex.cc +++ b/Models/Susy/SSNFSVertex.cc @@ -1,226 +1,227 @@ // -*- C++ -*- // // SSNFSVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SSNFSVertex class. // #include "SSNFSVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG::Helicity; using namespace Herwig; SSNFSVertex::SSNFSVertex() : _sw(0.), _cw(0.), _mw(), _sb(0.), _cb(0.), _q2last(), _couplast(0.), _leftlast(0.), _rightlast(0.), _id1last(0), _id2last(0), yukawa_(1) { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::DELTA); } void SSNFSVertex::persistentOutput(PersistentOStream & os) const { os << _stop << _sbot << _stau << _nmix << _theSS << _sw << _cw << ounit(_mw,GeV) << _sb << _cb << yukawa_; } void SSNFSVertex::persistentInput(PersistentIStream & is, int) { is >> _stop >> _sbot >> _stau >> _nmix >> _theSS >> _sw >> _cw >> iunit(_mw,GeV) >> _sb >> _cb >> yukawa_; } void SSNFSVertex::doinit() { long neut[5] = {1000022, 1000023, 1000025, 1000035, 1000045}; for(unsigned int nl = 0; nl < 5; ++nl) { //quarks for(long ix=1;ix<7;++ix){ addToList( neut[nl], ix, -(1000000+ix) ); addToList( neut[nl], ix, -(2000000+ix) ); addToList( neut[nl], -ix, (1000000+ix) ); addToList( neut[nl], -ix, (2000000+ix) ); } //leptons for(long ix=11;ix<17;++ix) { addToList( neut[nl], ix, -(1000000+ix) ); addToList( neut[nl], -ix, (1000000+ix) ); if( ix % 2 != 0 ) { addToList( neut[nl], ix, -(2000000+ix) ); addToList( neut[nl], -ix, (2000000+ix) ); } } } FFSVertex::doinit(); _theSS = dynamic_ptr_cast(generator()->standardModel()); if(!_theSS) throw InitException() << "SSGSSVertex::doinit() - " << "The model pointer is null." << Exception::abortnow; _stop = _theSS->stopMix(); _sbot = _theSS->sbottomMix(); _stau = _theSS->stauMix(); _nmix = _theSS->neutralinoMix(); if(!_stop || !_stau || !_sbot || !_nmix) throw InitException() << "SSNFSVertex::doinit() - " << "A mixing matrix pointer is null." << " stop: " << _stop << " sbottom: " << _sbot << " stau: " << _stau << " N: " << _nmix << Exception::abortnow; _sw = sqrt(sin2ThetaW()); _mw = getParticleData(24)->mass(); double tb = _theSS->tanBeta(); _cw = sqrt(1. - sqr(_sw)); _sb = tb/sqrt(1 + sqr(tb)); _cb = sqrt(1 - sqr(_sb)); } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigSSNFSVertex("Herwig::SSNFSVertex", "HwSusy.so"); void SSNFSVertex::Init() { static ClassDocumentation documentation ("The SSNFSVertex implements the coupling of a neutralino to " "a fermion-sfermion"); static Switch interfaceYukawa ("Yukawa", "Whether or not to include the Yukawa type couplings", &SSNFSVertex::yukawa_, 1, false, false); static SwitchOption interfaceYukawaYes (interfaceYukawa, "Yes", "Include the terms", 1); static SwitchOption interfaceYukawaNo (interfaceYukawa, "No", "Don't include them", 0); static SwitchOption interfaceYukawa3rdGen (interfaceYukawa, "ThirdGeneration", "Only include for the third generation", 2); } void SSNFSVertex::setCoupling(Energy2 q2,tcPDPtr part1, tcPDPtr part2,tcPDPtr part3) { long isc(abs(part3->id())), ism(abs(part1->id())), ineut(abs(part2->id())); tcPDPtr smfermion = part1; if( ism / 1000000 == 1 ) { swap( ism, ineut); smfermion = part2; } if(q2!=_q2last || _couplast==0.) { _couplast = -sqrt(2)*weakCoupling(q2); _q2last=q2; } norm(_couplast); if( ineut != _id1last || ism != _id2last || isc != _id3last ) { _id1last = ineut; _id2last = ism; _id3last = isc; // determine neutralino and squark eigenstates unsigned int alpha(isc/1000000 - 1), nl(0); switch( ineut ) { case 1000022 : nl = 0; break; case 1000023 : nl = 1; break; case 1000025 : nl = 2; break; case 1000035 : nl = 3; break; case 1000045 : nl = 4; break; default : assert(false); } // common primed neutralino matrices Complex n2prime = (*_nmix)(nl,1)*_cw - (*_nmix)(nl,0)*_sw; //handle neutrinos first if( ism == 12 || ism == 14 || ism == 16 ) { _leftlast = Complex(0., 0.); _rightlast = n2prime/2./_cw; } else { Complex n1prime = (*_nmix)(nl,0)*_cw + (*_nmix)(nl,1)*_sw; tcPDPtr smf = getParticleData(ism); double qf = smf->charge()/eplus; Complex bracketl = qf*_sw*( conj(n1prime) - _sw*conj(n2prime)/_cw ); double y = 0.; if(yukawa_==1 || ((ism==5 || ism==6 || ism==15) && yukawa_==2)) y = double(_theSS->mass(q2, smf)/2./_mw); double lambda(0.); //neutralino mixing element Complex nlf(0.); if( ism % 2 == 0 ) { y /= _sb; lambda = -0.5 + qf*sqr(_sw); nlf = (*_nmix)(nl,3); } else { y /= _cb; lambda = 0.5 + qf*sqr(_sw); nlf = (*_nmix)(nl,2); } Complex bracketr = _sw*qf*n1prime - n2prime*lambda/_cw; //heavy quarks/sleptons if( ism == 5 || ism == 6 || ism == 15 ) { Complex ma1(0.), ma2(0.); if( ism == 5 ) { ma1 = (*_sbot)(alpha,0); ma2 = (*_sbot)(alpha,1); } else if( ism == 6 ) { ma1 = (*_stop)(alpha,0); ma2 = (*_stop)(alpha,1); } else { ma1 = (*_stau)(alpha,0); ma2 = (*_stau)(alpha,1); } _leftlast = y*conj(nlf)*ma1 - ma2*bracketl; _rightlast = y*nlf*ma2 + ma1*bracketr; } else { if( alpha == 0 ) { _leftlast = y*conj(nlf); _rightlast = bracketr; } else { _leftlast = -bracketl; _rightlast = y*nlf; } } } } //determine the helicity order of the vertex if( smfermion->id() < 0 ) { left(conj(_rightlast)); right(conj(_leftlast)); } else { left(_leftlast); right(_rightlast); } } diff --git a/Models/Susy/SSNNPVertex.cc b/Models/Susy/SSNNPVertex.cc --- a/Models/Susy/SSNNPVertex.cc +++ b/Models/Susy/SSNNPVertex.cc @@ -1,366 +1,367 @@ // -*- C++ -*- // // SSNNPVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SSNNPVertex class. // #include "SSNNPVertex.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/Models/Susy/MixingMatrix.h" #include "ThePEG/PDT/EnumParticles.h" #include "Herwig/Looptools/clooptools.h" #include "Herwig/Utilities/Maths.h" using namespace ThePEG::Helicity; using namespace Herwig; SSNNPVertex::SSNNPVertex() : _includeOnShell(false), _realIntegral(false), _sw(0.), _cw(0.), _id1last(0), _id2last(0), _q2last(ZERO), _couplast(0.), _leftlast(ZERO), _rightlast(ZERO) { orderInGem(3); orderInGs(0); + colourStructure(ColourStructure::SINGLET); } void SSNNPVertex::doinit() { Looptools::ltini(); int ineu[5] = {1000022,1000023,1000025,1000035,1000045}; for(unsigned int i = 0; i < 5; ++i) { for(unsigned int j = 0; j < 5; ++j) { addToList(ineu[i], ineu[j], 22); } } GeneralFFVVertex::doinit(); tMSSMPtr theSS = dynamic_ptr_cast(generator()->standardModel()); if(!theSS) throw InitException() << "SSNNPVertex::doinit() - " << "The model pointer is null." << Exception::abortnow; _theN = theSS->neutralinoMix(); _theU = theSS->charginoUMix(); _theV = theSS->charginoVMix(); if(!_theN || !_theU || ! _theV) throw InitException() << "SSNNPVertex::doinit - The neutralino " << "mixing matrix pointer is null." << Exception::abortnow; _sw = sqrt(sin2ThetaW()); _cw = sqrt(1 - _sw*_sw); _mw = getParticleData(ParticleID::Wplus)->mass(); double tb = theSS->tanBeta(); _sb = tb/sqrt(1 + sqr(tb)); _cb = sqrt(1 - sqr(_sb)); _stop = theSS->stopMix(); _sbot = theSS->sbottomMix(); _stau = theSS->stauMix(); Looptools::ltexi(); } void SSNNPVertex::dofinish() { Looptools::ltexi(); GeneralFFVVertex::dofinish(); } void SSNNPVertex::doinitrun() { Looptools::ltini(); GeneralFFVVertex::doinitrun(); } void SSNNPVertex::persistentOutput(PersistentOStream & os) const { os << _sw << _cw << _theN << ounit(_mw,GeV) << _sb << _cb << _stop << _sbot << _stau << _theU << _theV << _includeOnShell << _realIntegral; } void SSNNPVertex::persistentInput(PersistentIStream & is, int) { is >> _sw >> _cw >> _theN >> iunit(_mw,GeV) >> _sb >> _cb >> _stop >> _sbot >> _stau >> _theU >> _theV >> _includeOnShell >> _realIntegral; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeSSNNPVertex("Herwig::SSNNPVertex", "HwSusy.so"); void SSNNPVertex::Init() { static ClassDocumentation documentation ("The loop-mediated coupling of the photon to a pair of neutralinos"); static Switch interfaceIncludeOnShellIntermediates ("IncludeOnShellIntermediates", "Whether or not to include on-shell intermediate states", &SSNNPVertex::_includeOnShell, false, false, false); static SwitchOption interfaceIncludeOnShellIntermediatesYes (interfaceIncludeOnShellIntermediates, "Yes", "Include them", true); static SwitchOption interfaceIncludeOnShellIntermediatesNo (interfaceIncludeOnShellIntermediates, "No", "Don't incldue them", false); static Switch interfaceRealIntegral ("RealIntegral", "Only include the real parts of the integrals", &SSNNPVertex::_realIntegral, false, false, false); static SwitchOption interfaceRealIntegralYes (interfaceRealIntegral, "Yes", "Only include the real part", true); static SwitchOption interfaceRealIntegralNo (interfaceRealIntegral, "No", "Don't include the real part", false); } void SSNNPVertex::setCoupling(Energy2 q2, tcPDPtr part1, #ifndef NDEBUG tcPDPtr part2,tcPDPtr part3) { #else tcPDPtr part2,tcPDPtr) { #endif int o[2]={1,0}; long in1 = part1->id(); long in2 = part2->id(); Energy Mj = part1->mass(); Energy Mi = part2->mass(); // checks of the particle ids assert(part3->id()==ParticleID::gamma); assert(in1 == ParticleID::SUSY_chi_10 || in1 == ParticleID::SUSY_chi_20 || in1 == ParticleID::SUSY_chi_30 || in1 == ParticleID::SUSY_chi_40 || in1 == 1000045 ); assert(in2 == ParticleID::SUSY_chi_10 || in2 == ParticleID::SUSY_chi_20 || in2 == ParticleID::SUSY_chi_30 || in2 == ParticleID::SUSY_chi_40 || in2 == 1000045 ); // normal couplings are zero setLeft (0.); setRight(0.); if(in1==in2) { _leftlast = ZERO; _rightlast = ZERO; setLeftSigma (_leftlast ); setRightSigma(_rightlast); return; } if(q2 != _q2last || _couplast==0.) { _q2last = q2; _couplast = sqr(weakCoupling(q2))* electroMagneticCoupling(q2)/32./sqr(Constants::pi); } if(in1 != _id1last || in2 != _id2last) { _leftlast = ZERO; _rightlast = ZERO; _id1last = in1; _id2last = in2; unsigned int neu1(in1 - 1000022), neu2(in2 - 1000022); if(neu1 > 1) neu1 = (in1-1000005)/10; if(neu2 > 1) neu2 = (in2-1000005)/10; Complex n1prime[2] = { (*_theN)(neu2,0)*_cw + (*_theN)(neu2,1)*_sw , (*_theN)(neu1,0)*_cw + (*_theN)(neu1,1)*_sw }; Complex n2prime[2] = { (*_theN)(neu2,1)*_cw - (*_theN)(neu2,0)*_sw , (*_theN)(neu1,1)*_cw - (*_theN)(neu1,0)*_sw }; // sfermion/fermion loops for(long iferm=1;iferm<16;++iferm) { if(iferm==7) iferm=11; if(iferm%2==0&&iferm>11) ++iferm; tcPDPtr smf = getParticleData(iferm); Energy mf = smf->mass(); double qf = smf->charge()/eplus; double y = 0.5*mf/_mw; Complex bracketl[2] = { qf*_sw*( conj(n1prime[0]) - _sw*conj(n2prime[0])/_cw ) , qf*_sw*( conj(n1prime[1]) - _sw*conj(n2prime[1])/_cw ) }; double lambda(0.); //neutralino mixing element Complex nlf[2]={0.,0.}; if( iferm % 2 == 0 ) { y /= _sb; lambda = -0.5 + qf*sqr(_sw); nlf[0] = (*_theN)(neu2,3); nlf[1] = (*_theN)(neu1,3); } else { y /= _cb; lambda = 0.5 + qf*sqr(_sw); nlf[0] = (*_theN)(neu2,2); nlf[1] = (*_theN)(neu1,2); } Complex bracketr[2] = { _sw*qf*n1prime[0] - n2prime[0]*lambda/_cw , _sw*qf*n1prime[1] - n2prime[1]*lambda/_cw }; for(long iy=0;iy<2;++iy) { long isf = 1000000*(1+iy)+iferm; Energy msf = getParticleData(isf)->mass(); if(!_includeOnShell&&(mf+msf I,J,K,I2; loopIntegrals(Mi,Mj,msf,mf,I,J,K,I2); complex coup[2]; for(unsigned int ix=0;ix<2;++ix) { coup[ix] = Mj*(I2-K)*(g[0][ix]*g[1][o[ix]]-conj(g[0][o[ix]]*g[1][ix])) +Mi*K*(g[0][o[ix]]*g[1][ix]-conj(g[0][ix]*g[1][o[ix]])) +mf*I*(g[0][ix]*g[1][ix]-conj(g[0][o[ix]]*g[1][o[ix]])); } double fact = 4.*qf; if(iferm<=6) fact *=3.; _leftlast += fact*coup[0]; _rightlast += fact*coup[1]; } } // the chargino W contribution for(unsigned int ic=0;ic<2;++ic) { long id = ic==0 ? ParticleID::SUSY_chi_1plus : ParticleID::SUSY_chi_2plus; Energy Mk = getParticleData(id)->mass(); if(!_includeOnShell&&(Mk+_mw I,J,K,I2; loopIntegrals(Mi,Mj,_mw,Mk,I,J,K,I2); Complex g[2][2]; for(unsigned int ix=0;ix<2;++ix) { unsigned int in = ix==0 ? neu2 : neu1; g[ix][0] = conj((*_theN)(in, 1))*(*_theV)(ic, 0) - conj((*_theN)(in, 3))*(*_theV)(ic, 1)/sqrt(2); g[ix][1] = (*_theN)(in, 1)*conj((*_theU)(ic, 0)) + (*_theN)(in, 2)*conj((*_theU)(ic, 1))/sqrt(2); } complex coup[2]; for(unsigned int ix=0;ix<2;++ix) { coup[ix] = Mj*(I2-J-K)*(g[0][o[ix]]*g[1][o[ix]]-conj(g[0][ix]*g[1][ix]))- Mi*(J-K)*(g[0][ix]*g[1][ix]-conj(g[0][o[ix]]*g[1][o[ix]]))+ 2.*Mk*J*(g[0][o[ix]]*g[1][ix]-conj(g[0][ix]*g[1][o[ix]])); } _leftlast += 4.*coup[0]; _rightlast += 4.*coup[1]; } // the chargino charged higgs contribution Energy mh = getParticleData(ParticleID::Hplus)->mass(); for(unsigned int ic=0;ic<2;++ic) { long id = ic==0 ? ParticleID::SUSY_chi_1plus : ParticleID::SUSY_chi_2plus; Energy Mk = getParticleData(id)->mass(); if(!_includeOnShell&&(Mk+mh I,J,K,I2; loopIntegrals(Mi,Mj,mh,Mk,I,J,K,I2); Complex g[2][2]; for(unsigned int ix=0;ix<2;++ix) { unsigned int in = ix==0 ? neu2 : neu1; g[ix][0] = (*_theN)(in, 3)*(*_theV)(ic,0) + ((*_theN)(in,1) + (*_theN)(in,0)*_sw/_cw)* (*_theV)(ic,1)/sqrt(2); g[ix][0] *= _cb; g[ix][1] = conj((*_theN)(in, 2)*(*_theU)(ic,0) - ((*_theN)(in,1) + (*_theN)(in,0)*_sw/_cw)* (*_theU)(ic,1)/sqrt(2)); g[ix][1] *= _sb; } swap(g[1][0],g[1][1]); complex coup[2]; for(unsigned int ix=0;ix<2;++ix) { coup[ix] = Mj*(I2-K)*(g[0][ix]*g[1][o[ix]]-conj(g[0][o[ix]]*g[1][ix])) +Mi*K*(g[0][o[ix]]*g[1][ix]-conj(g[0][ix]*g[1][o[ix]])) +Mk*I*(g[0][ix]*g[1][ix]-conj(g[0][o[ix]]*g[1][o[ix]])); } _leftlast += 2.*coup[0]; _rightlast += 2.*coup[1]; } // the chargino goldstone contribution for(unsigned int ic=0;ic<2;++ic) { long id = ic==0 ? ParticleID::SUSY_chi_1plus : ParticleID::SUSY_chi_2plus; Energy Mk = getParticleData(id)->mass(); if(!_includeOnShell&&(Mk+_mw I,J,K,I2; loopIntegrals(Mi,Mj,_mw,Mk,I,J,K,I2); Complex g[2][2]; for(unsigned int ix=0;ix<2;++ix) { unsigned int in = ix==0 ? neu2 : neu1; g[ix][0] = (*_theN)(in, 3)*(*_theV)(ic,0) + ((*_theN)(in,1) + (*_theN)(in,0)*_sw/_cw)* (*_theV)(ic,1)/sqrt(2); g[ix][0] *=-_sb; g[ix][1] = conj((*_theN)(in, 2)*(*_theU)(ic,0) - ((*_theN)(in,1) + (*_theN)(in,0)*_sw/_cw)* (*_theU)(ic,1)/sqrt(2)); g[ix][1] *= _cb; } swap(g[1][0],g[1][1]); complex coup[2]; for(unsigned int ix=0;ix<2;++ix) { coup[ix] = Mj*(I2-K)*(g[0][ix]*g[1][o[ix]]-conj(g[0][o[ix]]*g[1][ix])) +Mi*K*(g[0][o[ix]]*g[1][ix]-conj(g[0][ix]*g[1][o[ix]])) +Mk*I*(g[0][ix]*g[1][ix]-conj(g[0][o[ix]]*g[1][o[ix]])); } _leftlast += 2.*coup[0]; _rightlast += 2.*coup[1]; } } norm(_couplast); setLeftSigma ( _leftlast); setRightSigma(_rightlast); } void SSNNPVertex::loopIntegrals(Energy Mi, Energy Mj, Energy M, Energy m, complex & I, complex & J, complex & K, complex & I2) { Energy2 m2(sqr(m)),M2(sqr(M)),Mi2(sqr(Mi)),Mj2(sqr(Mj)); double min2 = Mj2*UnitRemoval::InvE2; double mout2 = Mi2*UnitRemoval::InvE2; double mf2 = m2 *UnitRemoval::InvE2; double ms2 = M2 *UnitRemoval::InvE2; I = Looptools::C0i(Looptools::cc0,min2,mout2,0.,mf2,ms2,mf2)*UnitRemoval::InvE2; J = Looptools::C0i(Looptools::cc0,min2,mout2,0.,ms2,mf2,ms2)*UnitRemoval::InvE2; I2 =-Looptools::C0i(Looptools::cc1,min2,mout2,0.,mf2,ms2,mf2)*UnitRemoval::InvE2; K = (1.+Complex(m2*I+M2*J-Mj2*I2))/(Mi2-Mj2); if(_realIntegral) { I = I .real(); J = J .real(); I2 = I2.real(); K = K .real(); } } diff --git a/Models/Susy/SSNNZVertex.cc b/Models/Susy/SSNNZVertex.cc --- a/Models/Susy/SSNNZVertex.cc +++ b/Models/Susy/SSNNZVertex.cc @@ -1,125 +1,126 @@ // -*- C++ -*- // // SSNNZVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SSNNZVertex class. // #include "SSNNZVertex.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "MixingMatrix.h" #include "ThePEG/PDT/EnumParticles.h" using namespace ThePEG::Helicity; using namespace Herwig; SSNNZVertex::SSNNZVertex() : _sw(0.), _cw(0.), _id1last(0), _id2last(0), _q2last(), _couplast(0.), _leftlast(0.), _rightlast(0.) { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::SINGLET); } void SSNNZVertex::doinit() { long neu[] = { 1000022, 1000023, 1000025, 1000035, 1000045 }; for(unsigned int i = 0; i < 5; ++i) for(unsigned int j = 0; j < 5; ++j) addToList(neu[i], neu[j], 23); FFVVertex::doinit(); tSusyBasePtr theSS = dynamic_ptr_cast(generator()->standardModel()); if(!theSS) throw InitException() << "SSNNZVertex::doinit() - " << "The model pointer is null." << Exception::abortnow; _theN = theSS->neutralinoMix(); if(!_theN) throw InitException() << "SSNNZVertex::doinit - The neutralino " << "mixing matrix pointer is null." << Exception::abortnow; _sw = sqrt(sin2ThetaW()); _cw = sqrt(1 - _sw*_sw); } void SSNNZVertex::persistentOutput(PersistentOStream & os) const { os << _sw << _cw << _theN; } void SSNNZVertex::persistentInput(PersistentIStream & is, int) { is >> _sw >> _cw >> _theN; _id1last = 0; _id2last = 0; _q2last = ZERO; _couplast = 0.; _leftlast = 0.; _rightlast = 0.; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeSSNNZVertex("Herwig::SSNNZVertex", "HwSusy.so"); void SSNNZVertex::Init() { static ClassDocumentation documentation ("The coupling of a Z-boson to a pair of neutralinos"); } void SSNNZVertex::setCoupling(Energy2 q2,tcPDPtr part1, #ifndef NDEBUG tcPDPtr part2,tcPDPtr part3) { #else tcPDPtr part2,tcPDPtr) { #endif assert(part3->id() == ParticleID::Z0); long ic1 = part2->id(); long ic2 = part1->id(); assert(ic1 == ParticleID::SUSY_chi_10 || ic1 == ParticleID::SUSY_chi_20 || ic1 == ParticleID::SUSY_chi_30 || ic1 == ParticleID::SUSY_chi_40 || ic1 == 1000045); assert(ic2 == ParticleID::SUSY_chi_10 || ic2 == ParticleID::SUSY_chi_20 || ic2 == ParticleID::SUSY_chi_30 || ic2 == ParticleID::SUSY_chi_40 || ic2 == 1000045); if(q2 != _q2last || _couplast==0.) { _q2last = q2; _couplast = weakCoupling(q2)/_cw; } if(ic1 != _id1last || ic2 != _id2last) { _id1last = ic1; _id2last = ic2; unsigned int neu1(ic1 - 1000022), neu2(ic2 - 1000022); if(neu1 > 1) { if(ic1 == 1000025) neu1 = 2; else if(ic1 == 1000035) neu1 = 3; else neu1 = 4; } if(neu2 > 1) { if(ic2 == 1000025) neu2 = 2; else if(ic2 == 1000035) neu2 = 3; else neu2 = 4; } _leftlast = 0.5*( (*_theN)(neu1, 3)*conj((*_theN)(neu2, 3)) - (*_theN)(neu1, 2)*conj((*_theN)(neu2, 2)) ); _rightlast = -conj(_leftlast); } norm(_couplast); left(_leftlast); right(_rightlast); } diff --git a/Models/Susy/SSWGSSVertex.cc b/Models/Susy/SSWGSSVertex.cc --- a/Models/Susy/SSWGSSVertex.cc +++ b/Models/Susy/SSWGSSVertex.cc @@ -1,201 +1,202 @@ // -*- C++ -*- // // SSWGSSVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SSWGSSVertex class. // #include "SSWGSSVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG::Helicity; using namespace Herwig; SSWGSSVertex::SSWGSSVertex() : _sw(0.), _cw(0.), _q2last(),_emcouplast(0.), _scouplast(0.), _ulast(0), _dlast(0), - _gblast(0), _factlast(0.) -{} + _gblast(0), _factlast(0.) { + colourStructure(ColourStructure::SU3TFUND); +} void SSWGSSVertex::doinit() { //W- //LL-squarks for(long ix=1000001;ix<1000006;ix+=2) { addToList(-24,21,ix+1,-ix); } //1-2 stop sbottom addToList(-24,21,1000006,-2000005); //2-1 stop sbottom addToList(-24,21,2000006,-1000005); //2-2 stop sbottom addToList(-24,21,2000006,-2000005); //W+ for(long ix=1000001;ix<1000006;ix+=2) { addToList(24,21,-(ix+1),ix); } //1-2 stop sbottom addToList(24,21,-1000006,2000005); //2-1 stop sbottom addToList(24,21,-2000006,1000005); //2-2 stop sbottom addToList(24,21,-2000006,2000005); //---Z0---- //LL squarks for(long ix=1000001;ix<1000007;++ix) { addToList(23,21,ix,-ix); } //RR squarks for(long ix=2000001;ix<2000007;++ix) { addToList(23,21,ix,-ix); } //L-Rbar stop addToList(23,21,1000006,-2000006); //Lbar-R stop addToList(23,21,-1000006,2000006); //L-Rbar sbottom addToList(23,21,1000005,-2000005); //Lbar-R sbottom addToList(23,21,-1000005,2000005); //----gamma---- //squarks for(long ix=1000001;ix<1000007;++ix) { addToList(22,21,ix,-ix); } for(long ix=2000001;ix<2000007;++ix) { addToList(22,21,ix,-ix); } orderInGem(1); orderInGs(1); VVSSVertex::doinit(); tMSSMPtr theSS = dynamic_ptr_cast(generator()->standardModel()); if(!theSS) throw InitException() << "SSWGSSVertex::doinit() - " << "The model pointer is null." << Exception::abortnow; _sw = sqrt(sin2ThetaW()); _cw = sqrt( 1. - sqr(_sw) ); _stop = theSS->stopMix(); _sbottom = theSS->sbottomMix(); if(!_stop || !_sbottom) throw InitException() << "SSWGSSVertex::doinit() - " << "A mixing matrix pointer is null." << " stop: " << _stop << " sbottom: " << _sbottom << Exception::abortnow; } void SSWGSSVertex::persistentOutput(PersistentOStream & os) const { os << _sw << _cw << _stop << _sbottom; } void SSWGSSVertex::persistentInput(PersistentIStream & is, int) { is >> _sw >> _cw >> _stop >> _sbottom; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigSSWGSSVertex("Herwig::SSWGSSVertex", "HwSusy.so"); void SSWGSSVertex::Init() { static ClassDocumentation documentation ("This implements the gluon-gluon-squark-squark vertex."); } void SSWGSSVertex::setCoupling(Energy2 q2, tcPDPtr part1, tcPDPtr part2,tcPDPtr part3,tcPDPtr part4) { long boson(abs(part1->id())); long gluon(abs(part2->id())); if (gluon > boson) swap(gluon, boson); if( boson != ParticleID::Wplus && boson != ParticleID::Z0 && boson != ParticleID::gamma ) { throw HelicityConsistencyError() << "SSWGSSVertex::setCoupling() - Vector particle in this " << "vertex is not a W/Z/gamma. " << boson << Exception::warning; norm(0.); } if( gluon != ParticleID::g ) { throw HelicityConsistencyError() << "SSWGSSVertex::setCoupling() - Vector particle in this " << "vertex is not a gluon. " << gluon << Exception::warning; norm(0.); } long sq1(abs(part3->id())),sq2(abs(part4->id())); if( (sq1 < 1000001 && sq1 > 1000006 && sq1 < 2000001 && sq1 > 2000006) || (sq2 < 1000001 && sq2 > 1000006 && sq2 < 2000001 && sq2 > 2000006)) throw HelicityConsistencyError() << "SSWGSSVertex::setCoupling() - There are no squarks in " << "this vertex! " << part3->id() << " " << part4->id() << Exception::warning; if( sq1 % 2 != 0 ) swap(sq1, sq2); if( sq1 != _ulast || sq2 != _dlast || boson != _gblast) { _gblast = boson; _ulast = sq1; _dlast = sq2; //photon is simplest if( boson == ParticleID::gamma ) _factlast = -2.*getParticleData(sq1)->charge()/eplus; else { //determine which helicity state unsigned int alpha(sq1/1000000 - 1), beta(sq2/1000000 - 1); //mixing factors Complex m1a(0.), m1b(0.); if( sq1 == ParticleID::SUSY_t_1 || sq1 == ParticleID::SUSY_t_2 ) m1a = (*_stop)(alpha, 0); else if( sq1 == ParticleID::SUSY_b_1 || sq1 == ParticleID::SUSY_b_2 ) m1a = (*_sbottom)(alpha, 0); else m1a = (alpha == 0) ? Complex(1.) : Complex(0.); if( sq2 == ParticleID::SUSY_t_1 || sq2 == ParticleID::SUSY_t_2 ) m1b = (*_stop)(beta, 0); else if( sq2 == ParticleID::SUSY_b_1 || sq2 == ParticleID::SUSY_b_2 ) m1b = (*_sbottom)(beta, 0); else m1b = (beta == 0) ? Complex(1.) : Complex(0.); //W boson if( boson == ParticleID::Wplus ) { _factlast = -1.*m1a*m1b*sqrt(2)/_sw; } //Z boson else { double lmda(1.); if( sq2 % 2 == 0 ) lmda = -1.; _factlast = lmda*m1a*m1b; if( alpha == beta) { double ef = getParticleData(sq1)->charge()/eplus; _factlast += 2.*ef*sqr(_sw); } _factlast *= 1./_cw/_sw; } } } if( q2 != _q2last || _emcouplast==0. || _scouplast==0. ) { _q2last = q2; _emcouplast = electroMagneticCoupling(q2); _scouplast = strongCoupling(q2); } norm(-_emcouplast*_scouplast*_factlast); } diff --git a/Models/Susy/SSWHHVertex.cc b/Models/Susy/SSWHHVertex.cc --- a/Models/Susy/SSWHHVertex.cc +++ b/Models/Susy/SSWHHVertex.cc @@ -1,128 +1,129 @@ // -*- C++ -*- // // SSWHHVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SSWHHVertex class. // #include "SSWHHVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include using namespace ThePEG::Helicity; using namespace Herwig; SSWHHVertex::SSWHHVertex() : theSw(0.), theS2w(0.), theC2w(0.), thesbma(0.), thecbma(0.), theq2last(ZERO), theElast(0.) { orderInGs(0); orderInGem(1); + colourStructure(ColourStructure::SINGLET); } void SSWHHVertex::doinit() { addToList(22,37,-37); addToList(23,36,25); addToList(23,36,35); addToList(23,37,-37); //outgoing W+ addToList(24,-37,25); addToList(24,-37,35); addToList(24,-37,36); //outgoing W- addToList(-24,37,25); addToList(-24,37,35); addToList(-24,37,36); VSSVertex::doinit(); tMSSMPtr theMSSM = dynamic_ptr_cast(generator()->standardModel()); if( !theMSSM ) throw InitException() << "SSWHHVertex::doinit() - The pointer to the MSSM object is null!" << Exception::abortnow; theSw = sqrt(sin2ThetaW()); double cw = sqrt(1. - sqr(theSw)); theS2w = 2.*theSw*cw; theC2w = cw*cw - theSw*theSw; double sina = sin(theMSSM->higgsMixingAngle()); double cosa = sqrt(1. - sqr(sina)); double tanb = theMSSM->tanBeta(); double sinb = tanb/sqrt(1. + sqr(tanb)); double cosb = sqrt( 1. - sqr(sinb) ); thesbma = sinb*cosa - sina*cosb; thecbma = cosa*cosb + sina*sinb; } void SSWHHVertex::persistentOutput(PersistentOStream & os) const { os << theSw << theS2w << theC2w << thesbma << thecbma; } void SSWHHVertex::persistentInput(PersistentIStream & is, int) { is >> theSw >> theS2w >> theC2w >> thesbma >> thecbma; } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigSSWHHVertex("Herwig::SSWHHVertex", "HwSusy.so"); void SSWHHVertex::Init() { static ClassDocumentation documentation ("The coupling of a pair of higgs bosons and a SM gauge boson"); } void SSWHHVertex::setCoupling(Energy2 q2, tcPDPtr particle1, tcPDPtr particle2, tcPDPtr particle3) { long gboson = particle1->id(); assert( gboson == ParticleID::Z0 || gboson == ParticleID::gamma || abs(gboson) == ParticleID::Wplus ); long h1ID = particle2->id(); long h2ID = particle3->id(); Complex coup(0.); if( gboson == ParticleID::Z0 ) { if( abs(h1ID) == ParticleID::Hplus ) { coup = theC2w/theS2w; if(h1ID<0) coup *= -1.; } else if( h1ID == ParticleID::h0 || h2ID == ParticleID::h0 ) { coup = Complex(0., 1.)*thecbma/theS2w; } else { coup =-Complex(0., 1.)*thesbma/theS2w; } if(h2ID==ParticleID::A0) coup *=-1.; } else if( gboson == ParticleID::gamma ) { coup = 1.; if(h1ID<0) coup *= -1.; } else { long higgs = abs(h1ID) == ParticleID::Hplus ? h2ID : h1ID; if( higgs == ParticleID::h0 ) { coup = 0.5*thecbma/theSw; } else if( higgs == ParticleID::H0) coup = -0.5*thesbma/theSw; else coup = -Complex(0., 0.5)/theSw; if(abs(h2ID) == ParticleID::Hplus ) coup *= -1.; if(gboson<0&&higgs!=ParticleID::A0) coup *= -1.; } if( q2 != theq2last || theElast==0.) { theq2last = q2; theElast = electroMagneticCoupling(q2); } norm(theElast*coup); } diff --git a/Models/Susy/SSWSSVertex.cc b/Models/Susy/SSWSSVertex.cc --- a/Models/Susy/SSWSSVertex.cc +++ b/Models/Susy/SSWSSVertex.cc @@ -1,237 +1,238 @@ // -*- C++ -*- // // SSWSSVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SSWSSVertex class. // #include "SSWSSVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" using namespace ThePEG::Helicity; using namespace Herwig; SSWSSVertex::SSWSSVertex():_sw(0.), _cw(0.), _q2last(),_couplast(0.), _ulast(0), _dlast(0), _gblast(0), _factlast(0.) { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::DELTA); } void SSWSSVertex::doinit() { //W- //LL-squarks for(long ix=1000001;ix<1000006;ix+=2) { addToList(-24,ix+1,-ix); } //1-2 stop sbottom addToList(-24,1000006,-2000005); //2-1 stop sbottom addToList(-24,2000006,-1000005); //2-2 stop sbottom addToList(-24,2000006,-2000005); //LL-sleptons for(long ix=1000011;ix<1000016;ix+=2) { addToList(-24,-ix,ix+1); } //2-L stau addToList(-24,-2000015,1000016); //W+ for(long ix=1000001;ix<1000006;ix+=2) { addToList(24,-(ix+1),ix); } //1-2 stop sbottom addToList(24,-1000006,2000005); //2-1 stop sbottom addToList(24,-2000006,1000005); //2-2 stop sbottom addToList(24,-2000006,2000005); //LL-sleptons for(long ix=1000011;ix<1000016;ix+=2) { addToList(24,ix,-ix-1); } //2-L stau addToList(24,2000015,-1000016); //---Z0---- //LL-sleptons for(long ix=1000011;ix<1000017;++ix) { addToList(23,ix,-ix); } //RR-sleptons for(long ix=2000011;ix<2000016;ix+=2) { addToList(23,ix,-ix); } //L-Rbar stau addToList(23,1000015,-2000015); //Lbar-R stau addToList(23,-1000015,2000015); //LL squarks for(long ix=1000001;ix<1000007;++ix) { addToList(23,ix,-ix); } //RR squarks for(long ix=2000001;ix<2000007;++ix) { addToList(23,ix,-ix); } //L-Rbar stop addToList(23,1000006,-2000006); //Lbar-R stop addToList(23,-1000006,2000006); //L-Rbar sbottom addToList(23,1000005,-2000005); //Lbar-R sbottom addToList(23,-1000005,2000005); //----gamma---- //sleptons for(long ix=1000011;ix<1000016;ix+=2) { addToList(22,ix,-ix); } for(long ix=2000011;ix<2000016;ix+=2) { addToList(22,ix,-ix); } //squarks for(long ix=1000001;ix<1000007;++ix) { addToList(22,ix,-ix); } for(long ix=2000001;ix<2000007;++ix) { addToList(22,ix,-ix); } VSSVertex::doinit(); tMSSMPtr theSS = dynamic_ptr_cast(generator()->standardModel()); if(!theSS) throw InitException() << "SSWSSVertex::doinit() - " << "The model pointer is null." << Exception::abortnow; _sw = sqrt(sin2ThetaW()); _cw = sqrt( 1. - sqr(_sw) ); _stop = theSS->stopMix(); _sbottom = theSS->sbottomMix(); _stau = theSS->stauMix(); if(!_stop || !_stau || !_sbottom) throw InitException() << "SSWSSVertex::doinit() - " << "A mixing matrix pointer is null." << " stop: " << _stop << " sbottom: " << _sbottom << " stau: " << _stau << Exception::abortnow; } void SSWSSVertex::persistentOutput(PersistentOStream & os) const { os << _sw << _cw << _stau << _stop << _sbottom; } void SSWSSVertex::persistentInput(PersistentIStream & is, int) { is >> _sw >> _cw >> _stau >> _stop >> _sbottom; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigSSWSSVertex("Herwig::SSWSSVertex", "HwSusy.so"); void SSWSSVertex::Init() { static ClassDocumentation documentation ("This is the implementation of the coupling of an SM boson " "a pair of sfermions"); } void SSWSSVertex::setCoupling(Energy2 q2,tcPDPtr part1, tcPDPtr part2,tcPDPtr part3) { long boson(abs(part1->id())); assert( boson == ParticleID::Wplus || boson == ParticleID::Z0 || boson == ParticleID::gamma ); long sf1(abs(part2->id())),sf2(abs(part3->id())); assert( (sf1 >= 1000001 && sf1 <= 1000006) || (sf1 >= 1000011 && sf1 <= 1000016) || (sf1 >= 2000001 && sf1 <= 2000006) || (sf1 >= 2000011 && sf1 <= 2000016) ); assert( (sf2 >= 1000001 && sf2 <= 1000006) || (sf2 >= 1000011 && sf2 <= 1000016) || (sf2 >= 2000001 && sf2 <= 2000006) || (sf2 >= 2000011 && sf2 <= 2000016) ); if( sf1 % 2 != 0 ) swap(sf1, sf2); if( sf1 != _ulast || sf2 != _dlast || boson != _gblast) { _gblast = boson; _ulast = sf1; _dlast = sf2; //photon is simplest if( boson == ParticleID::gamma ) _factlast = getParticleData(sf1)->charge()/eplus; else { //determine which helicity state unsigned int alpha(sf1/1000000 - 1), beta(sf2/1000000 - 1); //mixing factors Complex m1a(0.), m1b(0.); if( sf1 == ParticleID::SUSY_t_1 || sf1 == ParticleID::SUSY_t_2 ) m1a = (*_stop)(alpha, 0); else if( sf1 == ParticleID::SUSY_b_1 || sf1 == ParticleID::SUSY_b_2 ) m1a = (*_sbottom)(alpha, 0); else if( sf1 == ParticleID::SUSY_tau_1minus || sf1 == ParticleID::SUSY_tau_2minus ) m1a = (*_stau)(alpha, 0); else m1a = (alpha == 0) ? Complex(1.) : Complex(0.); if( sf2 == ParticleID::SUSY_t_1 || sf2 == ParticleID::SUSY_t_2 ) m1b = (*_stop)(beta, 0); else if( sf2 == ParticleID::SUSY_b_1 || sf2 == ParticleID::SUSY_b_2 ) m1b = (*_sbottom)(beta, 0); else if( sf2 == ParticleID::SUSY_tau_1minus || sf2 == ParticleID::SUSY_tau_2minus ) m1b = (*_stau)(beta, 0); else m1b = (beta == 0) ? Complex(1.) : Complex(0.); //W boson if( boson == ParticleID::Wplus ) { _factlast = m1a*m1b/sqrt(2)/_sw; } //Z boson else { if( sf1 == ParticleID::SUSY_nu_eL || sf1 == ParticleID::SUSY_nu_muL || sf1 == ParticleID::SUSY_nu_tauL ) { _factlast = 1./_cw/2./_sw; } else { double lmda(1.); if( sf2 % 2 == 0 ) lmda = -1.; _factlast = lmda*m1a*m1b; if( alpha == beta) { double ef = getParticleData(sf1)->charge()/eplus; _factlast += 2.*ef*sqr(_sw); } _factlast *= -1./2./_cw/_sw; } } } } if( q2 != _q2last || _couplast==0. ) { _q2last = q2; _couplast = electroMagneticCoupling(q2); } if(part2->id()>0) norm(-_couplast*_factlast); else norm(+_couplast*_factlast); } diff --git a/Models/Susy/SSWWHHVertex.cc b/Models/Susy/SSWWHHVertex.cc --- a/Models/Susy/SSWWHHVertex.cc +++ b/Models/Susy/SSWWHHVertex.cc @@ -1,181 +1,182 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the SSWWHHVertex class. // #include "SSWWHHVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "MSSM.h" using namespace Herwig; SSWWHHVertex::SSWWHHVertex() : couplast_(0.), q2last_(ZERO) { orderInGs(0); orderInGem(2); + colourStructure(ColourStructure::SINGLET); } IBPtr SSWWHHVertex::clone() const { return new_ptr(*this); } IBPtr SSWWHHVertex::fullclone() const { return new_ptr(*this); } void SSWWHHVertex::persistentOutput(PersistentOStream & os) const { os << coup_; } void SSWWHHVertex::persistentInput(PersistentIStream & is, int) { is >> coup_; } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigSSWWHHVertex("Herwig::SSWWHHVertex", "HwSusy.so"); void SSWWHHVertex::Init() { static ClassDocumentation documentation ("The SSWWHHVertex class implements the coupling of two Higgs bosons and" "two electroweak vector bosons in the MSSM."); } void SSWWHHVertex::doinit() { int id[3]={25,35,36}; for(unsigned int ix=0;ix<3;++ix) { addToList( 24,-24,id[ix],id[ix]); addToList( 23, 23,id[ix],id[ix]); addToList( 22, 24,id[ix],-37); addToList( 22,-24,id[ix], 37); addToList( 23, 24,id[ix],-37); addToList( 23,-24,id[ix], 37); } addToList( 24,-24, 37,-37); addToList( 23, 23, 37,-37); addToList( 22, 23, 37,-37); addToList( 22, 22, 37,-37); VVSSVertex::doinit(); tMSSMPtr model = dynamic_ptr_cast(generator()->standardModel()); if( !model ) throw Exception() << "SSWWHHVertex::doinit() - The pointer to the MSSM object is null!" << Exception::abortnow; coup_.resize(11); double sw2 = sin2ThetaW(); double sw = sqrt(sw2); double cw2 = 1.-sw2; double cw = sqrt(cw2); double c2w = cw2-sw2; double sinalp = sin(model->higgsMixingAngle()); double cosalp = sqrt(1. - sqr(sinalp)); double tanbeta = model->tanBeta(); double sinbeta = tanbeta/sqrt(1. + sqr(tanbeta)); double cosbeta = sqrt( 1. - sqr(sinbeta) ); double sinbma = sinbeta*cosalp - cosbeta*sinalp; double cosbma = cosbeta*cosalp + sinbeta*sinalp; // WWHH coup_[0] = 0.5/sw2; // ZZH0H0 coup_[1] = 0.5/sw2/cw2; // ZZH+H- coup_[2] = 0.5*sqr(c2w)/cw2/sw2; // Z W h0 H+ coup_[3] =-0.5/cw*cosbma; // Z W H0 H+ coup_[4] = 0.5/cw*sinbma; // Z W A0 H+ coup_[5] =-Complex(0.,0.5)/cw; // A A H+H- coup_[6] = 2.; // A Z H+H- coup_[7] = c2w/sw/cw; // A W h0 H+ coup_[8] = 0.5*cosbma/sw; // A W H0 H+ coup_[9] =-0.5*sinbma/sw; // A W A0 H+ coup_[10] = Complex(0.,0.5)/sw; } void SSWWHHVertex::setCoupling(Energy2 q2,tcPDPtr part1,tcPDPtr part2, tcPDPtr part3, tcPDPtr part4) { if(q2!=q2last_||couplast_==0.) { couplast_ = sqr(electroMagneticCoupling(q2)); q2last_=q2; } int ibos1 = part1->id(), ibos2 = part2->id(); int isca1 = part3->id(), isca2 = part4->id(); if(abs(ibos1)==abs(ibos2)) { if(abs(ibos1)==ParticleID::Wplus) { norm(couplast_*coup_[0]); } else if(ibos1==ParticleID::Z0) { if(abs(isca1)==ParticleID::Hplus) norm(couplast_*coup_[2]); else norm(couplast_*coup_[1]); } else if(ibos1==ParticleID::gamma) { norm(couplast_*coup_[6]); } else assert(false); } else if(abs(ibos1)==ParticleID::Wplus || abs(ibos2)==ParticleID::Wplus) { if(abs(ibos1)==ParticleID::gamma || abs(ibos2)==ParticleID::gamma) { if(abs(isca1)==ParticleID::h0 || abs(isca2)==ParticleID::h0) { norm(couplast_*coup_[8]); } else if(abs(isca1)==ParticleID::H0 || abs(isca2)==ParticleID::H0) { norm(couplast_*coup_[9]); } else if(abs(isca1)==ParticleID::A0 || abs(isca2)==ParticleID::A0) { if(isca1==ParticleID::Hplus || isca2==ParticleID::Hplus) { norm(couplast_* coup_[10] ); } else { norm(couplast_*conj(coup_[10])); } } else assert(false); } else { if(abs(isca1)==ParticleID::h0 || abs(isca2)==ParticleID::h0) { norm(couplast_*coup_[3]); } else if(abs(isca1)==ParticleID::H0 || abs(isca2)==ParticleID::H0) { norm(couplast_*coup_[4]); } else if(abs(isca1)==ParticleID::A0 || abs(isca2)==ParticleID::A0) { if(isca1==ParticleID::Hplus || isca2==ParticleID::Hplus) { norm(couplast_* coup_[5] ); } else { norm(couplast_*conj(coup_[5])); } } else assert(false); } } else { norm(couplast_*coup_[7]); } } diff --git a/Models/Susy/SSWWHVertex.cc b/Models/Susy/SSWWHVertex.cc --- a/Models/Susy/SSWWHVertex.cc +++ b/Models/Susy/SSWWHVertex.cc @@ -1,103 +1,104 @@ // -*- C++ -*- // // SSWWHVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SSWWHVertex class. // #include "SSWWHVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include using namespace ThePEG::Helicity; using namespace Herwig; SSWWHVertex::SSWWHVertex() : theh0Wfact(ZERO), theH0Wfact(ZERO), theh0Zfact(ZERO), theH0Zfact(ZERO), theCoupLast(ZERO), theElast(0.0), theq2last(ZERO), theHlast(0), theGBlast(0) { orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::SINGLET); } void SSWWHVertex::doinit() { addToList(23,23,25); addToList(-24,24,25); addToList(23,23,35); addToList(-24,24,35); VVSVertex::doinit(); tMSSMPtr model = dynamic_ptr_cast(generator()->standardModel()); if( !model ) throw InitException() << "SSWWHVertex::doinit() - The pointer to the MSSM object is null!" << Exception::abortnow; Energy mw = getParticleData(ParticleID::Wplus)->mass(); Energy mz = getParticleData(ParticleID::Z0)->mass(); double sw = sqrt(sin2ThetaW()); double sinalp = sin(model->higgsMixingAngle()); double cosalp = sqrt(1. - sqr(sinalp)); double tanbeta = model->tanBeta(); double sinbeta = tanbeta/sqrt(1. + sqr(tanbeta)); double cosbeta = sqrt( 1. - sqr(sinbeta) ); double sinbma = sinbeta*cosalp - cosbeta*sinalp; double cosbma = cosbeta*cosalp + sinbeta*sinalp; theh0Wfact = mw*sinbma/sw; theH0Wfact = mw*cosbma/sw; theh0Zfact = mz*sinbma/sw/sqrt(1. - sw*sw); theH0Zfact = mz*cosbma/sw/sqrt(1. - sw*sw); } void SSWWHVertex::persistentOutput(PersistentOStream & os) const { os << ounit(theh0Wfact,GeV) << ounit(theH0Wfact,GeV) << ounit(theh0Zfact,GeV) << ounit(theH0Zfact,GeV); } void SSWWHVertex::persistentInput(PersistentIStream & is, int) { is >> iunit(theh0Wfact,GeV) >> iunit(theH0Wfact,GeV) >> iunit(theh0Zfact,GeV) >> iunit(theH0Zfact,GeV); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigSSWWHVertex("Herwig::SSWWHVertex", "HwSusy.so"); void SSWWHVertex::Init() { static ClassDocumentation documentation ("This is the coupling of a pair of SM gauge bosons" "to the higgs particles in the MSSM"); } void SSWWHVertex::setCoupling(Energy2 q2, tcPDPtr particle1, tcPDPtr, tcPDPtr particle3) { long bosonID = abs(particle1->id()); long higgsID = particle3->id(); assert( higgsID == ParticleID::h0 || higgsID == ParticleID::H0 ); assert( bosonID == ParticleID::Wplus || bosonID == ParticleID::Z0 ); if( higgsID != theHlast || bosonID != theGBlast) { if( higgsID == ParticleID::h0 ) theCoupLast = (bosonID == ParticleID::Z0) ? theh0Zfact : theh0Wfact; else theCoupLast = (bosonID == ParticleID::Z0) ? theH0Zfact : theH0Wfact; } if( q2 != theq2last ) { theq2last = q2; theElast = electroMagneticCoupling(q2); } norm(theElast*theCoupLast*UnitRemoval::InvE); } diff --git a/Models/Susy/SSWWSSVertex.cc b/Models/Susy/SSWWSSVertex.cc --- a/Models/Susy/SSWWSSVertex.cc +++ b/Models/Susy/SSWWSSVertex.cc @@ -1,267 +1,269 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the SSWWSSVertex class. // #include "SSWWSSVertex.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; SSWWSSVertex::SSWWSSVertex() : sw_(0.), cw_(0.), q2last_(), couplast_(0.), ulast_(0), dlast_(0), gblast1_(0), gblast2_(0), - factlast_(0.) {} + factlast_(0.) { + colourStructure(ColourStructure::DELTA); +} IBPtr SSWWSSVertex::clone() const { return new_ptr(*this); } IBPtr SSWWSSVertex::fullclone() const { return new_ptr(*this); } void SSWWSSVertex::persistentOutput(PersistentOStream & os) const { os << sw_ << cw_ << stau_ << stop_ << sbottom_; } void SSWWSSVertex::persistentInput(PersistentIStream & is, int) { is >> sw_ >> cw_ >> stau_ >> stop_ >> sbottom_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigSSWWSSVertex("Herwig::SSWWSSVertex", "HwSusy.so"); void SSWWSSVertex::Init() { static ClassDocumentation documentation ("The SSWWSSVertex class implements the coupling of two" " weak bosons and two scalar fermions"); } void SSWWSSVertex::doinit() { // gamma gamma, gamma Z0 and Z0 Z0 PAIRS for(long ib1=22;ib1<24;++ib1) { for(long ib2=22;ib2<24;++ib2) { // sleptons long istep = ib1==23&&ib2==23 ? 1 : 2; for(long ix=1000011;ix<1000017;ix+=istep) { addToList(ib1,ib2,ix,-ix); } for(long ix=2000011;ix<2000017;ix+=2) { addToList(ib1,ib2,ix,-ix); } // squarks for(long ix=1000001;ix<1000007;++ix) { addToList(ib1,ib2,ix,-ix); } for(long ix=2000001;ix<2000007;++ix) { addToList(ib1,ib2,ix,-ix); } // L/R mixing if Z if(ib2==23) { //L-Rbar stau addToList(ib1,ib2,1000015,-2000015); //Lbar-R stau addToList(ib1,ib2,-1000015,2000015); //L-Rbar stop addToList(ib1,ib2,1000006,-2000006); //Lbar-R stop addToList(ib1,ib2,-1000006,2000006); //L-Rbar sbottom addToList(ib1,ib2,1000005,-2000005); //Lbar-R sbottom addToList(ib1,ib2,-1000005,2000005); } } // W- gamma/Z0 // LL-squarks for(long ix=1000001;ix<1000006;ix+=2) { addToList(-24,ib1,ix+1,-ix); } // 1-2 stop sbottom addToList(-24,ib1,1000006,-2000005); // 2-1 stop sbottom addToList(-24,ib1,2000006,-1000005); // 2-2 stop sbottom addToList(-24,ib1,2000006,-2000005); // LL-sleptons for(long ix=1000011;ix<1000016;ix+=2) { addToList(-24,ib1,-ix,ix+1); } //2-L stau addToList(-24,ib1,-2000015,1000016); // W+ gamma/Z0 // LL-squarks for(long ix=1000001;ix<1000006;ix+=2) { addToList(24,ib1,-(ix+1),ix); } // 1-2 stop sbottom addToList(24,ib1,-1000006,2000005); // 2-1 stop sbottom addToList(24,ib1,-2000006,1000005); // 2-2 stop sbottom addToList(24,ib1,-2000006,2000005); // LL-sleptons for(long ix=1000011;ix<1000016;ix+=2) { addToList(24,ib1,ix,-ix-1); } //2-L stau addToList(24,ib1,2000015,-1000016); } // finally WW pairs // sleptons for(long ix=1000011;ix<=1000017;++ix) { addToList(24,-24,ix,-ix); } addToList(24,-24,1000015,-2000015); addToList(24,-24,2000015,-1000015); // squarks for(long ix=1000001;ix<=1000007;++ix) { addToList(24,-24,ix,-ix); } addToList(24,-24,1000005,-2000005); addToList(24,-24,2000005,-1000005); addToList(24,-24,1000006,-2000006); addToList(24,-24,2000006,-1000006); // couplings etc orderInGem(2); orderInGs(0); VVSSVertex::doinit(); tMSSMPtr model = dynamic_ptr_cast(generator()->standardModel()); if(!model) throw InitException() << "SSWWSSVertex::doinit() - " << "The model pointer is null." << Exception::abortnow; sw_ = sqrt(sin2ThetaW()); cw_ = sqrt( 1. - sqr(sw_) ); stop_ = model->stopMix(); sbottom_ = model->sbottomMix(); stau_ = model->stauMix(); if(!stop_ || !stau_ || !sbottom_) throw InitException() << "SSWWSSVertex::doinit() - " << "A mixing matrix pointer is null." << " stop: " << stop_ << " sbottom: " << sbottom_ << " stau: " << stau_ << Exception::abortnow; } void SSWWSSVertex::setCoupling(Energy2 q2,tcPDPtr part1, tcPDPtr part2,tcPDPtr part3, tcPDPtr part4) { long boson[2] = {abs(part1->id()),abs(part2->id())}; assert( boson[0] == ParticleID::Wplus || boson[0] == ParticleID::Z0 || boson[0] == ParticleID::gamma ); assert( boson[1] == ParticleID::Wplus || boson[1] == ParticleID::Z0 || boson[1] == ParticleID::gamma ); long sf1(abs(part3->id())),sf2(abs(part4->id())); assert( (sf1 >= 1000001 && sf1 <= 1000006) || (sf1 >= 1000011 && sf1 <= 1000016) || (sf1 >= 2000001 && sf1 <= 2000006) || (sf1 >= 2000011 && sf1 <= 2000016) ); assert( (sf2 >= 1000001 && sf2 <= 1000006) || (sf2 >= 1000011 && sf2 <= 1000016) || (sf2 >= 2000001 && sf2 <= 2000006) || (sf2 >= 2000011 && sf2 <= 2000016) ); if( sf1 % 2 != 0 ) swap(sf1, sf2); if(boson[0]>boson[1]) swap(boson[0],boson[1]); if( sf1 != ulast_ || sf2 != dlast_ || boson[0] != gblast1_ || boson[1] != gblast2_) { gblast1_ = boson[0]; gblast2_ = boson[1]; ulast_ = sf1; dlast_ = sf2; double ef1 = getParticleData(sf1)->charge()/eplus; double ef2 = getParticleData(sf2)->charge()/eplus; // photon pairs are simplest if(gblast1_ == ParticleID::gamma && gblast2_ == ParticleID::gamma ) { factlast_ = 2.*sqr( ef1 ); } // otherwise we need the helicity states else { //determine which helicity state unsigned int alpha(sf1/1000000 - 1), beta(sf2/1000000 - 1); //mixing factors Complex m1a(0.), m1b(0.); if( sf1 == ParticleID::SUSY_t_1 || sf1 == ParticleID::SUSY_t_2 ) m1a = (*stop_)(alpha, 0); else if( sf1 == ParticleID::SUSY_b_1 || sf1 == ParticleID::SUSY_b_2 ) m1a = (*sbottom_)(alpha, 0); else if( sf1 == ParticleID::SUSY_tau_1minus || sf1 == ParticleID::SUSY_tau_2minus ) m1a = (*stau_)(alpha, 0); else m1a = (alpha == 0) ? Complex(1.) : Complex(0.); if( sf2 == ParticleID::SUSY_t_1 || sf2 == ParticleID::SUSY_t_2 ) m1b = (*stop_)(beta, 0); else if( sf2 == ParticleID::SUSY_b_1 || sf2 == ParticleID::SUSY_b_2 ) m1b = (*sbottom_)(beta, 0); else if( sf2 == ParticleID::SUSY_tau_1minus || sf2 == ParticleID::SUSY_tau_2minus ) m1b = (*stau_)(beta, 0); else m1b = (beta == 0) ? Complex(1.) : Complex(0.); // if either boson is a W if(gblast2_==ParticleID::Wplus) { // WW if(gblast1_==ParticleID::Wplus) { factlast_ = 0.5*m1a*m1b/sqr(sw_); } // gamma W else if(gblast1_==ParticleID::gamma) { factlast_ = sqrt(0.5)*m1a*m1b/sw_*(ef1+ef2); } // Z0 W else if(gblast1_==ParticleID::Z0) { factlast_ = -sqrt(0.5)*m1a*m1b/cw_*(ef1+ef2); } } else { // compute the Z coupling factlast_=1.; if(gblast1_==ParticleID::Z0||gblast2_==ParticleID::Z0) { if( sf1 == ParticleID::SUSY_nu_eL || sf1 == ParticleID::SUSY_nu_muL || sf1 == ParticleID::SUSY_nu_tauL ) { factlast_ = 0.5/cw_/sw_; } else { double lmda = sf2 % 2 == 0 ? 1. : -1.; factlast_ = lmda*m1a*m1b; if( alpha == beta) factlast_ -= 2.*ef1*sqr(sw_); factlast_ *= 0.5/cw_/sw_; } } // photon Z if(gblast1_ == ParticleID::gamma && gblast2_ == ParticleID::Z0 ) { factlast_ *= 2.*ef1; } // Z pairs else if(gblast1_ == ParticleID::Z0 && gblast2_ == ParticleID::Z0 ) { factlast_ *= 2.*factlast_; } } } } if( q2 != q2last_ || couplast_==0. ) { q2last_ = q2; couplast_ = sqr(electroMagneticCoupling(q2)); } norm(couplast_*factlast_); } diff --git a/Models/TTbAsymm/TTbAModelAGQQVertex.cc b/Models/TTbAsymm/TTbAModelAGQQVertex.cc --- a/Models/TTbAsymm/TTbAModelAGQQVertex.cc +++ b/Models/TTbAsymm/TTbAModelAGQQVertex.cc @@ -1,103 +1,101 @@ // -*- C++ -*- // // TTbAModelAGQQVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 TTbAModelAGQQVertex class. // #include "TTbAModelAGQQVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Config/Constants.h" using namespace Herwig; IBPtr TTbAModelAGQQVertex::clone() const { return new_ptr(*this); } IBPtr TTbAModelAGQQVertex::fullclone() const { return new_ptr(*this); } TTbAModelAGQQVertex::TTbAModelAGQQVertex() { orderInGem(1); orderInGs(1); addToList(-1,1,63); addToList(-2,2,63); addToList(-3,3,63); addToList(-4,4,63); addToList(-5,5,63); addToList(-6,6,63); - - - + colourStructure(ColourStructure::DELTA); } void TTbAModelAGQQVertex::doinit() { _theModel = generator()->standardModel(); tcHwTTbAPtr hwTTbA=dynamic_ptr_cast(_theModel); if(hwTTbA) { _cAGQQ_R =hwTTbA->_cAGQQ_right(); _cAGQQ_L =hwTTbA->_cAGQQ_left(); _cAGTT_R =hwTTbA->_cAGTT_right(); _cAGTT_L =hwTTbA->_cAGTT_left(); _models = hwTTbA->_model(); } FFVVertex::doinit(); } void TTbAModelAGQQVertex::persistentOutput(PersistentOStream & os) const { os << _cAGQQ_R << _cAGQQ_L << _cAGTT_R << _cAGTT_L << _models; } void TTbAModelAGQQVertex::persistentInput(PersistentIStream & is, int) { is >> _cAGQQ_R >> _cAGQQ_L >>_cAGTT_R >> _cAGTT_L >> _models; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigTTbAModelAGQQVertex("Herwig::TTbAModelAGQQVertex", "Herwig.so"); void TTbAModelAGQQVertex::Init() { static ClassDocumentation documentation ("The TTbAModelAGQQVertex class is the implementation" " of the helicity amplitude calculation of the TTbA" " quark-lepton vertex."); } void TTbAModelAGQQVertex::setCoupling(Energy2 q2,tcPDPtr aa ,tcPDPtr bb, tcPDPtr cc) { double _cL = 0, _cR = 0; double gstrong = 1.0; gstrong = strongCoupling(q2); if(abs(aa->id()) == 63 || abs(bb->id()) == 63 || abs(cc->id()) == 63) { if(abs(aa->id()) !=6 && abs(bb->id()) !=6 && abs(cc->id()) != 6) { _cR = _cAGQQ_R; _cL = _cAGQQ_L; } else { _cR = _cAGTT_R; _cL = _cAGTT_L; } } if(_models!=2) { _cL = 1E-10; _cR = 1E-10; } left(_cL); right(_cR); norm(gstrong); } diff --git a/Models/TTbAsymm/TTbAModelSU2XVertex.cc b/Models/TTbAsymm/TTbAModelSU2XVertex.cc --- a/Models/TTbAsymm/TTbAModelSU2XVertex.cc +++ b/Models/TTbAsymm/TTbAModelSU2XVertex.cc @@ -1,186 +1,186 @@ // -*- C++ -*- // // TTbAModelSU2XVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 TTbAModelSU2XVertex class. // #include "TTbAModelSU2XVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Config/Constants.h" using namespace Herwig; IBPtr TTbAModelSU2XVertex::clone() const { return new_ptr(*this); } IBPtr TTbAModelSU2XVertex::fullclone() const { return new_ptr(*this); } TTbAModelSU2XVertex::TTbAModelSU2XVertex() { orderInGem(1); orderInGs(1); addToList(-6,6,70); addToList(-2,2,70); addToList(-2,6,70); addToList(2,-6,70); addToList(-6,6,71); addToList(-2,2,71); addToList(-2,6,71); addToList(2,-6,71); addToList(-6,6,-71); addToList(-2,2,-71); addToList(-2,6,-71); addToList(2,-6,-71); - + colourStructure(ColourStructure::DELTA); } void TTbAModelSU2XVertex::doinit() { _theModel = generator()->standardModel(); tcHwTTbAPtr hwTTbA=dynamic_ptr_cast(_theModel); if(hwTTbA) { _alphaX =hwTTbA->_alphaX_value(); _costhetaX =hwTTbA->_costhetaX_value(); _models =hwTTbA->_model(); } FFVVertex::doinit(); } void TTbAModelSU2XVertex::persistentOutput(PersistentOStream & os) const { os << _alphaX << _costhetaX << _models; } void TTbAModelSU2XVertex::persistentInput(PersistentIStream & is, int) { is >> _alphaX >> _costhetaX >> _models; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigTTbAModelSU2XVertex("Herwig::TTbAModelSU2XVertex", "Herwig.so"); void TTbAModelSU2XVertex::Init() { static ClassDocumentation documentation ("The TTbAModelSU2XVertex class is the implementation" " of the helicity amplitude calculation of the TTbA" " SU(2)_X vertex."); } void TTbAModelSU2XVertex::setCoupling(Energy2,tcPDPtr aa ,tcPDPtr bb, tcPDPtr cc) { double _cR = 0, _fac = 0; _gX = sqrt( 4 * Constants::pi * _alphaX ); double ct = _costhetaX; double st = sqrt(1 - pow(ct,2)); //Vz if( abs(aa->id()) == 70 || abs(bb->id()) == 70 || abs(cc->id()) == 70) { _fac = _gX / 2.0; if( aa->id() == 6 || bb->id() == 6 || cc->id() == 6) { if( aa->id() == -6 || bb->id() == -6 || cc->id() == -6) { _cR = pow(ct,2) - pow(st,2); } } if( aa->id() == 2 || bb->id() == 2 || cc->id() == 2) { if( aa->id() == -2 || bb->id() == -2 || cc->id() == -2) { _cR = pow(st,2) - pow(ct,2); } } if( abs(aa->id()) == 2 || abs(bb->id()) == 2 || abs(cc->id()) == 2) { if( abs(aa->id()) == 6 || abs(bb->id()) == 6 || abs(cc->id()) == 6) { _cR = 2 * ct * st; } } } //Ym if( aa->id() == -71 || bb->id() == -71 || cc->id() == -71 ) { _fac = _gX / sqrt(2.0); if( aa->id() == 6 || bb->id() == 6 || cc->id() == 6) { if( aa->id() == -6 || bb->id() == -6 || cc->id() == -6) { _cR = - ct * st; } } if( aa->id() == 2 || bb->id() == 2 || cc->id() == 2) { if( aa->id() == -2 || bb->id() == -2 || cc->id() == -2) { _cR = ct * st; } } if( aa->id() == 2 || bb->id() == 2 || cc->id() == 2) { if( aa->id() == -6 || bb->id() == -6 || cc->id() == -6) { _cR = - pow(st,2); } } if( aa->id() == -2 || bb->id() == -2 || cc->id() == -2) { if( aa->id() == 6 || bb->id() == 6 || cc->id() == 6) { _cR = pow(ct,2); } } } //Yp if( aa->id() == 71 || bb->id() == 71 || cc->id() == 71 ) { _fac = _gX / sqrt(2.0); if( aa->id() == 6 || bb->id() == 6 || cc->id() == 6) { if( aa->id() == -6 || bb->id() == -6 || cc->id() == -6) { _cR = - ct * st; } } if( aa->id() == 2 || bb->id() == 2 || cc->id() == 2) { if( aa->id() == -2 || bb->id() == -2 || cc->id() == -2) { _cR = ct * st; } } if( aa->id() == 2 || bb->id() == 2 || cc->id() == 2) { if( aa->id() == -6 || bb->id() == -6 || cc->id() == -6) { _cR = pow(ct,2); } } if( aa->id() == -2 || bb->id() == -2 || cc->id() == -2) { if( aa->id() == 6 || bb->id() == 6 || cc->id() == 6) { _cR = - pow(st,2); } } } //normalise according to Lagrangian factor _cR *= _fac; //If this model is not selected set coupling to zero. if(_models!=3) { _cR = 1E-10; } right(_cR); left(0.); norm(1.0); } diff --git a/Models/TTbAsymm/TTbAModelWPTDVertex.cc b/Models/TTbAsymm/TTbAModelWPTDVertex.cc --- a/Models/TTbAsymm/TTbAModelWPTDVertex.cc +++ b/Models/TTbAsymm/TTbAModelWPTDVertex.cc @@ -1,85 +1,86 @@ // -*- C++ -*- // // TTbAModelWPTDVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 TTbAModelWPTDVertex class. // #include "TTbAModelWPTDVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Config/Constants.h" using namespace Herwig; IBPtr TTbAModelWPTDVertex::clone() const { return new_ptr(*this); } IBPtr TTbAModelWPTDVertex::fullclone() const { return new_ptr(*this); } TTbAModelWPTDVertex::TTbAModelWPTDVertex() { addToList(-1,6,-34); addToList(-6,1,34); orderInGem(1); orderInGs(1); + colourStructure(ColourStructure::DELTA); } void TTbAModelWPTDVertex::doinit() { _theModel = generator()->standardModel(); tcHwTTbAPtr hwTTbA=dynamic_ptr_cast(_theModel); if(hwTTbA) { _cWPTD_R =hwTTbA->_cWPTD_right(); _cWPTD_L =hwTTbA->_cWPTD_left(); _models =hwTTbA->_model(); } FFVVertex::doinit(); } void TTbAModelWPTDVertex::persistentOutput(PersistentOStream & os) const { os << _cWPTD_R << _cWPTD_L << _models; } void TTbAModelWPTDVertex::persistentInput(PersistentIStream & is, int) { is >> _cWPTD_R >> _cWPTD_L >> _models; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigTTbAModelWPTDVertex("Herwig::TTbAModelWPTDVertex", "Herwig.so"); void TTbAModelWPTDVertex::Init() { static ClassDocumentation documentation ("The TTbAModelWPTDVertex class is the implementation" " of the helicity amplitude calculation of the TTbA" " quark-lepton vertex."); } void TTbAModelWPTDVertex::setCoupling(Energy2,tcPDPtr aa ,tcPDPtr bb, tcPDPtr cc) { double _cL = 0, _cR = 0; if(abs(aa->id()) == 34 || abs(bb->id()) == 34 || abs(cc->id()) == 34) { _cR = _cWPTD_R; _cL = _cWPTD_L; } if(_models!=0) { _cL = 1E-10; _cR = 1E-10; } left(_cL); right(_cR); norm(1.0); } diff --git a/Models/TTbAsymm/TTbAModelZPQQVertex.cc b/Models/TTbAsymm/TTbAModelZPQQVertex.cc --- a/Models/TTbAsymm/TTbAModelZPQQVertex.cc +++ b/Models/TTbAsymm/TTbAModelZPQQVertex.cc @@ -1,101 +1,102 @@ // -*- C++ -*- // // TTbAModelZPQQVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 TTbAModelZPQQVertex class. // #include "TTbAModelZPQQVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Config/Constants.h" using namespace Herwig; IBPtr TTbAModelZPQQVertex::clone() const { return new_ptr(*this); } IBPtr TTbAModelZPQQVertex::fullclone() const { return new_ptr(*this); } TTbAModelZPQQVertex::TTbAModelZPQQVertex() { addToList(-2,6,32); addToList(-6,2,32); addToList(-2,2,32); addToList(-4,4,32); orderInGem(1); orderInGs(1); + colourStructure(ColourStructure::DELTA); } void TTbAModelZPQQVertex::doinit() { _theModel = generator()->standardModel(); tcHwTTbAPtr hwTTbA=dynamic_ptr_cast(_theModel); if(hwTTbA) { _cZPTU_R =hwTTbA->_cZPTU_right(); _cZPTU_L =hwTTbA->_cZPTU_left(); _cZPUU_R =hwTTbA->_cZPUU_right(); _cZPUU_L =hwTTbA->_cZPUU_left(); _cZPCC_R =hwTTbA->_cZPCC_right(); _cZPCC_L =hwTTbA->_cZPCC_left(); _models =hwTTbA->_model(); } FFVVertex::doinit(); } void TTbAModelZPQQVertex::persistentOutput(PersistentOStream & os) const { os << _cZPTU_R << _cZPTU_L << _cZPUU_R << _cZPUU_L << _cZPCC_R << _cZPCC_L << _models; } void TTbAModelZPQQVertex::persistentInput(PersistentIStream & is, int) { is >> _cZPTU_R >> _cZPTU_L >> _cZPUU_R >> _cZPUU_L >> _cZPCC_R >> _cZPCC_L >> _models; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigTTbAModelZPQQVertex("Herwig::TTbAModelZPQQVertex", "Herwig.so"); void TTbAModelZPQQVertex::Init() { static ClassDocumentation documentation ("The TTbAModelZPQQVertex class is the implementation" " of the helicity amplitude calculation of the TTbA" " Z prime Quark-antiQuark vertex."); } void TTbAModelZPQQVertex::setCoupling(Energy2,tcPDPtr aa ,tcPDPtr bb, tcPDPtr cc) { double _cR = 0, _cL = 0; if( abs(aa->id()) == 6 || abs(bb->id()) == 6 || abs(cc->id()) == 6) { _cR = _cZPTU_R; _cL = _cZPTU_L; } else { if( abs(aa->id()) != 4 && abs(bb->id()) != 4 && abs(cc->id()) != 4) { _cR = _cZPUU_R; _cL = _cZPUU_L; } if( abs(aa->id()) == 4 || abs(bb->id()) == 4 || abs(cc->id()) == 4) { _cR = _cZPCC_R; _cL = _cZPCC_L; } } if(_models!=1) { _cL = 1E-10; _cR = 1E-10; } right(_cR); left(_cL); norm(1.0); } diff --git a/Models/Transplanckian/METRP2to2.cc b/Models/Transplanckian/METRP2to2.cc --- a/Models/Transplanckian/METRP2to2.cc +++ b/Models/Transplanckian/METRP2to2.cc @@ -1,350 +1,344 @@ // -*- C++ -*- // // METRP2to2.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2009-2017 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 METRP2to2 class. // #include "METRP2to2.h" #include "ThePEG/Utilities/SimplePhaseSpace.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "Herwig/Models/StandardModel/StandardModel.h" #include "ThePEG/Handlers/StandardXComb.h" #include "ThePEG/Cuts/Cuts.h" #include "Herwig/Utilities/Interpolator.h" #include "ThePEG/Utilities/DescribeClass.h" #include using namespace Herwig; DescribeClass describeHerwigMETRP2to2("Herwig::METRP2to2","HwTransplanck.so"); HERWIG_INTERPOLATOR_CLASSDESC(METRP2to2,double,double) METRP2to2::METRP2to2() : _maxflavour(2), _ndim(6), _planckmass(1500.0*GeV), _process(0) { - massOption(vector(2,0)); + massOption({{0,0}}); } void METRP2to2::doinit() { HwMEBase::doinit(); setup_interpolator(); } void METRP2to2::rebind(const TranslationMap & trans) { _interpol = trans.translate(_interpol); HwMEBase::rebind(trans); } IVector METRP2to2::getReferences() { IVector ret = HwMEBase::getReferences(); ret.push_back(_interpol); return ret; } void METRP2to2::setup_interpolator() { - static const double xmatrix1[103] = {0.0, 0.02, 0.10, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3., 3.2, 3.4, 3.6, 3.8, 4., 4.2, 4.4, 4.6, 4.8, 5.0, 5.2, 5.4, 5.6, 5.8, 6., 6.2, 6.4, 6.6, 6.8, 7., 7.2, 7.4, 7.6, 7.8, 8., 8.2, 8.4, 8.6, 8.8, 9., 9.2, 9.4, 9.6, 9.8, 10., 10.2, 10.4, 10.6, 10.8, 11., 11.2, 11.4, 11.6, 11.8, 12., 12.2, 12.4, 12.6, 12.8, 13., 13.2, 13.4, 13.6, 13.8, 14., 14.2, 14.4, 14.6, 14.8, 15., 15.2, 15.4, 15.6, 15.8, 16., 16.2, 16.4, 16.6, 16.8, 17., 17.2, 17.4, 17.6, 17.8, 18., 18.2, 18.4, 18.6, 18.8, 19., 19.2, 19.4, 19.6, 19.8, 20.0 }; - static const double xmatrix2[102] = {0.02, 0.10, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3., 3.2, 3.4, 3.6, 3.8, 4., 4.2, 4.4, 4.6, 4.8, 5., 5.2, 5.4, 5.6, 5.8, 6., 6.2, 6.4, 6.6, 6.8, 7., 7.2, 7.4, 7.6, 7.8, 8., 8.2, 8.4, 8.6, 8.8, 9., 9.2, 9.4, 9.6, 9.8, 10., 10.2, 10.4, 10.6, 10.8, 11., 11.2, 11.4, 11.6, 11.8, 12., 12.2, 12.4, 12.6, 12.8, 13., 13.2, 13.4, 13.6, 13.8, 14., 14.2, 14.4, 14.6, 14.8, 15., 15.2, 15.4, 15.6, 15.8, 16., 16.2, 16.4, 16.6, 16.8, 17., 17.2, 17.4, 17.6, 17.8, 18., 18.2, 18.4, 18.6, 18.8, 19., 19.2, 19.4, 19.6, 19.8, 20.0 }; - static const double datamatrix2[102] = {4.32048, 2.74662, 2.090560, 1.457590, 1.113050, 0.885216, 0.720795, 0.597404, 0.501483, 0.425543, 0.364668, 0.315299, 0.274983, 0.241792, 0.214466, 0.191698, 0.172689, 0.156841, 0.143329, 0.131919, 0.122174, 0.113656, 0.106339, 0.099869, 0.094101, 0.089013, 0.084378, 0.080185, 0.076376, 0.072856, 0.069622, 0.066624, 0.063844, 0.061242, 0.058820, 0.056561, 0.054417, 0.052433, 0.05055, 0.048772, 0.047129, 0.045546, 0.044056, 0.042673, 0.041328, 0.040078, 0.038895, 0.037749, 0.036688, 0.035666, 0.034687, 0.033771, 0.032883, 0.032041, 0.031239, 0.030467, 0.029731, 0.029025, 0.028350, 0.027698, 0.027075, 0.026479, 0.025896, 0.025347, 0.024812, 0.024291, 0.023804, 0.023318, 0.022854, 0.022416, 0.021974, 0.021561, 0.021160, 0.020761, 0.020390, 0.020021, 0.019662, 0.019325, 0.01898, 0.018662, 0.018351, 0.018041, 0.017747, 0.017459, 0.017177, 0.016906, 0.016641, 0.016384, 0.016132, 0.015889, 0.015651, 0.015418, 0.015196, 0.014973, 0.014759, 0.014553, 0.014345, 0.014149, 0.013956, 0.013762, 0.013582, 0.013399}; - static const double datamatrix3[103] = {1.33947, 1.32238, 1.25505, 1.17491, 1.02696, 0.89463, 0.77688, 0.67270, 0.58105, 0.50095, 0.43143, 0.37156, 0.32046, 0.27726, 0.24113, 0.21126, 0.18684, 0.16707, 0.15118, 0.13843, 0.12815, 0.11974, 0.11271, 0.10670, 0.10141, 0.09663, 0.09224, 0.08814, 0.08427, 0.08061, 0.07715, 0.07387, 0.07077, 0.06785, 0.06511, 0.06254, 0.06014, 0.05790, 0.05582, 0.05388, 0.05207, 0.05038, 0.04879, 0.04731, 0.04591, 0.04459, 0.04334, 0.04216, 0.04103, 0.03996, 0.03894, 0.03796, 0.03702, 0.03612, 0.03526, 0.03443, 0.03363, 0.03287, 0.03214, 0.03143, 0.03075, 0.03010, 0.02947, 0.02887, 0.02829, 0.02773, 0.02719, 0.02666, 0.02616, 0.02567, 0.0250, 0.02475, 0.02431, 0.02388, 0.02347, 0.02306, 0.02267, 0.02230, 0.02193, 0.02157, 0.02123, 0.02089, 0.02056, 0.02025, 0.01994, 0.01964, 0.01934, 0.01906, 0.018, 0.01851, 0.01825, 0.01799, 0.01774, 0.01750, 0.01726, 0.01703, 0.01680, 0.01658, 0.01637, 0.01616, 0.01595, 0.01575, 0.01555}; - static const double datamatrix4[103] = {0.88623, 0.885845, 0.879328, 0.86361, 0.81617, 0.75594, 0.68928, 0.62036, 0.55206, 0.48641, 0.42484, 0.36832, 0.31749, 0.27273, 0.23419, 0.20185, 0.17547, 0.15464, 0.13871, 0.12685, 0.11813, 0.11162, 0.10654, 0.10229, 0.09844, 0.09475, 0.09107, 0.08738, 0.08368, 0.08000, 0.07641, 0.07295, 0.06967, 0.06660, 0.06377, 0.06118, 0.05883, 0.05670, 0.05476, 0.05300, 0.05138, 0.04989, 0.04849, 0.04716, 0.04590, 0.04469, 0.04353, 0.04240, 0.04131, 0.04026, 0.03924, 0.03826, 0.037, 0.03642, 0.03556, 0.03473, 0.03394, 0.03319, 0.03247, 0.03178, 0.03112, 0.03049, 0.02988, 0.02930, 0.02873, 0.02819, 0.02767, 0.02716, 0.02667, 0.02619, 0.02573, 0.02529, 0.02486, 0.02444, 0.02403, 0.02364, 0.02326, 0.02289, 0.02253, 0.02218, 0.02184, 0.02152, 0.02120, 0.02089, 0.02058, 0.02029, 0.02000, 0.01972, 0.01944, 0.01918, 0.01892, 0.01866, 0.01841, 0.01816, 0.01792, 0.01769, 0.01746, 0.01724, 0.01702, 0.01681, 0.01660, 0.01639, 0.01619 }; - static const double datamatrix5[103] = {0.744596, 0.744489, 0.742327, 0.73584, 0.71183, 0.67590, 0.63118, 0.58053, 0.52645, 0.47109, 0.41628, 0.36351, 0.31401, 0.26878, 0.22857, 0.19396, 0.16533, 0.14280, 0.12611, 0.11459, 0.10713, 0.10244, 0.09934, 0.09690, 0.09453, 0.09189, 0.08887, 0.08548, 0.08180, 0.07796, 0.07410, 0.07035, 0.06681, 0.06358, 0.06068, 0.05815, 0.05595, 0.05405, 0.05240, 0.05094, 0.04962, 0.04838, 0.04720, 0.04604, 0.04489, 0.04375, 0.04262, 0.04150, 0.04040, 0.03934, 0.03831, 0.03733, 0.03639, 0.03551, 0.03469, 0.03391, 0.03317, 0.03247, 0.03181, 0.03118, 0.03057, 0.02998, 0.02941, 0.02886, 0.02832, 0.02779, 0.02728, 0.02678, 0.02630, 0.02583, 0.02538, 0.02494, 0.02452, 0.02412, 0.02373, 0.02335, 0.02299, 0.02264, 0.02230, 0.02197, 0.02165, 0.02134, 0.02104, 0.02074, 0.02045, 0.02016, 0.01989, 0.01961, 0.01935, 0.01909, 0.01883, 0.01858, 0.01834, 0.01810, 0.01787, 0.01764, 0.01742, 0.01721, 0.01699, 0.01679, 0.01659, 0.01639, 0.01620}; - static const double datamatrix6[103] = {0.67759, 0.677074, 0.675686, 0.67139, 0.65466, 0.62818, 0.59351, 0.55242, 0.50671, 0.45815, 0.40837, 0.35888, 0.31104, 0.26603, 0.22490, 0.18855, 0.15777, 0.13319, 0.11510, 0.10322, 0.09650, 0.09333, 0.09206, 0.09137, 0.09045, 0.08888, 0.08652, 0.08343, 0.07977, 0.07574, 0.07157, 0.06747, 0.06364, 0.06020, 0.05725, 0.05479, 0.05281, 0.05121, 0.04991, 0.04880, 0.04779, 0.04680, 0.04580, 0.04475, 0.04364, 0.04249, 0.04130, 0.04012, 0.03895, 0.03783, 0.03677, 0.03579, 0.03488, 0.03405, 0.03330, 0.03261, 0.03197, 0.03137, 0.03080, 0.03025, 0.02970, 0.02917, 0.02863, 0.02811, 0.02758, 0.02707, 0.02657, 0.02608, 0.02560, 0.02515, 0.02471, 0.02430, 0.02390, 0.02351, 0.02314, 0.02279, 0.02244, 0.02211, 0.02178, 0.02146, 0.02115, 0.02084, 0.02054, 0.02025, 0.01996, 0.01968, 0.01941, 0.01915, 0.01890, 0.01865, 0.01841, 0.01818, 0.01795, 0.01773, 0.01751, 0.01730, 0.01710, 0.01690, 0.01670, 0.01650, 0.01631, 0.01612, 0.01593 }; - - const double * datamatrix = 0; - const double * xmatrix = 0; - int xsize = 0; - - //assign the appropriate tabulated points for the number of extra dimensions - switch ( _ndim ) { - case 2 : datamatrix = datamatrix2; xmatrix = xmatrix2; xsize = 102; break; - case 3 : datamatrix = datamatrix3; xmatrix = xmatrix1; xsize = 103; break; - case 4 : datamatrix = datamatrix4; xmatrix = xmatrix1; xsize = 103; break; - case 5 : datamatrix = datamatrix5; xmatrix = xmatrix1; xsize = 103; break; - case 6 : datamatrix = datamatrix6; xmatrix = xmatrix1; xsize = 103; break; - default : assert(false); - } - _interpol = make_InterpolatorPtr(xsize, datamatrix, 1.0, xmatrix, 1.0, 1); + static const array xmatrix1 = {{0.0, 0.02, 0.10, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3., 3.2, 3.4, 3.6, 3.8, 4., 4.2, 4.4, 4.6, 4.8, 5.0, 5.2, 5.4, 5.6, 5.8, 6., 6.2, 6.4, 6.6, 6.8, 7., 7.2, 7.4, 7.6, 7.8, 8., 8.2, 8.4, 8.6, 8.8, 9., 9.2, 9.4, 9.6, 9.8, 10., 10.2, 10.4, 10.6, 10.8, 11., 11.2, 11.4, 11.6, 11.8, 12., 12.2, 12.4, 12.6, 12.8, 13., 13.2, 13.4, 13.6, 13.8, 14., 14.2, 14.4, 14.6, 14.8, 15., 15.2, 15.4, 15.6, 15.8, 16., 16.2, 16.4, 16.6, 16.8, 17., 17.2, 17.4, 17.6, 17.8, 18., 18.2, 18.4, 18.6, 18.8, 19., 19.2, 19.4, 19.6, 19.8, 20.0 }}; + static const array xmatrix2 = {{0.02, 0.10, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3., 3.2, 3.4, 3.6, 3.8, 4., 4.2, 4.4, 4.6, 4.8, 5., 5.2, 5.4, 5.6, 5.8, 6., 6.2, 6.4, 6.6, 6.8, 7., 7.2, 7.4, 7.6, 7.8, 8., 8.2, 8.4, 8.6, 8.8, 9., 9.2, 9.4, 9.6, 9.8, 10., 10.2, 10.4, 10.6, 10.8, 11., 11.2, 11.4, 11.6, 11.8, 12., 12.2, 12.4, 12.6, 12.8, 13., 13.2, 13.4, 13.6, 13.8, 14., 14.2, 14.4, 14.6, 14.8, 15., 15.2, 15.4, 15.6, 15.8, 16., 16.2, 16.4, 16.6, 16.8, 17., 17.2, 17.4, 17.6, 17.8, 18., 18.2, 18.4, 18.6, 18.8, 19., 19.2, 19.4, 19.6, 19.8, 20.0 }}; + static const array datamatrix2 = {{4.32048, 2.74662, 2.090560, 1.457590, 1.113050, 0.885216, 0.720795, 0.597404, 0.501483, 0.425543, 0.364668, 0.315299, 0.274983, 0.241792, 0.214466, 0.191698, 0.172689, 0.156841, 0.143329, 0.131919, 0.122174, 0.113656, 0.106339, 0.099869, 0.094101, 0.089013, 0.084378, 0.080185, 0.076376, 0.072856, 0.069622, 0.066624, 0.063844, 0.061242, 0.058820, 0.056561, 0.054417, 0.052433, 0.05055, 0.048772, 0.047129, 0.045546, 0.044056, 0.042673, 0.041328, 0.040078, 0.038895, 0.037749, 0.036688, 0.035666, 0.034687, 0.033771, 0.032883, 0.032041, 0.031239, 0.030467, 0.029731, 0.029025, 0.028350, 0.027698, 0.027075, 0.026479, 0.025896, 0.025347, 0.024812, 0.024291, 0.023804, 0.023318, 0.022854, 0.022416, 0.021974, 0.021561, 0.021160, 0.020761, 0.020390, 0.020021, 0.019662, 0.019325, 0.01898, 0.018662, 0.018351, 0.018041, 0.017747, 0.017459, 0.017177, 0.016906, 0.016641, 0.016384, 0.016132, 0.015889, 0.015651, 0.015418, 0.015196, 0.014973, 0.014759, 0.014553, 0.014345, 0.014149, 0.013956, 0.013762, 0.013582, 0.013399 }}; + static const array datamatrix3 = {{1.33947, 1.32238, 1.25505, 1.17491, 1.02696, 0.89463, 0.77688, 0.67270, 0.58105, 0.50095, 0.43143, 0.37156, 0.32046, 0.27726, 0.24113, 0.21126, 0.18684, 0.16707, 0.15118, 0.13843, 0.12815, 0.11974, 0.11271, 0.10670, 0.10141, 0.09663, 0.09224, 0.08814, 0.08427, 0.08061, 0.07715, 0.07387, 0.07077, 0.06785, 0.06511, 0.06254, 0.06014, 0.05790, 0.05582, 0.05388, 0.05207, 0.05038, 0.04879, 0.04731, 0.04591, 0.04459, 0.04334, 0.04216, 0.04103, 0.03996, 0.03894, 0.03796, 0.03702, 0.03612, 0.03526, 0.03443, 0.03363, 0.03287, 0.03214, 0.03143, 0.03075, 0.03010, 0.02947, 0.02887, 0.02829, 0.02773, 0.02719, 0.02666, 0.02616, 0.02567, 0.0250, 0.02475, 0.02431, 0.02388, 0.02347, 0.02306, 0.02267, 0.02230, 0.02193, 0.02157, 0.02123, 0.02089, 0.02056, 0.02025, 0.01994, 0.01964, 0.01934, 0.01906, 0.018, 0.01851, 0.01825, 0.01799, 0.01774, 0.01750, 0.01726, 0.01703, 0.01680, 0.01658, 0.01637, 0.01616, 0.01595, 0.01575, 0.01555}}; + static const array datamatrix4 = {{0.88623, 0.885845, 0.879328, 0.86361, 0.81617, 0.75594, 0.68928, 0.62036, 0.55206, 0.48641, 0.42484, 0.36832, 0.31749, 0.27273, 0.23419, 0.20185, 0.17547, 0.15464, 0.13871, 0.12685, 0.11813, 0.11162, 0.10654, 0.10229, 0.09844, 0.09475, 0.09107, 0.08738, 0.08368, 0.08000, 0.07641, 0.07295, 0.06967, 0.06660, 0.06377, 0.06118, 0.05883, 0.05670, 0.05476, 0.05300, 0.05138, 0.04989, 0.04849, 0.04716, 0.04590, 0.04469, 0.04353, 0.04240, 0.04131, 0.04026, 0.03924, 0.03826, 0.037, 0.03642, 0.03556, 0.03473, 0.03394, 0.03319, 0.03247, 0.03178, 0.03112, 0.03049, 0.02988, 0.02930, 0.02873, 0.02819, 0.02767, 0.02716, 0.02667, 0.02619, 0.02573, 0.02529, 0.02486, 0.02444, 0.02403, 0.02364, 0.02326, 0.02289, 0.02253, 0.02218, 0.02184, 0.02152, 0.02120, 0.02089, 0.02058, 0.02029, 0.02000, 0.01972, 0.01944, 0.01918, 0.01892, 0.01866, 0.01841, 0.01816, 0.01792, 0.01769, 0.01746, 0.01724, 0.01702, 0.01681, 0.01660, 0.01639, 0.01619 }}; + static const array datamatrix5 = {{0.744596, 0.744489, 0.742327, 0.73584, 0.71183, 0.67590, 0.63118, 0.58053, 0.52645, 0.47109, 0.41628, 0.36351, 0.31401, 0.26878, 0.22857, 0.19396, 0.16533, 0.14280, 0.12611, 0.11459, 0.10713, 0.10244, 0.09934, 0.09690, 0.09453, 0.09189, 0.08887, 0.08548, 0.08180, 0.07796, 0.07410, 0.07035, 0.06681, 0.06358, 0.06068, 0.05815, 0.05595, 0.05405, 0.05240, 0.05094, 0.04962, 0.04838, 0.04720, 0.04604, 0.04489, 0.04375, 0.04262, 0.04150, 0.04040, 0.03934, 0.03831, 0.03733, 0.03639, 0.03551, 0.03469, 0.03391, 0.03317, 0.03247, 0.03181, 0.03118, 0.03057, 0.02998, 0.02941, 0.02886, 0.02832, 0.02779, 0.02728, 0.02678, 0.02630, 0.02583, 0.02538, 0.02494, 0.02452, 0.02412, 0.02373, 0.02335, 0.02299, 0.02264, 0.02230, 0.02197, 0.02165, 0.02134, 0.02104, 0.02074, 0.02045, 0.02016, 0.01989, 0.01961, 0.01935, 0.01909, 0.01883, 0.01858, 0.01834, 0.01810, 0.01787, 0.01764, 0.01742, 0.01721, 0.01699, 0.01679, 0.01659, 0.01639, 0.01620}}; + static const array datamatrix6 = {{0.67759, 0.677074, 0.675686, 0.67139, 0.65466, 0.62818, 0.59351, 0.55242, 0.50671, 0.45815, 0.40837, 0.35888, 0.31104, 0.26603, 0.22490, 0.18855, 0.15777, 0.13319, 0.11510, 0.10322, 0.09650, 0.09333, 0.09206, 0.09137, 0.09045, 0.08888, 0.08652, 0.08343, 0.07977, 0.07574, 0.07157, 0.06747, 0.06364, 0.06020, 0.05725, 0.05479, 0.05281, 0.05121, 0.04991, 0.04880, 0.04779, 0.04680, 0.04580, 0.04475, 0.04364, 0.04249, 0.04130, 0.04012, 0.03895, 0.03783, 0.03677, 0.03579, 0.03488, 0.03405, 0.03330, 0.03261, 0.03197, 0.03137, 0.03080, 0.03025, 0.02970, 0.02917, 0.02863, 0.02811, 0.02758, 0.02707, 0.02657, 0.02608, 0.02560, 0.02515, 0.02471, 0.02430, 0.02390, 0.02351, 0.02314, 0.02279, 0.02244, 0.02211, 0.02178, 0.02146, 0.02115, 0.02084, 0.02054, 0.02025, 0.01996, 0.01968, 0.01941, 0.01915, 0.01890, 0.01865, 0.01841, 0.01818, 0.01795, 0.01773, 0.01751, 0.01730, 0.01710, 0.01690, 0.01670, 0.01650, 0.01631, 0.01612, 0.01593 }}; + //assign the appropriate tabulated points for the number of extra dimensions + switch ( _ndim ) { + case 2 : _interpol = make_InterpolatorPtr(datamatrix2, xmatrix2, 1); break; + case 3 : _interpol = make_InterpolatorPtr(datamatrix3, xmatrix1, 1); break; + case 4 : _interpol = make_InterpolatorPtr(datamatrix4, xmatrix1, 1); break; + case 5 : _interpol = make_InterpolatorPtr(datamatrix5, xmatrix1, 1); break; + case 6 : _interpol = make_InterpolatorPtr(datamatrix6, xmatrix1, 1); break; + default : assert(false); + } } IBPtr METRP2to2::clone() const { return new_ptr(*this); } IBPtr METRP2to2::fullclone() const { return new_ptr(*this); } void METRP2to2::persistentOutput(PersistentOStream & os) const { os << _interpol << _maxflavour << _process << _ndim << ounit(_planckmass,GeV); } void METRP2to2::persistentInput(PersistentIStream & is, int) { is >> _interpol >> _maxflavour >> _process >> _ndim >> iunit(_planckmass,GeV); } Energy2 METRP2to2::scale() const { Energy2 invbcsq = 1 / sqr(bccalc(sHat())); return ( -tHat() > invbcsq ) ? invbcsq : -tHat(); } void METRP2to2::Init() { static ClassDocumentation documentation ("The METRP2to2 class implements the transplanckian 2->2 processes in hadron-hadron" " collisions"); static Parameter interfaceMaximumFlavour ("MaximumFlavour", "The maximum flavour of the quarks in the process", &METRP2to2::_maxflavour, 2, 1, 5, false, false, Interface::limited); static Parameter interfacePlanckMass ("PlanckMass", "The Planck Mass", &METRP2to2::_planckmass, GeV, 2000.0*GeV, 200.0*GeV, 200000.0*GeV, false, false, Interface::limited); static Parameter interfaceNumberExtraDimensions ("NumberExtraDimensions", "The number of extra dimensions to consider", &METRP2to2::_ndim, 6, 2, 6, false, false, Interface::limited); static Switch interfaceProcess ("Process", "Which subprocesses to include", &METRP2to2::_process, 0, false, false); static SwitchOption interfaceProcessAll (interfaceProcess, "All", "Include all subprocesses", 0); static SwitchOption interfaceProcess1 (interfaceProcess, "gg2gg", "Include only gg->gg subprocesses", 1); static SwitchOption interfaceProcessqgqg (interfaceProcess, "qg2qg", "Include only q g -> q g processes", 4); static SwitchOption interfaceProcessqbargqbarg (interfaceProcess, "qbarg2qbarg", "Include only qbar g -> qbar g processes", 5); static SwitchOption interfaceProcessqqqq (interfaceProcess, "qq2qq", "Include only q q -> q q processes", 6); static SwitchOption interfaceProcessqbarqbarqbarqbar (interfaceProcess, "qbarqbar2qbarqbar", "Include only qbar qbar -> qbar qbar processes", 7); static SwitchOption interfaceProcessqqbarqqbar (interfaceProcess, "qqbar2qqbar", "Include only q qbar -> q qbar processes", 8); } Selector METRP2to2::diagrams(const DiagramVector & diags) const { // select the diagram, this is easy for us as we have already done it Selector sel; for ( DiagramIndex i = 0; i < diags.size(); ++i ) { sel.insert(1.0, i); } return sel; } void METRP2to2::getDiagrams() const { // get the particle data objects PDPtr gluon = getParticleData(ParticleID::g); PDPtr trpon = getParticleData(39); vector quark,antiquark; for(int ix=1;ix<=int(_maxflavour);++ix) { quark.push_back( getParticleData( ix)); antiquark.push_back(getParticleData(-ix)); } // gg-> gg subprocess if(_process==0||_process==1) { add(new_ptr((Tree2toNDiagram(3),gluon,trpon,gluon, 1,gluon, 2,gluon,-2))); } // processes involving one quark line for(unsigned int ix=0;ix<_maxflavour;++ix) { // q g -> q g subprocesses if(_process==0||_process==4) { add(new_ptr((Tree2toNDiagram(3),quark[ix],trpon,gluon, 1,quark[ix],2,gluon,-12))); } // qbar g -> qbar g subprocesses if(_process==0||_process==5) { add(new_ptr((Tree2toNDiagram(3),antiquark[ix],trpon,gluon, 1,antiquark[ix],2,gluon,-15))); } // processes involving two quark lines for(unsigned int iy=0;iy<_maxflavour;++iy) { // q q -> q q subprocesses if(_process==0||_process==6) { // t-channel add(new_ptr((Tree2toNDiagram(3),quark[ix],trpon,quark[iy], 1,quark[ix],2,quark[iy],-16))); //exchange for identical quarks if(ix==iy) add(new_ptr((Tree2toNDiagram(3),quark[ix],trpon,quark[iy], 2,quark[ix],1,quark[iy],-17))); } // qbar qbar -> qbar qbar subprocesses if(_process==0||_process==7) { // t-channel add(new_ptr((Tree2toNDiagram(3),antiquark[ix],trpon,antiquark[iy], 1,antiquark[ix],2,antiquark[iy],-18))); //exchange for identical quarks if(ix==iy) add(new_ptr((Tree2toNDiagram(3),antiquark[ix],trpon,antiquark[iy], 2,antiquark[ix],1,antiquark[iy],-19))); } // q qbar -> q qbar if(_process==0||_process==8) { add(new_ptr((Tree2toNDiagram(3),quark[ix],trpon,antiquark[iy], 1,quark[ix],2,antiquark[iy],-21))); } } } } Selector METRP2to2::colourGeometries(tcDiagPtr diag) const { // colour lines for gg to gg static const ColourLines cgggg("1 4, -1 -4, 3 5, -3 -5"); // colour lines for q g to q g static const ColourLines cqgqg("1 4, 3 5, -3 -5"); // colour lines for qbar g -> qbar g static const ColourLines cqbgqbg("-1 -4, -3 -5, 3 5"); // colour lines for q q -> q q static const ColourLines cqqqq("1 4,3 5"); // colour lines for qbar qbar -> qbar qbar static const ColourLines cqbqbqbqb("-1 -4,-3 -5"); // colour lines for q qbar -> q qbar static const ColourLines cqqbqqb("1 4,-3 -5"); // select the colour flow (as already picked just insert answer) Selector sel; switch(abs(diag->id())) { //gg -> gg case 2: sel.insert(1.0, &cgggg); break; // q g -> q g subprocess case 12: sel.insert(1.0, &cqgqg); break; // qbar g -> qbar g subprocess case 15: sel.insert(1.0, &cqbgqbg); break; // q q -> q q subprocess case 16: case 17: sel.insert(1.0, &cqqqq); break; // qbar qbar -> qbar qbar subprocess case 18: case 19: sel.insert(1.0, &cqbqbqbqb); break; // q qbar -> q qbar subprocess case 21: sel.insert(1.0, &cqqbqqb); break; } return sel; } double METRP2to2::me2() const { double me(0.), me_exch(0.); double fac1(1.), fac2(0.); if ( mePartonData()[0]->id() == mePartonData()[1]->id() ) { if ( mePartonData()[0]->id()>0 ) { me_exch = - A_ny(sHat(),uHat()); fac1 = 2./3.; fac2 = 1./6.; } else if ( mePartonData()[0]->id() == ParticleID::g ) { me_exch = A_ny(sHat(),uHat()); fac1 = 7./8.; fac2 = 1./16.; } } me = A_ny(sHat(),tHat()); return fac1 * sqr(me) + fac2 * sqr(me+me_exch); } // Calculate the constant b_c which depends on s_hat and the number of // extra dimensions InvEnergy METRP2to2::bccalc(Energy2 s) const { static const double fourpi = 4.0*Constants::pi; return 1/_planckmass * sqrt(fourpi) * pow( (0.5 * s / (sqr(_planckmass) * fourpi)) * Math::gamma(_ndim/2.0), 1.0/_ndim); } //Calculation of the matrix element squared using the function F_n(y) double METRP2to2::A_ny(Energy2 s, Energy2 t) const { InvEnergy bc = bccalc(s); double fny = 0; double y = bc * sqrt(-t); if ( y >= 20.0 ) fny = fnyasympt(y); else fny = fpoint(y); return 4. * Constants::pi * fny * s * sqr(bc); } //The asymptotic form of the F_n functions; used for x > 20 double METRP2to2::fnyasympt(double y) const { return pow( _ndim, 1.0/(_ndim+1.0) ) * pow( y, -(_ndim+2.0)/(_ndim+1.0) ) / sqrt(_ndim+1.0); } //fpoint uses the interpolator to calculate the value of F_n for intermediate values of the argument double METRP2to2::fpoint(double x) const { assert( x < 20.0 ); if ( _ndim == 2 && x < 0.02 ) { return sqrt( sqr(-log(x/1.4)) + sqr(Constants::pi)/16 ); } else { return (*_interpol)(x); } } diff --git a/Models/UED/UEDF1F0G1Vertex.cc b/Models/UED/UEDF1F0G1Vertex.cc --- a/Models/UED/UEDF1F0G1Vertex.cc +++ b/Models/UED/UEDF1F0G1Vertex.cc @@ -1,100 +1,101 @@ // -*- C++ -*- // // UEDF1F0G1Vertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 UEDF1F0G1Vertex class. // #include "UEDF1F0G1Vertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG::Helicity; using namespace Herwig; UEDF1F0G1Vertex::UEDF1F0G1Vertex() : theq2Last(ZERO), theCoupLast(0.) { orderInGs(1); orderInGem(0); + colourStructure(ColourStructure::SU3TFUND); } // The following static variable is needed for the type // description system in ThePEG. DescribeNoPIOClass describeHerwigUEDF1F0G1Vertex("Herwig::UEDF1F0G1Vertex", "HwUED.so"); void UEDF1F0G1Vertex::Init() { static ClassDocumentation documentation ("This class implements the F^1-F^0-G^1 vertex."); } void UEDF1F0G1Vertex::setCoupling(Energy2 q2, tcPDPtr part1, tcPDPtr part2, tcPDPtr part3) { long ifermN; if(part1->id() == 5100021) { if(abs(part2->id()) > 5100000) ifermN = part2->id(); else ifermN = part3->id(); } else if(part2->id() == 5100021) { if(abs(part1->id()) > 5100000) ifermN = part1->id(); else ifermN = part3->id(); } else if(part3->id() == 5100021) { if(abs(part2->id()) > 5100000) ifermN = part2->id(); else ifermN = part1->id(); } else throw HelicityLogicalError() << "UEDF1F0G1Vertex::setCoupling - " << "There is no KK gluon in this vertex!" << Exception::warning; if((abs(ifermN) >= 5100001 && abs(ifermN) <= 5100006) || (abs(ifermN) >= 6100001 && abs(ifermN) <= 6100006)) { if(q2 != theq2Last || theCoupLast == 0.) { theq2Last = q2; theCoupLast = -strongCoupling(q2); } norm(theCoupLast); int state = abs(ifermN)/1000000; if(state == 5) { left(1.); right(0.); } else { left(0.); right(1.); } } else throw HelicityLogicalError() << "UEDF1F0G1Vertex::setCoupling - " << "There is an unknown particle in this vertex! " << ifermN << Exception::warning; } void UEDF1F0G1Vertex::doinit() { long boson = 5100021; //QQ for(long i = 1; i < 7; ++i) { addToList(-i, i + 5100000, boson); addToList(-(i + 5100000), i, boson); addToList(-i, i + 6100000, boson); addToList(-(i + 6100000), i, boson); } FFVVertex::doinit(); } diff --git a/Models/UED/UEDF1F0H1Vertex.cc b/Models/UED/UEDF1F0H1Vertex.cc --- a/Models/UED/UEDF1F0H1Vertex.cc +++ b/Models/UED/UEDF1F0H1Vertex.cc @@ -1,205 +1,206 @@ // -*- C++ -*- // // UEDF1F0H1Vertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 UEDF1F0H1Vertex class. // #include "UEDF1F0H1Vertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG::Helicity; using namespace Herwig; UEDF1F0H1Vertex::UEDF1F0H1Vertex() : theRadius(ZERO), theMw(ZERO), theSinThetaW(0.), theq2Last(ZERO), theCoupLast(0.), theLeftLast(0.), theRightLast(0.), theAntiLast(0), theFermLast(0), theHLast(0) { orderInGs(0); orderInGem(1); + colourStructure(ColourStructure::DELTA); } void UEDF1F0H1Vertex::doinit() { long heavy[3] = {5, 6, 15}; //h0 for( unsigned int i = 0; i < 3; ++i ) { addToList(-5100000 - i, 5100000 + i, 25); addToList(-6100000 - i, 6100000 + i, 25); addToList(-5100000 - i, 6100000 + i, 25); addToList(-6100000 - i, 5100000 + i, 25); } // Neutral KK-Higgs long higgs[2] = {5100025, 5100036}; for( unsigned int h = 0; h < 2; ++h ) { for( unsigned int i = 0; i < 3; ++i ) { addToList(-heavy[i], 5100000 + heavy[i], higgs[h]); addToList(-5100000 - heavy[i], heavy[i], higgs[h]); addToList(-heavy[i], 6100000 + heavy[i], higgs[h]); addToList(-6100000 - heavy[i], heavy[i], higgs[h]); } } //KK-charged higgs //outgoing H+ addToList(-5100006, 5, 5100037); addToList(-6100006, 5, 5100037); addToList(-6, 5100005, 5100037); addToList(-6, 6100005, 5100037); addToList(-5100016, 15, 5100037); addToList(-6100016, 15, 5100037); addToList(-16, 5100015, 5100037); addToList(-16, 6100015, 5100037); //outgoing H- addToList(-5100005, 6,-5100037); addToList(-6100005, 6,-5100037); addToList(-5, 5100006,-5100037); addToList(-5, 6100006,-5100037); addToList(-5100015, 16,-5100037); addToList(-6100015, 16,-5100037); addToList(-15, 5100016,-5100037); addToList(-15, 6100016,-5100037); FFSVertex::doinit(); tUEDBasePtr UEDBase = dynamic_ptr_cast(generator()->standardModel()); if(!UEDBase) throw InitException() << "UEDF1F0H1Vertex::doinit() - The pointer to " << "the UEDBase object is null!" << Exception::runerror; theRadius = UEDBase->compactRadius(); theSinThetaW = sqrt(sin2ThetaW()); theCosThetaW = sqrt(1. - sin2ThetaW()); theMw = getParticleData(24)->mass(); theMz = getParticleData(23)->mass(); } void UEDF1F0H1Vertex::persistentOutput(PersistentOStream & os) const { os << ounit(theRadius,1/GeV) << ounit(theMw,GeV) << theSinThetaW << ounit(theMz, GeV) << theCosThetaW; } void UEDF1F0H1Vertex::persistentInput(PersistentIStream & is, int) { is >> iunit(theRadius,1/GeV) >> iunit(theMw,GeV) >> theSinThetaW >> iunit(theMz, GeV) >> theCosThetaW; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigUEDF1F0H1Vertex("Herwig::UEDF1F0H1Vertex", "HwUED.so"); void UEDF1F0H1Vertex::Init() { static ClassDocumentation documentation ("The coupling involving a KK-Higgs and a pair of fermions."); } void UEDF1F0H1Vertex::setCoupling(Energy2 q2, tcPDPtr part1, tcPDPtr part2, tcPDPtr part3) { long anti(abs(part1->id())), ferm(abs(part2->id())), higgs(part3->id()); if( ferm > 17 ) swap( ferm, anti); if( anti != theAntiLast || ferm != theFermLast || higgs != theHLast ) { theAntiLast = anti; theFermLast = ferm; theHLast = higgs; tcPDPtr pd; if( higgs != 25 ) { pd = getParticleData(ferm); } else { long smid = ( ferm/1000000 == 5 ) ? ferm - 5100000 : ferm - 6100000; pd = getParticleData(smid); } Energy mf = pd->mass(); double alpha = mf*theRadius/2.; double salpha = sin(alpha); double calpha = cos(alpha); double fact(0.); if( abs(higgs) == 5100037 ) { fact = theRadius/2./sqrt(1. + sqr(theMw*theRadius)) * UnitRemoval::E; theRightLast = theRadius*theMw; if(anti/1000000 == 5) { Energy mfk = getParticleData(anti - 5100000)->mass(); theLeftLast = (theMw*calpha - (mfk*salpha/theRadius/theMw)) * UnitRemoval::InvE; theRightLast *= calpha*mfk* UnitRemoval::InvE; } else { Energy mfk = getParticleData(anti - 6100000)->mass(); theLeftLast = (theMw*salpha +(mfk*calpha/theRadius/theMw)) * UnitRemoval::InvE; theRightLast *= -salpha*mfk*UnitRemoval::InvE; } theLeftLast *= fact; theRightLast *= fact; if( higgs < 0 ) swap( theLeftLast, theRightLast ); } else if( higgs == 5100025 ) { fact = mf/theMw/2.; if( anti/1000000 == 5 ) theLeftLast = salpha + calpha; else theLeftLast = salpha - calpha; theRightLast = theLeftLast; theLeftLast *= fact; theRightLast *= fact; } else if( higgs == 5100036 ) { fact = theRadius/theCosThetaW/sqrt(1.+sqr(theMz*theRadius))*UnitRemoval::E; double i3f = ( ferm % 2 == 0 ) ? 0.5 : -0.5; double qf = pd->charge()/eplus; if( anti/1000000 == 5 ) { theLeftLast = (theMz*calpha*(i3f - qf*sqr(theSinThetaW)) - mf*salpha/theRadius/theMw) * UnitRemoval::InvE; theRightLast = (-theMz*salpha*qf*sqr(theSinThetaW) + mf*calpha/theRadius/theMw) * UnitRemoval::InvE; } else { theLeftLast = (theMz*salpha*(i3f - qf*sqr(theSinThetaW)) - mf*calpha/theRadius/theMw) * UnitRemoval::InvE; theRightLast = (-theMz*calpha*qf*sqr(theSinThetaW) + mf*salpha/theRadius/theMw)*UnitRemoval::InvE; } theLeftLast *= fact; theRightLast *= fact; } else { theLeftLast = mf*calpha*salpha/2./theMw; if( ferm/1000000 == 5 ) theLeftLast *= -1.; theRightLast = theLeftLast; } } if(q2 != theq2Last || theCoupLast == 0.) { theq2Last = q2; theCoupLast = weakCoupling(q2); } norm(theCoupLast); left(theLeftLast); right(theRightLast); } diff --git a/Models/UED/UEDF1F0W1Vertex.cc b/Models/UED/UEDF1F0W1Vertex.cc --- a/Models/UED/UEDF1F0W1Vertex.cc +++ b/Models/UED/UEDF1F0W1Vertex.cc @@ -1,186 +1,187 @@ // -*- C++ -*- // // UEDF1F0W1Vertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 UEDF1F0W1Vertex class. // #include "UEDF1F0W1Vertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/Models/StandardModel/StandardCKM.h" using namespace ThePEG::Helicity; using namespace Herwig; UEDF1F0W1Vertex::UEDF1F0W1Vertex() : theSinW(0.), theCosW(0.), theSinOne(0.), theCosOne(0.), theSinWmO(0.), theCosWmO(0.), theCKM(0, vector(0, 0.)), theq2last(), theCouplast(0.), theLlast(0.), theRlast(0.), theGBlast(0), theKKlast(0), theSMlast(0) { orderInGs(0); orderInGem(1); + colourStructure(ColourStructure::DELTA); } void UEDF1F0W1Vertex::doinit() { //outgoing W+ for(long i = 2; i < 7; i += 2) { for(long j = 1; j < 6; j += 2) { addToList( -i, 5100000 + j, 5100024 ); addToList( -(5100000 + i), j, 5100024 ); } } for(long i = 11; i < 17; i += 2) { addToList( -i-1, 5100000 + i, 5100024 ); addToList( -(5100001 + i), i, 5100024 ); } //outgoing W- for(long i = 1; i < 6; i += 2) { for(long j = 2 ; j < 7; j += 2) { addToList( -i, 5100000 + j, -5100024 ); addToList( -(5100000 + i), j, -5100024 ); } } for(long i = 11; i < 17; i += 2) { addToList( -i, 5100001 + i, -5100024 ); addToList(-(5100000 + i), i + 1, -5100024); } long boson[2] = {5100022,5100023}; for(long b = 0; b < 2; ++b) { //QQ for(int i = 1; i < 7; ++i) { addToList( -i, i + 5100000, boson[b]); addToList(-(i + 5100000), i, boson[b]); addToList(-i, i + 6100000, boson[b]); addToList(-(i + 6100000), i, boson[b]); } //LL for(int i = 11; i < 17; ++i) { addToList( -i, i + 5100000, boson[b]); addToList(-(i + 5100000), i, boson[b]); if( i % 2 != 0 ) { addToList(-i, i + 6100000, boson[b]); addToList(-(i + 6100000), i, boson[b]); } } } FFVVertex::doinit(); tUEDBasePtr UEDBase = dynamic_ptr_cast(generator()->standardModel()); if(!UEDBase) throw InitException() << "UEDF1F0W1Vertex::doinit() - The pointer to " << "the UEDBase object is null!" << Exception::runerror; theSinW = sqrt(sin2ThetaW()); theCosW = sqrt( 1. - sqr(theSinW)); theSinOne = UEDBase->sinThetaOne(); theCosOne = sqrt(1. - sqr(theSinOne)); theSinWmO = theSinW*theCosOne - theSinOne*theCosW; theCosWmO = theCosW*theCosOne + theSinW*theSinOne; theCKM = dynamic_ptr_cast::transient_pointer> (UEDBase->CKM())->getUnsquaredMatrix(UEDBase->families()); } void UEDF1F0W1Vertex::persistentOutput(PersistentOStream & os) const { os << theSinW << theCosW << theSinOne << theCosOne << theSinWmO << theCosWmO << theCKM; } void UEDF1F0W1Vertex::persistentInput(PersistentIStream & is, int) { is >> theSinW >> theCosW >> theSinOne >> theCosOne >> theSinWmO >> theCosWmO >> theCKM; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigUEDF1F0W1Vertex("Herwig::UEDF1F0W1Vertex", "HwUED.so"); void UEDF1F0W1Vertex::Init() { static ClassDocumentation documentation ("This is the coupling of a KK1 W boson to a KK1 fermion and " "a SM fermion."); } void UEDF1F0W1Vertex::setCoupling(Energy2 q2, tcPDPtr part1, tcPDPtr part2, tcPDPtr part3) { long id1(abs(part1->id())), id2(abs(part2->id())), gboson(abs(part3->id())), kkparticle(0), smID(0); assert( gboson == 5100022 || gboson == 5100023 || gboson == 5100024 ); if( id1 > 5000000 ) { kkparticle = id1; smID = id2; } else { kkparticle = id2; smID = id1; } if( (kkparticle >= 5100001 && kkparticle <= 5100006) || (kkparticle >= 6100001 && kkparticle <= 6100006) || (kkparticle >= 5100011 && kkparticle <= 5100016) || (kkparticle >= 6100011 && kkparticle <= 6100016) ) { if(q2 != theq2last || theCouplast == 0.) { theq2last = q2; theCouplast = electroMagneticCoupling(q2); } if( gboson != theGBlast || kkparticle != theKKlast || smID != theSMlast ) { theGBlast = gboson; theKKlast = kkparticle; theSMlast = smID; if( gboson == 5100024 ) { Complex ckm(1.); if( smID >= 1 && smID <= 6 ) { long smIDb(kkparticle - 5100000); if( smID % 2 != 0 ) swap(smID, smIDb); ckm = theCKM[smID/2 - 1][(smIDb - 1)/2]; } theLlast = -ckm/sqrt(2)/theSinW; theRlast = 0.; } else if( gboson == 5100022 || gboson == 5100023 ) { double Qf = getParticleData(smID)->charge()/eplus; if( kkparticle/1000000 == 5 ) { theRlast = 0.; double I3f = (abs(smID) % 2 == 0) ? 0.5 : -0.5; if( gboson == 5100023 ) theLlast = (Qf*theSinOne - I3f*theCosWmO/theSinW)/theCosW; else theLlast = -(Qf*theCosOne - I3f*theSinWmO/theSinW)/theCosW; } else { theLlast = 0.; if( gboson == 5100023 ) theRlast = Qf*theSinOne/theCosW; else theRlast = -Qf*theCosOne/theCosW; } } } norm(theCouplast); left(theLlast); right(theRlast); } else throw HelicityLogicalError() << "UEDF1F0W1Vertex::setCoupling - " << "There is an unknown particle in this vertex! " << kkparticle << Exception::warning; } diff --git a/Models/UED/UEDF1F1G0Vertex.cc b/Models/UED/UEDF1F1G0Vertex.cc --- a/Models/UED/UEDF1F1G0Vertex.cc +++ b/Models/UED/UEDF1F1G0Vertex.cc @@ -1,79 +1,80 @@ // -*- C++ -*- // // UEDF1F1G0Vertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 UEDF1F1G0Vertex class. // #include "UEDF1F1G0Vertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" using namespace ThePEG::Helicity; using namespace Herwig; UEDF1F1G0Vertex::UEDF1F1G0Vertex() : theq2Last(ZERO), theCoupLast(0.) { orderInGs(1); orderInGem(0); + colourStructure(ColourStructure::SU3TFUND); } // The following static variable is needed for the type // description system in ThePEG. DescribeNoPIOClass describeHerwigUEDF1F1G0Vertex("Herwig::UEDF1F1G0Vertex", "HwUED.so"); void UEDF1F1G0Vertex::Init() { static ClassDocumentation documentation ("This class implements the F^1 F^1 G^0 vertex."); } void UEDF1F1G0Vertex::setCoupling(Energy2 q2, tcPDPtr part1, tcPDPtr part2, tcPDPtr part3) { long iferm; if(part1->id() == ParticleID::g) iferm = abs(part2->id()); else if(part2->id() == ParticleID::g) iferm = abs(part1->id()); else if(part3->id() == ParticleID::g) iferm = abs(part1->id()); else throw HelicityLogicalError() << "UEDF1F1G0Vertex::setCoupling - " << "There is no gluon in this vertex!" << Exception::warning; if((iferm >= 5100001 && iferm <= 5100006) || (iferm >= 6100001 && iferm <= 6100006)) { if(q2 != theq2Last || theCoupLast ==0. ) { theCoupLast = -strongCoupling(q2); theq2Last=q2; } norm(theCoupLast); left(1.); right(1.); } else throw HelicityLogicalError() << "UEDF1F1G0Vertex::setCoupling - " << "There is an unknown particle in this vertex! " << iferm << Exception::warning; } void UEDF1F1G0Vertex::doinit() { long boson = 21; //QQ for(long i = 5100001; i < 6100007; ++i) { if(i == 5100007) i += 999994; addToList(-i, i, boson); } FFVVertex::doinit(); } diff --git a/Models/UED/UEDF1F1P0Vertex.cc b/Models/UED/UEDF1F1P0Vertex.cc --- a/Models/UED/UEDF1F1P0Vertex.cc +++ b/Models/UED/UEDF1F1P0Vertex.cc @@ -1,108 +1,109 @@ // -*- C++ -*- // // UEDF1F1P0Vertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 UEDF1F1P0Vertex class. // #include "UEDF1F1P0Vertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" using namespace ThePEG::Helicity; using namespace Herwig; UEDF1F1P0Vertex::UEDF1F1P0Vertex() : coupLast_(0.0), q2Last_(ZERO), fermLast_(0), LRLast_(0.0), charges_(3) { orderInGs(0); orderInGem(1); + colourStructure(ColourStructure::DELTA); } void UEDF1F1P0Vertex::persistentOutput(PersistentOStream & os) const { os << charges_; } void UEDF1F1P0Vertex::persistentInput(PersistentIStream & is, int) { is >> charges_; } void UEDF1F1P0Vertex::doinit() { long photon = 22; //quarks for(long i = 1; i < 7; ++i) { //left addToList(-5100000 - i, 5100000 + i, photon); //right addToList(-6100000 - i, 6100000 + i, photon); } //leptons for(long i = 11; i < 17; i += 2) { //left addToList(-5100000 - i, 5100000 + i, photon); //right addToList(-6100000 - i, 6100000 + i, photon); } FFVVertex::doinit(); tUEDBasePtr UEDBase = dynamic_ptr_cast(generator()->standardModel()); if(!UEDBase) throw InitException() << "UEDF1F1P0Vertex::doinit() - The pointer to " << "the UEDBase object is null!" << Exception::runerror; charges_[0] = UEDBase->ee(); charges_[1] = UEDBase->ed(); charges_[2] = UEDBase->eu(); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigUEDF1F1P0Vertex("Herwig::UEDF1F1P0Vertex", "HwUED.so"); void UEDF1F1P0Vertex::Init() { static ClassDocumentation documentation ("This class couples a pair of level-1 KK fermions to an SM " "photon."); } void UEDF1F1P0Vertex::setCoupling(Energy2 q2, tcPDPtr part1, tcPDPtr , #ifndef NDEBUG tcPDPtr part3) { #else tcPDPtr ) { #endif long iferm = abs(part1->id()); assert(part3->id()==ParticleID::gamma); assert((iferm >= 5100001 && iferm <= 5100006) || (iferm >= 5100011 && iferm <= 5100016) || (iferm >= 6100001 && iferm <= 6100006) || (iferm >= 6100011 && iferm <= 6100016)); if(q2 != q2Last_ || coupLast_ == 0. ) { q2Last_ = q2; coupLast_ = -electroMagneticCoupling(q2); } norm(coupLast_); if(iferm != fermLast_) { fermLast_ = iferm; int smtype = (iferm > 6000000) ? iferm - 6100000 : iferm - 5100000; if(smtype >= 11) LRLast_ = charges_[0]; else LRLast_ = (smtype % 2 == 0) ? charges_[2] : charges_[1]; } left(LRLast_); right(LRLast_); } diff --git a/Models/UED/UEDF1F1W0Vertex.cc b/Models/UED/UEDF1F1W0Vertex.cc --- a/Models/UED/UEDF1F1W0Vertex.cc +++ b/Models/UED/UEDF1F1W0Vertex.cc @@ -1,183 +1,184 @@ // -*- C++ -*- // // UEDF1F1W0Vertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 UEDF1F1W0Vertex class. // #include "UEDF1F1W0Vertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" using namespace ThePEG::Helicity; using namespace Herwig; UEDF1F1W0Vertex::UEDF1F1W0Vertex(): includeMixing_(true), theRadius(ZERO), theQ2Last(ZERO), theCoupLast(0.), thefermALast(0), thefermBLast(0) { orderInGs(0); orderInGem(1); + colourStructure(ColourStructure::DELTA); } void UEDF1F1W0Vertex::doinit() { //outgoing W+ for( long i = 2; i < 17; i += 2 ) { if( i == 7 ) i += 5; addToList(-5100000 - i, 5100000 + i - 1, 24); if( i < 7 ) { addToList(-6100000 - i, 6100000 + i - 1, 24); } } if(includeMixing_) { addToList(-6100006, 5100005, 24); addToList(-5100006, 6100005, 24); } //outgoing W- for( long i = 1; i < 16; i += 2 ) { if( i == 6 ) i += 5; addToList(-5100000 - i, 5100001 + i, -24); if( i < 6 ) { addToList(-6100000 - i, 6100001 + i, -24); } } if(includeMixing_) { addToList(-6100005, 5100006, -24); addToList(-5100005, 6100006, -24); } FFVVertex::doinit(); tUEDBasePtr model = dynamic_ptr_cast(generator()->standardModel()); if(!model) throw InitException() << "UEDF1F1W0Vertex::doinit() - The pointer to " << "the UEDBase object is null!" << Exception::runerror; theRadius = model->compactRadius(); } void UEDF1F1W0Vertex::persistentOutput(PersistentOStream & os) const { os << ounit(theRadius,1/GeV) << includeMixing_; } void UEDF1F1W0Vertex::persistentInput(PersistentIStream & is, int) { is >> iunit(theRadius,1/GeV) >> includeMixing_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigUEDF1F1W0Vertex("Herwig::UEDF1F1W0Vertex", "HwUED.so"); void UEDF1F1W0Vertex::Init() { static ClassDocumentation documentation ("This class implements the coupling of a pair of level-1 KK fermions" "to an SM W boson"); static Switch interfaceIncludeMixing ("IncludeMixing", "Include the mixing", &UEDF1F1W0Vertex::includeMixing_, true, false, false); static SwitchOption interfaceIncludeMixingYes (interfaceIncludeMixing, "Yes", "Include mixing", true); static SwitchOption interfaceIncludeMixingNo (interfaceIncludeMixing, "No", "Don't include mixing", false); } void UEDF1F1W0Vertex::setCoupling(Energy2 q2, tcPDPtr part1, tcPDPtr part2, #ifndef NDEBUG tcPDPtr part3) { #else tcPDPtr) { #endif long ianti(abs(part1->id())), iferm(abs(part2->id())); assert( abs(part3->id()) == 24 ); bool ferma = (iferm >= 5100001 && iferm <= 5100006) || (iferm >= 6100001 && iferm <= 6100006) || (iferm >= 5100011 && iferm <= 5100016) || (iferm >= 6100011 && iferm <= 6100016); bool fermb = (ianti >= 5100001 && ianti <= 5100006) || (ianti >= 6100001 && ianti <= 6100006) || (ianti >= 5100011 && ianti <= 5100016) || (ianti >= 6100011 && ianti <= 6100016); if( !ferma || !fermb ) throw HelicityLogicalError() << "UEDF1F1W0Vertex::setCoupling - " << "There is an unknown particle(s) in the " << "UED F^(1) F^(1) W^(0) vertex. ID: " << ianti << " " << iferm << Exception::runerror; if(q2 != theQ2Last || theCoupLast == 0. ) { theQ2Last = q2; theCoupLast = sqrt(0.5)*weakCoupling(q2); } if(iferm != thefermALast || ianti != thefermBLast) { thefermALast = iferm; thefermBLast = ianti; int stateA(ianti/1000000), stateB(iferm/1000000); long sma = (stateA == 6) ? ianti - 6100000 : ianti - 5100000; long smb = (stateB == 6) ? iferm - 6100000 : iferm - 5100000; double afu(0.), afd(0.); if(includeMixing_) { if( sma % 2 == 0 ) { afu = atan(getParticleData(sma)->mass()*theRadius)/2.; afd = atan(getParticleData(smb)->mass()*theRadius)/2.; } else { afd = atan(getParticleData(sma)->mass()*theRadius)/2.; afu = atan(getParticleData(smb)->mass()*theRadius)/2.; } } else { afd = afu = 0.; } if( stateA == stateB ) { if( stateA == 5 ) { left(cos(afu)*cos(afd)); right(cos(afu)*cos(afd)); } else { left(sin(afu)*sin(afd)); right(sin(afu)*sin(afd)); } } else { if( sma % 2 == 0 ) { if( stateA == 5 ) { left(cos(afu)*sin(afd)); right(-cos(afu)*sin(afd)); } else { left(sin(afu)*cos(afd)); right(-sin(afu)*cos(afd)); } } else { if( stateA == 5 ) { left(sin(afu)*cos(afd)); right(-sin(afu)*cos(afd)); } else { left(cos(afu)*sin(afd)); right(-cos(afu)*sin(afd)); } } } } norm(theCoupLast); } diff --git a/Models/UED/UEDF1F1Z0Vertex.cc b/Models/UED/UEDF1F1Z0Vertex.cc --- a/Models/UED/UEDF1F1Z0Vertex.cc +++ b/Models/UED/UEDF1F1Z0Vertex.cc @@ -1,161 +1,162 @@ // -*- C++ -*- // // UEDF1F1Z0Vertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 UEDF1F1Z0Vertex class. // #include "UEDF1F1Z0Vertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" using namespace ThePEG::Helicity; using namespace Herwig; UEDF1F1Z0Vertex::UEDF1F1Z0Vertex() : theSin2ThW(0.0), theCosThW(0.0), theRadius(), theID1Last(0), theID2Last(0) , theq2Last(ZERO), theCoupLast(0.), theLeftLast(0.), theRightLast(0.) { orderInGs(0); orderInGem(1); + colourStructure(ColourStructure::DELTA); } void UEDF1F1Z0Vertex::doinit() { long boson = 23; //QQ, uu, dd for(long i = 5100001; i < 6100007; ++i) { if(i == 5100007) i += 999994; addToList(-i, i, boson); } //top/bottom quark l/r mixing addToList(-5100006, 6100006, boson); addToList(-6100006, 5100006, boson); addToList(-5100005, 6100005, boson); addToList(-6100005, 5100005, boson); //leptons for(long i = 5100011; i < 5100017; ++i) { addToList(-i, i, boson); } for(long i = 6100011; i < 6100017; i +=2) { addToList(-i, i, boson); } FFVVertex::doinit(); UEDBasePtr model = dynamic_ptr_cast(generator()->standardModel()); if(!model) throw InitException() << "UEDF1F1Z0Vertex::doinit() - The pointer to " << "the UEDBase object is null!" << Exception::runerror; theSin2ThW = sin2ThetaW(); theCosThW = sqrt(1. - theSin2ThW); theRadius = model->compactRadius(); } void UEDF1F1Z0Vertex::persistentOutput(PersistentOStream & os) const { os << theSin2ThW << theCosThW << ounit(theRadius,1/GeV); } void UEDF1F1Z0Vertex::persistentInput(PersistentIStream & is, int) { is >> theSin2ThW >> theCosThW >> iunit(theRadius,1/GeV); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigUEDF1F1Z0Vertex("Herwig::UEDF1F1Z0Vertex", "HwUED.so"); void UEDF1F1Z0Vertex::Init() { static ClassDocumentation documentation ("This is the implementation of the level-1 fermion pair Z_0 boson " "coupling."); } void UEDF1F1Z0Vertex::setCoupling(Energy2 q2, tcPDPtr part1, tcPDPtr part2, tcPDPtr part3) { if( part3->id() != 23 ) { norm(0.0); left(0.0); right(0.0); throw HelicityLogicalError() << "UEDF1F1Z0Vertex::setCoupling - The vector boson in this vertex " << "is not a Z^0 boson. ID: " << part3->id() << "\n" << Exception::warning; return; } long ianti(abs(part1->id())), iferm(abs(part2->id())); bool ferma = (iferm >= 5100001 && iferm <= 5100006) || (iferm >= 6100001 && iferm <= 6100006) || (iferm >= 5100011 && iferm <= 5100016) || (iferm >= 6100011 && iferm <= 6100016); bool fermb = (ianti >= 5100001 && ianti <= 5100006) || (ianti >= 6100001 && ianti <= 6100006) || (ianti >= 5100011 && ianti <= 5100016) || (ianti >= 6100011 && ianti <= 6100016); if( ferma && fermb ) { if(q2 != theq2Last || theCoupLast == 0. ) { theq2Last = q2; theCoupLast = 0.5*weakCoupling(q2)/theCosThW; } if( ianti != theID1Last || iferm != theID2Last) { theID1Last = ianti; theID2Last = iferm; int stateA = ianti/1000000; int stateB = iferm/1000000; long smID = (stateA == 6) ? ianti - 6100000 : ianti - 5100000; // L/R mixing double alpha = atan(getParticleData(smID)->mass()*theRadius)/2.; double sin2al = sqr(sin(alpha)); double cos2al = 1. - sin2al; if(stateA == 5 && stateB == 5) { if(smID >= 11 && smID <= 16) theLeftLast = -cos2al + 2.*theSin2ThW; else if(smID <= 6 && smID % 2 == 0) theLeftLast = cos2al - 4.*theSin2ThW/3.; else theLeftLast = -cos2al + 2.*theSin2ThW/3.; theRightLast = theLeftLast; } else if(stateA == 6 && stateB == 6) { if(smID >= 11 && smID <= 16) theLeftLast = -sin2al + 2.*theSin2ThW; else if(smID <=6 && smID % 2 == 0) theLeftLast = sin2al - 4.*theSin2ThW/3.; else theLeftLast = -sin2al + 2.*theSin2ThW/3.; theRightLast = theLeftLast; } else { theLeftLast = sqrt(sin2al*cos2al); if(smID % 2 == 0) theLeftLast *= -1.; theRightLast = -theLeftLast; } } norm(theCoupLast); left(theLeftLast); right(theRightLast); } else { throw HelicityLogicalError() << "UEDF1F1Z0Vertex::setCoupling - " << "There is an unknown particle(s) in the " << "UED F^(1) F^(1) Z^(0) vertex. ID: " << ianti << " " << iferm << Exception::warning; norm(0.0); left(0.0); right(0.0); } } diff --git a/Models/UED/UEDG0G0G1G1Vertex.cc b/Models/UED/UEDG0G0G1G1Vertex.cc --- a/Models/UED/UEDG0G0G1G1Vertex.cc +++ b/Models/UED/UEDG0G0G1G1Vertex.cc @@ -1,65 +1,64 @@ // -*- C++ -*- // // UEDG0G0G1G1Vertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 UEDG0G0G1G1Vertex class. // #include "UEDG0G0G1G1Vertex.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/PDT/EnumParticles.h" #include "UEDBase.h" using namespace Herwig; UEDG0G0G1G1Vertex::UEDG0G0G1G1Vertex() : theq2Last(ZERO), theCoupLast(0.) { orderInGs(2); orderInGem(0); + colourStructure(ColourStructure::SU3FF); } void UEDG0G0G1G1Vertex::doinit() { long kk1g = 5100021, smgl = 21; addToList(smgl, smgl, kk1g, kk1g); VVVVVertex::doinit(); } // The following static variable is needed for the type // description system in ThePEG. DescribeNoPIOClass describeUEDG0G0G1G1Vertex("Herwig::UEDG0G0G1G1Vertex", "HwUED.so"); void UEDG0G0G1G1Vertex::Init() { static ClassDocumentation documentation ("This class implements the coupling of a pair of SM gluons to" "a pair of UED level-1 KK gluons."); } void UEDG0G0G1G1Vertex::setCoupling(Energy2 q2, tcPDPtr part1, tcPDPtr part2, tcPDPtr part3, tcPDPtr part4) { int ismg(0), ikkg(0); - vector particles(4); - particles[0] = part1; particles[1] = part2; - particles[2] = part3; particles[3] = part4; - for(vector::size_type i = 0; i < 4; ++i) { - if(particles[i]->id() == ParticleID::g) ++ismg; - if(particles[i]->id() == 5100021) ++ikkg; + const array particles{{ part1, part2, part3, part4 }}; + for(auto p : particles) { + if(p->id() == ParticleID::g) ++ismg; + if(p->id() == 5100021) ++ikkg; } assert(ismg == 2 && ikkg == 2); if(q2 != theq2Last || theCoupLast == 0. ) { theq2Last = q2; theCoupLast = sqr(strongCoupling(q2)); } norm(theCoupLast); setType(1); setOrder(0,1,2,3); } diff --git a/Models/UED/UEDG1G1G0Vertex.cc b/Models/UED/UEDG1G1G0Vertex.cc --- a/Models/UED/UEDG1G1G0Vertex.cc +++ b/Models/UED/UEDG1G1G0Vertex.cc @@ -1,65 +1,66 @@ // -*- C++ -*- // // UEDG1G1G0Vertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 UEDG1G1G0Vertex class. // #include "UEDG1G1G0Vertex.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" using namespace ThePEG::Helicity; using namespace Herwig; UEDG1G1G0Vertex::UEDG1G1G0Vertex() : theq2Last(ZERO), theCoupLast(0.) { orderInGs(1); orderInGem(0); + colourStructure(ColourStructure::SU3F); } void UEDG1G1G0Vertex::doinit() { long kkg1 = 5100021; addToList(kkg1, kkg1, 21); VVVVertex::doinit(); } // The following static variable is needed for the type // description system in ThePEG. DescribeNoPIOClass describeUEDG1G1G0Vertex("Herwig::UEDG1G1G0Vertex", "HwUED.so"); void UEDG1G1G0Vertex::Init() { static ClassDocumentation documentation ("The UEDG1G1G0Vertex class implements the coupling of the " "gluon to two KK excitations of the gluon in the UED model."); } void UEDG1G1G0Vertex::setCoupling(Energy2 q2, tcPDPtr part1, tcPDPtr part2, tcPDPtr part3) { long id1(part1->id()), id2(part2->id()), id3(part3->id()); if( (id1 == ParticleID::g && id2 == 5100021 && id3 == 5100021) || (id2 == ParticleID::g && id1 == 5100021 && id3 == 5100021) || (id3 == ParticleID::g && id1 == 5100021 && id2 == 5100021) ) { if(q2 != theq2Last || theCoupLast == 0.) { theq2Last = q2; theCoupLast = strongCoupling(q2); } norm(theCoupLast); } else throw HelicityLogicalError() << "UEDG1G1G0Vertex::setCoupling - " << "There is an unknown particle in this vertex " << id1 << " " << id2 << " " << id3 << Exception::runerror; } diff --git a/Models/UED/UEDP0H1H1Vertex.cc b/Models/UED/UEDP0H1H1Vertex.cc --- a/Models/UED/UEDP0H1H1Vertex.cc +++ b/Models/UED/UEDP0H1H1Vertex.cc @@ -1,63 +1,64 @@ // -*- C++ -*- // // UEDP0H1H1Vertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 UEDP0H1H1Vertex class. // #include "UEDP0H1H1Vertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" using namespace Herwig; using namespace ThePEG::Helicity; UEDP0H1H1Vertex::UEDP0H1H1Vertex() : theq2Last(ZERO), theCoupLast(0.) { orderInGs(0); orderInGem(1); + colourStructure(ColourStructure::SINGLET); } void UEDP0H1H1Vertex::doinit() { addToList(22, 5100037, -5100037); VSSVertex::doinit(); } // The following static variable is needed for the type // description system in ThePEG. DescribeNoPIOClass describeHerwigUEDP0H1H1Vertex("Herwig::UEDP0H1H1Vertex", "HwUED.so"); void UEDP0H1H1Vertex::Init() { static ClassDocumentation documentation ("This is the coupling of the SM photon to the level-1 charged higgs."); } #ifndef NDEBUG void UEDP0H1H1Vertex::setCoupling(Energy2 q2, tcPDPtr part1, tcPDPtr part2, tcPDPtr ) { #else void UEDP0H1H1Vertex::setCoupling(Energy2 q2, tcPDPtr , tcPDPtr part2, tcPDPtr ) { #endif assert(part1->id()==ParticleID::gamma); assert(abs(part2->id()) == 5100037); if(q2 != theq2Last || theCoupLast == 0.) { theq2Last = q2; theCoupLast = electroMagneticCoupling(q2); } if(part2->id()>0) norm(-theCoupLast); else norm( theCoupLast); } diff --git a/Models/UED/UEDW0A1H1Vertex.cc b/Models/UED/UEDW0A1H1Vertex.cc --- a/Models/UED/UEDW0A1H1Vertex.cc +++ b/Models/UED/UEDW0A1H1Vertex.cc @@ -1,96 +1,97 @@ // -*- C++ -*- // // UEDW0A1H1Vertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 UEDW0A1H1Vertex class. // #include "UEDW0A1H1Vertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" using namespace ThePEG::Helicity; using namespace Herwig; void UEDW0A1H1Vertex::doinit() { addToList( 24, 5100036, -5100037); addToList(-24, 5100036, 5100037); VSSVertex::doinit(); tUEDBasePtr UEDBase = dynamic_ptr_cast(generator()->standardModel()); if(!UEDBase) throw InitException() << "UEDW0A1H1Vertex::doinit() - The pointer to " << "the UEDBase object is null!" << Exception::runerror; theMw2 = sqr(getParticleData(24)->mass()); theMz2 = sqr(getParticleData(23)->mass()); theR2 = sqr(UEDBase->compactRadius()); } UEDW0A1H1Vertex::UEDW0A1H1Vertex() : theMw2(), theMz2(), theR2(), theq2Last(), theCoupLast(0.) { orderInGs(0); orderInGem(1); + colourStructure(ColourStructure::SINGLET); } void UEDW0A1H1Vertex::persistentOutput(PersistentOStream & os) const { os << ounit(theMw2,GeV2) << ounit(theMz2,GeV2) << ounit(theR2,1/GeV2); } void UEDW0A1H1Vertex::persistentInput(PersistentIStream & is, int) { is >> iunit(theMw2,GeV2) >> iunit(theMz2,GeV2) >> iunit(theR2,1/GeV2); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigUEDW0A1H1Vertex("Herwig::UEDW0A1H1Vertex", "HwUED.so"); void UEDW0A1H1Vertex::Init() { static ClassDocumentation documentation ("The coupling of a SM W boson to a level-1 charged higgs and the " "level-1 heavy neutral higgs"); } void UEDW0A1H1Vertex::setCoupling(Energy2 q2, tcPDPtr part1, tcPDPtr part2, tcPDPtr part3) { long chiggs(0); if(abs(part1->id()) == ParticleID::Wplus) chiggs = (abs(part2->id()) == 5100037) ? part2->id() : part3->id(); else if(abs(part2->id()) == ParticleID::Wplus) chiggs = (abs(part1->id()) == 5100037) ? part1->id() : part3->id(); else if(abs(part3->id()) == ParticleID::Wplus) chiggs = (abs(part1->id()) == 5100037) ? part1->id() : part2->id(); else { throw HelicityLogicalError() << "UEDW0A1H1Vertex::setCoupling - " << "There is no SM W boson in this vertex" << Exception::warning; return; } if(abs(chiggs) == 5100037) { if(q2 != theq2Last || theCoupLast == 0.) { theq2Last = q2; theCoupLast = weakCoupling(q2); double mwRs = theMw2*theR2; double denom = sqrt( (1 + mwRs)*(1. + theMw2*theR2) ); theCoupLast *= ( 0.5 + mwRs )/denom; } if(chiggs > 0) theCoupLast *= -1.; norm(theCoupLast); } else throw HelicityLogicalError() << "UEDW0A1H1Vertex::setCoupling - " << "There is an unknown particle in this " << "vertex " << chiggs << Exception::runerror; } diff --git a/Models/UED/UEDW0W1W1Vertex.cc b/Models/UED/UEDW0W1W1Vertex.cc --- a/Models/UED/UEDW0W1W1Vertex.cc +++ b/Models/UED/UEDW0W1W1Vertex.cc @@ -1,139 +1,140 @@ // -*- C++ -*- // // UEDW0W1W1Vertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 UEDW0W1W1Vertex class. // #include "UEDW0W1W1Vertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG::Helicity; using namespace Herwig; UEDW0W1W1Vertex::UEDW0W1W1Vertex() : theSinW(0.), theCosW(0.), theSinThetaOne(0.), theCosThetaOne(0.), theq2last(), theElast(0.), theCouplast(0.), theSMlast(0), theKKlast(0) { orderInGs(0); orderInGem(1); + colourStructure(ColourStructure::SINGLET); } void UEDW0W1W1Vertex::doinit() { addToList( 22, -5100024, 5100024); addToList( 23, -5100024, 5100024); addToList( 24, -5100024, 5100022); addToList( 24, -5100024, 5100023); addToList(-24, 5100024, 5100022); addToList(-24, 5100024, 5100023); VVVVertex::doinit(); tUEDBasePtr model = dynamic_ptr_cast(generator()->standardModel()); if(!model) throw InitException() << "UEDW0W1W1Vertex::doinit() - The pointer to " << "the UEDBase object is null!" << Exception::runerror; theSinW = sqrt(sin2ThetaW()); theCosW = sqrt( 1. - sqr(theSinW) ); theSinThetaOne = model->sinThetaOne(); theCosThetaOne = sqrt( 1. - sqr(theSinThetaOne)); } void UEDW0W1W1Vertex::persistentOutput(PersistentOStream & os) const { os << theSinW << theCosW << theSinThetaOne << theCosThetaOne; } void UEDW0W1W1Vertex::persistentInput(PersistentIStream & is, int) { is >> theSinW >> theCosW >> theSinThetaOne >> theCosThetaOne; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigUEDW0W1W1Vertex("Herwig::UEDW0W1W1Vertex", "HwUED.so"); void UEDW0W1W1Vertex::Init() { static ClassDocumentation documentation ("The coupling of an SM W boson to a level 1 KK W and KK Z and KK photon"); } /// \todo look again void UEDW0W1W1Vertex::setCoupling(Energy2 q2, tcPDPtr part1, tcPDPtr part2, tcPDPtr part3) { long id1(abs(part1->id())), id2(abs(part2->id())), id3(abs(part3->id())), smID(0), kkparticle(0); double perm(1.); if( id1 == 22 || id1 == 23) { smID = id1; kkparticle = id2; if(part2->id()>0) perm=-1.; } else if(id2 == 22 || id2 == 23) { smID = id2; kkparticle = id1; if(part1->id()<0) perm=-1.; } else if(id3 == 22 || id3 == 23) { smID = id3; kkparticle = id1; if(part1->id()>0) perm=-1.; } else if(id1 == 24 ) { if( part1->id() == 24 ) perm = -1.; smID = id1; kkparticle = (id2 == 5100024) ? id3 : id2; if(id3 == 5100024) perm *=-1.; } else if( id2 == 24 ) { if( part2->id() == 24 ) perm = -1.; smID = id2; kkparticle = (id1 == 5100024) ? id3 : id1; if(id1 == 5100024) perm *=-1.; } else if( id3 == 24 ) { if( part3->id() == 24 ) perm = -1.; smID = id3; kkparticle = (id1 == 5100024) ? id2 : id1; if(id2 == 5100024) perm *=-1.; } else { throw HelicityLogicalError() << "UEDW0W1W1Vertex::setCoupling() - There is no SM gauge boson in " << "this vertex. " << id1 << " " << id2 << " " << id3 << Exception::warning; norm(0.); return; } if( q2 != theq2last || theElast == 0.) { theq2last = q2; theElast = electroMagneticCoupling(q2); } if( smID != theSMlast || kkparticle != theKKlast ) { theSMlast = smID; theKKlast = kkparticle; if( smID == 22 ) theCouplast = 1.; else if(smID == 23) theCouplast = theCosW/theSinW; else { if( kkparticle == 5100023 ) theCouplast = theCosThetaOne/theSinW; else theCouplast = theSinThetaOne/theSinW; } } norm(perm*theElast*theCouplast); } diff --git a/Models/UED/UEDZ0A1h1Vertex.cc b/Models/UED/UEDZ0A1h1Vertex.cc --- a/Models/UED/UEDZ0A1h1Vertex.cc +++ b/Models/UED/UEDZ0A1h1Vertex.cc @@ -1,100 +1,101 @@ // -*- C++ -*- // // UEDZ0A1h1Vertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 UEDZ0A1h1Vertex class. // #include "UEDZ0A1h1Vertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" using namespace ThePEG::Helicity; using namespace Herwig; UEDZ0A1h1Vertex::UEDZ0A1h1Vertex() : theSin2ThetaW(0.), theKappa(0.), theq2Last(ZERO), theCoupLast(0.) { orderInGs(0); orderInGem(1); + colourStructure(ColourStructure::SINGLET); } void UEDZ0A1h1Vertex::doinit() { addToList(23, 5100036, 5100025); VSSVertex::doinit(); tUEDBasePtr UEDBase = dynamic_ptr_cast(generator()->standardModel()); if(!UEDBase) throw InitException() << "UEDZ0A1h1Vertex::doinit() - The pointer to " << "the UEDBase object is null!" << Exception::runerror; double sw2 = sin2ThetaW(); theSin2ThetaW = 2.*sqrt(sw2*(1. - sw2)); Energy2 mz2 = sqr(getParticleData(23)->mass()); InvEnergy2 rad2 = sqr(UEDBase->compactRadius()); theKappa = 1./sqrt(1. + mz2*rad2); } void UEDZ0A1h1Vertex::persistentOutput(PersistentOStream & os) const { os << theSin2ThetaW << theKappa; } void UEDZ0A1h1Vertex::persistentInput(PersistentIStream & is, int) { is >> theSin2ThetaW >> theKappa; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigUEDZ0A1h1Vertex("Herwig::UEDZ0A1h1Vertex", "HwUED.so"); void UEDZ0A1h1Vertex::Init() { static ClassDocumentation documentation ("The coupling of an SM Z boson to a level-1 CP-Odd pseudo-scalar " "and level 1 higgs."); } void UEDZ0A1h1Vertex::setCoupling(Energy2 q2, tcPDPtr part1, tcPDPtr part2, tcPDPtr part3) { long scaA(0), scaB(0); if(part1->id() == ParticleID::Z0) { scaA = part2->id(); scaB = part3->id(); } else if(part2->id() == ParticleID::Z0) { scaA = part1->id(); scaB = part3->id(); } else if(part3->id() == ParticleID::Z0) { scaA = part1->id(); scaB = part2->id(); } else { throw HelicityLogicalError() << "UEDZ0A1h1Vertex::setCoupling - " << "There is no SM Z boson in this vertex" << Exception::warning; } if( (scaA == 5100036 && scaB == 5100025) || (scaB == 5100036 && scaA == 5100025) ) { if(q2 != theq2Last || theCoupLast == 0.) { theq2Last = q2; theCoupLast = theKappa*electroMagneticCoupling(q2)/theSin2ThetaW; } norm(theCoupLast); } else throw HelicityLogicalError() << "UEDZ0A1h1Vertex::setCoupling - " << "There is an unknown particle in this " << "vertex. " << scaA << " " << scaB << Exception::warning; } diff --git a/Models/UED/UEDZ0H1H1Vertex.cc b/Models/UED/UEDZ0H1H1Vertex.cc --- a/Models/UED/UEDZ0H1H1Vertex.cc +++ b/Models/UED/UEDZ0H1H1Vertex.cc @@ -1,95 +1,96 @@ // -*- C++ -*- // // UEDZ0H1H1Vertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 UEDZ0H1H1Vertex class. // #include "UEDZ0H1H1Vertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" using namespace ThePEG::Helicity; using namespace Herwig; UEDZ0H1H1Vertex::UEDZ0H1H1Vertex() : theCosThetaW(0.), theCosTheta2W(0.), theMw2(), theR2(), theq2Last(ZERO), theCoupLast(0.) { orderInGs(0); orderInGem(1); + colourStructure(ColourStructure::SINGLET); } void UEDZ0H1H1Vertex::doinit() { addToList(23, 5100037, -5100037); VSSVertex::doinit(); tUEDBasePtr theUEDBase = dynamic_ptr_cast(generator()->standardModel()); if(!theUEDBase) throw InitException() << "UEDZ0H1H1Vertex::doinit() - The pointer to " << "the UEDBase object is null!" << Exception::runerror; theCosThetaW = sqrt(1. - sin2ThetaW()); theCosTheta2W = 1. - 2.*sin2ThetaW(); theMw2 = sqr(getParticleData(24)->mass()); theR2 = sqr(theUEDBase->compactRadius()); } void UEDZ0H1H1Vertex::persistentOutput(PersistentOStream & os) const { os << theCosThetaW << theCosTheta2W << ounit(theMw2,GeV2) << ounit(theR2,1/GeV2); } void UEDZ0H1H1Vertex::persistentInput(PersistentIStream & is, int) { is >> theCosThetaW >> theCosTheta2W >> iunit(theMw2,GeV2) >> iunit(theR2,1/GeV2); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigUEDZ0H1H1Vertex("Herwig::UEDZ0H1H1Vertex", "HwUED.so"); void UEDZ0H1H1Vertex::Init() { static ClassDocumentation documentation ("This is the coupling of the SM Z boson to the level-1 charged higgs."); } void UEDZ0H1H1Vertex::setCoupling(Energy2 q2, tcPDPtr part1, tcPDPtr part2, tcPDPtr part3) { long kkhiggs(0); if(part1->id() == ParticleID::Z0) kkhiggs = abs(part2->id()); else if(part2->id() == ParticleID::Z0) kkhiggs = abs(part1->id()); else if(part3->id() == ParticleID::Z0) kkhiggs = abs(part1->id()); else { throw HelicityLogicalError() << "UEDZ0H1H1Vertex::setCoupling - There is no " << "SM photon in this vertex!." << Exception::warning; return; } if(kkhiggs == 5100037) { if(q2 != theq2Last || theCoupLast == 0.) { theq2Last = q2; theCoupLast = Complex(0., 1.)*weakCoupling(q2); theCoupLast *= ( (theCosTheta2W/2./theCosThetaW) - sqr(theCosThetaW)*theMw2*theR2 )/(1. + theMw2*theR2); } norm(theCoupLast); } else throw HelicityLogicalError() << "UEDZ0H1H1Vertex::setCoupling - There is no " << "level-1 higgs in this vertex! " << kkhiggs << Exception::warning; } diff --git a/Models/Zprime/ZprimeModelZPQQVertex.cc b/Models/Zprime/ZprimeModelZPQQVertex.cc --- a/Models/Zprime/ZprimeModelZPQQVertex.cc +++ b/Models/Zprime/ZprimeModelZPQQVertex.cc @@ -1,186 +1,187 @@ // -*- C++ -*- // // ZprimeModelZPQQVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 ZprimeModelZPQQVertex class. // #include "ZprimeModelZPQQVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Config/Constants.h" using namespace Herwig; IBPtr ZprimeModelZPQQVertex::clone() const { return new_ptr(*this); } IBPtr ZprimeModelZPQQVertex::fullclone() const { return new_ptr(*this); } ZprimeModelZPQQVertex::ZprimeModelZPQQVertex() { addToList(-2,6,32); addToList(-6,2,32); addToList(-6,6,32); addToList(-5,5,32); addToList(-4,4,32); addToList(-3,3,32); addToList(-2,2,32); addToList(-1,1,32); addToList(-11,11,32); addToList(-13,13,32); addToList(-15,15,32); addToList(-12,12,32); addToList(-14,14,32); addToList(-16,16,32); orderInGem(1); orderInGs(0); + colourStructure(ColourStructure::SU3F); } void ZprimeModelZPQQVertex::doinit() { _theModel = generator()->standardModel(); tcHwZprimePtr hwZprime=dynamic_ptr_cast(_theModel); if(hwZprime) { _cZPTU_R =hwZprime->_cZPTU_right(); _cZPTU_L =hwZprime->_cZPTU_left(); _cZPTT_R =hwZprime->_cZPTT_right(); _cZPTT_L =hwZprime->_cZPTT_left(); _cZPUU_R =hwZprime->_cZPUU_right(); _cZPUU_L =hwZprime->_cZPUU_left(); _cZPCC_R =hwZprime->_cZPCC_right(); _cZPCC_L =hwZprime->_cZPCC_left(); _cZPDD_R =hwZprime->_cZPDD_right(); _cZPDD_L =hwZprime->_cZPDD_left(); _cZPBB_R =hwZprime->_cZPBB_right(); _cZPBB_L =hwZprime->_cZPBB_left(); _cZPSS_R =hwZprime->_cZPSS_right(); _cZPSS_L =hwZprime->_cZPSS_left(); _cZPee_R =hwZprime->_cZPee_right(); _cZPee_L =hwZprime->_cZPee_left(); _cZPmm_R =hwZprime->_cZPmm_right(); _cZPmm_L =hwZprime->_cZPmm_left(); _cZPtt_R =hwZprime->_cZPtt_right(); _cZPtt_L =hwZprime->_cZPtt_left(); _cZPnuenue_R =hwZprime->_cZPnuenue_right(); _cZPnuenue_L =hwZprime->_cZPnuenue_left(); _cZPnuenue_R =hwZprime->_cZPnumnum_right(); _cZPnumnum_L =hwZprime->_cZPnumnum_left(); _cZPnutnut_R =hwZprime->_cZPnutnut_right(); _cZPnutnut_L =hwZprime->_cZPnutnut_left(); _cZP_o =hwZprime->_cZPoverallCoup(); } FFVVertex::doinit(); } void ZprimeModelZPQQVertex::persistentOutput(PersistentOStream & os) const { os << _cZPTU_R << _cZPTU_L << _cZPTT_R << _cZPTT_L << _cZPUU_R << _cZPUU_L << _cZPCC_R << _cZPCC_L << _cZPDD_R << _cZPDD_L << _cZPSS_R << _cZPSS_L << _cZPBB_R << _cZPBB_L << _cZPee_R << _cZPee_L << _cZPmm_R << _cZPmm_L << _cZPtt_R << _cZPtt_L << _cZPnuenue_R << _cZPnuenue_L << _cZPnumnum_R << _cZPnumnum_L << _cZPnutnut_R << _cZPnutnut_L << _cZP_o; } void ZprimeModelZPQQVertex::persistentInput(PersistentIStream & is, int) { is >> _cZPTU_R >> _cZPTU_L >> _cZPTT_R >> _cZPTT_L >> _cZPUU_R >> _cZPUU_L >> _cZPCC_R >> _cZPCC_L >> _cZPDD_R >> _cZPDD_L >> _cZPSS_R >> _cZPSS_L >> _cZPBB_R >> _cZPBB_L >> _cZPee_R >> _cZPee_L >> _cZPmm_R >> _cZPmm_L >> _cZPtt_R >> _cZPtt_L >> _cZPnuenue_R >> _cZPnuenue_L >> _cZPnumnum_R >> _cZPnumnum_L >> _cZPnutnut_R >> _cZPnutnut_L >> _cZP_o; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigZprimeModelZPQQVertex("Herwig::ZprimeModelZPQQVertex", "Herwig.so"); void ZprimeModelZPQQVertex::Init() { static ClassDocumentation documentation ("The ZprimeModelZPQQVertex class is the implementation" " of the helicity amplitude calculation of the Zprime" " Z prime Quark-antiQuark vertex."); } void ZprimeModelZPQQVertex::setCoupling(Energy2,tcPDPtr aa ,tcPDPtr bb, tcPDPtr cc) { double _cR = 1.0, _cL = 1.0; long ccc(cc->id()), aaa(aa->id()), bbb(bb->id()); if( abs(aaa) == 6 || abs(bbb) == 6 || abs(ccc) == 6 ) { if( abs(aaa) !=2 && abs(bbb) !=2 && abs(ccc) != 2 ) { _cL = _cZPTT_L; _cR = _cZPTT_R; } else if( abs(aaa) ==2 || abs(bbb) ==2 || abs(ccc) == 2 ) { _cL = _cZPTU_L; _cR = _cZPTU_R; } } if( abs(aaa) == 5 || abs(bbb) == 5 || abs(ccc) == 5 ) { _cL = _cZPBB_L; _cR = _cZPBB_R; } if( abs(aaa) == 4 || abs(bbb) == 4 || abs(ccc) == 4 ) { _cL = _cZPCC_L; _cR = _cZPCC_R; } if( abs(aaa) == 3 || abs(bbb) == 3 || abs(ccc) == 3 ) { _cL = _cZPSS_L; _cR = _cZPSS_R; } if( (abs(aaa) == 2 || abs(bbb) == 2 || abs(ccc) == 2) && (abs(aaa) !=6 && abs(bbb) !=6 && abs(ccc) != 6)) { _cL = _cZPUU_L; _cR = _cZPUU_R; } if( abs(aaa) == 1 || abs(bbb) == 1 || abs(ccc) == 1 ) { _cL = _cZPDD_L; _cR = _cZPDD_R; } if( abs(aaa) == 11 || abs(bbb) == 11 || abs(ccc) == 11 ) { _cL = _cZPee_L; _cR = _cZPee_R; } if( abs(aaa) == 13 || abs(bbb) == 13 || abs(ccc) == 13 ) { _cL = _cZPmm_L; _cR = _cZPmm_R; } if( abs(aaa) == 15 || abs(bbb) == 15 || abs(ccc) == 15 ) { _cL = _cZPtt_L; _cR = _cZPtt_R; } if( abs(aaa) == 12 || abs(bbb) == 12 || abs(ccc) == 12 ) { _cL = _cZPnuenue_L; _cR = _cZPnuenue_R; } if( abs(aaa) == 14 || abs(bbb) == 14 || abs(ccc) == 14 ) { _cL = _cZPnumnum_L; _cR = _cZPnumnum_R; } if( abs(aaa) == 16 || abs(bbb) == 16 || abs(ccc) == 16 ) { _cL = _cZPnutnut_L; _cR = _cZPnutnut_R; } right(_cR); left(_cL); norm(_cZP_o); } diff --git a/NEWS b/NEWS --- a/NEWS +++ b/NEWS @@ -1,1667 +1,1689 @@ Herwig News -*- outline -*- ================================================================================ +* Herwig 7.1.3 release: 2018-04-05 + +** Dipole Shower +*** Changed default phase space limits +*** g -> gg splitting function asymmetrized +*** Initial retune supplied, given the visible changes + to LEP observables + +** Added new Baryonic colour reconnection model + (arXiv 1710:10906) + +** Added Schuler-Sjostrand Photon PDFs + +** Handling of massless taus from external sources + +** various minor fixes + +** use std::array<> where possible + + + * Herwig 7.1.2 release: 2017-11-01 ** Reduction of the default pt cut for QED radiation off leptons. ** Inputfile changes due to new read mode in ThePEG. ThePEG remains in current repo dir when reading input-file/snippet. ** Fix for shower scale variations in qtilde shower. ** All standard input files now use the tuned intrinsic pt. ** Remove obsolete input files for various tunes. ** Fix for Madgraph interface for NLO corrections with recent version. ** Run file size reduction for processes using madgraph/openloops. ** Fix in jacobian for massive dipole kinematics. ** General improvements for UFO model handling. + * Herwig 7.1.1 release: 2017-07-14 ** Snippets are now all installed ** Fixed broken ufo2herwig output and LHC-MB.in ** UFO improvements *** More robust SLHA file handling *** option of creating diagonal mixing matrices, needed for ATLAS simplfied models *** Improved warnings about resetting standard model particles *** Fixed certain cases where the wrong lorentz structure was picked in VVS vertices ** Improved error message for unhandled beam particles ** Fix for Dipole Shower chain selection ** Fixed crash in double diffractive delta resonances * Herwig 7.1.0 release: 2017-05-19 ** Major new release For a more detailed overview and further references please see the release note arXiv:1705.06919 ** NLO multijet merging with the dipole shower ** A new soft model ** An interface to EvtGen ** Improved calculation of mass effects in the dipole shower ** Top decays in the dipole shower, and NLO corrections to the decay ** An implementation of the KrkNLO method for simple processes ** Major restructuring and cleanup of default input files ** C++11 is now mandatory and heavily used in the code ** Many smaller bugfixes and improvements * Herwig 7.0.4 release: 2016-10-24 ** API The high level API is now properly available as a library, providing an alternative to the Herwig main program. ** Dipole shower Added nloops() function to the AlphaS classes to return the number of loops in the running coupling ** Matchbox Improved error handling and clearer messages ** BSM models Initialize W mass correctly from SLHA file. Improved reading in of decay modes if they already exist. ** Sampling Introduced option to reduce reference weight in AlmostUnweighted mode by Kappa factor. Useful for processes where full unweighting is infeasible. ** Qtilde shower Better control of scale in splitting functions using the SplittingFunction:ScaleChoice interface. ** Tests New NLO fixed-order input files for testing Matchbox in Tests/ExternNLO. ** Input files Set diagonal CKM options consistently. Added TauTauHVertex and MuMuHVertex to MatchboxDefaults. * Herwig 7.0.3 release: 2016-07-21 ** subprocess generation filters A number of filters has been implemented to speed up process and diagram generation for the case of Standard Model like processes; this is particularly helpful for processes involving a large number of electroweak combinatorics. See the documentation for more details. ** fix to directory hierarchy A bug in the Herwig-scratch directory hierarchy when integrating with different seeds has been fixed. ** fix for relocating MadGraph generated amplitudes The directory and symbolic link structure for MadGraph-built amplitudes has been changed to allow for relocation of a run directory to a different file system hierarchy. ** z* variable added to LeptonsJetsAnalysis The builtin LeptonsJetsAnalysis has been extented to include the normalized relative rapidity z* ** detuning parameter for shower reweighting An efficiency tweak when using the shower reweighting facilities has been introduced for the veto algorithms in both the QTilde and the Dipole shower. See the documentation for more details. ** BaryonThreeQuarkModelFormFactor A scaling bug in the form factor series expansion was fixed. * Herwig 7.0.2 release: 2016-04-29 ** Event reweighting New option of calculating the weights for the effect of varying the scale used in both the default and dipole showers. The method is described in arXiv:1605.08256 ** mergegrids mode A main mode for the Herwig executable has been added which merges the integration grids from parallel runs. ** NLO Diphoton production The NLO matrix elements in the POWHEG approach for diphoton production as described in JHEP 1202 (2012) 130, arXiv:1106.3939 have been included as MEPP2GammaGammaPowheg. ** BSM Hard process constructor A missing Feynman diagram with a t-channel vector boson has been added to the matrix element for vv2ss ** BSM Decay Modes calculation The behaviour of the option to disable decay modes in BSM Models has been changed so that the partial width for the ignored modes is now calculated and included in the total width, but the branching ratio is set to zero. This is more physical than the previous option where the mode was t otally ignored and hence not included in the calculation of the width. ** Mass Generation The behaviour of the GenericMassGenerator has been changed so that modes which have been disabled are only included in the calculation of the total width and not in the partial width used in the numerator of the weight used to select the off-shell mass. ** Boost detection Boost could not detect the compiler version for gcc-5.3 and gcc-6.1 * Herwig 7.0.1 release: 2016-01-17 ** Version number written to log file The Herwig version number is now included in addition to ThePEG's version. ** Tau lifetimes A bug with lifetimes for hard process Taus is fixed. Thanks to ATLAS for the report! ** Shower FSR retries Rare events could take a long time due to an extremely large number of FSR retries. These are now capped at a configurable number. ** Dipole shower Reweighting for non-radiating events; fixes for shower profile handling; option to downgrade large-Q expansion for alphaS ** Matchbox builtins Added massive currents for q-qbar ** ShowerAlphaQCD can now use user-defined thresholds ** Input snippets W/Z/H on-shell now split into three files; 4-flavour scheme added ** UFO converter The converter now has experimental support for writing out param cards of its current settings. ** LEPJetAnalysis loading fixed ** Contrib HJets++ has moved to a stand-alone project, FxFx has been added * Herwig 7.0.0 (Herwig++ 3.0.0) release: 2015-12-04 ** Major new release A major new release of the Monte Carlo event generator Herwig++ (version 3.0) is now available. This release marks the end of distinguishing Herwig++ and HERWIG development and therefore constitutes the first major release of version 7 of the Herwig event generator family. The new version features a number of significant improvements to the event simulation, including: built-in NLO hard process calculation for all Standard Model processes, with matching to both angular ordered and dipole shower modules via variants of both subtractive (MC@NLO-type) and multiplicative (Powheg-type) algorithms; QED radiation and spin correlations in the angular ordered shower; a consistent treatment of perturbative uncertainties within the hard process and parton showering, as well as a vastly improved documentation. This version includes (for a more detailed overview and further references please see the release note arXiv:1512.01178): ** A long list of improvements and fixes for the Matchbox module *** includes MC@NLO and Powheg matching to both showers with truncated showering ** A long list of improvements and fixes for both of the shower modules *** includes improvements of numerics issues relevant to 100 TeV pp collisions ** NLO event simulation and Matchbox development *** Interfaces to a number of external libraries *** A new workflow for event generation *** Electroweak corrections to VV production ** Parton shower development *** QED radiation in the angular ordered shower *** Spin correlations in the angular ordered shower *** New scale choices in gluon branchings ** Improvements to event generation workflow *** Re-organized and streamlined input files for the new NLO development *** A unified treatment of shower and matching uncertainties *** New integrator modules featuring parallel integration ** New default tunes for both shower modules ** New contrib modules *** Electroweak Higgs plus jets production *** FxFx merging support *** Higgs boson pair production * Herwig++-2.7.1 release: 2014-07-07 ** New shower switches to select schemes for momentum reconstruction *** QTildeReconstructor:FinalStateReconOption has the following options: *** Default All momenta are rescaled in the rest frame. *** MostOffShell Put all particles on the new-mass shell and the most off-shell and recoiling system are rescaled to ensure 4-momentum is conserved. *** Recursive Recursively put the most off-shell particle which hasn't yet been rescaled on-shell by rescaling the particles and the recoiling system. *** RestMostOffShell The most off-shell is put on shell by rescaling it and the recoiling system, the recoiling system is then put on-shell in its rest frame. *** RestRecursive As above, but recursively treat the currently most-off shell (only makes a difference for more than 3 partons) ** Ticket #378: Hadronization of baryon number violating clusters involving diquarks Fixed by only considering non-diquarks to be combined in the ClusterFinder. ** UFO converter can now parse SLHA files for parameter settings The UFO converter code can now use SLHA files for modifying parameters. The first pass "ufo2herwig" produces the model to be compiled. For each parameter card, run "slha2herwig" to get the matching input file. ** Fix for systems using lib64 The repository is now initialized correctly on systems using lib64 as the library location. ** Efficiency optimization Better allocation of internal vector variables for a noticeable speed increase of 10-20% with LHC events. * Herwig++-2.7.0 release: 2013-10-28 ** UFO interface to Feynman rules generators Herwig++ now includes "ufo2herwig", a tool that automatically creates all required files to run a BSM model from a UFO directory. The conversion has been extensively tested against Feynrules models MSSM, NMSSM, RS, Technicolor, and less extensively with most of the other models in the Feynrules model database. We expect that following this release there will be no further hard-coded new physics models added to Herwig++ and that future models will be included using the UFO interface. ** Shower uncertainties A first set of scaling parameters to estimate shower uncertainties is provided for both the angular ordered as well as the dipole shower; they are Evolver:HardScaleFactor and ShowerAlphaQCD: RenormalizationScaleFactor. ** Rewrite of Matchbox NLO matching The NLO matching implementation has been rewritten and is now more flexible and consistent. Profile scales are provided for the hardest emission both for the dipole shower and matrix element correction matching. ** BLHA2 Interface and new processes Matchbox now features a generic BLHA2 interface to one-loop amplitude codes and now also includes W and W+jet production as well as Higss production in gluon fusion as builtin processes. ** Impoved dipole shower kinematics parametrization The kinematics parametrization for emissions in the dipole shower has been made more efficient. ** W and Z Powheg decays Decays of W and Z bosons now use the Powheg decayers by default. ** Improved treatment of beam remnants The handling of beam remnants has been improved in multiple contexts, leading to a much lower error rate at p+/p- collisions. An additional value "VeryHard" for ClusterFissioner:RemnantOption can be used to disable any special treatment of beam remnant clusters. ** New underlying event tune Herwig++ now uses tune UE-EE-5-MRST by default. Other related tunes can be obtained from the Herwig++ tunes page ** Improvements in BSM code The UFO development identified many sign fixes in rarely used BSM vertices; many improvements were made to general decayers, allowing four-body decays in BSM for the first time; Powheg is enabled in General two-body decayers; and the handling of colour sextets has been improved. ** A new HiggsPair matrix element in Contrib. ** A new matrix element for single top production. ** The Higgs mass is now set to 125.9 GeV (from PDG 2013 update). ** C++-11 testing To help with the coming transition to C++-11, we provide the new --enable-stdcxx11 configure flag. Please try to test builds with this flag enabled and let us know any problems, but do not use this in production code yet. In future releases, this flag will be on by default. ** Other changes *** Many new Rivet analyses have been included in the Tests directory. *** Cleaned Shower header structure; grouped shower parameters into one struct. *** The boolean Powheg flag in HwMEBase changed to an enumeration. * Herwig++-2.6.3 release: 2013-02-22 ** Decay vertex positioning in HepMC output Pseudo-vertices that Herwig++ inserts for technical reasons will now not contribute to the Lorentz positions of downstream vertices. Thanks to ATLAS for the bug report! ** Updated Rivet tests Herwig's library of Rivet test runs has been brought up-to-date with new analyses that were recently published by the Rivet collaboration. * Herwig++-2.6.2 release: 2013-01-30 ** Fixes for PDF and scale choices in POWHEG events Scale settings for MPI and the regular shower are now correct in POWHEG events. This should fix reported anomalies in POWHEG jet rates. NLO PDFs are now also set consistently in the example input files. ** Ticket #373: Branching ratio factors in cross-section If any decay modes are selectively disabled, setting the following post-handler will cause all reported cross-sections to include the branching ratio factor(s) from the previous stages correctly: create Herwig::BranchingRatioReweighter BRreweight insert LHCGenerator:EventHandler:PostDecayHandlers 0 BRreweight ** Anomalous vertices now possible in MEfftoVH ** Interactive shell does not quit on error ** Better warning messages for events from inconsistent LHEF files ** Possible division by zero error fixed in BSM branching ratio calculations ** Decayer and ME changes to improve checkpointing The checkpointing changes in ThePEG 1.8.2 are implemented here, too. Regular dump files are consistent now. * Herwig++-2.6.1 release: 2012-10-16 ** Configure switches The various switches to turn off compilation of BSM models have been unified into a single '--disable-models'. A new flag '--disable-dipole' can be used to turn off the compilation of the Dipole and Matchbox codes. ** Ticket #348: Search path for repository 'read' command The search path for the 'read' command is configurable on the command line with the -i and -I switches. By default, the installation location is now included in the search path, so that 'Herwig++ read LEP.in' will work in an empty directory. The current working directory will always be searched first. The rarely used "Herwig++ init" command has been made consistent with 'read' and 'run' and should now be used without the '-i' flag. ** Width treatment in BSM The width treatment in BSM decay chains has been greatly improved and is now switched on by default in the .model files. To get the old behaviour, use set /Herwig/NewPhysics/NewModel:WhichOffshell Selected ** New BSM models Little Higgs models with and without T-parity are now available. ** Resonance photon lifetime A lifetime bug affecting decays of pi0 to e+e-X was fixed. The virtual photon is not part of the event record anymore. ** Ticket #371: Hard diffraction FPE Herwig++ 2.6.0 introduced a bug into the diffraction code which would abort any runs. This is now fixed. ** O2AlphaS Support for setting quark masses different from the particle data objects as introduced in ThePEG 1.8.1 has been enabled. ** Matchbox Several improvements and bug fixes are included for Matchbox. Amplitudes relevant to pp -> Z+jet and crossed processes at NLO are now available, and various scale choices have been added in a more flexible way. All subtraction dipoles for massive quarks are now included. ** Dipole shower Parameters to perform scale variations in the shower have been added to estimate uncertainties. A bug in showering off gg -> h has been fixed. ** Minor fixes *** Two broken colour structures in GeneralHardME *** Susy Higgs mixing matrix *** BaryonFactorizedDecayer out-of-bounds access *** Mass values in SimpleLHCAnalysis * Herwig++-2.6.0 release: 2012-05-21 (tagged at SVN r7407) ** New NLO framework Matchbox, a flexible and very general framework for performing NLO calculations at fixed order or matched to parton showers is provided with this release. ** Dipole shower algorithm A first implementation of the coherent dipole shower algorithm by Plätzer and Gieseke (arXiv:0909.5593 and arXiv:1109.6256) is available. ** Alternative samplers and the ExSample library The ExSample library by Plätzer (arXiv:1108.6182) is shipped along with Herwig++ in an extended version. The extended version provides SamplerBase objects which can be used alternatively to the default ACDCSampler. ** New BSM models *** New colour sextet diquark model A colour sextet diquark model has been included, as described in Richardson and Winn (arXiv:1108.6154). *** Models reproducing the CDF t-tbar asymmetry Four models that can reproduce the reported t-tbar asymmetry have been included. *** Zprime A simple standard model extension by one additional heavy neutral vector boson. ** Interface to AlpGen, with MLM merging The Contrib directory contains a new interface to the AlpGen matrix element generator. AlpGen events must be preprocessed with the provided AlpGenToLH.exe tool before they can be used. More information can be found in the Herwig++ 2.6 release note. ** HiggsVBF Powheg Higgs boson production by vector boson fusion is available at NLO in the POWHEG scheme, as described in d'Errico, Richardson (arXiv:1106.2983). The Powheg DIS processes were available in Herwig++-2.5.2 already. ** Statistical colour reconnection Alternative mechanisms to minimize the colour length Sum(m_clu) before the hadronization stage, based on Metropolis and annealing algorithms. ** Energy extrapolation of underlying-event tunes To describe underlying-event data at different c.m. energies, the energy-dependent parameter pT_min will now be adjusted automatically, following a power-law. The new tune parameters are the value at 7000 GeV "MPIHandler:pTmin0", and MPIHandler:Power. ** Ticket #239: Reporting of minimum-bias cross-section When simulating minimum-bias events using the MEMinBias matrix element, the correct unitarized cross section can now be reported via the standard facilities; it is no longer necessary to extract it from the .log file of the run. The corresponding functionality is enabled by inserting a MPIXSecReweighter object as a post-subprocess handler: create Herwig::MPIXSecReweighter MPIXSecReweighter insert LHCHandler:PostSubProcessHandlers 0 MPIXSecReweighter ** Dependency on 'boost' Herwig++ now requires the boost headers to build; if not detected in standard locations, specify with the --with-boost configure option. ** Tests directory The Tests directory now contains input cards for almost all Rivet analyses. A full comparison run can be initiated with 'make tests'. ** Minor changes *** Default LHC energy now 8 TeV All LHC-based defaults have now been updated to use 8 TeV as the center-of-mass energy. *** Herwig::ExtraParticleID -> ThePEG::ParticleID The namespace for additional particles has been unified into ThePEG::ParticleID *** MEee2VectorMeson The e+e- -> vector meson matrix element has moved from Contrib into HwMELepton.so *** SUSY numerics fixes Better handling of rare numerical instabilities. *** YODA output for Rivet The built-in histogramming handler can now output data in the YODA format used by Rivet. *** Consistency checks in SLHA file reader Better warnings for inconsistent SusyLHA files *** better colour flow checking for development ** Bug fixes *** Extremely offshell W from top decay Numerical improvements for very off-shell W bosons coming from top decays. *** Ticket #367: problems in using SUSY + LHE Susy events from Les Houches event files are now handled better. *** Infinite loop in remnant decayer The remnant decayer will now abort after 100 tries. *** Fix to HiggsVBF LO diagrams The diagram structure of HiggsVBF LO matrix elements has been fixed. *** LEP thrust fix The calculation of the transverse momentum of a branching from the evolution variable in final-state radiation can now be changed. While formally a sub-leading choice this enables a better description of the thrust distribution in e+e- collisions at small values of the thrust. Currently the default behaviour, where the cut-off masses are used in the calculation, remains the same as previous versions. * Herwig++-2.5.2 release: 2011-11-01 (tagged at SVN r6928) ** Optional new jet vetoing model The jet vetoing model by Schofield and Seymour (arXiv:1103.4811) is available via Evolver:ColourEvolutionMethod, PartnerFinder:PartnerMethod and SplittingFunction:SplittingColourMethod. The default behaviour is unchanged. ** MPI tune Version 3 of the MPI tunes is now the default. Please note that the pT parameter is energy-dependent and needs to be modified when an LHC run is not at 7 TeV. The latest tunes are always available at http://projects.hepforge.org/herwig/trac/wiki/MB_UE_tunes ** MPI PDFs MPI PDFs can now be controlled independently. ** Initialization time speedup A new BSMModel base class was introduced between StandardModel and the BSM model classes. Together with a restructured decay mode initialization, this offers significantly faster startup times for BSM runs. ThreeBodyDecays can now always be switched on without a large speed penalty. ** Decay mode file Decay mode files in the SLHA format can now be read separately in any BSM model with 'set Model:DecayFileName filename' ** Powheg DIS Charged- and neutral-current DIS processes implementing the POWHEG method are now available. ** Diffraction models Xi cut implemented in PomeronFlux ** Ticket #352: Colour reconnection fixed in DIS ** Ticket #353: Improved numerical stability in chargino decays ** Ticket #358: Infinite loop in top events with pT cut in shower ** Ticket #361: Problem with duplicate 2-body modes in BSM ** Tickets #362 / #363: Crashes with baryon number violating models Particle decays in SUSY models with RPV now work correctly in the colour 8 -> 3,3,3 case. Colour reshuffling now works for RPV clusters. ** Improved Fastjet detection The configure step uses fastjet-config to make sure all header file paths are seen. ** Darwin 11 / OS X Lion A configure bug was fixed which prevented 'make check' from succeeding on OS X Lion. ** Vertex classes The specification of QED / QCD orders has been moved to the vertex constructors, to allow ThePEG consistency checks. WWHH vertices in MSSM and NMSSM were fixed. Some Leptoquark and UED vertices fixed. ** Hadronization Cleanup of obsolete code. * Herwig++-2.5.1 release: 2011-06-24 (tagged at SVN r6609) ** Example input files at 7 TeV All our example input files for LHC now have their beam energy set to 7 TeV instead of 14 TeV. ** Colour reconnection on by default The colour reconnection tunes are now the default setup. Version 2 of the tunes replaces the *-1 tunes, which had a problem with LEP event shapes. ** Run name tags Aded possibility to add a tag to the run name when running with the '-t' option. One run file can thus be run with different seeds and results stored in different output files. ** Floating point exceptions The new command line option -D enables floating point error checking. ** General improvements to WeakCurrent decays ** Remnant decayer Hardwired gluon mass was removed. ** WeakCurrentDecayConstructor Instead of specifying separate Particle1...Particle5 vectors for the decay modes, the new interface DecayModes can be filled with decay tags in the standard syntax. ** BSM: improvements to handling of vertex and model initialisation ** Powheg Higgs Option to use pT or mT as the scale in alphaS and for the factorization scale in the PDFs ** Ticket #337: Tau polarization wrong in charged Higgs decay ** Ticket #339: Colour flows in GeneralThreeBody Decayers for 3bar -> 8 3bar 1 ** Ticket #340: Crash for resonant zero-width particles ** Ticket #341: Varying scale for BSM processes The scale used is now ResonantProcessConstructor:ScaleFactor or TwoToTwoProcessConstructor:ScaleFactor multiplied by sHat. ** Ticket #346: Chargino decays Chargino decayers now automatically switch between the mesonic decays for mass differences less than 2 GeV and the normal partonic decays above 2 GeV. ** Ticket #349: Stop by default on input file errors The '--exitonerror' flag is now the default behaviour for the Herwig++ binary. To switch back to the old behaviour, '--noexitonerror' is required. ** Ticket #351: Four-body stop decays ** Tested with gcc-4.6 * Herwig++-2.5.0 release: 2011-02-08 (tagged at SVN r6274) ** Uses ThePEG-1.7.0 Herwig++ 2.5.0 requires ThePEG 1.7.0 to benefit from various improvements, particularly: handling of diffractive processes; respecting LD_LIBRARY_PATH when loading dynamic libraries, including LHAPDF; improvements to repository commands for decay modes. See ThePEG's NEWS file for more details. ** POWHEG improvements *** New POWHEG processes Simulation at NLO accuracy using the POWHEG method is now available for hadronic diboson production (pp to WW,WZ,ZZ), Higgs decays to heavy quarks, and e+e- to two jets or ttbar, including full mass dependence. *** Input file changes The input files for setting up POWHEG process simulation have been simplified. See the example files LHC-Powheg.in and TVT-Powheg.in for the improved command list. *** Structural changes The POWHEG backend in the shower code has been restructured to make future additions easier: PowhegEvolver has merged with Evolver; both the matrix element corrections and real corrections in the POWHEG scheme are implemented directly in the ME or Decayer classes. ** New processes at leading order *** Photon initiated processes We have added a matrix element for dijet production in gamma hadron collisions. *** Bottom and charm in heavy quark ME The option of bottom and charm quarks is now supported for heavy quark production in MEHeavyQuark. ** Colour reconnection The cluster hadronization model has been extended by an option to reconnect coloured constituents between clusters with a given probability. This new model is different from the colour reconnection model used in FORTRAN HERWIG, and improves the description of minimum bias and underlying event data. ** Diffractive Processes Both single and double diffractive processes are now supported in Herwig++. The Pomeron PDF is implemented using a fit to HERA data, and a pion PDF can be used to model reggeon flux. ** BSM physics *** New models We have added new BSM models, particularly ADD-type extra dimension models and the next-to-minimal supersymmetric standard model (NMSSM). Effects of leptoquarks can as well be simulated. *** Vertex additions We have added flavour changing stop interactions (stop - neutralino - charm) and gravitino interactions with particular emphasis on numerical stability for very light gravitinos. Tri-linear Higgs and Higgs-Higgs/Vector-Vector four-vertices are available as well. *** Input file changes The SUSY model can now also extract the SLHA information from the header of a Les Houches event file: replace the SLHA file name in the example input files with the LH file name. *** Structure The backend structure of the HardProcessConstructor has changed, to allow easier inclusion of new process constructors. Some 2->3 BSM scattering processes involving neutral higgs bosons are now included. The spin handling has been improved in the background. ** Shower splitting code reorganized The selection of spin structures has been decoupled from the choice of colour structure. This gives more flexibility in implementing new splittings. Selected splittings can be disabled in the input files. ** B mixing B mixing, and indirect CP violation in the B meson system are included now. ** Looptools The Looptools directory has been updated to reflect T.Hahn's Looptools 2.6. ** Contrib changes The ROOT interface has been removed as deprecated. The MCPWNLO code has temporarily been removed from the Contrib directory as a major review of this code is required. Additionally, there are various fixes to all other codes shipped in Contrib. ** DIS improvements The momentum reshuffling in DIS events has been improved. ** mu and nu beams mu, nu_e and nu_mu and their antiparticles are now available as beam particles. They are all supported in the DIS matrix elements. mu+ mu- collisions are supported in the general matrix element code for BSM models, but not yet in the hard-coded matrix elements for lepton-lepton scattering. ** Structural changes *** Inline code Inline code has been merged into the header files, .icc files were removed. *** Silent build By default, Herwig++ now builds with silent build rules. To get the old behaviour, run 'make V=1'. *** Debug level The debug level on the command line will now always have priority. *** Event counter The event counter has been simplified. *** Interpolator persistency Interpolators can now be written persistently. ** Ticket #307: Momentum violation check in BasicConsistency Added parameters AbsoluteMomentumTolerance and RelativeMomentumTolerance ** Example POWHEG input files The example input files for Powheg processes now set the NLO alpha_S correctly, and are run as part of 'make check'. ** Truncated shower A problem which lead to the truncated shower not being applied in some cases has been fixed. ** Fixes to numerical problems Minor problems with values close to zero were fixed in several locations. ** Remove duplicated calculation of event shapes An accidental duplication in the calculation of event shapes was removed, they are now only calculated once per event. Several other minor issues in the event shape calculations have also been fixed. ** MRST PDFs fixed An initialization problem in the internal MRST PDFs was fixed. ** Vertex scale choice The scale in the Vertex classes can now be zero where possible. ** Treatment of -N flag The Herwig++ main program now correctly treats the -N flag as optional. ** Numerical stability improved The numerical stability in the 'RunningMass' and 'QTildeReconstructor' classes has been improved. The stability of the boosts in the SOPTHY code for the simulation of QED radiation has been improved. The accuracy of boosts in the z-direction has been improved to fix problems with extremely high p_T partons. ** Bugfix in initial state splittings A bug in the implementation of the PDF weight in initial-state qbar -> qbar g splittings has been fixed. ** Bugfix in chargino neutralino vertices A bug in the 'chi+- chi0 W-+' and charged Higgs-sfermions vertices has been fixed. ** Remove uninitialized variables written to repository A number of uninitialised variables which were written to the repository have been initialised to zero to avoid problems on some systems. ** Fix to QED radiation in hadronic collisions The longitudinal boost of the centre-of-mass frame in hadronic collisions is correctly accounted for now in the generation of QED radiation. ** Fix to numerical problems in two-body decays Numerical problems have been fixed, which appeared in the rare case that the three-momenta of the decay products in two-body decays are zero in the rest frame of the decay particle. ** A problem with forced splittings in the Remnant was fixed. ** ME correction for W+- decays applied properly The matrix element correction for QCD radiation in W+- decays which was not being applied is now correctly used. ** Top quark decays from SLHA file The presence of top quark decay modes in SLHA files is now handled correctly. ** Exceptional shower reconstruction kinematics Additional protection against problems due to the shower reconstruction leading to partons with x>1 has been added. ** Ordering of particles in BSM processes Changes have been made to allow arbitrary ordering of the outgoing particles in BSM processes. ** Bugfixes in tau decays Two bugs involving tau decays have been fixed. The wrong masses were used in the 'KPiCurrent' class for the scalar form factors and a mistake in the selection of decay products lead to tau- --> pi0 K- being generated instead of tau- --> eta K-. ** Avoid crashes in baryon number violating processes. To avoid crashes, better protection has been introduced for the case where diquarks cannot be formed from the quarks in a baryon-number violating process. In addition, the parents of the baryon-number violating clusters have been changed to avoid problems with the conversion of the events to HepMC. ** QED radiation in W- decays A bug in the 'QEDRadiationHandler' class which resulted in no QED radiation being generated in W- decays has been fixed. ** A number of minor fixes to the SUSY models have been made. ** Partial width calculations in BSM models A fix for the direction of the incoming particle in the calculation of two-body partial widths in BSM models has been made. ** LoopTools improvements The LoopTools cache is now cleared more frequently to reduce the amount of memory used by the particle. ** Negative gluino masses are now correctly handled. ** A problem with mixing matrices which are not square has been fixed. ** Removed duplicate diagram The 'MEee2gZ2ll' class has been fixed to only include the photon exchange diagram once rather than twice as previously. ** Fix for duplicate particles in DecayConstructor A problem has been fixed which occurred if the same particle was included in the list of DecayConstructor:DecayParticles. ** Fixes for UED model vertices A number of minor problems in the vertices for the UED model have been fixed. ** Include missing symmetry factor The missing identical-particle symmetry factor in 'MEPP2GammaGamma' has been included. ** Fix floating point problem in top decays A floating point problem in the matrix element correction for top decays has been fixed. * Herwig++-2.4.2 release: 2009-12-11 (tagged at SVN r5022) ** Ticket #292: Tau decay numerical instability The momentum assignment in tau decays contained numerical instabilities which have been fixed by postponing the tau decay until after the parton shower. A new interface setting DecayHandler:Excluded is available to prevent decays in the shower step. This is enabled by default for tau only. ** Ticket #290: Missing MSSM colour structure The missing colour structure for gluino -> gluon neutralino was added. ** Ticket #294: Zero momentum in some decays Some rare phase space points lead to zero momentum in two-body decays. This has been fixed. ** Ticket #295: Stability of QED radiation for lepton collider processes The numerical stability of QED radiation momenta was improved further. ** Ticket #296: K0 oscillation vertex was wrong The oscillation from K0 to K0_L/S now takes place at the production vertex of K0. ** Ticket #289: Undefined variables in repository On some system configurations, undefined variables were written to the repository. These have been fixed. ** Fixed QED radiation for hadron processes The longitudinal boost of the centre-of-mass frame in hadronic collisions is correctly accounted for now. ** Numerical stability fixes Small fixes in RunningMass and QTildeReconstructor. ** Powheg example input files The example input files for Powheg processes now set the NLO alpha_S correctly, and are run as part of 'make check'. ** OS X builds for Snow Leopard Snow Leopard machines will now be recognized as a 64bit architecture. * Herwig++-2.4.1 release: 2009-11-19 (tagged at SVN r4932) ** Uses ThePEG-1.6.0 Herwig++ now requires ThePEG-1.6.0 to benefit from the improved helicity code there. If you have self-written vertex classes, see ThePEG's NEWS file for conversion instructions. ** Vertex improvements ThePEG's new helicity code allowed major simplification of the vertex implementations for all Standard Model and BSM physics models. ** New Transplanckian scattering model An example configuration is in LHC-TRP.in ** BSM ModelGenerator as branching ratio calculator The BSM ModelGenerator has a new switch to output the branching ratios for a given SLHA file in SLHA format, which can then be used elsewhere. ** BSM debugging: HardProcessConstructor New interface 'Excluded' to exclude certain particles from intermediate lines. ** Chargino-Neutralino-W vertex fixed ** Spin correlations are now switched on by default for all perturbative decays. ** Ticket #276: Scale choice in BSM models' HardProcessConstructor New interface 'ScaleChoice' to choose process scale between - sHat (default for colour neutral intermediates) and - transverse mass (default for all other processes). ** Ticket #287: Powheg process scale choice The default choice is now the mass of the colour-singlet system. ** Ticket #278: QED radiation for BSM Soft QED radiation is now enabled in BSM decays and all perturbative decays by default. ** Ticket #279: Full 1-loop QED radiation for Z decays Soft QED radiation in Z decays is now fully 1-loop by default. ** Ticket #280: Redirect all files to stdout This is now implemented globally. The files previously ending in -UE.out and -BSMinfo.out are now appended to the log file. They now also obey the EventGenerator:UseStdout flag. ** Ticket #270: LaTeX output updated After each run, a LaTeX file is produced that contains the full list of citations. Please include the relevant ones in publications. ** Ticket #256: Mac OS X problems An initialization problem that affected only some configurations has been identified and fixed. ** Tests directory added This contains many .in files, to exercise most matrix elements. ** Minor fixes *** Prevent rare x>1 partons in shower reconstruction. *** SUSY-LHA parameter EXTPAR can be used to set tan beta *** Improved Fastjet detection at configure time * Herwig++-2.4.0 release: 2009-09-01 (tagged at SVN r4616) ** New matrix elements We have added a built-in implementation of several new matrix elements: PP --> WW / WZ / ZZ PP --> W gamma / Z gamma PP --> VBF Higgs PP --> Higgs tt / Higgs bb e+e- --> WW / ZZ gamma gamma --> ff / WW ** Base code improvements *** Ticket #257: Remnant handling A problem with forced splittings in the Remnant was fixed. *** Ticket #264: Soft matrix element correction A problem with emissions form antiquarks was fixed. ** PDF sets *** New default set MRST LO** is the new default PDF set. LO* is also available built-in. *** Shower PDFs can be set separately from the hard process Use the 'ShowerHandler:PDF' interface. ** Parameter tunes Shower, hadronization and underlying event parameters were retuned against LEP and Tevatron data respectively. ** BSM module improvements *** Ticket #259: read error for some UED models Arbitrary ordering of outgoing lines in the process description is now possible. *** Ticket #266: branching ratio sums The warning threshold for branching ratios not summing to 1 has been relaxed. It is now a user interface parameter. *** Ticket #267: Top decay modes Top decay modes listed in SLHA files are now handled correctly. ** QED radiation *** Ticket #241: Soft QED radiation is now enabled by default *** Ticket #265: Radiation off W+ and W- is now handled correctly ** Interfaces *** Ticket #243: Fastjet Fastjet is now the only supported jet finder code. All example analyses have been converted to use Fastjet. *** KtJet and CLHEP interfaces have been removed. *** New interfaces to AcerDet and PGS available in Contrib *** MCPWnlo distributed in Contrib *** HepMC and Rivet interfaces moved to ThePEG ** Ticket #239: Inelastic cross-section for MinBias This information is now available in the ...-UE.out files. ** Technical changes *** Ticket #186 Configure now looks for ThePEG in the --prefix location first. *** Configure information Important configuration information is listed at the end of the 'configure' run and in the file 'config.thepeg'. Please provide this file in any bug reports. *** New ZERO object The ZERO object can be used to set any dimensionful quantity to zero. This avoids explicit constructs like 0.0*GeV. *** Exception specifiers removed Client code changes are needed in doinit() etc., simply remove the exception specifier after the function name. *** Ticket #263: Tau polarizations can be forced in TauDecayer * Herwig++-2.3.2 release: 2009-05-08 (tagged at SVN r4249) ** SUSY enhancements *** Ticket #245: Select inclusive / exclusive production Using the new 'HardProcessConstructor:Processes' switch options 'SingleParticleInclusive', 'TwoParticleInclusive' or 'Exclusive' *** Improved three-body decay generation Several problems were fixed, incl. tickets #249 #250 #251 Thanks to J.Tattersall and K.Rolbiecki for the stress-testing! *** Looptools fix Release 2.3.1 had broken the Looptools initialization. *** Improved warning message texts ** Ticket #237: Values of q2last can now be zero where possible. ** Ticket #240: The Herwig++ main program now correctly treats the -N flag as optional. ** Ticket #246: Extreme pT partons fixed by improving accuracy of z boosts. ** DIS Improved parton shower momentum reshuffling. ** Minimum Bias events The zero-momentum interacting particle used for bookkeeping is now labelled as a pomeron. ** User Makefile Makefile-UserModules does not enable -pedantic anymore. User's ROOT code will not compile otherwise. ** Build system Small fixes in the build system. * Herwig++-2.3.1 release: 2009-03-31 (tagged at SVN r4140) ** Initial state showers The PDF veto was wrongly applied to qbar->qbar g splittings. ** User interaction The Makefile-UserModules now includes the Herwig version number. The -N flag to 'Herwig++ run' is optional now, as was always intended. ** Contrib The contrib directory is now included in the tarball. The omission was accidental. ** Numerical accuracy Minor problems with values close to zero were fixed in several locations. ** LEP event shapes An accidental duplication was removed, they are now only calculated once per event. ** MRST PDF code Initialization problem fixed. ** Mac OS X The configure script was improved to detect libraries better. ** Libtool Updated to version 2.2.6 * Herwig++-2.3.0 release: 2008-12-02 (tagged at SVN r3939) ** Major release, with many new features and bug fixes ** Extension to lepton-hadron collisions ** Inclusion of several processes accurate at next-to-leading order in the POsitive Weight Hardest Emission Generator (POWHEG) scheme ** Inclusion of three-body decays and finite-width effects in BSM processes ** New procedure for reconstructing kinematics of the parton shower based on the colour structure of the hard scattering process ** New model for baryon decays including excited baryon multiplets ** Addition of a soft component to the multiple scattering model of the underlying event and the option to choose more than one hard scattering explicitly ** New matrix elements for DIS and e+e- processes ** New /Contrib directory added containing external modules that will hopefully be of use to some users but are not expected to be needed by most users and are not supported at the same level as the main Herwig++ code ** Minor changes to improve the physics simulation: *** IncomingPhotonEvolver added to allow the simulation of partonic processes with incoming photons in hadron collisions *** KTRapidityCut added to allow cuts on the p_T and rapidity, rather than just the p_T and pseudorapidity used in SimpleKTCut. This is now used by default for cuts on massive particles such as the $W^\pm$, $Z^0$ and Higgs bosons and the top quark *** Several changes to the decayers of B mesons both to resolve problems with the modelling of partonic decays and improve agreement with $\Upsilon(4s)$ data *** Changes to allow values other than transverse mass of final-state particles as maximum transverse momentum for radiation in parton shower either SCALUP for Les Houches events or the scale of the hard process for internally generated hard processes *** Changed defaults for intrinsic transverse momentum in hadron collisions to 1.9GeV, 2.1GeV and 2.2GeV for the Tevatron and LHC at 10 TeV and 14 TeV, respectively *** Pdfinfo object is now created in the HepMC interface However in order to support all versions of HepMC containing this feature the PDF set is not specified as not all versions contain this information *** New option of only decaying particles with lifetimes below user specified value *** New options for the cut-off in the shower and some obsolete parameters removed *** Added option of switching off certain decay modes in BSM models *** Added a Matcher for Higgs boson to allow cuts to be placed on it *** Diffractive particles deleted from default input files they were not previously used ** Technical changes: *** Some AnalysisHandler classes comparing to LEP data have been renamed e.g. MultiplicityCount becomes LEPMultiplicityCount to avoid confusion with those supplied in /Contrib for observables at the Upsilon(4s) resonance *** Reorganisation to remove the majority of the .icc files by moving inlined functions to headers in an effort to improve compile time *** Restructured the decay libraries to reduce the amount of memory allocation and de-allocation which improves run-time performance *** The switch to turn off LoopTools has been removed because LoopTools is now used by several core modules. As LoopTools does not work on 64-bit platforms with g77 this build option is not supported *** Removed support for obsolete version of HepMC supplied with CLHEP and improved the support for different units options with HepMC *** EvtGen interface has been removed until it is more stable *** Support for ROOT has been removed it was not previously used *** CKKW infrastructure has been removed from the release until a concrete implementation is available *** Default optimisation has been increased from -O2 to -O3 *** Handling of the fortran compiler has been improved mainly due to improvements in the autotools *** Use of FixedAllocator for Particle objects in ThePEG has been removed as it had no performance benefits ** Bugs fixed: *** Problems with the mother/daughter relations in the hard process and diagram selection in W+- and Z0 production in association with a hard jet *** In general matrix element code for fermion-vector to fermion-scalar where the outgoing fermion is coloured and the scalar neutral *** In the selection of diagrams in some associated squark gaugino processes *** h0->mu+mu- was being generated when h0->tau+tau- *** Normalisation in the Histogram class for non unit-weight events *** Protection against negative PDF values has been improved these can occur when using NLO PDF sets *** Lifetime for BSM particles is now automatically calculated at the same time as the width *** Hadrons containing a top quark now treated like hadrons containing BSM particles in order to support this possibility *** Several ambiguous uses of unsigned int *** Several variables that may have been used undefined *** Several memory leaks at initialisation *** The configuration now aborts if no fortran compiler is found as this is required to compile Looptools *** Several minor floating point errors that did not affect results * Herwig++-2.2.1 release: 2008-07-09 (tagged at SVN r3434) ** Ticket #181: BSM shower with a decay close to threshold Now fixed. ** Ticket #191: Split SUSY crash Improved error message. ** Ticket #192: using SCALUP as the pT veto in the shower Now implemented. ** Ticket #194: production processes of ~chi_1(2)- Fixed bug in the diagram creation. ** Removed unused particles DiffractiveParticles.in was removed, they were never produced. ** Hadronization Top quark clusters now possible, handled as 'exotic' clusters. ** Improved handling of decay modes See ThePEG-1.3.0. 'defaultparticle' command is now obsolete. ** Multi-Parton interactions Increased phase space sampling to have less than 1% uncertainty on average multiplicity. ** New libtool version gfortran is now used as default if it is available. Set FC=g77 to override this. ** Fixed several memory leaks ** Memory allocation Now using plain 'new' and 'delete'. * Herwig++-2.2.0 release: 2008-04-18 (tagged at SVN r3195) ** Major release: now as stand-alone library Herwig++ is now a stand-alone dlopen() plugin to ThePEG. No compile-time linking to Herwig code is required. The Herwig++ binary is a simple executable steering ThePEG, which can be replaced by other frontends (such as setupThePEG / runThePEG). ** New matrix elements p p -> W + jet / Z + jet / W + higgs / Z + higgs e+ e- -> Z + higgs ** Looptools Updated to version 2.2. ** Ticket #141: segfault from using 'run' command Fixed by using default allocators in Herwig++, and the Repository::cleanup() method in ThePEG 1.2.0. ** Ticket #157: broken gsl library path on some 64bit systems Paths with lib64 are correctly identified now. ** Ticket #159: p_t spectrum of ttbar pair Fixed identical particle multiplier in Sudakov form factor. ** Ticket #161: glibc segfault Rare segfault in MPI handler fixed. ** Ticket #165: rare infinite loop in four-body decay All 4-body decays without dedicated decayers now use the Mambo algorithm. A loop guard has been introduced to 3-body decays to avoid infinite retries. ** Ticket #166: rare infinite loop in top ME correction These very rare events (O(1) in 10^7) close to mass threshold now are discarded. ** Higgs width fixes ** SatPDF Optionally, the PDF extrapolation behaviour outside a given range can now be specified. ** gcc 4.3 Herwig++-2.2 compiles cleanly with the new gcc 4.3 series. * Herwig++-2.1.4 release: 2008-03-03 (tagged at SVN r3024) ** Ticket #152: Vertex positions All vertex positions of unphysical particles are set to zero until a fix for the previous nonsensical values can be implemented. * Herwig++-2.1.3 release: 2008-02-25 (tagged at SVN r2957) ** Ticket #129: Baryon decays Fix for baryon decay modes. ** Ticket #131: HepMC Check if IO_GenEvent exists ** Ticket #134: Hadronization Smearing of hadron directions in cluster decay fixed. ** Ticket #137: HepMC HepMC conversion allows specification of energy and length units to be used. ** Ticket #139: Neutral kaons Ratio K_L / K_S corrected. ** Ticket #140 / #141: Crash on shutdown Event generation from the 'read' stage or an interface now shuts down cleanly. Fixes a crash bug introduced in 2.1.1 which affected external APIs to ThePEG / Herwig. ** Ticket #146: BSM models can be disabled To save build time, some or all of the BSM models can be disabled using the '--enable-models' configure switch. ** Reorganised .model files The .model files now include the model-specific particles, too. ** Re-tune Re-tuned hadronization parameters to LEP data. ** Other fixes in QSPAC implementation in Shower; Multi-parton interaction tuning; MRST initialization * Herwig++-2.1.2 release: 2008-01-05 (tagged at SVN r2694) ** Ticket #127 Thanks to a patch submitted by Fred Stober, HepMCFile now can output event files in all supported formats. ** Ticket #128 Fixed incorrect value of pi in histogram limits. ** Other fixes in CKKW Qtilde clusterers, BSM width cut, SUSY mixing matrices. * Herwig++-2.1.1 release: 2007-12-08 (tagged at SVN r2589) ** Bug #123 Fixed a bug with particle lifetimes which resulted in nan for some vertex positions. ** Secondary scatters Fixed bug which gave intrinsic pT to secondary scatters. ** gcc abs bug detection configure now checks for and works around http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34130 ** CKKW reweighting Fixed wrong check for top quarks. ** MPIHandler Fixed call order ambiguity. * Herwig++-2.1.0 release: 2007-11-20 (tagged at SVN r2542) ** Major new release Herwig++-2.1 includes significant improvements, including multi-parton interactions, BSM physics and a new hadronic decay model, tuned to LEP data. For an overview of the changes, please see the release note arXiv:0711.3137 * Herwig++-2.0.3 release: 2007-08-21 (tagged at SVN r2101) ** Bug #90 nan in top decay ME corrections fixed. ** unlisted Colour flow fix in LightClusterDecayer ** unlisted Updated version of MultiplicityCount analysis handler. * Herwig++-2.0.2 release: 2007-07-06 (tagged at SVN r1716) ** Bug #80 Separation of HepMC from CLHEP is handled properly now. ** Bug #83 Workaround for OS X header problem ** unlisted Veto on very hard emissions from Shower. ** unlisted Detailed documentation in .in files * Herwig++-2.0.1 release: 2006-12-05 (tagged at SVN r1195) ** Bug #54 ClusterFissioner vertex calculation fixed. ** Bug #57 Crash when showering W+jet events supplied by Les Houches interface. ** Bug #59 Fix for #57 applied to LHC events. ** Bug #60 Segfault when PDF is set to NoPDF. ** Bug #61 Missing weight factor for I=0 mesons ** Bug #62 Spinor vertex calculations broken when spinor rep is not default rep. ** Bug #63 Top decay never produces tau. ** Bug #69 TTbar and HiggsJet analysis handlers fixed. ** unlisted Reorganization of Hadronization module gives 30% speedup. Thanks to Vincenzo Innocente at CMS for his profiling work! ** unlisted cleaner automake files in include/ and src/ ** unlisted Hw64 hadron selection algorithm 'abortnow' fixed. ** unlisted Top/LeptonDalitzAnalysis removed (only worked with modified code). ** unlisted removed f'_0 from particle list, decays were not handled * Herwig++-2.0.0 release: 2006-09-28 (tagged at SVN r1066) ** Full simulation of hadron collisions diff --git a/PDF/Makefile.am b/PDF/Makefile.am --- a/PDF/Makefile.am +++ b/PDF/Makefile.am @@ -1,52 +1,58 @@ EXTRA_DIST = diffraction pkglib_LTLIBRARIES = HwPomeronPDF.la HwPomeronPDF_la_SOURCES = \ PomeronPDF.cc PomeronPDF.h ## add this to produce tests of the PDFs ## HwDIFFRACTIVEPDF_la_CPPFLAGS=$(AM_CPPFLAGS) -DDIFFRACTIVEPDF_TESTING HwPomeronPDF_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 3:0:0 pkglib_LTLIBRARIES += HwReggeonPDF.la HwReggeonPDF_la_SOURCES = \ ReggeonPDF.cc ReggeonPDF.h ## add this to produce tests of the PDFs ## HwDIFFRACTIVEPDF_la_CPPFLAGS=$(AM_CPPFLAGS) -DDIFFRACTIVEPDF_TESTING HwReggeonPDF_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 3:0:0 pkglib_LTLIBRARIES += HwPomeronFlux.la HwPomeronFlux_la_SOURCES = \ PomeronFlux.h PomeronFlux.cc HwPomeronFlux_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 4:0:0 ## bound into HwShower.la noinst_LTLIBRARIES = libHwRemDecayer.la libHwRemDecayer_la_SOURCES = \ HwRemDecayer.h HwRemDecayer.cc HwRemDecayer.fh ## bound into HwShower.la noinst_LTLIBRARIES += libHwMPIPDF.la libHwMPIPDF_la_SOURCES = \ MPIPDF.h MPIPDF.cc MPIPDF.fh \ MinBiasPDF.h MinBiasPDF.cc MinBiasPDF.fh pkglib_LTLIBRARIES += HwSatPDF.la HwSatPDF_la_SOURCES = \ SatPDF.h SatPDF.cc HwSatPDF_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 6:0:0 pkglib_LTLIBRARIES += HwIncomingPhotonEvolver.la HwIncomingPhotonEvolver_la_SOURCES = \ IncomingPhotonEvolver.h IncomingPhotonEvolver.cc HwIncomingPhotonEvolver_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 6:0:0 +pkglib_LTLIBRARIES += HwSaSPhotonPDF.la +HwSaSPhotonPDF_la_SOURCES = \ +SaSGamma.f SaSPhotonPDF.cc SaSPhotonPDF.h + +HwSaSPhotonPDF_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 1:0:0 + install-data-local: for i in `find $(srcdir)/diffraction -name '*.data'`; \ do \ $(install_sh_DATA) $$i $(DESTDIR)$(pkgdatadir)/PDF/$${i#$(srcdir)/}; \ done uninstall-local: rm -rf $(DESTDIR)$(pkgdatadir)/PDF diff --git a/PDF/SaSGamma.f b/PDF/SaSGamma.f new file mode 100644 --- /dev/null +++ b/PDF/SaSGamma.f @@ -0,0 +1,718 @@ +C----------------------------------------------------------------------- +C...SaSgam version 2 - parton distributions of the photon +C...by Gerhard A. Schuler and Torbjorn Sjostrand +C...For further information see Z. Phys. C68 (1995) 607 +C...and CERN-TH/96-04 and LU TP 96-2. +C...Program last changed on 18 January 1996. +C +C!!!Note that one further call parameter - IP2 - has been added +C!!!to the SASGAM argument list compared with version 1. +C +C...The user should only need to call the SASGAM routine, +C...which in turn calls the auxiliary routines SASVMD, SASANO, +C...SASBEH and SASDIR. The package is self-contained. +C +C...One particular aspect of these parametrizations is that F2 for +C...the photon is not obtained just as the charge-squared-weighted +C...sum of quark distributions, but differ in the treatment of +C...heavy flavours (in F2 the DIS relation W2 = Q2*(1-x)/x restricts +C...the kinematics range of heavy-flavour production, but the same +C...kinematics is not relevant e.g. for jet production) and, for the +C...'MSbar' fits, in the addition of a Cgamma term related to the +C...separation of direct processes. Schematically: +C...PDF = VMD (rho, omega, phi) + anomalous (d, u, s, c, b). +C...F2 = VMD (rho, omega, phi) + anomalous (d, u, s) + +C... Bethe-Heitler (c, b) (+ Cgamma (d, u, s)). +C...The J/psi and Upsilon states have not been included in the VMD sum, +C...but low c and b masses in the other components should compensate +C...for this in a duality sense. +C +C...The calling sequence is the following: +C CALL SASGAM(ISET,X,Q2,P2,IP2,F2GM,XPDFGM) +C...with the following declaration statement: +C DIMENSION XPDFGM(-6:6) +C...and, optionally, further information in: +C COMMON/SASCOM/XPVMD(-6:6),XPANL(-6:6),XPANH(-6:6),XPBEH(-6:6), +C &XPDIR(-6:6) +C COMMON/SASVAL/VXPVMD(-6:6),VXPANL(-6:6),VXPANH(-6:6),VXPDGM(-6:6) +C...Input: ISET = 1 : SaS set 1D ('DIS', Q0 = 0.6 GeV) +C = 2 : SaS set 1M ('MSbar', Q0 = 0.6 GeV) +C = 3 : SaS set 2D ('DIS', Q0 = 2 GeV) +C = 4 : SaS set 2M ('MSbar', Q0 = 2 GeV) +C X : x value. +C Q2 : Q2 value. +C P2 : P2 value; should be = 0. for an on-shell photon. +C IP2 : scheme used to evaluate off-shell anomalous component. +C = 0 : recommended default, see = 7. +C = 1 : dipole dampening by integration; very time-consuming. +C = 2 : P_0^2 = max( Q_0^2, P^2 ) +C = 3 : P'_0^2 = Q_0^2 + P^2. +C = 4 : P_{eff} that preserves momentum sum. +C = 5 : P_{int} that preserves momentum and average +C evolution range. +C = 6 : P_{eff}, matched to P_0 in P2 -> Q2 limit. +C = 7 : P_{eff}, matched to P_0 in P2 -> Q2 limit. +C...Output: F2GM : F2 value of the photon (including factors of alpha_em). +C XPFDGM : x times parton distribution functions of the photon, +C with elements 0 = g, 1 = d, 2 = u, 3 = s, 4 = c, 5 = b, +C 6 = t (always empty!), - for antiquarks (result is same). +C...The breakdown by component is stored in the commonblock SASCOM, +C with elements as above. +C XPVMD : rho, omega, phi VMD part only of output. +C XPANL : d, u, s anomalous part only of output. +C XPANH : c, b anomalous part only of output. +C XPBEH : c, b Bethe-Heitler part only of output. +C XPDIR : Cgamma (direct contribution) part only of output. +C...The above arrays do not distinguish valence and sea contributions, +C...although this information is available internally. The additional +C...commonblock SASVAL provides the valence part only of the above +C...distributions. Array names VXPVMD, VXPANL and VXPANH correspond +C...to XPVMD, XPANL and XPANH, while XPBEH and XPDIR are valence only +C...and therefore not given doubly. VXPDGM gives the sum of valence +C...parts, and so matches XPDFGM. The difference, i.e. XPVMD-VXPVMD +C...and so on, gives the sea part only. +C + SUBROUTINE SASGAM(ISET,X,Q2,P2,IP2,F2GM,XPDFGM) +C...Purpose: to construct the F2 and parton distributions of the photon +C...by summing homogeneous (VMD) and inhomogeneous (anomalous) terms. +C...For F2, c and b are included by the Bethe-Heitler formula; +C...in the 'MSbar' scheme additionally a Cgamma term is added. + DIMENSION XPDFGM(-6:6) + COMMON/SASCOM/XPVMD(-6:6),XPANL(-6:6),XPANH(-6:6),XPBEH(-6:6), + &XPDIR(-6:6) + COMMON/SASVAL/VXPVMD(-6:6),VXPANL(-6:6),VXPANH(-6:6),VXPDGM(-6:6) + SAVE /SASCOM/,/SASVAL/ +C +C...Temporary array. + DIMENSION XPGA(-6:6), VXPGA(-6:6) + SAVE PMC,PMB,AEM,AEM2PI,ALAM,FRACU,FRHO,FOMEGA,FPHI,PMRHO,PMPHI, + $ NSTEP +C...Charm and bottom masses (low to compensate for J/psi etc.). + DATA PMC/1.3/, PMB/4.6/ +C...alpha_em and alpha_em/(2*pi). + DATA AEM/0.007297/, AEM2PI/0.0011614/ +C...Lambda value for 4 flavours. + DATA ALAM/0.20/ +C...Mixture u/(u+d), = 0.5 for incoherent and = 0.8 for coherent sum. + DATA FRACU/0.8/ +C...VMD couplings f_V**2/(4*pi). + DATA FRHO/2.20/, FOMEGA/23.6/, FPHI/18.4/ +C...Masses for rho (=omega) and phi. + DATA PMRHO/0.770/, PMPHI/1.020/ +C...Number of points in integration for IP2=1. + DATA NSTEP/100/ +C +C...Reset output. + F2GM=0. + DO 100 KFL=-6,6 + XPDFGM(KFL)=0. + XPVMD(KFL)=0. + XPANL(KFL)=0. + XPANH(KFL)=0. + XPBEH(KFL)=0. + XPDIR(KFL)=0. + VXPVMD(KFL)=0. + VXPANL(KFL)=0. + VXPANH(KFL)=0. + VXPDGM(KFL)=0. + 100 CONTINUE +C +C...Check that input sensible. + IF(ISET.LE.0.OR.ISET.GE.5) THEN + WRITE(*,*) ' FATAL ERROR: SaSgam called for unknown set' + WRITE(*,*) ' ISET = ',ISET + STOP + ENDIF + IF(X.LE.0..OR.X.GT.1.) THEN + WRITE(*,*) ' FATAL ERROR: SaSgam called for unphysical x' + WRITE(*,*) ' X = ',X + STOP + ENDIF +C +C...Set Q0 cut-off parameter as function of set used. + IF(ISET.LE.2) THEN + Q0=0.6 + ELSE + Q0=2. + ENDIF + Q02=Q0**2 +C +C...Scale choice for off-shell photon; common factors. + Q2A=Q2 + FACNOR=1. + IF(IP2.EQ.1) THEN + P2MX=P2+Q02 + Q2A=Q2+P2*Q02/MAX(Q02,Q2) + FACNOR=LOG(Q2/Q02)/NSTEP + ELSEIF(IP2.EQ.2) THEN + P2MX=MAX(P2,Q02) + ELSEIF(IP2.EQ.3) THEN + P2MX=P2+Q02 + Q2A=Q2+P2*Q02/MAX(Q02,Q2) + ELSEIF(IP2.EQ.4) THEN + P2MX=Q2*(Q02+P2)/(Q2+P2)*EXP(P2*(Q2-Q02)/ + & ((Q2+P2)*(Q02+P2))) + ELSEIF(IP2.EQ.5) THEN + P2MXA=Q2*(Q02+P2)/(Q2+P2)*EXP(P2*(Q2-Q02)/ + & ((Q2+P2)*(Q02+P2))) + P2MX=Q0*SQRT(P2MXA) + FACNOR=LOG(Q2/P2MXA)/LOG(Q2/P2MX) + ELSEIF(IP2.EQ.6) THEN + P2MX=Q2*(Q02+P2)/(Q2+P2)*EXP(P2*(Q2-Q02)/ + & ((Q2+P2)*(Q02+P2))) + P2MX=MAX(0.,1.-P2/Q2)*P2MX+MIN(1.,P2/Q2)*MAX(P2,Q02) + ELSE + P2MXA=Q2*(Q02+P2)/(Q2+P2)*EXP(P2*(Q2-Q02)/ + & ((Q2+P2)*(Q02+P2))) + P2MX=Q0*SQRT(P2MXA) + P2MXB=P2MX + P2MX=MAX(0.,1.-P2/Q2)*P2MX+MIN(1.,P2/Q2)*MAX(P2,Q02) + P2MXB=MAX(0.,1.-P2/Q2)*P2MXB+MIN(1.,P2/Q2)*P2MXA + FACNOR=LOG(Q2/P2MXA)/LOG(Q2/P2MXB) + ENDIF +C +C...Call VMD parametrization for d quark and use to give rho, omega, +C...phi. Note dipole dampening for off-shell photon. + CALL SASVMD(ISET,1,X,Q2A,P2MX,ALAM,XPGA,VXPGA) + XFVAL=VXPGA(1) + XPGA(1)=XPGA(2) + XPGA(-1)=XPGA(-2) + FACUD=AEM*(1./FRHO+1./FOMEGA)*(PMRHO**2/(PMRHO**2+P2))**2 + FACS=AEM*(1./FPHI)*(PMPHI**2/(PMPHI**2+P2))**2 + DO 110 KFL=-5,5 + XPVMD(KFL)=(FACUD+FACS)*XPGA(KFL) + 110 CONTINUE + XPVMD(1)=XPVMD(1)+(1.-FRACU)*FACUD*XFVAL + XPVMD(2)=XPVMD(2)+FRACU*FACUD*XFVAL + XPVMD(3)=XPVMD(3)+FACS*XFVAL + XPVMD(-1)=XPVMD(-1)+(1.-FRACU)*FACUD*XFVAL + XPVMD(-2)=XPVMD(-2)+FRACU*FACUD*XFVAL + XPVMD(-3)=XPVMD(-3)+FACS*XFVAL + VXPVMD(1)=(1.-FRACU)*FACUD*XFVAL + VXPVMD(2)=FRACU*FACUD*XFVAL + VXPVMD(3)=FACS*XFVAL + VXPVMD(-1)=(1.-FRACU)*FACUD*XFVAL + VXPVMD(-2)=FRACU*FACUD*XFVAL + VXPVMD(-3)=FACS*XFVAL +C + IF(IP2.NE.1) THEN +C...Anomalous parametrizations for different strategies +C...for off-shell photons; except full integration. +C +C...Call anomalous parametrization for d + u + s. + CALL SASANO(-3,X,Q2A,P2MX,ALAM,XPGA,VXPGA) + DO 120 KFL=-5,5 + XPANL(KFL)=FACNOR*XPGA(KFL) + VXPANL(KFL)=FACNOR*VXPGA(KFL) + 120 CONTINUE +C +C...Call anomalous parametrization for c and b. + CALL SASANO(4,X,Q2A,P2MX,ALAM,XPGA,VXPGA) + DO 130 KFL=-5,5 + XPANH(KFL)=FACNOR*XPGA(KFL) + VXPANH(KFL)=FACNOR*VXPGA(KFL) + 130 CONTINUE + CALL SASANO(5,X,Q2A,P2MX,ALAM,XPGA,VXPGA) + DO 140 KFL=-5,5 + XPANH(KFL)=XPANH(KFL)+FACNOR*XPGA(KFL) + VXPANH(KFL)=VXPANH(KFL)+FACNOR*VXPGA(KFL) + 140 CONTINUE +C + ELSE +C...Special option: loop over flavours and integrate over k2. + DO 170 KF=1,5 + DO 160 ISTEP=1,NSTEP + Q2STEP=Q02*(Q2/Q02)**((ISTEP-0.5)/NSTEP) + IF((KF.EQ.4.AND.Q2STEP.LT.PMC**2).OR. + & (KF.EQ.5.AND.Q2STEP.LT.PMB**2)) GOTO 160 + CALL SASVMD(0,KF,X,Q2,Q2STEP,ALAM,XPGA,VXPGA) + FACQ=AEM2PI*(Q2STEP/(Q2STEP+P2))**2*FACNOR + IF(MOD(KF,2).EQ.0) FACQ=FACQ*(8./9.) + IF(MOD(KF,2).EQ.1) FACQ=FACQ*(2./9.) + DO 150 KFL=-5,5 + IF(KF.LE.3) XPANL(KFL)=XPANL(KFL)+FACQ*XPGA(KFL) + IF(KF.GE.4) XPANH(KFL)=XPANH(KFL)+FACQ*XPGA(KFL) + IF(KF.LE.3) VXPANL(KFL)=VXPANL(KFL)+FACQ*VXPGA(KFL) + IF(KF.GE.4) VXPANH(KFL)=VXPANH(KFL)+FACQ*VXPGA(KFL) + 150 CONTINUE + 160 CONTINUE + 170 CONTINUE + ENDIF +C +C...Call Bethe-Heitler term expression for charm and bottom. + CALL SASBEH(4,X,Q2,P2,PMC**2,XPBH) + XPBEH(4)=XPBH + XPBEH(-4)=XPBH + CALL SASBEH(5,X,Q2,P2,PMB**2,XPBH) + XPBEH(5)=XPBH + XPBEH(-5)=XPBH +C +C...For MSbar subtraction call C^gamma term expression for d, u, s. + IF(ISET.EQ.2.OR.ISET.EQ.4) THEN + CALL SASDIR(X,Q2,P2,Q02,XPGA) + DO 180 KFL=-5,5 + XPDIR(KFL)=XPGA(KFL) + 180 CONTINUE + ENDIF +C +C...Store result in output array. + DO 190 KFL=-5,5 + CHSQ=1./9. + IF(IABS(KFL).EQ.2.OR.IABS(KFL).EQ.4) CHSQ=4./9. + XPF2=XPVMD(KFL)+XPANL(KFL)+XPBEH(KFL)+XPDIR(KFL) + IF(KFL.NE.0) F2GM=F2GM+CHSQ*XPF2 + XPDFGM(KFL)=XPVMD(KFL)+XPANL(KFL)+XPANH(KFL) + VXPDGM(KFL)=VXPVMD(KFL)+VXPANL(KFL)+VXPANH(KFL) + 190 CONTINUE +C + END +C +C********************************************************************* +C + SUBROUTINE SASVMD(ISET,KF,X,Q2,P2,ALAM,XPGA,VXPGA) +C...Purpose: to evaluate the VMD parton distributions of a photon, +C...evolved homogeneously from an initial scale P2 to Q2. +C...Does not include dipole suppression factor. +C...ISET is parton distribution set, see above; +C...additionally ISET=0 is used for the evolution of an anomalous photon +C...which branched at a scale P2 and then evolved homogeneously to Q2. +C...ALAM is the 4-flavour Lambda, which is automatically converted +C...to 3- and 5-flavour equivalents as needed. + DIMENSION XPGA(-6:6), VXPGA(-6:6) + SAVE PMC,PMB + DATA PMC/1.3/, PMB/4.6/ +C +C...Reset output. + DO 100 KFL=-6,6 + XPGA(KFL)=0. + VXPGA(KFL)=0. + 100 CONTINUE + KFA=IABS(KF) +C +C...Calculate Lambda; protect against unphysical Q2 and P2 input. + ALAM3=ALAM*(PMC/ALAM)**(2./27.) + ALAM5=ALAM*(ALAM/PMB)**(2./23.) + P2EFF=MAX(P2,1.2*ALAM3**2) + IF(KFA.EQ.4) P2EFF=MAX(P2EFF,PMC**2) + IF(KFA.EQ.5) P2EFF=MAX(P2EFF,PMB**2) + Q2EFF=MAX(Q2,P2EFF) +C +C...Find number of flavours at lower and upper scale. + NFP=4 + IF(P2EFF.LT.PMC**2) NFP=3 + IF(P2EFF.GT.PMB**2) NFP=5 + NFQ=4 + IF(Q2EFF.LT.PMC**2) NFQ=3 + IF(Q2EFF.GT.PMB**2) NFQ=5 +C +C...Find s as sum of 3-, 4- and 5-flavour parts. + S=0. + IF(NFP.EQ.3) THEN + Q2DIV=PMC**2 + IF(NFQ.EQ.3) Q2DIV=Q2EFF + S=S+(6./27.)*LOG(LOG(Q2DIV/ALAM3**2)/LOG(P2EFF/ALAM3**2)) + ENDIF + IF(NFP.LE.4.AND.NFQ.GE.4) THEN + P2DIV=P2EFF + IF(NFP.EQ.3) P2DIV=PMC**2 + Q2DIV=Q2EFF + IF(NFQ.EQ.5) Q2DIV=PMB**2 + S=S+(6./25.)*LOG(LOG(Q2DIV/ALAM**2)/LOG(P2DIV/ALAM**2)) + ENDIF + IF(NFQ.EQ.5) THEN + P2DIV=PMB**2 + IF(NFP.EQ.5) P2DIV=P2EFF + S=S+(6./23.)*LOG(LOG(Q2EFF/ALAM5**2)/LOG(P2DIV/ALAM5**2)) + ENDIF +C +C...Calculate frequent combinations of x and s. + X1=1.-X + XL=-LOG(X) + S2=S**2 + S3=S**3 + S4=S**4 +C +C...Evaluate homogeneous anomalous parton distributions below or +C...above threshold. + IF(ISET.EQ.0) THEN + IF(Q2.LE.P2.OR.(KFA.EQ.4.AND.Q2.LT.PMC**2).OR. + &(KFA.EQ.5.AND.Q2.LT.PMB**2)) THEN + XVAL = X * 1.5 * (X**2+X1**2) + XGLU = 0. + XSEA = 0. + ELSE + XVAL = (1.5/(1.-0.197*S+4.33*S2)*X**2 + (1.5+2.10*S)/ + & (1.+3.29*S)*X1**2 + 5.23*S/(1.+1.17*S+19.9*S3)*X*X1) * + & X**(1./(1.+1.5*S)) * (1.-X**2)**(2.667*S) + XGLU = 4.*S/(1.+4.76*S+15.2*S2+29.3*S4) * + & X**(-2.03*S/(1.+2.44*S)) * (X1*XL)**(1.333*S) * + & ((4.*X**2+7.*X+4.)*X1/3. - 2.*X*(1.+X)*XL) + XSEA = S2/(1.+4.54*S+8.19*S2+8.05*S3) * + & X**(-1.54*S/(1.+1.29*S)) * X1**(2.667*S) * + & ((8.-73.*X+62.*X**2)*X1/9. + (3.-8.*X**2/3.)*X*XL + + & (2.*X-1.)*X*XL**2) + ENDIF +C +C...Evaluate set 1D parton distributions below or above threshold. + ELSEIF(ISET.EQ.1) THEN + IF(Q2.LE.P2.OR.(KFA.EQ.4.AND.Q2.LT.PMC**2).OR. + &(KFA.EQ.5.AND.Q2.LT.PMB**2)) THEN + XVAL = 1.294 * X**0.80 * X1**0.76 + XGLU = 1.273 * X**0.40 * X1**1.76 + XSEA = 0.100 * X1**3.76 + ELSE + XVAL = 1.294/(1.+0.252*S+3.079*S2) * X**(0.80-0.13*S) * + & X1**(0.76+0.667*S) * XL**(2.*S) + XGLU = 7.90*S/(1.+5.50*S) * EXP(-5.16*S) * + & X**(-1.90*S/(1.+3.60*S)) * X1**1.30 * XL**(0.50+3.*S) + + & 1.273 * EXP(-10.*S) * X**0.40 * X1**(1.76+3.*S) + XSEA = (0.1-0.397*S2+1.121*S3)/(1.+5.61*S2+5.26*S3) * + & X**(-7.32*S2/(1.+10.3*S2)) * + & X1**((3.76+15.*S+12.*S2)/(1.+4.*S)) + XSEA0 = 0.100 * X1**3.76 + ENDIF +C +C...Evaluate set 1M parton distributions below or above threshold. + ELSEIF(ISET.EQ.2) THEN + IF(Q2.LE.P2.OR.(KFA.EQ.4.AND.Q2.LT.PMC**2).OR. + &(KFA.EQ.5.AND.Q2.LT.PMB**2)) THEN + XVAL = 0.8477 * X**0.51 * X1**1.37 + XGLU = 3.42 * X**0.255 * X1**2.37 + XSEA = 0. + ELSE + XVAL = 0.8477/(1.+1.37*S+2.18*S2+3.73*S3) * X**(0.51+0.21*S) + & * X1**1.37 * XL**(2.667*S) + XGLU = 24.*S/(1.+9.6*S+0.92*S2+14.34*S3) * EXP(-5.94*S) * + & X**((-0.013-1.80*S)/(1.+3.14*S)) * X1**(2.37+0.4*S) * + & XL**(0.32+3.6*S) + 3.42 * EXP(-12.*S) * X**0.255 * + & X1**(2.37+3.*S) + XSEA = 0.842*S/(1.+21.3*S-33.2*S2+229.*S3) * + & X**((0.13-2.90*S)/(1.+5.44*S)) * X1**(3.45+0.5*S) * + & XL**(2.8*S) + XSEA0 = 0. + ENDIF +C +C...Evaluate set 2D parton distributions below or above threshold. + ELSEIF(ISET.EQ.3) THEN + IF(Q2.LE.P2.OR.(KFA.EQ.4.AND.Q2.LT.PMC**2).OR. + &(KFA.EQ.5.AND.Q2.LT.PMB**2)) THEN + XVAL = X**0.46 * X1**0.64 + 0.76 * X + XGLU = 1.925 * X1**2 + XSEA = 0.242 * X1**4 + ELSE + XVAL = (1.+0.186*S)/(1.-0.209*S+1.495*S2) * X**(0.46+0.25*S) + & * X1**((0.64+0.14*S+5.*S2)/(1.+S)) * XL**(1.9*S) + + & (0.76+0.4*S) * X * X1**(2.667*S) + XGLU = (1.925+5.55*S+147.*S2)/(1.-3.59*S+3.32*S2) * + & EXP(-18.67*S) * X**((-5.81*S-5.34*S2)/(1.+29.*S-4.26*S2)) + & * X1**((2.-5.9*S)/(1.+1.7*S)) * XL**(9.3*S/(1.+1.7*S)) + XSEA = (0.242-0.252*S+1.19*S2)/(1.-0.607*S+21.95*S2) * + & X**(-12.1*S2/(1.+2.62*S+16.7*S2)) * X1**4 * XL**S + XSEA0 = 0.242 * X1**4 + ENDIF +C +C...Evaluate set 2M parton distributions below or above threshold. + ELSEIF(ISET.EQ.4) THEN + IF(Q2.LE.P2.OR.(KFA.EQ.4.AND.Q2.LT.PMC**2).OR. + &(KFA.EQ.5.AND.Q2.LT.PMB**2)) THEN + XVAL = 1.168 * X**0.50 * X1**2.60 + 0.965 * X + XGLU = 1.808 * X1**2 + XSEA = 0.209 * X1**4 + ELSE + XVAL = (1.168+1.771*S+29.35*S2) * EXP(-5.776*S) * + & X**((0.5+0.208*S)/(1.-0.794*S+1.516*S2)) * + & X1**((2.6+7.6*S)/(1.+5.*S)) * XL**(5.15*S/(1.+2.*S)) + + & (0.965+22.35*S)/(1.+18.4*S) * X * X1**(2.667*S) + XGLU = (1.808+29.9*S)/(1.+26.4*S) * EXP(-5.28*S) * + & X**((-5.35*S-10.11*S2)/(1.+31.71*S)) * + & X1**((2.-7.3*S+4.*S2)/(1.+2.5*S)) * + & XL**(10.9*S/(1.+2.5*S)) + XSEA = (0.209+0.644*S2)/(1.+0.319*S+17.6*S2) * + & X**((-0.373*S-7.71*S2)/(1.+0.815*S+11.0*S2)) * + & X1**(4.+S) * XL**(0.45*S) + XSEA0 = 0.209 * X1**4 + ENDIF + ENDIF +C +C...Threshold factors for c and b sea. + SLL=LOG(LOG(Q2EFF/ALAM**2)/LOG(P2EFF/ALAM**2)) + XCHM=0. + IF(Q2.GT.PMC**2.AND.Q2.GT.1.001*P2EFF) THEN + SCH=MAX(0.,LOG(LOG(PMC**2/ALAM**2)/LOG(P2EFF/ALAM**2))) + IF(ISET.EQ.0) THEN + XCHM=XSEA*(1.-(SCH/SLL)**2) + ELSE + XCHM=MAX(0.,XSEA-XSEA0*X1**(2.667*S))*(1.-SCH/SLL) + ENDIF + ENDIF + XBOT=0. + IF(Q2.GT.PMB**2.AND.Q2.GT.1.001*P2EFF) THEN + SBT=MAX(0.,LOG(LOG(PMB**2/ALAM**2)/LOG(P2EFF/ALAM**2))) + IF(ISET.EQ.0) THEN + XBOT=XSEA*(1.-(SBT/SLL)**2) + ELSE + XBOT=MAX(0.,XSEA-XSEA0*X1**(2.667*S))*(1.-SBT/SLL) + ENDIF + ENDIF +C +C...Fill parton distributions. + XPGA(0)=XGLU + XPGA(1)=XSEA + XPGA(2)=XSEA + XPGA(3)=XSEA + XPGA(4)=XCHM + XPGA(5)=XBOT + XPGA(KFA)=XPGA(KFA)+XVAL + DO 110 KFL=1,5 + XPGA(-KFL)=XPGA(KFL) + 110 CONTINUE + VXPGA(KFA)=XVAL + VXPGA(-KFA)=XVAL +C + END +C +C********************************************************************* +C + SUBROUTINE SASANO(KF,X,Q2,P2,ALAM,XPGA,VXPGA) +C...Purpose: to evaluate the parton distributions of the anomalous +C...photon, inhomogeneously evolved from a scale P2 (where it vanishes) +C...to Q2. +C...KF=0 gives the sum over (up to) 5 flavours, +C...KF<0 limits to flavours up to abs(KF), +C...KF>0 is for flavour KF only. +C...ALAM is the 4-flavour Lambda, which is automatically converted +C...to 3- and 5-flavour equivalents as needed. + DIMENSION XPGA(-6:6), VXPGA(-6:6), ALAMSQ(3:5) + SAVE PMC,PMB,AEM2PI + DATA PMC/1.3/, PMB/4.6/, AEM2PI/0.0011614/ +C +C...Reset output. + DO 100 KFL=-6,6 + XPGA(KFL)=0. + VXPGA(KFL)=0. + 100 CONTINUE + IF(Q2.LE.P2) RETURN + KFA=IABS(KF) +C +C...Calculate Lambda; protect against unphysical Q2 and P2 input. + ALAMSQ(3)=(ALAM*(PMC/ALAM)**(2./27.))**2 + ALAMSQ(4)=ALAM**2 + ALAMSQ(5)=(ALAM*(ALAM/PMB)**(2./23.))**2 + P2EFF=MAX(P2,1.2*ALAMSQ(3)) + IF(KF.EQ.4) P2EFF=MAX(P2EFF,PMC**2) + IF(KF.EQ.5) P2EFF=MAX(P2EFF,PMB**2) + Q2EFF=MAX(Q2,P2EFF) + XL=-LOG(X) +C +C...Find number of flavours at lower and upper scale. + NFP=4 + IF(P2EFF.LT.PMC**2) NFP=3 + IF(P2EFF.GT.PMB**2) NFP=5 + NFQ=4 + IF(Q2EFF.LT.PMC**2) NFQ=3 + IF(Q2EFF.GT.PMB**2) NFQ=5 +C +C...Define range of flavour loop. + IF(KF.EQ.0) THEN + KFLMN=1 + KFLMX=5 + ELSEIF(KF.LT.0) THEN + KFLMN=1 + KFLMX=KFA + ELSE + KFLMN=KFA + KFLMX=KFA + ENDIF +C +C...Loop over flavours the photon can branch into. + DO 110 KFL=KFLMN,KFLMX +C +C...Light flavours: calculate t range and (approximate) s range. + IF(KFL.LE.3.AND.(KFL.EQ.1.OR.KFL.EQ.KF)) THEN + TDIFF=LOG(Q2EFF/P2EFF) + S=(6./(33.-2.*NFQ))*LOG(LOG(Q2EFF/ALAMSQ(NFQ))/ + & LOG(P2EFF/ALAMSQ(NFQ))) + IF(NFQ.GT.NFP) THEN + Q2DIV=PMB**2 + IF(NFQ.EQ.4) Q2DIV=PMC**2 + SNFQ=(6./(33.-2.*NFQ))*LOG(LOG(Q2DIV/ALAMSQ(NFQ))/ + & LOG(P2EFF/ALAMSQ(NFQ))) + SNFP=(6./(33.-2.*(NFQ-1)))*LOG(LOG(Q2DIV/ALAMSQ(NFQ-1))/ + & LOG(P2EFF/ALAMSQ(NFQ-1))) + S=S+(LOG(Q2DIV/P2EFF)/LOG(Q2EFF/P2EFF))*(SNFP-SNFQ) + ENDIF + IF(NFQ.EQ.5.AND.NFP.EQ.3) THEN + Q2DIV=PMC**2 + SNF4=(6./(33.-2.*4))*LOG(LOG(Q2DIV/ALAMSQ(4))/ + & LOG(P2EFF/ALAMSQ(4))) + SNF3=(6./(33.-2.*3))*LOG(LOG(Q2DIV/ALAMSQ(3))/ + & LOG(P2EFF/ALAMSQ(3))) + S=S+(LOG(Q2DIV/P2EFF)/LOG(Q2EFF/P2EFF))*(SNF3-SNF4) + ENDIF +C +C...u and s quark do not need a separate treatment when d has been done. + ELSEIF(KFL.EQ.2.OR.KFL.EQ.3) THEN +C +C...Charm: as above, but only include range above c threshold. + ELSEIF(KFL.EQ.4) THEN + IF(Q2.LE.PMC**2) GOTO 110 + P2EFF=MAX(P2EFF,PMC**2) + Q2EFF=MAX(Q2EFF,P2EFF) + TDIFF=LOG(Q2EFF/P2EFF) + S=(6./(33.-2.*NFQ))*LOG(LOG(Q2EFF/ALAMSQ(NFQ))/ + & LOG(P2EFF/ALAMSQ(NFQ))) + IF(NFQ.EQ.5.AND.NFP.EQ.4) THEN + Q2DIV=PMB**2 + SNFQ=(6./(33.-2.*NFQ))*LOG(LOG(Q2DIV/ALAMSQ(NFQ))/ + & LOG(P2EFF/ALAMSQ(NFQ))) + SNFP=(6./(33.-2.*(NFQ-1)))*LOG(LOG(Q2DIV/ALAMSQ(NFQ-1))/ + & LOG(P2EFF/ALAMSQ(NFQ-1))) + S=S+(LOG(Q2DIV/P2EFF)/LOG(Q2EFF/P2EFF))*(SNFP-SNFQ) + ENDIF +C +C...Bottom: as above, but only include range above b threshold. + ELSEIF(KFL.EQ.5) THEN + IF(Q2.LE.PMB**2) GOTO 110 + P2EFF=MAX(P2EFF,PMB**2) + Q2EFF=MAX(Q2,P2EFF) + TDIFF=LOG(Q2EFF/P2EFF) + S=(6./(33.-2.*NFQ))*LOG(LOG(Q2EFF/ALAMSQ(NFQ))/ + & LOG(P2EFF/ALAMSQ(NFQ))) + ENDIF +C +C...Evaluate flavour-dependent prefactor (charge^2 etc.). + CHSQ=1./9. + IF(KFL.EQ.2.OR.KFL.EQ.4) CHSQ=4./9. + FAC=AEM2PI*2.*CHSQ*TDIFF +C +C...Evaluate parton distributions (normalized to unit momentum sum). + IF(KFL.EQ.1.OR.KFL.EQ.4.OR.KFL.EQ.5.OR.KFL.EQ.KF) THEN + XVAL= ((1.5+2.49*S+26.9*S**2)/(1.+32.3*S**2)*X**2 + + & (1.5-0.49*S+7.83*S**2)/(1.+7.68*S**2)*(1.-X)**2 + + & 1.5*S/(1.-3.2*S+7.*S**2)*X*(1.-X)) * + & X**(1./(1.+0.58*S)) * (1.-X**2)**(2.5*S/(1.+10.*S)) + XGLU= 2.*S/(1.+4.*S+7.*S**2) * + & X**(-1.67*S/(1.+2.*S)) * (1.-X**2)**(1.2*S) * + & ((4.*X**2+7.*X+4.)*(1.-X)/3. - 2.*X*(1.+X)*XL) + XSEA= 0.333*S**2/(1.+4.90*S+4.69*S**2+21.4*S**3) * + & X**(-1.18*S/(1.+1.22*S)) * (1.-X)**(1.2*S) * + & ((8.-73.*X+62.*X**2)*(1.-X)/9. + (3.-8.*X**2/3.)*X*XL + + & (2.*X-1.)*X*XL**2) +C +C...Threshold factors for c and b sea. + SLL=LOG(LOG(Q2EFF/ALAM**2)/LOG(P2EFF/ALAM**2)) + XCHM=0. + IF(Q2.GT.PMC**2.AND.Q2.GT.1.001*P2EFF) THEN + SCH=MAX(0.,LOG(LOG(PMC**2/ALAM**2)/LOG(P2EFF/ALAM**2))) + XCHM=XSEA*(1.-(SCH/SLL)**3) + ENDIF + XBOT=0. + IF(Q2.GT.PMB**2.AND.Q2.GT.1.001*P2EFF) THEN + SBT=MAX(0.,LOG(LOG(PMB**2/ALAM**2)/LOG(P2EFF/ALAM**2))) + XBOT=XSEA*(1.-(SBT/SLL)**3) + ENDIF + ENDIF +C +C...Add contribution of each valence flavour. + XPGA(0)=XPGA(0)+FAC*XGLU + XPGA(1)=XPGA(1)+FAC*XSEA + XPGA(2)=XPGA(2)+FAC*XSEA + XPGA(3)=XPGA(3)+FAC*XSEA + XPGA(4)=XPGA(4)+FAC*XCHM + XPGA(5)=XPGA(5)+FAC*XBOT + XPGA(KFL)=XPGA(KFL)+FAC*XVAL + VXPGA(KFL)=VXPGA(KFL)+FAC*XVAL + 110 CONTINUE + DO 120 KFL=1,5 + XPGA(-KFL)=XPGA(KFL) + VXPGA(-KFL)=VXPGA(KFL) + 120 CONTINUE +C + END +C +C********************************************************************* +C + SUBROUTINE SASBEH(KF,X,Q2,P2,PM2,XPBH) +C...Purpose: to evaluate the Bethe-Heitler cross section for +C...heavy flavour production. + SAVE AEM2PI + DATA AEM2PI/0.0011614/ +C +C...Reset output. + XPBH=0. + SIGBH=0. +C +C...Check kinematics limits. + IF(X.GE.Q2/(4.*PM2+Q2+P2)) RETURN + W2=Q2*(1.-X)/X-P2 + BETA2=1.-4.*PM2/W2 + IF(BETA2.LT.1E-10) RETURN + BETA=SQRT(BETA2) + RMQ=4.*PM2/Q2 +C +C...Simple case: P2 = 0. + IF(P2.LT.1E-4) THEN + IF(BETA.LT.0.99) THEN + XBL=LOG((1.+BETA)/(1.-BETA)) + ELSE + XBL=LOG((1.+BETA)**2*W2/(4.*PM2)) + ENDIF + SIGBH=BETA*(8.*X*(1.-X)-1.-RMQ*X*(1.-X))+ + & XBL*(X**2+(1.-X)**2+RMQ*X*(1.-3.*X)-0.5*RMQ**2*X**2) +C +C...Complicated case: P2 > 0, based on approximation of +C...C.T. Hill and G.G. Ross, Nucl. Phys. B148 (1979) 373 + ELSE + RPQ=1.-4.*X**2*P2/Q2 + IF(RPQ.GT.1E-10) THEN + RPBE=SQRT(RPQ*BETA2) + IF(RPBE.LT.0.99) THEN + XBL=LOG((1.+RPBE)/(1.-RPBE)) + XBI=2.*RPBE/(1.-RPBE**2) + ELSE + RPBESN=4.*PM2/W2+(4.*X**2*P2/Q2)*BETA2 + XBL=LOG((1.+RPBE)**2/RPBESN) + XBI=2.*RPBE/RPBESN + ENDIF + SIGBH=BETA*(6.*X*(1.-X)-1.)+ + & XBL*(X**2+(1.-X)**2+RMQ*X*(1.-3.*X)-0.5*RMQ**2*X**2)+ + & XBI*(2.*X/Q2)*(PM2*X*(2.-RMQ)-P2*X) + ENDIF + ENDIF +C +C...Multiply by charge-squared etc. to get parton distribution. + CHSQ=1./9. + IF(IABS(KF).EQ.2.OR.IABS(KF).EQ.4) CHSQ=4./9. + XPBH=3.*CHSQ*AEM2PI*X*SIGBH +C + END +C +C********************************************************************* +C + SUBROUTINE SASDIR(X,Q2,P2,Q02,XPGA) +C...Purpose: to evaluate the direct contribution, i.e. the C^gamma term, +C...as needed in MSbar parametrizations. + DIMENSION XPGA(-6:6) + SAVE AEM2PI + DATA AEM2PI/0.0011614/ +C +C...Reset output. + DO 100 KFL=-6,6 + XPGA(KFL)=0. + 100 CONTINUE +C +C...Evaluate common x-dependent expression. + XTMP = (X**2+(1.-X)**2) * (-LOG(X)) - 1. + CGAM = 3.*AEM2PI*X * (XTMP*(1.+P2/(P2+Q02)) + 6.*X*(1.-X)) +C +C...d, u, s part by simple charge factor. + XPGA(1)=(1./9.)*CGAM + XPGA(2)=(4./9.)*CGAM + XPGA(3)=(1./9.)*CGAM +C +C...Also fill for antiquarks. + DO 110 KF=1,5 + XPGA(-KF)=XPGA(KF) + 110 CONTINUE +C + END diff --git a/PDF/SaSPhotonPDF.cc.in b/PDF/SaSPhotonPDF.cc.in new file mode 100644 --- /dev/null +++ b/PDF/SaSPhotonPDF.cc.in @@ -0,0 +1,180 @@ +// -*- C++ -*- +// +// This is the implementation of the non-inlined, non-templated member +// functions of the SaSPhotonPDF class. +// + +#include "SaSPhotonPDF.h" +#include "ThePEG/Interface/ClassDocumentation.h" +#include "ThePEG/EventRecord/Particle.h" +#include "ThePEG/Repository/UseRandom.h" +#include "ThePEG/Repository/EventGenerator.h" +#include "ThePEG/Utilities/DescribeClass.h" +#include "ThePEG/Interface/Switch.h" +#include "ThePEG/Persistency/PersistentOStream.h" +#include "ThePEG/Persistency/PersistentIStream.h" +#include "ThePEG/PDT/ParticleData.h" +#include "ThePEG/PDT/EnumParticles.h" + +using namespace Herwig; + +/* Define to a macro mangling the given C identifier (in lower and upper + case), which must not contain underscores, for linking with Fortran. */ +#undef FC_FUNC + +extern "C" { + + #define SASGAM_F77 FC_FUNC(sasgam,SASGAM) + void SASGAM_F77(int *,float *,float *,float *,int *,float *,float *); + +} + +bool SaSPhotonPDF::canHandleParticle(tcPDPtr particle) const { + // only the photon can be handled + return ( particle->id() == ParticleID::gamma ); +} + +cPDVector SaSPhotonPDF::partons(tcPDPtr particle) const { + // All standard partons can be extracted. + cPDVector ret; + if ( canHandleParticle(particle) ) { + ret.push_back(getParticleData(ParticleID::g)); + for ( int i = 1; i <= 5; ++i ) { + ret.push_back(getParticleData(i)); + ret.push_back(getParticleData(-i)); + } + } + return ret; +} + +double SaSPhotonPDF::xfl(tcPDPtr, tcPDPtr parton, Energy2 partonScale, + double l, Energy2 particleScale) const { + float x = exp(-l); + float q2 = partonScale/GeV2; + float p2 = particleScale/GeV2; + float f2gm=0.; + float xpdf[13]; + int iloc = parton->id()!=ParticleID::g ? 6+parton->id() : 6; + assert(x>=0. && x<=1.); + SASGAM_F77(&iset_,&x,&q2,&p2,&ip_,&f2gm,xpdf); + // cerr << "testing " << partonScale/GeV2 << " " << particleScale/GeV2 << " " << x << "\n"; + // for(unsigned int ix=0;ix<13;++ix) + // cerr << ix << " " << xpdf[ix] << "\n"; + // cerr << "testing " << parton->PDGName() << " " << iloc << "\n"; + return xpdf[iloc]; +} + +double SaSPhotonPDF::xfvl(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, + double l, Energy2 particleScale) const { + if(parton->id()==ParticleID::g) + return 0.; + else + return xfl(particle,parton,partonScale,l,particleScale); +} + +IBPtr SaSPhotonPDF::clone() const { + return new_ptr(*this); +} + +IBPtr SaSPhotonPDF::fullclone() const { + return new_ptr(*this); +} + +void SaSPhotonPDF::persistentOutput(PersistentOStream & os) const { + os << iset_ << ip_; +} + +void SaSPhotonPDF::persistentInput(PersistentIStream & is, int) { + is >> iset_ >> ip_; +} + + +// The following static variable is needed for the type +// description system in ThePEG. +DescribeClass +describeHerwigSaSPhotonPDF("Herwig::SaSPhotonPDF", "HwSaSPhotonPDF.so"); + +void SaSPhotonPDF::Init() { + + static ClassDocumentation documentation + ("The SaSPhotonPDF class interfaces to the photon PDFs of Schuler and Sjostrand", + "The photon PDF of \\cite{Schuler:1995fk} was used.", + "\bibitem{Schuler:1995fk}\n" + "G.~A.~Schuler and T.~Sjostrand,\n" + "%``Low and high mass components of the photon distribution functions,''\n" + "Z.\\ Phys.\\ C {\bf 68} (1995) 607\n" + "doi:10.1007/BF01565260\n" + "[hep-ph/9503384].\n" + "%%CITATION = doi:10.1007/BF01565260;\n"); + + static Switch interfaceIset + ("Iset", + "The choice of PDF set", + &SaSPhotonPDF::iset_, 2, false, false); + static SwitchOption interfaceIset1D + (interfaceIset, + "1D", + "SaS set 1D ('DIS', Q0 = 0.6 GeV)", + 1); + static SwitchOption interfaceIset1M + (interfaceIset, + "1M", + "SaS set 1M ('MSbar', Q0 = 0.6 GeV)", + 2); + static SwitchOption interfaceIset2D + (interfaceIset, + "2D", + "SaS set 2D ('DIS', Q0 = 2 GeV)", + 3); + static SwitchOption interfaceIset2M + (interfaceIset, + "2M", + "SaS set 2M ('MSbar', Q0 = 2 GeV)", + 4); + + static Switch interfaceIP2 + ("IP2", + "scheme used to evaluate off-shell anomalous component.", + &SaSPhotonPDF::ip_, 0, false, false); + static SwitchOption interfaceIP20 + (interfaceIP2, + "0", + "recommended default, see = 7.", + 0); + static SwitchOption interfaceIP21 + (interfaceIP2, + "1", + "dipole dampening by integration; very time-consuming.", + 1); + static SwitchOption interfaceIP22 + (interfaceIP2, + "2", + "P_0^2 = max( Q_0^2, P^2 )", + 2); + static SwitchOption interfaceIP23 + (interfaceIP2, + "3", + "P'_0^2 = Q_0^2 + P^2.", + 3); + static SwitchOption interfaceIP24 + (interfaceIP2, + "4", + "P_{eff} that preserves momentum sum.", + 4); + static SwitchOption interfaceIP25 + (interfaceIP2, + "5", + "P_{int} that preserves momentum and average evolution range.", + 5); + static SwitchOption interfaceIP26 + (interfaceIP2, + "6", + "P_{eff}, matched to P_0 in P2 -> Q2 limit.", + 6); + static SwitchOption interfaceIP27 + (interfaceIP2, + "7", + "P_{eff}, matched to P_0 in P2 -> Q2 limit.", + 7); + +} diff --git a/PDF/SaSPhotonPDF.h b/PDF/SaSPhotonPDF.h new file mode 100644 --- /dev/null +++ b/PDF/SaSPhotonPDF.h @@ -0,0 +1,134 @@ +// -*- C++ -*- +#ifndef Herwig_SaSPhotonPDF_H +#define Herwig_SaSPhotonPDF_H +// +// This is the declaration of the SaSPhotonPDF class. +// + +#include "ThePEG/PDF/PDFBase.h" + +namespace Herwig { + +using namespace ThePEG; + +/** + * The SaSPhotonPDF class provides an interface to the + * + * @see \ref SaSPhotonPDFInterfaces "The interfaces" + * defined for SaSPhotonPDF. + */ +class SaSPhotonPDF: public PDFBase { + +public: + + /** + * The default constructor. + */ + SaSPhotonPDF() : iset_(2), ip_(0) {} + +public: + + /** @name Virtual functions to be overridden by sub-classes. */ + //@{ + /** + * Return true if this PDF can handle the extraction of partons from + * the given \a particle. + */ + virtual bool canHandleParticle(tcPDPtr particle) const; + + /** + * Return the partons which this PDF may extract from the given + * \a particle. + */ + virtual cPDVector partons(tcPDPtr particle) const; + + /** + * The density. Return the pdf for the given \a parton inside the + * given \a particle for the virtuality \a partonScale and + * logarithmic momentum fraction \a l \f$(l=\log(1/x)\$f. The \a + * particle is assumed to have a virtuality \a particleScale. + */ + virtual double xfl(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, + double l, Energy2 particleScale = 0.0*GeV2) const; + + /** + * The valence density. Return the pdf for the given cvalence \a + * parton inside the given \a particle for the virtuality \a + * partonScale and logarithmic momentum fraction \a l + * \f$(l=\log(1/x)\$f. The \a particle is assumed to have a + * virtuality \a particleScale. If not overidden by a sub class this + * will return zero. + */ + virtual double xfvl(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, + double l, Energy2 particleScale = 0.0*GeV2) 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; + //@} + +private: + + /** + * The assignment operator is private and must never be called. + * In fact, it should not even be implemented. + */ + SaSPhotonPDF & operator=(const SaSPhotonPDF &); + +private: + + /** + * PDF Set + */ + mutable int iset_; + + /** + * Scheme used to evaluate off-shell anomalous component. + */ + mutable int ip_; + +}; + +} + +#endif /* Herwig_SaSPhotonPDF_H */ diff --git a/PDT/StandardMatchers.cc b/PDT/StandardMatchers.cc --- a/PDT/StandardMatchers.cc +++ b/PDT/StandardMatchers.cc @@ -1,30 +1,31 @@ // -*- C++ -*- // // StandardMatchers.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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. // // // Ensures the StandardMatchers get created // #include "ThePEG/PDT/Matcher.h" #include "ThePEG/PDT/StandardMatchers.h" #include "StandardMatchers.h" using namespace Herwig; using namespace ThePEG; namespace { static MatchPhoton m00; static MatchBottom m01; static MatchTop m02; static MatchHadron m03; static MatchWBoson m04; static MatchZBoson m05; static MatchHiggsBoson m06; static MatchChargedLepton m07; + static MatchLightParticle m08; } diff --git a/PDT/StandardMatchers.h b/PDT/StandardMatchers.h --- a/PDT/StandardMatchers.h +++ b/PDT/StandardMatchers.h @@ -1,210 +1,231 @@ // -*- C++ -*- // // StandardMatchers.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_StandardMatchers_H #define Herwig_StandardMatchers_H // This is the declaration of the AnyMatcher, #include "ThePEG/PDT/Matcher.h" #include "ThePEG/Repository/CurrentGenerator.h" #include "ThePEG/PDF/BeamParticleData.h" #include "ThePEG/PDT/EnumParticles.h" namespace Herwig { using namespace ThePEG; /** * * This file declare a set of standard matcher classes in addition to those * defined in ThePEG. The classes can be used by themselves (with * their static functions) or together with the Matcher class to * define Interfaced objects of the MatcherBase type to be used in the * Repository. Suitable typedefs are declared for the latter. * * @see Matcher * @see MatcherBase */ /** * A Matcher class which matches photons */ struct PhotonMatcher: public MatcherType { /** Typedef the class matching the complex conjugate particles. */ typedef PhotonMatcher CC; /** The main static function to check if a given particle type \a pd matches. */ static bool Check(const ParticleData & pd) { return pd.id()==ParticleID::gamma; } /** A simplified but unique class name. */ static string className() { return "Photon"; } }; /** * Gives a MatcherBase class based on PhotonMatcher. */ typedef Matcher MatchPhoton; /** * A Matcher class which matches top quarks */ struct TopMatcher: public MatcherType { /** Typedef the class matching the complex conjugate particles. */ typedef TopMatcher CC; /** The main static function to check if a given particle type \a pd matches. */ static bool Check(const ParticleData & pd) { return abs(pd.id())==ParticleID::t; } /** A simplified but unique class name. */ static string className() { return "Top"; } }; /** * Gives a MatcherBase class based on TopMatcher. */ typedef Matcher MatchTop; /** * A Matcher class which matches bottom quarks */ struct BottomMatcher: public MatcherType { /** Typedef the class matching the complex conjugate particles. */ typedef BottomMatcher CC; /** The main static function to check if a given particle type \a pd matches. */ static bool Check(const ParticleData & pd) { return abs(pd.id())==ParticleID::b; } /** A simplified but unique class name. */ static string className() { return "Bottom"; } }; /** * Gives a MatcherBase class based on BottomMatcher. */ typedef Matcher MatchBottom; /** * A Matcher class which matches any hadron. */ struct HadronMatcher: public MatcherType { /** Typedef the class matching the complex conjugate particles. */ typedef HadronMatcher CC; /** The main static function to check if a given particle type \a pd matches. */ static bool Check(const ParticleData & pd) { if (pd.id() != ParticleID::gamma) return Check(pd.id()); else { Ptr::const_pointer beam = dynamic_ptr_cast< Ptr::const_pointer>(&pd); return beam && beam->pdf(); } } /** The main static function to check if a given particle with type \a id matches. */ static bool Check(long id) { bool hadron = (id/10)%10 && (id/100)%10; if(hadron) return true; // special for gamma when acting like a hadron if (id != ParticleID::gamma) return false; tcPDPtr gamma = CurrentGenerator::current().getParticleData(ParticleID::gamma); Ptr::const_pointer beam = dynamic_ptr_cast< Ptr::const_pointer>(gamma); return beam && beam->pdf(); } /** A simplified but unique class name. */ static string className() { return "Hadron"; } }; /** Gives a MatcherBase class based on HadronMatcher. */ typedef Matcher MatchHadron; /** * A Matcher class which matches W bosons */ struct WBosonMatcher: public MatcherType { /** Typedef the class matching the complex conjugate particles. */ typedef WBosonMatcher CC; /** The main static function to check if a given particle type \a pd matches. */ static bool Check(const ParticleData & pd) { return abs(pd.id())==ParticleID::Wplus; } /** A simplified but unique class name. */ static string className() { return "WBoson"; } }; /** * Gives a MatcherBase class based on WBosonMatcher. */ typedef Matcher MatchWBoson; /** * A Matcher class which matches Z bosons */ struct ZBosonMatcher: public MatcherType { /** Typedef the class matching the complex conjugate particles. */ typedef ZBosonMatcher CC; /** The main static function to check if a given particle type \a pd matches. */ static bool Check(const ParticleData & pd) { return abs(pd.id())==ParticleID::Z0; } /** A simplified but unique class name. */ static string className() { return "ZBoson"; } }; /** * Gives a MatcherBase class based on ZBosonMatcher. */ typedef Matcher MatchZBoson; /** * A Matcher class which matches Higgs bosons */ struct HiggsBosonMatcher: public MatcherType { /** Typedef the class matching the complex conjugate particles. */ typedef HiggsBosonMatcher CC; /** The main static function to check if a given particle type \a pd matches. */ static bool Check(const ParticleData & pd) { return abs(pd.id())==ParticleID::h0; } /** A simplified but unique class name. */ static string className() { return "HiggsBoson"; } }; /** * Gives a MatcherBase class based on HiggsBosonMatcher. */ typedef Matcher MatchHiggsBoson; /** * A Matcher class which matches any charged lepton. */ struct ChargedLeptonMatcher: public MatcherType { /** Typedef the class matching the complex conjugate particles. */ typedef ChargedLeptonMatcher CC; /** The main static function to check if a given particle type \a pd matches. */ static bool Check(const ParticleData & pd) { return Check(pd.id()); } static bool Check(long id) { return abs(id) > 10 && abs(id) <= 20 && abs(id)%2!=0; } /** A simplified but unique class name. */ static string className() { return "ChargedLepton"; } }; /** Gives a MatcherBase class based on ChargedLeptonMatcher. */ typedef Matcher MatchChargedLepton; + +/** + * A Matcher class which matches any light (<1GeV) particles other than the photon + */ +struct LightParticleMatcher: public MatcherType { + /** Typedef the class matching the complex conjugate particles. */ + typedef LightParticleMatcher CC; + /** The main static function to check if a given particle type \a pd + matches. */ + static bool Check(const ParticleData & pd) { + return pd.id()!=22 && abs(pd.id()) > 6 && abs(pd.id())!=11 && + abs(pd.id())!=13 && abs(pd.id())!=15 && abs(pd.mass())<=GeV; + } + /** A simplified but unique class name. */ + static string className() { return "LightParticle"; } +}; + +/** + * Gives a MatcherBase class based on LightParticleatcher. + */ +typedef Matcher MatchLightParticle; + } - #endif /* Herwig_StandardMatchers_H */ diff --git a/README b/README --- a/README +++ b/README @@ -1,14 +1,14 @@ ======== Herwig 7 ======== -This is the release of Herwig 7.1.2, a multi purpose event +This is the release of Herwig 7.1.3, a multi purpose event generator for high energy physics. The Herwig++ distribution contains an adapted version of LoopTools 2.6 . BUILD AND INSTALL ================= Please refer to https://herwig.hepforge.org/tutorials/ for detailed instructions. diff --git a/Shower/Dipole/AlphaS/alpha_s.cc b/Shower/Dipole/AlphaS/alpha_s.cc --- a/Shower/Dipole/AlphaS/alpha_s.cc +++ b/Shower/Dipole/AlphaS/alpha_s.cc @@ -1,236 +1,236 @@ // -*- C++ -*- // couplings/alpha_s.cc is part of matchbox // (C) 2008 Simon Platzer -- sp@particle.uni-karlsruhe.de #include "alpha_s.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Command.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/Repository.h" #include "ThePEG/PDT/ParticleData.h" using namespace matchbox; alpha_s::alpha_s() : AlphaSBase(), min_active_flavours_(3), max_active_flavours_(6), matched_(false), scale_factor_(1.), quark_masses_squared_(), lambda_squared_(), alpha_s_in_(.1176), scale_in_(91.1876*GeV), lambda_range_(1.*MeV2,1.e6*MeV2), fixed_(false) { } alpha_s::~alpha_s() {} void alpha_s::persistentOutput(PersistentOStream & os) const { os << min_active_flavours_ << max_active_flavours_ << matched_ << scale_factor_; for (size_t f = 0; f < 7; ++f) os << ounit(quark_masses_squared_[f],MeV2) << ounit(lambda_squared_[f],MeV2); for (size_t f = 0; f < 6; ++f) os << ounit(nfvector[f],MeV2); os << alpha_s_in_ << ounit(scale_in_,GeV) << ounit(lambda_range_.first,MeV2) << ounit(lambda_range_.second,MeV2) << fixed_; } void alpha_s::persistentInput(PersistentIStream & is, int) { is >> min_active_flavours_ >> max_active_flavours_ >> matched_ >> scale_factor_; for (size_t f = 0; f < 7; ++f) is >> iunit(quark_masses_squared_[f],MeV2) >> iunit(lambda_squared_[f],MeV2); for (size_t f = 0; f < 6; ++f) is >> iunit(nfvector[f],MeV2); is >> alpha_s_in_ >> iunit(scale_in_,GeV) >> iunit(lambda_range_.first,MeV2) >> iunit(lambda_range_.second,MeV2) >> fixed_; } AbstractClassDescription alpha_s::initalpha_s; // Definition of the static class description member. void alpha_s::Init() { static ClassDocumentation documentation ("Base class for strong coupoling as used in matchbox"); static Parameter interfacemin_active_flavours ("min_active_flavours", "Minimum number of active flavours", &alpha_s::min_active_flavours_, 3, 0, 6, true, false, Interface::limited); static Parameter interfacemax_active_flavours ("max_active_flavours", "Maximum number of active flavours", &alpha_s::max_active_flavours_, 6, 0, 6, true, false, Interface::limited); static Parameter interfaceinput_alpha_s ("input_alpha_s", "alpha_s value at input scale", &alpha_s::alpha_s_in_, .1176, 0.0, 1.0, true, false, Interface::limited); static Parameter interfaceinput_scale ("input_scale", "Input scale for alpha_s value", &alpha_s::scale_in_, GeV, 91.1876*GeV, 0.*GeV, 0.*GeV, true, false, Interface::lowerlim); static Command interfacecheck ("check", "check", &alpha_s::check, false); static Parameter interfacescale_factor ("scale_factor", "scale factor for argument", &alpha_s::scale_factor_, 1., 0.0, 100.0, true, false, Interface::limited); static Switch interfacefixed ("fixed", "", &alpha_s::fixed_, false, false, false); static SwitchOption interfacefixedYes (interfacefixed, "Yes", "", true); static SwitchOption interfacefixedNo (interfacefixed, "No", "", false); } string alpha_s::check (string args) { istringstream argin(args); double Q_low, Q_high; long n_steps; argin >> Q_low >> Q_high >> n_steps; string fname; argin >> fname; - generator()->log() << "checking alpha_s in range [" << Q_low << "," << Q_high << "] GeV in " - << n_steps << " steps.\nResults are written to " << fname << "\n"; + Repository::clog() << "checking alpha_s in range [" << Q_low << "," << Q_high << "] GeV in " + << n_steps << " steps.\nResults are written to " << fname << "\n"; double step_width = (Q_high-Q_low)/n_steps; match_thresholds(); - generator()->log() << "threshold matching results:\n" - << "(m_Q^2 -> Lambda^2) / GeV^2 for dynamic flavours in range [" - << min_active_flavours_ << "," << max_active_flavours_ << "]\n"; + Repository::clog() << "threshold matching results:\n" + << "(m_Q^2 -> Lambda^2) / GeV^2 for dynamic flavours in range [" + << min_active_flavours_ << "," << max_active_flavours_ << "]\n"; for (size_t f = 0; f < 7; ++f) { - generator()->log() << (quark_masses_squared_[f]/GeV2) << " " - << (lambda_squared_[f]/GeV2) << "\n"; + Repository::clog() << (quark_masses_squared_[f]/GeV2) << " " + << (lambda_squared_[f]/GeV2) << "\n"; } ofstream out (fname.c_str()); for (long k = 0; k <= n_steps; ++k) { Energy Q = Q_low*GeV + k*step_width*GeV; out << (Q/GeV) << " " << (operator () (Q*Q)) << "\n"; } return "alpha_s check finished"; } void alpha_s::match_thresholds () { if (matched_) return; // get the quark masses quark_masses_squared_[0] = 0.*MeV2; for (long f = 1; f < 7; ++f) { if ( quarkMasses().empty() ) quark_masses_squared_[static_cast(f)] = sqr(getParticleData(f)->mass()); else quark_masses_squared_[static_cast(f)] = sqr(quarkMasses()[static_cast(f-1)]); } if ( quark_masses_squared_[1] > quark_masses_squared_[2] ) swap(quark_masses_squared_[1],quark_masses_squared_[2]); unsigned int active_at_input = active_flavours(sqr(scale_in_)); // solve for input lambda solve_input_lambda input_equation (this,active_at_input,alpha_s_in_,sqr(scale_in_)); gsl::bisection_root_solver,100> input_solver(input_equation); lambda_squared_[active_at_input] = MeV2 * input_solver.solve({lambda_range_.first/MeV2,lambda_range_.second/MeV2}); // get lambdas down to min active flavours unsigned int below = active_at_input; while (below > min_active_flavours_) { solve_lambda_below match_equation (this,below, lambda_squared_[below], quark_masses_squared_[below]); gsl::bisection_root_solver,100> match_solver(match_equation); lambda_squared_[below-1] = MeV2 * match_solver.solve({lambda_range_.first/MeV2,lambda_range_.second/MeV2}); --below; } // get lambdas up to max active flavours unsigned int above = active_at_input; while (above < max_active_flavours_) { solve_lambda_above match_equation (this,above, lambda_squared_[above], quark_masses_squared_[above+1]); gsl::bisection_root_solver,100> match_solver(match_equation); lambda_squared_[above+1] = MeV2 *match_solver.solve({lambda_range_.first/MeV2,lambda_range_.second/MeV2}); ++above; } if (min_active_flavours_ > 0) { for (size_t f = 0; f < min_active_flavours_; ++f) { lambda_squared_[f] = lambda_squared_[min_active_flavours_]; } } if (max_active_flavours_ < 6) { for (size_t f = max_active_flavours_+1; f < 7; ++f) { lambda_squared_[f] = lambda_squared_[max_active_flavours_]; } } matched_ = true; return; } diff --git a/Shower/Dipole/Base/Dipole.h b/Shower/Dipole/Base/Dipole.h --- a/Shower/Dipole/Base/Dipole.h +++ b/Shower/Dipole/Base/Dipole.h @@ -1,327 +1,337 @@ // -*- C++ -*- // // Dipole.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_Dipole_H #define HERWIG_Dipole_H // // This is the declaration of the Dipole class. // #include "Herwig/Shower/Dipole/Kinematics/DipoleSplittingKinematics.h" #include "Herwig/Shower/Dipole/Base/DipoleSplittingInfo.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer, Stephen Webster, Johannes Bellm * * \brief The Dipole class is used by the dipole shower to * represent a dipole of two coloured partons. * */ class Dipole { public: /** * The default constructor */ Dipole(); /** * The standard constructor */ Dipole(const pair& newParticles, const pair& newPDFs, pair newFractions, pair newScales); /** * The standard constructor */ Dipole(const pair& newParticles, const pair& newPDFs, pair newFractions, const pair decaying = pair(false,false), const pair offShell = pair(false,false), pair newScales = pair(ZERO,ZERO)); public: /** * Get the left particle. */ tPPtr leftParticle() const { return theParticles.first; } /** * Get the right particle. */ tPPtr rightParticle() const { return theParticles.second; } /** * Get the left PDF. */ const PDF& leftPDF() const { return thePDFs.first; } /** * Get the right PDF. */ const PDF& rightPDF() const { return thePDFs.second; } /** * Get the left fraction. */ double leftFraction() const { return theFractions.first; } /** * Get the right fraction. */ double rightFraction() const { return theFractions.second; } /** * Get the bool indicating * incoming decay for the left * particle, for debugging only. */ bool leftDecaying() { return theDecaying.first; } /** * Get the bool indicating * incoming decay for the right * particle, for debugging only. */ bool rightDecaying() { return theDecaying.second; } /** * Set the left particle. */ void leftParticle(PPtr p) { theParticles.first = p; } /** * Set the right particle. */ void rightParticle(PPtr p) { theParticles.second = p; } /** * Set the left PDF */ void leftPDF(const PDF& p) { thePDFs.first = p; } /** * Set the right PDF */ void rightPDF(const PDF& p) { thePDFs.second = p; } /** * Set the momentum fraction for the left particle. */ void leftFraction(double x) { theFractions.first = x; } /** * Set the momentum fraction for the right particle. */ void rightFraction(double x) { theFractions.second = x; } /** * Get the scale for the left particle. */ Energy leftScale() const { return theScales.first; } /** * Set the scale for the left particle. */ void leftScale(Energy s) { theScales.first = s; } /** * Get the scale for the right particle. */ Energy rightScale() const { return theScales.second; } /** * Set the scale for the right particle. */ void rightScale(Energy s) { theScales.second = s; } /** * Set the decayed particle indicator * for the left particle */ void leftDecaying(bool decaying) { theDecaying.first = decaying; } /** * Set the decayed particle indicator * for the right particle */ void rightDecaying(bool decaying) { theDecaying.second = decaying; } /** * Update information, if modified. */ void update(); public: /** * Return the dipole index for the selected * emitter-spectator assignment. */ const DipoleIndex& index(pair conf) const { return conf.first ? theIndices.first : theIndices.second; } /** + * Set the first index + */ + void setFirstIndex(DipoleIndex s){theIndices.first=s;} + + /** + * Set the first index + */ + void setSecondIndex(DipoleIndex s){theIndices.second=s;} + + /** * Return the emitter particle for the * selected configuration. */ tPPtr emitter(pair conf) const { return conf.first ? theParticles.first : theParticles.second; } /** * Return the spectator particle for the * selected configuration. */ tPPtr spectator(pair conf) const { return conf.first ? theParticles.second : theParticles.first; } /** * Return the scale associated to the emitter * for the selected configuration. */ Energy emitterScale(pair conf) const { return conf.first ? theScales.first : theScales.second; } /** * Set the scale associated to the emitter * for the selected configuration. */ void emitterScale(pair conf, Energy scale) { (conf.first ? theScales.first : theScales.second) = scale; } /** * Return the momentum fraction of the emitter * for the selected configuration. */ double emitterX(pair conf) const { return conf.first ? theFractions.first : theFractions.second; } /** * Return the PDF of the emitter * for the selected configuration. */ const PDF& emitterPDF(pair conf) const { return conf.first ? thePDFs.first : thePDFs.second; } /** * Return the momentum fraction of the spectator * for the selected configuration. */ double spectatorX(pair conf) const { return conf.first ? theFractions.second : theFractions.first; } /** * Return the PDF of the spectator * for the selected configuration. */ const PDF& spectatorPDF(pair conf) const { return conf.first ? thePDFs.second : thePDFs.first; } public: /** * Split this dipole according to the given splitting. * If colourSpectator is true, do not change the spectator. */ pair split (DipoleSplittingInfo& dsplit, bool colourSpectator) const; /** * As split, but without touching the event record. * Needed to produce a phase space point as it would * be after calling split. */ void tmpsplit (DipoleSplittingInfo& dsplit, bool colourSpectator) const; /** * Produce a new spectator according to the * given splitting. */ void recoil (DipoleSplittingInfo& dsplit); public: /** * Put information to ostream */ void print(ostream&) const; private: /** * The particles forming the dipole */ pair theParticles; /** * The PDF objects. */ pair thePDFs; /** * The momentum fractions associated * to the incoming particles */ pair theFractions; /** * The dipole indices, if the first or second particle * is considered as emitter. */ pair theIndices; /** * Indicates if either the first or the second parton * is incoming to a decay. */ pair theDecaying; /** * Indicates if either the first or second parton * can be off-shell (required for sampling). **/ pair theOffShell; /** * The scale associated to the first and second * particle, respectively. */ pair theScales; }; inline ostream& operator << (ostream& os, const Dipole& di) { di.print(os); return os; } } #endif /* HERWIG_Dipole_H */ diff --git a/Shower/Dipole/Base/DipoleChain.cc b/Shower/Dipole/Base/DipoleChain.cc --- a/Shower/Dipole/Base/DipoleChain.cc +++ b/Shower/Dipole/Base/DipoleChain.cc @@ -1,334 +1,342 @@ // -*- C++ -*- // // DipoleChain.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 DipoleChain class. // #include "DipoleChain.h" #include "Herwig/Shower/Dipole/Utility/DipolePartonSplitter.h" +#include "Herwig/Shower/Dipole/Colorea/Colorea.h" #include using namespace Herwig; DipoleChain::DipoleChain() : ggSingleDipole(false) {} bool DipoleChain::circular () const { return (theDipoles.front().leftParticle() == theDipoles.back().rightParticle()); } bool DipoleChain::hasLeftNeighbour (list::const_iterator dc) const { if ( dc == dipoles().begin() ) return circular(); return true; } Dipole& DipoleChain::leftNeighbour (list::iterator dc) { assert(hasLeftNeighbour(dc)); if ( dc == dipoles().begin() ) return dipoles().back(); return *(--dc); } const Dipole& DipoleChain::leftNeighbour (list::const_iterator dc) const { assert(hasLeftNeighbour(dc)); if ( dc == dipoles().begin() ) return dipoles().back(); return *(--dc); } list::iterator DipoleChain::leftNeighbourIterator(list::iterator dc) { assert(hasLeftNeighbour(dc)); if ( dc == dipoles().begin() ) return --dipoles().end(); return --dc; } bool DipoleChain::hasRightNeighbour (list::const_iterator dc) const { if (dc == --dipoles().end()) return circular(); return true; } Dipole& DipoleChain::rightNeighbour (list::iterator dc) { assert(hasRightNeighbour(dc)); if ( dc == --dipoles().end() ) return dipoles().front(); return *(++dc); } const Dipole& DipoleChain::rightNeighbour (list::const_iterator dc) const { assert(hasRightNeighbour(dc)); if ( dc == --dipoles().end() ) return dipoles().front(); return *(++dc); } list::iterator DipoleChain::rightNeighbourIterator(list::iterator dc) { assert(hasRightNeighbour(dc)); if ( dc == --dipoles().end() ) return dipoles().begin(); return ++dc; } void DipoleChain::check() { if ( theDipoles.begin() == std::prev(theDipoles.end()) ) { if ( theDipoles.front().leftParticle()->hasColour() && theDipoles.front().leftParticle()->hasAntiColour() ) { assert(theDipoles.front().rightParticle()->hasColour() && theDipoles.front().rightParticle()->hasAntiColour()); ggSingleDipole = true; } } } + +void DipoleChain::rearrange(int dipmax,int diplong){ + static auto colorea = Colorea(); + colorea.setChain(this); + colorea.rearrange( dipmax, diplong); +} + list::iterator DipoleChain::insertSplitting(list::iterator emittingDipole, pair children, pair::iterator,list::iterator>& childIterators) { assert(DipolePartonSplitter::colourConnected(children.first.leftParticle(),children.first.rightParticle()) || DipolePartonSplitter::colourConnected(children.second.leftParticle(),children.second.rightParticle())); bool was_circular = circular(); if (hasLeftNeighbour(emittingDipole)) { list::iterator theLeftNeighbour = leftNeighbourIterator(emittingDipole); theLeftNeighbour->rightParticle(children.first.leftParticle()); if ( children.first.leftParticle()->scale() < sqr(theLeftNeighbour->rightScale()) ) theLeftNeighbour->rightScale(sqrt(children.first.leftParticle()->scale())); theLeftNeighbour->rightPDF(children.first.leftPDF()); theLeftNeighbour->rightFraction(children.first.leftFraction()); theLeftNeighbour->rightDecaying(children.first.leftDecaying()); theLeftNeighbour->update(); } if (hasRightNeighbour(emittingDipole)) { list::iterator theRightNeighbour = rightNeighbourIterator(emittingDipole); theRightNeighbour->leftParticle(children.second.rightParticle()); if ( children.second.rightParticle()->scale() < sqr(theRightNeighbour->leftScale()) ) theRightNeighbour->leftScale(sqrt(children.second.rightParticle()->scale())); theRightNeighbour->leftPDF(children.second.rightPDF()); theRightNeighbour->leftFraction(children.second.rightFraction()); theRightNeighbour->leftDecaying(children.second.rightDecaying()); theRightNeighbour->update(); } if (DipolePartonSplitter::colourConnected(children.first.leftParticle(),children.first.rightParticle()) && DipolePartonSplitter::colourConnected(children.second.leftParticle(),children.second.rightParticle())) { // nothing special to do, just replace the emitting dipole // by the right one and insert the left one before it *emittingDipole = children.second; childIterators.second = emittingDipole; childIterators.first = dipoles().insert(emittingDipole,children.first); if ( ggSingleDipole ) { ggSingleDipole = false; Dipole miss; miss.leftParticle(dipoles().back().rightParticle()); miss.rightParticle(dipoles().front().leftParticle()); miss.leftScale(dipoles().back().rightScale()); miss.rightScale(dipoles().front().leftScale()); miss.leftPDF(dipoles().back().rightPDF()); miss.rightPDF(dipoles().front().leftPDF()); miss.leftFraction(dipoles().back().rightFraction()); miss.rightFraction(dipoles().front().leftFraction()); miss.leftDecaying(dipoles().back().rightDecaying()); miss.rightDecaying(dipoles().front().leftDecaying()); miss.update(); dipoles().push_back(miss); } return dipoles().end(); } if (!DipolePartonSplitter::colourConnected(children.first.leftParticle(),children.first.rightParticle())) { if ( !was_circular && !ggSingleDipole ) { *emittingDipole = children.second; childIterators.second = emittingDipole; assert(emittingDipole != dipoles().begin()); childIterators.first = std::prev(emittingDipole); return emittingDipole; } *emittingDipole = children.second; if ( ggSingleDipole ) { ggSingleDipole = false; Dipole miss; miss.leftParticle(children.second.rightParticle()); miss.rightParticle(children.first.leftParticle()); miss.leftScale(children.second.rightScale()); miss.rightScale(children.first.leftScale()); miss.leftPDF(children.second.rightPDF()); miss.rightPDF(children.first.leftPDF()); miss.leftFraction(children.second.rightFraction()); miss.rightFraction(children.first.leftFraction()); miss.leftDecaying(dipoles().back().rightDecaying()); miss.rightDecaying(dipoles().front().leftDecaying()); miss.update(); dipoles().push_back(miss); childIterators.first = dipoles().begin(); childIterators.second = std::prev(dipoles().end()); return dipoles().end(); } childIterators.second = emittingDipole; if ( emittingDipole == dipoles().begin() ) childIterators.first = --dipoles().end(); else childIterators.first = std::prev(emittingDipole); if ( emittingDipole == dipoles().begin() ) return dipoles().end(); dipoles().splice(dipoles().begin(),dipoles(),emittingDipole,dipoles().end()); // explicitly fix iterators in case the splice implementation // at hand does invalidate iterators (the SGI docu says, it doesn't, // but it seems that this behaviour is not part of the standard) childIterators.second = dipoles().begin(); childIterators.first = --dipoles().end(); return dipoles().end(); } if (!DipolePartonSplitter::colourConnected(children.second.leftParticle(),children.second.rightParticle())) { if ( !was_circular && !ggSingleDipole ) { *emittingDipole = children.first; childIterators.first = emittingDipole; assert(emittingDipole != --dipoles().end()); childIterators.second = std::next(emittingDipole); return std::next(emittingDipole); } *emittingDipole = children.first; if ( ggSingleDipole ) { ggSingleDipole = false; Dipole miss; miss.leftParticle(children.second.rightParticle()); miss.rightParticle(children.first.leftParticle()); miss.leftScale(children.second.rightScale()); miss.rightScale(children.first.leftScale()); miss.leftPDF(children.second.rightPDF()); miss.rightPDF(children.first.leftPDF()); miss.leftFraction(children.second.rightFraction()); miss.rightFraction(children.first.leftFraction()); miss.leftDecaying(dipoles().back().rightDecaying()); miss.rightDecaying(dipoles().front().leftDecaying()); miss.update(); dipoles().push_front(miss); childIterators.first = dipoles().begin(); childIterators.second = std::prev(dipoles().end()); return dipoles().end(); } childIterators.first = emittingDipole; if ( emittingDipole == --dipoles().end() ) childIterators.second = dipoles().begin(); else childIterators.second = std::next(emittingDipole); if ( emittingDipole == --dipoles().end() ) return dipoles().end(); dipoles().splice(dipoles().begin(),dipoles(),std::next(emittingDipole),dipoles().end()); // explicitly fix iterators in case the splice implementation // at hand does invalidate iterators (the SGI docu says, it doesn't, // but it seems that this behaviour is not part of the standard) childIterators.first = dipoles().begin(); childIterators.second = --dipoles().end(); return dipoles().end(); } return dipoles().end(); } void DipoleChain::updateDipole(list::iterator dip) { dip->update(); if (hasLeftNeighbour(dip)) { list::iterator theLeftNeighbour = leftNeighbourIterator(dip); theLeftNeighbour->rightParticle(dip->leftParticle()); theLeftNeighbour->rightPDF(dip->leftPDF()); theLeftNeighbour->rightFraction(dip->leftFraction()); theLeftNeighbour->rightDecaying(dip->leftDecaying()); theLeftNeighbour->update(); } if (hasRightNeighbour(dip)) { list::iterator theRightNeighbour = rightNeighbourIterator(dip); theRightNeighbour->leftParticle(dip->rightParticle()); theRightNeighbour->leftPDF(dip->rightPDF()); theRightNeighbour->leftFraction(dip->rightFraction()); theRightNeighbour->leftDecaying(dip->rightDecaying()); theRightNeighbour->update(); } } void DipoleChain::print(ostream& os) const { os << "--- DipoleChain ----------------------------------------------------------------\n"; if ( theDipoles.empty() ) { os << " *** This DipoleChain is empty. ***\n"; } else { os << " " << (!circular() ? "non-" : "") << "circular with " << theDipoles.size() << " dipoles\n"; for (list::const_iterator dit = theDipoles.begin(); dit != theDipoles.end(); ++dit) { os << (*dit); } } os << "--------------------------------------------------------------------------------\n"; os << flush; } diff --git a/Shower/Dipole/Base/DipoleChain.fh b/Shower/Dipole/Base/DipoleChain.fh new file mode 100644 --- /dev/null +++ b/Shower/Dipole/Base/DipoleChain.fh @@ -0,0 +1,21 @@ +// -*- C++ -*- +// This is the forward declaration of the DipoleChain class + +#ifndef HERWIG_DipoleChain_FH +#define HERWIG_DipoleChain_FH + +#include "ThePEG/Config/ThePEG.h" +#include "ThePEG/Config/Pointers.h" + + +namespace Herwig { + +class DipoleChain; +using namespace ThePEG; + + ThePEG_DECLARE_POINTERS(DipoleChain , DipoleChainPtr ); + + +} + +#endif // HERWIG_DipoleChain_FH diff --git a/Shower/Dipole/Base/DipoleChain.h b/Shower/Dipole/Base/DipoleChain.h --- a/Shower/Dipole/Base/DipoleChain.h +++ b/Shower/Dipole/Base/DipoleChain.h @@ -1,153 +1,158 @@ // -*- C++ -*- // // DipoleChain.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_DipoleChain_H #define HERWIG_DipoleChain_H // // This is the declaration of the DipoleChain class. // #include "Dipole.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief The DipoleChain class is used by the dipole shower to * represent a chain of dipoles. * */ class DipoleChain { public: /** * Default constructor */ DipoleChain(); /** * Return true, if this chain is circular. */ bool circular () const; /* * Return true, if the dipole referred to * has a left neighbour */ bool hasLeftNeighbour(list::const_iterator dc) const; /* * Return a reference to the left neighbour, * if existing */ Dipole& leftNeighbour(list::iterator dc); /* * Return a const reference to the left neighbour, * if existing */ const Dipole& leftNeighbour(list::const_iterator dc) const; /** * Return an iterator to the left neighbour */ list::iterator leftNeighbourIterator(list::iterator dc); /* * Return true, if the dipole referred to * has a right neighbour */ bool hasRightNeighbour (list::const_iterator dc) const; /* * Return a reference to the right neighbour, * if existing */ Dipole& rightNeighbour (list::iterator dc); /* * Return a const reference to the right neighbour, * if existing */ const Dipole& rightNeighbour (list::const_iterator dc) const; /** * Return an iterator to the right neighbour */ list::iterator rightNeighbourIterator(list::iterator dc); public: /** * Access the dipole list */ list& dipoles() { return theDipoles; } /** * Return the dipole list */ const list& dipoles() const { return theDipoles; } /** * Check for gg single dipole */ void check(); + /** + * Rearrange the dipole chain (arXiv:1801.06113). + */ + void rearrange(int dipmax,int diplong); + public: /* * Insert the given splitting; if this contains a chain-breakup emission and * the chain is circular, reshuffle the chain to make it non-circular; if it is * already non-circular return the iterator starting the new chain. If no * splitting is needed return the end iterator of the dipole list. * Set the iterators pointing to the children dipoles. */ list::iterator insertSplitting(list::iterator emittingDipole, pair children, pair::iterator,list::iterator>& childIterators); /** * Indicate a change in the given dipole. */ void updateDipole(list::iterator dip); public: /** * Put information to ostream */ void print(ostream&) const; private: /** * The dipoles contained in this chain */ list theDipoles; /** * Switch on special treatment for * gg single dipole */ bool ggSingleDipole; }; inline ostream& operator << (ostream& os, const DipoleChain& di) { di.print(os); return os; } } #endif /* HERWIG_DipoleChain_H */ diff --git a/Shower/Dipole/Base/Makefile.am b/Shower/Dipole/Base/Makefile.am --- a/Shower/Dipole/Base/Makefile.am +++ b/Shower/Dipole/Base/Makefile.am @@ -1,13 +1,13 @@ noinst_LTLIBRARIES = libHwDipoleShowerBase.la libHwDipoleShowerBase_la_SOURCES = \ DipoleSplittingInfo.h DipoleSplittingInfo.cc \ Dipole.h Dipole.cc \ - DipoleChain.h DipoleChain.cc \ + DipoleChain.fh DipoleChain.h DipoleChain.cc \ DipoleEventRecord.h DipoleEventRecord.cc \ DipoleEventReweight.h DipoleEventReweight.cc \ DipoleSplittingGenerator.h DipoleSplittingGenerator.cc \ DipoleSplittingReweight.h DipoleSplittingReweight.cc \ DipoleEvolutionOrdering.h DipoleEvolutionOrdering.cc \ DipoleChainOrdering.h DipoleChainOrdering.cc diff --git a/Shower/Dipole/Colorea/Colorea.cc b/Shower/Dipole/Colorea/Colorea.cc new file mode 100644 --- /dev/null +++ b/Shower/Dipole/Colorea/Colorea.cc @@ -0,0 +1,716 @@ + // -*- C++ -*- + // + // Colorea.cc is a part of Herwig - A multi-purpose Monte Carlo event generator + // Copyright (C) 2002-2017 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 Colorea class. + // + +#include "Colorea.h" +#include "eeuugg.h" +#include "eeuuggg.h" +#include "eeuugggg.h" +#include "Herwig/Shower/Dipole/Utility/DipolePartonSplitter.h" +#include "Herwig/Shower/Dipole/Base/DipoleChain.h" +#include "Herwig/Shower/Dipole/Base/Dipole.h" + + +#include + +using namespace Herwig; + +Colorea::Colorea(){} + +list& Colorea::dipoles() { return theChain->dipoles(); } + +void Colorea::rearrange( int dipmax , int diplong ){ + + assert( dipmax >= diplong ); + // if there are only 2 dipoles in the chain + //there is nothing to do for now. + if( dipoles().size() < 3 )return; + + if( dipoles().size() == 3 ){ + // get the 3 dipoles: + auto dipi=dipoles().begin(); + auto dipj=dipoles().begin();dipj++; + auto dipk=dipoles().begin();dipk++;dipk++; + rearrange3(dipi,dipj,dipk); + + if( theChain->circular () ){ + // if the chain is circular, + // we need to check also the + // connected ends. + rearrange3(dipj,dipk,dipi); + rearrange3(dipk,dipi,dipj); + } + return; + } + if( dipoles().size() == 4 && dipmax >= 4 ){ + // get the 4 dipoles + auto dipi=dipoles().begin(); + auto dipj=dipoles().begin();dipj++; + auto dipk=dipoles().begin();dipk++;dipk++; + auto dipl=dipoles().begin();dipl++;dipl++;dipl++; + rearrange4(dipi,dipj,dipk,dipl); + return; + } + if( dipoles().size() == 5 && dipmax >= 5 ){ + // get the 5 dipoles + auto dipi=dipoles().begin(); + auto dipj=dipoles().begin();dipj++; + auto dipk=dipoles().begin();dipk++;dipk++; + auto dipl=dipoles().begin();dipl++;dipl++;dipl++; + auto dipm=dipoles().begin();dipm++;dipm++;dipm++;dipm++; + rearrange5(dipi,dipj,dipk,dipl,dipm); + return; + } + // if the chain is longer than dipmax + // go though the chain with diplong dipoles. + rearrangeLong( diplong ); + return; + +} + +void Colorea::rearrangeLong( int diplong ){ + if ( diplong == 3 ){ + // get the 3 dipoles: + auto dipi=dipoles().begin(); + auto dipj=dipoles().begin();dipj++; + auto dipk=dipoles().begin();dipk++;dipk++; + while (dipk!=dipoles().end()) { + rearrange3(dipi,dipj,dipk); + dipi++;dipj++;dipk++; + } + if( theChain->circular() ){ + // if the chain is circular, + // we need to check also the + // connected ends. + dipk=dipoles().begin(); // as dipk was end + rearrange3( dipi , dipj , dipk ); + // rotate further. + dipi++;dipk++; + dipj=dipoles().begin(); + rearrange3(dipi,dipj,dipk); + } + }else if (diplong ==4){ + // get the 4 dipoles: + assert(!theChain->circular ()); + auto dipi=dipoles().begin(); + auto dipj=dipoles().begin();dipj++; + auto dipk=dipoles().begin();dipk++;dipk++; + auto dipl=dipoles().begin();dipl++;dipl++;dipl++; + while (dipl!=dipoles().end()) { + rearrange4(dipi,dipj,dipk,dipl); + dipi++;dipj++;dipk++;dipl++; + } + }else if (diplong ==5){ + // get the 5 dipoles: + assert(!theChain->circular ()); + auto dipi=dipoles().begin(); + auto dipj=dipoles().begin();dipj++; + auto dipk=dipoles().begin();dipk++;dipk++; + auto dipl=dipoles().begin();dipl++;dipl++;dipl++; + auto dipm=dipoles().begin();dipm++;dipm++;dipm++;dipm++; + + while (dipm!=dipoles().end()) { + rearrange5(dipi,dipj,dipk,dipl,dipm); + dipi++;dipj++;dipk++;dipl++;dipm++; + } + }else{ + assert(false); + } +} + + + +void Colorea::rmcol(tColinePtr A, + tColinePtr B, + list::iterator & dip){ + if(A==B){ + auto AA=A->coloured(); + for (auto col:AA){ + if(col==dip->leftParticle()) A->removeColoured (col); + if(col==dip->rightParticle())A->removeColoured (col); + } + auto BB=A->antiColoured(); + for (auto col:BB){ + if(col==dip->leftParticle()) A->removeAntiColoured (col); + if(col==dip->rightParticle())A->removeAntiColoured (col); + } + } +} + + + +void Colorea::removeColors(list::iterator dipi, + list::iterator dipj, + list::iterator dipk){ + auto ilc = dipi->leftParticle()->colourInfo()-> colourLine(); + auto irc = dipi->rightParticle()->colourInfo()-> colourLine(); + auto ila = dipi->leftParticle()->colourInfo()-> antiColourLine(); + auto ira = dipi->rightParticle()->colourInfo()-> antiColourLine(); + auto jlc = dipj->leftParticle()->colourInfo()-> colourLine(); + auto jrc = dipj->rightParticle()->colourInfo()-> colourLine(); + auto jla = dipj->leftParticle()->colourInfo()-> antiColourLine(); + auto jra = dipj->rightParticle()->colourInfo()-> antiColourLine(); + auto klc = dipk->leftParticle()->colourInfo()-> colourLine(); + auto krc = dipk->rightParticle()->colourInfo()-> colourLine(); + auto kla = dipk->leftParticle()->colourInfo()-> antiColourLine(); + auto kra = dipk->rightParticle()->colourInfo()-> antiColourLine(); + + if( ilc && irc ) rmcol(ilc,irc,dipi); + if( ila && ira ) rmcol(ila,ira,dipi); + if( jlc && jrc ) rmcol(jlc,jrc,dipj); + if( jla && jra ) rmcol(jla,jra,dipj); + if( klc && krc ) rmcol(klc,krc,dipk); + if( kla && kra ) rmcol(kla,kra,dipk); + + return; +} + + + +void Colorea::rearrange3_FF_FF_FF(list::iterator dipi, + list::iterator dipj, + list::iterator dipk){ + produceSwapping( dipi, dipj, dipk,true); + // compared to IF of FI dipoles we do not need to repair colors as + // the swapping just modified the gluon momenta. +} + + + + + +void Colorea::rearrange3_FF_FI_IF(list::iterator dipi, + list::iterator dipj, + list::iterator dipk){ + auto ilc = dipi->leftParticle()->colourInfo()-> colourLine(); + auto irc = dipi->rightParticle()->colourInfo()-> colourLine(); + auto ila = dipi->leftParticle()->colourInfo()-> antiColourLine(); + auto ira = dipi->rightParticle()->colourInfo()-> antiColourLine(); + auto jlc = dipj->leftParticle()->colourInfo()-> colourLine(); + auto jrc = dipj->rightParticle()->colourInfo()-> colourLine(); + auto jla = dipj->leftParticle()->colourInfo()-> antiColourLine(); + auto jra = dipj->rightParticle()->colourInfo()-> antiColourLine(); + auto klc = dipk->leftParticle()->colourInfo()-> colourLine(); + auto krc = dipk->rightParticle()->colourInfo()-> colourLine(); + auto kla = dipk->leftParticle()->colourInfo()-> antiColourLine(); + auto kra = dipk->rightParticle()->colourInfo()-> antiColourLine(); + + bool didperm = produceSwapping( dipi, dipj, dipk,false); + + if (!didperm)return; + removeColors(dipi,dipj,dipk); + auto new1Line = new_ptr(ColourLine()); + auto new2Line = new_ptr(ColourLine()); + auto new3Line = new_ptr(ColourLine()); + //Example: + // before + //ila (F)--irc (F) =g1(in,jl)= jla (F) -- jra(I)=g2(in,jr)=klc(I) -- krc(F) + // Should be after: + //ila (F) -- ira (I) =g2(in,jl)= jlc (I) -- jrc(F) =g1(out,jr)= kla(F) -- krc(F) + + //Then: + // FaFc_FaIa_IcFc FFFIIF aa -> FaIa_IcFc_FaFc + // FcFa_FcIc_IaFa FFFIIF cc -> FcIc_IaFa_FcFa + // FaFc_FaIa_IcIa FFFIII aa -> FaIa_IcFc_FaIa + // FcFa_FcIc_IaIc FFFIII cc -> FcIc_IaFa_FcIc + // IcFc_FaIa_IcFc IFFIIF aa -> IcIa_IcFc_FaFc + // IaFa_FcIc_IaFa IFFIIF cc -> IaIc_IaFa_FcFa + // IcFc_FaIa_IcIa IFFIII aa -> IcIa_IcFc_FaIa + // IaFa_FcIc_IaIc IFFIII cc -> IaIc_IaFa_FcIc + // end particles keep colors + // central all change color. + // + + if(ilc==irc){ + new1Line->addColoured (dipi->leftParticle()); + new1Line->addAntiColoured (dipi->rightParticle());} + if(ilc==ira){ + new1Line->addColoured (dipi->leftParticle()); + new1Line->addColoured (dipi->rightParticle());} + if(ila==irc){ + new1Line->addAntiColoured (dipi->leftParticle()); + new1Line->addAntiColoured (dipi->rightParticle());} + if(ila==ira){ + new1Line->addAntiColoured (dipi->leftParticle()); + new1Line->addColoured (dipi->rightParticle());} + + if(jlc==jrc){ + new2Line->addAntiColoured (dipj->leftParticle()); + new2Line->addAntiColoured (dipj->rightParticle());} + if(jlc==jra){ + new2Line->addAntiColoured (dipj->leftParticle()); + new2Line->addColoured (dipj->rightParticle());} + if(jla==jrc){ + new2Line->addColoured (dipj->leftParticle()); + new2Line->addAntiColoured (dipj->rightParticle());} + if(jla==jra){ + new2Line->addColoured (dipj->leftParticle()); + new2Line->addColoured (dipj->rightParticle());} + + if(klc==krc){ + new3Line->addAntiColoured (dipk->leftParticle()); + new3Line->addColoured (dipk->rightParticle());} + if(klc==kra){ + new3Line->addAntiColoured (dipk->leftParticle()); + new3Line->addAntiColoured (dipk->rightParticle());} + if(kla==krc){ + new3Line->addColoured (dipk->leftParticle()); + new3Line->addColoured (dipk->rightParticle());} + if(kla==kra){ + new3Line->addColoured (dipk->leftParticle()); + new3Line->addAntiColoured (dipk->rightParticle());} + +} + + + +void Colorea::rearrange3(list::iterator dipi, + list::iterator dipj, + list::iterator dipk){ + + // We only care about the cenral dipole. + // If central dipole is FI or IF we need to take care that + // momentum fractions and pdfs are treated correctly. + // If central dipole is FF we only swap momenta. + // Also the color lines of IF and FI swappings + // needs to be repaired. + + bool dipjisFF = dipj->leftFraction() == 1 && dipj->rightFraction() == 1; + bool dipjisIF = dipj->leftFraction() != 1 && dipj->rightFraction() == 1; + bool dipjisFI = dipj->leftFraction() == 1 && dipj->rightFraction() != 1; + bool dipjisII = dipj->leftFraction() != 1 && dipj->rightFraction() != 1; + + // if the possibly swaping dipole is II we + // do nothing as this should not be swapped!(?) + if(dipjisII) return; + + if(dipjisFF){ + // possibly swap gluon momenta + rearrange3_FF_FF_FF(dipi,dipj,dipk); + } + // If central dipole is IF or FI -> keep end colors and swap central colors + else if( dipjisIF || dipjisFI ){ + rearrange3_FF_FI_IF(dipi,dipj,dipk); + } + else { + assert(false); + } + + + return; + +} + + // local helper function to fill madgraph momenta. +void fillMGmom(double * mom,Lorentz5Momentum lmom){ + mom[0]=lmom.t()/GeV; + mom[1]=lmom.x()/GeV; + mom[2]=lmom.y()/GeV; + mom[3]=lmom.z()/GeV; +} + + +bool Colorea::produceSwapping(list::iterator dipi, + list::iterator dipj, + list::iterator dipk,bool FF){ + + // get the process for all tripple dipole swappings. + static auto pro= eeuugg(); + + // set mass of q qbar + pro.setMass( 3 , dipi->leftParticle()->momentum().m()/GeV); + pro.setMass( 4 , dipk->rightParticle()->momentum().m()/GeV); + + // If the central dipole dipj is not a FF-dipole the rearragment is + // not a simple swapping of gluon momenta. We need to take care that + // the 'new' dipoles get the correct fraction, pdf and index assignments. + if(!FF){ + // for the interfacing with madgraph we need new momenta + double mom0[4], mom1[4], mom2[4]; + double mom3[4], mom4[4], mom5[4]; + + //q + double prefact=1.;//dipi->leftFraction()!=0.?-1.:1.; ?? + auto PP=dipi->leftParticle()->momentum(); + PP.setX(prefact*PP.x()); + PP.setY(prefact*PP.y()); + PP.setZ(prefact*PP.z()); + // get the momentum sum for the triple dipole system. + // we need this for the incoming e+e-. + auto fmomsum=PP; + // lets rotate the system to be sure that momenta + // are not misinterpreted as incomming. + PP=PP.rotateX(0.3); + fillMGmom(mom2,PP); + + + //qbar + prefact=1.;//dipk->rightFraction()!=0.?-1.:1.; + PP=dipk->rightParticle()->momentum(); + PP.setX(prefact*PP.x()); + PP.setY(prefact*PP.y()); + PP.setZ(prefact*PP.z()); + fmomsum+=PP; + PP=PP.rotateX(0.3); + fillMGmom(mom3,PP); + + //g1 + prefact=1.;//dipj->leftFraction()!=0.?-1.:1.; + PP=dipj->leftParticle()->momentum(); + PP.setX(prefact*PP.x()); + PP.setY(prefact*PP.y()); + PP.setZ(prefact*PP.z()); + fmomsum+=PP; + PP=PP.rotateX(0.3); + fillMGmom(mom4,PP); + + //g2 + prefact=1.;//dipj->rightFraction()!=0.?-1.:1.; + PP=dipj->rightParticle()->momentum(); + PP.setX(prefact*PP.x()); + PP.setY(prefact*PP.y()); + PP.setZ(prefact*PP.z()); + fmomsum+=PP; + PP=PP.rotateX(0.3); + fillMGmom(mom5,PP); + + // get the boost to to triple dipole restframe + auto boostto=fmomsum.findBoostToCM(); + // center of mass energy. + auto CME=fmomsum.m2(); + // construct incoming momenta. + // point incoming axis along arbitrary y axis; + Lorentz5Momentum in1=Lorentz5Momentum(ZERO,sqrt(CME)/2.,ZERO,sqrt(CME)/2.); + Lorentz5Momentum in2=Lorentz5Momentum(ZERO,-sqrt(CME)/2.,ZERO,sqrt(CME)/2.); + + in1=in1.boost(-boostto); + in1=in1.rotateX(0.3); + in2=in2.boost(-boostto); + in2=in2.rotateX(0.3); + fillMGmom(mom0,in1); + fillMGmom(mom1,in2); + + vector < double * > momenta{{ mom0, mom1, mom2, + mom3, mom4, mom5}}; + + // calculate the permutation from madgraph process. + auto perm=pro.producePermutation(UseRandom::rnd(),momenta); + // for tripple dipoles there is only one possible permutation. + bool didperm=perm[0]!=5; + + if(!didperm) return didperm; + + // insert the original dipj fractions + vector tmpfrac{{dipj->leftFraction(),dipj->rightFraction()}}; + // insert the original dipj pdfs + vector< PDF > tmppdf; + tmppdf.push_back(dipj->leftPDF()); + tmppdf.push_back(dipj->rightPDF()); + // insert the original dipj particles + vector tmppart; + tmppart.push_back(dipj->leftParticle()); + tmppart.push_back(dipj->rightParticle()); + // make sure the dipj are gluons. + assert(dipj->leftParticle()->id()==21); + assert(dipj->rightParticle()->id()==21); + + // Now set the new or old particles in the dipole + dipi->rightParticle(tmppart[perm[0]-1-4]); + dipj->leftParticle (tmppart[perm[0]-1-4]); + dipj->rightParticle(tmppart[perm[1]-1-4]); + dipk->leftParticle(tmppart[perm[1]-1-4]); + + dipi->rightPDF(tmppdf[perm[0]-1-4]); + dipj->leftPDF (tmppdf[perm[0]-1-4]); + dipj->rightPDF(tmppdf[perm[1]-1-4]); + dipk->leftPDF (tmppdf[perm[1]-1-4]); + + dipi->rightFraction(tmpfrac[perm[0]-1-4]); + dipj->leftFraction (tmpfrac[perm[0]-1-4]); + dipj->rightFraction(tmpfrac[perm[1]-1-4]); + dipk->leftFraction (tmpfrac[perm[1]-1-4]); + + + auto firstindex =DipoleIndex(&(dipj->leftParticle()->data()), + &(dipj->rightParticle()->data()), + dipj->leftPDF(), + dipj->rightPDF()); + auto secondindex =DipoleIndex(&(dipj->rightParticle()->data()), + &(dipj->leftParticle()->data()), + dipj->rightPDF(), + dipj->leftPDF()); + dipj->setFirstIndex(firstindex); + dipj->setSecondIndex(secondindex); + + auto firstindex2 =DipoleIndex(&(dipi->leftParticle()->data()), + &(dipi->rightParticle()->data()), + dipi->leftPDF(), + dipi->rightPDF()); + auto secondindex2 =DipoleIndex(&(dipi->rightParticle()->data()), + &(dipi->leftParticle()->data()), + dipi->rightPDF(), + dipi->leftPDF()); + dipi->setFirstIndex(firstindex2); + dipi->setSecondIndex(secondindex2); + + auto firstindex3 =DipoleIndex(&(dipk->leftParticle()->data()), + &(dipk->rightParticle()->data()), + dipk->leftPDF(), + dipk->rightPDF()); + auto secondindex3 =DipoleIndex(&(dipk->rightParticle()->data()), + &(dipk->leftParticle()->data()), + dipk->rightPDF(), + dipk->leftPDF()); + dipk->setFirstIndex(firstindex3); + dipk->setSecondIndex(secondindex3); + // check a few things + // assert(dipj->leftFraction()!=1.&&(dipj->leftPDF().pdf() ) || dipj->leftFraction()==1. &&!(dipj->leftPDF().pdf())); + // assert(dipj->rightFraction()!=1.&&(dipj->rightPDF().pdf() )|| dipj->rightFraction()==1.&&!(dipj->rightPDF().pdf())); + // assert(dipi->leftFraction()!=1.&&(dipi->leftPDF().pdf() ) || dipi->leftFraction()==1. &&!(dipi->leftPDF().pdf())); + // assert(dipi->rightFraction()!=1.&&(dipi->rightPDF().pdf() )|| dipi->rightFraction()==1.&&!(dipi->rightPDF().pdf())); + // assert(dipk->leftFraction()!=1.&&(dipk->leftPDF().pdf() ) || dipk->leftFraction()==1. &&!(dipk->leftPDF().pdf())); + // assert(dipk->rightFraction()!=1.&&(dipk->rightPDF().pdf() )|| dipk->rightFraction()==1.&&!(dipk->rightPDF().pdf())); + + return didperm; + }else{ + // if dipj is a FF dipole the color rearrangement is done by + // swapping the gluon momenta. Let's do this! + + double mom0[4]; + double mom1[4]; + double mom2[4]; + double mom3[4]; + double mom4[4]; + double mom5[4]; + vector tmpvec; + + //q + auto PP=dipi->leftParticle()->momentum(); + auto fmomsum=PP; + PP=PP.rotateX(0.3); + fillMGmom(mom2,PP); + + //qbar + PP=dipk->rightParticle()->momentum(); + fmomsum+=PP; + PP=PP.rotateX(0.3); + fillMGmom(mom3,PP); + + //g1 + PP=dipj->leftParticle()->momentum(); + fmomsum+=PP; + PP=PP.rotateX(0.3); + fillMGmom(mom4,PP); + + //g2 + PP=dipj->rightParticle()->momentum(); + fmomsum+=PP; + PP=PP.rotateX(0.3); + fillMGmom(mom5,PP); + + // get the boost to to triple dipole restframe + auto boostto=fmomsum.findBoostToCM(); + + auto CME=fmomsum.m2(); + // point incoming axis along arbitrary y axis; + Lorentz5Momentum in1=Lorentz5Momentum(ZERO,sqrt(CME)/2.,ZERO,sqrt(CME)/2.); + Lorentz5Momentum in2=Lorentz5Momentum(ZERO,-sqrt(CME)/2.,ZERO,sqrt(CME)/2.); + + + + assert(dipj->leftParticle()->id()==21); + assert(dipj->rightParticle()->id()==21); + + in1=in1.boost(-boostto); + in1=in1.rotateX(0.3); + in2=in2.boost(-boostto); + in2=in2.rotateX(0.3); + fillMGmom(mom0,in1); + fillMGmom(mom1,in2); + + vector < double * > momenta{{ mom0, mom1, mom2, + mom3, mom4, mom5}}; + + // calculate the permutation from madgraph process. + auto perm=pro.producePermutation(UseRandom::rnd(),momenta); + + bool didperm=perm[0]!=5; + + // For final state we can just swap gluon momenta. + tmpvec.push_back(dipj->leftParticle()->momentum()); // g1 + tmpvec.push_back(dipj->rightParticle()->momentum()); // g2 + + dipj->leftParticle() ->setMomentum(tmpvec[perm[0]-1-4]); + dipj->rightParticle()->setMomentum(tmpvec[perm[1]-1-4]); + + return didperm; + } + +} + + + + + +void Colorea::rearrange4(list::iterator dipi, + list::iterator dipj, + list::iterator dipk, + list::iterator dipl){ + + assert(dipk->leftParticle()==dipj->rightParticle()); + assert(dipl->leftParticle()==dipk->rightParticle()); + + double mom0[4], mom1[4], mom2[4], mom3[4]; + double mom6[4], mom4[4], mom5[4]; + + // q g1 g2 g3 qbar + // il -- ir=jl -- jr=kl -- kr=ll -- lr + + //q + fillMGmom(mom2,dipi->leftParticle()->momentum()); + //qbar + fillMGmom(mom3,dipl->rightParticle()->momentum()); + //g1 + fillMGmom(mom4,dipj->leftParticle()->momentum()); + //g2 + fillMGmom(mom5,dipj->rightParticle()->momentum()); + //g3 + fillMGmom(mom6,dipl->leftParticle()->momentum()); + + // q g1 g2 g3 qbar + // il -- ir=jl -- jr=kl -- kr=ll -- lr + auto fmomsum=dipi->leftParticle()->momentum()+ + dipj->leftParticle()->momentum()+ + dipj->rightParticle()->momentum()+ + dipl->leftParticle()->momentum()+ + dipl->rightParticle()->momentum(); + + auto boostto=fmomsum.findBoostToCM(); + + auto CME=fmomsum.m2(); + // point incoming axis along arbitrary y axis; + Lorentz5Momentum in1=Lorentz5Momentum(ZERO,sqrt(CME)/2.,ZERO,sqrt(CME)/2.); + Lorentz5Momentum in2=Lorentz5Momentum(ZERO,-sqrt(CME)/2.,ZERO,sqrt(CME)/2.); + + in1=in1.boost(-boostto); + in2=in2.boost(-boostto); + fillMGmom(mom0,in1); + fillMGmom(mom1,in2); + + vector < double * > momenta{{ mom0, mom1, + mom2, mom3, + mom4, mom5, mom6}}; + + static auto pro= eeuuggg(); + + // set mass of q qbar + pro.setMass( 3 , dipi->leftParticle()->momentum().m()/GeV); + pro.setMass( 5 , dipl->rightParticle()->momentum().m()/GeV); + + + auto perm=pro.producePermutation(UseRandom::rnd(),momenta); + + vector tmpvec; + tmpvec.push_back(dipj->leftParticle()->momentum()); // g1 + tmpvec.push_back(dipj->rightParticle()->momentum()); // g2 + tmpvec.push_back(dipl->leftParticle()->momentum()); // g3 + + dipj->leftParticle() ->setMomentum(tmpvec[perm[0]-1-4]); + dipj->rightParticle()->setMomentum(tmpvec[perm[1]-1-4]); + dipl->leftParticle() ->setMomentum(tmpvec[perm[2]-1-4]); + +} + + + + + +void Colorea::rearrange5(list::iterator dipi, + list::iterator dipj, + list::iterator dipk, + list::iterator dipl, + list::iterator dipm){ + + assert(dipk->leftParticle()==dipj->rightParticle()); + assert(dipl->leftParticle()==dipk->rightParticle()); + + + double mom0[4], mom1[4], mom2[4], mom3[4]; + double mom4[4], mom5[4], mom6[4], mom7[4]; + // q g1 g2 g3 g4 qbar + // il -- ir=jl -- jr=kl -- kr=ll -- lr=ml -- mr + + //q + fillMGmom(mom2,dipi->leftParticle()->momentum()); + //qbar + fillMGmom(mom3,dipm->rightParticle()->momentum()); + //g1 + fillMGmom(mom4,dipj->leftParticle()->momentum()); + //g2 + fillMGmom(mom5,dipj->rightParticle()->momentum()); + //g3 + fillMGmom(mom6,dipl->leftParticle()->momentum()); + //g4 + fillMGmom(mom7,dipm->leftParticle()->momentum()); + + // q g1 g2 g3 g4 qbar + // il -- ir=jl -- jr=kl -- kr=ll -- lr=ml -- mr + auto fmomsum=dipi->leftParticle()->momentum()+ + dipj->leftParticle()->momentum()+ + dipj->rightParticle()->momentum()+ + dipl->leftParticle()->momentum()+ + dipl->rightParticle()->momentum()+ + dipm->rightParticle()->momentum(); + + auto boostto=fmomsum.findBoostToCM(); + + auto CME=fmomsum.m2(); + // point incoming axis along arbitrary y axis; + Lorentz5Momentum in1=Lorentz5Momentum(ZERO,sqrt(CME)/2.,ZERO,sqrt(CME)/2.); + Lorentz5Momentum in2=Lorentz5Momentum(ZERO,-sqrt(CME)/2.,ZERO,sqrt(CME)/2.); + + + in1=in1.boost(-boostto); + in2=in2.boost(-boostto); + fillMGmom(mom0,in1); + fillMGmom(mom1,in2); + + vector < double * > momenta{{ mom0, mom1, mom2, mom3, + mom4, mom5, mom6, mom7}}; + + static auto pro= eeuugggg(); + + // set mass of q qbar + pro.setMass( 3 , dipi->leftParticle()->momentum().m()/GeV); + pro.setMass( 5 , dipl->rightParticle()->momentum().m()/GeV); + + auto perm=pro.producePermutation(UseRandom::rnd(),momenta); + + vector tmpvec; + tmpvec.push_back(dipj->leftParticle()->momentum()); // g1 + tmpvec.push_back(dipj->rightParticle()->momentum()); // g2 + tmpvec.push_back(dipl->leftParticle()->momentum()); // g3 + tmpvec.push_back(dipm->leftParticle()->momentum()); // g4 + + // set the gluon momenta with permuted momenta. + dipj->leftParticle() ->setMomentum(tmpvec[perm[0]-1-4]); + dipj->rightParticle()->setMomentum(tmpvec[perm[1]-1-4]); + dipl->leftParticle() ->setMomentum(tmpvec[perm[2]-1-4]); + dipm->leftParticle() ->setMomentum(tmpvec[perm[3]-1-4]); + +} + + + + + + diff --git a/Shower/Dipole/Colorea/Colorea.fh b/Shower/Dipole/Colorea/Colorea.fh new file mode 100644 --- /dev/null +++ b/Shower/Dipole/Colorea/Colorea.fh @@ -0,0 +1,21 @@ +// -*- C++ -*- +// This is the forward declaration of the Colorea class + +#ifndef HERWIG_Colorea_FH +#define HERWIG_Colorea_FH + +#include "ThePEG/Config/ThePEG.h" +#include "ThePEG/Config/Pointers.h" + + +namespace Herwig { + +class Colorea; +using namespace ThePEG; + + ThePEG_DECLARE_POINTERS(Colorea , ColoreaPtr ); + + +} + +#endif // HERWIG_Colorea_FH diff --git a/Shower/Dipole/Colorea/Colorea.h b/Shower/Dipole/Colorea/Colorea.h new file mode 100644 --- /dev/null +++ b/Shower/Dipole/Colorea/Colorea.h @@ -0,0 +1,147 @@ +// -*- C++ -*- +// +// Colorea.h is a part of Herwig - A multi-purpose Monte Carlo event generator +// Copyright (C) 2002-2017 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_Colorea_H +#define HERWIG_Colorea_H +// +// This is the declaration of the Colorea class. +// +#include "Herwig/Shower/Dipole/Base/DipoleChain.fh" +#include "Herwig/Shower/Dipole/Base/Dipole.h" + +namespace Herwig { + +using namespace ThePEG; + +/** + * \ingroup DipoleShower + * \author Johannes Bellm + * + * This class implemets the method described in arXiv:1801.06113. + * and it's extension described in arXiv:180X.XXXXX. + * It allows to calculate the probability to rearrange + * dipole chains with simple matrix elements. + * + * The implementation currently allows: + * - rearranging pure FF dipole chains with + * processes: eeuugg eeuuggg and eeuugggg + * - IF or FI dipoles can be rearranged with eeuugg. + * - II should not be rearranged. + * - masses of the q qbar particles are set. + * + */ +class Colorea { + +public: + + /** + * Default constructor + */ + Colorea(); + + /** + * main function to rearrange the dipole chain. + * - dipmax: chains with dipmax are rearranged with matix elements including + * dipmax dipoles: + * dipmax=3 -> eeuugg + * dipmax=4 -> eeuuggg + * dipmax=5 -> eeuugggg + * if a chain contains more than dipmax dipoles, we treat the chain + * as long. + * - diplong: this parameter allows to change the behaviour for Coloreas + * that are longer than dipmax (long chains). + * If diplong is 3 the chain is rearranged with eeuugg + * matrix elements. + * If diplong is 4 the chain is rearranged with eeuuggg + * matrix elements. diplong > 4 is currently not implemented. + * Note: We dont observe a difference between the diplong=3 or + * diplong=4 treatment. + */ + void rearrange(int dipmax,int diplong); + + /** + * Set the chain to use in the rearrangement. + */ + void setChain(Ptr::tptr ch){theChain=ch;}; + + // Everything below is private. The rearranging is acting only on the current chain. + private: + /** + * Main function for rearranging tripple dipoles. + */ + void rearrange3(list::iterator dipi, + list::iterator dipj, + list::iterator dipk); + + /** + * Function to rearrange triple dipoles in the all FF dipole case. + */ + void rearrange3_FF_FF_FF(list::iterator dipi, + list::iterator dipj, + list::iterator dipk); + + /** + * Function to rearrange triple dipoles if dipj is FI dipole. + * This function is also used for IF. + */ + void rearrange3_FF_FI_IF(list::iterator dipi, + list::iterator dipj, + list::iterator dipk); + /** + * Main function for rearranging 4 dipoles. + * This funtion currently only implements the case of 4 FF dipoles. + */ + void rearrange4(list::iterator dipi, + list::iterator dipj, + list::iterator dipk, + list::iterator dipl); + /** + * Main function for rearranging 5 dipoles. + * This funtion currently only implements the case of 5 FF dipoles. + */ + void rearrange5(list::iterator dipi, + list::iterator dipj, + list::iterator dipk, + list::iterator dipl, + list::iterator dipm); + /** + * Rearrange long chains. + */ + void rearrangeLong(int diplong); + + /** + * Produce the possible swapping or the dipj gluons. + */ + bool produceSwapping(list::iterator dipi, + list::iterator dipj, + list::iterator dipk,bool FF); + + // helper function to remove particles from color line if color line connects them. + void rmcol(tColinePtr A,tColinePtr B, list::iterator & dip); + + // remove connecting color lines from these dipoles + void removeColors(list::iterator dipi, + list::iterator dipj, + list::iterator dipk); + + // Access the dipoles of the current chain. + list& dipoles(); + + private: + // the current chain to rearrange. + Ptr::tptr theChain; + +}; + +inline ostream& operator << (ostream& os, const Colorea& ) { + return os; +} + +} + +#endif /* HERWIG_Colorea_H */ diff --git a/Shower/Dipole/Colorea/HelAmps_sm.cc b/Shower/Dipole/Colorea/HelAmps_sm.cc new file mode 100644 --- /dev/null +++ b/Shower/Dipole/Colorea/HelAmps_sm.cc @@ -0,0 +1,1035 @@ +//========================================================================== +// This file has been automatically generated for C++ Standalone by +// MadGraph5_aMC@NLO v. 2.5.4, 2017-03-28 +// By the MadGraph5_aMC@NLO Development Team +// Visit launchpad.net/madgraph5 and amcatnlo.web.cern.ch +//========================================================================== + +#include "HelAmps_sm.h" +#include +#include +#include +#include +using namespace std; + +namespace MG5_sm_COLOREA +{ + +void ixxxxx(double p[4], double fmass, int nhel, int nsf, complex fi[6]) +{ + complex chi[2]; + double sf[2], sfomega[2], omega[2], pp, pp3, sqp0p3, sqm[2]; + int ip, im, nh; + fi[0] = complex (-p[0] * nsf, -p[3] * nsf); + fi[1] = complex (-p[1] * nsf, -p[2] * nsf); + nh = nhel * nsf; + if (fmass != 0.0) + { + pp = min(p[0], sqrt(p[1] * p[1] + p[2] * p[2] + p[3] * p[3])); + if (pp == 0.0) + { + sqm[0] = sqrt(std::abs(fmass)); + sqm[1] = Sgn(sqm[0], fmass); + ip = (1 + nh)/2; + im = (1 - nh)/2; + fi[2] = ip * sqm[ip]; + fi[3] = im * nsf * sqm[ip]; + fi[4] = ip * nsf * sqm[im]; + fi[5] = im * sqm[im]; + } + else + { + sf[0] = (1 + nsf + (1 - nsf) * nh) * 0.5; + sf[1] = (1 + nsf - (1 - nsf) * nh) * 0.5; + omega[0] = sqrt(p[0] + pp); + omega[1] = fmass/omega[0]; + ip = (1 + nh)/2; + im = (1 - nh)/2; + sfomega[0] = sf[0] * omega[ip]; + sfomega[1] = sf[1] * omega[im]; + pp3 = max(pp + p[3], 0.0); + chi[0] = complex (sqrt(pp3 * 0.5/pp), 0); + if (pp3 == 0.0) + { + chi[1] = complex (-nh, 0); + } + else + { + chi[1] = complex (nh * p[1], p[2])/sqrt(2.0 * pp * pp3); + } + fi[2] = sfomega[0] * chi[im]; + fi[3] = sfomega[0] * chi[ip]; + fi[4] = sfomega[1] * chi[im]; + fi[5] = sfomega[1] * chi[ip]; + } + } + else + { + if (p[1] == 0.0 and p[2] == 0.0 and p[3] < 0.0) + { + sqp0p3 = 0.0; + } + else + { + sqp0p3 = sqrt(max(p[0] + p[3], 0.0)) * nsf; + } + chi[0] = complex (sqp0p3, 0.0); + if (sqp0p3 == 0.0) + { + chi[1] = complex (-nhel * sqrt(2.0 * p[0]), 0.0); + } + else + { + chi[1] = complex (nh * p[1], p[2])/sqp0p3; + } + if (nh == 1) + { + fi[2] = complex (0.0, 0.0); + fi[3] = complex (0.0, 0.0); + fi[4] = chi[0]; + fi[5] = chi[1]; + } + else + { + fi[2] = chi[1]; + fi[3] = chi[0]; + fi[4] = complex (0.0, 0.0); + fi[5] = complex (0.0, 0.0); + } + } + return; +} + + +double Sgn(double a, double b) +{ + return (b < 0)? - abs(a):abs(a); +} + + +void txxxxx(double p[4], double tmass, int nhel, int nst, complex + tc[18]) +{ + complex ft[6][4], ep[4], em[4], e0[4]; + double pt, pt2, pp, pzpt, emp, sqh, sqs; + int i, j; + + sqh = sqrt(0.5); + sqs = sqrt(0.5/3); + + pt2 = p[1] * p[1] + p[2] * p[2]; + pp = min(p[0], sqrt(pt2 + p[3] * p[3])); + pt = min(pp, sqrt(pt2)); + + ft[4][0] = complex (p[0] * nst, p[3] * nst); + ft[5][0] = complex (p[1] * nst, p[2] * nst); + + // construct eps+ + if(nhel >= 0) + { + if(pp == 0) + { + ep[0] = complex (0, 0); + ep[1] = complex (-sqh, 0); + ep[2] = complex (0, nst * sqh); + ep[3] = complex (0, 0); + } + else + { + ep[0] = complex (0, 0); + ep[3] = complex (pt/pp * sqh, 0); + + if(pt != 0) + { + pzpt = p[3]/(pp * pt) * sqh; + ep[1] = complex (-p[1] * pzpt, -nst * p[2]/pt * sqh); + ep[2] = complex (-p[2] * pzpt, nst * p[1]/pt * sqh); + } + else + { + ep[1] = complex (-sqh, 0); + ep[2] = complex (0, nst * Sgn(sqh, p[3])); + } + } + + } + + // construct eps- + if(nhel <= 0) + { + if(pp == 0) + { + em[0] = complex (0, 0); + em[1] = complex (sqh, 0); + em[2] = complex (0, nst * sqh); + em[3] = complex (0, 0); + } + else + { + em[0] = complex (0, 0); + em[3] = complex (-pt/pp * sqh, 0); + + if(pt != 0) + { + pzpt = -p[3]/(pp * pt) * sqh; + em[1] = complex (-p[1] * pzpt, -nst * p[2]/pt * sqh); + em[2] = complex (-p[2] * pzpt, nst * p[1]/pt * sqh); + } + else + { + em[1] = complex (sqh, 0); + em[2] = complex (0, nst * Sgn(sqh, p[3])); + } + } + } + + // construct eps0 + if(std::labs(nhel) <= 1) + { + if(pp == 0) + { + e0[0] = complex (0, 0); + e0[1] = complex (0, 0); + e0[2] = complex (0, 0); + e0[3] = complex (1, 0); + } + else + { + emp = p[0]/(tmass * pp); + e0[0] = complex (pp/tmass, 0); + e0[3] = complex (p[3] * emp, 0); + + if(pt != 0) + { + e0[1] = complex (p[1] * emp, 0); + e0[2] = complex (p[2] * emp, 0); + } + else + { + e0[1] = complex (0, 0); + e0[2] = complex (0, 0); + } + } + } + + if(nhel == 2) + { + for(j = 0; j < 4; j++ ) + { + for(i = 0; i < 4; i++ ) + ft[i][j] = ep[i] * ep[j]; + } + } + else if(nhel == -2) + { + for(j = 0; j < 4; j++ ) + { + for(i = 0; i < 4; i++ ) + ft[i][j] = em[i] * em[j]; + } + } + else if(tmass == 0) + { + for(j = 0; j < 4; j++ ) + { + for(i = 0; i < 4; i++ ) + ft[i][j] = 0; + } + } + else if(tmass != 0) + { + if(nhel == 1) + { + for(j = 0; j < 4; j++ ) + { + for(i = 0; i < 4; i++ ) + ft[i][j] = sqh * (ep[i] * e0[j] + e0[i] * ep[j]); + } + } + else if(nhel == 0) + { + for(j = 0; j < 4; j++ ) + { + for(i = 0; i < 4; i++ ) + ft[i][j] = sqs * (ep[i] * em[j] + em[i] * ep[j] + + 2.0 * e0[i] * e0[j]); + } + } + else if(nhel == -1) + { + for(j = 0; j < 4; j++ ) + { + for(i = 0; i < 4; i++ ) + ft[i][j] = sqh * (em[i] * e0[j] + e0[i] * em[j]); + } + } + else + { + std::cerr << "Invalid helicity in txxxxx.\n"; + std::exit(1); + } + } + + tc[0] = ft[4][0]; + tc[1] = ft[5][0]; + + for(j = 0; j < 4; j++ ) + { + for(i = 0; i < 4; i++ ) + tc[j * 4 + i + 2] = ft[j][i]; + } +} + +void vxxxxx(double p[4], double vmass, int nhel, int nsv, complex vc[6]) +{ + double hel, hel0, pt, pt2, pp, pzpt, emp, sqh; + int nsvahl; + sqh = sqrt(0.5); + hel = double(nhel); + nsvahl = nsv * std::abs(hel); + pt2 = (p[1] * p[1]) + (p[2] * p[2]); + pp = min(p[0], sqrt(pt2 + (p[3] * p[3]))); + pt = min(pp, sqrt(pt2)); + vc[0] = complex (p[0] * nsv, p[3] * nsv); + vc[1] = complex (p[1] * nsv, p[2] * nsv); + if (vmass != 0.0) + { + hel0 = 1.0 - std::abs(hel); + if(pp == 0.0) + { + vc[2] = complex (0.0, 0.0); + vc[3] = complex (-hel * sqh, 0.0); + vc[4] = complex (0.0, nsvahl * sqh); + vc[5] = complex (hel0, 0.0); + } + else + { + emp = p[0]/(vmass * pp); + vc[2] = complex (hel0 * pp/vmass, 0.0); + vc[5] = complex (hel0 * p[3] * emp + hel * pt/pp * sqh, 0.0); + if (pt != 0.0) + { + pzpt = p[3]/(pp * pt) * sqh * hel; + vc[3] = complex (hel0 * p[1] * emp - p[1] * pzpt, -nsvahl * + p[2]/pt * sqh); + vc[4] = complex (hel0 * p[2] * emp - p[2] * pzpt, nsvahl * + p[1]/pt * sqh); + } + else + { + vc[3] = complex (-hel * sqh, 0.0); + vc[4] = complex (0.0, nsvahl * Sgn(sqh, p[3])); + } + } + } + else + { + pp = p[0]; + pt = sqrt((p[1] * p[1]) + (p[2] * p[2])); + vc[2] = complex (0.0, 0.0); + vc[5] = complex (hel * pt/pp * sqh, 0.0); + if (pt != 0.0) + { + pzpt = p[3]/(pp * pt) * sqh * hel; + vc[3] = complex (-p[1] * pzpt, -nsv * p[2]/pt * sqh); + vc[4] = complex (-p[2] * pzpt, nsv * p[1]/pt * sqh); + } + else + { + vc[3] = complex (-hel * sqh, 0.0); + vc[4] = complex (0.0, nsv * Sgn(sqh, p[3])); + } + } + return; +} + +void sxxxxx(double p[4], int nss, complex sc[3]) +{ + sc[2] = complex (1.00, 0.00); + sc[0] = complex (p[0] * nss, p[3] * nss); + sc[1] = complex (p[1] * nss, p[2] * nss); + return; +} + +void oxxxxx(double p[4], double fmass, int nhel, int nsf, complex fo[6]) +{ + complex chi[2]; + double sf[2], sfomeg[2], omega[2], pp, pp3, sqp0p3, sqm[2]; + int nh, ip, im; + fo[0] = complex (p[0] * nsf, p[3] * nsf); + fo[1] = complex (p[1] * nsf, p[2] * nsf); + nh = nhel * nsf; + if (fmass != 0.000) + { + pp = min(p[0], sqrt((p[1] * p[1]) + (p[2] * p[2]) + (p[3] * p[3]))); + if (pp == 0.000) + { + sqm[0] = sqrt(std::abs(fmass)); + sqm[1] = Sgn(sqm[0], fmass); + ip = -((1 - nh)/2) * nhel; + im = (1 + nh)/2 * nhel; + fo[2] = im * sqm[std::abs(ip)]; + fo[3] = ip * nsf * sqm[std::abs(ip)]; + fo[4] = im * nsf * sqm[std::abs(im)]; + fo[5] = ip * sqm[std::abs(im)]; + } + else + { + pp = min(p[0], sqrt((p[1] * p[1]) + (p[2] * p[2]) + (p[3] * p[3]))); + sf[0] = double(1 + nsf + (1 - nsf) * nh) * 0.5; + sf[1] = double(1 + nsf - (1 - nsf) * nh) * 0.5; + omega[0] = sqrt(p[0] + pp); + omega[1] = fmass/omega[0]; + ip = (1 + nh)/2; + im = (1 - nh)/2; + sfomeg[0] = sf[0] * omega[ip]; + sfomeg[1] = sf[1] * omega[im]; + pp3 = max(pp + p[3], 0.00); + chi[0] = complex (sqrt(pp3 * 0.5/pp), 0.00); + if (pp3 == 0.00) + { + chi[1] = complex (-nh, 0.00); + } + else + { + chi[1] = complex (nh * p[1], -p[2])/sqrt(2.0 * pp * pp3); + } + fo[2] = sfomeg[1] * chi[im]; + fo[3] = sfomeg[1] * chi[ip]; + fo[4] = sfomeg[0] * chi[im]; + fo[5] = sfomeg[0] * chi[ip]; + } + } + else + { + if((p[1] == 0.00) and (p[2] == 0.00) and (p[3] < 0.00)) + { + sqp0p3 = 0.00; + } + else + { + sqp0p3 = sqrt(max(p[0] + p[3], 0.00)) * nsf; + } + chi[0] = complex (sqp0p3, 0.00); + if(sqp0p3 == 0.000) + { + chi[1] = complex (-nhel, 0.00) * sqrt(2.0 * p[0]); + } + else + { + chi[1] = complex (nh * p[1], -p[2])/sqp0p3; + } + if(nh == 1) + { + fo[2] = chi[0]; + fo[3] = chi[1]; + fo[4] = complex (0.00, 0.00); + fo[5] = complex (0.00, 0.00); + } + else + { + fo[2] = complex (0.00, 0.00); + fo[3] = complex (0.00, 0.00); + fo[4] = chi[1]; + fo[5] = chi[0]; + } + } + return; +} + +void FFV1P0_3(std::complex F1[], std::complex F2[], + std::complex COUP, double M3, double W3, std::complex V3[]) +{ + static std::complex cI = std::complex (0., 1.); + double P3[4]; + std::complex denom; + V3[0] = +F1[0] + F2[0]; + V3[1] = +F1[1] + F2[1]; + P3[0] = -V3[0].real(); + P3[1] = -V3[1].real(); + P3[2] = -V3[1].imag(); + P3[3] = -V3[0].imag(); + denom = COUP/((P3[0] * P3[0]) - (P3[1] * P3[1]) - (P3[2] * P3[2]) - (P3[3] * + P3[3]) - M3 * (M3 - cI * W3)); + V3[2] = denom * (-cI) * (F1[2] * F2[4] + F1[3] * F2[5] + F1[4] * F2[2] + + F1[5] * F2[3]); + V3[3] = denom * (-cI) * (F1[4] * F2[3] + F1[5] * F2[2] - F1[2] * F2[5] - + F1[3] * F2[4]); + V3[4] = denom * (-cI) * (-cI * (F1[2] * F2[5] + F1[5] * F2[2]) + cI * (F1[3] + * F2[4] + F1[4] * F2[3])); + V3[5] = denom * (-cI) * (F1[3] * F2[5] + F1[4] * F2[2] - F1[2] * F2[4] - + F1[5] * F2[3]); +} + + +void FFV2_2(std::complex F1[], std::complex V3[], + std::complex COUP, double M2, double W2, std::complex F2[]) +{ + static std::complex cI = std::complex (0., 1.); + double P2[4]; + std::complex denom; + F2[0] = +F1[0] + V3[0]; + F2[1] = +F1[1] + V3[1]; + P2[0] = -F2[0].real(); + P2[1] = -F2[1].real(); + P2[2] = -F2[1].imag(); + P2[3] = -F2[0].imag(); + denom = COUP/((P2[0] * P2[0]) - (P2[1] * P2[1]) - (P2[2] * P2[2]) - (P2[3] * + P2[3]) - M2 * (M2 - cI * W2)); + F2[2] = denom * cI * (F1[2] * (P2[0] * (V3[2] + V3[5]) + (P2[1] * (-1.) * + (V3[3] + cI * (V3[4])) + (P2[2] * (+cI * (V3[3]) - V3[4]) - P2[3] * + (V3[2] + V3[5])))) + F1[3] * (P2[0] * (V3[3] - cI * (V3[4])) + (P2[1] * + (V3[5] - V3[2]) + (P2[2] * (-cI * (V3[5]) + cI * (V3[2])) + P2[3] * (+cI + * (V3[4]) - V3[3]))))); + F2[3] = denom * cI * (F1[2] * (P2[0] * (V3[3] + cI * (V3[4])) + (P2[1] * + (-1.) * (V3[2] + V3[5]) + (P2[2] * (-1.) * (+cI * (V3[2] + V3[5])) + + P2[3] * (V3[3] + cI * (V3[4]))))) + F1[3] * (P2[0] * (V3[2] - V3[5]) + + (P2[1] * (+cI * (V3[4]) - V3[3]) + (P2[2] * (-1.) * (V3[4] + cI * + (V3[3])) + P2[3] * (V3[2] - V3[5]))))); + F2[4] = denom * - cI * M2 * (F1[2] * (-1.) * (V3[2] + V3[5]) + F1[3] * (+cI * + (V3[4]) - V3[3])); + F2[5] = denom * cI * M2 * (F1[2] * (V3[3] + cI * (V3[4])) + F1[3] * (V3[2] - + V3[5])); +} + +void FFV2_5_2(std::complex F1[], std::complex V3[], + std::complex COUP1, std::complex COUP2, double M2, double + W2, std::complex F2[]) +{ + static std::complex cI = std::complex (0., 1.); + std::complex Ftmp[6]; + double P2[4]; + std::complex denom; + int i; + FFV2_2(F1, V3, COUP1, M2, W2, F2); + FFV5_2(F1, V3, COUP2, M2, W2, Ftmp); + i = 2; + while (i < 6) + { + F2[i] = F2[i] + Ftmp[i]; + i++; + } +} + +void FFV1_2(std::complex F1[], std::complex V3[], + std::complex COUP, double M2, double W2, std::complex F2[]) +{ + static std::complex cI = std::complex (0., 1.); + double P2[4]; + std::complex denom; + F2[0] = +F1[0] + V3[0]; + F2[1] = +F1[1] + V3[1]; + P2[0] = -F2[0].real(); + P2[1] = -F2[1].real(); + P2[2] = -F2[1].imag(); + P2[3] = -F2[0].imag(); + denom = COUP/((P2[0] * P2[0]) - (P2[1] * P2[1]) - (P2[2] * P2[2]) - (P2[3] * + P2[3]) - M2 * (M2 - cI * W2)); + F2[2] = denom * cI * (F1[2] * (P2[0] * (V3[2] + V3[5]) + (P2[1] * (-1.) * + (V3[3] + cI * (V3[4])) + (P2[2] * (+cI * (V3[3]) - V3[4]) - P2[3] * + (V3[2] + V3[5])))) + (F1[3] * (P2[0] * (V3[3] - cI * (V3[4])) + (P2[1] * + (V3[5] - V3[2]) + (P2[2] * (-cI * (V3[5]) + cI * (V3[2])) + P2[3] * (+cI + * (V3[4]) - V3[3])))) + M2 * (F1[4] * (V3[2] - V3[5]) + F1[5] * (+cI * + (V3[4]) - V3[3])))); + F2[3] = denom * (-cI) * (F1[2] * (P2[0] * (-1.) * (V3[3] + cI * (V3[4])) + + (P2[1] * (V3[2] + V3[5]) + (P2[2] * (+cI * (V3[2] + V3[5])) - P2[3] * + (V3[3] + cI * (V3[4]))))) + (F1[3] * (P2[0] * (V3[5] - V3[2]) + (P2[1] * + (V3[3] - cI * (V3[4])) + (P2[2] * (V3[4] + cI * (V3[3])) + P2[3] * (V3[5] + - V3[2])))) + M2 * (F1[4] * (V3[3] + cI * (V3[4])) - F1[5] * (V3[2] + + V3[5])))); + F2[4] = denom * (-cI) * (F1[4] * (P2[0] * (V3[5] - V3[2]) + (P2[1] * (V3[3] + + cI * (V3[4])) + (P2[2] * (V3[4] - cI * (V3[3])) + P2[3] * (V3[5] - + V3[2])))) + (F1[5] * (P2[0] * (V3[3] - cI * (V3[4])) + (P2[1] * (-1.) * + (V3[2] + V3[5]) + (P2[2] * (+cI * (V3[2] + V3[5])) + P2[3] * (V3[3] - cI + * (V3[4]))))) + M2 * (F1[2] * (-1.) * (V3[2] + V3[5]) + F1[3] * (+cI * + (V3[4]) - V3[3])))); + F2[5] = denom * cI * (F1[4] * (P2[0] * (-1.) * (V3[3] + cI * (V3[4])) + + (P2[1] * (V3[2] - V3[5]) + (P2[2] * (-cI * (V3[5]) + cI * (V3[2])) + + P2[3] * (V3[3] + cI * (V3[4]))))) + (F1[5] * (P2[0] * (V3[2] + V3[5]) + + (P2[1] * (+cI * (V3[4]) - V3[3]) + (P2[2] * (-1.) * (V3[4] + cI * + (V3[3])) - P2[3] * (V3[2] + V3[5])))) + M2 * (F1[2] * (V3[3] + cI * + (V3[4])) + F1[3] * (V3[2] - V3[5])))); +} + + +void FFV2_0(std::complex F1[], std::complex F2[], + std::complex V3[], std::complex COUP, std::complex + & vertex) +{ + static std::complex cI = std::complex (0., 1.); + std::complex TMP9; + TMP9 = (F1[2] * (F2[4] * (V3[2] + V3[5]) + F2[5] * (V3[3] + cI * (V3[4]))) + + F1[3] * (F2[4] * (V3[3] - cI * (V3[4])) + F2[5] * (V3[2] - V3[5]))); + vertex = COUP * - cI * TMP9; +} + +void FFV2_5_0(std::complex F1[], std::complex F2[], + std::complex V3[], std::complex COUP1, std::complex + COUP2, std::complex & vertex) +{ + static std::complex cI = std::complex (0., 1.); + std::complex tmp; + FFV2_0(F1, F2, V3, COUP1, vertex); + FFV5_0(F1, F2, V3, COUP2, tmp); + vertex = vertex + tmp; +} + +void FFV5_1(std::complex F2[], std::complex V3[], + std::complex COUP, double M1, double W1, std::complex F1[]) +{ + static std::complex cI = std::complex (0., 1.); + double P1[4]; + std::complex denom; + F1[0] = +F2[0] + V3[0]; + F1[1] = +F2[1] + V3[1]; + P1[0] = -F1[0].real(); + P1[1] = -F1[1].real(); + P1[2] = -F1[1].imag(); + P1[3] = -F1[0].imag(); + denom = COUP/((P1[0] * P1[0]) - (P1[1] * P1[1]) - (P1[2] * P1[2]) - (P1[3] * + P1[3]) - M1 * (M1 - cI * W1)); + F1[2] = denom * 4. * cI * (F2[2] * (P1[0] * (V3[5] - V3[2]) + (P1[1] * (V3[3] + - cI * (V3[4])) + (P1[2] * (V3[4] + cI * (V3[3])) + P1[3] * (V3[5] - + V3[2])))) + (+1./4. * (M1 * (F2[5] * (V3[3] + cI * (V3[4])) + 4. * (F2[4] + * 1./4. * (V3[2] + V3[5])))) + F2[3] * (P1[0] * (V3[3] + cI * (V3[4])) + + (P1[1] * (-1.) * (V3[2] + V3[5]) + (P1[2] * (-1.) * (+cI * (V3[2] + + V3[5])) + P1[3] * (V3[3] + cI * (V3[4]))))))); + F1[3] = denom * 4. * cI * (F2[2] * (P1[0] * (V3[3] - cI * (V3[4])) + (P1[1] * + (V3[5] - V3[2]) + (P1[2] * (-cI * (V3[5]) + cI * (V3[2])) + P1[3] * (+cI + * (V3[4]) - V3[3])))) + (+1./4. * (M1 * (F2[5] * (V3[2] - V3[5]) + 4. * + (F2[4] * 1./4. * (V3[3] - cI * (V3[4]))))) + F2[3] * (P1[0] * (-1.) * + (V3[2] + V3[5]) + (P1[1] * (V3[3] + cI * (V3[4])) + (P1[2] * (V3[4] - cI + * (V3[3])) + P1[3] * (V3[2] + V3[5])))))); + F1[4] = denom * (-cI) * (F2[4] * (P1[0] * (V3[2] + V3[5]) + (P1[1] * (+cI * + (V3[4]) - V3[3]) + (P1[2] * (-1.) * (V3[4] + cI * (V3[3])) - P1[3] * + (V3[2] + V3[5])))) + (F2[5] * (P1[0] * (V3[3] + cI * (V3[4])) + (P1[1] * + (V3[5] - V3[2]) + (P1[2] * (-cI * (V3[2]) + cI * (V3[5])) - P1[3] * + (V3[3] + cI * (V3[4]))))) + M1 * (F2[2] * 4. * (V3[5] - V3[2]) + 4. * + (F2[3] * (V3[3] + cI * (V3[4])))))); + F1[5] = denom * cI * (F2[4] * (P1[0] * (+cI * (V3[4]) - V3[3]) + (P1[1] * + (V3[2] + V3[5]) + (P1[2] * (-1.) * (+cI * (V3[2] + V3[5])) + P1[3] * (+cI + * (V3[4]) - V3[3])))) + (F2[5] * (P1[0] * (V3[5] - V3[2]) + (P1[1] * + (V3[3] + cI * (V3[4])) + (P1[2] * (V3[4] - cI * (V3[3])) + P1[3] * (V3[5] + - V3[2])))) + M1 * (F2[2] * 4. * (+cI * (V3[4]) - V3[3]) + 4. * (F2[3] * + (V3[2] + V3[5]))))); +} + + +void FFV1_0(std::complex F1[], std::complex F2[], + std::complex V3[], std::complex COUP, std::complex + & vertex) +{ + static std::complex cI = std::complex (0., 1.); + std::complex TMP13; + TMP13 = (F1[2] * (F2[4] * (V3[2] + V3[5]) + F2[5] * (V3[3] + cI * (V3[4]))) + + (F1[3] * (F2[4] * (V3[3] - cI * (V3[4])) + F2[5] * (V3[2] - V3[5])) + + (F1[4] * (F2[2] * (V3[2] - V3[5]) - F2[3] * (V3[3] + cI * (V3[4]))) + + F1[5] * (F2[2] * (+cI * (V3[4]) - V3[3]) + F2[3] * (V3[2] + V3[5]))))); + vertex = COUP * - cI * TMP13; +} + + +void VVVV4P0_1(std::complex V2[], std::complex V3[], + std::complex V4[], std::complex COUP, double M1, double W1, + std::complex V1[]) +{ + static std::complex cI = std::complex (0., 1.); + std::complex TMP12; + std::complex TMP11; + double P1[4]; + std::complex denom; + V1[0] = +V2[0] + V3[0] + V4[0]; + V1[1] = +V2[1] + V3[1] + V4[1]; + P1[0] = -V1[0].real(); + P1[1] = -V1[1].real(); + P1[2] = -V1[1].imag(); + P1[3] = -V1[0].imag(); + TMP11 = (V2[2] * V4[2] - V2[3] * V4[3] - V2[4] * V4[4] - V2[5] * V4[5]); + TMP12 = (V3[2] * V4[2] - V3[3] * V4[3] - V3[4] * V4[4] - V3[5] * V4[5]); + denom = COUP/((P1[0] * P1[0]) - (P1[1] * P1[1]) - (P1[2] * P1[2]) - (P1[3] * + P1[3]) - M1 * (M1 - cI * W1)); + V1[2] = denom * (-cI * (V3[2] * TMP11) + cI * (V2[2] * TMP12)); + V1[3] = denom * (-cI * (V3[3] * TMP11) + cI * (V2[3] * TMP12)); + V1[4] = denom * (-cI * (V3[4] * TMP11) + cI * (V2[4] * TMP12)); + V1[5] = denom * (-cI * (V3[5] * TMP11) + cI * (V2[5] * TMP12)); +} + + +void VVVV3P0_1(std::complex V2[], std::complex V3[], + std::complex V4[], std::complex COUP, double M1, double W1, + std::complex V1[]) +{ + static std::complex cI = std::complex (0., 1.); + std::complex TMP12; + double P1[4]; + std::complex TMP6; + std::complex denom; + V1[0] = +V2[0] + V3[0] + V4[0]; + V1[1] = +V2[1] + V3[1] + V4[1]; + P1[0] = -V1[0].real(); + P1[1] = -V1[1].real(); + P1[2] = -V1[1].imag(); + P1[3] = -V1[0].imag(); + TMP6 = (V3[2] * V2[2] - V3[3] * V2[3] - V3[4] * V2[4] - V3[5] * V2[5]); + TMP12 = (V3[2] * V4[2] - V3[3] * V4[3] - V3[4] * V4[4] - V3[5] * V4[5]); + denom = COUP/((P1[0] * P1[0]) - (P1[1] * P1[1]) - (P1[2] * P1[2]) - (P1[3] * + P1[3]) - M1 * (M1 - cI * W1)); + V1[2] = denom * (-cI * (TMP6 * V4[2]) + cI * (V2[2] * TMP12)); + V1[3] = denom * (-cI * (TMP6 * V4[3]) + cI * (V2[3] * TMP12)); + V1[4] = denom * (-cI * (TMP6 * V4[4]) + cI * (V2[4] * TMP12)); + V1[5] = denom * (-cI * (TMP6 * V4[5]) + cI * (V2[5] * TMP12)); +} + + +void VVV1_0(std::complex V1[], std::complex V2[], + std::complex V3[], std::complex COUP, std::complex + & vertex) +{ + static std::complex cI = std::complex (0., 1.); + std::complex TMP2; + std::complex TMP1; + double P1[4]; + std::complex TMP0; + double P2[4]; + std::complex TMP7; + double P3[4]; + std::complex TMP6; + std::complex TMP5; + std::complex TMP4; + std::complex TMP3; + std::complex TMP8; + P1[0] = V1[0].real(); + P1[1] = V1[1].real(); + P1[2] = V1[1].imag(); + P1[3] = V1[0].imag(); + P2[0] = V2[0].real(); + P2[1] = V2[1].real(); + P2[2] = V2[1].imag(); + P2[3] = V2[0].imag(); + P3[0] = V3[0].real(); + P3[1] = V3[1].real(); + P3[2] = V3[1].imag(); + P3[3] = V3[0].imag(); + TMP8 = (V1[2] * P3[0] - V1[3] * P3[1] - V1[4] * P3[2] - V1[5] * P3[3]); + TMP5 = (V2[2] * P3[0] - V2[3] * P3[1] - V2[4] * P3[2] - V2[5] * P3[3]); + TMP4 = (P1[0] * V2[2] - P1[1] * V2[3] - P1[2] * V2[4] - P1[3] * V2[5]); + TMP7 = (V1[2] * P2[0] - V1[3] * P2[1] - V1[4] * P2[2] - V1[5] * P2[3]); + TMP6 = (V3[2] * V2[2] - V3[3] * V2[3] - V3[4] * V2[4] - V3[5] * V2[5]); + TMP1 = (V2[2] * V1[2] - V2[3] * V1[3] - V2[4] * V1[4] - V2[5] * V1[5]); + TMP0 = (V3[2] * P1[0] - V3[3] * P1[1] - V3[4] * P1[2] - V3[5] * P1[3]); + TMP3 = (V3[2] * V1[2] - V3[3] * V1[3] - V3[4] * V1[4] - V3[5] * V1[5]); + TMP2 = (V3[2] * P2[0] - V3[3] * P2[1] - V3[4] * P2[2] - V3[5] * P2[3]); + vertex = COUP * (TMP1 * (-cI * (TMP0) + cI * (TMP2)) + (TMP3 * (-cI * (TMP5) + + cI * (TMP4)) + TMP6 * (-cI * (TMP7) + cI * (TMP8)))); +} + + +void FFV2_3(std::complex F1[], std::complex F2[], + std::complex COUP, double M3, double W3, std::complex V3[]) +{ + static std::complex cI = std::complex (0., 1.); + std::complex denom; + std::complex TMP10; + double P3[4]; + double OM3; + OM3 = 0.; + if (M3 != 0.) + OM3 = 1./(M3 * M3); + V3[0] = +F1[0] + F2[0]; + V3[1] = +F1[1] + F2[1]; + P3[0] = -V3[0].real(); + P3[1] = -V3[1].real(); + P3[2] = -V3[1].imag(); + P3[3] = -V3[0].imag(); + TMP10 = (F1[2] * (F2[4] * (P3[0] + P3[3]) + F2[5] * (P3[1] + cI * (P3[2]))) + + F1[3] * (F2[4] * (P3[1] - cI * (P3[2])) + F2[5] * (P3[0] - P3[3]))); + denom = COUP/((P3[0] * P3[0]) - (P3[1] * P3[1]) - (P3[2] * P3[2]) - (P3[3] * + P3[3]) - M3 * (M3 - cI * W3)); + V3[2] = denom * (-cI) * (F1[2] * F2[4] + F1[3] * F2[5] - P3[0] * OM3 * + TMP10); + V3[3] = denom * (-cI) * (-F1[2] * F2[5] - F1[3] * F2[4] - P3[1] * OM3 * + TMP10); + V3[4] = denom * (-cI) * (-cI * (F1[2] * F2[5]) + cI * (F1[3] * F2[4]) - P3[2] + * OM3 * TMP10); + V3[5] = denom * (-cI) * (F1[3] * F2[5] - F1[2] * F2[4] - P3[3] * OM3 * + TMP10); +} + +void FFV2_4_3(std::complex F1[], std::complex F2[], + std::complex COUP1, std::complex COUP2, double M3, double + W3, std::complex V3[]) +{ + static std::complex cI = std::complex (0., 1.); + std::complex denom; + double P3[4]; + double OM3; + int i; + std::complex Vtmp[6]; + FFV2_3(F1, F2, COUP1, M3, W3, V3); + FFV4_3(F1, F2, COUP2, M3, W3, Vtmp); + i = 2; + while (i < 6) + { + V3[i] = V3[i] + Vtmp[i]; + i++; + } +} + +void FFV5_2(std::complex F1[], std::complex V3[], + std::complex COUP, double M2, double W2, std::complex F2[]) +{ + static std::complex cI = std::complex (0., 1.); + double P2[4]; + std::complex denom; + F2[0] = +F1[0] + V3[0]; + F2[1] = +F1[1] + V3[1]; + P2[0] = -F2[0].real(); + P2[1] = -F2[1].real(); + P2[2] = -F2[1].imag(); + P2[3] = -F2[0].imag(); + denom = COUP/((P2[0] * P2[0]) - (P2[1] * P2[1]) - (P2[2] * P2[2]) - (P2[3] * + P2[3]) - M2 * (M2 - cI * W2)); + F2[2] = denom * cI * (F1[2] * (P2[0] * (V3[2] + V3[5]) + (P2[1] * (-1.) * + (V3[3] + cI * (V3[4])) + (P2[2] * (+cI * (V3[3]) - V3[4]) - P2[3] * + (V3[2] + V3[5])))) + (F1[3] * (P2[0] * (V3[3] - cI * (V3[4])) + (P2[1] * + (V3[5] - V3[2]) + (P2[2] * (-cI * (V3[5]) + cI * (V3[2])) + P2[3] * (+cI + * (V3[4]) - V3[3])))) + M2 * (F1[4] * 4. * (V3[2] - V3[5]) + 4. * (F1[5] + * (+cI * (V3[4]) - V3[3]))))); + F2[3] = denom * cI * (F1[2] * (P2[0] * (V3[3] + cI * (V3[4])) + (P2[1] * + (-1.) * (V3[2] + V3[5]) + (P2[2] * (-1.) * (+cI * (V3[2] + V3[5])) + + P2[3] * (V3[3] + cI * (V3[4]))))) + (F1[3] * (P2[0] * (V3[2] - V3[5]) + + (P2[1] * (+cI * (V3[4]) - V3[3]) + (P2[2] * (-1.) * (V3[4] + cI * + (V3[3])) + P2[3] * (V3[2] - V3[5])))) + M2 * (F1[4] * (-4.) * (V3[3] + cI + * (V3[4])) + 4. * (F1[5] * (V3[2] + V3[5]))))); + F2[4] = denom * (-4. * cI) * (F1[4] * (P2[0] * (V3[5] - V3[2]) + (P2[1] * + (V3[3] + cI * (V3[4])) + (P2[2] * (V3[4] - cI * (V3[3])) + P2[3] * (V3[5] + - V3[2])))) + (+1./4. * (M2 * (F1[3] * (+cI * (V3[4]) - V3[3]) + 4. * + (F1[2] * (-1./4.) * (V3[2] + V3[5])))) + F1[5] * (P2[0] * (V3[3] - cI * + (V3[4])) + (P2[1] * (-1.) * (V3[2] + V3[5]) + (P2[2] * (+cI * (V3[2] + + V3[5])) + P2[3] * (V3[3] - cI * (V3[4]))))))); + F2[5] = denom * (-4. * cI) * (F1[4] * (P2[0] * (V3[3] + cI * (V3[4])) + + (P2[1] * (V3[5] - V3[2]) + (P2[2] * (-cI * (V3[2]) + cI * (V3[5])) - + P2[3] * (V3[3] + cI * (V3[4]))))) + (+1./4. * (M2 * (F1[3] * (V3[5] - + V3[2]) + 4. * (F1[2] * (-1./4.) * (V3[3] + cI * (V3[4]))))) + F1[5] * + (P2[0] * (-1.) * (V3[2] + V3[5]) + (P2[1] * (V3[3] - cI * (V3[4])) + + (P2[2] * (V3[4] + cI * (V3[3])) + P2[3] * (V3[2] + V3[5])))))); +} + + +void FFV2_1(std::complex F2[], std::complex V3[], + std::complex COUP, double M1, double W1, std::complex F1[]) +{ + static std::complex cI = std::complex (0., 1.); + double P1[4]; + std::complex denom; + F1[0] = +F2[0] + V3[0]; + F1[1] = +F2[1] + V3[1]; + P1[0] = -F1[0].real(); + P1[1] = -F1[1].real(); + P1[2] = -F1[1].imag(); + P1[3] = -F1[0].imag(); + denom = COUP/((P1[0] * P1[0]) - (P1[1] * P1[1]) - (P1[2] * P1[2]) - (P1[3] * + P1[3]) - M1 * (M1 - cI * W1)); + F1[2] = denom * cI * M1 * (F2[4] * (V3[2] + V3[5]) + F2[5] * (V3[3] + cI * + (V3[4]))); + F1[3] = denom * - cI * M1 * (F2[4] * (+cI * (V3[4]) - V3[3]) + F2[5] * (V3[5] + - V3[2])); + F1[4] = denom * (-cI) * (F2[4] * (P1[0] * (V3[2] + V3[5]) + (P1[1] * (+cI * + (V3[4]) - V3[3]) + (P1[2] * (-1.) * (V3[4] + cI * (V3[3])) - P1[3] * + (V3[2] + V3[5])))) + F2[5] * (P1[0] * (V3[3] + cI * (V3[4])) + (P1[1] * + (V3[5] - V3[2]) + (P1[2] * (-cI * (V3[2]) + cI * (V3[5])) - P1[3] * + (V3[3] + cI * (V3[4])))))); + F1[5] = denom * (-cI) * (F2[4] * (P1[0] * (V3[3] - cI * (V3[4])) + (P1[1] * + (-1.) * (V3[2] + V3[5]) + (P1[2] * (+cI * (V3[2] + V3[5])) + P1[3] * + (V3[3] - cI * (V3[4]))))) + F2[5] * (P1[0] * (V3[2] - V3[5]) + (P1[1] * + (-1.) * (V3[3] + cI * (V3[4])) + (P1[2] * (+cI * (V3[3]) - V3[4]) + P1[3] + * (V3[2] - V3[5]))))); +} + +void FFV2_5_1(std::complex F2[], std::complex V3[], + std::complex COUP1, std::complex COUP2, double M1, double + W1, std::complex F1[]) +{ + static std::complex cI = std::complex (0., 1.); + double P1[4]; + std::complex denom; + int i; + std::complex Ftmp[6]; + FFV2_1(F2, V3, COUP1, M1, W1, F1); + FFV5_1(F2, V3, COUP2, M1, W1, Ftmp); + i = 2; + while (i < 6) + { + F1[i] = F1[i] + Ftmp[i]; + i++; + } +} + +void FFV5_0(std::complex F1[], std::complex F2[], + std::complex V3[], std::complex COUP, std::complex + & vertex) +{ + static std::complex cI = std::complex (0., 1.); + std::complex TMP15; + std::complex TMP16; + TMP15 = (F1[2] * (F2[4] * (V3[2] + V3[5]) + F2[5] * (V3[3] + cI * (V3[4]))) + + F1[3] * (F2[4] * (V3[3] - cI * (V3[4])) + F2[5] * (V3[2] - V3[5]))); + TMP16 = (F1[4] * (F2[2] * (V3[2] - V3[5]) - F2[3] * (V3[3] + cI * (V3[4]))) + + F1[5] * (F2[2] * (+cI * (V3[4]) - V3[3]) + F2[3] * (V3[2] + V3[5]))); + vertex = COUP * (-1.) * (+cI * (TMP15) + 4. * cI * (TMP16)); +} + + +void FFV1_1(std::complex F2[], std::complex V3[], + std::complex COUP, double M1, double W1, std::complex F1[]) +{ + static std::complex cI = std::complex (0., 1.); + double P1[4]; + std::complex denom; + F1[0] = +F2[0] + V3[0]; + F1[1] = +F2[1] + V3[1]; + P1[0] = -F1[0].real(); + P1[1] = -F1[1].real(); + P1[2] = -F1[1].imag(); + P1[3] = -F1[0].imag(); + denom = COUP/((P1[0] * P1[0]) - (P1[1] * P1[1]) - (P1[2] * P1[2]) - (P1[3] * + P1[3]) - M1 * (M1 - cI * W1)); + F1[2] = denom * cI * (F2[2] * (P1[0] * (V3[5] - V3[2]) + (P1[1] * (V3[3] - cI + * (V3[4])) + (P1[2] * (V3[4] + cI * (V3[3])) + P1[3] * (V3[5] - V3[2])))) + + (F2[3] * (P1[0] * (V3[3] + cI * (V3[4])) + (P1[1] * (-1.) * (V3[2] + + V3[5]) + (P1[2] * (-1.) * (+cI * (V3[2] + V3[5])) + P1[3] * (V3[3] + cI * + (V3[4]))))) + M1 * (F2[4] * (V3[2] + V3[5]) + F2[5] * (V3[3] + cI * + (V3[4]))))); + F1[3] = denom * (-cI) * (F2[2] * (P1[0] * (+cI * (V3[4]) - V3[3]) + (P1[1] * + (V3[2] - V3[5]) + (P1[2] * (-cI * (V3[2]) + cI * (V3[5])) + P1[3] * + (V3[3] - cI * (V3[4]))))) + (F2[3] * (P1[0] * (V3[2] + V3[5]) + (P1[1] * + (-1.) * (V3[3] + cI * (V3[4])) + (P1[2] * (+cI * (V3[3]) - V3[4]) - P1[3] + * (V3[2] + V3[5])))) + M1 * (F2[4] * (+cI * (V3[4]) - V3[3]) + F2[5] * + (V3[5] - V3[2])))); + F1[4] = denom * (-cI) * (F2[4] * (P1[0] * (V3[2] + V3[5]) + (P1[1] * (+cI * + (V3[4]) - V3[3]) + (P1[2] * (-1.) * (V3[4] + cI * (V3[3])) - P1[3] * + (V3[2] + V3[5])))) + (F2[5] * (P1[0] * (V3[3] + cI * (V3[4])) + (P1[1] * + (V3[5] - V3[2]) + (P1[2] * (-cI * (V3[2]) + cI * (V3[5])) - P1[3] * + (V3[3] + cI * (V3[4]))))) + M1 * (F2[2] * (V3[5] - V3[2]) + F2[3] * + (V3[3] + cI * (V3[4]))))); + F1[5] = denom * cI * (F2[4] * (P1[0] * (+cI * (V3[4]) - V3[3]) + (P1[1] * + (V3[2] + V3[5]) + (P1[2] * (-1.) * (+cI * (V3[2] + V3[5])) + P1[3] * (+cI + * (V3[4]) - V3[3])))) + (F2[5] * (P1[0] * (V3[5] - V3[2]) + (P1[1] * + (V3[3] + cI * (V3[4])) + (P1[2] * (V3[4] - cI * (V3[3])) + P1[3] * (V3[5] + - V3[2])))) + M1 * (F2[2] * (+cI * (V3[4]) - V3[3]) + F2[3] * (V3[2] + + V3[5])))); +} + + +void FFV4_3(std::complex F1[], std::complex F2[], + std::complex COUP, double M3, double W3, std::complex V3[]) +{ + static std::complex cI = std::complex (0., 1.); + std::complex denom; + std::complex TMP10; + double P3[4]; + double OM3; + std::complex TMP14; + OM3 = 0.; + if (M3 != 0.) + OM3 = 1./(M3 * M3); + V3[0] = +F1[0] + F2[0]; + V3[1] = +F1[1] + F2[1]; + P3[0] = -V3[0].real(); + P3[1] = -V3[1].real(); + P3[2] = -V3[1].imag(); + P3[3] = -V3[0].imag(); + TMP14 = (F1[4] * (F2[2] * (P3[0] - P3[3]) - F2[3] * (P3[1] + cI * (P3[2]))) + + F1[5] * (F2[2] * (+cI * (P3[2]) - P3[1]) + F2[3] * (P3[0] + P3[3]))); + TMP10 = (F1[2] * (F2[4] * (P3[0] + P3[3]) + F2[5] * (P3[1] + cI * (P3[2]))) + + F1[3] * (F2[4] * (P3[1] - cI * (P3[2])) + F2[5] * (P3[0] - P3[3]))); + denom = COUP/((P3[0] * P3[0]) - (P3[1] * P3[1]) - (P3[2] * P3[2]) - (P3[3] * + P3[3]) - M3 * (M3 - cI * W3)); + V3[2] = denom * (-2. * cI) * (OM3 * - 1./2. * P3[0] * (TMP10 + 2. * (TMP14)) + + (+1./2. * (F1[2] * F2[4] + F1[3] * F2[5]) + F1[4] * F2[2] + F1[5] * + F2[3])); + V3[3] = denom * (-2. * cI) * (OM3 * - 1./2. * P3[1] * (TMP10 + 2. * (TMP14)) + + (-1./2. * (F1[2] * F2[5] + F1[3] * F2[4]) + F1[4] * F2[3] + F1[5] * + F2[2])); + V3[4] = denom * 2. * cI * (OM3 * 1./2. * P3[2] * (TMP10 + 2. * (TMP14)) + + (+1./2. * cI * (F1[2] * F2[5]) - 1./2. * cI * (F1[3] * F2[4]) - cI * + (F1[4] * F2[3]) + cI * (F1[5] * F2[2]))); + V3[5] = denom * 2. * cI * (OM3 * 1./2. * P3[3] * (TMP10 + 2. * (TMP14)) + + (+1./2. * (F1[2] * F2[4]) - 1./2. * (F1[3] * F2[5]) - F1[4] * F2[2] + + F1[5] * F2[3])); +} + + +void VVVV1P0_1(std::complex V2[], std::complex V3[], + std::complex V4[], std::complex COUP, double M1, double W1, + std::complex V1[]) +{ + static std::complex cI = std::complex (0., 1.); + std::complex TMP11; + double P1[4]; + std::complex TMP6; + std::complex denom; + V1[0] = +V2[0] + V3[0] + V4[0]; + V1[1] = +V2[1] + V3[1] + V4[1]; + P1[0] = -V1[0].real(); + P1[1] = -V1[1].real(); + P1[2] = -V1[1].imag(); + P1[3] = -V1[0].imag(); + TMP6 = (V3[2] * V2[2] - V3[3] * V2[3] - V3[4] * V2[4] - V3[5] * V2[5]); + TMP11 = (V2[2] * V4[2] - V2[3] * V4[3] - V2[4] * V4[4] - V2[5] * V4[5]); + denom = COUP/((P1[0] * P1[0]) - (P1[1] * P1[1]) - (P1[2] * P1[2]) - (P1[3] * + P1[3]) - M1 * (M1 - cI * W1)); + V1[2] = denom * (-cI * (TMP6 * V4[2]) + cI * (V3[2] * TMP11)); + V1[3] = denom * (-cI * (TMP6 * V4[3]) + cI * (V3[3] * TMP11)); + V1[4] = denom * (-cI * (TMP6 * V4[4]) + cI * (V3[4] * TMP11)); + V1[5] = denom * (-cI * (TMP6 * V4[5]) + cI * (V3[5] * TMP11)); +} + + +void VVV1P0_1(std::complex V2[], std::complex V3[], + std::complex COUP, double M1, double W1, std::complex V1[]) +{ + static std::complex cI = std::complex (0., 1.); + std::complex TMP2; + double P1[4]; + std::complex TMP0; + double P2[4]; + double P3[4]; + std::complex TMP6; + std::complex TMP5; + std::complex TMP4; + std::complex denom; + P2[0] = V2[0].real(); + P2[1] = V2[1].real(); + P2[2] = V2[1].imag(); + P2[3] = V2[0].imag(); + P3[0] = V3[0].real(); + P3[1] = V3[1].real(); + P3[2] = V3[1].imag(); + P3[3] = V3[0].imag(); + V1[0] = +V2[0] + V3[0]; + V1[1] = +V2[1] + V3[1]; + P1[0] = -V1[0].real(); + P1[1] = -V1[1].real(); + P1[2] = -V1[1].imag(); + P1[3] = -V1[0].imag(); + TMP5 = (V2[2] * P3[0] - V2[3] * P3[1] - V2[4] * P3[2] - V2[5] * P3[3]); + TMP4 = (P1[0] * V2[2] - P1[1] * V2[3] - P1[2] * V2[4] - P1[3] * V2[5]); + TMP6 = (V3[2] * V2[2] - V3[3] * V2[3] - V3[4] * V2[4] - V3[5] * V2[5]); + TMP0 = (V3[2] * P1[0] - V3[3] * P1[1] - V3[4] * P1[2] - V3[5] * P1[3]); + TMP2 = (V3[2] * P2[0] - V3[3] * P2[1] - V3[4] * P2[2] - V3[5] * P2[3]); + denom = COUP/((P1[0] * P1[0]) - (P1[1] * P1[1]) - (P1[2] * P1[2]) - (P1[3] * + P1[3]) - M1 * (M1 - cI * W1)); + V1[2] = denom * (TMP6 * (-cI * (P2[0]) + cI * (P3[0])) + (V2[2] * (-cI * + (TMP0) + cI * (TMP2)) + V3[2] * (-cI * (TMP5) + cI * (TMP4)))); + V1[3] = denom * (TMP6 * (-cI * (P2[1]) + cI * (P3[1])) + (V2[3] * (-cI * + (TMP0) + cI * (TMP2)) + V3[3] * (-cI * (TMP5) + cI * (TMP4)))); + V1[4] = denom * (TMP6 * (-cI * (P2[2]) + cI * (P3[2])) + (V2[4] * (-cI * + (TMP0) + cI * (TMP2)) + V3[4] * (-cI * (TMP5) + cI * (TMP4)))); + V1[5] = denom * (TMP6 * (-cI * (P2[3]) + cI * (P3[3])) + (V2[5] * (-cI * + (TMP0) + cI * (TMP2)) + V3[5] * (-cI * (TMP5) + cI * (TMP4)))); +} + + +} // end namespace MG5_sm_COLOREA + diff --git a/Shower/Dipole/Colorea/HelAmps_sm.h b/Shower/Dipole/Colorea/HelAmps_sm.h new file mode 100644 --- /dev/null +++ b/Shower/Dipole/Colorea/HelAmps_sm.h @@ -0,0 +1,106 @@ +//========================================================================== +// This file has been automatically generated for C++ Standalone +// MadGraph5_aMC@NLO v. 2.5.4, 2017-03-28 +// By the MadGraph5_aMC@NLO Development Team +// Visit launchpad.net/madgraph5 and amcatnlo.web.cern.ch +//========================================================================== + +#ifndef HelAmps_sm_H +#define HelAmps_sm_H + +#include +#include + +using namespace std; + +namespace MG5_sm_COLOREA +{ +double Sgn(double e, double f); + +void oxxxxx(double p[4], double fmass, int nhel, int nsf, std::complex + fo[6]); + +void sxxxxx(double p[4], int nss, std::complex sc[3]); + +void ixxxxx(double p[4], double fmass, int nhel, int nsf, std::complex + fi[6]); + +void txxxxx(double p[4], double tmass, int nhel, int nst, std::complex + fi[18]); + +void vxxxxx(double p[4], double vmass, int nhel, int nsv, std::complex + v[6]); + +void FFV1P0_3(std::complex F1[], std::complex F2[], + std::complex COUP, double M3, double W3, std::complex V3[]); + +void FFV2_2(std::complex F1[], std::complex V3[], + std::complex COUP, double M2, double W2, std::complex F2[]); +void FFV2_5_2(std::complex F1[], std::complex V3[], + std::complex COUP1, std::complex COUP2, double M2, double + W2, std::complex F2[]); + +void FFV1_2(std::complex F1[], std::complex V3[], + std::complex COUP, double M2, double W2, std::complex F2[]); + +void FFV2_0(std::complex F1[], std::complex F2[], + std::complex V3[], std::complex COUP, std::complex + & vertex); +void FFV2_5_0(std::complex F1[], std::complex F2[], + std::complex V3[], std::complex COUP1, std::complex + COUP2, std::complex & vertex); + +void FFV5_1(std::complex F2[], std::complex V3[], + std::complex COUP, double M1, double W1, std::complex F1[]); + +void FFV1_0(std::complex F1[], std::complex F2[], + std::complex V3[], std::complex COUP, std::complex + & vertex); + +void VVVV4P0_1(std::complex V2[], std::complex V3[], + std::complex V4[], std::complex COUP, double M1, double W1, + std::complex V1[]); + +void VVVV3P0_1(std::complex V2[], std::complex V3[], + std::complex V4[], std::complex COUP, double M1, double W1, + std::complex V1[]); + +void VVV1_0(std::complex V1[], std::complex V2[], + std::complex V3[], std::complex COUP, std::complex + & vertex); + +void FFV2_3(std::complex F1[], std::complex F2[], + std::complex COUP, double M3, double W3, std::complex V3[]); +void FFV2_4_3(std::complex F1[], std::complex F2[], + std::complex COUP1, std::complex COUP2, double M3, double + W3, std::complex V3[]); + +void FFV5_2(std::complex F1[], std::complex V3[], + std::complex COUP, double M2, double W2, std::complex F2[]); + +void FFV2_1(std::complex F2[], std::complex V3[], + std::complex COUP, double M1, double W1, std::complex F1[]); +void FFV2_5_1(std::complex F2[], std::complex V3[], + std::complex COUP1, std::complex COUP2, double M1, double + W1, std::complex F1[]); + +void FFV5_0(std::complex F1[], std::complex F2[], + std::complex V3[], std::complex COUP, std::complex + & vertex); + +void FFV1_1(std::complex F2[], std::complex V3[], + std::complex COUP, double M1, double W1, std::complex F1[]); + +void FFV4_3(std::complex F1[], std::complex F2[], + std::complex COUP, double M3, double W3, std::complex V3[]); + +void VVVV1P0_1(std::complex V2[], std::complex V3[], + std::complex V4[], std::complex COUP, double M1, double W1, + std::complex V1[]); + +void VVV1P0_1(std::complex V2[], std::complex V3[], + std::complex COUP, double M1, double W1, std::complex V1[]); + +} // end namespace MG5_sm_COLOREA + +#endif // HelAmps_sm_H diff --git a/Shower/Dipole/Colorea/Makefile.am b/Shower/Dipole/Colorea/Makefile.am new file mode 100644 --- /dev/null +++ b/Shower/Dipole/Colorea/Makefile.am @@ -0,0 +1,19 @@ +noinst_LTLIBRARIES = libHwDipoleShowerColorea.la + +libHwDipoleShowerColorea_la_SOURCES = \ + Colorea.fh \ + Colorea.cc \ + Colorea.h \ + HelAmps_sm.cc \ + HelAmps_sm.h \ + Parameters_sm.cc \ + Parameters_sm.h \ + read_slha_COLOREA.cc \ + read_slha_COLOREA.h \ + eeuugg.h \ + eeuugg.cc \ + eeuuggg.h \ + eeuuggg.cc \ + eeuugggg.h \ + eeuugggg.cc + diff --git a/Shower/Dipole/Colorea/Parameters_sm.cc b/Shower/Dipole/Colorea/Parameters_sm.cc new file mode 100644 --- /dev/null +++ b/Shower/Dipole/Colorea/Parameters_sm.cc @@ -0,0 +1,241 @@ +//========================================================================== +// This file has been automatically generated for C++ by +// MadGraph5_aMC@NLO v. 2.5.4, 2017-03-28 +// By the MadGraph5_aMC@NLO Development Team +// Visit launchpad.net/madgraph5 and amcatnlo.web.cern.ch +//========================================================================== + +#include +#include +#include "Parameters_sm.h" + +// Initialize static instance +Parameters_sm * Parameters_sm::instance = 0; + +// Function to get static instance - only one instance per program +Parameters_sm * Parameters_sm::getInstance() +{ + if (instance == 0) + instance = new Parameters_sm(); + + return instance; +} + +void Parameters_sm::setIndependentParameters(SLHAReader_COLOREA& slha) +{ + // Define "zero" + zero = 0; + ZERO = 0; + // Prepare a vector for indices + vector indices(2, 0); + mdl_WH = slha.get_block_entry("decay", 25, 6.382339e-03); + mdl_WW = slha.get_block_entry("decay", 24, 2.047600e+00); + mdl_WZ = slha.get_block_entry("decay", 23, 2.441404e+00); + mdl_WT = slha.get_block_entry("decay", 6, 1.491500e+00); + mdl_ymtau = slha.get_block_entry("yukawa", 15, 1.777000e+00); + mdl_ymt = slha.get_block_entry("yukawa", 6, 1.730000e+02); + mdl_ymb = slha.get_block_entry("yukawa", 5, 4.700000e+00); + aS = slha.get_block_entry("sminputs", 3, 1.180000e-01); + mdl_Gf = slha.get_block_entry("sminputs", 2, 1.166390e-05); + aEWM1 = slha.get_block_entry("sminputs", 1, 1.325070e+02); + mdl_MH = slha.get_block_entry("mass", 25, 1.250000e+02); + mdl_MZ = slha.get_block_entry("mass", 23, 9.118800e+01); + mdl_MTA = slha.get_block_entry("mass", 15, 1.777000e+00); + mdl_MT = slha.get_block_entry("mass", 6, 1.730000e+02); + mdl_MB = slha.get_block_entry("mass", 5, 4.700000e+00); + mdl_conjg__CKM3x3 = 1.; + mdl_CKM3x3 = 1.; + mdl_conjg__CKM1x1 = 1.; + mdl_complexi = std::complex (0., 1.); + mdl_MZ__exp__2 = ((mdl_MZ) * (mdl_MZ)); + mdl_MZ__exp__4 = ((mdl_MZ) * (mdl_MZ) * (mdl_MZ) * (mdl_MZ)); + mdl_sqrt__2 = sqrt(2.); + mdl_MH__exp__2 = ((mdl_MH) * (mdl_MH)); + mdl_aEW = 1./aEWM1; + mdl_MW = sqrt(mdl_MZ__exp__2/2. + sqrt(mdl_MZ__exp__4/4. - (mdl_aEW * M_PI * + mdl_MZ__exp__2)/(mdl_Gf * mdl_sqrt__2))); + mdl_sqrt__aEW = sqrt(mdl_aEW); + mdl_ee = 2. * mdl_sqrt__aEW * sqrt(M_PI); + mdl_MW__exp__2 = ((mdl_MW) * (mdl_MW)); + mdl_sw2 = 1. - mdl_MW__exp__2/mdl_MZ__exp__2; + mdl_cw = sqrt(1. - mdl_sw2); + mdl_sqrt__sw2 = sqrt(mdl_sw2); + mdl_sw = mdl_sqrt__sw2; + mdl_g1 = mdl_ee/mdl_cw; + mdl_gw = mdl_ee/mdl_sw; + mdl_vev = (2. * mdl_MW * mdl_sw)/mdl_ee; + mdl_vev__exp__2 = ((mdl_vev) * (mdl_vev)); + mdl_lam = mdl_MH__exp__2/(2. * mdl_vev__exp__2); + mdl_yb = (mdl_ymb * mdl_sqrt__2)/mdl_vev; + mdl_yt = (mdl_ymt * mdl_sqrt__2)/mdl_vev; + mdl_ytau = (mdl_ymtau * mdl_sqrt__2)/mdl_vev; + mdl_muH = sqrt(mdl_lam * mdl_vev__exp__2); + mdl_I1x33 = mdl_yb * mdl_conjg__CKM3x3; + mdl_I2x33 = mdl_yt * mdl_conjg__CKM3x3; + mdl_I3x33 = mdl_CKM3x3 * mdl_yt; + mdl_I4x33 = mdl_CKM3x3 * mdl_yb; + mdl_ee__exp__2 = ((mdl_ee) * (mdl_ee)); + mdl_sw__exp__2 = ((mdl_sw) * (mdl_sw)); + mdl_cw__exp__2 = ((mdl_cw) * (mdl_cw)); +} +void Parameters_sm::setIndependentCouplings() +{ + GC_2 = (2. * mdl_ee * mdl_complexi)/3.; + GC_3 = -(mdl_ee * mdl_complexi); + GC_50 = -(mdl_cw * mdl_ee * mdl_complexi)/(2. * mdl_sw); + GC_51 = (mdl_cw * mdl_ee * mdl_complexi)/(2. * mdl_sw); + GC_58 = -(mdl_ee * mdl_complexi * mdl_sw)/(6. * mdl_cw); + GC_59 = (mdl_ee * mdl_complexi * mdl_sw)/(2. * mdl_cw); +} +void Parameters_sm::setDependentParameters() +{ + mdl_sqrt__aS = sqrt(aS); + G = 2. * mdl_sqrt__aS * sqrt(M_PI); + mdl_G__exp__2 = ((G) * (G)); +} +void Parameters_sm::setDependentCouplings() +{ + GC_12 = mdl_complexi * mdl_G__exp__2; + GC_11 = mdl_complexi * G; + GC_10 = -G; +} + +// Routines for printing out parameters +void Parameters_sm::printIndependentParameters() +{ + cout << "sm model parameters independent of event kinematics:" << endl; + cout << setw(20) << "mdl_WH " << "= " << setiosflags(ios::scientific) << + setw(10) << mdl_WH << endl; + cout << setw(20) << "mdl_WW " << "= " << setiosflags(ios::scientific) << + setw(10) << mdl_WW << endl; + cout << setw(20) << "mdl_WZ " << "= " << setiosflags(ios::scientific) << + setw(10) << mdl_WZ << endl; + cout << setw(20) << "mdl_WT " << "= " << setiosflags(ios::scientific) << + setw(10) << mdl_WT << endl; + cout << setw(20) << "mdl_ymtau " << "= " << setiosflags(ios::scientific) << + setw(10) << mdl_ymtau << endl; + cout << setw(20) << "mdl_ymt " << "= " << setiosflags(ios::scientific) << + setw(10) << mdl_ymt << endl; + cout << setw(20) << "mdl_ymb " << "= " << setiosflags(ios::scientific) << + setw(10) << mdl_ymb << endl; + cout << setw(20) << "aS " << "= " << setiosflags(ios::scientific) << + setw(10) << aS << endl; + cout << setw(20) << "mdl_Gf " << "= " << setiosflags(ios::scientific) << + setw(10) << mdl_Gf << endl; + cout << setw(20) << "aEWM1 " << "= " << setiosflags(ios::scientific) << + setw(10) << aEWM1 << endl; + cout << setw(20) << "mdl_MH " << "= " << setiosflags(ios::scientific) << + setw(10) << mdl_MH << endl; + cout << setw(20) << "mdl_MZ " << "= " << setiosflags(ios::scientific) << + setw(10) << mdl_MZ << endl; + cout << setw(20) << "mdl_MTA " << "= " << setiosflags(ios::scientific) << + setw(10) << mdl_MTA << endl; + cout << setw(20) << "mdl_MT " << "= " << setiosflags(ios::scientific) << + setw(10) << mdl_MT << endl; + cout << setw(20) << "mdl_MB " << "= " << setiosflags(ios::scientific) << + setw(10) << mdl_MB << endl; + cout << setw(20) << "mdl_conjg__CKM3x3 " << "= " << + setiosflags(ios::scientific) << setw(10) << mdl_conjg__CKM3x3 << endl; + cout << setw(20) << "mdl_CKM3x3 " << "= " << setiosflags(ios::scientific) + << setw(10) << mdl_CKM3x3 << endl; + cout << setw(20) << "mdl_conjg__CKM1x1 " << "= " << + setiosflags(ios::scientific) << setw(10) << mdl_conjg__CKM1x1 << endl; + cout << setw(20) << "mdl_complexi " << "= " << setiosflags(ios::scientific) + << setw(10) << mdl_complexi << endl; + cout << setw(20) << "mdl_MZ__exp__2 " << "= " << + setiosflags(ios::scientific) << setw(10) << mdl_MZ__exp__2 << endl; + cout << setw(20) << "mdl_MZ__exp__4 " << "= " << + setiosflags(ios::scientific) << setw(10) << mdl_MZ__exp__4 << endl; + cout << setw(20) << "mdl_sqrt__2 " << "= " << setiosflags(ios::scientific) + << setw(10) << mdl_sqrt__2 << endl; + cout << setw(20) << "mdl_MH__exp__2 " << "= " << + setiosflags(ios::scientific) << setw(10) << mdl_MH__exp__2 << endl; + cout << setw(20) << "mdl_aEW " << "= " << setiosflags(ios::scientific) << + setw(10) << mdl_aEW << endl; + cout << setw(20) << "mdl_MW " << "= " << setiosflags(ios::scientific) << + setw(10) << mdl_MW << endl; + cout << setw(20) << "mdl_sqrt__aEW " << "= " << + setiosflags(ios::scientific) << setw(10) << mdl_sqrt__aEW << endl; + cout << setw(20) << "mdl_ee " << "= " << setiosflags(ios::scientific) << + setw(10) << mdl_ee << endl; + cout << setw(20) << "mdl_MW__exp__2 " << "= " << + setiosflags(ios::scientific) << setw(10) << mdl_MW__exp__2 << endl; + cout << setw(20) << "mdl_sw2 " << "= " << setiosflags(ios::scientific) << + setw(10) << mdl_sw2 << endl; + cout << setw(20) << "mdl_cw " << "= " << setiosflags(ios::scientific) << + setw(10) << mdl_cw << endl; + cout << setw(20) << "mdl_sqrt__sw2 " << "= " << + setiosflags(ios::scientific) << setw(10) << mdl_sqrt__sw2 << endl; + cout << setw(20) << "mdl_sw " << "= " << setiosflags(ios::scientific) << + setw(10) << mdl_sw << endl; + cout << setw(20) << "mdl_g1 " << "= " << setiosflags(ios::scientific) << + setw(10) << mdl_g1 << endl; + cout << setw(20) << "mdl_gw " << "= " << setiosflags(ios::scientific) << + setw(10) << mdl_gw << endl; + cout << setw(20) << "mdl_vev " << "= " << setiosflags(ios::scientific) << + setw(10) << mdl_vev << endl; + cout << setw(20) << "mdl_vev__exp__2 " << "= " << + setiosflags(ios::scientific) << setw(10) << mdl_vev__exp__2 << endl; + cout << setw(20) << "mdl_lam " << "= " << setiosflags(ios::scientific) << + setw(10) << mdl_lam << endl; + cout << setw(20) << "mdl_yb " << "= " << setiosflags(ios::scientific) << + setw(10) << mdl_yb << endl; + cout << setw(20) << "mdl_yt " << "= " << setiosflags(ios::scientific) << + setw(10) << mdl_yt << endl; + cout << setw(20) << "mdl_ytau " << "= " << setiosflags(ios::scientific) << + setw(10) << mdl_ytau << endl; + cout << setw(20) << "mdl_muH " << "= " << setiosflags(ios::scientific) << + setw(10) << mdl_muH << endl; + cout << setw(20) << "mdl_I1x33 " << "= " << setiosflags(ios::scientific) << + setw(10) << mdl_I1x33 << endl; + cout << setw(20) << "mdl_I2x33 " << "= " << setiosflags(ios::scientific) << + setw(10) << mdl_I2x33 << endl; + cout << setw(20) << "mdl_I3x33 " << "= " << setiosflags(ios::scientific) << + setw(10) << mdl_I3x33 << endl; + cout << setw(20) << "mdl_I4x33 " << "= " << setiosflags(ios::scientific) << + setw(10) << mdl_I4x33 << endl; + cout << setw(20) << "mdl_ee__exp__2 " << "= " << + setiosflags(ios::scientific) << setw(10) << mdl_ee__exp__2 << endl; + cout << setw(20) << "mdl_sw__exp__2 " << "= " << + setiosflags(ios::scientific) << setw(10) << mdl_sw__exp__2 << endl; + cout << setw(20) << "mdl_cw__exp__2 " << "= " << + setiosflags(ios::scientific) << setw(10) << mdl_cw__exp__2 << endl; +} +void Parameters_sm::printIndependentCouplings() +{ + cout << "sm model couplings independent of event kinematics:" << endl; + cout << setw(20) << "GC_2 " << "= " << setiosflags(ios::scientific) << + setw(10) << GC_2 << endl; + cout << setw(20) << "GC_3 " << "= " << setiosflags(ios::scientific) << + setw(10) << GC_3 << endl; + cout << setw(20) << "GC_50 " << "= " << setiosflags(ios::scientific) << + setw(10) << GC_50 << endl; + cout << setw(20) << "GC_51 " << "= " << setiosflags(ios::scientific) << + setw(10) << GC_51 << endl; + cout << setw(20) << "GC_58 " << "= " << setiosflags(ios::scientific) << + setw(10) << GC_58 << endl; + cout << setw(20) << "GC_59 " << "= " << setiosflags(ios::scientific) << + setw(10) << GC_59 << endl; +} +void Parameters_sm::printDependentParameters() +{ + cout << "sm model parameters dependent on event kinematics:" << endl; + cout << setw(20) << "mdl_sqrt__aS " << "= " << setiosflags(ios::scientific) + << setw(10) << mdl_sqrt__aS << endl; + cout << setw(20) << "G " << "= " << setiosflags(ios::scientific) << + setw(10) << G << endl; + cout << setw(20) << "mdl_G__exp__2 " << "= " << + setiosflags(ios::scientific) << setw(10) << mdl_G__exp__2 << endl; +} +void Parameters_sm::printDependentCouplings() +{ + cout << "sm model couplings dependent on event kinematics:" << endl; + cout << setw(20) << "GC_12 " << "= " << setiosflags(ios::scientific) << + setw(10) << GC_12 << endl; + cout << setw(20) << "GC_11 " << "= " << setiosflags(ios::scientific) << + setw(10) << GC_11 << endl; + cout << setw(20) << "GC_10 " << "= " << setiosflags(ios::scientific) << + setw(10) << GC_10 << endl; +} + + diff --git a/Shower/Dipole/Colorea/Parameters_sm.h b/Shower/Dipole/Colorea/Parameters_sm.h new file mode 100644 --- /dev/null +++ b/Shower/Dipole/Colorea/Parameters_sm.h @@ -0,0 +1,66 @@ +//========================================================================== +// This file has been automatically generated for C++ +// MadGraph5_aMC@NLO v. 2.5.4, 2017-03-28 +// By the MadGraph5_aMC@NLO Development Team +// Visit launchpad.net/madgraph5 and amcatnlo.web.cern.ch +//========================================================================== + +#ifndef Parameters_sm_H +#define Parameters_sm_H + +#include + +#include "read_slha_COLOREA.h" +using namespace std; + +class Parameters_sm +{ + public: + + static Parameters_sm * getInstance(); + + // Define "zero" + double zero, ZERO; + // Model parameters independent of aS + double mdl_WH, mdl_WW, mdl_WZ, mdl_WT, mdl_ymtau, mdl_ymt, mdl_ymb, aS, + mdl_Gf, aEWM1, mdl_MH, mdl_MZ, mdl_MTA, mdl_MT, mdl_MB, + mdl_conjg__CKM3x3, mdl_CKM3x3, mdl_conjg__CKM1x1, mdl_MZ__exp__2, + mdl_MZ__exp__4, mdl_sqrt__2, mdl_MH__exp__2, mdl_aEW, mdl_MW, + mdl_sqrt__aEW, mdl_ee, mdl_MW__exp__2, mdl_sw2, mdl_cw, mdl_sqrt__sw2, + mdl_sw, mdl_g1, mdl_gw, mdl_vev, mdl_vev__exp__2, mdl_lam, mdl_yb, + mdl_yt, mdl_ytau, mdl_muH, mdl_ee__exp__2, mdl_sw__exp__2, + mdl_cw__exp__2; + std::complex mdl_complexi, mdl_I1x33, mdl_I2x33, mdl_I3x33, + mdl_I4x33; + // Model parameters dependent on aS + double mdl_sqrt__aS, G, mdl_G__exp__2; + // Model couplings independent of aS + std::complex GC_2, GC_3, GC_50, GC_51, GC_58, GC_59; + // Model couplings dependent on aS + std::complex GC_12, GC_11, GC_10; + + // Set parameters that are unchanged during the run + void setIndependentParameters(SLHAReader_COLOREA& slha); + // Set couplings that are unchanged during the run + void setIndependentCouplings(); + // Set parameters that are changed event by event + void setDependentParameters(); + // Set couplings that are changed event by event + void setDependentCouplings(); + + // Print parameters that are unchanged during the run + void printIndependentParameters(); + // Print couplings that are unchanged during the run + void printIndependentCouplings(); + // Print parameters that are changed event by event + void printDependentParameters(); + // Print couplings that are changed event by event + void printDependentCouplings(); + + + private: + static Parameters_sm * instance; +}; + +#endif // Parameters_sm_H + diff --git a/Shower/Dipole/Colorea/eeuugg.cc b/Shower/Dipole/Colorea/eeuugg.cc new file mode 100644 --- /dev/null +++ b/Shower/Dipole/Colorea/eeuugg.cc @@ -0,0 +1,292 @@ +//========================================================================== +// This file has been automatically generated for C++ Standalone by +// MadGraph5_aMC@NLO v. 2.5.4, 2017-03-28 +// By the MadGraph5_aMC@NLO Development Team +// Visit launchpad.net/madgraph5 and amcatnlo.web.cern.ch +//========================================================================== +// and was then modified by J. Bellm. +#include "eeuugg.h" +#include "HelAmps_sm.h" +#include + +using namespace MG5_sm_COLOREA; + +//========================================================================== +// Class member functions for calculating the matrix elements for +// Process: e+ e- > u u~ g g WEIGHTED<=6 @1 + +//-------------------------------------------------------------------------- +// Initialize process. + +vector eeuugg::producePermutation(double r,vector < double * > & momenta){ + + setMomenta(momenta); + sigmaKin(); + + static const int res[2][5] = { + {5, 6, 3, 4, 0}, + {6, 5, 3, 4, 0}}; + + double jampsum=0.; + for( int i=0;i<2;i++) jampsum+=jamp2[0][i]; +// std::cout<<"\njampsum "< r )return std::vector(res[i], res[i] + sizeof res[i] / sizeof res[i][0]); + } + std::cerr<<"\nproducePermutation: Upps.. Something went wrong!!\n"<(); +} + + + +void eeuugg::initProc(string param_card_name) +{ + cout<<"\nColorea: Init process eeuugg for rearrangement (arXiv:1801.06113)."; + // Instantiate the model class and set parameters that stay fixed during run + pars = Parameters_sm::getInstance(); + SLHAReader_COLOREA slha(param_card_name); + pars->setIndependentParameters(slha); + pars->setIndependentCouplings(); +// pars->printIndependentParameters(); +// pars->printIndependentCouplings(); + // Set external particle masses for this matrix element + mME.push_back(pars->ZERO); + mME.push_back(pars->ZERO); + mME.push_back(pars->ZERO); + mME.push_back(pars->ZERO); + mME.push_back(pars->ZERO); + mME.push_back(pars->ZERO); + jamp2[0] = new double[2]; +} + +//-------------------------------------------------------------------------- +// Evaluate |M|^2, part independent of incoming flavour. + +void eeuugg::sigmaKin() +{ + // Set the parameters which change event by event + pars->setDependentParameters(); + pars->setDependentCouplings(); + static bool firsttime = true; + if (firsttime) + { +// pars->printDependentParameters(); +// pars->printDependentCouplings(); + firsttime = false; + } + + // Reset color flows + for(int i = 0; i < 2; i++ ) + jamp2[0][i] = 0.; + + // Local variables and constants + const int ncomb = 64; + static bool goodhel[ncomb] = {ncomb * false}; + static int ntry = 0, sum_hel = 0, ngood = 0; + static int igood[ncomb]; + static int jhel; + double t[nprocesses]; + // Helicities for the process + static const int helicities[ncomb][nexternal] = {{-1, -1, -1, -1, -1, -1}, + {-1, -1, -1, -1, -1, 1}, {-1, -1, -1, -1, 1, -1}, {-1, -1, -1, -1, 1, 1}, + {-1, -1, -1, 1, -1, -1}, {-1, -1, -1, 1, -1, 1}, {-1, -1, -1, 1, 1, -1}, + {-1, -1, -1, 1, 1, 1}, {-1, -1, 1, -1, -1, -1}, {-1, -1, 1, -1, -1, 1}, + {-1, -1, 1, -1, 1, -1}, {-1, -1, 1, -1, 1, 1}, {-1, -1, 1, 1, -1, -1}, + {-1, -1, 1, 1, -1, 1}, {-1, -1, 1, 1, 1, -1}, {-1, -1, 1, 1, 1, 1}, {-1, + 1, -1, -1, -1, -1}, {-1, 1, -1, -1, -1, 1}, {-1, 1, -1, -1, 1, -1}, {-1, + 1, -1, -1, 1, 1}, {-1, 1, -1, 1, -1, -1}, {-1, 1, -1, 1, -1, 1}, {-1, 1, + -1, 1, 1, -1}, {-1, 1, -1, 1, 1, 1}, {-1, 1, 1, -1, -1, -1}, {-1, 1, 1, + -1, -1, 1}, {-1, 1, 1, -1, 1, -1}, {-1, 1, 1, -1, 1, 1}, {-1, 1, 1, 1, + -1, -1}, {-1, 1, 1, 1, -1, 1}, {-1, 1, 1, 1, 1, -1}, {-1, 1, 1, 1, 1, 1}, + {1, -1, -1, -1, -1, -1}, {1, -1, -1, -1, -1, 1}, {1, -1, -1, -1, 1, -1}, + {1, -1, -1, -1, 1, 1}, {1, -1, -1, 1, -1, -1}, {1, -1, -1, 1, -1, 1}, {1, + -1, -1, 1, 1, -1}, {1, -1, -1, 1, 1, 1}, {1, -1, 1, -1, -1, -1}, {1, -1, + 1, -1, -1, 1}, {1, -1, 1, -1, 1, -1}, {1, -1, 1, -1, 1, 1}, {1, -1, 1, 1, + -1, -1}, {1, -1, 1, 1, -1, 1}, {1, -1, 1, 1, 1, -1}, {1, -1, 1, 1, 1, 1}, + {1, 1, -1, -1, -1, -1}, {1, 1, -1, -1, -1, 1}, {1, 1, -1, -1, 1, -1}, {1, + 1, -1, -1, 1, 1}, {1, 1, -1, 1, -1, -1}, {1, 1, -1, 1, -1, 1}, {1, 1, -1, + 1, 1, -1}, {1, 1, -1, 1, 1, 1}, {1, 1, 1, -1, -1, -1}, {1, 1, 1, -1, -1, + 1}, {1, 1, 1, -1, 1, -1}, {1, 1, 1, -1, 1, 1}, {1, 1, 1, 1, -1, -1}, {1, + 1, 1, 1, -1, 1}, {1, 1, 1, 1, 1, -1}, {1, 1, 1, 1, 1, 1}}; + // Denominators: spins, colors and identical particles + const int denominators[nprocesses] = {8}; + + ntry = ntry + 1; + + // Reset the matrix elements + for(int i = 0; i < nprocesses; i++ ) + { + matrix_element[i] = 0.; + } + // Define permutation + int perm[nexternal]; + for(int i = 0; i < nexternal; i++ ) + { + perm[i] = i; + } + + if (sum_hel == 0 || ntry < 10) + { + // Calculate the matrix element for all helicities + for(int ihel = 0; ihel < ncomb; ihel++ ) + { + if (goodhel[ihel] || ntry < 2) + { + calculate_wavefunctions(perm, helicities[ihel]); + t[0] = matrix_1_epem_uuxgg(); + + double tsum = 0; + for(int iproc = 0; iproc < nprocesses; iproc++ ) + { + matrix_element[iproc] += t[iproc]; + tsum += t[iproc]; + } + // Store which helicities give non-zero result + if (tsum != 0. && !goodhel[ihel]) + { + goodhel[ihel] = true; + ngood++; + igood[ngood] = ihel; + } + } + } + jhel = 0; + sum_hel = min(sum_hel, ngood); + } + else + { + // Only use the "good" helicities + for(int j = 0; j < sum_hel; j++ ) + { + jhel++; + if (jhel >= ngood) + jhel = 0; + double hwgt = double(ngood)/double(sum_hel); + int ihel = igood[jhel]; + calculate_wavefunctions(perm, helicities[ihel]); + t[0] = matrix_1_epem_uuxgg(); + + for(int iproc = 0; iproc < nprocesses; iproc++ ) + { + matrix_element[iproc] += t[iproc] * hwgt; + } + } + } + + for (int i = 0; i < nprocesses; i++ ) + matrix_element[i] /= denominators[i]; + + + +} + + +//-------------------------------------------------------------------------- +// Evaluate |M|^2 for each subprocess + +void eeuugg::calculate_wavefunctions(const int perm[], const int hel[]) +{ + // Calculate wavefunctions for all processes + + + // Calculate all wavefunctions + oxxxxx(p[perm[0]], mME[0], hel[0], -1, w[0]); + ixxxxx(p[perm[1]], mME[1], hel[1], +1, w[1]); + oxxxxx(p[perm[2]], mME[2], hel[2], +1, w[2]); + ixxxxx(p[perm[3]], mME[3], hel[3], -1, w[3]); + vxxxxx(p[perm[4]], mME[4], hel[4], +1, w[4]); + vxxxxx(p[perm[5]], mME[5], hel[5], +1, w[5]); + FFV1P0_3(w[1], w[0], pars->GC_3, pars->ZERO, pars->ZERO, w[6]); + FFV1_1(w[2], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[7]); + FFV1_2(w[3], w[6], pars->GC_2, pars->ZERO, pars->ZERO, w[8]); + FFV2_4_3(w[1], w[0], pars->GC_50, pars->GC_59, pars->mdl_MZ, pars->mdl_WZ, + w[9]); + FFV2_5_2(w[3], w[9], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, + w[10]); + FFV1_2(w[3], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[11]); + FFV1_1(w[2], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[12]); + FFV1_2(w[3], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[13]); + FFV1_1(w[2], w[6], pars->GC_2, pars->ZERO, pars->ZERO, w[14]); + FFV2_5_1(w[2], w[9], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, + w[15]); + VVV1P0_1(w[4], w[5], pars->GC_10, pars->ZERO, pars->ZERO, w[16]); + + // Calculate all amplitudes + // Amplitude(s) for diagram number 0 + FFV1_0(w[8], w[7], w[5], pars->GC_11, amp[0]); + FFV1_0(w[10], w[7], w[5], pars->GC_11, amp[1]); + FFV1_0(w[11], w[7], w[6], pars->GC_2, amp[2]); + FFV2_5_0(w[11], w[7], w[9], pars->GC_51, pars->GC_58, amp[3]); + FFV1_0(w[8], w[12], w[4], pars->GC_11, amp[4]); + FFV1_0(w[10], w[12], w[4], pars->GC_11, amp[5]); + FFV1_0(w[13], w[12], w[6], pars->GC_2, amp[6]); + FFV2_5_0(w[13], w[12], w[9], pars->GC_51, pars->GC_58, amp[7]); + FFV1_0(w[13], w[14], w[5], pars->GC_11, amp[8]); + FFV1_0(w[13], w[15], w[5], pars->GC_11, amp[9]); + FFV1_0(w[11], w[14], w[4], pars->GC_11, amp[10]); + FFV1_0(w[11], w[15], w[4], pars->GC_11, amp[11]); + FFV1_0(w[3], w[14], w[16], pars->GC_11, amp[12]); + FFV1_0(w[8], w[2], w[16], pars->GC_11, amp[13]); + FFV1_0(w[3], w[15], w[16], pars->GC_11, amp[14]); + FFV1_0(w[10], w[2], w[16], pars->GC_11, amp[15]); + +} +double eeuugg::matrix_1_epem_uuxgg() +{ + //int i, j; + // Local variables + //const int ngraphs = 16; + //const int ncolor = 2; + std::complex ztemp; + std::complex jamp[2]; + // The color matrix; + //static const double denom[ncolor] = {3, 3}; + //static const double cf[ncolor][ncolor] = {{16, -2}, {-2, 16}}; + + // Calculate color flows + jamp[0] = +amp[0] + amp[1] + amp[2] + amp[3] + amp[10] + amp[11] - + std::complex (0, 1) * amp[12] - std::complex (0, 1) * + amp[13] - std::complex (0, 1) * amp[14] - std::complex + (0, 1) * amp[15]; + jamp[1] = +amp[4] + amp[5] + amp[6] + amp[7] + amp[8] + amp[9] + + std::complex (0, 1) * amp[12] + std::complex (0, 1) * + amp[13] + std::complex (0, 1) * amp[14] + std::complex + (0, 1) * amp[15]; + + // Store the leading color flows for choice of color + for(int i = 0; i < 2; i++ ) + jamp2[0][i] += real(jamp[i] * conj(jamp[i])); + + return -1.; +} + + +double eeuugg::get_jamp2(int i) +{ + return jamp2[0][i]; +} + +int eeuugg::colorstring(int i, int j) +{ + static const double res[2][5] = { + {5, 6, 3, 4, 0}, + {6, 5, 3, 4, 0}}; + return res[i][j]; +} + + +int eeuugg::NCol() +{ + const int ncolor = 2; + return ncolor; +} + + + + + + diff --git a/Shower/Dipole/Colorea/eeuugg.h b/Shower/Dipole/Colorea/eeuugg.h new file mode 100644 --- /dev/null +++ b/Shower/Dipole/Colorea/eeuugg.h @@ -0,0 +1,52 @@ + //========================================================================== + // This file has been automatically generated for C++ Standalone by + // MadGraph5_aMC@NLO v. 2.5.4, 2017-03-28 + // By the MadGraph5_aMC@NLO Development Team + // Visit launchpad.net/madgraph5 and amcatnlo.web.cern.ch + //========================================================================== + // and was then modified by J. Bellm. +#ifndef MG5_Sigma_sm_epem_uuxgg_H +#define MG5_Sigma_sm_epem_uuxgg_H +#include +#include +#include "Parameters_sm.h" +using namespace std; +class eeuugg +{ + public: + eeuugg() { + initProc("param_card.dat"); + } + // Retrun the prefered gluon order + vector producePermutation(double r,vector < double * > & momenta); + void setMass(int i,double M){mME[i]=M;} + private: + ///////// Process Dependent + static const int ninitial = 2; + static const int nexternal = 6; + static const int nprocesses = 1; + static const int nwavefuncs = 17; + static const int namplitudes = 16; + std::complex w[nwavefuncs][18]; + double matrix_1_epem_uuxgg(); + ///////// Generic + double matrix_element[nprocesses]; + std::complex amp[namplitudes]; + double * jamp2[nprocesses]; + Parameters_sm * pars; + vector mME; + vector < double * > p; + int id1, id2; + void initProc(string param_card_name); + void sigmaKin(); + const vector & getMasses() const {return mME;} + vector < double * > getMomenta(){return p;} + void setMomenta(vector < double * > & momenta){p = momenta;} + void setInitial(int inid1, int inid2){id1 = inid1; id2 = inid2;} + void calculate_wavefunctions(const int perm[], const int hel[]); + // New function + double get_jamp2(int i); + int colorstring(int i, int j); + int NCol(); +}; +#endif // MG5_Sigma_sm_epem_uuxgg_H diff --git a/Shower/Dipole/Colorea/eeuuggg.cc b/Shower/Dipole/Colorea/eeuuggg.cc new file mode 100644 --- /dev/null +++ b/Shower/Dipole/Colorea/eeuuggg.cc @@ -0,0 +1,532 @@ +//========================================================================== +// This file has been automatically generated for C++ Standalone by +// MadGraph5_aMC@NLO v. 2.5.4, 2017-03-28 +// By the MadGraph5_aMC@NLO Development Team +// Visit launchpad.net/madgraph5 and amcatnlo.web.cern.ch +//========================================================================== +// and was then modified by J. Bellm. +#include "eeuuggg.h" +#include "HelAmps_sm.h" +#include + +using namespace MG5_sm_COLOREA; + +//========================================================================== +// Class member functions for calculating the matrix elements for +// Process: e+ e- > u u~ g g g WEIGHTED<=7 @1 + +//-------------------------------------------------------------------------- +// Initialize process. + +vector eeuuggg::producePermutation(double r,vector < double * > & momenta){ + static bool initialized=false; + if (!initialized){ + initProc("param_card.dat"); + initialized=true; + } + setMomenta(momenta); + sigmaKin(); + + static const int res[6][6] = { + {5, 6, 7, 3, 4, 0}, + {5, 7, 6, 3, 4, 0}, + {6, 5, 7, 3, 4, 0}, + {6, 7, 5, 3, 4, 0}, + {7, 5, 6, 3, 4, 0}, + {7, 6, 5, 3, 4, 0}}; + + double jampsum=0.; + for( int i=0;i<6;i++) jampsum+=jamp2[0][i]; + double cur=0.; + for(int i=0;i<6;i++){ + cur+=jamp2[0][i]; + if( cur/jampsum > r )return std::vector(res[i], res[i] + sizeof res[i] / sizeof res[i][0]); + } + //std::cout<<"producePermutation: Upps.. Something went wrong!!"; + return std::vector(); +} + + +void eeuuggg::initProc(string param_card_name) +{ + // Instantiate the model class and set parameters that stay fixed during run + cout<<"\nColorea: Init process eeuuggg for rearrangement (arXiv:1801.06113)."; + pars = Parameters_sm::getInstance(); + SLHAReader_COLOREA slha(param_card_name); + pars->setIndependentParameters(slha); + pars->setIndependentCouplings(); +// pars->printIndependentParameters(); +// pars->printIndependentCouplings(); + // Set external particle masses for this matrix element + mME.push_back(pars->ZERO); + mME.push_back(pars->ZERO); + mME.push_back(pars->ZERO); + mME.push_back(pars->ZERO); + mME.push_back(pars->ZERO); + mME.push_back(pars->ZERO); + mME.push_back(pars->ZERO); + jamp2[0] = new double[6]; +} + +//-------------------------------------------------------------------------- +// Evaluate |M|^2, part independent of incoming flavour. + +void eeuuggg::sigmaKin() +{ + // Set the parameters which change event by event + pars->setDependentParameters(); + pars->setDependentCouplings(); + static bool firsttime = true; + if (firsttime) + { +// pars->printDependentParameters(); +// pars->printDependentCouplings(); + firsttime = false; + } + + // Reset color flows + for(int i = 0; i < 6; i++ ) + jamp2[0][i] = 0.; + + // Local variables and constants + const int ncomb = 128; + static bool goodhel[ncomb] = {ncomb * false}; + static int ntry = 0, sum_hel = 0, ngood = 0; + static int igood[ncomb]; + static int jhel; +// std::complex * * wfs; + double t[nprocesses]; + // Helicities for the process + static const int helicities[ncomb][nexternal] = {{-1, -1, -1, -1, -1, -1, + -1}, {-1, -1, -1, -1, -1, -1, 1}, {-1, -1, -1, -1, -1, 1, -1}, {-1, -1, + -1, -1, -1, 1, 1}, {-1, -1, -1, -1, 1, -1, -1}, {-1, -1, -1, -1, 1, -1, + 1}, {-1, -1, -1, -1, 1, 1, -1}, {-1, -1, -1, -1, 1, 1, 1}, {-1, -1, -1, + 1, -1, -1, -1}, {-1, -1, -1, 1, -1, -1, 1}, {-1, -1, -1, 1, -1, 1, -1}, + {-1, -1, -1, 1, -1, 1, 1}, {-1, -1, -1, 1, 1, -1, -1}, {-1, -1, -1, 1, 1, + -1, 1}, {-1, -1, -1, 1, 1, 1, -1}, {-1, -1, -1, 1, 1, 1, 1}, {-1, -1, 1, + -1, -1, -1, -1}, {-1, -1, 1, -1, -1, -1, 1}, {-1, -1, 1, -1, -1, 1, -1}, + {-1, -1, 1, -1, -1, 1, 1}, {-1, -1, 1, -1, 1, -1, -1}, {-1, -1, 1, -1, 1, + -1, 1}, {-1, -1, 1, -1, 1, 1, -1}, {-1, -1, 1, -1, 1, 1, 1}, {-1, -1, 1, + 1, -1, -1, -1}, {-1, -1, 1, 1, -1, -1, 1}, {-1, -1, 1, 1, -1, 1, -1}, + {-1, -1, 1, 1, -1, 1, 1}, {-1, -1, 1, 1, 1, -1, -1}, {-1, -1, 1, 1, 1, + -1, 1}, {-1, -1, 1, 1, 1, 1, -1}, {-1, -1, 1, 1, 1, 1, 1}, {-1, 1, -1, + -1, -1, -1, -1}, {-1, 1, -1, -1, -1, -1, 1}, {-1, 1, -1, -1, -1, 1, -1}, + {-1, 1, -1, -1, -1, 1, 1}, {-1, 1, -1, -1, 1, -1, -1}, {-1, 1, -1, -1, 1, + -1, 1}, {-1, 1, -1, -1, 1, 1, -1}, {-1, 1, -1, -1, 1, 1, 1}, {-1, 1, -1, + 1, -1, -1, -1}, {-1, 1, -1, 1, -1, -1, 1}, {-1, 1, -1, 1, -1, 1, -1}, + {-1, 1, -1, 1, -1, 1, 1}, {-1, 1, -1, 1, 1, -1, -1}, {-1, 1, -1, 1, 1, + -1, 1}, {-1, 1, -1, 1, 1, 1, -1}, {-1, 1, -1, 1, 1, 1, 1}, {-1, 1, 1, -1, + -1, -1, -1}, {-1, 1, 1, -1, -1, -1, 1}, {-1, 1, 1, -1, -1, 1, -1}, {-1, + 1, 1, -1, -1, 1, 1}, {-1, 1, 1, -1, 1, -1, -1}, {-1, 1, 1, -1, 1, -1, 1}, + {-1, 1, 1, -1, 1, 1, -1}, {-1, 1, 1, -1, 1, 1, 1}, {-1, 1, 1, 1, -1, -1, + -1}, {-1, 1, 1, 1, -1, -1, 1}, {-1, 1, 1, 1, -1, 1, -1}, {-1, 1, 1, 1, + -1, 1, 1}, {-1, 1, 1, 1, 1, -1, -1}, {-1, 1, 1, 1, 1, -1, 1}, {-1, 1, 1, + 1, 1, 1, -1}, {-1, 1, 1, 1, 1, 1, 1}, {1, -1, -1, -1, -1, -1, -1}, {1, + -1, -1, -1, -1, -1, 1}, {1, -1, -1, -1, -1, 1, -1}, {1, -1, -1, -1, -1, + 1, 1}, {1, -1, -1, -1, 1, -1, -1}, {1, -1, -1, -1, 1, -1, 1}, {1, -1, -1, + -1, 1, 1, -1}, {1, -1, -1, -1, 1, 1, 1}, {1, -1, -1, 1, -1, -1, -1}, {1, + -1, -1, 1, -1, -1, 1}, {1, -1, -1, 1, -1, 1, -1}, {1, -1, -1, 1, -1, 1, + 1}, {1, -1, -1, 1, 1, -1, -1}, {1, -1, -1, 1, 1, -1, 1}, {1, -1, -1, 1, + 1, 1, -1}, {1, -1, -1, 1, 1, 1, 1}, {1, -1, 1, -1, -1, -1, -1}, {1, -1, + 1, -1, -1, -1, 1}, {1, -1, 1, -1, -1, 1, -1}, {1, -1, 1, -1, -1, 1, 1}, + {1, -1, 1, -1, 1, -1, -1}, {1, -1, 1, -1, 1, -1, 1}, {1, -1, 1, -1, 1, 1, + -1}, {1, -1, 1, -1, 1, 1, 1}, {1, -1, 1, 1, -1, -1, -1}, {1, -1, 1, 1, + -1, -1, 1}, {1, -1, 1, 1, -1, 1, -1}, {1, -1, 1, 1, -1, 1, 1}, {1, -1, 1, + 1, 1, -1, -1}, {1, -1, 1, 1, 1, -1, 1}, {1, -1, 1, 1, 1, 1, -1}, {1, -1, + 1, 1, 1, 1, 1}, {1, 1, -1, -1, -1, -1, -1}, {1, 1, -1, -1, -1, -1, 1}, + {1, 1, -1, -1, -1, 1, -1}, {1, 1, -1, -1, -1, 1, 1}, {1, 1, -1, -1, 1, + -1, -1}, {1, 1, -1, -1, 1, -1, 1}, {1, 1, -1, -1, 1, 1, -1}, {1, 1, -1, + -1, 1, 1, 1}, {1, 1, -1, 1, -1, -1, -1}, {1, 1, -1, 1, -1, -1, 1}, {1, 1, + -1, 1, -1, 1, -1}, {1, 1, -1, 1, -1, 1, 1}, {1, 1, -1, 1, 1, -1, -1}, {1, + 1, -1, 1, 1, -1, 1}, {1, 1, -1, 1, 1, 1, -1}, {1, 1, -1, 1, 1, 1, 1}, {1, + 1, 1, -1, -1, -1, -1}, {1, 1, 1, -1, -1, -1, 1}, {1, 1, 1, -1, -1, 1, + -1}, {1, 1, 1, -1, -1, 1, 1}, {1, 1, 1, -1, 1, -1, -1}, {1, 1, 1, -1, 1, + -1, 1}, {1, 1, 1, -1, 1, 1, -1}, {1, 1, 1, -1, 1, 1, 1}, {1, 1, 1, 1, -1, + -1, -1}, {1, 1, 1, 1, -1, -1, 1}, {1, 1, 1, 1, -1, 1, -1}, {1, 1, 1, 1, + -1, 1, 1}, {1, 1, 1, 1, 1, -1, -1}, {1, 1, 1, 1, 1, -1, 1}, {1, 1, 1, 1, + 1, 1, -1}, {1, 1, 1, 1, 1, 1, 1}}; + // Denominators: spins, colors and identical particles + const int denominators[nprocesses] = {24}; + + ntry = ntry + 1; + + // Reset the matrix elements + for(int i = 0; i < nprocesses; i++ ) + { + matrix_element[i] = 0.; + } + // Define permutation + int perm[nexternal]; + for(int i = 0; i < nexternal; i++ ) + { + perm[i] = i; + } + + if (sum_hel == 0 || ntry < 10) + { + // Calculate the matrix element for all helicities + for(int ihel = 0; ihel < ncomb; ihel++ ) + { + if (goodhel[ihel] || ntry < 2) + { + calculate_wavefunctions(perm, helicities[ihel]); + t[0] = matrix_1_epem_uuxggg(); + + double tsum = 0; + for(int iproc = 0; iproc < nprocesses; iproc++ ) + { + matrix_element[iproc] += t[iproc]; + tsum += t[iproc]; + } + // Store which helicities give non-zero result + if (tsum != 0. && !goodhel[ihel]) + { + goodhel[ihel] = true; + ngood++; + igood[ngood] = ihel; + } + } + } + jhel = 0; + sum_hel = min(sum_hel, ngood); + } + else + { + // Only use the "good" helicities + for(int j = 0; j < sum_hel; j++ ) + { + jhel++; + if (jhel >= ngood) + jhel = 0; + double hwgt = double(ngood)/double(sum_hel); + int ihel = igood[jhel]; + calculate_wavefunctions(perm, helicities[ihel]); + t[0] = matrix_1_epem_uuxggg(); + + for(int iproc = 0; iproc < nprocesses; iproc++ ) + { + matrix_element[iproc] += t[iproc] * hwgt; + } + } + } + + for (int i = 0; i < nprocesses; i++ ) + matrix_element[i] /= denominators[i]; + + + +} + + +//========================================================================== +// Private class member functions + +//-------------------------------------------------------------------------- +// Evaluate |M|^2 for each subprocess + +void eeuuggg::calculate_wavefunctions(const int perm[], const int hel[]) +{ + // Calculate wavefunctions for all processes +// int i;//, j; + + // Calculate all wavefunctions + oxxxxx(p[perm[0]], mME[0], hel[0], -1, w[0]); + ixxxxx(p[perm[1]], mME[1], hel[1], +1, w[1]); + oxxxxx(p[perm[2]], mME[2], hel[2], +1, w[2]); + ixxxxx(p[perm[3]], mME[3], hel[3], -1, w[3]); + vxxxxx(p[perm[4]], mME[4], hel[4], +1, w[4]); + vxxxxx(p[perm[5]], mME[5], hel[5], +1, w[5]); + vxxxxx(p[perm[6]], mME[6], hel[6], +1, w[6]); + FFV1P0_3(w[1], w[0], pars->GC_3, pars->ZERO, pars->ZERO, w[7]); + FFV1_1(w[2], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[8]); + FFV1_2(w[3], w[7], pars->GC_2, pars->ZERO, pars->ZERO, w[9]); + FFV1_1(w[8], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[10]); + FFV1_1(w[8], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[11]); + FFV2_4_3(w[1], w[0], pars->GC_50, pars->GC_59, pars->mdl_MZ, pars->mdl_WZ, + w[12]); + FFV2_5_2(w[3], w[12], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, + w[13]); + FFV1_2(w[3], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[14]); + FFV1_1(w[8], w[7], pars->GC_2, pars->ZERO, pars->ZERO, w[15]); + FFV1_2(w[14], w[7], pars->GC_2, pars->ZERO, pars->ZERO, w[16]); + FFV2_5_1(w[8], w[12], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, + w[17]); + FFV2_5_2(w[14], w[12], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, + w[18]); + FFV1_2(w[3], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[19]); + FFV1_2(w[19], w[7], pars->GC_2, pars->ZERO, pars->ZERO, w[20]); + FFV2_5_2(w[19], w[12], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, + w[21]); + VVV1P0_1(w[5], w[6], pars->GC_10, pars->ZERO, pars->ZERO, w[22]); + FFV1_1(w[2], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[23]); + FFV1_1(w[23], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[24]); + FFV1_1(w[23], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[25]); + FFV1_2(w[3], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[26]); + FFV1_1(w[23], w[7], pars->GC_2, pars->ZERO, pars->ZERO, w[27]); + FFV1_2(w[26], w[7], pars->GC_2, pars->ZERO, pars->ZERO, w[28]); + FFV2_5_1(w[23], w[12], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, + w[29]); + FFV2_5_2(w[26], w[12], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, + w[30]); + VVV1P0_1(w[4], w[6], pars->GC_10, pars->ZERO, pars->ZERO, w[31]); + FFV1_1(w[2], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[32]); + FFV1_1(w[32], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[33]); + FFV1_1(w[32], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[34]); + FFV1_1(w[32], w[7], pars->GC_2, pars->ZERO, pars->ZERO, w[35]); + FFV2_5_1(w[32], w[12], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, + w[36]); + VVV1P0_1(w[4], w[5], pars->GC_10, pars->ZERO, pars->ZERO, w[37]); + FFV1_1(w[2], w[7], pars->GC_2, pars->ZERO, pars->ZERO, w[38]); + FFV1_2(w[26], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[39]); + FFV1_2(w[26], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[40]); + FFV2_5_1(w[2], w[12], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, + w[41]); + FFV1_2(w[14], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[42]); + FFV1_2(w[14], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[43]); + FFV1_2(w[19], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[44]); + FFV1_2(w[19], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[45]); + FFV1_2(w[3], w[37], pars->GC_11, pars->ZERO, pars->ZERO, w[46]); + VVV1P0_1(w[37], w[6], pars->GC_10, pars->ZERO, pars->ZERO, w[47]); + FFV1_1(w[2], w[37], pars->GC_11, pars->ZERO, pars->ZERO, w[48]); + FFV1_2(w[3], w[31], pars->GC_11, pars->ZERO, pars->ZERO, w[49]); + VVV1P0_1(w[31], w[5], pars->GC_10, pars->ZERO, pars->ZERO, w[50]); + FFV1_1(w[2], w[31], pars->GC_11, pars->ZERO, pars->ZERO, w[51]); + FFV1_2(w[3], w[22], pars->GC_11, pars->ZERO, pars->ZERO, w[52]); + VVV1P0_1(w[4], w[22], pars->GC_10, pars->ZERO, pars->ZERO, w[53]); + FFV1_1(w[2], w[22], pars->GC_11, pars->ZERO, pars->ZERO, w[54]); + VVVV1P0_1(w[4], w[5], w[6], pars->GC_12, pars->ZERO, pars->ZERO, w[55]); + VVVV3P0_1(w[4], w[5], w[6], pars->GC_12, pars->ZERO, pars->ZERO, w[56]); + VVVV4P0_1(w[4], w[5], w[6], pars->GC_12, pars->ZERO, pars->ZERO, w[57]); + + // Calculate all amplitudes + // Amplitude(s) for diagram number 0 + FFV1_0(w[9], w[10], w[6], pars->GC_11, amp[0]); + FFV1_0(w[9], w[11], w[5], pars->GC_11, amp[1]); + FFV1_0(w[13], w[10], w[6], pars->GC_11, amp[2]); + FFV1_0(w[13], w[11], w[5], pars->GC_11, amp[3]); + FFV1_0(w[14], w[15], w[6], pars->GC_11, amp[4]); + FFV1_0(w[16], w[8], w[6], pars->GC_11, amp[5]); + FFV1_0(w[14], w[17], w[6], pars->GC_11, amp[6]); + FFV1_0(w[18], w[8], w[6], pars->GC_11, amp[7]); + FFV1_0(w[19], w[15], w[5], pars->GC_11, amp[8]); + FFV1_0(w[20], w[8], w[5], pars->GC_11, amp[9]); + FFV1_0(w[19], w[17], w[5], pars->GC_11, amp[10]); + FFV1_0(w[21], w[8], w[5], pars->GC_11, amp[11]); + FFV1_0(w[3], w[15], w[22], pars->GC_11, amp[12]); + FFV1_0(w[9], w[8], w[22], pars->GC_11, amp[13]); + FFV1_0(w[3], w[17], w[22], pars->GC_11, amp[14]); + FFV1_0(w[13], w[8], w[22], pars->GC_11, amp[15]); + FFV1_0(w[9], w[24], w[6], pars->GC_11, amp[16]); + FFV1_0(w[9], w[25], w[4], pars->GC_11, amp[17]); + FFV1_0(w[13], w[24], w[6], pars->GC_11, amp[18]); + FFV1_0(w[13], w[25], w[4], pars->GC_11, amp[19]); + FFV1_0(w[26], w[27], w[6], pars->GC_11, amp[20]); + FFV1_0(w[28], w[23], w[6], pars->GC_11, amp[21]); + FFV1_0(w[26], w[29], w[6], pars->GC_11, amp[22]); + FFV1_0(w[30], w[23], w[6], pars->GC_11, amp[23]); + FFV1_0(w[19], w[27], w[4], pars->GC_11, amp[24]); + FFV1_0(w[20], w[23], w[4], pars->GC_11, amp[25]); + FFV1_0(w[19], w[29], w[4], pars->GC_11, amp[26]); + FFV1_0(w[21], w[23], w[4], pars->GC_11, amp[27]); + FFV1_0(w[3], w[27], w[31], pars->GC_11, amp[28]); + FFV1_0(w[9], w[23], w[31], pars->GC_11, amp[29]); + FFV1_0(w[3], w[29], w[31], pars->GC_11, amp[30]); + FFV1_0(w[13], w[23], w[31], pars->GC_11, amp[31]); + FFV1_0(w[9], w[33], w[5], pars->GC_11, amp[32]); + FFV1_0(w[9], w[34], w[4], pars->GC_11, amp[33]); + FFV1_0(w[13], w[33], w[5], pars->GC_11, amp[34]); + FFV1_0(w[13], w[34], w[4], pars->GC_11, amp[35]); + FFV1_0(w[26], w[35], w[5], pars->GC_11, amp[36]); + FFV1_0(w[28], w[32], w[5], pars->GC_11, amp[37]); + FFV1_0(w[26], w[36], w[5], pars->GC_11, amp[38]); + FFV1_0(w[30], w[32], w[5], pars->GC_11, amp[39]); + FFV1_0(w[14], w[35], w[4], pars->GC_11, amp[40]); + FFV1_0(w[16], w[32], w[4], pars->GC_11, amp[41]); + FFV1_0(w[14], w[36], w[4], pars->GC_11, amp[42]); + FFV1_0(w[18], w[32], w[4], pars->GC_11, amp[43]); + FFV1_0(w[3], w[35], w[37], pars->GC_11, amp[44]); + FFV1_0(w[9], w[32], w[37], pars->GC_11, amp[45]); + FFV1_0(w[3], w[36], w[37], pars->GC_11, amp[46]); + FFV1_0(w[13], w[32], w[37], pars->GC_11, amp[47]); + FFV1_0(w[39], w[38], w[6], pars->GC_11, amp[48]); + FFV1_0(w[40], w[38], w[5], pars->GC_11, amp[49]); + FFV1_0(w[39], w[41], w[6], pars->GC_11, amp[50]); + FFV1_0(w[40], w[41], w[5], pars->GC_11, amp[51]); + FFV1_0(w[26], w[38], w[22], pars->GC_11, amp[52]); + FFV1_0(w[28], w[2], w[22], pars->GC_11, amp[53]); + FFV1_0(w[26], w[41], w[22], pars->GC_11, amp[54]); + FFV1_0(w[30], w[2], w[22], pars->GC_11, amp[55]); + FFV1_0(w[42], w[38], w[6], pars->GC_11, amp[56]); + FFV1_0(w[43], w[38], w[4], pars->GC_11, amp[57]); + FFV1_0(w[42], w[41], w[6], pars->GC_11, amp[58]); + FFV1_0(w[43], w[41], w[4], pars->GC_11, amp[59]); + FFV1_0(w[14], w[38], w[31], pars->GC_11, amp[60]); + FFV1_0(w[16], w[2], w[31], pars->GC_11, amp[61]); + FFV1_0(w[14], w[41], w[31], pars->GC_11, amp[62]); + FFV1_0(w[18], w[2], w[31], pars->GC_11, amp[63]); + FFV1_0(w[44], w[38], w[5], pars->GC_11, amp[64]); + FFV1_0(w[45], w[38], w[4], pars->GC_11, amp[65]); + FFV1_0(w[44], w[41], w[5], pars->GC_11, amp[66]); + FFV1_0(w[45], w[41], w[4], pars->GC_11, amp[67]); + FFV1_0(w[19], w[38], w[37], pars->GC_11, amp[68]); + FFV1_0(w[20], w[2], w[37], pars->GC_11, amp[69]); + FFV1_0(w[19], w[41], w[37], pars->GC_11, amp[70]); + FFV1_0(w[21], w[2], w[37], pars->GC_11, amp[71]); + FFV1_0(w[46], w[38], w[6], pars->GC_11, amp[72]); + FFV1_0(w[3], w[38], w[47], pars->GC_11, amp[73]); + FFV1_0(w[9], w[48], w[6], pars->GC_11, amp[74]); + FFV1_0(w[9], w[2], w[47], pars->GC_11, amp[75]); + FFV1_0(w[46], w[41], w[6], pars->GC_11, amp[76]); + FFV1_0(w[3], w[41], w[47], pars->GC_11, amp[77]); + FFV1_0(w[13], w[48], w[6], pars->GC_11, amp[78]); + FFV1_0(w[13], w[2], w[47], pars->GC_11, amp[79]); + FFV1_0(w[49], w[38], w[5], pars->GC_11, amp[80]); + FFV1_0(w[3], w[38], w[50], pars->GC_11, amp[81]); + FFV1_0(w[9], w[51], w[5], pars->GC_11, amp[82]); + FFV1_0(w[9], w[2], w[50], pars->GC_11, amp[83]); + FFV1_0(w[49], w[41], w[5], pars->GC_11, amp[84]); + FFV1_0(w[3], w[41], w[50], pars->GC_11, amp[85]); + FFV1_0(w[13], w[51], w[5], pars->GC_11, amp[86]); + FFV1_0(w[13], w[2], w[50], pars->GC_11, amp[87]); + FFV1_0(w[52], w[38], w[4], pars->GC_11, amp[88]); + FFV1_0(w[3], w[38], w[53], pars->GC_11, amp[89]); + FFV1_0(w[9], w[54], w[4], pars->GC_11, amp[90]); + FFV1_0(w[9], w[2], w[53], pars->GC_11, amp[91]); + FFV1_0(w[52], w[41], w[4], pars->GC_11, amp[92]); + FFV1_0(w[3], w[41], w[53], pars->GC_11, amp[93]); + FFV1_0(w[13], w[54], w[4], pars->GC_11, amp[94]); + FFV1_0(w[13], w[2], w[53], pars->GC_11, amp[95]); + FFV1_0(w[3], w[38], w[55], pars->GC_11, amp[96]); + FFV1_0(w[3], w[38], w[56], pars->GC_11, amp[97]); + FFV1_0(w[3], w[38], w[57], pars->GC_11, amp[98]); + FFV1_0(w[9], w[2], w[55], pars->GC_11, amp[99]); + FFV1_0(w[9], w[2], w[56], pars->GC_11, amp[100]); + FFV1_0(w[9], w[2], w[57], pars->GC_11, amp[101]); + FFV1_0(w[3], w[41], w[55], pars->GC_11, amp[102]); + FFV1_0(w[3], w[41], w[56], pars->GC_11, amp[103]); + FFV1_0(w[3], w[41], w[57], pars->GC_11, amp[104]); + FFV1_0(w[13], w[2], w[55], pars->GC_11, amp[105]); + FFV1_0(w[13], w[2], w[56], pars->GC_11, amp[106]); + FFV1_0(w[13], w[2], w[57], pars->GC_11, amp[107]); + +} +double eeuuggg::matrix_1_epem_uuxggg() +{ + int i;//, j; + // Local variables +// const int ngraphs = 108; + const int ncolor = 6; + std::complex ztemp; + std::complex jamp[ncolor]; + // The color matrix; +// static const double denom[ncolor] = {9, 9, 9, 9, 9, 9}; +// static const double cf[ncolor][ncolor] = {{64, -8, -8, 1, 1, 10}, {-8, 64, 1, +// 10, -8, 1}, {-8, 1, 64, -8, 10, 1}, {1, 10, -8, 64, 1, -8}, {1, -8, 10, +// 1, 64, -8}, {10, 1, 1, -8, -8, 64}}; + + // Calculate color flows + jamp[0] = +amp[0] + amp[2] + amp[8] + amp[9] + amp[10] + amp[11] - + std::complex (0, 1) * amp[12] - std::complex (0, 1) * + amp[13] - std::complex (0, 1) * amp[14] - std::complex + (0, 1) * amp[15] + amp[65] + amp[67] - std::complex (0, 1) * + amp[68] - std::complex (0, 1) * amp[69] - std::complex + (0, 1) * amp[70] - std::complex (0, 1) * amp[71] - amp[73] - + std::complex (0, 1) * amp[74] - amp[75] - amp[77] - + std::complex (0, 1) * amp[78] - amp[79] - std::complex + (0, 1) * amp[88] - amp[89] - amp[91] - std::complex (0, 1) * + amp[92] - amp[93] - amp[95] + amp[98] - amp[96] + amp[101] - amp[99] + + amp[104] - amp[102] + amp[107] - amp[105]; + jamp[1] = +amp[1] + amp[3] + amp[4] + amp[5] + amp[6] + amp[7] + + std::complex (0, 1) * amp[12] + std::complex (0, 1) * + amp[13] + std::complex (0, 1) * amp[14] + std::complex + (0, 1) * amp[15] + amp[57] + amp[59] - std::complex (0, 1) * + amp[60] - std::complex (0, 1) * amp[61] - std::complex + (0, 1) * amp[62] - std::complex (0, 1) * amp[63] - amp[81] - + std::complex (0, 1) * amp[82] - amp[83] - amp[85] - + std::complex (0, 1) * amp[86] - amp[87] + std::complex + (0, 1) * amp[88] + amp[89] + amp[91] + std::complex (0, 1) * + amp[92] + amp[93] + amp[95] + amp[96] + amp[97] + amp[99] + amp[100] + + amp[102] + amp[103] + amp[105] + amp[106]; + jamp[2] = +amp[16] + amp[18] + amp[24] + amp[25] + amp[26] + amp[27] - + std::complex (0, 1) * amp[28] - std::complex (0, 1) * + amp[29] - std::complex (0, 1) * amp[30] - std::complex + (0, 1) * amp[31] + amp[64] + amp[66] + std::complex (0, 1) * + amp[68] + std::complex (0, 1) * amp[69] + std::complex + (0, 1) * amp[70] + std::complex (0, 1) * amp[71] + amp[73] + + std::complex (0, 1) * amp[74] + amp[75] + amp[77] + + std::complex (0, 1) * amp[78] + amp[79] - std::complex + (0, 1) * amp[80] + amp[81] + amp[83] - std::complex (0, 1) * + amp[84] + amp[85] + amp[87] - amp[98] - amp[97] - amp[101] - amp[100] - + amp[104] - amp[103] - amp[107] - amp[106]; + jamp[3] = +amp[17] + amp[19] + amp[20] + amp[21] + amp[22] + amp[23] + + std::complex (0, 1) * amp[28] + std::complex (0, 1) * + amp[29] + std::complex (0, 1) * amp[30] + std::complex + (0, 1) * amp[31] + amp[49] + amp[51] - std::complex (0, 1) * + amp[52] - std::complex (0, 1) * amp[53] - std::complex + (0, 1) * amp[54] - std::complex (0, 1) * amp[55] + + std::complex (0, 1) * amp[80] - amp[81] - amp[83] + + std::complex (0, 1) * amp[84] - amp[85] - amp[87] + amp[89] - + std::complex (0, 1) * amp[90] + amp[91] + amp[93] - + std::complex (0, 1) * amp[94] + amp[95] + amp[96] + amp[97] + + amp[99] + amp[100] + amp[102] + amp[103] + amp[105] + amp[106]; + jamp[4] = +amp[32] + amp[34] + amp[40] + amp[41] + amp[42] + amp[43] - + std::complex (0, 1) * amp[44] - std::complex (0, 1) * + amp[45] - std::complex (0, 1) * amp[46] - std::complex + (0, 1) * amp[47] + amp[56] + amp[58] + std::complex (0, 1) * + amp[60] + std::complex (0, 1) * amp[61] + std::complex + (0, 1) * amp[62] + std::complex (0, 1) * amp[63] - + std::complex (0, 1) * amp[72] + amp[73] + amp[75] - + std::complex (0, 1) * amp[76] + amp[77] + amp[79] + amp[81] + + std::complex (0, 1) * amp[82] + amp[83] + amp[85] + + std::complex (0, 1) * amp[86] + amp[87] - amp[98] - amp[97] - + amp[101] - amp[100] - amp[104] - amp[103] - amp[107] - amp[106]; + jamp[5] = +amp[33] + amp[35] + amp[36] + amp[37] + amp[38] + amp[39] + + std::complex (0, 1) * amp[44] + std::complex (0, 1) * + amp[45] + std::complex (0, 1) * amp[46] + std::complex + (0, 1) * amp[47] + amp[48] + amp[50] + std::complex (0, 1) * + amp[52] + std::complex (0, 1) * amp[53] + std::complex + (0, 1) * amp[54] + std::complex (0, 1) * amp[55] + + std::complex (0, 1) * amp[72] - amp[73] - amp[75] + + std::complex (0, 1) * amp[76] - amp[77] - amp[79] - amp[89] + + std::complex (0, 1) * amp[90] - amp[91] - amp[93] + + std::complex (0, 1) * amp[94] - amp[95] + amp[98] - amp[96] + + amp[101] - amp[99] + amp[104] - amp[102] + amp[107] - amp[105]; + + + + // Store the leading color flows for choice of color + for(i = 0; i < ncolor; i++ ) + jamp2[0][i] += real(jamp[i] * conj(jamp[i])); + + return -1.; +} + + +double eeuuggg::get_jamp2(int i) +{ + return jamp2[0][i]; +} + +int eeuuggg::colorstring(int i, int j) +{ + static const double res[6][6] = { + {5, 6, 7, 3, 4, 0}, + {5, 7, 6, 3, 4, 0}, + {6, 5, 7, 3, 4, 0}, + {6, 7, 5, 3, 4, 0}, + {7, 5, 6, 3, 4, 0}, + {7, 6, 5, 3, 4, 0}}; + return res[i][j]; +} + + +int eeuuggg::NCol() +{ + const int ncolor = 6; + return ncolor; +} + + + + + diff --git a/Shower/Dipole/Colorea/eeuuggg.h b/Shower/Dipole/Colorea/eeuuggg.h new file mode 100644 --- /dev/null +++ b/Shower/Dipole/Colorea/eeuuggg.h @@ -0,0 +1,52 @@ + //========================================================================== + // This file has been automatically generated for C++ Standalone by + // MadGraph5_aMC@NLO v. 2.5.4, 2017-03-28 + // By the MadGraph5_aMC@NLO Development Team + // Visit launchpad.net/madgraph5 and amcatnlo.web.cern.ch + //========================================================================== + // and was then modified by J. Bellm. +#ifndef MG5_Sigma_sm_epem_uuxggg_H +#define MG5_Sigma_sm_epem_uuxggg_H +#include +#include +#include "Parameters_sm.h" +using namespace std; +class eeuuggg +{ + public: + eeuuggg() { + initProc("param_card.dat"); + } + // Retrun the prefered gluon order + vector producePermutation(double r,vector < double * > & momenta); + void setMass(int i,double M){mME[i]=M;} + private: + ///////// Process Dependent + static const int ninitial = 2; + static const int nexternal = 7; + static const int nprocesses = 1; + static const int nwavefuncs = 58; + static const int namplitudes = 108; + std::complex w[nwavefuncs][18]; + double matrix_1_epem_uuxggg(); + ///////// Generic + double matrix_element[nprocesses]; + std::complex amp[namplitudes]; + double * jamp2[nprocesses]; + Parameters_sm * pars; + vector mME; + vector < double * > p; + int id1, id2; + void initProc(string param_card_name); + void sigmaKin(); + const vector & getMasses() const {return mME;} + vector < double * > getMomenta(){return p;} + void setMomenta(vector < double * > & momenta){p = momenta;} + void setInitial(int inid1, int inid2){id1 = inid1; id2 = inid2;} + void calculate_wavefunctions(const int perm[], const int hel[]); + // New function + double get_jamp2(int i); + int colorstring(int i, int j); + int NCol(); +}; +#endif // MG5_Sigma_sm_epem_uuxggg_H diff --git a/Shower/Dipole/Colorea/eeuugggg.cc b/Shower/Dipole/Colorea/eeuugggg.cc new file mode 100644 --- /dev/null +++ b/Shower/Dipole/Colorea/eeuugggg.cc @@ -0,0 +1,3120 @@ +//========================================================================== +// This file has been automatically generated for C++ Standalone by +// MadGraph5_aMC@NLO v. 2.5.4, 2017-03-28 +// By the MadGraph5_aMC@NLO Development Team +// Visit launchpad.net/madgraph5 and amcatnlo.web.cern.ch +//========================================================================== +// and was then modified by J. Bellm. +#include "eeuugggg.h" +#include "HelAmps_sm.h" +#include + +using namespace MG5_sm_COLOREA; + +//========================================================================== +// Class member functions for calculating the matrix elements for +// Process: e+ e- > u u~ g g g g WEIGHTED<=8 @1 + +//-------------------------------------------------------------------------- +// Initialize process. + +vector eeuugggg::producePermutation(double r,vector < double * > & momenta){ + static bool initialized=false; + if (!initialized){ + initProc("param_card.dat"); + initialized=true; + } + setMomenta(momenta); + sigmaKin(); + + + static const int res[24][8] = { + {5, 6, 7, 8, 3, 4, 0, 0}, + {5, 6, 8, 7, 3, 4, 0, 0}, + {5, 7, 6, 8, 3, 4, 0, 0}, + {5, 7, 8, 6, 3, 4, 0, 0}, + {5, 8, 6, 7, 3, 4, 0, 0}, + {5, 8, 7, 6, 3, 4, 0, 0}, + {6, 5, 7, 8, 3, 4, 0, 0}, + {6, 5, 8, 7, 3, 4, 0, 0}, + {6, 7, 5, 8, 3, 4, 0, 0}, + {6, 7, 8, 5, 3, 4, 0, 0}, + {6, 8, 5, 7, 3, 4, 0, 0}, + {6, 8, 7, 5, 3, 4, 0, 0}, + {7, 5, 6, 8, 3, 4, 0, 0}, + {7, 5, 8, 6, 3, 4, 0, 0}, + {7, 6, 5, 8, 3, 4, 0, 0}, + {7, 6, 8, 5, 3, 4, 0, 0}, + {7, 8, 5, 6, 3, 4, 0, 0}, + {7, 8, 6, 5, 3, 4, 0, 0}, + {8, 5, 6, 7, 3, 4, 0, 0}, + {8, 5, 7, 6, 3, 4, 0, 0}, + {8, 6, 5, 7, 3, 4, 0, 0}, + {8, 6, 7, 5, 3, 4, 0, 0}, + {8, 7, 5, 6, 3, 4, 0, 0}, + {8, 7, 6, 5, 3, 4, 0, 0}}; + + double jampsum=0.; + for( int i=0;i<24;i++) jampsum+=jamp2[0][i]; + double cur=0.; + for(int i=0;i<24;i++){ + cur+=jamp2[0][i]; + if( cur/jampsum > r )return std::vector(res[i], res[i] + sizeof res[i] / sizeof res[i][0]); + } + //std::cout<<"producePermutation: Upps.. Something went wrong!!"; + return std::vector(); +} + + + +void eeuugggg::initProc(string param_card_name) +{ + cout<<"\nColorea: Init process eeuugggg for rearrangement (arXiv:1801.06113)."; + // Instantiate the model class and set parameters that stay fixed during run + pars = Parameters_sm::getInstance(); + SLHAReader_COLOREA slha(param_card_name); + pars->setIndependentParameters(slha); + pars->setIndependentCouplings(); +// pars->printIndependentParameters(); +// pars->printIndependentCouplings(); + // Set external particle masses for this matrix element + mME.push_back(pars->ZERO); + mME.push_back(pars->ZERO); + mME.push_back(pars->ZERO); + mME.push_back(pars->ZERO); + mME.push_back(pars->ZERO); + mME.push_back(pars->ZERO); + mME.push_back(pars->ZERO); + mME.push_back(pars->ZERO); + jamp2[0] = new double[24]; +} + +//-------------------------------------------------------------------------- +// Evaluate |M|^2, part independent of incoming flavour. + +void eeuugggg::sigmaKin() +{ + // Set the parameters which change event by event + pars->setDependentParameters(); + pars->setDependentCouplings(); + static bool firsttime = true; + if (firsttime) + { +// pars->printDependentParameters(); +// pars->printDependentCouplings(); + firsttime = false; + } + + // Reset color flows + for(int i = 0; i < 24; i++ ) + jamp2[0][i] = 0.; + + // Local variables and constants + const int ncomb = 256; + static bool goodhel[ncomb] = {ncomb * false}; + static int ntry = 0, sum_hel = 0, ngood = 0; + static int igood[ncomb]; + static int jhel; +// std::complex * * wfs; + double t[nprocesses]; + // Helicities for the process + static const int helicities[ncomb][nexternal] = {{-1, -1, -1, -1, -1, -1, -1, + -1}, {-1, -1, -1, -1, -1, -1, -1, 1}, {-1, -1, -1, -1, -1, -1, 1, -1}, + {-1, -1, -1, -1, -1, -1, 1, 1}, {-1, -1, -1, -1, -1, 1, -1, -1}, {-1, -1, + -1, -1, -1, 1, -1, 1}, {-1, -1, -1, -1, -1, 1, 1, -1}, {-1, -1, -1, -1, + -1, 1, 1, 1}, {-1, -1, -1, -1, 1, -1, -1, -1}, {-1, -1, -1, -1, 1, -1, + -1, 1}, {-1, -1, -1, -1, 1, -1, 1, -1}, {-1, -1, -1, -1, 1, -1, 1, 1}, + {-1, -1, -1, -1, 1, 1, -1, -1}, {-1, -1, -1, -1, 1, 1, -1, 1}, {-1, -1, + -1, -1, 1, 1, 1, -1}, {-1, -1, -1, -1, 1, 1, 1, 1}, {-1, -1, -1, 1, -1, + -1, -1, -1}, {-1, -1, -1, 1, -1, -1, -1, 1}, {-1, -1, -1, 1, -1, -1, 1, + -1}, {-1, -1, -1, 1, -1, -1, 1, 1}, {-1, -1, -1, 1, -1, 1, -1, -1}, {-1, + -1, -1, 1, -1, 1, -1, 1}, {-1, -1, -1, 1, -1, 1, 1, -1}, {-1, -1, -1, 1, + -1, 1, 1, 1}, {-1, -1, -1, 1, 1, -1, -1, -1}, {-1, -1, -1, 1, 1, -1, -1, + 1}, {-1, -1, -1, 1, 1, -1, 1, -1}, {-1, -1, -1, 1, 1, -1, 1, 1}, {-1, -1, + -1, 1, 1, 1, -1, -1}, {-1, -1, -1, 1, 1, 1, -1, 1}, {-1, -1, -1, 1, 1, 1, + 1, -1}, {-1, -1, -1, 1, 1, 1, 1, 1}, {-1, -1, 1, -1, -1, -1, -1, -1}, + {-1, -1, 1, -1, -1, -1, -1, 1}, {-1, -1, 1, -1, -1, -1, 1, -1}, {-1, -1, + 1, -1, -1, -1, 1, 1}, {-1, -1, 1, -1, -1, 1, -1, -1}, {-1, -1, 1, -1, -1, + 1, -1, 1}, {-1, -1, 1, -1, -1, 1, 1, -1}, {-1, -1, 1, -1, -1, 1, 1, 1}, + {-1, -1, 1, -1, 1, -1, -1, -1}, {-1, -1, 1, -1, 1, -1, -1, 1}, {-1, -1, + 1, -1, 1, -1, 1, -1}, {-1, -1, 1, -1, 1, -1, 1, 1}, {-1, -1, 1, -1, 1, 1, + -1, -1}, {-1, -1, 1, -1, 1, 1, -1, 1}, {-1, -1, 1, -1, 1, 1, 1, -1}, {-1, + -1, 1, -1, 1, 1, 1, 1}, {-1, -1, 1, 1, -1, -1, -1, -1}, {-1, -1, 1, 1, + -1, -1, -1, 1}, {-1, -1, 1, 1, -1, -1, 1, -1}, {-1, -1, 1, 1, -1, -1, 1, + 1}, {-1, -1, 1, 1, -1, 1, -1, -1}, {-1, -1, 1, 1, -1, 1, -1, 1}, {-1, -1, + 1, 1, -1, 1, 1, -1}, {-1, -1, 1, 1, -1, 1, 1, 1}, {-1, -1, 1, 1, 1, -1, + -1, -1}, {-1, -1, 1, 1, 1, -1, -1, 1}, {-1, -1, 1, 1, 1, -1, 1, -1}, {-1, + -1, 1, 1, 1, -1, 1, 1}, {-1, -1, 1, 1, 1, 1, -1, -1}, {-1, -1, 1, 1, 1, + 1, -1, 1}, {-1, -1, 1, 1, 1, 1, 1, -1}, {-1, -1, 1, 1, 1, 1, 1, 1}, {-1, + 1, -1, -1, -1, -1, -1, -1}, {-1, 1, -1, -1, -1, -1, -1, 1}, {-1, 1, -1, + -1, -1, -1, 1, -1}, {-1, 1, -1, -1, -1, -1, 1, 1}, {-1, 1, -1, -1, -1, 1, + -1, -1}, {-1, 1, -1, -1, -1, 1, -1, 1}, {-1, 1, -1, -1, -1, 1, 1, -1}, + {-1, 1, -1, -1, -1, 1, 1, 1}, {-1, 1, -1, -1, 1, -1, -1, -1}, {-1, 1, -1, + -1, 1, -1, -1, 1}, {-1, 1, -1, -1, 1, -1, 1, -1}, {-1, 1, -1, -1, 1, -1, + 1, 1}, {-1, 1, -1, -1, 1, 1, -1, -1}, {-1, 1, -1, -1, 1, 1, -1, 1}, {-1, + 1, -1, -1, 1, 1, 1, -1}, {-1, 1, -1, -1, 1, 1, 1, 1}, {-1, 1, -1, 1, -1, + -1, -1, -1}, {-1, 1, -1, 1, -1, -1, -1, 1}, {-1, 1, -1, 1, -1, -1, 1, + -1}, {-1, 1, -1, 1, -1, -1, 1, 1}, {-1, 1, -1, 1, -1, 1, -1, -1}, {-1, 1, + -1, 1, -1, 1, -1, 1}, {-1, 1, -1, 1, -1, 1, 1, -1}, {-1, 1, -1, 1, -1, 1, + 1, 1}, {-1, 1, -1, 1, 1, -1, -1, -1}, {-1, 1, -1, 1, 1, -1, -1, 1}, {-1, + 1, -1, 1, 1, -1, 1, -1}, {-1, 1, -1, 1, 1, -1, 1, 1}, {-1, 1, -1, 1, 1, + 1, -1, -1}, {-1, 1, -1, 1, 1, 1, -1, 1}, {-1, 1, -1, 1, 1, 1, 1, -1}, + {-1, 1, -1, 1, 1, 1, 1, 1}, {-1, 1, 1, -1, -1, -1, -1, -1}, {-1, 1, 1, + -1, -1, -1, -1, 1}, {-1, 1, 1, -1, -1, -1, 1, -1}, {-1, 1, 1, -1, -1, -1, + 1, 1}, {-1, 1, 1, -1, -1, 1, -1, -1}, {-1, 1, 1, -1, -1, 1, -1, 1}, {-1, + 1, 1, -1, -1, 1, 1, -1}, {-1, 1, 1, -1, -1, 1, 1, 1}, {-1, 1, 1, -1, 1, + -1, -1, -1}, {-1, 1, 1, -1, 1, -1, -1, 1}, {-1, 1, 1, -1, 1, -1, 1, -1}, + {-1, 1, 1, -1, 1, -1, 1, 1}, {-1, 1, 1, -1, 1, 1, -1, -1}, {-1, 1, 1, -1, + 1, 1, -1, 1}, {-1, 1, 1, -1, 1, 1, 1, -1}, {-1, 1, 1, -1, 1, 1, 1, 1}, + {-1, 1, 1, 1, -1, -1, -1, -1}, {-1, 1, 1, 1, -1, -1, -1, 1}, {-1, 1, 1, + 1, -1, -1, 1, -1}, {-1, 1, 1, 1, -1, -1, 1, 1}, {-1, 1, 1, 1, -1, 1, -1, + -1}, {-1, 1, 1, 1, -1, 1, -1, 1}, {-1, 1, 1, 1, -1, 1, 1, -1}, {-1, 1, 1, + 1, -1, 1, 1, 1}, {-1, 1, 1, 1, 1, -1, -1, -1}, {-1, 1, 1, 1, 1, -1, -1, + 1}, {-1, 1, 1, 1, 1, -1, 1, -1}, {-1, 1, 1, 1, 1, -1, 1, 1}, {-1, 1, 1, + 1, 1, 1, -1, -1}, {-1, 1, 1, 1, 1, 1, -1, 1}, {-1, 1, 1, 1, 1, 1, 1, -1}, + {-1, 1, 1, 1, 1, 1, 1, 1}, {1, -1, -1, -1, -1, -1, -1, -1}, {1, -1, -1, + -1, -1, -1, -1, 1}, {1, -1, -1, -1, -1, -1, 1, -1}, {1, -1, -1, -1, -1, + -1, 1, 1}, {1, -1, -1, -1, -1, 1, -1, -1}, {1, -1, -1, -1, -1, 1, -1, 1}, + {1, -1, -1, -1, -1, 1, 1, -1}, {1, -1, -1, -1, -1, 1, 1, 1}, {1, -1, -1, + -1, 1, -1, -1, -1}, {1, -1, -1, -1, 1, -1, -1, 1}, {1, -1, -1, -1, 1, -1, + 1, -1}, {1, -1, -1, -1, 1, -1, 1, 1}, {1, -1, -1, -1, 1, 1, -1, -1}, {1, + -1, -1, -1, 1, 1, -1, 1}, {1, -1, -1, -1, 1, 1, 1, -1}, {1, -1, -1, -1, + 1, 1, 1, 1}, {1, -1, -1, 1, -1, -1, -1, -1}, {1, -1, -1, 1, -1, -1, -1, + 1}, {1, -1, -1, 1, -1, -1, 1, -1}, {1, -1, -1, 1, -1, -1, 1, 1}, {1, -1, + -1, 1, -1, 1, -1, -1}, {1, -1, -1, 1, -1, 1, -1, 1}, {1, -1, -1, 1, -1, + 1, 1, -1}, {1, -1, -1, 1, -1, 1, 1, 1}, {1, -1, -1, 1, 1, -1, -1, -1}, + {1, -1, -1, 1, 1, -1, -1, 1}, {1, -1, -1, 1, 1, -1, 1, -1}, {1, -1, -1, + 1, 1, -1, 1, 1}, {1, -1, -1, 1, 1, 1, -1, -1}, {1, -1, -1, 1, 1, 1, -1, + 1}, {1, -1, -1, 1, 1, 1, 1, -1}, {1, -1, -1, 1, 1, 1, 1, 1}, {1, -1, 1, + -1, -1, -1, -1, -1}, {1, -1, 1, -1, -1, -1, -1, 1}, {1, -1, 1, -1, -1, + -1, 1, -1}, {1, -1, 1, -1, -1, -1, 1, 1}, {1, -1, 1, -1, -1, 1, -1, -1}, + {1, -1, 1, -1, -1, 1, -1, 1}, {1, -1, 1, -1, -1, 1, 1, -1}, {1, -1, 1, + -1, -1, 1, 1, 1}, {1, -1, 1, -1, 1, -1, -1, -1}, {1, -1, 1, -1, 1, -1, + -1, 1}, {1, -1, 1, -1, 1, -1, 1, -1}, {1, -1, 1, -1, 1, -1, 1, 1}, {1, + -1, 1, -1, 1, 1, -1, -1}, {1, -1, 1, -1, 1, 1, -1, 1}, {1, -1, 1, -1, 1, + 1, 1, -1}, {1, -1, 1, -1, 1, 1, 1, 1}, {1, -1, 1, 1, -1, -1, -1, -1}, {1, + -1, 1, 1, -1, -1, -1, 1}, {1, -1, 1, 1, -1, -1, 1, -1}, {1, -1, 1, 1, -1, + -1, 1, 1}, {1, -1, 1, 1, -1, 1, -1, -1}, {1, -1, 1, 1, -1, 1, -1, 1}, {1, + -1, 1, 1, -1, 1, 1, -1}, {1, -1, 1, 1, -1, 1, 1, 1}, {1, -1, 1, 1, 1, -1, + -1, -1}, {1, -1, 1, 1, 1, -1, -1, 1}, {1, -1, 1, 1, 1, -1, 1, -1}, {1, + -1, 1, 1, 1, -1, 1, 1}, {1, -1, 1, 1, 1, 1, -1, -1}, {1, -1, 1, 1, 1, 1, + -1, 1}, {1, -1, 1, 1, 1, 1, 1, -1}, {1, -1, 1, 1, 1, 1, 1, 1}, {1, 1, -1, + -1, -1, -1, -1, -1}, {1, 1, -1, -1, -1, -1, -1, 1}, {1, 1, -1, -1, -1, + -1, 1, -1}, {1, 1, -1, -1, -1, -1, 1, 1}, {1, 1, -1, -1, -1, 1, -1, -1}, + {1, 1, -1, -1, -1, 1, -1, 1}, {1, 1, -1, -1, -1, 1, 1, -1}, {1, 1, -1, + -1, -1, 1, 1, 1}, {1, 1, -1, -1, 1, -1, -1, -1}, {1, 1, -1, -1, 1, -1, + -1, 1}, {1, 1, -1, -1, 1, -1, 1, -1}, {1, 1, -1, -1, 1, -1, 1, 1}, {1, 1, + -1, -1, 1, 1, -1, -1}, {1, 1, -1, -1, 1, 1, -1, 1}, {1, 1, -1, -1, 1, 1, + 1, -1}, {1, 1, -1, -1, 1, 1, 1, 1}, {1, 1, -1, 1, -1, -1, -1, -1}, {1, 1, + -1, 1, -1, -1, -1, 1}, {1, 1, -1, 1, -1, -1, 1, -1}, {1, 1, -1, 1, -1, + -1, 1, 1}, {1, 1, -1, 1, -1, 1, -1, -1}, {1, 1, -1, 1, -1, 1, -1, 1}, {1, + 1, -1, 1, -1, 1, 1, -1}, {1, 1, -1, 1, -1, 1, 1, 1}, {1, 1, -1, 1, 1, -1, + -1, -1}, {1, 1, -1, 1, 1, -1, -1, 1}, {1, 1, -1, 1, 1, -1, 1, -1}, {1, 1, + -1, 1, 1, -1, 1, 1}, {1, 1, -1, 1, 1, 1, -1, -1}, {1, 1, -1, 1, 1, 1, -1, + 1}, {1, 1, -1, 1, 1, 1, 1, -1}, {1, 1, -1, 1, 1, 1, 1, 1}, {1, 1, 1, -1, + -1, -1, -1, -1}, {1, 1, 1, -1, -1, -1, -1, 1}, {1, 1, 1, -1, -1, -1, 1, + -1}, {1, 1, 1, -1, -1, -1, 1, 1}, {1, 1, 1, -1, -1, 1, -1, -1}, {1, 1, 1, + -1, -1, 1, -1, 1}, {1, 1, 1, -1, -1, 1, 1, -1}, {1, 1, 1, -1, -1, 1, 1, + 1}, {1, 1, 1, -1, 1, -1, -1, -1}, {1, 1, 1, -1, 1, -1, -1, 1}, {1, 1, 1, + -1, 1, -1, 1, -1}, {1, 1, 1, -1, 1, -1, 1, 1}, {1, 1, 1, -1, 1, 1, -1, + -1}, {1, 1, 1, -1, 1, 1, -1, 1}, {1, 1, 1, -1, 1, 1, 1, -1}, {1, 1, 1, + -1, 1, 1, 1, 1}, {1, 1, 1, 1, -1, -1, -1, -1}, {1, 1, 1, 1, -1, -1, -1, + 1}, {1, 1, 1, 1, -1, -1, 1, -1}, {1, 1, 1, 1, -1, -1, 1, 1}, {1, 1, 1, 1, + -1, 1, -1, -1}, {1, 1, 1, 1, -1, 1, -1, 1}, {1, 1, 1, 1, -1, 1, 1, -1}, + {1, 1, 1, 1, -1, 1, 1, 1}, {1, 1, 1, 1, 1, -1, -1, -1}, {1, 1, 1, 1, 1, + -1, -1, 1}, {1, 1, 1, 1, 1, -1, 1, -1}, {1, 1, 1, 1, 1, -1, 1, 1}, {1, 1, + 1, 1, 1, 1, -1, -1}, {1, 1, 1, 1, 1, 1, -1, 1}, {1, 1, 1, 1, 1, 1, 1, + -1}, {1, 1, 1, 1, 1, 1, 1, 1}}; + // Denominators: spins, colors and identical particles + const int denominators[nprocesses] = {96}; + + ntry = ntry + 1; + + // Reset the matrix elements + for(int i = 0; i < nprocesses; i++ ) + { + matrix_element[i] = 0.; + } + // Define permutation + int perm[nexternal]; + for(int i = 0; i < nexternal; i++ ) + { + perm[i] = i; + } + + if (sum_hel == 0 || ntry < 10) + { + // Calculate the matrix element for all helicities + for(int ihel = 0; ihel < ncomb; ihel++ ) + { + if (goodhel[ihel] || ntry < 2) + { + calculate_wavefunctions(perm, helicities[ihel]); + t[0] = matrix_1_epem_uuxgggg(); + + double tsum = 0; + for(int iproc = 0; iproc < nprocesses; iproc++ ) + { + matrix_element[iproc] += t[iproc]; + tsum += t[iproc]; + } + // Store which helicities give non-zero result + if (tsum != 0. && !goodhel[ihel]) + { + goodhel[ihel] = true; + ngood++; + igood[ngood] = ihel; + } + } + } + jhel = 0; + sum_hel = min(sum_hel, ngood); + } + else + { + // Only use the "good" helicities + for(int j = 0; j < sum_hel; j++ ) + { + jhel++; + if (jhel >= ngood) + jhel = 0; + double hwgt = double(ngood)/double(sum_hel); + int ihel = igood[jhel]; + calculate_wavefunctions(perm, helicities[ihel]); + t[0] = matrix_1_epem_uuxgggg(); + + for(int iproc = 0; iproc < nprocesses; iproc++ ) + { + matrix_element[iproc] += t[iproc] * hwgt; + } + } + } + + for (int i = 0; i < nprocesses; i++ ) + matrix_element[i] /= denominators[i]; + + + +} + + +//-------------------------------------------------------------------------- +// Evaluate |M|^2 for each subprocess + +void eeuugggg::calculate_wavefunctions(const int perm[], const int hel[]) +{ + + // Calculate all wavefunctions + oxxxxx(p[perm[0]], mME[0], hel[0], -1, w[0]); + ixxxxx(p[perm[1]], mME[1], hel[1], +1, w[1]); + oxxxxx(p[perm[2]], mME[2], hel[2], +1, w[2]); + ixxxxx(p[perm[3]], mME[3], hel[3], -1, w[3]); + vxxxxx(p[perm[4]], mME[4], hel[4], +1, w[4]); + vxxxxx(p[perm[5]], mME[5], hel[5], +1, w[5]); + vxxxxx(p[perm[6]], mME[6], hel[6], +1, w[6]); + vxxxxx(p[perm[7]], mME[7], hel[7], +1, w[7]); + FFV1P0_3(w[1], w[0], pars->GC_3, pars->ZERO, pars->ZERO, w[8]); + FFV1_1(w[2], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[9]); + FFV1_2(w[3], w[8], pars->GC_2, pars->ZERO, pars->ZERO, w[10]); + FFV1_1(w[9], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[11]); + FFV1_2(w[10], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[12]); + FFV1_2(w[10], w[7], pars->GC_11, pars->ZERO, pars->ZERO, w[13]); + FFV1_1(w[9], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[14]); + FFV1_2(w[10], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[15]); + FFV1_1(w[9], w[7], pars->GC_11, pars->ZERO, pars->ZERO, w[16]); + FFV2_4_3(w[1], w[0], pars->GC_50, pars->GC_59, pars->mdl_MZ, pars->mdl_WZ, + w[17]); + FFV2_5_2(w[3], w[17], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, + w[18]); + FFV1_2(w[18], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[19]); + FFV1_2(w[18], w[7], pars->GC_11, pars->ZERO, pars->ZERO, w[20]); + FFV1_2(w[18], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[21]); + FFV1_2(w[3], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[22]); + FFV1_1(w[9], w[8], pars->GC_2, pars->ZERO, pars->ZERO, w[23]); + FFV1_2(w[22], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[24]); + FFV1_2(w[22], w[7], pars->GC_11, pars->ZERO, pars->ZERO, w[25]); + FFV1_2(w[22], w[8], pars->GC_2, pars->ZERO, pars->ZERO, w[26]); + FFV2_5_1(w[9], w[17], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, + w[27]); + FFV2_5_2(w[22], w[17], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, + w[28]); + VVV1P0_1(w[6], w[7], pars->GC_10, pars->ZERO, pars->ZERO, w[29]); + FFV1_2(w[3], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[30]); + FFV1_2(w[30], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[31]); + FFV1_2(w[30], w[7], pars->GC_11, pars->ZERO, pars->ZERO, w[32]); + FFV1_2(w[30], w[8], pars->GC_2, pars->ZERO, pars->ZERO, w[33]); + FFV2_5_2(w[30], w[17], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, + w[34]); + VVV1P0_1(w[5], w[7], pars->GC_10, pars->ZERO, pars->ZERO, w[35]); + FFV1_2(w[3], w[7], pars->GC_11, pars->ZERO, pars->ZERO, w[36]); + FFV1_2(w[36], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[37]); + FFV1_2(w[36], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[38]); + FFV1_2(w[36], w[8], pars->GC_2, pars->ZERO, pars->ZERO, w[39]); + FFV2_5_2(w[36], w[17], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, + w[40]); + VVV1P0_1(w[5], w[6], pars->GC_10, pars->ZERO, pars->ZERO, w[41]); + FFV1_2(w[3], w[41], pars->GC_11, pars->ZERO, pars->ZERO, w[42]); + VVV1P0_1(w[41], w[7], pars->GC_10, pars->ZERO, pars->ZERO, w[43]); + FFV1_1(w[9], w[41], pars->GC_11, pars->ZERO, pars->ZERO, w[44]); + FFV1_2(w[3], w[35], pars->GC_11, pars->ZERO, pars->ZERO, w[45]); + VVV1P0_1(w[35], w[6], pars->GC_10, pars->ZERO, pars->ZERO, w[46]); + FFV1_1(w[9], w[35], pars->GC_11, pars->ZERO, pars->ZERO, w[47]); + FFV1_2(w[3], w[29], pars->GC_11, pars->ZERO, pars->ZERO, w[48]); + VVV1P0_1(w[5], w[29], pars->GC_10, pars->ZERO, pars->ZERO, w[49]); + FFV1_1(w[9], w[29], pars->GC_11, pars->ZERO, pars->ZERO, w[50]); + VVVV1P0_1(w[5], w[6], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[51]); + VVVV3P0_1(w[5], w[6], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[52]); + VVVV4P0_1(w[5], w[6], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[53]); + FFV1_1(w[2], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[54]); + FFV1_1(w[54], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[55]); + FFV1_1(w[54], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[56]); + FFV1_2(w[10], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[57]); + FFV1_1(w[54], w[7], pars->GC_11, pars->ZERO, pars->ZERO, w[58]); + FFV1_2(w[18], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[59]); + FFV1_2(w[3], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[60]); + FFV1_1(w[54], w[8], pars->GC_2, pars->ZERO, pars->ZERO, w[61]); + FFV1_2(w[60], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[62]); + FFV1_2(w[60], w[7], pars->GC_11, pars->ZERO, pars->ZERO, w[63]); + FFV1_2(w[60], w[8], pars->GC_2, pars->ZERO, pars->ZERO, w[64]); + FFV2_5_1(w[54], w[17], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, + w[65]); + FFV2_5_2(w[60], w[17], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, + w[66]); + FFV1_2(w[30], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[67]); + VVV1P0_1(w[4], w[7], pars->GC_10, pars->ZERO, pars->ZERO, w[68]); + FFV1_2(w[36], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[69]); + VVV1P0_1(w[4], w[6], pars->GC_10, pars->ZERO, pars->ZERO, w[70]); + FFV1_2(w[3], w[70], pars->GC_11, pars->ZERO, pars->ZERO, w[71]); + VVV1P0_1(w[70], w[7], pars->GC_10, pars->ZERO, pars->ZERO, w[72]); + FFV1_1(w[54], w[70], pars->GC_11, pars->ZERO, pars->ZERO, w[73]); + FFV1_2(w[3], w[68], pars->GC_11, pars->ZERO, pars->ZERO, w[74]); + VVV1P0_1(w[68], w[6], pars->GC_10, pars->ZERO, pars->ZERO, w[75]); + FFV1_1(w[54], w[68], pars->GC_11, pars->ZERO, pars->ZERO, w[76]); + VVV1P0_1(w[4], w[29], pars->GC_10, pars->ZERO, pars->ZERO, w[77]); + FFV1_1(w[54], w[29], pars->GC_11, pars->ZERO, pars->ZERO, w[78]); + VVVV1P0_1(w[4], w[6], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[79]); + VVVV3P0_1(w[4], w[6], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[80]); + VVVV4P0_1(w[4], w[6], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[81]); + FFV1_1(w[2], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[82]); + FFV1_1(w[82], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[83]); + FFV1_1(w[82], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[84]); + FFV1_1(w[82], w[7], pars->GC_11, pars->ZERO, pars->ZERO, w[85]); + FFV1_1(w[82], w[8], pars->GC_2, pars->ZERO, pars->ZERO, w[86]); + FFV1_2(w[60], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[87]); + FFV2_5_1(w[82], w[17], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, + w[88]); + FFV1_2(w[22], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[89]); + VVV1P0_1(w[4], w[5], pars->GC_10, pars->ZERO, pars->ZERO, w[90]); + FFV1_2(w[3], w[90], pars->GC_11, pars->ZERO, pars->ZERO, w[91]); + VVV1P0_1(w[90], w[7], pars->GC_10, pars->ZERO, pars->ZERO, w[92]); + FFV1_1(w[82], w[90], pars->GC_11, pars->ZERO, pars->ZERO, w[93]); + VVV1P0_1(w[68], w[5], pars->GC_10, pars->ZERO, pars->ZERO, w[94]); + FFV1_1(w[82], w[68], pars->GC_11, pars->ZERO, pars->ZERO, w[95]); + VVV1P0_1(w[4], w[35], pars->GC_10, pars->ZERO, pars->ZERO, w[96]); + FFV1_1(w[82], w[35], pars->GC_11, pars->ZERO, pars->ZERO, w[97]); + VVVV1P0_1(w[4], w[5], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[98]); + VVVV3P0_1(w[4], w[5], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[99]); + VVVV4P0_1(w[4], w[5], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[100]); + FFV1_1(w[2], w[7], pars->GC_11, pars->ZERO, pars->ZERO, w[101]); + FFV1_1(w[101], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[102]); + FFV1_1(w[101], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[103]); + FFV1_1(w[101], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[104]); + FFV1_1(w[101], w[8], pars->GC_2, pars->ZERO, pars->ZERO, w[105]); + FFV2_5_1(w[101], w[17], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, + w[106]); + VVV1P0_1(w[90], w[6], pars->GC_10, pars->ZERO, pars->ZERO, w[107]); + FFV1_1(w[101], w[90], pars->GC_11, pars->ZERO, pars->ZERO, w[108]); + VVV1P0_1(w[70], w[5], pars->GC_10, pars->ZERO, pars->ZERO, w[109]); + FFV1_1(w[101], w[70], pars->GC_11, pars->ZERO, pars->ZERO, w[110]); + VVV1P0_1(w[4], w[41], pars->GC_10, pars->ZERO, pars->ZERO, w[111]); + FFV1_1(w[101], w[41], pars->GC_11, pars->ZERO, pars->ZERO, w[112]); + VVVV1P0_1(w[4], w[5], w[6], pars->GC_12, pars->ZERO, pars->ZERO, w[113]); + VVVV3P0_1(w[4], w[5], w[6], pars->GC_12, pars->ZERO, pars->ZERO, w[114]); + VVVV4P0_1(w[4], w[5], w[6], pars->GC_12, pars->ZERO, pars->ZERO, w[115]); + FFV1_1(w[2], w[8], pars->GC_2, pars->ZERO, pars->ZERO, w[116]); + FFV1_1(w[116], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[117]); + FFV1_1(w[116], w[7], pars->GC_11, pars->ZERO, pars->ZERO, w[118]); + FFV1_1(w[116], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[119]); + FFV2_5_1(w[2], w[17], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, + w[120]); + FFV1_1(w[120], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[121]); + FFV1_1(w[120], w[7], pars->GC_11, pars->ZERO, pars->ZERO, w[122]); + FFV1_1(w[120], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[123]); + FFV1_2(w[60], w[41], pars->GC_11, pars->ZERO, pars->ZERO, w[124]); + FFV1_1(w[2], w[41], pars->GC_11, pars->ZERO, pars->ZERO, w[125]); + FFV1_2(w[60], w[35], pars->GC_11, pars->ZERO, pars->ZERO, w[126]); + FFV1_1(w[2], w[35], pars->GC_11, pars->ZERO, pars->ZERO, w[127]); + FFV1_2(w[60], w[29], pars->GC_11, pars->ZERO, pars->ZERO, w[128]); + FFV1_1(w[2], w[29], pars->GC_11, pars->ZERO, pars->ZERO, w[129]); + FFV1_1(w[116], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[130]); + FFV1_1(w[120], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[131]); + FFV1_2(w[22], w[70], pars->GC_11, pars->ZERO, pars->ZERO, w[132]); + FFV1_1(w[2], w[70], pars->GC_11, pars->ZERO, pars->ZERO, w[133]); + FFV1_2(w[22], w[68], pars->GC_11, pars->ZERO, pars->ZERO, w[134]); + FFV1_1(w[2], w[68], pars->GC_11, pars->ZERO, pars->ZERO, w[135]); + FFV1_2(w[22], w[29], pars->GC_11, pars->ZERO, pars->ZERO, w[136]); + FFV1_2(w[30], w[90], pars->GC_11, pars->ZERO, pars->ZERO, w[137]); + FFV1_1(w[2], w[90], pars->GC_11, pars->ZERO, pars->ZERO, w[138]); + FFV1_2(w[30], w[68], pars->GC_11, pars->ZERO, pars->ZERO, w[139]); + FFV1_2(w[30], w[35], pars->GC_11, pars->ZERO, pars->ZERO, w[140]); + FFV1_2(w[36], w[90], pars->GC_11, pars->ZERO, pars->ZERO, w[141]); + FFV1_2(w[36], w[70], pars->GC_11, pars->ZERO, pars->ZERO, w[142]); + FFV1_2(w[36], w[41], pars->GC_11, pars->ZERO, pars->ZERO, w[143]); + FFV1P0_3(w[3], w[116], pars->GC_11, pars->ZERO, pars->ZERO, w[144]); + VVVV1P0_1(w[90], w[6], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[145]); + VVVV3P0_1(w[90], w[6], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[146]); + VVVV4P0_1(w[90], w[6], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[147]); + FFV1P0_3(w[10], w[2], pars->GC_11, pars->ZERO, pars->ZERO, w[148]); + FFV1P0_3(w[3], w[120], pars->GC_11, pars->ZERO, pars->ZERO, w[149]); + FFV1P0_3(w[18], w[2], pars->GC_11, pars->ZERO, pars->ZERO, w[150]); + VVV1P0_1(w[90], w[29], pars->GC_10, pars->ZERO, pars->ZERO, w[151]); + VVVV1P0_1(w[70], w[5], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[152]); + VVVV3P0_1(w[70], w[5], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[153]); + VVVV4P0_1(w[70], w[5], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[154]); + VVV1P0_1(w[70], w[35], pars->GC_10, pars->ZERO, pars->ZERO, w[155]); + VVVV1P0_1(w[68], w[5], w[6], pars->GC_12, pars->ZERO, pars->ZERO, w[156]); + VVVV3P0_1(w[68], w[5], w[6], pars->GC_12, pars->ZERO, pars->ZERO, w[157]); + VVVV4P0_1(w[68], w[5], w[6], pars->GC_12, pars->ZERO, pars->ZERO, w[158]); + VVV1P0_1(w[68], w[41], pars->GC_10, pars->ZERO, pars->ZERO, w[159]); + VVVV1P0_1(w[4], w[41], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[160]); + VVVV3P0_1(w[4], w[41], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[161]); + VVVV4P0_1(w[4], w[41], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[162]); + VVVV1P0_1(w[4], w[35], w[6], pars->GC_12, pars->ZERO, pars->ZERO, w[163]); + VVVV3P0_1(w[4], w[35], w[6], pars->GC_12, pars->ZERO, pars->ZERO, w[164]); + VVVV4P0_1(w[4], w[35], w[6], pars->GC_12, pars->ZERO, pars->ZERO, w[165]); + VVVV1P0_1(w[4], w[5], w[29], pars->GC_12, pars->ZERO, pars->ZERO, w[166]); + VVVV3P0_1(w[4], w[5], w[29], pars->GC_12, pars->ZERO, pars->ZERO, w[167]); + VVVV4P0_1(w[4], w[5], w[29], pars->GC_12, pars->ZERO, pars->ZERO, w[168]); + FFV1_2(w[3], w[113], pars->GC_11, pars->ZERO, pars->ZERO, w[169]); + FFV1_2(w[3], w[114], pars->GC_11, pars->ZERO, pars->ZERO, w[170]); + FFV1_2(w[3], w[115], pars->GC_11, pars->ZERO, pars->ZERO, w[171]); + VVV1P0_1(w[113], w[7], pars->GC_10, pars->ZERO, pars->ZERO, w[172]); + VVV1P0_1(w[114], w[7], pars->GC_10, pars->ZERO, pars->ZERO, w[173]); + VVV1P0_1(w[115], w[7], pars->GC_10, pars->ZERO, pars->ZERO, w[174]); + FFV1_1(w[2], w[113], pars->GC_11, pars->ZERO, pars->ZERO, w[175]); + FFV1_1(w[2], w[114], pars->GC_11, pars->ZERO, pars->ZERO, w[176]); + FFV1_1(w[2], w[115], pars->GC_11, pars->ZERO, pars->ZERO, w[177]); + FFV1_2(w[3], w[98], pars->GC_11, pars->ZERO, pars->ZERO, w[178]); + FFV1_2(w[3], w[99], pars->GC_11, pars->ZERO, pars->ZERO, w[179]); + FFV1_2(w[3], w[100], pars->GC_11, pars->ZERO, pars->ZERO, w[180]); + VVV1P0_1(w[98], w[6], pars->GC_10, pars->ZERO, pars->ZERO, w[181]); + VVV1P0_1(w[99], w[6], pars->GC_10, pars->ZERO, pars->ZERO, w[182]); + VVV1P0_1(w[100], w[6], pars->GC_10, pars->ZERO, pars->ZERO, w[183]); + FFV1_1(w[2], w[98], pars->GC_11, pars->ZERO, pars->ZERO, w[184]); + FFV1_1(w[2], w[99], pars->GC_11, pars->ZERO, pars->ZERO, w[185]); + FFV1_1(w[2], w[100], pars->GC_11, pars->ZERO, pars->ZERO, w[186]); + FFV1_2(w[3], w[79], pars->GC_11, pars->ZERO, pars->ZERO, w[187]); + FFV1_2(w[3], w[80], pars->GC_11, pars->ZERO, pars->ZERO, w[188]); + FFV1_2(w[3], w[81], pars->GC_11, pars->ZERO, pars->ZERO, w[189]); + VVV1P0_1(w[79], w[5], pars->GC_10, pars->ZERO, pars->ZERO, w[190]); + VVV1P0_1(w[80], w[5], pars->GC_10, pars->ZERO, pars->ZERO, w[191]); + VVV1P0_1(w[81], w[5], pars->GC_10, pars->ZERO, pars->ZERO, w[192]); + FFV1_1(w[2], w[79], pars->GC_11, pars->ZERO, pars->ZERO, w[193]); + FFV1_1(w[2], w[80], pars->GC_11, pars->ZERO, pars->ZERO, w[194]); + FFV1_1(w[2], w[81], pars->GC_11, pars->ZERO, pars->ZERO, w[195]); + FFV1_2(w[3], w[51], pars->GC_11, pars->ZERO, pars->ZERO, w[196]); + FFV1_2(w[3], w[52], pars->GC_11, pars->ZERO, pars->ZERO, w[197]); + FFV1_2(w[3], w[53], pars->GC_11, pars->ZERO, pars->ZERO, w[198]); + VVV1P0_1(w[4], w[51], pars->GC_10, pars->ZERO, pars->ZERO, w[199]); + VVV1P0_1(w[4], w[52], pars->GC_10, pars->ZERO, pars->ZERO, w[200]); + VVV1P0_1(w[4], w[53], pars->GC_10, pars->ZERO, pars->ZERO, w[201]); + FFV1_1(w[2], w[51], pars->GC_11, pars->ZERO, pars->ZERO, w[202]); + FFV1_1(w[2], w[52], pars->GC_11, pars->ZERO, pars->ZERO, w[203]); + FFV1_1(w[2], w[53], pars->GC_11, pars->ZERO, pars->ZERO, w[204]); + + // Calculate all amplitudes + // Amplitude(s) for diagram number 0 + FFV1_0(w[12], w[11], w[7], pars->GC_11, amp[0]); + FFV1_0(w[13], w[11], w[6], pars->GC_11, amp[1]); + FFV1_0(w[15], w[14], w[7], pars->GC_11, amp[2]); + FFV1_0(w[13], w[14], w[5], pars->GC_11, amp[3]); + FFV1_0(w[15], w[16], w[6], pars->GC_11, amp[4]); + FFV1_0(w[12], w[16], w[5], pars->GC_11, amp[5]); + FFV1_0(w[19], w[11], w[7], pars->GC_11, amp[6]); + FFV1_0(w[20], w[11], w[6], pars->GC_11, amp[7]); + FFV1_0(w[21], w[14], w[7], pars->GC_11, amp[8]); + FFV1_0(w[20], w[14], w[5], pars->GC_11, amp[9]); + FFV1_0(w[21], w[16], w[6], pars->GC_11, amp[10]); + FFV1_0(w[19], w[16], w[5], pars->GC_11, amp[11]); + FFV1_0(w[24], w[23], w[7], pars->GC_11, amp[12]); + FFV1_0(w[25], w[23], w[6], pars->GC_11, amp[13]); + FFV1_0(w[26], w[14], w[7], pars->GC_11, amp[14]); + FFV1_0(w[26], w[16], w[6], pars->GC_11, amp[15]); + FFV1_0(w[25], w[14], w[8], pars->GC_2, amp[16]); + FFV1_0(w[24], w[16], w[8], pars->GC_2, amp[17]); + FFV1_0(w[24], w[27], w[7], pars->GC_11, amp[18]); + FFV1_0(w[25], w[27], w[6], pars->GC_11, amp[19]); + FFV1_0(w[28], w[14], w[7], pars->GC_11, amp[20]); + FFV1_0(w[28], w[16], w[6], pars->GC_11, amp[21]); + FFV2_5_0(w[25], w[14], w[17], pars->GC_51, pars->GC_58, amp[22]); + FFV2_5_0(w[24], w[16], w[17], pars->GC_51, pars->GC_58, amp[23]); + FFV1_0(w[22], w[23], w[29], pars->GC_11, amp[24]); + FFV1_0(w[26], w[9], w[29], pars->GC_11, amp[25]); + FFV1_0(w[22], w[27], w[29], pars->GC_11, amp[26]); + FFV1_0(w[28], w[9], w[29], pars->GC_11, amp[27]); + FFV1_0(w[31], w[23], w[7], pars->GC_11, amp[28]); + FFV1_0(w[32], w[23], w[5], pars->GC_11, amp[29]); + FFV1_0(w[33], w[11], w[7], pars->GC_11, amp[30]); + FFV1_0(w[33], w[16], w[5], pars->GC_11, amp[31]); + FFV1_0(w[32], w[11], w[8], pars->GC_2, amp[32]); + FFV1_0(w[31], w[16], w[8], pars->GC_2, amp[33]); + FFV1_0(w[31], w[27], w[7], pars->GC_11, amp[34]); + FFV1_0(w[32], w[27], w[5], pars->GC_11, amp[35]); + FFV1_0(w[34], w[11], w[7], pars->GC_11, amp[36]); + FFV1_0(w[34], w[16], w[5], pars->GC_11, amp[37]); + FFV2_5_0(w[32], w[11], w[17], pars->GC_51, pars->GC_58, amp[38]); + FFV2_5_0(w[31], w[16], w[17], pars->GC_51, pars->GC_58, amp[39]); + FFV1_0(w[30], w[23], w[35], pars->GC_11, amp[40]); + FFV1_0(w[33], w[9], w[35], pars->GC_11, amp[41]); + FFV1_0(w[30], w[27], w[35], pars->GC_11, amp[42]); + FFV1_0(w[34], w[9], w[35], pars->GC_11, amp[43]); + FFV1_0(w[37], w[23], w[6], pars->GC_11, amp[44]); + FFV1_0(w[38], w[23], w[5], pars->GC_11, amp[45]); + FFV1_0(w[39], w[11], w[6], pars->GC_11, amp[46]); + FFV1_0(w[39], w[14], w[5], pars->GC_11, amp[47]); + FFV1_0(w[38], w[11], w[8], pars->GC_2, amp[48]); + FFV1_0(w[37], w[14], w[8], pars->GC_2, amp[49]); + FFV1_0(w[37], w[27], w[6], pars->GC_11, amp[50]); + FFV1_0(w[38], w[27], w[5], pars->GC_11, amp[51]); + FFV1_0(w[40], w[11], w[6], pars->GC_11, amp[52]); + FFV1_0(w[40], w[14], w[5], pars->GC_11, amp[53]); + FFV2_5_0(w[38], w[11], w[17], pars->GC_51, pars->GC_58, amp[54]); + FFV2_5_0(w[37], w[14], w[17], pars->GC_51, pars->GC_58, amp[55]); + FFV1_0(w[36], w[23], w[41], pars->GC_11, amp[56]); + FFV1_0(w[39], w[9], w[41], pars->GC_11, amp[57]); + FFV1_0(w[36], w[27], w[41], pars->GC_11, amp[58]); + FFV1_0(w[40], w[9], w[41], pars->GC_11, amp[59]); + FFV1_0(w[42], w[23], w[7], pars->GC_11, amp[60]); + FFV1_0(w[3], w[23], w[43], pars->GC_11, amp[61]); + FFV1_0(w[10], w[44], w[7], pars->GC_11, amp[62]); + FFV1_0(w[10], w[16], w[41], pars->GC_11, amp[63]); + FFV1_0(w[10], w[9], w[43], pars->GC_11, amp[64]); + FFV1_0(w[42], w[16], w[8], pars->GC_2, amp[65]); + FFV1_0(w[42], w[27], w[7], pars->GC_11, amp[66]); + FFV1_0(w[3], w[27], w[43], pars->GC_11, amp[67]); + FFV1_0(w[18], w[44], w[7], pars->GC_11, amp[68]); + FFV1_0(w[18], w[16], w[41], pars->GC_11, amp[69]); + FFV1_0(w[18], w[9], w[43], pars->GC_11, amp[70]); + FFV2_5_0(w[42], w[16], w[17], pars->GC_51, pars->GC_58, amp[71]); + FFV1_0(w[45], w[23], w[6], pars->GC_11, amp[72]); + FFV1_0(w[3], w[23], w[46], pars->GC_11, amp[73]); + FFV1_0(w[10], w[47], w[6], pars->GC_11, amp[74]); + FFV1_0(w[10], w[14], w[35], pars->GC_11, amp[75]); + FFV1_0(w[10], w[9], w[46], pars->GC_11, amp[76]); + FFV1_0(w[45], w[14], w[8], pars->GC_2, amp[77]); + FFV1_0(w[45], w[27], w[6], pars->GC_11, amp[78]); + FFV1_0(w[3], w[27], w[46], pars->GC_11, amp[79]); + FFV1_0(w[18], w[47], w[6], pars->GC_11, amp[80]); + FFV1_0(w[18], w[14], w[35], pars->GC_11, amp[81]); + FFV1_0(w[18], w[9], w[46], pars->GC_11, amp[82]); + FFV2_5_0(w[45], w[14], w[17], pars->GC_51, pars->GC_58, amp[83]); + FFV1_0(w[48], w[23], w[5], pars->GC_11, amp[84]); + FFV1_0(w[3], w[23], w[49], pars->GC_11, amp[85]); + FFV1_0(w[10], w[11], w[29], pars->GC_11, amp[86]); + FFV1_0(w[10], w[50], w[5], pars->GC_11, amp[87]); + FFV1_0(w[10], w[9], w[49], pars->GC_11, amp[88]); + FFV1_0(w[48], w[11], w[8], pars->GC_2, amp[89]); + FFV1_0(w[48], w[27], w[5], pars->GC_11, amp[90]); + FFV1_0(w[3], w[27], w[49], pars->GC_11, amp[91]); + FFV1_0(w[18], w[11], w[29], pars->GC_11, amp[92]); + FFV1_0(w[18], w[50], w[5], pars->GC_11, amp[93]); + FFV1_0(w[18], w[9], w[49], pars->GC_11, amp[94]); + FFV2_5_0(w[48], w[11], w[17], pars->GC_51, pars->GC_58, amp[95]); + FFV1_0(w[3], w[23], w[51], pars->GC_11, amp[96]); + FFV1_0(w[3], w[23], w[52], pars->GC_11, amp[97]); + FFV1_0(w[3], w[23], w[53], pars->GC_11, amp[98]); + FFV1_0(w[10], w[9], w[51], pars->GC_11, amp[99]); + FFV1_0(w[10], w[9], w[52], pars->GC_11, amp[100]); + FFV1_0(w[10], w[9], w[53], pars->GC_11, amp[101]); + FFV1_0(w[3], w[27], w[51], pars->GC_11, amp[102]); + FFV1_0(w[3], w[27], w[52], pars->GC_11, amp[103]); + FFV1_0(w[3], w[27], w[53], pars->GC_11, amp[104]); + FFV1_0(w[18], w[9], w[51], pars->GC_11, amp[105]); + FFV1_0(w[18], w[9], w[52], pars->GC_11, amp[106]); + FFV1_0(w[18], w[9], w[53], pars->GC_11, amp[107]); + FFV1_0(w[12], w[55], w[7], pars->GC_11, amp[108]); + FFV1_0(w[13], w[55], w[6], pars->GC_11, amp[109]); + FFV1_0(w[57], w[56], w[7], pars->GC_11, amp[110]); + FFV1_0(w[13], w[56], w[4], pars->GC_11, amp[111]); + FFV1_0(w[57], w[58], w[6], pars->GC_11, amp[112]); + FFV1_0(w[12], w[58], w[4], pars->GC_11, amp[113]); + FFV1_0(w[19], w[55], w[7], pars->GC_11, amp[114]); + FFV1_0(w[20], w[55], w[6], pars->GC_11, amp[115]); + FFV1_0(w[59], w[56], w[7], pars->GC_11, amp[116]); + FFV1_0(w[20], w[56], w[4], pars->GC_11, amp[117]); + FFV1_0(w[59], w[58], w[6], pars->GC_11, amp[118]); + FFV1_0(w[19], w[58], w[4], pars->GC_11, amp[119]); + FFV1_0(w[62], w[61], w[7], pars->GC_11, amp[120]); + FFV1_0(w[63], w[61], w[6], pars->GC_11, amp[121]); + FFV1_0(w[64], w[56], w[7], pars->GC_11, amp[122]); + FFV1_0(w[64], w[58], w[6], pars->GC_11, amp[123]); + FFV1_0(w[63], w[56], w[8], pars->GC_2, amp[124]); + FFV1_0(w[62], w[58], w[8], pars->GC_2, amp[125]); + FFV1_0(w[62], w[65], w[7], pars->GC_11, amp[126]); + FFV1_0(w[63], w[65], w[6], pars->GC_11, amp[127]); + FFV1_0(w[66], w[56], w[7], pars->GC_11, amp[128]); + FFV1_0(w[66], w[58], w[6], pars->GC_11, amp[129]); + FFV2_5_0(w[63], w[56], w[17], pars->GC_51, pars->GC_58, amp[130]); + FFV2_5_0(w[62], w[58], w[17], pars->GC_51, pars->GC_58, amp[131]); + FFV1_0(w[60], w[61], w[29], pars->GC_11, amp[132]); + FFV1_0(w[64], w[54], w[29], pars->GC_11, amp[133]); + FFV1_0(w[60], w[65], w[29], pars->GC_11, amp[134]); + FFV1_0(w[66], w[54], w[29], pars->GC_11, amp[135]); + FFV1_0(w[67], w[61], w[7], pars->GC_11, amp[136]); + FFV1_0(w[32], w[61], w[4], pars->GC_11, amp[137]); + FFV1_0(w[33], w[55], w[7], pars->GC_11, amp[138]); + FFV1_0(w[33], w[58], w[4], pars->GC_11, amp[139]); + FFV1_0(w[32], w[55], w[8], pars->GC_2, amp[140]); + FFV1_0(w[67], w[58], w[8], pars->GC_2, amp[141]); + FFV1_0(w[67], w[65], w[7], pars->GC_11, amp[142]); + FFV1_0(w[32], w[65], w[4], pars->GC_11, amp[143]); + FFV1_0(w[34], w[55], w[7], pars->GC_11, amp[144]); + FFV1_0(w[34], w[58], w[4], pars->GC_11, amp[145]); + FFV2_5_0(w[32], w[55], w[17], pars->GC_51, pars->GC_58, amp[146]); + FFV2_5_0(w[67], w[58], w[17], pars->GC_51, pars->GC_58, amp[147]); + FFV1_0(w[30], w[61], w[68], pars->GC_11, amp[148]); + FFV1_0(w[33], w[54], w[68], pars->GC_11, amp[149]); + FFV1_0(w[30], w[65], w[68], pars->GC_11, amp[150]); + FFV1_0(w[34], w[54], w[68], pars->GC_11, amp[151]); + FFV1_0(w[69], w[61], w[6], pars->GC_11, amp[152]); + FFV1_0(w[38], w[61], w[4], pars->GC_11, amp[153]); + FFV1_0(w[39], w[55], w[6], pars->GC_11, amp[154]); + FFV1_0(w[39], w[56], w[4], pars->GC_11, amp[155]); + FFV1_0(w[38], w[55], w[8], pars->GC_2, amp[156]); + FFV1_0(w[69], w[56], w[8], pars->GC_2, amp[157]); + FFV1_0(w[69], w[65], w[6], pars->GC_11, amp[158]); + FFV1_0(w[38], w[65], w[4], pars->GC_11, amp[159]); + FFV1_0(w[40], w[55], w[6], pars->GC_11, amp[160]); + FFV1_0(w[40], w[56], w[4], pars->GC_11, amp[161]); + FFV2_5_0(w[38], w[55], w[17], pars->GC_51, pars->GC_58, amp[162]); + FFV2_5_0(w[69], w[56], w[17], pars->GC_51, pars->GC_58, amp[163]); + FFV1_0(w[36], w[61], w[70], pars->GC_11, amp[164]); + FFV1_0(w[39], w[54], w[70], pars->GC_11, amp[165]); + FFV1_0(w[36], w[65], w[70], pars->GC_11, amp[166]); + FFV1_0(w[40], w[54], w[70], pars->GC_11, amp[167]); + FFV1_0(w[71], w[61], w[7], pars->GC_11, amp[168]); + FFV1_0(w[3], w[61], w[72], pars->GC_11, amp[169]); + FFV1_0(w[10], w[73], w[7], pars->GC_11, amp[170]); + FFV1_0(w[10], w[58], w[70], pars->GC_11, amp[171]); + FFV1_0(w[10], w[54], w[72], pars->GC_11, amp[172]); + FFV1_0(w[71], w[58], w[8], pars->GC_2, amp[173]); + FFV1_0(w[71], w[65], w[7], pars->GC_11, amp[174]); + FFV1_0(w[3], w[65], w[72], pars->GC_11, amp[175]); + FFV1_0(w[18], w[73], w[7], pars->GC_11, amp[176]); + FFV1_0(w[18], w[58], w[70], pars->GC_11, amp[177]); + FFV1_0(w[18], w[54], w[72], pars->GC_11, amp[178]); + FFV2_5_0(w[71], w[58], w[17], pars->GC_51, pars->GC_58, amp[179]); + FFV1_0(w[74], w[61], w[6], pars->GC_11, amp[180]); + FFV1_0(w[3], w[61], w[75], pars->GC_11, amp[181]); + FFV1_0(w[10], w[76], w[6], pars->GC_11, amp[182]); + FFV1_0(w[10], w[56], w[68], pars->GC_11, amp[183]); + FFV1_0(w[10], w[54], w[75], pars->GC_11, amp[184]); + FFV1_0(w[74], w[56], w[8], pars->GC_2, amp[185]); + FFV1_0(w[74], w[65], w[6], pars->GC_11, amp[186]); + FFV1_0(w[3], w[65], w[75], pars->GC_11, amp[187]); + FFV1_0(w[18], w[76], w[6], pars->GC_11, amp[188]); + FFV1_0(w[18], w[56], w[68], pars->GC_11, amp[189]); + FFV1_0(w[18], w[54], w[75], pars->GC_11, amp[190]); + FFV2_5_0(w[74], w[56], w[17], pars->GC_51, pars->GC_58, amp[191]); + FFV1_0(w[48], w[61], w[4], pars->GC_11, amp[192]); + FFV1_0(w[3], w[61], w[77], pars->GC_11, amp[193]); + FFV1_0(w[10], w[55], w[29], pars->GC_11, amp[194]); + FFV1_0(w[10], w[78], w[4], pars->GC_11, amp[195]); + FFV1_0(w[10], w[54], w[77], pars->GC_11, amp[196]); + FFV1_0(w[48], w[55], w[8], pars->GC_2, amp[197]); + FFV1_0(w[48], w[65], w[4], pars->GC_11, amp[198]); + FFV1_0(w[3], w[65], w[77], pars->GC_11, amp[199]); + FFV1_0(w[18], w[55], w[29], pars->GC_11, amp[200]); + FFV1_0(w[18], w[78], w[4], pars->GC_11, amp[201]); + FFV1_0(w[18], w[54], w[77], pars->GC_11, amp[202]); + FFV2_5_0(w[48], w[55], w[17], pars->GC_51, pars->GC_58, amp[203]); + FFV1_0(w[3], w[61], w[79], pars->GC_11, amp[204]); + FFV1_0(w[3], w[61], w[80], pars->GC_11, amp[205]); + FFV1_0(w[3], w[61], w[81], pars->GC_11, amp[206]); + FFV1_0(w[10], w[54], w[79], pars->GC_11, amp[207]); + FFV1_0(w[10], w[54], w[80], pars->GC_11, amp[208]); + FFV1_0(w[10], w[54], w[81], pars->GC_11, amp[209]); + FFV1_0(w[3], w[65], w[79], pars->GC_11, amp[210]); + FFV1_0(w[3], w[65], w[80], pars->GC_11, amp[211]); + FFV1_0(w[3], w[65], w[81], pars->GC_11, amp[212]); + FFV1_0(w[18], w[54], w[79], pars->GC_11, amp[213]); + FFV1_0(w[18], w[54], w[80], pars->GC_11, amp[214]); + FFV1_0(w[18], w[54], w[81], pars->GC_11, amp[215]); + FFV1_0(w[15], w[83], w[7], pars->GC_11, amp[216]); + FFV1_0(w[13], w[83], w[5], pars->GC_11, amp[217]); + FFV1_0(w[57], w[84], w[7], pars->GC_11, amp[218]); + FFV1_0(w[13], w[84], w[4], pars->GC_11, amp[219]); + FFV1_0(w[57], w[85], w[5], pars->GC_11, amp[220]); + FFV1_0(w[15], w[85], w[4], pars->GC_11, amp[221]); + FFV1_0(w[21], w[83], w[7], pars->GC_11, amp[222]); + FFV1_0(w[20], w[83], w[5], pars->GC_11, amp[223]); + FFV1_0(w[59], w[84], w[7], pars->GC_11, amp[224]); + FFV1_0(w[20], w[84], w[4], pars->GC_11, amp[225]); + FFV1_0(w[59], w[85], w[5], pars->GC_11, amp[226]); + FFV1_0(w[21], w[85], w[4], pars->GC_11, amp[227]); + FFV1_0(w[87], w[86], w[7], pars->GC_11, amp[228]); + FFV1_0(w[63], w[86], w[5], pars->GC_11, amp[229]); + FFV1_0(w[64], w[84], w[7], pars->GC_11, amp[230]); + FFV1_0(w[64], w[85], w[5], pars->GC_11, amp[231]); + FFV1_0(w[63], w[84], w[8], pars->GC_2, amp[232]); + FFV1_0(w[87], w[85], w[8], pars->GC_2, amp[233]); + FFV1_0(w[87], w[88], w[7], pars->GC_11, amp[234]); + FFV1_0(w[63], w[88], w[5], pars->GC_11, amp[235]); + FFV1_0(w[66], w[84], w[7], pars->GC_11, amp[236]); + FFV1_0(w[66], w[85], w[5], pars->GC_11, amp[237]); + FFV2_5_0(w[63], w[84], w[17], pars->GC_51, pars->GC_58, amp[238]); + FFV2_5_0(w[87], w[85], w[17], pars->GC_51, pars->GC_58, amp[239]); + FFV1_0(w[60], w[86], w[35], pars->GC_11, amp[240]); + FFV1_0(w[64], w[82], w[35], pars->GC_11, amp[241]); + FFV1_0(w[60], w[88], w[35], pars->GC_11, amp[242]); + FFV1_0(w[66], w[82], w[35], pars->GC_11, amp[243]); + FFV1_0(w[89], w[86], w[7], pars->GC_11, amp[244]); + FFV1_0(w[25], w[86], w[4], pars->GC_11, amp[245]); + FFV1_0(w[26], w[83], w[7], pars->GC_11, amp[246]); + FFV1_0(w[26], w[85], w[4], pars->GC_11, amp[247]); + FFV1_0(w[25], w[83], w[8], pars->GC_2, amp[248]); + FFV1_0(w[89], w[85], w[8], pars->GC_2, amp[249]); + FFV1_0(w[89], w[88], w[7], pars->GC_11, amp[250]); + FFV1_0(w[25], w[88], w[4], pars->GC_11, amp[251]); + FFV1_0(w[28], w[83], w[7], pars->GC_11, amp[252]); + FFV1_0(w[28], w[85], w[4], pars->GC_11, amp[253]); + FFV2_5_0(w[25], w[83], w[17], pars->GC_51, pars->GC_58, amp[254]); + FFV2_5_0(w[89], w[85], w[17], pars->GC_51, pars->GC_58, amp[255]); + FFV1_0(w[22], w[86], w[68], pars->GC_11, amp[256]); + FFV1_0(w[26], w[82], w[68], pars->GC_11, amp[257]); + FFV1_0(w[22], w[88], w[68], pars->GC_11, amp[258]); + FFV1_0(w[28], w[82], w[68], pars->GC_11, amp[259]); + FFV1_0(w[69], w[86], w[5], pars->GC_11, amp[260]); + FFV1_0(w[37], w[86], w[4], pars->GC_11, amp[261]); + FFV1_0(w[39], w[83], w[5], pars->GC_11, amp[262]); + FFV1_0(w[39], w[84], w[4], pars->GC_11, amp[263]); + FFV1_0(w[37], w[83], w[8], pars->GC_2, amp[264]); + FFV1_0(w[69], w[84], w[8], pars->GC_2, amp[265]); + FFV1_0(w[69], w[88], w[5], pars->GC_11, amp[266]); + FFV1_0(w[37], w[88], w[4], pars->GC_11, amp[267]); + FFV1_0(w[40], w[83], w[5], pars->GC_11, amp[268]); + FFV1_0(w[40], w[84], w[4], pars->GC_11, amp[269]); + FFV2_5_0(w[37], w[83], w[17], pars->GC_51, pars->GC_58, amp[270]); + FFV2_5_0(w[69], w[84], w[17], pars->GC_51, pars->GC_58, amp[271]); + FFV1_0(w[36], w[86], w[90], pars->GC_11, amp[272]); + FFV1_0(w[39], w[82], w[90], pars->GC_11, amp[273]); + FFV1_0(w[36], w[88], w[90], pars->GC_11, amp[274]); + FFV1_0(w[40], w[82], w[90], pars->GC_11, amp[275]); + FFV1_0(w[91], w[86], w[7], pars->GC_11, amp[276]); + FFV1_0(w[3], w[86], w[92], pars->GC_11, amp[277]); + FFV1_0(w[10], w[93], w[7], pars->GC_11, amp[278]); + FFV1_0(w[10], w[85], w[90], pars->GC_11, amp[279]); + FFV1_0(w[10], w[82], w[92], pars->GC_11, amp[280]); + FFV1_0(w[91], w[85], w[8], pars->GC_2, amp[281]); + FFV1_0(w[91], w[88], w[7], pars->GC_11, amp[282]); + FFV1_0(w[3], w[88], w[92], pars->GC_11, amp[283]); + FFV1_0(w[18], w[93], w[7], pars->GC_11, amp[284]); + FFV1_0(w[18], w[85], w[90], pars->GC_11, amp[285]); + FFV1_0(w[18], w[82], w[92], pars->GC_11, amp[286]); + FFV2_5_0(w[91], w[85], w[17], pars->GC_51, pars->GC_58, amp[287]); + FFV1_0(w[74], w[86], w[5], pars->GC_11, amp[288]); + FFV1_0(w[3], w[86], w[94], pars->GC_11, amp[289]); + FFV1_0(w[10], w[95], w[5], pars->GC_11, amp[290]); + FFV1_0(w[10], w[84], w[68], pars->GC_11, amp[291]); + FFV1_0(w[10], w[82], w[94], pars->GC_11, amp[292]); + FFV1_0(w[74], w[84], w[8], pars->GC_2, amp[293]); + FFV1_0(w[74], w[88], w[5], pars->GC_11, amp[294]); + FFV1_0(w[3], w[88], w[94], pars->GC_11, amp[295]); + FFV1_0(w[18], w[95], w[5], pars->GC_11, amp[296]); + FFV1_0(w[18], w[84], w[68], pars->GC_11, amp[297]); + FFV1_0(w[18], w[82], w[94], pars->GC_11, amp[298]); + FFV2_5_0(w[74], w[84], w[17], pars->GC_51, pars->GC_58, amp[299]); + FFV1_0(w[45], w[86], w[4], pars->GC_11, amp[300]); + FFV1_0(w[3], w[86], w[96], pars->GC_11, amp[301]); + FFV1_0(w[10], w[83], w[35], pars->GC_11, amp[302]); + FFV1_0(w[10], w[97], w[4], pars->GC_11, amp[303]); + FFV1_0(w[10], w[82], w[96], pars->GC_11, amp[304]); + FFV1_0(w[45], w[83], w[8], pars->GC_2, amp[305]); + FFV1_0(w[45], w[88], w[4], pars->GC_11, amp[306]); + FFV1_0(w[3], w[88], w[96], pars->GC_11, amp[307]); + FFV1_0(w[18], w[83], w[35], pars->GC_11, amp[308]); + FFV1_0(w[18], w[97], w[4], pars->GC_11, amp[309]); + FFV1_0(w[18], w[82], w[96], pars->GC_11, amp[310]); + FFV2_5_0(w[45], w[83], w[17], pars->GC_51, pars->GC_58, amp[311]); + FFV1_0(w[3], w[86], w[98], pars->GC_11, amp[312]); + FFV1_0(w[3], w[86], w[99], pars->GC_11, amp[313]); + FFV1_0(w[3], w[86], w[100], pars->GC_11, amp[314]); + FFV1_0(w[10], w[82], w[98], pars->GC_11, amp[315]); + FFV1_0(w[10], w[82], w[99], pars->GC_11, amp[316]); + FFV1_0(w[10], w[82], w[100], pars->GC_11, amp[317]); + FFV1_0(w[3], w[88], w[98], pars->GC_11, amp[318]); + FFV1_0(w[3], w[88], w[99], pars->GC_11, amp[319]); + FFV1_0(w[3], w[88], w[100], pars->GC_11, amp[320]); + FFV1_0(w[18], w[82], w[98], pars->GC_11, amp[321]); + FFV1_0(w[18], w[82], w[99], pars->GC_11, amp[322]); + FFV1_0(w[18], w[82], w[100], pars->GC_11, amp[323]); + FFV1_0(w[15], w[102], w[6], pars->GC_11, amp[324]); + FFV1_0(w[12], w[102], w[5], pars->GC_11, amp[325]); + FFV1_0(w[57], w[103], w[6], pars->GC_11, amp[326]); + FFV1_0(w[12], w[103], w[4], pars->GC_11, amp[327]); + FFV1_0(w[57], w[104], w[5], pars->GC_11, amp[328]); + FFV1_0(w[15], w[104], w[4], pars->GC_11, amp[329]); + FFV1_0(w[21], w[102], w[6], pars->GC_11, amp[330]); + FFV1_0(w[19], w[102], w[5], pars->GC_11, amp[331]); + FFV1_0(w[59], w[103], w[6], pars->GC_11, amp[332]); + FFV1_0(w[19], w[103], w[4], pars->GC_11, amp[333]); + FFV1_0(w[59], w[104], w[5], pars->GC_11, amp[334]); + FFV1_0(w[21], w[104], w[4], pars->GC_11, amp[335]); + FFV1_0(w[87], w[105], w[6], pars->GC_11, amp[336]); + FFV1_0(w[62], w[105], w[5], pars->GC_11, amp[337]); + FFV1_0(w[64], w[103], w[6], pars->GC_11, amp[338]); + FFV1_0(w[64], w[104], w[5], pars->GC_11, amp[339]); + FFV1_0(w[62], w[103], w[8], pars->GC_2, amp[340]); + FFV1_0(w[87], w[104], w[8], pars->GC_2, amp[341]); + FFV1_0(w[87], w[106], w[6], pars->GC_11, amp[342]); + FFV1_0(w[62], w[106], w[5], pars->GC_11, amp[343]); + FFV1_0(w[66], w[103], w[6], pars->GC_11, amp[344]); + FFV1_0(w[66], w[104], w[5], pars->GC_11, amp[345]); + FFV2_5_0(w[62], w[103], w[17], pars->GC_51, pars->GC_58, amp[346]); + FFV2_5_0(w[87], w[104], w[17], pars->GC_51, pars->GC_58, amp[347]); + FFV1_0(w[60], w[105], w[41], pars->GC_11, amp[348]); + FFV1_0(w[64], w[101], w[41], pars->GC_11, amp[349]); + FFV1_0(w[60], w[106], w[41], pars->GC_11, amp[350]); + FFV1_0(w[66], w[101], w[41], pars->GC_11, amp[351]); + FFV1_0(w[89], w[105], w[6], pars->GC_11, amp[352]); + FFV1_0(w[24], w[105], w[4], pars->GC_11, amp[353]); + FFV1_0(w[26], w[102], w[6], pars->GC_11, amp[354]); + FFV1_0(w[26], w[104], w[4], pars->GC_11, amp[355]); + FFV1_0(w[24], w[102], w[8], pars->GC_2, amp[356]); + FFV1_0(w[89], w[104], w[8], pars->GC_2, amp[357]); + FFV1_0(w[89], w[106], w[6], pars->GC_11, amp[358]); + FFV1_0(w[24], w[106], w[4], pars->GC_11, amp[359]); + FFV1_0(w[28], w[102], w[6], pars->GC_11, amp[360]); + FFV1_0(w[28], w[104], w[4], pars->GC_11, amp[361]); + FFV2_5_0(w[24], w[102], w[17], pars->GC_51, pars->GC_58, amp[362]); + FFV2_5_0(w[89], w[104], w[17], pars->GC_51, pars->GC_58, amp[363]); + FFV1_0(w[22], w[105], w[70], pars->GC_11, amp[364]); + FFV1_0(w[26], w[101], w[70], pars->GC_11, amp[365]); + FFV1_0(w[22], w[106], w[70], pars->GC_11, amp[366]); + FFV1_0(w[28], w[101], w[70], pars->GC_11, amp[367]); + FFV1_0(w[67], w[105], w[5], pars->GC_11, amp[368]); + FFV1_0(w[31], w[105], w[4], pars->GC_11, amp[369]); + FFV1_0(w[33], w[102], w[5], pars->GC_11, amp[370]); + FFV1_0(w[33], w[103], w[4], pars->GC_11, amp[371]); + FFV1_0(w[31], w[102], w[8], pars->GC_2, amp[372]); + FFV1_0(w[67], w[103], w[8], pars->GC_2, amp[373]); + FFV1_0(w[67], w[106], w[5], pars->GC_11, amp[374]); + FFV1_0(w[31], w[106], w[4], pars->GC_11, amp[375]); + FFV1_0(w[34], w[102], w[5], pars->GC_11, amp[376]); + FFV1_0(w[34], w[103], w[4], pars->GC_11, amp[377]); + FFV2_5_0(w[31], w[102], w[17], pars->GC_51, pars->GC_58, amp[378]); + FFV2_5_0(w[67], w[103], w[17], pars->GC_51, pars->GC_58, amp[379]); + FFV1_0(w[30], w[105], w[90], pars->GC_11, amp[380]); + FFV1_0(w[33], w[101], w[90], pars->GC_11, amp[381]); + FFV1_0(w[30], w[106], w[90], pars->GC_11, amp[382]); + FFV1_0(w[34], w[101], w[90], pars->GC_11, amp[383]); + FFV1_0(w[91], w[105], w[6], pars->GC_11, amp[384]); + FFV1_0(w[3], w[105], w[107], pars->GC_11, amp[385]); + FFV1_0(w[10], w[108], w[6], pars->GC_11, amp[386]); + FFV1_0(w[10], w[104], w[90], pars->GC_11, amp[387]); + FFV1_0(w[10], w[101], w[107], pars->GC_11, amp[388]); + FFV1_0(w[91], w[104], w[8], pars->GC_2, amp[389]); + FFV1_0(w[91], w[106], w[6], pars->GC_11, amp[390]); + FFV1_0(w[3], w[106], w[107], pars->GC_11, amp[391]); + FFV1_0(w[18], w[108], w[6], pars->GC_11, amp[392]); + FFV1_0(w[18], w[104], w[90], pars->GC_11, amp[393]); + FFV1_0(w[18], w[101], w[107], pars->GC_11, amp[394]); + FFV2_5_0(w[91], w[104], w[17], pars->GC_51, pars->GC_58, amp[395]); + FFV1_0(w[71], w[105], w[5], pars->GC_11, amp[396]); + FFV1_0(w[3], w[105], w[109], pars->GC_11, amp[397]); + FFV1_0(w[10], w[110], w[5], pars->GC_11, amp[398]); + FFV1_0(w[10], w[103], w[70], pars->GC_11, amp[399]); + FFV1_0(w[10], w[101], w[109], pars->GC_11, amp[400]); + FFV1_0(w[71], w[103], w[8], pars->GC_2, amp[401]); + FFV1_0(w[71], w[106], w[5], pars->GC_11, amp[402]); + FFV1_0(w[3], w[106], w[109], pars->GC_11, amp[403]); + FFV1_0(w[18], w[110], w[5], pars->GC_11, amp[404]); + FFV1_0(w[18], w[103], w[70], pars->GC_11, amp[405]); + FFV1_0(w[18], w[101], w[109], pars->GC_11, amp[406]); + FFV2_5_0(w[71], w[103], w[17], pars->GC_51, pars->GC_58, amp[407]); + FFV1_0(w[42], w[105], w[4], pars->GC_11, amp[408]); + FFV1_0(w[3], w[105], w[111], pars->GC_11, amp[409]); + FFV1_0(w[10], w[102], w[41], pars->GC_11, amp[410]); + FFV1_0(w[10], w[112], w[4], pars->GC_11, amp[411]); + FFV1_0(w[10], w[101], w[111], pars->GC_11, amp[412]); + FFV1_0(w[42], w[102], w[8], pars->GC_2, amp[413]); + FFV1_0(w[42], w[106], w[4], pars->GC_11, amp[414]); + FFV1_0(w[3], w[106], w[111], pars->GC_11, amp[415]); + FFV1_0(w[18], w[102], w[41], pars->GC_11, amp[416]); + FFV1_0(w[18], w[112], w[4], pars->GC_11, amp[417]); + FFV1_0(w[18], w[101], w[111], pars->GC_11, amp[418]); + FFV2_5_0(w[42], w[102], w[17], pars->GC_51, pars->GC_58, amp[419]); + FFV1_0(w[3], w[105], w[113], pars->GC_11, amp[420]); + FFV1_0(w[3], w[105], w[114], pars->GC_11, amp[421]); + FFV1_0(w[3], w[105], w[115], pars->GC_11, amp[422]); + FFV1_0(w[10], w[101], w[113], pars->GC_11, amp[423]); + FFV1_0(w[10], w[101], w[114], pars->GC_11, amp[424]); + FFV1_0(w[10], w[101], w[115], pars->GC_11, amp[425]); + FFV1_0(w[3], w[106], w[113], pars->GC_11, amp[426]); + FFV1_0(w[3], w[106], w[114], pars->GC_11, amp[427]); + FFV1_0(w[3], w[106], w[115], pars->GC_11, amp[428]); + FFV1_0(w[18], w[101], w[113], pars->GC_11, amp[429]); + FFV1_0(w[18], w[101], w[114], pars->GC_11, amp[430]); + FFV1_0(w[18], w[101], w[115], pars->GC_11, amp[431]); + FFV1_0(w[87], w[117], w[7], pars->GC_11, amp[432]); + FFV1_0(w[87], w[118], w[6], pars->GC_11, amp[433]); + FFV1_0(w[62], w[119], w[7], pars->GC_11, amp[434]); + FFV1_0(w[62], w[118], w[5], pars->GC_11, amp[435]); + FFV1_0(w[63], w[119], w[6], pars->GC_11, amp[436]); + FFV1_0(w[63], w[117], w[5], pars->GC_11, amp[437]); + FFV1_0(w[87], w[121], w[7], pars->GC_11, amp[438]); + FFV1_0(w[87], w[122], w[6], pars->GC_11, amp[439]); + FFV1_0(w[62], w[123], w[7], pars->GC_11, amp[440]); + FFV1_0(w[62], w[122], w[5], pars->GC_11, amp[441]); + FFV1_0(w[63], w[123], w[6], pars->GC_11, amp[442]); + FFV1_0(w[63], w[121], w[5], pars->GC_11, amp[443]); + FFV1_0(w[124], w[116], w[7], pars->GC_11, amp[444]); + FFV1_0(w[63], w[116], w[41], pars->GC_11, amp[445]); + FFV1_0(w[60], w[116], w[43], pars->GC_11, amp[446]); + FFV1_0(w[64], w[125], w[7], pars->GC_11, amp[447]); + FFV1_0(w[64], w[2], w[43], pars->GC_11, amp[448]); + FFV1_0(w[63], w[125], w[8], pars->GC_2, amp[449]); + FFV1_0(w[124], w[120], w[7], pars->GC_11, amp[450]); + FFV1_0(w[63], w[120], w[41], pars->GC_11, amp[451]); + FFV1_0(w[60], w[120], w[43], pars->GC_11, amp[452]); + FFV1_0(w[66], w[125], w[7], pars->GC_11, amp[453]); + FFV1_0(w[66], w[2], w[43], pars->GC_11, amp[454]); + FFV2_5_0(w[63], w[125], w[17], pars->GC_51, pars->GC_58, amp[455]); + FFV1_0(w[126], w[116], w[6], pars->GC_11, amp[456]); + FFV1_0(w[62], w[116], w[35], pars->GC_11, amp[457]); + FFV1_0(w[60], w[116], w[46], pars->GC_11, amp[458]); + FFV1_0(w[64], w[127], w[6], pars->GC_11, amp[459]); + FFV1_0(w[64], w[2], w[46], pars->GC_11, amp[460]); + FFV1_0(w[62], w[127], w[8], pars->GC_2, amp[461]); + FFV1_0(w[126], w[120], w[6], pars->GC_11, amp[462]); + FFV1_0(w[62], w[120], w[35], pars->GC_11, amp[463]); + FFV1_0(w[60], w[120], w[46], pars->GC_11, amp[464]); + FFV1_0(w[66], w[127], w[6], pars->GC_11, amp[465]); + FFV1_0(w[66], w[2], w[46], pars->GC_11, amp[466]); + FFV2_5_0(w[62], w[127], w[17], pars->GC_51, pars->GC_58, amp[467]); + FFV1_0(w[87], w[116], w[29], pars->GC_11, amp[468]); + FFV1_0(w[128], w[116], w[5], pars->GC_11, amp[469]); + FFV1_0(w[60], w[116], w[49], pars->GC_11, amp[470]); + FFV1_0(w[64], w[129], w[5], pars->GC_11, amp[471]); + FFV1_0(w[64], w[2], w[49], pars->GC_11, amp[472]); + FFV1_0(w[87], w[129], w[8], pars->GC_2, amp[473]); + FFV1_0(w[87], w[120], w[29], pars->GC_11, amp[474]); + FFV1_0(w[128], w[120], w[5], pars->GC_11, amp[475]); + FFV1_0(w[60], w[120], w[49], pars->GC_11, amp[476]); + FFV1_0(w[66], w[129], w[5], pars->GC_11, amp[477]); + FFV1_0(w[66], w[2], w[49], pars->GC_11, amp[478]); + FFV2_5_0(w[87], w[129], w[17], pars->GC_51, pars->GC_58, amp[479]); + FFV1_0(w[60], w[116], w[51], pars->GC_11, amp[480]); + FFV1_0(w[60], w[116], w[52], pars->GC_11, amp[481]); + FFV1_0(w[60], w[116], w[53], pars->GC_11, amp[482]); + FFV1_0(w[64], w[2], w[51], pars->GC_11, amp[483]); + FFV1_0(w[64], w[2], w[52], pars->GC_11, amp[484]); + FFV1_0(w[64], w[2], w[53], pars->GC_11, amp[485]); + FFV1_0(w[60], w[120], w[51], pars->GC_11, amp[486]); + FFV1_0(w[60], w[120], w[52], pars->GC_11, amp[487]); + FFV1_0(w[60], w[120], w[53], pars->GC_11, amp[488]); + FFV1_0(w[66], w[2], w[51], pars->GC_11, amp[489]); + FFV1_0(w[66], w[2], w[52], pars->GC_11, amp[490]); + FFV1_0(w[66], w[2], w[53], pars->GC_11, amp[491]); + FFV1_0(w[89], w[117], w[7], pars->GC_11, amp[492]); + FFV1_0(w[89], w[118], w[6], pars->GC_11, amp[493]); + FFV1_0(w[24], w[130], w[7], pars->GC_11, amp[494]); + FFV1_0(w[24], w[118], w[4], pars->GC_11, amp[495]); + FFV1_0(w[25], w[130], w[6], pars->GC_11, amp[496]); + FFV1_0(w[25], w[117], w[4], pars->GC_11, amp[497]); + FFV1_0(w[89], w[121], w[7], pars->GC_11, amp[498]); + FFV1_0(w[89], w[122], w[6], pars->GC_11, amp[499]); + FFV1_0(w[24], w[131], w[7], pars->GC_11, amp[500]); + FFV1_0(w[24], w[122], w[4], pars->GC_11, amp[501]); + FFV1_0(w[25], w[131], w[6], pars->GC_11, amp[502]); + FFV1_0(w[25], w[121], w[4], pars->GC_11, amp[503]); + FFV1_0(w[132], w[116], w[7], pars->GC_11, amp[504]); + FFV1_0(w[25], w[116], w[70], pars->GC_11, amp[505]); + FFV1_0(w[22], w[116], w[72], pars->GC_11, amp[506]); + FFV1_0(w[26], w[133], w[7], pars->GC_11, amp[507]); + FFV1_0(w[26], w[2], w[72], pars->GC_11, amp[508]); + FFV1_0(w[25], w[133], w[8], pars->GC_2, amp[509]); + FFV1_0(w[132], w[120], w[7], pars->GC_11, amp[510]); + FFV1_0(w[25], w[120], w[70], pars->GC_11, amp[511]); + FFV1_0(w[22], w[120], w[72], pars->GC_11, amp[512]); + FFV1_0(w[28], w[133], w[7], pars->GC_11, amp[513]); + FFV1_0(w[28], w[2], w[72], pars->GC_11, amp[514]); + FFV2_5_0(w[25], w[133], w[17], pars->GC_51, pars->GC_58, amp[515]); + FFV1_0(w[134], w[116], w[6], pars->GC_11, amp[516]); + FFV1_0(w[24], w[116], w[68], pars->GC_11, amp[517]); + FFV1_0(w[22], w[116], w[75], pars->GC_11, amp[518]); + FFV1_0(w[26], w[135], w[6], pars->GC_11, amp[519]); + FFV1_0(w[26], w[2], w[75], pars->GC_11, amp[520]); + FFV1_0(w[24], w[135], w[8], pars->GC_2, amp[521]); + FFV1_0(w[134], w[120], w[6], pars->GC_11, amp[522]); + FFV1_0(w[24], w[120], w[68], pars->GC_11, amp[523]); + FFV1_0(w[22], w[120], w[75], pars->GC_11, amp[524]); + FFV1_0(w[28], w[135], w[6], pars->GC_11, amp[525]); + FFV1_0(w[28], w[2], w[75], pars->GC_11, amp[526]); + FFV2_5_0(w[24], w[135], w[17], pars->GC_51, pars->GC_58, amp[527]); + FFV1_0(w[89], w[116], w[29], pars->GC_11, amp[528]); + FFV1_0(w[136], w[116], w[4], pars->GC_11, amp[529]); + FFV1_0(w[22], w[116], w[77], pars->GC_11, amp[530]); + FFV1_0(w[26], w[129], w[4], pars->GC_11, amp[531]); + FFV1_0(w[26], w[2], w[77], pars->GC_11, amp[532]); + FFV1_0(w[89], w[129], w[8], pars->GC_2, amp[533]); + FFV1_0(w[89], w[120], w[29], pars->GC_11, amp[534]); + FFV1_0(w[136], w[120], w[4], pars->GC_11, amp[535]); + FFV1_0(w[22], w[120], w[77], pars->GC_11, amp[536]); + FFV1_0(w[28], w[129], w[4], pars->GC_11, amp[537]); + FFV1_0(w[28], w[2], w[77], pars->GC_11, amp[538]); + FFV2_5_0(w[89], w[129], w[17], pars->GC_51, pars->GC_58, amp[539]); + FFV1_0(w[22], w[116], w[79], pars->GC_11, amp[540]); + FFV1_0(w[22], w[116], w[80], pars->GC_11, amp[541]); + FFV1_0(w[22], w[116], w[81], pars->GC_11, amp[542]); + FFV1_0(w[26], w[2], w[79], pars->GC_11, amp[543]); + FFV1_0(w[26], w[2], w[80], pars->GC_11, amp[544]); + FFV1_0(w[26], w[2], w[81], pars->GC_11, amp[545]); + FFV1_0(w[22], w[120], w[79], pars->GC_11, amp[546]); + FFV1_0(w[22], w[120], w[80], pars->GC_11, amp[547]); + FFV1_0(w[22], w[120], w[81], pars->GC_11, amp[548]); + FFV1_0(w[28], w[2], w[79], pars->GC_11, amp[549]); + FFV1_0(w[28], w[2], w[80], pars->GC_11, amp[550]); + FFV1_0(w[28], w[2], w[81], pars->GC_11, amp[551]); + FFV1_0(w[67], w[119], w[7], pars->GC_11, amp[552]); + FFV1_0(w[67], w[118], w[5], pars->GC_11, amp[553]); + FFV1_0(w[31], w[130], w[7], pars->GC_11, amp[554]); + FFV1_0(w[31], w[118], w[4], pars->GC_11, amp[555]); + FFV1_0(w[32], w[130], w[5], pars->GC_11, amp[556]); + FFV1_0(w[32], w[119], w[4], pars->GC_11, amp[557]); + FFV1_0(w[67], w[123], w[7], pars->GC_11, amp[558]); + FFV1_0(w[67], w[122], w[5], pars->GC_11, amp[559]); + FFV1_0(w[31], w[131], w[7], pars->GC_11, amp[560]); + FFV1_0(w[31], w[122], w[4], pars->GC_11, amp[561]); + FFV1_0(w[32], w[131], w[5], pars->GC_11, amp[562]); + FFV1_0(w[32], w[123], w[4], pars->GC_11, amp[563]); + FFV1_0(w[137], w[116], w[7], pars->GC_11, amp[564]); + FFV1_0(w[32], w[116], w[90], pars->GC_11, amp[565]); + FFV1_0(w[30], w[116], w[92], pars->GC_11, amp[566]); + FFV1_0(w[33], w[138], w[7], pars->GC_11, amp[567]); + FFV1_0(w[33], w[2], w[92], pars->GC_11, amp[568]); + FFV1_0(w[32], w[138], w[8], pars->GC_2, amp[569]); + FFV1_0(w[137], w[120], w[7], pars->GC_11, amp[570]); + FFV1_0(w[32], w[120], w[90], pars->GC_11, amp[571]); + FFV1_0(w[30], w[120], w[92], pars->GC_11, amp[572]); + FFV1_0(w[34], w[138], w[7], pars->GC_11, amp[573]); + FFV1_0(w[34], w[2], w[92], pars->GC_11, amp[574]); + FFV2_5_0(w[32], w[138], w[17], pars->GC_51, pars->GC_58, amp[575]); + FFV1_0(w[139], w[116], w[5], pars->GC_11, amp[576]); + FFV1_0(w[31], w[116], w[68], pars->GC_11, amp[577]); + FFV1_0(w[30], w[116], w[94], pars->GC_11, amp[578]); + FFV1_0(w[33], w[135], w[5], pars->GC_11, amp[579]); + FFV1_0(w[33], w[2], w[94], pars->GC_11, amp[580]); + FFV1_0(w[31], w[135], w[8], pars->GC_2, amp[581]); + FFV1_0(w[139], w[120], w[5], pars->GC_11, amp[582]); + FFV1_0(w[31], w[120], w[68], pars->GC_11, amp[583]); + FFV1_0(w[30], w[120], w[94], pars->GC_11, amp[584]); + FFV1_0(w[34], w[135], w[5], pars->GC_11, amp[585]); + FFV1_0(w[34], w[2], w[94], pars->GC_11, amp[586]); + FFV2_5_0(w[31], w[135], w[17], pars->GC_51, pars->GC_58, amp[587]); + FFV1_0(w[67], w[116], w[35], pars->GC_11, amp[588]); + FFV1_0(w[140], w[116], w[4], pars->GC_11, amp[589]); + FFV1_0(w[30], w[116], w[96], pars->GC_11, amp[590]); + FFV1_0(w[33], w[127], w[4], pars->GC_11, amp[591]); + FFV1_0(w[33], w[2], w[96], pars->GC_11, amp[592]); + FFV1_0(w[67], w[127], w[8], pars->GC_2, amp[593]); + FFV1_0(w[67], w[120], w[35], pars->GC_11, amp[594]); + FFV1_0(w[140], w[120], w[4], pars->GC_11, amp[595]); + FFV1_0(w[30], w[120], w[96], pars->GC_11, amp[596]); + FFV1_0(w[34], w[127], w[4], pars->GC_11, amp[597]); + FFV1_0(w[34], w[2], w[96], pars->GC_11, amp[598]); + FFV2_5_0(w[67], w[127], w[17], pars->GC_51, pars->GC_58, amp[599]); + FFV1_0(w[30], w[116], w[98], pars->GC_11, amp[600]); + FFV1_0(w[30], w[116], w[99], pars->GC_11, amp[601]); + FFV1_0(w[30], w[116], w[100], pars->GC_11, amp[602]); + FFV1_0(w[33], w[2], w[98], pars->GC_11, amp[603]); + FFV1_0(w[33], w[2], w[99], pars->GC_11, amp[604]); + FFV1_0(w[33], w[2], w[100], pars->GC_11, amp[605]); + FFV1_0(w[30], w[120], w[98], pars->GC_11, amp[606]); + FFV1_0(w[30], w[120], w[99], pars->GC_11, amp[607]); + FFV1_0(w[30], w[120], w[100], pars->GC_11, amp[608]); + FFV1_0(w[34], w[2], w[98], pars->GC_11, amp[609]); + FFV1_0(w[34], w[2], w[99], pars->GC_11, amp[610]); + FFV1_0(w[34], w[2], w[100], pars->GC_11, amp[611]); + FFV1_0(w[69], w[119], w[6], pars->GC_11, amp[612]); + FFV1_0(w[69], w[117], w[5], pars->GC_11, amp[613]); + FFV1_0(w[37], w[130], w[6], pars->GC_11, amp[614]); + FFV1_0(w[37], w[117], w[4], pars->GC_11, amp[615]); + FFV1_0(w[38], w[130], w[5], pars->GC_11, amp[616]); + FFV1_0(w[38], w[119], w[4], pars->GC_11, amp[617]); + FFV1_0(w[69], w[123], w[6], pars->GC_11, amp[618]); + FFV1_0(w[69], w[121], w[5], pars->GC_11, amp[619]); + FFV1_0(w[37], w[131], w[6], pars->GC_11, amp[620]); + FFV1_0(w[37], w[121], w[4], pars->GC_11, amp[621]); + FFV1_0(w[38], w[131], w[5], pars->GC_11, amp[622]); + FFV1_0(w[38], w[123], w[4], pars->GC_11, amp[623]); + FFV1_0(w[141], w[116], w[6], pars->GC_11, amp[624]); + FFV1_0(w[38], w[116], w[90], pars->GC_11, amp[625]); + FFV1_0(w[36], w[116], w[107], pars->GC_11, amp[626]); + FFV1_0(w[39], w[138], w[6], pars->GC_11, amp[627]); + FFV1_0(w[39], w[2], w[107], pars->GC_11, amp[628]); + FFV1_0(w[38], w[138], w[8], pars->GC_2, amp[629]); + FFV1_0(w[141], w[120], w[6], pars->GC_11, amp[630]); + FFV1_0(w[38], w[120], w[90], pars->GC_11, amp[631]); + FFV1_0(w[36], w[120], w[107], pars->GC_11, amp[632]); + FFV1_0(w[40], w[138], w[6], pars->GC_11, amp[633]); + FFV1_0(w[40], w[2], w[107], pars->GC_11, amp[634]); + FFV2_5_0(w[38], w[138], w[17], pars->GC_51, pars->GC_58, amp[635]); + FFV1_0(w[142], w[116], w[5], pars->GC_11, amp[636]); + FFV1_0(w[37], w[116], w[70], pars->GC_11, amp[637]); + FFV1_0(w[36], w[116], w[109], pars->GC_11, amp[638]); + FFV1_0(w[39], w[133], w[5], pars->GC_11, amp[639]); + FFV1_0(w[39], w[2], w[109], pars->GC_11, amp[640]); + FFV1_0(w[37], w[133], w[8], pars->GC_2, amp[641]); + FFV1_0(w[142], w[120], w[5], pars->GC_11, amp[642]); + FFV1_0(w[37], w[120], w[70], pars->GC_11, amp[643]); + FFV1_0(w[36], w[120], w[109], pars->GC_11, amp[644]); + FFV1_0(w[40], w[133], w[5], pars->GC_11, amp[645]); + FFV1_0(w[40], w[2], w[109], pars->GC_11, amp[646]); + FFV2_5_0(w[37], w[133], w[17], pars->GC_51, pars->GC_58, amp[647]); + FFV1_0(w[69], w[116], w[41], pars->GC_11, amp[648]); + FFV1_0(w[143], w[116], w[4], pars->GC_11, amp[649]); + FFV1_0(w[36], w[116], w[111], pars->GC_11, amp[650]); + FFV1_0(w[39], w[125], w[4], pars->GC_11, amp[651]); + FFV1_0(w[39], w[2], w[111], pars->GC_11, amp[652]); + FFV1_0(w[69], w[125], w[8], pars->GC_2, amp[653]); + FFV1_0(w[69], w[120], w[41], pars->GC_11, amp[654]); + FFV1_0(w[143], w[120], w[4], pars->GC_11, amp[655]); + FFV1_0(w[36], w[120], w[111], pars->GC_11, amp[656]); + FFV1_0(w[40], w[125], w[4], pars->GC_11, amp[657]); + FFV1_0(w[40], w[2], w[111], pars->GC_11, amp[658]); + FFV2_5_0(w[69], w[125], w[17], pars->GC_51, pars->GC_58, amp[659]); + FFV1_0(w[36], w[116], w[113], pars->GC_11, amp[660]); + FFV1_0(w[36], w[116], w[114], pars->GC_11, amp[661]); + FFV1_0(w[36], w[116], w[115], pars->GC_11, amp[662]); + FFV1_0(w[39], w[2], w[113], pars->GC_11, amp[663]); + FFV1_0(w[39], w[2], w[114], pars->GC_11, amp[664]); + FFV1_0(w[39], w[2], w[115], pars->GC_11, amp[665]); + FFV1_0(w[36], w[120], w[113], pars->GC_11, amp[666]); + FFV1_0(w[36], w[120], w[114], pars->GC_11, amp[667]); + FFV1_0(w[36], w[120], w[115], pars->GC_11, amp[668]); + FFV1_0(w[40], w[2], w[113], pars->GC_11, amp[669]); + FFV1_0(w[40], w[2], w[114], pars->GC_11, amp[670]); + FFV1_0(w[40], w[2], w[115], pars->GC_11, amp[671]); + FFV1_0(w[91], w[117], w[7], pars->GC_11, amp[672]); + FFV1_0(w[91], w[118], w[6], pars->GC_11, amp[673]); + VVV1_0(w[107], w[7], w[144], pars->GC_10, amp[674]); + FFV1_0(w[3], w[118], w[107], pars->GC_11, amp[675]); + VVV1_0(w[92], w[6], w[144], pars->GC_10, amp[676]); + FFV1_0(w[3], w[117], w[92], pars->GC_11, amp[677]); + FFV1_0(w[3], w[116], w[145], pars->GC_11, amp[678]); + FFV1_0(w[3], w[116], w[146], pars->GC_11, amp[679]); + FFV1_0(w[3], w[116], w[147], pars->GC_11, amp[680]); + FFV1_0(w[12], w[138], w[7], pars->GC_11, amp[681]); + FFV1_0(w[13], w[138], w[6], pars->GC_11, amp[682]); + VVV1_0(w[107], w[7], w[148], pars->GC_10, amp[683]); + FFV1_0(w[13], w[2], w[107], pars->GC_11, amp[684]); + VVV1_0(w[92], w[6], w[148], pars->GC_10, amp[685]); + FFV1_0(w[12], w[2], w[92], pars->GC_11, amp[686]); + FFV1_0(w[10], w[2], w[145], pars->GC_11, amp[687]); + FFV1_0(w[10], w[2], w[146], pars->GC_11, amp[688]); + FFV1_0(w[10], w[2], w[147], pars->GC_11, amp[689]); + FFV1_0(w[91], w[121], w[7], pars->GC_11, amp[690]); + FFV1_0(w[91], w[122], w[6], pars->GC_11, amp[691]); + VVV1_0(w[107], w[7], w[149], pars->GC_10, amp[692]); + FFV1_0(w[3], w[122], w[107], pars->GC_11, amp[693]); + VVV1_0(w[92], w[6], w[149], pars->GC_10, amp[694]); + FFV1_0(w[3], w[121], w[92], pars->GC_11, amp[695]); + FFV1_0(w[3], w[120], w[145], pars->GC_11, amp[696]); + FFV1_0(w[3], w[120], w[146], pars->GC_11, amp[697]); + FFV1_0(w[3], w[120], w[147], pars->GC_11, amp[698]); + FFV1_0(w[19], w[138], w[7], pars->GC_11, amp[699]); + FFV1_0(w[20], w[138], w[6], pars->GC_11, amp[700]); + VVV1_0(w[107], w[7], w[150], pars->GC_10, amp[701]); + FFV1_0(w[20], w[2], w[107], pars->GC_11, amp[702]); + VVV1_0(w[92], w[6], w[150], pars->GC_10, amp[703]); + FFV1_0(w[19], w[2], w[92], pars->GC_11, amp[704]); + FFV1_0(w[18], w[2], w[145], pars->GC_11, amp[705]); + FFV1_0(w[18], w[2], w[146], pars->GC_11, amp[706]); + FFV1_0(w[18], w[2], w[147], pars->GC_11, amp[707]); + FFV1_0(w[91], w[116], w[29], pars->GC_11, amp[708]); + FFV1_0(w[48], w[116], w[90], pars->GC_11, amp[709]); + FFV1_0(w[3], w[116], w[151], pars->GC_11, amp[710]); + FFV1_0(w[10], w[138], w[29], pars->GC_11, amp[711]); + FFV1_0(w[10], w[129], w[90], pars->GC_11, amp[712]); + FFV1_0(w[10], w[2], w[151], pars->GC_11, amp[713]); + FFV1_0(w[48], w[138], w[8], pars->GC_2, amp[714]); + FFV1_0(w[91], w[129], w[8], pars->GC_2, amp[715]); + FFV1_0(w[91], w[120], w[29], pars->GC_11, amp[716]); + FFV1_0(w[48], w[120], w[90], pars->GC_11, amp[717]); + FFV1_0(w[3], w[120], w[151], pars->GC_11, amp[718]); + FFV1_0(w[18], w[138], w[29], pars->GC_11, amp[719]); + FFV1_0(w[18], w[129], w[90], pars->GC_11, amp[720]); + FFV1_0(w[18], w[2], w[151], pars->GC_11, amp[721]); + FFV2_5_0(w[48], w[138], w[17], pars->GC_51, pars->GC_58, amp[722]); + FFV2_5_0(w[91], w[129], w[17], pars->GC_51, pars->GC_58, amp[723]); + FFV1_0(w[71], w[119], w[7], pars->GC_11, amp[724]); + FFV1_0(w[71], w[118], w[5], pars->GC_11, amp[725]); + VVV1_0(w[109], w[7], w[144], pars->GC_10, amp[726]); + FFV1_0(w[3], w[118], w[109], pars->GC_11, amp[727]); + VVV1_0(w[72], w[5], w[144], pars->GC_10, amp[728]); + FFV1_0(w[3], w[119], w[72], pars->GC_11, amp[729]); + FFV1_0(w[3], w[116], w[152], pars->GC_11, amp[730]); + FFV1_0(w[3], w[116], w[153], pars->GC_11, amp[731]); + FFV1_0(w[3], w[116], w[154], pars->GC_11, amp[732]); + FFV1_0(w[15], w[133], w[7], pars->GC_11, amp[733]); + FFV1_0(w[13], w[133], w[5], pars->GC_11, amp[734]); + VVV1_0(w[109], w[7], w[148], pars->GC_10, amp[735]); + FFV1_0(w[13], w[2], w[109], pars->GC_11, amp[736]); + VVV1_0(w[72], w[5], w[148], pars->GC_10, amp[737]); + FFV1_0(w[15], w[2], w[72], pars->GC_11, amp[738]); + FFV1_0(w[10], w[2], w[152], pars->GC_11, amp[739]); + FFV1_0(w[10], w[2], w[153], pars->GC_11, amp[740]); + FFV1_0(w[10], w[2], w[154], pars->GC_11, amp[741]); + FFV1_0(w[71], w[123], w[7], pars->GC_11, amp[742]); + FFV1_0(w[71], w[122], w[5], pars->GC_11, amp[743]); + VVV1_0(w[109], w[7], w[149], pars->GC_10, amp[744]); + FFV1_0(w[3], w[122], w[109], pars->GC_11, amp[745]); + VVV1_0(w[72], w[5], w[149], pars->GC_10, amp[746]); + FFV1_0(w[3], w[123], w[72], pars->GC_11, amp[747]); + FFV1_0(w[3], w[120], w[152], pars->GC_11, amp[748]); + FFV1_0(w[3], w[120], w[153], pars->GC_11, amp[749]); + FFV1_0(w[3], w[120], w[154], pars->GC_11, amp[750]); + FFV1_0(w[21], w[133], w[7], pars->GC_11, amp[751]); + FFV1_0(w[20], w[133], w[5], pars->GC_11, amp[752]); + VVV1_0(w[109], w[7], w[150], pars->GC_10, amp[753]); + FFV1_0(w[20], w[2], w[109], pars->GC_11, amp[754]); + VVV1_0(w[72], w[5], w[150], pars->GC_10, amp[755]); + FFV1_0(w[21], w[2], w[72], pars->GC_11, amp[756]); + FFV1_0(w[18], w[2], w[152], pars->GC_11, amp[757]); + FFV1_0(w[18], w[2], w[153], pars->GC_11, amp[758]); + FFV1_0(w[18], w[2], w[154], pars->GC_11, amp[759]); + FFV1_0(w[71], w[116], w[35], pars->GC_11, amp[760]); + FFV1_0(w[45], w[116], w[70], pars->GC_11, amp[761]); + FFV1_0(w[3], w[116], w[155], pars->GC_11, amp[762]); + FFV1_0(w[10], w[133], w[35], pars->GC_11, amp[763]); + FFV1_0(w[10], w[127], w[70], pars->GC_11, amp[764]); + FFV1_0(w[10], w[2], w[155], pars->GC_11, amp[765]); + FFV1_0(w[45], w[133], w[8], pars->GC_2, amp[766]); + FFV1_0(w[71], w[127], w[8], pars->GC_2, amp[767]); + FFV1_0(w[71], w[120], w[35], pars->GC_11, amp[768]); + FFV1_0(w[45], w[120], w[70], pars->GC_11, amp[769]); + FFV1_0(w[3], w[120], w[155], pars->GC_11, amp[770]); + FFV1_0(w[18], w[133], w[35], pars->GC_11, amp[771]); + FFV1_0(w[18], w[127], w[70], pars->GC_11, amp[772]); + FFV1_0(w[18], w[2], w[155], pars->GC_11, amp[773]); + FFV2_5_0(w[45], w[133], w[17], pars->GC_51, pars->GC_58, amp[774]); + FFV2_5_0(w[71], w[127], w[17], pars->GC_51, pars->GC_58, amp[775]); + FFV1_0(w[74], w[119], w[6], pars->GC_11, amp[776]); + FFV1_0(w[74], w[117], w[5], pars->GC_11, amp[777]); + VVV1_0(w[94], w[6], w[144], pars->GC_10, amp[778]); + FFV1_0(w[3], w[117], w[94], pars->GC_11, amp[779]); + VVV1_0(w[75], w[5], w[144], pars->GC_10, amp[780]); + FFV1_0(w[3], w[119], w[75], pars->GC_11, amp[781]); + FFV1_0(w[3], w[116], w[156], pars->GC_11, amp[782]); + FFV1_0(w[3], w[116], w[157], pars->GC_11, amp[783]); + FFV1_0(w[3], w[116], w[158], pars->GC_11, amp[784]); + FFV1_0(w[15], w[135], w[6], pars->GC_11, amp[785]); + FFV1_0(w[12], w[135], w[5], pars->GC_11, amp[786]); + VVV1_0(w[94], w[6], w[148], pars->GC_10, amp[787]); + FFV1_0(w[12], w[2], w[94], pars->GC_11, amp[788]); + VVV1_0(w[75], w[5], w[148], pars->GC_10, amp[789]); + FFV1_0(w[15], w[2], w[75], pars->GC_11, amp[790]); + FFV1_0(w[10], w[2], w[156], pars->GC_11, amp[791]); + FFV1_0(w[10], w[2], w[157], pars->GC_11, amp[792]); + FFV1_0(w[10], w[2], w[158], pars->GC_11, amp[793]); + FFV1_0(w[74], w[123], w[6], pars->GC_11, amp[794]); + FFV1_0(w[74], w[121], w[5], pars->GC_11, amp[795]); + VVV1_0(w[94], w[6], w[149], pars->GC_10, amp[796]); + FFV1_0(w[3], w[121], w[94], pars->GC_11, amp[797]); + VVV1_0(w[75], w[5], w[149], pars->GC_10, amp[798]); + FFV1_0(w[3], w[123], w[75], pars->GC_11, amp[799]); + FFV1_0(w[3], w[120], w[156], pars->GC_11, amp[800]); + FFV1_0(w[3], w[120], w[157], pars->GC_11, amp[801]); + FFV1_0(w[3], w[120], w[158], pars->GC_11, amp[802]); + FFV1_0(w[21], w[135], w[6], pars->GC_11, amp[803]); + FFV1_0(w[19], w[135], w[5], pars->GC_11, amp[804]); + VVV1_0(w[94], w[6], w[150], pars->GC_10, amp[805]); + FFV1_0(w[19], w[2], w[94], pars->GC_11, amp[806]); + VVV1_0(w[75], w[5], w[150], pars->GC_10, amp[807]); + FFV1_0(w[21], w[2], w[75], pars->GC_11, amp[808]); + FFV1_0(w[18], w[2], w[156], pars->GC_11, amp[809]); + FFV1_0(w[18], w[2], w[157], pars->GC_11, amp[810]); + FFV1_0(w[18], w[2], w[158], pars->GC_11, amp[811]); + FFV1_0(w[74], w[116], w[41], pars->GC_11, amp[812]); + FFV1_0(w[42], w[116], w[68], pars->GC_11, amp[813]); + FFV1_0(w[3], w[116], w[159], pars->GC_11, amp[814]); + FFV1_0(w[10], w[135], w[41], pars->GC_11, amp[815]); + FFV1_0(w[10], w[125], w[68], pars->GC_11, amp[816]); + FFV1_0(w[10], w[2], w[159], pars->GC_11, amp[817]); + FFV1_0(w[42], w[135], w[8], pars->GC_2, amp[818]); + FFV1_0(w[74], w[125], w[8], pars->GC_2, amp[819]); + FFV1_0(w[74], w[120], w[41], pars->GC_11, amp[820]); + FFV1_0(w[42], w[120], w[68], pars->GC_11, amp[821]); + FFV1_0(w[3], w[120], w[159], pars->GC_11, amp[822]); + FFV1_0(w[18], w[135], w[41], pars->GC_11, amp[823]); + FFV1_0(w[18], w[125], w[68], pars->GC_11, amp[824]); + FFV1_0(w[18], w[2], w[159], pars->GC_11, amp[825]); + FFV2_5_0(w[42], w[135], w[17], pars->GC_51, pars->GC_58, amp[826]); + FFV2_5_0(w[74], w[125], w[17], pars->GC_51, pars->GC_58, amp[827]); + FFV1_0(w[42], w[130], w[7], pars->GC_11, amp[828]); + FFV1_0(w[42], w[118], w[4], pars->GC_11, amp[829]); + VVV1_0(w[111], w[7], w[144], pars->GC_10, amp[830]); + FFV1_0(w[3], w[118], w[111], pars->GC_11, amp[831]); + VVV1_0(w[4], w[43], w[144], pars->GC_10, amp[832]); + FFV1_0(w[3], w[130], w[43], pars->GC_11, amp[833]); + FFV1_0(w[3], w[116], w[160], pars->GC_11, amp[834]); + FFV1_0(w[3], w[116], w[161], pars->GC_11, amp[835]); + FFV1_0(w[3], w[116], w[162], pars->GC_11, amp[836]); + FFV1_0(w[57], w[125], w[7], pars->GC_11, amp[837]); + FFV1_0(w[13], w[125], w[4], pars->GC_11, amp[838]); + VVV1_0(w[111], w[7], w[148], pars->GC_10, amp[839]); + FFV1_0(w[13], w[2], w[111], pars->GC_11, amp[840]); + VVV1_0(w[4], w[43], w[148], pars->GC_10, amp[841]); + FFV1_0(w[57], w[2], w[43], pars->GC_11, amp[842]); + FFV1_0(w[10], w[2], w[160], pars->GC_11, amp[843]); + FFV1_0(w[10], w[2], w[161], pars->GC_11, amp[844]); + FFV1_0(w[10], w[2], w[162], pars->GC_11, amp[845]); + FFV1_0(w[42], w[131], w[7], pars->GC_11, amp[846]); + FFV1_0(w[42], w[122], w[4], pars->GC_11, amp[847]); + VVV1_0(w[111], w[7], w[149], pars->GC_10, amp[848]); + FFV1_0(w[3], w[122], w[111], pars->GC_11, amp[849]); + VVV1_0(w[4], w[43], w[149], pars->GC_10, amp[850]); + FFV1_0(w[3], w[131], w[43], pars->GC_11, amp[851]); + FFV1_0(w[3], w[120], w[160], pars->GC_11, amp[852]); + FFV1_0(w[3], w[120], w[161], pars->GC_11, amp[853]); + FFV1_0(w[3], w[120], w[162], pars->GC_11, amp[854]); + FFV1_0(w[59], w[125], w[7], pars->GC_11, amp[855]); + FFV1_0(w[20], w[125], w[4], pars->GC_11, amp[856]); + VVV1_0(w[111], w[7], w[150], pars->GC_10, amp[857]); + FFV1_0(w[20], w[2], w[111], pars->GC_11, amp[858]); + VVV1_0(w[4], w[43], w[150], pars->GC_10, amp[859]); + FFV1_0(w[59], w[2], w[43], pars->GC_11, amp[860]); + FFV1_0(w[18], w[2], w[160], pars->GC_11, amp[861]); + FFV1_0(w[18], w[2], w[161], pars->GC_11, amp[862]); + FFV1_0(w[18], w[2], w[162], pars->GC_11, amp[863]); + FFV1_0(w[45], w[130], w[6], pars->GC_11, amp[864]); + FFV1_0(w[45], w[117], w[4], pars->GC_11, amp[865]); + VVV1_0(w[96], w[6], w[144], pars->GC_10, amp[866]); + FFV1_0(w[3], w[117], w[96], pars->GC_11, amp[867]); + VVV1_0(w[4], w[46], w[144], pars->GC_10, amp[868]); + FFV1_0(w[3], w[130], w[46], pars->GC_11, amp[869]); + FFV1_0(w[3], w[116], w[163], pars->GC_11, amp[870]); + FFV1_0(w[3], w[116], w[164], pars->GC_11, amp[871]); + FFV1_0(w[3], w[116], w[165], pars->GC_11, amp[872]); + FFV1_0(w[57], w[127], w[6], pars->GC_11, amp[873]); + FFV1_0(w[12], w[127], w[4], pars->GC_11, amp[874]); + VVV1_0(w[96], w[6], w[148], pars->GC_10, amp[875]); + FFV1_0(w[12], w[2], w[96], pars->GC_11, amp[876]); + VVV1_0(w[4], w[46], w[148], pars->GC_10, amp[877]); + FFV1_0(w[57], w[2], w[46], pars->GC_11, amp[878]); + FFV1_0(w[10], w[2], w[163], pars->GC_11, amp[879]); + FFV1_0(w[10], w[2], w[164], pars->GC_11, amp[880]); + FFV1_0(w[10], w[2], w[165], pars->GC_11, amp[881]); + FFV1_0(w[45], w[131], w[6], pars->GC_11, amp[882]); + FFV1_0(w[45], w[121], w[4], pars->GC_11, amp[883]); + VVV1_0(w[96], w[6], w[149], pars->GC_10, amp[884]); + FFV1_0(w[3], w[121], w[96], pars->GC_11, amp[885]); + VVV1_0(w[4], w[46], w[149], pars->GC_10, amp[886]); + FFV1_0(w[3], w[131], w[46], pars->GC_11, amp[887]); + FFV1_0(w[3], w[120], w[163], pars->GC_11, amp[888]); + FFV1_0(w[3], w[120], w[164], pars->GC_11, amp[889]); + FFV1_0(w[3], w[120], w[165], pars->GC_11, amp[890]); + FFV1_0(w[59], w[127], w[6], pars->GC_11, amp[891]); + FFV1_0(w[19], w[127], w[4], pars->GC_11, amp[892]); + VVV1_0(w[96], w[6], w[150], pars->GC_10, amp[893]); + FFV1_0(w[19], w[2], w[96], pars->GC_11, amp[894]); + VVV1_0(w[4], w[46], w[150], pars->GC_10, amp[895]); + FFV1_0(w[59], w[2], w[46], pars->GC_11, amp[896]); + FFV1_0(w[18], w[2], w[163], pars->GC_11, amp[897]); + FFV1_0(w[18], w[2], w[164], pars->GC_11, amp[898]); + FFV1_0(w[18], w[2], w[165], pars->GC_11, amp[899]); + FFV1_0(w[48], w[130], w[5], pars->GC_11, amp[900]); + FFV1_0(w[48], w[119], w[4], pars->GC_11, amp[901]); + VVV1_0(w[77], w[5], w[144], pars->GC_10, amp[902]); + FFV1_0(w[3], w[119], w[77], pars->GC_11, amp[903]); + VVV1_0(w[4], w[49], w[144], pars->GC_10, amp[904]); + FFV1_0(w[3], w[130], w[49], pars->GC_11, amp[905]); + FFV1_0(w[3], w[116], w[166], pars->GC_11, amp[906]); + FFV1_0(w[3], w[116], w[167], pars->GC_11, amp[907]); + FFV1_0(w[3], w[116], w[168], pars->GC_11, amp[908]); + FFV1_0(w[57], w[129], w[5], pars->GC_11, amp[909]); + FFV1_0(w[15], w[129], w[4], pars->GC_11, amp[910]); + VVV1_0(w[77], w[5], w[148], pars->GC_10, amp[911]); + FFV1_0(w[15], w[2], w[77], pars->GC_11, amp[912]); + VVV1_0(w[4], w[49], w[148], pars->GC_10, amp[913]); + FFV1_0(w[57], w[2], w[49], pars->GC_11, amp[914]); + FFV1_0(w[10], w[2], w[166], pars->GC_11, amp[915]); + FFV1_0(w[10], w[2], w[167], pars->GC_11, amp[916]); + FFV1_0(w[10], w[2], w[168], pars->GC_11, amp[917]); + FFV1_0(w[48], w[131], w[5], pars->GC_11, amp[918]); + FFV1_0(w[48], w[123], w[4], pars->GC_11, amp[919]); + VVV1_0(w[77], w[5], w[149], pars->GC_10, amp[920]); + FFV1_0(w[3], w[123], w[77], pars->GC_11, amp[921]); + VVV1_0(w[4], w[49], w[149], pars->GC_10, amp[922]); + FFV1_0(w[3], w[131], w[49], pars->GC_11, amp[923]); + FFV1_0(w[3], w[120], w[166], pars->GC_11, amp[924]); + FFV1_0(w[3], w[120], w[167], pars->GC_11, amp[925]); + FFV1_0(w[3], w[120], w[168], pars->GC_11, amp[926]); + FFV1_0(w[59], w[129], w[5], pars->GC_11, amp[927]); + FFV1_0(w[21], w[129], w[4], pars->GC_11, amp[928]); + VVV1_0(w[77], w[5], w[150], pars->GC_10, amp[929]); + FFV1_0(w[21], w[2], w[77], pars->GC_11, amp[930]); + VVV1_0(w[4], w[49], w[150], pars->GC_10, amp[931]); + FFV1_0(w[59], w[2], w[49], pars->GC_11, amp[932]); + FFV1_0(w[18], w[2], w[166], pars->GC_11, amp[933]); + FFV1_0(w[18], w[2], w[167], pars->GC_11, amp[934]); + FFV1_0(w[18], w[2], w[168], pars->GC_11, amp[935]); + FFV1_0(w[169], w[116], w[7], pars->GC_11, amp[936]); + FFV1_0(w[170], w[116], w[7], pars->GC_11, amp[937]); + FFV1_0(w[171], w[116], w[7], pars->GC_11, amp[938]); + FFV1_0(w[3], w[116], w[172], pars->GC_11, amp[939]); + FFV1_0(w[3], w[116], w[173], pars->GC_11, amp[940]); + FFV1_0(w[3], w[116], w[174], pars->GC_11, amp[941]); + FFV1_0(w[10], w[175], w[7], pars->GC_11, amp[942]); + FFV1_0(w[10], w[176], w[7], pars->GC_11, amp[943]); + FFV1_0(w[10], w[177], w[7], pars->GC_11, amp[944]); + FFV1_0(w[10], w[2], w[172], pars->GC_11, amp[945]); + FFV1_0(w[10], w[2], w[173], pars->GC_11, amp[946]); + FFV1_0(w[10], w[2], w[174], pars->GC_11, amp[947]); + FFV1_0(w[169], w[120], w[7], pars->GC_11, amp[948]); + FFV1_0(w[170], w[120], w[7], pars->GC_11, amp[949]); + FFV1_0(w[171], w[120], w[7], pars->GC_11, amp[950]); + FFV1_0(w[3], w[120], w[172], pars->GC_11, amp[951]); + FFV1_0(w[3], w[120], w[173], pars->GC_11, amp[952]); + FFV1_0(w[3], w[120], w[174], pars->GC_11, amp[953]); + FFV1_0(w[18], w[175], w[7], pars->GC_11, amp[954]); + FFV1_0(w[18], w[176], w[7], pars->GC_11, amp[955]); + FFV1_0(w[18], w[177], w[7], pars->GC_11, amp[956]); + FFV1_0(w[18], w[2], w[172], pars->GC_11, amp[957]); + FFV1_0(w[18], w[2], w[173], pars->GC_11, amp[958]); + FFV1_0(w[18], w[2], w[174], pars->GC_11, amp[959]); + FFV1_0(w[178], w[116], w[6], pars->GC_11, amp[960]); + FFV1_0(w[179], w[116], w[6], pars->GC_11, amp[961]); + FFV1_0(w[180], w[116], w[6], pars->GC_11, amp[962]); + FFV1_0(w[3], w[116], w[181], pars->GC_11, amp[963]); + FFV1_0(w[3], w[116], w[182], pars->GC_11, amp[964]); + FFV1_0(w[3], w[116], w[183], pars->GC_11, amp[965]); + FFV1_0(w[10], w[184], w[6], pars->GC_11, amp[966]); + FFV1_0(w[10], w[185], w[6], pars->GC_11, amp[967]); + FFV1_0(w[10], w[186], w[6], pars->GC_11, amp[968]); + FFV1_0(w[10], w[2], w[181], pars->GC_11, amp[969]); + FFV1_0(w[10], w[2], w[182], pars->GC_11, amp[970]); + FFV1_0(w[10], w[2], w[183], pars->GC_11, amp[971]); + FFV1_0(w[178], w[120], w[6], pars->GC_11, amp[972]); + FFV1_0(w[179], w[120], w[6], pars->GC_11, amp[973]); + FFV1_0(w[180], w[120], w[6], pars->GC_11, amp[974]); + FFV1_0(w[3], w[120], w[181], pars->GC_11, amp[975]); + FFV1_0(w[3], w[120], w[182], pars->GC_11, amp[976]); + FFV1_0(w[3], w[120], w[183], pars->GC_11, amp[977]); + FFV1_0(w[18], w[184], w[6], pars->GC_11, amp[978]); + FFV1_0(w[18], w[185], w[6], pars->GC_11, amp[979]); + FFV1_0(w[18], w[186], w[6], pars->GC_11, amp[980]); + FFV1_0(w[18], w[2], w[181], pars->GC_11, amp[981]); + FFV1_0(w[18], w[2], w[182], pars->GC_11, amp[982]); + FFV1_0(w[18], w[2], w[183], pars->GC_11, amp[983]); + FFV1_0(w[187], w[116], w[5], pars->GC_11, amp[984]); + FFV1_0(w[188], w[116], w[5], pars->GC_11, amp[985]); + FFV1_0(w[189], w[116], w[5], pars->GC_11, amp[986]); + FFV1_0(w[3], w[116], w[190], pars->GC_11, amp[987]); + FFV1_0(w[3], w[116], w[191], pars->GC_11, amp[988]); + FFV1_0(w[3], w[116], w[192], pars->GC_11, amp[989]); + FFV1_0(w[10], w[193], w[5], pars->GC_11, amp[990]); + FFV1_0(w[10], w[194], w[5], pars->GC_11, amp[991]); + FFV1_0(w[10], w[195], w[5], pars->GC_11, amp[992]); + FFV1_0(w[10], w[2], w[190], pars->GC_11, amp[993]); + FFV1_0(w[10], w[2], w[191], pars->GC_11, amp[994]); + FFV1_0(w[10], w[2], w[192], pars->GC_11, amp[995]); + FFV1_0(w[187], w[120], w[5], pars->GC_11, amp[996]); + FFV1_0(w[188], w[120], w[5], pars->GC_11, amp[997]); + FFV1_0(w[189], w[120], w[5], pars->GC_11, amp[998]); + FFV1_0(w[3], w[120], w[190], pars->GC_11, amp[999]); + FFV1_0(w[3], w[120], w[191], pars->GC_11, amp[1000]); + FFV1_0(w[3], w[120], w[192], pars->GC_11, amp[1001]); + FFV1_0(w[18], w[193], w[5], pars->GC_11, amp[1002]); + FFV1_0(w[18], w[194], w[5], pars->GC_11, amp[1003]); + FFV1_0(w[18], w[195], w[5], pars->GC_11, amp[1004]); + FFV1_0(w[18], w[2], w[190], pars->GC_11, amp[1005]); + FFV1_0(w[18], w[2], w[191], pars->GC_11, amp[1006]); + FFV1_0(w[18], w[2], w[192], pars->GC_11, amp[1007]); + FFV1_0(w[196], w[116], w[4], pars->GC_11, amp[1008]); + FFV1_0(w[197], w[116], w[4], pars->GC_11, amp[1009]); + FFV1_0(w[198], w[116], w[4], pars->GC_11, amp[1010]); + FFV1_0(w[3], w[116], w[199], pars->GC_11, amp[1011]); + FFV1_0(w[3], w[116], w[200], pars->GC_11, amp[1012]); + FFV1_0(w[3], w[116], w[201], pars->GC_11, amp[1013]); + FFV1_0(w[10], w[202], w[4], pars->GC_11, amp[1014]); + FFV1_0(w[10], w[203], w[4], pars->GC_11, amp[1015]); + FFV1_0(w[10], w[204], w[4], pars->GC_11, amp[1016]); + FFV1_0(w[10], w[2], w[199], pars->GC_11, amp[1017]); + FFV1_0(w[10], w[2], w[200], pars->GC_11, amp[1018]); + FFV1_0(w[10], w[2], w[201], pars->GC_11, amp[1019]); + FFV1_0(w[196], w[120], w[4], pars->GC_11, amp[1020]); + FFV1_0(w[197], w[120], w[4], pars->GC_11, amp[1021]); + FFV1_0(w[198], w[120], w[4], pars->GC_11, amp[1022]); + FFV1_0(w[3], w[120], w[199], pars->GC_11, amp[1023]); + FFV1_0(w[3], w[120], w[200], pars->GC_11, amp[1024]); + FFV1_0(w[3], w[120], w[201], pars->GC_11, amp[1025]); + FFV1_0(w[18], w[202], w[4], pars->GC_11, amp[1026]); + FFV1_0(w[18], w[203], w[4], pars->GC_11, amp[1027]); + FFV1_0(w[18], w[204], w[4], pars->GC_11, amp[1028]); + FFV1_0(w[18], w[2], w[199], pars->GC_11, amp[1029]); + FFV1_0(w[18], w[2], w[200], pars->GC_11, amp[1030]); + FFV1_0(w[18], w[2], w[201], pars->GC_11, amp[1031]); + +} +double eeuugggg::matrix_1_epem_uuxgggg() +{ +// int i, j; + // Local variables +// const int ngraphs = 1032; + const int ncolor = 24; + std::complex ztemp; + std::complex jamp[ncolor]; + // The color matrix; + //static const double denom[ncolor] = {54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + // 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54}; + /*static const double cf[ncolor][ncolor] = {{512, -64, -64, 8, 8, 80, -64, 8, + 8, -1, -1, -10, 8, -1, 80, -10, 71, 62, -1, -10, -10, 62, 62, -28}, {-64, + 512, 8, 80, -64, 8, 8, -64, -1, -10, 8, -1, -1, -10, -10, 62, 62, -28, 8, + -1, 80, -10, 71, 62}, {-64, 8, 512, -64, 80, 8, 8, -1, 80, -10, 71, 62, + -64, 8, 8, -1, -1, -10, -10, -1, 62, -28, -10, 62}, {8, 80, -64, 512, 8, + -64, -1, -10, -10, 62, 62, -28, 8, -64, -1, -10, 8, -1, -1, 8, 71, 62, + 80, -10}, {8, -64, 80, 8, 512, -64, -1, 8, 71, 62, 80, -10, -10, -1, 62, + -28, -10, 62, -64, 8, 8, -1, -1, -10}, {80, 8, 8, -64, -64, 512, -10, -1, + 62, -28, -10, 62, -1, 8, 71, 62, 80, -10, 8, -64, -1, -10, 8, -1}, {-64, + 8, 8, -1, -1, -10, 512, -64, -64, 8, 8, 80, 80, -10, 8, -1, 62, 71, -10, + 62, -1, -10, -28, 62}, {8, -64, -1, -10, 8, -1, -64, 512, 8, 80, -64, 8, + -10, 62, -1, -10, -28, 62, 80, -10, 8, -1, 62, 71}, {8, -1, 80, -10, 71, + 62, -64, 8, 512, -64, 80, 8, 8, -1, -64, 8, -10, -1, 62, -28, -10, -1, + 62, -10}, {-1, -10, -10, 62, 62, -28, 8, 80, -64, 512, 8, -64, -1, -10, + 8, -64, -1, 8, 71, 62, -1, 8, -10, 80}, {-1, 8, 71, 62, 80, -10, 8, -64, + 80, 8, 512, -64, 62, -28, -10, -1, 62, -10, 8, -1, -64, 8, -10, -1}, + {-10, -1, 62, -28, -10, 62, 80, 8, 8, -64, -64, 512, 71, 62, -1, 8, -10, + 80, -1, -10, 8, -64, -1, 8}, {8, -1, -64, 8, -10, -1, 80, -10, 8, -1, 62, + 71, 512, -64, -64, 8, 8, 80, 62, -10, -28, 62, -1, -10}, {-1, -10, 8, + -64, -1, 8, -10, 62, -1, -10, -28, 62, -64, 512, 8, 80, -64, 8, -10, 80, + 62, 71, 8, -1}, {80, -10, 8, -1, 62, 71, 8, -1, -64, 8, -10, -1, -64, 8, + 512, -64, 80, 8, -28, 62, 62, -10, -10, -1}, {-10, 62, -1, -10, -28, 62, + -1, -10, 8, -64, -1, 8, 8, 80, -64, 512, 8, -64, 62, 71, -10, 80, -1, 8}, + {71, 62, -1, 8, -10, 80, 62, -28, -10, -1, 62, -10, 8, -64, 80, 8, 512, + -64, -1, 8, -10, -1, -64, 8}, {62, -28, -10, -1, 62, -10, 71, 62, -1, 8, + -10, 80, 80, 8, 8, -64, -64, 512, -10, -1, -1, 8, 8, -64}, {-1, 8, -10, + -1, -64, 8, -10, 80, 62, 71, 8, -1, 62, -10, -28, 62, -1, -10, 512, -64, + -64, 8, 8, 80}, {-10, -1, -1, 8, 8, -64, 62, -10, -28, 62, -1, -10, -10, + 80, 62, 71, 8, -1, -64, 512, 8, 80, -64, 8}, {-10, 80, 62, 71, 8, -1, -1, + 8, -10, -1, -64, 8, -28, 62, 62, -10, -10, -1, -64, 8, 512, -64, 80, 8}, + {62, -10, -28, 62, -1, -10, -10, -1, -1, 8, 8, -64, 62, 71, -10, 80, -1, + 8, 8, 80, -64, 512, 8, -64}, {62, 71, -10, 80, -1, 8, -28, 62, 62, -10, + -10, -1, -1, 8, -10, -1, -64, 8, 8, -64, 80, 8, 512, -64}, {-28, 62, 62, + -10, -10, -1, 62, 71, -10, 80, -1, 8, -10, -1, -1, 8, 8, -64, 80, 8, 8, + -64, -64, 512}}; + */ + + // Calculate color flows + jamp[0] = +amp[1] + amp[7] + amp[45] + amp[46] + amp[48] + amp[51] + amp[52] + + amp[54] - std::complex (0, 1) * amp[56] - std::complex + (0, 1) * amp[57] - std::complex (0, 1) * amp[58] - + std::complex (0, 1) * amp[59] - amp[61] - std::complex + (0, 1) * amp[62] - amp[64] - amp[67] - std::complex (0, 1) * + amp[68] - amp[70] - std::complex (0, 1) * amp[84] - amp[85] - + std::complex (0, 1) * amp[86] - amp[88] - std::complex + (0, 1) * amp[89] - std::complex (0, 1) * amp[90] - amp[91] - + std::complex (0, 1) * amp[92] - amp[94] - std::complex + (0, 1) * amp[95] + amp[98] - amp[96] + amp[101] - amp[99] + amp[104] - + amp[102] + amp[107] - amp[105] + amp[616] + amp[622] - + std::complex (0, 1) * amp[625] - amp[626] - std::complex + (0, 1) * amp[627] - amp[628] - std::complex (0, 1) * amp[629] - + std::complex (0, 1) * amp[631] - amp[632] - std::complex + (0, 1) * amp[633] - amp[634] - std::complex (0, 1) * amp[635] - + std::complex (0, 1) * amp[649] - amp[650] - amp[652] - + std::complex (0, 1) * amp[655] - amp[656] - amp[658] + amp[662] - + amp[660] + amp[665] - amp[663] + amp[668] - amp[666] + amp[671] - + amp[669] + std::complex (0, 1) * amp[674] - std::complex + (0, 1) * amp[680] + std::complex (0, 1) * amp[678] - + std::complex (0, 1) * amp[682] + std::complex (0, 1) * + amp[683] - amp[684] - std::complex (0, 1) * amp[689] + + std::complex (0, 1) * amp[687] + std::complex (0, 1) * + amp[692] - std::complex (0, 1) * amp[698] + std::complex + (0, 1) * amp[696] - std::complex (0, 1) * amp[700] + + std::complex (0, 1) * amp[701] - amp[702] - std::complex + (0, 1) * amp[707] + std::complex (0, 1) * amp[705] - amp[709] + + std::complex (0, 1) * amp[710] - amp[711] + std::complex + (0, 1) * amp[713] - amp[714] - amp[717] + std::complex (0, 1) * + amp[718] - amp[719] + std::complex (0, 1) * amp[721] - amp[722] + + std::complex (0, 1) * amp[830] + std::complex (0, 1) * + amp[832] - amp[833] - std::complex (0, 1) * amp[836] + + std::complex (0, 1) * amp[834] + std::complex (0, 1) * + amp[839] - amp[840] + std::complex (0, 1) * amp[841] - + std::complex (0, 1) * amp[845] + std::complex (0, 1) * + amp[843] + std::complex (0, 1) * amp[848] + std::complex + (0, 1) * amp[850] - amp[851] - std::complex (0, 1) * amp[854] + + std::complex (0, 1) * amp[852] + std::complex (0, 1) * + amp[857] - amp[858] + std::complex (0, 1) * amp[859] - + std::complex (0, 1) * amp[863] + std::complex (0, 1) * + amp[861] - std::complex (0, 1) * amp[900] + std::complex + (0, 1) * amp[904] - amp[905] - std::complex (0, 1) * amp[908] + + std::complex (0, 1) * amp[906] + std::complex (0, 1) * + amp[913] - std::complex (0, 1) * amp[917] + std::complex + (0, 1) * amp[915] - std::complex (0, 1) * amp[918] + + std::complex (0, 1) * amp[922] - amp[923] - std::complex + (0, 1) * amp[926] + std::complex (0, 1) * amp[924] + + std::complex (0, 1) * amp[931] - std::complex (0, 1) * + amp[935] + std::complex (0, 1) * amp[933] - std::complex + (0, 1) * amp[941] + std::complex (0, 1) * amp[939] + amp[944] - + amp[942] - std::complex (0, 1) * amp[947] + std::complex + (0, 1) * amp[945] - std::complex (0, 1) * amp[953] + + std::complex (0, 1) * amp[951] + amp[956] - amp[954] - + std::complex (0, 1) * amp[959] + std::complex (0, 1) * + amp[957] + amp[1010] - amp[1008] - std::complex (0, 1) * + amp[1013] + std::complex (0, 1) * amp[1011] - + std::complex (0, 1) * amp[1019] + std::complex (0, 1) * + amp[1017] + amp[1022] - amp[1020] - std::complex (0, 1) * + amp[1025] + std::complex (0, 1) * amp[1023] - + std::complex (0, 1) * amp[1031] + std::complex (0, 1) * + amp[1029]; + jamp[1] = +amp[0] + amp[6] + amp[29] + amp[30] + amp[32] + amp[35] + amp[36] + + amp[38] - std::complex (0, 1) * amp[40] - std::complex + (0, 1) * amp[41] - std::complex (0, 1) * amp[42] - + std::complex (0, 1) * amp[43] - amp[73] - std::complex + (0, 1) * amp[74] - amp[76] - amp[79] - std::complex (0, 1) * + amp[80] - amp[82] + std::complex (0, 1) * amp[84] + amp[85] + + std::complex (0, 1) * amp[86] + amp[88] + std::complex + (0, 1) * amp[89] + std::complex (0, 1) * amp[90] + amp[91] + + std::complex (0, 1) * amp[92] + amp[94] + std::complex + (0, 1) * amp[95] + amp[96] + amp[97] + amp[99] + amp[100] + amp[102] + + amp[103] + amp[105] + amp[106] + amp[556] + amp[562] - + std::complex (0, 1) * amp[565] - amp[566] - std::complex + (0, 1) * amp[567] - amp[568] - std::complex (0, 1) * amp[569] - + std::complex (0, 1) * amp[571] - amp[572] - std::complex + (0, 1) * amp[573] - amp[574] - std::complex (0, 1) * amp[575] - + std::complex (0, 1) * amp[589] - amp[590] - amp[592] - + std::complex (0, 1) * amp[595] - amp[596] - amp[598] + amp[602] - + amp[600] + amp[605] - amp[603] + amp[608] - amp[606] + amp[611] - + amp[609] + std::complex (0, 1) * amp[676] - std::complex + (0, 1) * amp[678] - std::complex (0, 1) * amp[679] - + std::complex (0, 1) * amp[681] + std::complex (0, 1) * + amp[685] - amp[686] - std::complex (0, 1) * amp[687] - + std::complex (0, 1) * amp[688] + std::complex (0, 1) * + amp[694] - std::complex (0, 1) * amp[696] - std::complex + (0, 1) * amp[697] - std::complex (0, 1) * amp[699] + + std::complex (0, 1) * amp[703] - amp[704] - std::complex + (0, 1) * amp[705] - std::complex (0, 1) * amp[706] + amp[709] - + std::complex (0, 1) * amp[710] + amp[711] - std::complex + (0, 1) * amp[713] + amp[714] + amp[717] - std::complex (0, 1) * + amp[718] + amp[719] - std::complex (0, 1) * amp[721] + amp[722] + + std::complex (0, 1) * amp[866] + std::complex (0, 1) * + amp[868] - amp[869] - std::complex (0, 1) * amp[872] + + std::complex (0, 1) * amp[870] + std::complex (0, 1) * + amp[875] - amp[876] + std::complex (0, 1) * amp[877] - + std::complex (0, 1) * amp[881] + std::complex (0, 1) * + amp[879] + std::complex (0, 1) * amp[884] + std::complex + (0, 1) * amp[886] - amp[887] - std::complex (0, 1) * amp[890] + + std::complex (0, 1) * amp[888] + std::complex (0, 1) * + amp[893] - amp[894] + std::complex (0, 1) * amp[895] - + std::complex (0, 1) * amp[899] + std::complex (0, 1) * + amp[897] + std::complex (0, 1) * amp[900] - std::complex + (0, 1) * amp[904] + amp[905] + std::complex (0, 1) * amp[908] - + std::complex (0, 1) * amp[906] - std::complex (0, 1) * + amp[913] + std::complex (0, 1) * amp[917] - std::complex + (0, 1) * amp[915] + std::complex (0, 1) * amp[918] - + std::complex (0, 1) * amp[922] + amp[923] + std::complex + (0, 1) * amp[926] - std::complex (0, 1) * amp[924] - + std::complex (0, 1) * amp[931] + std::complex (0, 1) * + amp[935] - std::complex (0, 1) * amp[933] - std::complex + (0, 1) * amp[965] + std::complex (0, 1) * amp[963] + amp[968] - + amp[966] - std::complex (0, 1) * amp[971] + std::complex + (0, 1) * amp[969] - std::complex (0, 1) * amp[977] + + std::complex (0, 1) * amp[975] + amp[980] - amp[978] - + std::complex (0, 1) * amp[983] + std::complex (0, 1) * + amp[981] + amp[1008] + amp[1009] - std::complex (0, 1) * + amp[1011] - std::complex (0, 1) * amp[1012] - + std::complex (0, 1) * amp[1017] - std::complex (0, 1) * + amp[1018] + amp[1020] + amp[1021] - std::complex (0, 1) * + amp[1023] - std::complex (0, 1) * amp[1024] - + std::complex (0, 1) * amp[1029] - std::complex (0, 1) * + amp[1030]; + jamp[2] = +amp[3] + amp[9] + amp[44] + amp[47] + amp[49] + amp[50] + amp[53] + + amp[55] + std::complex (0, 1) * amp[56] + std::complex + (0, 1) * amp[57] + std::complex (0, 1) * amp[58] + + std::complex (0, 1) * amp[59] + amp[61] + std::complex + (0, 1) * amp[62] + amp[64] + amp[67] + std::complex (0, 1) * + amp[68] + amp[70] - std::complex (0, 1) * amp[72] + amp[73] - + std::complex (0, 1) * amp[75] + amp[76] - std::complex + (0, 1) * amp[77] - std::complex (0, 1) * amp[78] + amp[79] - + std::complex (0, 1) * amp[81] + amp[82] - std::complex + (0, 1) * amp[83] - amp[98] - amp[97] - amp[101] - amp[100] - amp[104] - + amp[103] - amp[107] - amp[106] + amp[614] + amp[620] - + std::complex (0, 1) * amp[637] - amp[638] - std::complex + (0, 1) * amp[639] - amp[640] - std::complex (0, 1) * amp[641] - + std::complex (0, 1) * amp[643] - amp[644] - std::complex + (0, 1) * amp[645] - amp[646] - std::complex (0, 1) * amp[647] + + std::complex (0, 1) * amp[649] + amp[650] + amp[652] + + std::complex (0, 1) * amp[655] + amp[656] + amp[658] + amp[660] + + amp[661] + amp[663] + amp[664] + amp[666] + amp[667] + amp[669] + + amp[670] + std::complex (0, 1) * amp[726] - std::complex + (0, 1) * amp[732] + std::complex (0, 1) * amp[730] - + std::complex (0, 1) * amp[734] + std::complex (0, 1) * + amp[735] - amp[736] - std::complex (0, 1) * amp[741] + + std::complex (0, 1) * amp[739] + std::complex (0, 1) * + amp[744] - std::complex (0, 1) * amp[750] + std::complex + (0, 1) * amp[748] - std::complex (0, 1) * amp[752] + + std::complex (0, 1) * amp[753] - amp[754] - std::complex + (0, 1) * amp[759] + std::complex (0, 1) * amp[757] - amp[761] + + std::complex (0, 1) * amp[762] - amp[763] + std::complex + (0, 1) * amp[765] - amp[766] - amp[769] + std::complex (0, 1) * + amp[770] - amp[771] + std::complex (0, 1) * amp[773] - amp[774] - + std::complex (0, 1) * amp[830] - std::complex (0, 1) * + amp[832] + amp[833] + std::complex (0, 1) * amp[836] - + std::complex (0, 1) * amp[834] - std::complex (0, 1) * + amp[839] + amp[840] - std::complex (0, 1) * amp[841] + + std::complex (0, 1) * amp[845] - std::complex (0, 1) * + amp[843] - std::complex (0, 1) * amp[848] - std::complex + (0, 1) * amp[850] + amp[851] + std::complex (0, 1) * amp[854] - + std::complex (0, 1) * amp[852] - std::complex (0, 1) * + amp[857] + amp[858] - std::complex (0, 1) * amp[859] + + std::complex (0, 1) * amp[863] - std::complex (0, 1) * + amp[861] - std::complex (0, 1) * amp[864] - std::complex + (0, 1) * amp[868] + amp[869] - std::complex (0, 1) * amp[870] - + std::complex (0, 1) * amp[871] - std::complex (0, 1) * + amp[877] - std::complex (0, 1) * amp[879] - std::complex + (0, 1) * amp[880] - std::complex (0, 1) * amp[882] - + std::complex (0, 1) * amp[886] + amp[887] - std::complex + (0, 1) * amp[888] - std::complex (0, 1) * amp[889] - + std::complex (0, 1) * amp[895] - std::complex (0, 1) * + amp[897] - std::complex (0, 1) * amp[898] - std::complex + (0, 1) * amp[939] - std::complex (0, 1) * amp[940] + amp[942] + + amp[943] - std::complex (0, 1) * amp[945] - std::complex + (0, 1) * amp[946] - std::complex (0, 1) * amp[951] - + std::complex (0, 1) * amp[952] + amp[954] + amp[955] - + std::complex (0, 1) * amp[957] - std::complex (0, 1) * + amp[958] - amp[1010] - amp[1009] + std::complex (0, 1) * + amp[1013] + std::complex (0, 1) * amp[1012] + + std::complex (0, 1) * amp[1019] + std::complex (0, 1) * + amp[1018] - amp[1022] - amp[1021] + std::complex (0, 1) * + amp[1025] + std::complex (0, 1) * amp[1024] + + std::complex (0, 1) * amp[1031] + std::complex (0, 1) * + amp[1030]; + jamp[3] = +amp[2] + amp[8] + amp[13] + amp[14] + amp[16] + amp[19] + amp[20] + + amp[22] - std::complex (0, 1) * amp[24] - std::complex + (0, 1) * amp[25] - std::complex (0, 1) * amp[26] - + std::complex (0, 1) * amp[27] + std::complex (0, 1) * + amp[72] - amp[73] + std::complex (0, 1) * amp[75] - amp[76] + + std::complex (0, 1) * amp[77] + std::complex (0, 1) * + amp[78] - amp[79] + std::complex (0, 1) * amp[81] - amp[82] + + std::complex (0, 1) * amp[83] + amp[85] - std::complex + (0, 1) * amp[87] + amp[88] + amp[91] - std::complex (0, 1) * + amp[93] + amp[94] + amp[96] + amp[97] + amp[99] + amp[100] + amp[102] + + amp[103] + amp[105] + amp[106] + amp[496] + amp[502] - + std::complex (0, 1) * amp[505] - amp[506] - std::complex + (0, 1) * amp[507] - amp[508] - std::complex (0, 1) * amp[509] - + std::complex (0, 1) * amp[511] - amp[512] - std::complex + (0, 1) * amp[513] - amp[514] - std::complex (0, 1) * amp[515] - + std::complex (0, 1) * amp[529] - amp[530] - amp[532] - + std::complex (0, 1) * amp[535] - amp[536] - amp[538] + amp[542] - + amp[540] + amp[545] - amp[543] + amp[548] - amp[546] + amp[551] - + amp[549] + std::complex (0, 1) * amp[728] - std::complex + (0, 1) * amp[730] - std::complex (0, 1) * amp[731] - + std::complex (0, 1) * amp[733] + std::complex (0, 1) * + amp[737] - amp[738] - std::complex (0, 1) * amp[739] - + std::complex (0, 1) * amp[740] + std::complex (0, 1) * + amp[746] - std::complex (0, 1) * amp[748] - std::complex + (0, 1) * amp[749] - std::complex (0, 1) * amp[751] + + std::complex (0, 1) * amp[755] - amp[756] - std::complex + (0, 1) * amp[757] - std::complex (0, 1) * amp[758] + amp[761] - + std::complex (0, 1) * amp[762] + amp[763] - std::complex + (0, 1) * amp[765] + amp[766] + amp[769] - std::complex (0, 1) * + amp[770] + amp[771] - std::complex (0, 1) * amp[773] + amp[774] + + std::complex (0, 1) * amp[864] + std::complex (0, 1) * + amp[868] - amp[869] + std::complex (0, 1) * amp[870] + + std::complex (0, 1) * amp[871] + std::complex (0, 1) * + amp[877] + std::complex (0, 1) * amp[879] + std::complex + (0, 1) * amp[880] + std::complex (0, 1) * amp[882] + + std::complex (0, 1) * amp[886] - amp[887] + std::complex + (0, 1) * amp[888] + std::complex (0, 1) * amp[889] + + std::complex (0, 1) * amp[895] + std::complex (0, 1) * + amp[897] + std::complex (0, 1) * amp[898] + std::complex + (0, 1) * amp[902] - std::complex (0, 1) * amp[904] + amp[905] - + std::complex (0, 1) * amp[906] - std::complex (0, 1) * + amp[907] + std::complex (0, 1) * amp[911] - amp[912] - + std::complex (0, 1) * amp[913] - std::complex (0, 1) * + amp[915] - std::complex (0, 1) * amp[916] + std::complex + (0, 1) * amp[920] - std::complex (0, 1) * amp[922] + amp[923] - + std::complex (0, 1) * amp[924] - std::complex (0, 1) * + amp[925] + std::complex (0, 1) * amp[929] - amp[930] - + std::complex (0, 1) * amp[931] - std::complex (0, 1) * + amp[933] - std::complex (0, 1) * amp[934] - std::complex + (0, 1) * amp[989] + std::complex (0, 1) * amp[987] + amp[992] - + amp[990] - std::complex (0, 1) * amp[995] + std::complex + (0, 1) * amp[993] - std::complex (0, 1) * amp[1001] + + std::complex (0, 1) * amp[999] + amp[1004] - amp[1002] - + std::complex (0, 1) * amp[1007] + std::complex (0, 1) * + amp[1005] + amp[1008] + amp[1009] - std::complex (0, 1) * + amp[1011] - std::complex (0, 1) * amp[1012] - + std::complex (0, 1) * amp[1017] - std::complex (0, 1) * + amp[1018] + amp[1020] + amp[1021] - std::complex (0, 1) * + amp[1023] - std::complex (0, 1) * amp[1024] - + std::complex (0, 1) * amp[1029] - std::complex (0, 1) * + amp[1030]; + jamp[4] = +amp[5] + amp[11] + amp[28] + amp[31] + amp[33] + amp[34] + amp[37] + + amp[39] + std::complex (0, 1) * amp[40] + std::complex + (0, 1) * amp[41] + std::complex (0, 1) * amp[42] + + std::complex (0, 1) * amp[43] - std::complex (0, 1) * + amp[60] + amp[61] - std::complex (0, 1) * amp[63] + amp[64] - + std::complex (0, 1) * amp[65] - std::complex (0, 1) * + amp[66] + amp[67] - std::complex (0, 1) * amp[69] + amp[70] - + std::complex (0, 1) * amp[71] + amp[73] + std::complex + (0, 1) * amp[74] + amp[76] + amp[79] + std::complex (0, 1) * + amp[80] + amp[82] - amp[98] - amp[97] - amp[101] - amp[100] - amp[104] - + amp[103] - amp[107] - amp[106] + amp[554] + amp[560] - + std::complex (0, 1) * amp[577] - amp[578] - std::complex + (0, 1) * amp[579] - amp[580] - std::complex (0, 1) * amp[581] - + std::complex (0, 1) * amp[583] - amp[584] - std::complex + (0, 1) * amp[585] - amp[586] - std::complex (0, 1) * amp[587] + + std::complex (0, 1) * amp[589] + amp[590] + amp[592] + + std::complex (0, 1) * amp[595] + amp[596] + amp[598] + amp[600] + + amp[601] + amp[603] + amp[604] + amp[606] + amp[607] + amp[609] + + amp[610] + std::complex (0, 1) * amp[778] - std::complex + (0, 1) * amp[784] + std::complex (0, 1) * amp[782] - + std::complex (0, 1) * amp[786] + std::complex (0, 1) * + amp[787] - amp[788] - std::complex (0, 1) * amp[793] + + std::complex (0, 1) * amp[791] + std::complex (0, 1) * + amp[796] - std::complex (0, 1) * amp[802] + std::complex + (0, 1) * amp[800] - std::complex (0, 1) * amp[804] + + std::complex (0, 1) * amp[805] - amp[806] - std::complex + (0, 1) * amp[811] + std::complex (0, 1) * amp[809] - amp[813] + + std::complex (0, 1) * amp[814] - amp[815] + std::complex + (0, 1) * amp[817] - amp[818] - amp[821] + std::complex (0, 1) * + amp[822] - amp[823] + std::complex (0, 1) * amp[825] - amp[826] - + std::complex (0, 1) * amp[828] - std::complex (0, 1) * + amp[832] + amp[833] - std::complex (0, 1) * amp[834] - + std::complex (0, 1) * amp[835] - std::complex (0, 1) * + amp[841] - std::complex (0, 1) * amp[843] - std::complex + (0, 1) * amp[844] - std::complex (0, 1) * amp[846] - + std::complex (0, 1) * amp[850] + amp[851] - std::complex + (0, 1) * amp[852] - std::complex (0, 1) * amp[853] - + std::complex (0, 1) * amp[859] - std::complex (0, 1) * + amp[861] - std::complex (0, 1) * amp[862] - std::complex + (0, 1) * amp[866] - std::complex (0, 1) * amp[868] + amp[869] + + std::complex (0, 1) * amp[872] - std::complex (0, 1) * + amp[870] - std::complex (0, 1) * amp[875] + amp[876] - + std::complex (0, 1) * amp[877] + std::complex (0, 1) * + amp[881] - std::complex (0, 1) * amp[879] - std::complex + (0, 1) * amp[884] - std::complex (0, 1) * amp[886] + amp[887] + + std::complex (0, 1) * amp[890] - std::complex (0, 1) * + amp[888] - std::complex (0, 1) * amp[893] + amp[894] - + std::complex (0, 1) * amp[895] + std::complex (0, 1) * + amp[899] - std::complex (0, 1) * amp[897] - std::complex + (0, 1) * amp[963] - std::complex (0, 1) * amp[964] + amp[966] + + amp[967] - std::complex (0, 1) * amp[969] - std::complex + (0, 1) * amp[970] - std::complex (0, 1) * amp[975] - + std::complex (0, 1) * amp[976] + amp[978] + amp[979] - + std::complex (0, 1) * amp[981] - std::complex (0, 1) * + amp[982] - amp[1010] - amp[1009] + std::complex (0, 1) * + amp[1013] + std::complex (0, 1) * amp[1012] + + std::complex (0, 1) * amp[1019] + std::complex (0, 1) * + amp[1018] - amp[1022] - amp[1021] + std::complex (0, 1) * + amp[1025] + std::complex (0, 1) * amp[1024] + + std::complex (0, 1) * amp[1031] + std::complex (0, 1) * + amp[1030]; + jamp[5] = +amp[4] + amp[10] + amp[12] + amp[15] + amp[17] + amp[18] + amp[21] + + amp[23] + std::complex (0, 1) * amp[24] + std::complex + (0, 1) * amp[25] + std::complex (0, 1) * amp[26] + + std::complex (0, 1) * amp[27] + std::complex (0, 1) * + amp[60] - amp[61] + std::complex (0, 1) * amp[63] - amp[64] + + std::complex (0, 1) * amp[65] + std::complex (0, 1) * + amp[66] - amp[67] + std::complex (0, 1) * amp[69] - amp[70] + + std::complex (0, 1) * amp[71] - amp[85] + std::complex + (0, 1) * amp[87] - amp[88] - amp[91] + std::complex (0, 1) * + amp[93] - amp[94] + amp[98] - amp[96] + amp[101] - amp[99] + amp[104] - + amp[102] + amp[107] - amp[105] + amp[494] + amp[500] - + std::complex (0, 1) * amp[517] - amp[518] - std::complex + (0, 1) * amp[519] - amp[520] - std::complex (0, 1) * amp[521] - + std::complex (0, 1) * amp[523] - amp[524] - std::complex + (0, 1) * amp[525] - amp[526] - std::complex (0, 1) * amp[527] + + std::complex (0, 1) * amp[529] + amp[530] + amp[532] + + std::complex (0, 1) * amp[535] + amp[536] + amp[538] + amp[540] + + amp[541] + amp[543] + amp[544] + amp[546] + amp[547] + amp[549] + + amp[550] + std::complex (0, 1) * amp[780] - std::complex + (0, 1) * amp[782] - std::complex (0, 1) * amp[783] - + std::complex (0, 1) * amp[785] + std::complex (0, 1) * + amp[789] - amp[790] - std::complex (0, 1) * amp[791] - + std::complex (0, 1) * amp[792] + std::complex (0, 1) * + amp[798] - std::complex (0, 1) * amp[800] - std::complex + (0, 1) * amp[801] - std::complex (0, 1) * amp[803] + + std::complex (0, 1) * amp[807] - amp[808] - std::complex + (0, 1) * amp[809] - std::complex (0, 1) * amp[810] + amp[813] - + std::complex (0, 1) * amp[814] + amp[815] - std::complex + (0, 1) * amp[817] + amp[818] + amp[821] - std::complex (0, 1) * + amp[822] + amp[823] - std::complex (0, 1) * amp[825] + amp[826] + + std::complex (0, 1) * amp[828] + std::complex (0, 1) * + amp[832] - amp[833] + std::complex (0, 1) * amp[834] + + std::complex (0, 1) * amp[835] + std::complex (0, 1) * + amp[841] + std::complex (0, 1) * amp[843] + std::complex + (0, 1) * amp[844] + std::complex (0, 1) * amp[846] + + std::complex (0, 1) * amp[850] - amp[851] + std::complex + (0, 1) * amp[852] + std::complex (0, 1) * amp[853] + + std::complex (0, 1) * amp[859] + std::complex (0, 1) * + amp[861] + std::complex (0, 1) * amp[862] - std::complex + (0, 1) * amp[902] + std::complex (0, 1) * amp[904] - amp[905] + + std::complex (0, 1) * amp[906] + std::complex (0, 1) * + amp[907] - std::complex (0, 1) * amp[911] + amp[912] + + std::complex (0, 1) * amp[913] + std::complex (0, 1) * + amp[915] + std::complex (0, 1) * amp[916] - std::complex + (0, 1) * amp[920] + std::complex (0, 1) * amp[922] - amp[923] + + std::complex (0, 1) * amp[924] + std::complex (0, 1) * + amp[925] - std::complex (0, 1) * amp[929] + amp[930] + + std::complex (0, 1) * amp[931] + std::complex (0, 1) * + amp[933] + std::complex (0, 1) * amp[934] - std::complex + (0, 1) * amp[987] - std::complex (0, 1) * amp[988] + amp[990] + + amp[991] - std::complex (0, 1) * amp[993] - std::complex + (0, 1) * amp[994] - std::complex (0, 1) * amp[999] - + std::complex (0, 1) * amp[1000] + amp[1002] + amp[1003] - + std::complex (0, 1) * amp[1005] - std::complex (0, 1) * + amp[1006] + amp[1010] - amp[1008] - std::complex (0, 1) * + amp[1013] + std::complex (0, 1) * amp[1011] - + std::complex (0, 1) * amp[1019] + std::complex (0, 1) * + amp[1017] + amp[1022] - amp[1020] - std::complex (0, 1) * + amp[1025] + std::complex (0, 1) * amp[1023] - + std::complex (0, 1) * amp[1031] + std::complex (0, 1) * + amp[1029]; + jamp[6] = +amp[109] + amp[115] + amp[153] + amp[154] + amp[156] + amp[159] + + amp[160] + amp[162] - std::complex (0, 1) * amp[164] - + std::complex (0, 1) * amp[165] - std::complex (0, 1) * + amp[166] - std::complex (0, 1) * amp[167] - amp[169] - + std::complex (0, 1) * amp[170] - amp[172] - amp[175] - + std::complex (0, 1) * amp[176] - amp[178] - std::complex + (0, 1) * amp[192] - amp[193] - std::complex (0, 1) * amp[194] - + amp[196] - std::complex (0, 1) * amp[197] - std::complex + (0, 1) * amp[198] - amp[199] - std::complex (0, 1) * amp[200] - + amp[202] - std::complex (0, 1) * amp[203] + amp[206] - amp[204] + + amp[209] - amp[207] + amp[212] - amp[210] + amp[215] - amp[213] + + amp[617] + amp[623] + std::complex (0, 1) * amp[625] + amp[626] + + std::complex (0, 1) * amp[627] + amp[628] + std::complex + (0, 1) * amp[629] + std::complex (0, 1) * amp[631] + amp[632] + + std::complex (0, 1) * amp[633] + amp[634] + std::complex + (0, 1) * amp[635] - std::complex (0, 1) * amp[636] + amp[638] + + amp[640] - std::complex (0, 1) * amp[642] + amp[644] + amp[646] - + amp[662] - amp[661] - amp[665] - amp[664] - amp[668] - amp[667] - + amp[671] - amp[670] - std::complex (0, 1) * amp[674] + + std::complex (0, 1) * amp[680] - std::complex (0, 1) * + amp[678] + std::complex (0, 1) * amp[682] - std::complex + (0, 1) * amp[683] + amp[684] + std::complex (0, 1) * amp[689] - + std::complex (0, 1) * amp[687] - std::complex (0, 1) * + amp[692] + std::complex (0, 1) * amp[698] - std::complex + (0, 1) * amp[696] + std::complex (0, 1) * amp[700] - + std::complex (0, 1) * amp[701] + amp[702] + std::complex + (0, 1) * amp[707] - std::complex (0, 1) * amp[705] + amp[709] - + std::complex (0, 1) * amp[710] + amp[711] - std::complex + (0, 1) * amp[713] + amp[714] + amp[717] - std::complex (0, 1) * + amp[718] + amp[719] - std::complex (0, 1) * amp[721] + amp[722] - + std::complex (0, 1) * amp[726] - std::complex (0, 1) * + amp[728] - amp[729] + std::complex (0, 1) * amp[732] + + std::complex (0, 1) * amp[731] - std::complex (0, 1) * + amp[735] + amp[736] - std::complex (0, 1) * amp[737] + + std::complex (0, 1) * amp[741] + std::complex (0, 1) * + amp[740] - std::complex (0, 1) * amp[744] - std::complex + (0, 1) * amp[746] - amp[747] + std::complex (0, 1) * amp[750] + + std::complex (0, 1) * amp[749] - std::complex (0, 1) * + amp[753] + amp[754] - std::complex (0, 1) * amp[755] + + std::complex (0, 1) * amp[759] + std::complex (0, 1) * + amp[758] - std::complex (0, 1) * amp[901] - std::complex + (0, 1) * amp[902] - amp[903] + std::complex (0, 1) * amp[908] + + std::complex (0, 1) * amp[907] - std::complex (0, 1) * + amp[911] + std::complex (0, 1) * amp[917] + std::complex + (0, 1) * amp[916] - std::complex (0, 1) * amp[919] - + std::complex (0, 1) * amp[920] - amp[921] + std::complex + (0, 1) * amp[926] + std::complex (0, 1) * amp[925] - + std::complex (0, 1) * amp[929] + std::complex (0, 1) * + amp[935] + std::complex (0, 1) * amp[934] + std::complex + (0, 1) * amp[941] + std::complex (0, 1) * amp[940] - amp[944] - + amp[943] + std::complex (0, 1) * amp[947] + std::complex + (0, 1) * amp[946] + std::complex (0, 1) * amp[953] + + std::complex (0, 1) * amp[952] - amp[956] - amp[955] + + std::complex (0, 1) * amp[959] + std::complex (0, 1) * + amp[958] + amp[986] - amp[984] + std::complex (0, 1) * amp[989] - + std::complex (0, 1) * amp[987] + std::complex (0, 1) * + amp[995] - std::complex (0, 1) * amp[993] + amp[998] - amp[996] + + std::complex (0, 1) * amp[1001] - std::complex (0, 1) * + amp[999] + std::complex (0, 1) * amp[1007] - std::complex + (0, 1) * amp[1005]; + jamp[7] = +amp[108] + amp[114] + amp[137] + amp[138] + amp[140] + amp[143] + + amp[144] + amp[146] - std::complex (0, 1) * amp[148] - + std::complex (0, 1) * amp[149] - std::complex (0, 1) * + amp[150] - std::complex (0, 1) * amp[151] - amp[181] - + std::complex (0, 1) * amp[182] - amp[184] - amp[187] - + std::complex (0, 1) * amp[188] - amp[190] + std::complex + (0, 1) * amp[192] + amp[193] + std::complex (0, 1) * amp[194] + + amp[196] + std::complex (0, 1) * amp[197] + std::complex + (0, 1) * amp[198] + amp[199] + std::complex (0, 1) * amp[200] + + amp[202] + std::complex (0, 1) * amp[203] + amp[204] + amp[205] + + amp[207] + amp[208] + amp[210] + amp[211] + amp[213] + amp[214] + + amp[557] + amp[563] + std::complex (0, 1) * amp[565] + amp[566] + + std::complex (0, 1) * amp[567] + amp[568] + std::complex + (0, 1) * amp[569] + std::complex (0, 1) * amp[571] + amp[572] + + std::complex (0, 1) * amp[573] + amp[574] + std::complex + (0, 1) * amp[575] - std::complex (0, 1) * amp[576] + amp[578] + + amp[580] - std::complex (0, 1) * amp[582] + amp[584] + amp[586] - + amp[602] - amp[601] - amp[605] - amp[604] - amp[608] - amp[607] - + amp[611] - amp[610] - std::complex (0, 1) * amp[676] + + std::complex (0, 1) * amp[678] + std::complex (0, 1) * + amp[679] + std::complex (0, 1) * amp[681] - std::complex + (0, 1) * amp[685] + amp[686] + std::complex (0, 1) * amp[687] + + std::complex (0, 1) * amp[688] - std::complex (0, 1) * + amp[694] + std::complex (0, 1) * amp[696] + std::complex + (0, 1) * amp[697] + std::complex (0, 1) * amp[699] - + std::complex (0, 1) * amp[703] + amp[704] + std::complex + (0, 1) * amp[705] + std::complex (0, 1) * amp[706] - amp[709] + + std::complex (0, 1) * amp[710] - amp[711] + std::complex + (0, 1) * amp[713] - amp[714] - amp[717] + std::complex (0, 1) * + amp[718] - amp[719] + std::complex (0, 1) * amp[721] - amp[722] - + std::complex (0, 1) * amp[778] - std::complex (0, 1) * + amp[780] - amp[781] + std::complex (0, 1) * amp[784] + + std::complex (0, 1) * amp[783] - std::complex (0, 1) * + amp[787] + amp[788] - std::complex (0, 1) * amp[789] + + std::complex (0, 1) * amp[793] + std::complex (0, 1) * + amp[792] - std::complex (0, 1) * amp[796] - std::complex + (0, 1) * amp[798] - amp[799] + std::complex (0, 1) * amp[802] + + std::complex (0, 1) * amp[801] - std::complex (0, 1) * + amp[805] + amp[806] - std::complex (0, 1) * amp[807] + + std::complex (0, 1) * amp[811] + std::complex (0, 1) * + amp[810] + std::complex (0, 1) * amp[901] + std::complex + (0, 1) * amp[902] + amp[903] - std::complex (0, 1) * amp[908] - + std::complex (0, 1) * amp[907] + std::complex (0, 1) * + amp[911] - std::complex (0, 1) * amp[917] - std::complex + (0, 1) * amp[916] + std::complex (0, 1) * amp[919] + + std::complex (0, 1) * amp[920] + amp[921] - std::complex + (0, 1) * amp[926] - std::complex (0, 1) * amp[925] + + std::complex (0, 1) * amp[929] - std::complex (0, 1) * + amp[935] - std::complex (0, 1) * amp[934] + std::complex + (0, 1) * amp[965] + std::complex (0, 1) * amp[964] - amp[968] - + amp[967] + std::complex (0, 1) * amp[971] + std::complex + (0, 1) * amp[970] + std::complex (0, 1) * amp[977] + + std::complex (0, 1) * amp[976] - amp[980] - amp[979] + + std::complex (0, 1) * amp[983] + std::complex (0, 1) * + amp[982] + amp[984] + amp[985] + std::complex (0, 1) * amp[987] + + std::complex (0, 1) * amp[988] + std::complex (0, 1) * + amp[993] + std::complex (0, 1) * amp[994] + amp[996] + amp[997] + + std::complex (0, 1) * amp[999] + std::complex (0, 1) * + amp[1000] + std::complex (0, 1) * amp[1005] + + std::complex (0, 1) * amp[1006]; + jamp[8] = +amp[111] + amp[117] + amp[152] + amp[155] + amp[157] + amp[158] + + amp[161] + amp[163] + std::complex (0, 1) * amp[164] + + std::complex (0, 1) * amp[165] + std::complex (0, 1) * + amp[166] + std::complex (0, 1) * amp[167] + amp[169] + + std::complex (0, 1) * amp[170] + amp[172] + amp[175] + + std::complex (0, 1) * amp[176] + amp[178] - std::complex + (0, 1) * amp[180] + amp[181] - std::complex (0, 1) * amp[183] + + amp[184] - std::complex (0, 1) * amp[185] - std::complex + (0, 1) * amp[186] + amp[187] - std::complex (0, 1) * amp[189] + + amp[190] - std::complex (0, 1) * amp[191] - amp[206] - amp[205] - + amp[209] - amp[208] - amp[212] - amp[211] - amp[215] - amp[214] + + amp[612] + amp[618] + std::complex (0, 1) * amp[636] - amp[638] - + amp[640] + std::complex (0, 1) * amp[642] - amp[644] - amp[646] - + std::complex (0, 1) * amp[648] + amp[650] - std::complex + (0, 1) * amp[651] + amp[652] - std::complex (0, 1) * amp[653] - + std::complex (0, 1) * amp[654] + amp[656] - std::complex + (0, 1) * amp[657] + amp[658] - std::complex (0, 1) * amp[659] + + amp[660] + amp[661] + amp[663] + amp[664] + amp[666] + amp[667] + + amp[669] + amp[670] + std::complex (0, 1) * amp[726] + + std::complex (0, 1) * amp[728] + amp[729] - std::complex + (0, 1) * amp[732] - std::complex (0, 1) * amp[731] + + std::complex (0, 1) * amp[735] - amp[736] + std::complex + (0, 1) * amp[737] - std::complex (0, 1) * amp[741] - + std::complex (0, 1) * amp[740] + std::complex (0, 1) * + amp[744] + std::complex (0, 1) * amp[746] + amp[747] - + std::complex (0, 1) * amp[750] - std::complex (0, 1) * + amp[749] + std::complex (0, 1) * amp[753] - amp[754] + + std::complex (0, 1) * amp[755] - std::complex (0, 1) * + amp[759] - std::complex (0, 1) * amp[758] - std::complex + (0, 1) * amp[776] + std::complex (0, 1) * amp[780] + amp[781] - + std::complex (0, 1) * amp[782] - std::complex (0, 1) * + amp[783] + std::complex (0, 1) * amp[789] - std::complex + (0, 1) * amp[791] - std::complex (0, 1) * amp[792] - + std::complex (0, 1) * amp[794] + std::complex (0, 1) * + amp[798] + amp[799] - std::complex (0, 1) * amp[800] - + std::complex (0, 1) * amp[801] + std::complex (0, 1) * + amp[807] - std::complex (0, 1) * amp[809] - std::complex + (0, 1) * amp[810] - amp[812] - std::complex (0, 1) * amp[814] - + amp[816] - std::complex (0, 1) * amp[817] - amp[819] - amp[820] - + std::complex (0, 1) * amp[822] - amp[824] - std::complex + (0, 1) * amp[825] - amp[827] - std::complex (0, 1) * amp[830] + + std::complex (0, 1) * amp[836] + std::complex (0, 1) * + amp[835] - std::complex (0, 1) * amp[838] - std::complex + (0, 1) * amp[839] + amp[840] + std::complex (0, 1) * amp[845] + + std::complex (0, 1) * amp[844] - std::complex (0, 1) * + amp[848] + std::complex (0, 1) * amp[854] + std::complex + (0, 1) * amp[853] - std::complex (0, 1) * amp[856] - + std::complex (0, 1) * amp[857] + amp[858] + std::complex + (0, 1) * amp[863] + std::complex (0, 1) * amp[862] - + std::complex (0, 1) * amp[939] - std::complex (0, 1) * + amp[940] + amp[942] + amp[943] - std::complex (0, 1) * amp[945] - + std::complex (0, 1) * amp[946] - std::complex (0, 1) * + amp[951] - std::complex (0, 1) * amp[952] + amp[954] + amp[955] - + std::complex (0, 1) * amp[957] - std::complex (0, 1) * + amp[958] - amp[986] - amp[985] - std::complex (0, 1) * amp[989] - + std::complex (0, 1) * amp[988] - std::complex (0, 1) * + amp[995] - std::complex (0, 1) * amp[994] - amp[998] - amp[997] - + std::complex (0, 1) * amp[1001] - std::complex (0, 1) * + amp[1000] - std::complex (0, 1) * amp[1007] - + std::complex (0, 1) * amp[1006]; + jamp[9] = +amp[110] + amp[116] + amp[121] + amp[122] + amp[124] + amp[127] + + amp[128] + amp[130] - std::complex (0, 1) * amp[132] - + std::complex (0, 1) * amp[133] - std::complex (0, 1) * + amp[134] - std::complex (0, 1) * amp[135] + std::complex + (0, 1) * amp[180] - amp[181] + std::complex (0, 1) * amp[183] - + amp[184] + std::complex (0, 1) * amp[185] + std::complex + (0, 1) * amp[186] - amp[187] + std::complex (0, 1) * amp[189] - + amp[190] + std::complex (0, 1) * amp[191] + amp[193] - + std::complex (0, 1) * amp[195] + amp[196] + amp[199] - + std::complex (0, 1) * amp[201] + amp[202] + amp[204] + amp[205] + + amp[207] + amp[208] + amp[210] + amp[211] + amp[213] + amp[214] + + amp[436] + amp[442] - std::complex (0, 1) * amp[445] - amp[446] - + std::complex (0, 1) * amp[447] - amp[448] - std::complex + (0, 1) * amp[449] - std::complex (0, 1) * amp[451] - amp[452] - + std::complex (0, 1) * amp[453] - amp[454] - std::complex + (0, 1) * amp[455] - std::complex (0, 1) * amp[469] - amp[470] - + amp[472] - std::complex (0, 1) * amp[475] - amp[476] - amp[478] + + amp[482] - amp[480] + amp[485] - amp[483] + amp[488] - amp[486] + + amp[491] - amp[489] + std::complex (0, 1) * amp[776] - + std::complex (0, 1) * amp[780] - amp[781] + std::complex + (0, 1) * amp[782] + std::complex (0, 1) * amp[783] - + std::complex (0, 1) * amp[789] + std::complex (0, 1) * + amp[791] + std::complex (0, 1) * amp[792] + std::complex + (0, 1) * amp[794] - std::complex (0, 1) * amp[798] - amp[799] + + std::complex (0, 1) * amp[800] + std::complex (0, 1) * + amp[801] - std::complex (0, 1) * amp[807] + std::complex + (0, 1) * amp[809] + std::complex (0, 1) * amp[810] + amp[812] + + std::complex (0, 1) * amp[814] + amp[816] + std::complex + (0, 1) * amp[817] + amp[819] + amp[820] + std::complex (0, 1) * + amp[822] + amp[824] + std::complex (0, 1) * amp[825] + amp[827] - + std::complex (0, 1) * amp[832] - std::complex (0, 1) * + amp[834] - std::complex (0, 1) * amp[835] - std::complex + (0, 1) * amp[837] - std::complex (0, 1) * amp[841] - amp[842] - + std::complex (0, 1) * amp[843] - std::complex (0, 1) * + amp[844] - std::complex (0, 1) * amp[850] - std::complex + (0, 1) * amp[852] - std::complex (0, 1) * amp[853] - + std::complex (0, 1) * amp[855] - std::complex (0, 1) * + amp[859] - amp[860] - std::complex (0, 1) * amp[861] - + std::complex (0, 1) * amp[862] + std::complex (0, 1) * + amp[902] + amp[903] - std::complex (0, 1) * amp[904] - + std::complex (0, 1) * amp[906] - std::complex (0, 1) * + amp[907] + std::complex (0, 1) * amp[911] - std::complex + (0, 1) * amp[913] - amp[914] - std::complex (0, 1) * amp[915] - + std::complex (0, 1) * amp[916] + std::complex (0, 1) * + amp[920] + amp[921] - std::complex (0, 1) * amp[922] - + std::complex (0, 1) * amp[924] - std::complex (0, 1) * + amp[925] + std::complex (0, 1) * amp[929] - std::complex + (0, 1) * amp[931] - amp[932] - std::complex (0, 1) * amp[933] - + std::complex (0, 1) * amp[934] + amp[984] + amp[985] + + std::complex (0, 1) * amp[987] + std::complex (0, 1) * + amp[988] + std::complex (0, 1) * amp[993] + std::complex + (0, 1) * amp[994] + amp[996] + amp[997] + std::complex (0, 1) * + amp[999] + std::complex (0, 1) * amp[1000] + std::complex + (0, 1) * amp[1005] + std::complex (0, 1) * amp[1006] + + std::complex (0, 1) * amp[1013] - std::complex (0, 1) * + amp[1011] + amp[1016] - amp[1014] + std::complex (0, 1) * + amp[1019] - std::complex (0, 1) * amp[1017] + + std::complex (0, 1) * amp[1025] - std::complex (0, 1) * + amp[1023] + amp[1028] - amp[1026] + std::complex (0, 1) * + amp[1031] - std::complex (0, 1) * amp[1029]; + jamp[10] = +amp[113] + amp[119] + amp[136] + amp[139] + amp[141] + amp[142] + + amp[145] + amp[147] + std::complex (0, 1) * amp[148] + + std::complex (0, 1) * amp[149] + std::complex (0, 1) * + amp[150] + std::complex (0, 1) * amp[151] - std::complex + (0, 1) * amp[168] + amp[169] - std::complex (0, 1) * amp[171] + + amp[172] - std::complex (0, 1) * amp[173] - std::complex + (0, 1) * amp[174] + amp[175] - std::complex (0, 1) * amp[177] + + amp[178] - std::complex (0, 1) * amp[179] + amp[181] + + std::complex (0, 1) * amp[182] + amp[184] + amp[187] + + std::complex (0, 1) * amp[188] + amp[190] - amp[206] - amp[205] - + amp[209] - amp[208] - amp[212] - amp[211] - amp[215] - amp[214] + + amp[552] + amp[558] + std::complex (0, 1) * amp[576] - amp[578] - + amp[580] + std::complex (0, 1) * amp[582] - amp[584] - amp[586] - + std::complex (0, 1) * amp[588] + amp[590] - std::complex + (0, 1) * amp[591] + amp[592] - std::complex (0, 1) * amp[593] - + std::complex (0, 1) * amp[594] + amp[596] - std::complex + (0, 1) * amp[597] + amp[598] - std::complex (0, 1) * amp[599] + + amp[600] + amp[601] + amp[603] + amp[604] + amp[606] + amp[607] + + amp[609] + amp[610] - std::complex (0, 1) * amp[724] + + std::complex (0, 1) * amp[728] + amp[729] - std::complex + (0, 1) * amp[730] - std::complex (0, 1) * amp[731] + + std::complex (0, 1) * amp[737] - std::complex (0, 1) * + amp[739] - std::complex (0, 1) * amp[740] - std::complex + (0, 1) * amp[742] + std::complex (0, 1) * amp[746] + amp[747] - + std::complex (0, 1) * amp[748] - std::complex (0, 1) * + amp[749] + std::complex (0, 1) * amp[755] - std::complex + (0, 1) * amp[757] - std::complex (0, 1) * amp[758] - amp[760] - + std::complex (0, 1) * amp[762] - amp[764] - std::complex + (0, 1) * amp[765] - amp[767] - amp[768] - std::complex (0, 1) * + amp[770] - amp[772] - std::complex (0, 1) * amp[773] - amp[775] + + std::complex (0, 1) * amp[778] + std::complex (0, 1) * + amp[780] + amp[781] - std::complex (0, 1) * amp[784] - + std::complex (0, 1) * amp[783] + std::complex (0, 1) * + amp[787] - amp[788] + std::complex (0, 1) * amp[789] - + std::complex (0, 1) * amp[793] - std::complex (0, 1) * + amp[792] + std::complex (0, 1) * amp[796] + std::complex + (0, 1) * amp[798] + amp[799] - std::complex (0, 1) * amp[802] - + std::complex (0, 1) * amp[801] + std::complex (0, 1) * + amp[805] - amp[806] + std::complex (0, 1) * amp[807] - + std::complex (0, 1) * amp[811] - std::complex (0, 1) * + amp[810] - std::complex (0, 1) * amp[866] + std::complex + (0, 1) * amp[872] + std::complex (0, 1) * amp[871] - + std::complex (0, 1) * amp[874] - std::complex (0, 1) * + amp[875] + amp[876] + std::complex (0, 1) * amp[881] + + std::complex (0, 1) * amp[880] - std::complex (0, 1) * + amp[884] + std::complex (0, 1) * amp[890] + std::complex + (0, 1) * amp[889] - std::complex (0, 1) * amp[892] - + std::complex (0, 1) * amp[893] + amp[894] + std::complex + (0, 1) * amp[899] + std::complex (0, 1) * amp[898] - + std::complex (0, 1) * amp[963] - std::complex (0, 1) * + amp[964] + amp[966] + amp[967] - std::complex (0, 1) * amp[969] - + std::complex (0, 1) * amp[970] - std::complex (0, 1) * + amp[975] - std::complex (0, 1) * amp[976] + amp[978] + amp[979] - + std::complex (0, 1) * amp[981] - std::complex (0, 1) * + amp[982] - amp[986] - amp[985] - std::complex (0, 1) * amp[989] - + std::complex (0, 1) * amp[988] - std::complex (0, 1) * + amp[995] - std::complex (0, 1) * amp[994] - amp[998] - amp[997] - + std::complex (0, 1) * amp[1001] - std::complex (0, 1) * + amp[1000] - std::complex (0, 1) * amp[1007] - + std::complex (0, 1) * amp[1006]; + jamp[11] = +amp[112] + amp[118] + amp[120] + amp[123] + amp[125] + amp[126] + + amp[129] + amp[131] + std::complex (0, 1) * amp[132] + + std::complex (0, 1) * amp[133] + std::complex (0, 1) * + amp[134] + std::complex (0, 1) * amp[135] + std::complex + (0, 1) * amp[168] - amp[169] + std::complex (0, 1) * amp[171] - + amp[172] + std::complex (0, 1) * amp[173] + std::complex + (0, 1) * amp[174] - amp[175] + std::complex (0, 1) * amp[177] - + amp[178] + std::complex (0, 1) * amp[179] - amp[193] + + std::complex (0, 1) * amp[195] - amp[196] - amp[199] + + std::complex (0, 1) * amp[201] - amp[202] + amp[206] - amp[204] + + amp[209] - amp[207] + amp[212] - amp[210] + amp[215] - amp[213] + + amp[434] + amp[440] - std::complex (0, 1) * amp[457] - amp[458] - + std::complex (0, 1) * amp[459] - amp[460] - std::complex + (0, 1) * amp[461] - std::complex (0, 1) * amp[463] - amp[464] - + std::complex (0, 1) * amp[465] - amp[466] - std::complex + (0, 1) * amp[467] + std::complex (0, 1) * amp[469] + amp[470] + + amp[472] + std::complex (0, 1) * amp[475] + amp[476] + amp[478] + + amp[480] + amp[481] + amp[483] + amp[484] + amp[486] + amp[487] + + amp[489] + amp[490] + std::complex (0, 1) * amp[724] - + std::complex (0, 1) * amp[728] - amp[729] + std::complex + (0, 1) * amp[730] + std::complex (0, 1) * amp[731] - + std::complex (0, 1) * amp[737] + std::complex (0, 1) * + amp[739] + std::complex (0, 1) * amp[740] + std::complex + (0, 1) * amp[742] - std::complex (0, 1) * amp[746] - amp[747] + + std::complex (0, 1) * amp[748] + std::complex (0, 1) * + amp[749] - std::complex (0, 1) * amp[755] + std::complex + (0, 1) * amp[757] + std::complex (0, 1) * amp[758] + amp[760] + + std::complex (0, 1) * amp[762] + amp[764] + std::complex + (0, 1) * amp[765] + amp[767] + amp[768] + std::complex (0, 1) * + amp[770] + amp[772] + std::complex (0, 1) * amp[773] + amp[775] - + std::complex (0, 1) * amp[868] - std::complex (0, 1) * + amp[870] - std::complex (0, 1) * amp[871] - std::complex + (0, 1) * amp[873] - std::complex (0, 1) * amp[877] - amp[878] - + std::complex (0, 1) * amp[879] - std::complex (0, 1) * + amp[880] - std::complex (0, 1) * amp[886] - std::complex + (0, 1) * amp[888] - std::complex (0, 1) * amp[889] - + std::complex (0, 1) * amp[891] - std::complex (0, 1) * + amp[895] - amp[896] - std::complex (0, 1) * amp[897] - + std::complex (0, 1) * amp[898] - std::complex (0, 1) * + amp[902] - amp[903] + std::complex (0, 1) * amp[904] + + std::complex (0, 1) * amp[906] + std::complex (0, 1) * + amp[907] - std::complex (0, 1) * amp[911] + std::complex + (0, 1) * amp[913] + amp[914] + std::complex (0, 1) * amp[915] + + std::complex (0, 1) * amp[916] - std::complex (0, 1) * + amp[920] - amp[921] + std::complex (0, 1) * amp[922] + + std::complex (0, 1) * amp[924] + std::complex (0, 1) * + amp[925] - std::complex (0, 1) * amp[929] + std::complex + (0, 1) * amp[931] + amp[932] + std::complex (0, 1) * amp[933] + + std::complex (0, 1) * amp[934] + amp[986] - amp[984] + + std::complex (0, 1) * amp[989] - std::complex (0, 1) * + amp[987] + std::complex (0, 1) * amp[995] - std::complex + (0, 1) * amp[993] + amp[998] - amp[996] + std::complex (0, 1) * + amp[1001] - std::complex (0, 1) * amp[999] + std::complex + (0, 1) * amp[1007] - std::complex (0, 1) * amp[1005] + + std::complex (0, 1) * amp[1011] + std::complex (0, 1) * + amp[1012] + amp[1014] + amp[1015] + std::complex (0, 1) * + amp[1017] + std::complex (0, 1) * amp[1018] + + std::complex (0, 1) * amp[1023] + std::complex (0, 1) * + amp[1024] + amp[1026] + amp[1027] + std::complex (0, 1) * + amp[1029] + std::complex (0, 1) * amp[1030]; + jamp[12] = +amp[217] + amp[223] + amp[261] + amp[262] + amp[264] + amp[267] + + amp[268] + amp[270] - std::complex (0, 1) * amp[272] - + std::complex (0, 1) * amp[273] - std::complex (0, 1) * + amp[274] - std::complex (0, 1) * amp[275] - amp[277] - + std::complex (0, 1) * amp[278] - amp[280] - amp[283] - + std::complex (0, 1) * amp[284] - amp[286] - std::complex + (0, 1) * amp[300] - amp[301] - std::complex (0, 1) * amp[302] - + amp[304] - std::complex (0, 1) * amp[305] - std::complex + (0, 1) * amp[306] - amp[307] - std::complex (0, 1) * amp[308] - + amp[310] - std::complex (0, 1) * amp[311] + amp[314] - amp[312] + + amp[317] - amp[315] + amp[320] - amp[318] + amp[323] - amp[321] + + amp[615] + amp[621] - std::complex (0, 1) * amp[624] + amp[626] + + amp[628] - std::complex (0, 1) * amp[630] + amp[632] + amp[634] + + std::complex (0, 1) * amp[637] + amp[638] + std::complex + (0, 1) * amp[639] + amp[640] + std::complex (0, 1) * amp[641] + + std::complex (0, 1) * amp[643] + amp[644] + std::complex + (0, 1) * amp[645] + amp[646] + std::complex (0, 1) * amp[647] - + amp[662] - amp[661] - amp[665] - amp[664] - amp[668] - amp[667] - + amp[671] - amp[670] - std::complex (0, 1) * amp[674] - + std::complex (0, 1) * amp[676] - amp[677] + std::complex + (0, 1) * amp[680] + std::complex (0, 1) * amp[679] - + std::complex (0, 1) * amp[683] + amp[684] - std::complex + (0, 1) * amp[685] + std::complex (0, 1) * amp[689] + + std::complex (0, 1) * amp[688] - std::complex (0, 1) * + amp[692] - std::complex (0, 1) * amp[694] - amp[695] + + std::complex (0, 1) * amp[698] + std::complex (0, 1) * + amp[697] - std::complex (0, 1) * amp[701] + amp[702] - + std::complex (0, 1) * amp[703] + std::complex (0, 1) * + amp[707] + std::complex (0, 1) * amp[706] - std::complex + (0, 1) * amp[726] + std::complex (0, 1) * amp[732] - + std::complex (0, 1) * amp[730] + std::complex (0, 1) * + amp[734] - std::complex (0, 1) * amp[735] + amp[736] + + std::complex (0, 1) * amp[741] - std::complex (0, 1) * + amp[739] - std::complex (0, 1) * amp[744] + std::complex + (0, 1) * amp[750] - std::complex (0, 1) * amp[748] + + std::complex (0, 1) * amp[752] - std::complex (0, 1) * + amp[753] + amp[754] + std::complex (0, 1) * amp[759] - + std::complex (0, 1) * amp[757] + amp[761] - std::complex + (0, 1) * amp[762] + amp[763] - std::complex (0, 1) * amp[765] + + amp[766] + amp[769] - std::complex (0, 1) * amp[770] + amp[771] - + std::complex (0, 1) * amp[773] + amp[774] - std::complex + (0, 1) * amp[865] - std::complex (0, 1) * amp[866] - amp[867] + + std::complex (0, 1) * amp[872] + std::complex (0, 1) * + amp[871] - std::complex (0, 1) * amp[875] + std::complex + (0, 1) * amp[881] + std::complex (0, 1) * amp[880] - + std::complex (0, 1) * amp[883] - std::complex (0, 1) * + amp[884] - amp[885] + std::complex (0, 1) * amp[890] + + std::complex (0, 1) * amp[889] - std::complex (0, 1) * + amp[893] + std::complex (0, 1) * amp[899] + std::complex + (0, 1) * amp[898] + std::complex (0, 1) * amp[941] + + std::complex (0, 1) * amp[940] - amp[944] - amp[943] + + std::complex (0, 1) * amp[947] + std::complex (0, 1) * + amp[946] + std::complex (0, 1) * amp[953] + std::complex + (0, 1) * amp[952] - amp[956] - amp[955] + std::complex (0, 1) * + amp[959] + std::complex (0, 1) * amp[958] + amp[962] - amp[960] + + std::complex (0, 1) * amp[965] - std::complex (0, 1) * + amp[963] + std::complex (0, 1) * amp[971] - std::complex + (0, 1) * amp[969] + amp[974] - amp[972] + std::complex (0, 1) * + amp[977] - std::complex (0, 1) * amp[975] + std::complex + (0, 1) * amp[983] - std::complex (0, 1) * amp[981]; + jamp[13] = +amp[216] + amp[222] + amp[245] + amp[246] + amp[248] + amp[251] + + amp[252] + amp[254] - std::complex (0, 1) * amp[256] - + std::complex (0, 1) * amp[257] - std::complex (0, 1) * + amp[258] - std::complex (0, 1) * amp[259] - amp[289] - + std::complex (0, 1) * amp[290] - amp[292] - amp[295] - + std::complex (0, 1) * amp[296] - amp[298] + std::complex + (0, 1) * amp[300] + amp[301] + std::complex (0, 1) * amp[302] + + amp[304] + std::complex (0, 1) * amp[305] + std::complex + (0, 1) * amp[306] + amp[307] + std::complex (0, 1) * amp[308] + + amp[310] + std::complex (0, 1) * amp[311] + amp[312] + amp[313] + + amp[315] + amp[316] + amp[318] + amp[319] + amp[321] + amp[322] + + amp[497] + amp[503] + std::complex (0, 1) * amp[505] + amp[506] + + std::complex (0, 1) * amp[507] + amp[508] + std::complex + (0, 1) * amp[509] + std::complex (0, 1) * amp[511] + amp[512] + + std::complex (0, 1) * amp[513] + amp[514] + std::complex + (0, 1) * amp[515] - std::complex (0, 1) * amp[516] + amp[518] + + amp[520] - std::complex (0, 1) * amp[522] + amp[524] + amp[526] - + amp[542] - amp[541] - amp[545] - amp[544] - amp[548] - amp[547] - + amp[551] - amp[550] - std::complex (0, 1) * amp[728] + + std::complex (0, 1) * amp[730] + std::complex (0, 1) * + amp[731] + std::complex (0, 1) * amp[733] - std::complex + (0, 1) * amp[737] + amp[738] + std::complex (0, 1) * amp[739] + + std::complex (0, 1) * amp[740] - std::complex (0, 1) * + amp[746] + std::complex (0, 1) * amp[748] + std::complex + (0, 1) * amp[749] + std::complex (0, 1) * amp[751] - + std::complex (0, 1) * amp[755] + amp[756] + std::complex + (0, 1) * amp[757] + std::complex (0, 1) * amp[758] - amp[761] + + std::complex (0, 1) * amp[762] - amp[763] + std::complex + (0, 1) * amp[765] - amp[766] - amp[769] + std::complex (0, 1) * + amp[770] - amp[771] + std::complex (0, 1) * amp[773] - amp[774] - + std::complex (0, 1) * amp[778] - amp[779] - std::complex + (0, 1) * amp[780] + std::complex (0, 1) * amp[784] + + std::complex (0, 1) * amp[783] - std::complex (0, 1) * + amp[787] - std::complex (0, 1) * amp[789] + amp[790] + + std::complex (0, 1) * amp[793] + std::complex (0, 1) * + amp[792] - std::complex (0, 1) * amp[796] - amp[797] - + std::complex (0, 1) * amp[798] + std::complex (0, 1) * + amp[802] + std::complex (0, 1) * amp[801] - std::complex + (0, 1) * amp[805] - std::complex (0, 1) * amp[807] + amp[808] + + std::complex (0, 1) * amp[811] + std::complex (0, 1) * + amp[810] + std::complex (0, 1) * amp[865] + std::complex + (0, 1) * amp[866] + amp[867] - std::complex (0, 1) * amp[872] - + std::complex (0, 1) * amp[871] + std::complex (0, 1) * + amp[875] - std::complex (0, 1) * amp[881] - std::complex + (0, 1) * amp[880] + std::complex (0, 1) * amp[883] + + std::complex (0, 1) * amp[884] + amp[885] - std::complex + (0, 1) * amp[890] - std::complex (0, 1) * amp[889] + + std::complex (0, 1) * amp[893] - std::complex (0, 1) * + amp[899] - std::complex (0, 1) * amp[898] + amp[960] + amp[961] + + std::complex (0, 1) * amp[963] + std::complex (0, 1) * + amp[964] + std::complex (0, 1) * amp[969] + std::complex + (0, 1) * amp[970] + amp[972] + amp[973] + std::complex (0, 1) * + amp[975] + std::complex (0, 1) * amp[976] + std::complex + (0, 1) * amp[981] + std::complex (0, 1) * amp[982] + + std::complex (0, 1) * amp[989] + std::complex (0, 1) * + amp[988] - amp[992] - amp[991] + std::complex (0, 1) * amp[995] + + std::complex (0, 1) * amp[994] + std::complex (0, 1) * + amp[1001] + std::complex (0, 1) * amp[1000] - amp[1004] - + amp[1003] + std::complex (0, 1) * amp[1007] + + std::complex (0, 1) * amp[1006]; + jamp[14] = +amp[219] + amp[225] + amp[260] + amp[263] + amp[265] + amp[266] + + amp[269] + amp[271] + std::complex (0, 1) * amp[272] + + std::complex (0, 1) * amp[273] + std::complex (0, 1) * + amp[274] + std::complex (0, 1) * amp[275] + amp[277] + + std::complex (0, 1) * amp[278] + amp[280] + amp[283] + + std::complex (0, 1) * amp[284] + amp[286] - std::complex + (0, 1) * amp[288] + amp[289] - std::complex (0, 1) * amp[291] + + amp[292] - std::complex (0, 1) * amp[293] - std::complex + (0, 1) * amp[294] + amp[295] - std::complex (0, 1) * amp[297] + + amp[298] - std::complex (0, 1) * amp[299] - amp[314] - amp[313] - + amp[317] - amp[316] - amp[320] - amp[319] - amp[323] - amp[322] + + amp[613] + amp[619] + std::complex (0, 1) * amp[624] - amp[626] - + amp[628] + std::complex (0, 1) * amp[630] - amp[632] - amp[634] + + std::complex (0, 1) * amp[648] - amp[650] + std::complex + (0, 1) * amp[651] - amp[652] + std::complex (0, 1) * amp[653] + + std::complex (0, 1) * amp[654] - amp[656] + std::complex + (0, 1) * amp[657] - amp[658] + std::complex (0, 1) * amp[659] + + amp[662] - amp[660] + amp[665] - amp[663] + amp[668] - amp[666] + + amp[671] - amp[669] + std::complex (0, 1) * amp[674] + + std::complex (0, 1) * amp[676] + amp[677] - std::complex + (0, 1) * amp[680] - std::complex (0, 1) * amp[679] + + std::complex (0, 1) * amp[683] - amp[684] + std::complex + (0, 1) * amp[685] - std::complex (0, 1) * amp[689] - + std::complex (0, 1) * amp[688] + std::complex (0, 1) * + amp[692] + std::complex (0, 1) * amp[694] + amp[695] - + std::complex (0, 1) * amp[698] - std::complex (0, 1) * + amp[697] + std::complex (0, 1) * amp[701] - amp[702] + + std::complex (0, 1) * amp[703] - std::complex (0, 1) * + amp[707] - std::complex (0, 1) * amp[706] - std::complex + (0, 1) * amp[777] + std::complex (0, 1) * amp[778] + amp[779] - + std::complex (0, 1) * amp[784] + std::complex (0, 1) * + amp[782] + std::complex (0, 1) * amp[787] - std::complex + (0, 1) * amp[793] + std::complex (0, 1) * amp[791] - + std::complex (0, 1) * amp[795] + std::complex (0, 1) * + amp[796] + amp[797] - std::complex (0, 1) * amp[802] + + std::complex (0, 1) * amp[800] + std::complex (0, 1) * + amp[805] - std::complex (0, 1) * amp[811] + std::complex + (0, 1) * amp[809] + amp[812] + std::complex (0, 1) * amp[814] + + amp[816] + std::complex (0, 1) * amp[817] + amp[819] + amp[820] + + std::complex (0, 1) * amp[822] + amp[824] + std::complex + (0, 1) * amp[825] + amp[827] + std::complex (0, 1) * amp[830] - + std::complex (0, 1) * amp[836] - std::complex (0, 1) * + amp[835] + std::complex (0, 1) * amp[838] + std::complex + (0, 1) * amp[839] - amp[840] - std::complex (0, 1) * amp[845] - + std::complex (0, 1) * amp[844] + std::complex (0, 1) * + amp[848] - std::complex (0, 1) * amp[854] - std::complex + (0, 1) * amp[853] + std::complex (0, 1) * amp[856] + + std::complex (0, 1) * amp[857] - amp[858] - std::complex + (0, 1) * amp[863] - std::complex (0, 1) * amp[862] - + std::complex (0, 1) * amp[941] + std::complex (0, 1) * + amp[939] + amp[944] - amp[942] - std::complex (0, 1) * amp[947] + + std::complex (0, 1) * amp[945] - std::complex (0, 1) * + amp[953] + std::complex (0, 1) * amp[951] + amp[956] - amp[954] - + std::complex (0, 1) * amp[959] + std::complex (0, 1) * + amp[957] - amp[962] - amp[961] - std::complex (0, 1) * amp[965] - + std::complex (0, 1) * amp[964] - std::complex (0, 1) * + amp[971] - std::complex (0, 1) * amp[970] - amp[974] - amp[973] - + std::complex (0, 1) * amp[977] - std::complex (0, 1) * + amp[976] - std::complex (0, 1) * amp[983] - std::complex + (0, 1) * amp[982]; + jamp[15] = +amp[218] + amp[224] + amp[229] + amp[230] + amp[232] + amp[235] + + amp[236] + amp[238] - std::complex (0, 1) * amp[240] - + std::complex (0, 1) * amp[241] - std::complex (0, 1) * + amp[242] - std::complex (0, 1) * amp[243] + std::complex + (0, 1) * amp[288] - amp[289] + std::complex (0, 1) * amp[291] - + amp[292] + std::complex (0, 1) * amp[293] + std::complex + (0, 1) * amp[294] - amp[295] + std::complex (0, 1) * amp[297] - + amp[298] + std::complex (0, 1) * amp[299] + amp[301] - + std::complex (0, 1) * amp[303] + amp[304] + amp[307] - + std::complex (0, 1) * amp[309] + amp[310] + amp[312] + amp[313] + + amp[315] + amp[316] + amp[318] + amp[319] + amp[321] + amp[322] + + amp[437] + amp[443] + std::complex (0, 1) * amp[445] + amp[446] + + std::complex (0, 1) * amp[447] + amp[448] + std::complex + (0, 1) * amp[449] + std::complex (0, 1) * amp[451] + amp[452] + + std::complex (0, 1) * amp[453] + amp[454] + std::complex + (0, 1) * amp[455] - std::complex (0, 1) * amp[456] + amp[458] + + amp[460] - std::complex (0, 1) * amp[462] + amp[464] + amp[466] - + amp[482] - amp[481] - amp[485] - amp[484] - amp[488] - amp[487] - + amp[491] - amp[490] + std::complex (0, 1) * amp[777] - + std::complex (0, 1) * amp[778] - amp[779] + std::complex + (0, 1) * amp[784] - std::complex (0, 1) * amp[782] - + std::complex (0, 1) * amp[787] + std::complex (0, 1) * + amp[793] - std::complex (0, 1) * amp[791] + std::complex + (0, 1) * amp[795] - std::complex (0, 1) * amp[796] - amp[797] + + std::complex (0, 1) * amp[802] - std::complex (0, 1) * + amp[800] - std::complex (0, 1) * amp[805] + std::complex + (0, 1) * amp[811] - std::complex (0, 1) * amp[809] - amp[812] - + std::complex (0, 1) * amp[814] - amp[816] - std::complex + (0, 1) * amp[817] - amp[819] - amp[820] - std::complex (0, 1) * + amp[822] - amp[824] - std::complex (0, 1) * amp[825] - amp[827] + + std::complex (0, 1) * amp[832] + std::complex (0, 1) * + amp[834] + std::complex (0, 1) * amp[835] + std::complex + (0, 1) * amp[837] + std::complex (0, 1) * amp[841] + amp[842] + + std::complex (0, 1) * amp[843] + std::complex (0, 1) * + amp[844] + std::complex (0, 1) * amp[850] + std::complex + (0, 1) * amp[852] + std::complex (0, 1) * amp[853] + + std::complex (0, 1) * amp[855] + std::complex (0, 1) * + amp[859] + amp[860] + std::complex (0, 1) * amp[861] + + std::complex (0, 1) * amp[862] + std::complex (0, 1) * + amp[866] + amp[867] + std::complex (0, 1) * amp[868] - + std::complex (0, 1) * amp[872] + std::complex (0, 1) * + amp[870] + std::complex (0, 1) * amp[875] + std::complex + (0, 1) * amp[877] + amp[878] - std::complex (0, 1) * amp[881] + + std::complex (0, 1) * amp[879] + std::complex (0, 1) * + amp[884] + amp[885] + std::complex (0, 1) * amp[886] - + std::complex (0, 1) * amp[890] + std::complex (0, 1) * + amp[888] + std::complex (0, 1) * amp[893] + std::complex + (0, 1) * amp[895] + amp[896] - std::complex (0, 1) * amp[899] + + std::complex (0, 1) * amp[897] + amp[960] + amp[961] + + std::complex (0, 1) * amp[963] + std::complex (0, 1) * + amp[964] + std::complex (0, 1) * amp[969] + std::complex + (0, 1) * amp[970] + amp[972] + amp[973] + std::complex (0, 1) * + amp[975] + std::complex (0, 1) * amp[976] + std::complex + (0, 1) * amp[981] + std::complex (0, 1) * amp[982] - + std::complex (0, 1) * amp[1013] - std::complex (0, 1) * + amp[1012] - amp[1016] - amp[1015] - std::complex (0, 1) * + amp[1019] - std::complex (0, 1) * amp[1018] - + std::complex (0, 1) * amp[1025] - std::complex (0, 1) * + amp[1024] - amp[1028] - amp[1027] - std::complex (0, 1) * + amp[1031] - std::complex (0, 1) * amp[1030]; + jamp[16] = +amp[221] + amp[227] + amp[244] + amp[247] + amp[249] + amp[250] + + amp[253] + amp[255] + std::complex (0, 1) * amp[256] + + std::complex (0, 1) * amp[257] + std::complex (0, 1) * + amp[258] + std::complex (0, 1) * amp[259] - std::complex + (0, 1) * amp[276] + amp[277] - std::complex (0, 1) * amp[279] + + amp[280] - std::complex (0, 1) * amp[281] - std::complex + (0, 1) * amp[282] + amp[283] - std::complex (0, 1) * amp[285] + + amp[286] - std::complex (0, 1) * amp[287] + amp[289] + + std::complex (0, 1) * amp[290] + amp[292] + amp[295] + + std::complex (0, 1) * amp[296] + amp[298] - amp[314] - amp[313] - + amp[317] - amp[316] - amp[320] - amp[319] - amp[323] - amp[322] + + amp[492] + amp[498] + std::complex (0, 1) * amp[516] - amp[518] - + amp[520] + std::complex (0, 1) * amp[522] - amp[524] - amp[526] - + std::complex (0, 1) * amp[528] + amp[530] - std::complex + (0, 1) * amp[531] + amp[532] - std::complex (0, 1) * amp[533] - + std::complex (0, 1) * amp[534] + amp[536] - std::complex + (0, 1) * amp[537] + amp[538] - std::complex (0, 1) * amp[539] + + amp[540] + amp[541] + amp[543] + amp[544] + amp[546] + amp[547] + + amp[549] + amp[550] - std::complex (0, 1) * amp[672] + + std::complex (0, 1) * amp[676] + amp[677] - std::complex + (0, 1) * amp[678] - std::complex (0, 1) * amp[679] + + std::complex (0, 1) * amp[685] - std::complex (0, 1) * + amp[687] - std::complex (0, 1) * amp[688] - std::complex + (0, 1) * amp[690] + std::complex (0, 1) * amp[694] + amp[695] - + std::complex (0, 1) * amp[696] - std::complex (0, 1) * + amp[697] + std::complex (0, 1) * amp[703] - std::complex + (0, 1) * amp[705] - std::complex (0, 1) * amp[706] - amp[708] - + std::complex (0, 1) * amp[710] - amp[712] - std::complex + (0, 1) * amp[713] - amp[715] - amp[716] - std::complex (0, 1) * + amp[718] - amp[720] - std::complex (0, 1) * amp[721] - amp[723] + + std::complex (0, 1) * amp[778] + amp[779] + std::complex + (0, 1) * amp[780] - std::complex (0, 1) * amp[784] - + std::complex (0, 1) * amp[783] + std::complex (0, 1) * + amp[787] + std::complex (0, 1) * amp[789] - amp[790] - + std::complex (0, 1) * amp[793] - std::complex (0, 1) * + amp[792] + std::complex (0, 1) * amp[796] + amp[797] + + std::complex (0, 1) * amp[798] - std::complex (0, 1) * + amp[802] - std::complex (0, 1) * amp[801] + std::complex + (0, 1) * amp[805] + std::complex (0, 1) * amp[807] - amp[808] - + std::complex (0, 1) * amp[811] - std::complex (0, 1) * + amp[810] - std::complex (0, 1) * amp[902] + std::complex + (0, 1) * amp[908] + std::complex (0, 1) * amp[907] - + std::complex (0, 1) * amp[910] - std::complex (0, 1) * + amp[911] + amp[912] + std::complex (0, 1) * amp[917] + + std::complex (0, 1) * amp[916] - std::complex (0, 1) * + amp[920] + std::complex (0, 1) * amp[926] + std::complex + (0, 1) * amp[925] - std::complex (0, 1) * amp[928] - + std::complex (0, 1) * amp[929] + amp[930] + std::complex + (0, 1) * amp[935] + std::complex (0, 1) * amp[934] - amp[962] - + amp[961] - std::complex (0, 1) * amp[965] - std::complex + (0, 1) * amp[964] - std::complex (0, 1) * amp[971] - + std::complex (0, 1) * amp[970] - amp[974] - amp[973] - + std::complex (0, 1) * amp[977] - std::complex (0, 1) * + amp[976] - std::complex (0, 1) * amp[983] - std::complex + (0, 1) * amp[982] - std::complex (0, 1) * amp[987] - + std::complex (0, 1) * amp[988] + amp[990] + amp[991] - + std::complex (0, 1) * amp[993] - std::complex (0, 1) * + amp[994] - std::complex (0, 1) * amp[999] - std::complex + (0, 1) * amp[1000] + amp[1002] + amp[1003] - std::complex (0, 1) + * amp[1005] - std::complex (0, 1) * amp[1006]; + jamp[17] = +amp[220] + amp[226] + amp[228] + amp[231] + amp[233] + amp[234] + + amp[237] + amp[239] + std::complex (0, 1) * amp[240] + + std::complex (0, 1) * amp[241] + std::complex (0, 1) * + amp[242] + std::complex (0, 1) * amp[243] + std::complex + (0, 1) * amp[276] - amp[277] + std::complex (0, 1) * amp[279] - + amp[280] + std::complex (0, 1) * amp[281] + std::complex + (0, 1) * amp[282] - amp[283] + std::complex (0, 1) * amp[285] - + amp[286] + std::complex (0, 1) * amp[287] - amp[301] + + std::complex (0, 1) * amp[303] - amp[304] - amp[307] + + std::complex (0, 1) * amp[309] - amp[310] + amp[314] - amp[312] + + amp[317] - amp[315] + amp[320] - amp[318] + amp[323] - amp[321] + + amp[432] + amp[438] + std::complex (0, 1) * amp[456] - amp[458] - + amp[460] + std::complex (0, 1) * amp[462] - amp[464] - amp[466] - + std::complex (0, 1) * amp[468] + amp[470] - std::complex + (0, 1) * amp[471] + amp[472] - std::complex (0, 1) * amp[473] - + std::complex (0, 1) * amp[474] + amp[476] - std::complex + (0, 1) * amp[477] + amp[478] - std::complex (0, 1) * amp[479] + + amp[480] + amp[481] + amp[483] + amp[484] + amp[486] + amp[487] + + amp[489] + amp[490] + std::complex (0, 1) * amp[672] - + std::complex (0, 1) * amp[676] - amp[677] + std::complex + (0, 1) * amp[678] + std::complex (0, 1) * amp[679] - + std::complex (0, 1) * amp[685] + std::complex (0, 1) * + amp[687] + std::complex (0, 1) * amp[688] + std::complex + (0, 1) * amp[690] - std::complex (0, 1) * amp[694] - amp[695] + + std::complex (0, 1) * amp[696] + std::complex (0, 1) * + amp[697] - std::complex (0, 1) * amp[703] + std::complex + (0, 1) * amp[705] + std::complex (0, 1) * amp[706] + amp[708] + + std::complex (0, 1) * amp[710] + amp[712] + std::complex + (0, 1) * amp[713] + amp[715] + amp[716] + std::complex (0, 1) * + amp[718] + amp[720] + std::complex (0, 1) * amp[721] + amp[723] - + std::complex (0, 1) * amp[866] - amp[867] - std::complex + (0, 1) * amp[868] + std::complex (0, 1) * amp[872] - + std::complex (0, 1) * amp[870] - std::complex (0, 1) * + amp[875] - std::complex (0, 1) * amp[877] - amp[878] + + std::complex (0, 1) * amp[881] - std::complex (0, 1) * + amp[879] - std::complex (0, 1) * amp[884] - amp[885] - + std::complex (0, 1) * amp[886] + std::complex (0, 1) * + amp[890] - std::complex (0, 1) * amp[888] - std::complex + (0, 1) * amp[893] - std::complex (0, 1) * amp[895] - amp[896] + + std::complex (0, 1) * amp[899] - std::complex (0, 1) * + amp[897] + std::complex (0, 1) * amp[904] - std::complex + (0, 1) * amp[908] + std::complex (0, 1) * amp[906] - + std::complex (0, 1) * amp[909] + std::complex (0, 1) * + amp[913] + amp[914] - std::complex (0, 1) * amp[917] + + std::complex (0, 1) * amp[915] + std::complex (0, 1) * + amp[922] - std::complex (0, 1) * amp[926] + std::complex + (0, 1) * amp[924] - std::complex (0, 1) * amp[927] + + std::complex (0, 1) * amp[931] + amp[932] - std::complex + (0, 1) * amp[935] + std::complex (0, 1) * amp[933] + amp[962] - + amp[960] + std::complex (0, 1) * amp[965] - std::complex + (0, 1) * amp[963] + std::complex (0, 1) * amp[971] - + std::complex (0, 1) * amp[969] + amp[974] - amp[972] + + std::complex (0, 1) * amp[977] - std::complex (0, 1) * + amp[975] + std::complex (0, 1) * amp[983] - std::complex + (0, 1) * amp[981] + std::complex (0, 1) * amp[1011] + + std::complex (0, 1) * amp[1012] + amp[1014] + amp[1015] + + std::complex (0, 1) * amp[1017] + std::complex (0, 1) * + amp[1018] + std::complex (0, 1) * amp[1023] + + std::complex (0, 1) * amp[1024] + amp[1026] + amp[1027] + + std::complex (0, 1) * amp[1029] + std::complex (0, 1) * + amp[1030]; + jamp[18] = +amp[325] + amp[331] + amp[369] + amp[370] + amp[372] + amp[375] + + amp[376] + amp[378] - std::complex (0, 1) * amp[380] - + std::complex (0, 1) * amp[381] - std::complex (0, 1) * + amp[382] - std::complex (0, 1) * amp[383] - amp[385] - + std::complex (0, 1) * amp[386] - amp[388] - amp[391] - + std::complex (0, 1) * amp[392] - amp[394] - std::complex + (0, 1) * amp[408] - amp[409] - std::complex (0, 1) * amp[410] - + amp[412] - std::complex (0, 1) * amp[413] - std::complex + (0, 1) * amp[414] - amp[415] - std::complex (0, 1) * amp[416] - + amp[418] - std::complex (0, 1) * amp[419] + amp[422] - amp[420] + + amp[425] - amp[423] + amp[428] - amp[426] + amp[431] - amp[429] + + amp[555] + amp[561] - std::complex (0, 1) * amp[564] + amp[566] + + amp[568] - std::complex (0, 1) * amp[570] + amp[572] + amp[574] + + std::complex (0, 1) * amp[577] + amp[578] + std::complex + (0, 1) * amp[579] + amp[580] + std::complex (0, 1) * amp[581] + + std::complex (0, 1) * amp[583] + amp[584] + std::complex + (0, 1) * amp[585] + amp[586] + std::complex (0, 1) * amp[587] - + amp[602] - amp[601] - amp[605] - amp[604] - amp[608] - amp[607] - + amp[611] - amp[610] - std::complex (0, 1) * amp[674] - amp[675] - + std::complex (0, 1) * amp[676] + std::complex (0, 1) * + amp[680] + std::complex (0, 1) * amp[679] - std::complex + (0, 1) * amp[683] - std::complex (0, 1) * amp[685] + amp[686] + + std::complex (0, 1) * amp[689] + std::complex (0, 1) * + amp[688] - std::complex (0, 1) * amp[692] - amp[693] - + std::complex (0, 1) * amp[694] + std::complex (0, 1) * + amp[698] + std::complex (0, 1) * amp[697] - std::complex + (0, 1) * amp[701] - std::complex (0, 1) * amp[703] + amp[704] + + std::complex (0, 1) * amp[707] + std::complex (0, 1) * + amp[706] - std::complex (0, 1) * amp[778] + std::complex + (0, 1) * amp[784] - std::complex (0, 1) * amp[782] + + std::complex (0, 1) * amp[786] - std::complex (0, 1) * + amp[787] + amp[788] + std::complex (0, 1) * amp[793] - + std::complex (0, 1) * amp[791] - std::complex (0, 1) * + amp[796] + std::complex (0, 1) * amp[802] - std::complex + (0, 1) * amp[800] + std::complex (0, 1) * amp[804] - + std::complex (0, 1) * amp[805] + amp[806] + std::complex + (0, 1) * amp[811] - std::complex (0, 1) * amp[809] + amp[813] - + std::complex (0, 1) * amp[814] + amp[815] - std::complex + (0, 1) * amp[817] + amp[818] + amp[821] - std::complex (0, 1) * + amp[822] + amp[823] - std::complex (0, 1) * amp[825] + amp[826] - + std::complex (0, 1) * amp[829] - std::complex (0, 1) * + amp[830] - amp[831] + std::complex (0, 1) * amp[836] + + std::complex (0, 1) * amp[835] - std::complex (0, 1) * + amp[839] + std::complex (0, 1) * amp[845] + std::complex + (0, 1) * amp[844] - std::complex (0, 1) * amp[847] - + std::complex (0, 1) * amp[848] - amp[849] + std::complex + (0, 1) * amp[854] + std::complex (0, 1) * amp[853] - + std::complex (0, 1) * amp[857] + std::complex (0, 1) * + amp[863] + std::complex (0, 1) * amp[862] + amp[938] - amp[936] + + std::complex (0, 1) * amp[941] - std::complex (0, 1) * + amp[939] + std::complex (0, 1) * amp[947] - std::complex + (0, 1) * amp[945] + amp[950] - amp[948] + std::complex (0, 1) * + amp[953] - std::complex (0, 1) * amp[951] + std::complex + (0, 1) * amp[959] - std::complex (0, 1) * amp[957] + + std::complex (0, 1) * amp[965] + std::complex (0, 1) * + amp[964] - amp[968] - amp[967] + std::complex (0, 1) * amp[971] + + std::complex (0, 1) * amp[970] + std::complex (0, 1) * + amp[977] + std::complex (0, 1) * amp[976] - amp[980] - amp[979] + + std::complex (0, 1) * amp[983] + std::complex (0, 1) * + amp[982]; + jamp[19] = +amp[324] + amp[330] + amp[353] + amp[354] + amp[356] + amp[359] + + amp[360] + amp[362] - std::complex (0, 1) * amp[364] - + std::complex (0, 1) * amp[365] - std::complex (0, 1) * + amp[366] - std::complex (0, 1) * amp[367] - amp[397] - + std::complex (0, 1) * amp[398] - amp[400] - amp[403] - + std::complex (0, 1) * amp[404] - amp[406] + std::complex + (0, 1) * amp[408] + amp[409] + std::complex (0, 1) * amp[410] + + amp[412] + std::complex (0, 1) * amp[413] + std::complex + (0, 1) * amp[414] + amp[415] + std::complex (0, 1) * amp[416] + + amp[418] + std::complex (0, 1) * amp[419] + amp[420] + amp[421] + + amp[423] + amp[424] + amp[426] + amp[427] + amp[429] + amp[430] + + amp[495] + amp[501] - std::complex (0, 1) * amp[504] + amp[506] + + amp[508] - std::complex (0, 1) * amp[510] + amp[512] + amp[514] + + std::complex (0, 1) * amp[517] + amp[518] + std::complex + (0, 1) * amp[519] + amp[520] + std::complex (0, 1) * amp[521] + + std::complex (0, 1) * amp[523] + amp[524] + std::complex + (0, 1) * amp[525] + amp[526] + std::complex (0, 1) * amp[527] - + amp[542] - amp[541] - amp[545] - amp[544] - amp[548] - amp[547] - + amp[551] - amp[550] - std::complex (0, 1) * amp[726] - amp[727] - + std::complex (0, 1) * amp[728] + std::complex (0, 1) * + amp[732] + std::complex (0, 1) * amp[731] - std::complex + (0, 1) * amp[735] - std::complex (0, 1) * amp[737] + amp[738] + + std::complex (0, 1) * amp[741] + std::complex (0, 1) * + amp[740] - std::complex (0, 1) * amp[744] - amp[745] - + std::complex (0, 1) * amp[746] + std::complex (0, 1) * + amp[750] + std::complex (0, 1) * amp[749] - std::complex + (0, 1) * amp[753] - std::complex (0, 1) * amp[755] + amp[756] + + std::complex (0, 1) * amp[759] + std::complex (0, 1) * + amp[758] - std::complex (0, 1) * amp[780] + std::complex + (0, 1) * amp[782] + std::complex (0, 1) * amp[783] + + std::complex (0, 1) * amp[785] - std::complex (0, 1) * + amp[789] + amp[790] + std::complex (0, 1) * amp[791] + + std::complex (0, 1) * amp[792] - std::complex (0, 1) * + amp[798] + std::complex (0, 1) * amp[800] + std::complex + (0, 1) * amp[801] + std::complex (0, 1) * amp[803] - + std::complex (0, 1) * amp[807] + amp[808] + std::complex + (0, 1) * amp[809] + std::complex (0, 1) * amp[810] - amp[813] + + std::complex (0, 1) * amp[814] - amp[815] + std::complex + (0, 1) * amp[817] - amp[818] - amp[821] + std::complex (0, 1) * + amp[822] - amp[823] + std::complex (0, 1) * amp[825] - amp[826] + + std::complex (0, 1) * amp[829] + std::complex (0, 1) * + amp[830] + amp[831] - std::complex (0, 1) * amp[836] - + std::complex (0, 1) * amp[835] + std::complex (0, 1) * + amp[839] - std::complex (0, 1) * amp[845] - std::complex + (0, 1) * amp[844] + std::complex (0, 1) * amp[847] + + std::complex (0, 1) * amp[848] + amp[849] - std::complex + (0, 1) * amp[854] - std::complex (0, 1) * amp[853] + + std::complex (0, 1) * amp[857] - std::complex (0, 1) * + amp[863] - std::complex (0, 1) * amp[862] + amp[936] + amp[937] + + std::complex (0, 1) * amp[939] + std::complex (0, 1) * + amp[940] + std::complex (0, 1) * amp[945] + std::complex + (0, 1) * amp[946] + amp[948] + amp[949] + std::complex (0, 1) * + amp[951] + std::complex (0, 1) * amp[952] + std::complex + (0, 1) * amp[957] + std::complex (0, 1) * amp[958] + + std::complex (0, 1) * amp[989] + std::complex (0, 1) * + amp[988] - amp[992] - amp[991] + std::complex (0, 1) * amp[995] + + std::complex (0, 1) * amp[994] + std::complex (0, 1) * + amp[1001] + std::complex (0, 1) * amp[1000] - amp[1004] - + amp[1003] + std::complex (0, 1) * amp[1007] + + std::complex (0, 1) * amp[1006]; + jamp[20] = +amp[327] + amp[333] + amp[368] + amp[371] + amp[373] + amp[374] + + amp[377] + amp[379] + std::complex (0, 1) * amp[380] + + std::complex (0, 1) * amp[381] + std::complex (0, 1) * + amp[382] + std::complex (0, 1) * amp[383] + amp[385] + + std::complex (0, 1) * amp[386] + amp[388] + amp[391] + + std::complex (0, 1) * amp[392] + amp[394] - std::complex + (0, 1) * amp[396] + amp[397] - std::complex (0, 1) * amp[399] + + amp[400] - std::complex (0, 1) * amp[401] - std::complex + (0, 1) * amp[402] + amp[403] - std::complex (0, 1) * amp[405] + + amp[406] - std::complex (0, 1) * amp[407] - amp[422] - amp[421] - + amp[425] - amp[424] - amp[428] - amp[427] - amp[431] - amp[430] + + amp[553] + amp[559] + std::complex (0, 1) * amp[564] - amp[566] - + amp[568] + std::complex (0, 1) * amp[570] - amp[572] - amp[574] + + std::complex (0, 1) * amp[588] - amp[590] + std::complex + (0, 1) * amp[591] - amp[592] + std::complex (0, 1) * amp[593] + + std::complex (0, 1) * amp[594] - amp[596] + std::complex + (0, 1) * amp[597] - amp[598] + std::complex (0, 1) * amp[599] + + amp[602] - amp[600] + amp[605] - amp[603] + amp[608] - amp[606] + + amp[611] - amp[609] + std::complex (0, 1) * amp[674] + amp[675] + + std::complex (0, 1) * amp[676] - std::complex (0, 1) * + amp[680] - std::complex (0, 1) * amp[679] + std::complex + (0, 1) * amp[683] + std::complex (0, 1) * amp[685] - amp[686] - + std::complex (0, 1) * amp[689] - std::complex (0, 1) * + amp[688] + std::complex (0, 1) * amp[692] + amp[693] + + std::complex (0, 1) * amp[694] - std::complex (0, 1) * + amp[698] - std::complex (0, 1) * amp[697] + std::complex + (0, 1) * amp[701] + std::complex (0, 1) * amp[703] - amp[704] - + std::complex (0, 1) * amp[707] - std::complex (0, 1) * + amp[706] - std::complex (0, 1) * amp[725] + std::complex + (0, 1) * amp[726] + amp[727] - std::complex (0, 1) * amp[732] + + std::complex (0, 1) * amp[730] + std::complex (0, 1) * + amp[735] - std::complex (0, 1) * amp[741] + std::complex + (0, 1) * amp[739] - std::complex (0, 1) * amp[743] + + std::complex (0, 1) * amp[744] + amp[745] - std::complex + (0, 1) * amp[750] + std::complex (0, 1) * amp[748] + + std::complex (0, 1) * amp[753] - std::complex (0, 1) * + amp[759] + std::complex (0, 1) * amp[757] + amp[760] + + std::complex (0, 1) * amp[762] + amp[764] + std::complex + (0, 1) * amp[765] + amp[767] + amp[768] + std::complex (0, 1) * + amp[770] + amp[772] + std::complex (0, 1) * amp[773] + amp[775] + + std::complex (0, 1) * amp[866] - std::complex (0, 1) * + amp[872] - std::complex (0, 1) * amp[871] + std::complex + (0, 1) * amp[874] + std::complex (0, 1) * amp[875] - amp[876] - + std::complex (0, 1) * amp[881] - std::complex (0, 1) * + amp[880] + std::complex (0, 1) * amp[884] - std::complex + (0, 1) * amp[890] - std::complex (0, 1) * amp[889] + + std::complex (0, 1) * amp[892] + std::complex (0, 1) * + amp[893] - amp[894] - std::complex (0, 1) * amp[899] - + std::complex (0, 1) * amp[898] - amp[938] - amp[937] - + std::complex (0, 1) * amp[941] - std::complex (0, 1) * + amp[940] - std::complex (0, 1) * amp[947] - std::complex + (0, 1) * amp[946] - amp[950] - amp[949] - std::complex (0, 1) * + amp[953] - std::complex (0, 1) * amp[952] - std::complex + (0, 1) * amp[959] - std::complex (0, 1) * amp[958] - + std::complex (0, 1) * amp[965] + std::complex (0, 1) * + amp[963] + amp[968] - amp[966] - std::complex (0, 1) * amp[971] + + std::complex (0, 1) * amp[969] - std::complex (0, 1) * + amp[977] + std::complex (0, 1) * amp[975] + amp[980] - amp[978] - + std::complex (0, 1) * amp[983] + std::complex (0, 1) * + amp[981]; + jamp[21] = +amp[326] + amp[332] + amp[337] + amp[338] + amp[340] + amp[343] + + amp[344] + amp[346] - std::complex (0, 1) * amp[348] - + std::complex (0, 1) * amp[349] - std::complex (0, 1) * + amp[350] - std::complex (0, 1) * amp[351] + std::complex + (0, 1) * amp[396] - amp[397] + std::complex (0, 1) * amp[399] - + amp[400] + std::complex (0, 1) * amp[401] + std::complex + (0, 1) * amp[402] - amp[403] + std::complex (0, 1) * amp[405] - + amp[406] + std::complex (0, 1) * amp[407] + amp[409] - + std::complex (0, 1) * amp[411] + amp[412] + amp[415] - + std::complex (0, 1) * amp[417] + amp[418] + amp[420] + amp[421] + + amp[423] + amp[424] + amp[426] + amp[427] + amp[429] + amp[430] + + amp[435] + amp[441] - std::complex (0, 1) * amp[444] + amp[446] + + amp[448] - std::complex (0, 1) * amp[450] + amp[452] + amp[454] + + std::complex (0, 1) * amp[457] + amp[458] + std::complex + (0, 1) * amp[459] + amp[460] + std::complex (0, 1) * amp[461] + + std::complex (0, 1) * amp[463] + amp[464] + std::complex + (0, 1) * amp[465] + amp[466] + std::complex (0, 1) * amp[467] - + amp[482] - amp[481] - amp[485] - amp[484] - amp[488] - amp[487] - + amp[491] - amp[490] + std::complex (0, 1) * amp[725] - + std::complex (0, 1) * amp[726] - amp[727] + std::complex + (0, 1) * amp[732] - std::complex (0, 1) * amp[730] - + std::complex (0, 1) * amp[735] + std::complex (0, 1) * + amp[741] - std::complex (0, 1) * amp[739] + std::complex + (0, 1) * amp[743] - std::complex (0, 1) * amp[744] - amp[745] + + std::complex (0, 1) * amp[750] - std::complex (0, 1) * + amp[748] - std::complex (0, 1) * amp[753] + std::complex + (0, 1) * amp[759] - std::complex (0, 1) * amp[757] - amp[760] - + std::complex (0, 1) * amp[762] - amp[764] - std::complex + (0, 1) * amp[765] - amp[767] - amp[768] - std::complex (0, 1) * + amp[770] - amp[772] - std::complex (0, 1) * amp[773] - amp[775] + + std::complex (0, 1) * amp[830] + amp[831] + std::complex + (0, 1) * amp[832] - std::complex (0, 1) * amp[836] + + std::complex (0, 1) * amp[834] + std::complex (0, 1) * + amp[839] + std::complex (0, 1) * amp[841] + amp[842] - + std::complex (0, 1) * amp[845] + std::complex (0, 1) * + amp[843] + std::complex (0, 1) * amp[848] + amp[849] + + std::complex (0, 1) * amp[850] - std::complex (0, 1) * + amp[854] + std::complex (0, 1) * amp[852] + std::complex + (0, 1) * amp[857] + std::complex (0, 1) * amp[859] + amp[860] - + std::complex (0, 1) * amp[863] + std::complex (0, 1) * + amp[861] + std::complex (0, 1) * amp[868] + std::complex + (0, 1) * amp[870] + std::complex (0, 1) * amp[871] + + std::complex (0, 1) * amp[873] + std::complex (0, 1) * + amp[877] + amp[878] + std::complex (0, 1) * amp[879] + + std::complex (0, 1) * amp[880] + std::complex (0, 1) * + amp[886] + std::complex (0, 1) * amp[888] + std::complex + (0, 1) * amp[889] + std::complex (0, 1) * amp[891] + + std::complex (0, 1) * amp[895] + amp[896] + std::complex + (0, 1) * amp[897] + std::complex (0, 1) * amp[898] + amp[936] + + amp[937] + std::complex (0, 1) * amp[939] + std::complex + (0, 1) * amp[940] + std::complex (0, 1) * amp[945] + + std::complex (0, 1) * amp[946] + amp[948] + amp[949] + + std::complex (0, 1) * amp[951] + std::complex (0, 1) * + amp[952] + std::complex (0, 1) * amp[957] + std::complex + (0, 1) * amp[958] - std::complex (0, 1) * amp[1013] - + std::complex (0, 1) * amp[1012] - amp[1016] - amp[1015] - + std::complex (0, 1) * amp[1019] - std::complex (0, 1) * + amp[1018] - std::complex (0, 1) * amp[1025] - + std::complex (0, 1) * amp[1024] - amp[1028] - amp[1027] - + std::complex (0, 1) * amp[1031] - std::complex (0, 1) * + amp[1030]; + jamp[22] = +amp[329] + amp[335] + amp[352] + amp[355] + amp[357] + amp[358] + + amp[361] + amp[363] + std::complex (0, 1) * amp[364] + + std::complex (0, 1) * amp[365] + std::complex (0, 1) * + amp[366] + std::complex (0, 1) * amp[367] - std::complex + (0, 1) * amp[384] + amp[385] - std::complex (0, 1) * amp[387] + + amp[388] - std::complex (0, 1) * amp[389] - std::complex + (0, 1) * amp[390] + amp[391] - std::complex (0, 1) * amp[393] + + amp[394] - std::complex (0, 1) * amp[395] + amp[397] + + std::complex (0, 1) * amp[398] + amp[400] + amp[403] + + std::complex (0, 1) * amp[404] + amp[406] - amp[422] - amp[421] - + amp[425] - amp[424] - amp[428] - amp[427] - amp[431] - amp[430] + + amp[493] + amp[499] + std::complex (0, 1) * amp[504] - amp[506] - + amp[508] + std::complex (0, 1) * amp[510] - amp[512] - amp[514] + + std::complex (0, 1) * amp[528] - amp[530] + std::complex + (0, 1) * amp[531] - amp[532] + std::complex (0, 1) * amp[533] + + std::complex (0, 1) * amp[534] - amp[536] + std::complex + (0, 1) * amp[537] - amp[538] + std::complex (0, 1) * amp[539] + + amp[542] - amp[540] + amp[545] - amp[543] + amp[548] - amp[546] + + amp[551] - amp[549] - std::complex (0, 1) * amp[673] + + std::complex (0, 1) * amp[674] + amp[675] - std::complex + (0, 1) * amp[680] + std::complex (0, 1) * amp[678] + + std::complex (0, 1) * amp[683] - std::complex (0, 1) * + amp[689] + std::complex (0, 1) * amp[687] - std::complex + (0, 1) * amp[691] + std::complex (0, 1) * amp[692] + amp[693] - + std::complex (0, 1) * amp[698] + std::complex (0, 1) * + amp[696] + std::complex (0, 1) * amp[701] - std::complex + (0, 1) * amp[707] + std::complex (0, 1) * amp[705] + amp[708] + + std::complex (0, 1) * amp[710] + amp[712] + std::complex + (0, 1) * amp[713] + amp[715] + amp[716] + std::complex (0, 1) * + amp[718] + amp[720] + std::complex (0, 1) * amp[721] + amp[723] + + std::complex (0, 1) * amp[726] + amp[727] + std::complex + (0, 1) * amp[728] - std::complex (0, 1) * amp[732] - + std::complex (0, 1) * amp[731] + std::complex (0, 1) * + amp[735] + std::complex (0, 1) * amp[737] - amp[738] - + std::complex (0, 1) * amp[741] - std::complex (0, 1) * + amp[740] + std::complex (0, 1) * amp[744] + amp[745] + + std::complex (0, 1) * amp[746] - std::complex (0, 1) * + amp[750] - std::complex (0, 1) * amp[749] + std::complex + (0, 1) * amp[753] + std::complex (0, 1) * amp[755] - amp[756] - + std::complex (0, 1) * amp[759] - std::complex (0, 1) * + amp[758] + std::complex (0, 1) * amp[902] - std::complex + (0, 1) * amp[908] - std::complex (0, 1) * amp[907] + + std::complex (0, 1) * amp[910] + std::complex (0, 1) * + amp[911] - amp[912] - std::complex (0, 1) * amp[917] - + std::complex (0, 1) * amp[916] + std::complex (0, 1) * + amp[920] - std::complex (0, 1) * amp[926] - std::complex + (0, 1) * amp[925] + std::complex (0, 1) * amp[928] + + std::complex (0, 1) * amp[929] - amp[930] - std::complex + (0, 1) * amp[935] - std::complex (0, 1) * amp[934] - amp[938] - + amp[937] - std::complex (0, 1) * amp[941] - std::complex + (0, 1) * amp[940] - std::complex (0, 1) * amp[947] - + std::complex (0, 1) * amp[946] - amp[950] - amp[949] - + std::complex (0, 1) * amp[953] - std::complex (0, 1) * + amp[952] - std::complex (0, 1) * amp[959] - std::complex + (0, 1) * amp[958] - std::complex (0, 1) * amp[989] + + std::complex (0, 1) * amp[987] + amp[992] - amp[990] - + std::complex (0, 1) * amp[995] + std::complex (0, 1) * + amp[993] - std::complex (0, 1) * amp[1001] + std::complex + (0, 1) * amp[999] + amp[1004] - amp[1002] - std::complex (0, 1) * + amp[1007] + std::complex (0, 1) * amp[1005]; + jamp[23] = +amp[328] + amp[334] + amp[336] + amp[339] + amp[341] + amp[342] + + amp[345] + amp[347] + std::complex (0, 1) * amp[348] + + std::complex (0, 1) * amp[349] + std::complex (0, 1) * + amp[350] + std::complex (0, 1) * amp[351] + std::complex + (0, 1) * amp[384] - amp[385] + std::complex (0, 1) * amp[387] - + amp[388] + std::complex (0, 1) * amp[389] + std::complex + (0, 1) * amp[390] - amp[391] + std::complex (0, 1) * amp[393] - + amp[394] + std::complex (0, 1) * amp[395] - amp[409] + + std::complex (0, 1) * amp[411] - amp[412] - amp[415] + + std::complex (0, 1) * amp[417] - amp[418] + amp[422] - amp[420] + + amp[425] - amp[423] + amp[428] - amp[426] + amp[431] - amp[429] + + amp[433] + amp[439] + std::complex (0, 1) * amp[444] - amp[446] - + amp[448] + std::complex (0, 1) * amp[450] - amp[452] - amp[454] + + std::complex (0, 1) * amp[468] - amp[470] + std::complex + (0, 1) * amp[471] - amp[472] + std::complex (0, 1) * amp[473] + + std::complex (0, 1) * amp[474] - amp[476] + std::complex + (0, 1) * amp[477] - amp[478] + std::complex (0, 1) * amp[479] + + amp[482] - amp[480] + amp[485] - amp[483] + amp[488] - amp[486] + + amp[491] - amp[489] + std::complex (0, 1) * amp[673] - + std::complex (0, 1) * amp[674] - amp[675] + std::complex + (0, 1) * amp[680] - std::complex (0, 1) * amp[678] - + std::complex (0, 1) * amp[683] + std::complex (0, 1) * + amp[689] - std::complex (0, 1) * amp[687] + std::complex + (0, 1) * amp[691] - std::complex (0, 1) * amp[692] - amp[693] + + std::complex (0, 1) * amp[698] - std::complex (0, 1) * + amp[696] - std::complex (0, 1) * amp[701] + std::complex + (0, 1) * amp[707] - std::complex (0, 1) * amp[705] - amp[708] - + std::complex (0, 1) * amp[710] - amp[712] - std::complex + (0, 1) * amp[713] - amp[715] - amp[716] - std::complex (0, 1) * + amp[718] - amp[720] - std::complex (0, 1) * amp[721] - amp[723] - + std::complex (0, 1) * amp[830] - amp[831] - std::complex + (0, 1) * amp[832] + std::complex (0, 1) * amp[836] - + std::complex (0, 1) * amp[834] - std::complex (0, 1) * + amp[839] - std::complex (0, 1) * amp[841] - amp[842] + + std::complex (0, 1) * amp[845] - std::complex (0, 1) * + amp[843] - std::complex (0, 1) * amp[848] - amp[849] - + std::complex (0, 1) * amp[850] + std::complex (0, 1) * + amp[854] - std::complex (0, 1) * amp[852] - std::complex + (0, 1) * amp[857] - std::complex (0, 1) * amp[859] - amp[860] + + std::complex (0, 1) * amp[863] - std::complex (0, 1) * + amp[861] - std::complex (0, 1) * amp[904] + std::complex + (0, 1) * amp[908] - std::complex (0, 1) * amp[906] + + std::complex (0, 1) * amp[909] - std::complex (0, 1) * + amp[913] - amp[914] + std::complex (0, 1) * amp[917] - + std::complex (0, 1) * amp[915] - std::complex (0, 1) * + amp[922] + std::complex (0, 1) * amp[926] - std::complex + (0, 1) * amp[924] + std::complex (0, 1) * amp[927] - + std::complex (0, 1) * amp[931] - amp[932] + std::complex + (0, 1) * amp[935] - std::complex (0, 1) * amp[933] + amp[938] - + amp[936] + std::complex (0, 1) * amp[941] - std::complex + (0, 1) * amp[939] + std::complex (0, 1) * amp[947] - + std::complex (0, 1) * amp[945] + amp[950] - amp[948] + + std::complex (0, 1) * amp[953] - std::complex (0, 1) * + amp[951] + std::complex (0, 1) * amp[959] - std::complex + (0, 1) * amp[957] + std::complex (0, 1) * amp[1013] - + std::complex (0, 1) * amp[1011] + amp[1016] - amp[1014] + + std::complex (0, 1) * amp[1019] - std::complex (0, 1) * + amp[1017] + std::complex (0, 1) * amp[1025] - + std::complex (0, 1) * amp[1023] + amp[1028] - amp[1026] + + std::complex (0, 1) * amp[1031] - std::complex (0, 1) * + amp[1029]; + + // Store the leading color flows for choice of color + for(int i = 0; i < ncolor; i++ ) + jamp2[0][i] += real(jamp[i] * conj(jamp[i])); + + return -1.; +} + + +double eeuugggg::get_jamp2(int i) +{ + return jamp2[0][i]; +} + +int eeuugggg::colorstring(int i, int j) +{ + static const int res[24][8] = { + {5, 6, 7, 8, 3, 4, 0, 0}, + {5, 6, 8, 7, 3, 4, 0, 0}, + {5, 7, 6, 8, 3, 4, 0, 0}, + {5, 7, 8, 6, 3, 4, 0, 0}, + {5, 8, 6, 7, 3, 4, 0, 0}, + {5, 8, 7, 6, 3, 4, 0, 0}, + {6, 5, 7, 8, 3, 4, 0, 0}, + {6, 5, 8, 7, 3, 4, 0, 0}, + {6, 7, 5, 8, 3, 4, 0, 0}, + {6, 7, 8, 5, 3, 4, 0, 0}, + {6, 8, 5, 7, 3, 4, 0, 0}, + {6, 8, 7, 5, 3, 4, 0, 0}, + {7, 5, 6, 8, 3, 4, 0, 0}, + {7, 5, 8, 6, 3, 4, 0, 0}, + {7, 6, 5, 8, 3, 4, 0, 0}, + {7, 6, 8, 5, 3, 4, 0, 0}, + {7, 8, 5, 6, 3, 4, 0, 0}, + {7, 8, 6, 5, 3, 4, 0, 0}, + {8, 5, 6, 7, 3, 4, 0, 0}, + {8, 5, 7, 6, 3, 4, 0, 0}, + {8, 6, 5, 7, 3, 4, 0, 0}, + {8, 6, 7, 5, 3, 4, 0, 0}, + {8, 7, 5, 6, 3, 4, 0, 0}, + {8, 7, 6, 5, 3, 4, 0, 0}}; + return res[i][j]; +} + + +int eeuugggg::NCol() +{ + static const int ncolor = 24; + return ncolor; +} + + + + + + + + + + + + diff --git a/Shower/Dipole/Colorea/eeuugggg.h b/Shower/Dipole/Colorea/eeuugggg.h new file mode 100644 --- /dev/null +++ b/Shower/Dipole/Colorea/eeuugggg.h @@ -0,0 +1,52 @@ + //========================================================================== + // This file has been automatically generated for C++ Standalone by + // MadGraph5_aMC@NLO v. 2.5.4, 2017-03-28 + // By the MadGraph5_aMC@NLO Development Team + // Visit launchpad.net/madgraph5 and amcatnlo.web.cern.ch + //========================================================================== + // and was then modified by J. Bellm. +#ifndef MG5_Sigma_sm_epem_uuxgggg_H +#define MG5_Sigma_sm_epem_uuxgggg_H +#include +#include +#include "Parameters_sm.h" +using namespace std; +class eeuugggg +{ + public: + eeuugggg(){ + initProc("param_card.dat"); + } + // Retrun the prefered gluon order + vector producePermutation(double r,vector < double * > & momenta); + void setMass(int i,double M){mME[i]=M;} + private: + ///////// Process Dependent + static const int ninitial = 2; + static const int nexternal = 8; + static const int nprocesses = 1; + static const int nwavefuncs = 205; + static const int namplitudes = 1032; + std::complex w[nwavefuncs][18]; + double matrix_1_epem_uuxgggg(); + ///////// Generic + double matrix_element[nprocesses]; + std::complex amp[namplitudes]; + double * jamp2[nprocesses]; + Parameters_sm * pars; + vector mME; + vector < double * > p; + int id1, id2; + void initProc(string param_card_name); + void sigmaKin(); + const vector & getMasses() const {return mME;} + vector < double * > getMomenta(){return p;} + void setMomenta(vector < double * > & momenta){p = momenta;} + void setInitial(int inid1, int inid2){id1 = inid1; id2 = inid2;} + void calculate_wavefunctions(const int perm[], const int hel[]); + // New function + double get_jamp2(int i); + int colorstring(int i, int j); + int NCol(); +}; +#endif // MG5_Sigma_sm_epem_uuxgggg_H diff --git a/Shower/Dipole/Colorea/read_slha_COLOREA.cc b/Shower/Dipole/Colorea/read_slha_COLOREA.cc new file mode 100644 --- /dev/null +++ b/Shower/Dipole/Colorea/read_slha_COLOREA.cc @@ -0,0 +1,144 @@ +#include +#include +#include +#include "read_slha_COLOREA.h" + +void SLHABlock_COLOREA::set_entry(std::vector indices, double value) +{ + if (_entries.size() == 0) + _indices = indices.size(); + else if(indices.size() != _indices) + throw "Wrong number of indices in set_entry"; + + _entries[indices] = value; +} + +double SLHABlock_COLOREA::get_entry(std::vector indices, double def_val) +{ + if (_entries.find(indices) == _entries.end()){ + std::cout << "Warning: No such entry in " << _name << ", using default value " + << def_val << std::endl; + return def_val; + } + return _entries[indices]; +} + +void SLHAReader_COLOREA::read_slha_file(std::string file_name) +{ + std::ifstream param_card; + param_card.open(file_name.c_str(), std::ifstream::in); + if(!param_card.good()) + throw "Error while opening param card"; + std::cout << "\nColorea: Opened slha file " << file_name << " for reading" << std::endl; + char buf[200]; + std::string line; + std::string block(""); + + while(param_card.good()){ + param_card.getline(buf, 200); + line = buf; + // Change to lowercase + transform(line.begin(), line.end(), line.begin(), (int(*)(int)) tolower); + if(line != "" && line[0] != '#'){ + if(block != ""){ + // Look for double index blocks + double dindex1, dindex2; + double value; + std::stringstream linestr2(line); + if (linestr2 >> dindex1 >> dindex2 >> value && + dindex1 == int(dindex1) and dindex2 == int(dindex2)) + { + std::vector indices; + indices.push_back(int(dindex1)); + indices.push_back(int(dindex2)); + set_block_entry(block, indices, value); + // Done with this line, read next + continue; + } + std::stringstream linestr1(line); + // Look for single index blocks + if(linestr1 >> dindex1 >> value && dindex1 == int(dindex1)) + { + std::vector indices; + indices.push_back(int(dindex1)); + set_block_entry(block, indices, value); + // Done with this line, read next + continue; + } + } + // Look for block + if(line.find("block ") != line.npos){ + line = line.substr(6); + // Get rid of spaces between block and block name + while (line[0] == ' ') + line = line.substr(1); + // Now find end of block name + int space_pos = line.find(' '); + if(space_pos != line.npos) + line = line.substr(0, space_pos); + block = line; + continue; + } + // Look for decay + if(line.find("decay ") == 0){ + line = line.substr(6); + block = ""; + std::stringstream linestr(line); + int pdg_code; + double value; + if(linestr >> pdg_code >> value) + set_block_entry("decay", pdg_code, value); + else + std::cout << "Warning: Wrong format for decay block " << line << std::endl; + continue; + } + } + } + + if (_blocks.size() == 0) + throw "No information read from SLHA card"; + + param_card.close(); +} + +double SLHAReader_COLOREA::get_block_entry(std::string block_name, std::vector indices, + double def_val) +{ + if (_blocks.find(block_name) == _blocks.end()){ + std::cout << "No such block " << block_name << ", using default value " + << def_val << std::endl; + return def_val; + } + return _blocks[block_name].get_entry(indices); +} + +double SLHAReader_COLOREA::get_block_entry(std::string block_name, int index, + double def_val) +{ + std::vector indices; + indices.push_back(index); + return get_block_entry(block_name, indices, def_val); +} + + +void SLHAReader_COLOREA::set_block_entry(std::string block_name, std::vector indices, + double value) +{ + if (_blocks.find(block_name) == _blocks.end()){ + SLHABlock_COLOREA block(block_name); + _blocks[block_name] = block; + } + _blocks[block_name].set_entry(indices, value); + /* cout << "Set block " << block_name << " entry "; + for (int i=0;i < indices.size();i++) + cout << indices[i] << " "; + cout << "to " << _blocks[block_name].get_entry(indices) << endl;*/ +} + +void SLHAReader_COLOREA::set_block_entry(std::string block_name, int index, + double value) +{ + std::vector indices; + indices.push_back(index); + set_block_entry(block_name, indices, value); +} diff --git a/Shower/Dipole/Colorea/read_slha_COLOREA.h b/Shower/Dipole/Colorea/read_slha_COLOREA.h new file mode 100644 --- /dev/null +++ b/Shower/Dipole/Colorea/read_slha_COLOREA.h @@ -0,0 +1,46 @@ +#ifndef READ_SLHA_H +#define READ_SLHA_H + +#include +#include +#include +#include + +class SLHABlock_COLOREA +{ + public: + SLHABlock_COLOREA(std::string name = ""){_name = name;} + ~SLHABlock_COLOREA(){} + + void set_entry(std::vector indices, double value); + double get_entry(std::vector indices, double def_val = 0); + void set_name(std::string name) {_name = name;} + std::string get_name(){return _name;} + int get_indices() { return _indices;} + + private: + std::string _name; + std::map, double> _entries; + unsigned int _indices; +}; + +class SLHAReader_COLOREA +{ + public: + SLHAReader_COLOREA(std::string file_name = "") + {if(file_name != "") read_slha_file(file_name);} + + void read_slha_file(std::string file_name); + double get_block_entry(std::string block_name, std::vector indices, + double def_val = 0); + double get_block_entry(std::string block_name, int index, + double def_val = 0); + void set_block_entry(std::string block_name, std::vector indices, + double value); + void set_block_entry(std::string block_name, int index, + double value); + private: + std::map _blocks; +}; + +#endif diff --git a/Shower/Dipole/DipoleShowerHandler.cc b/Shower/Dipole/DipoleShowerHandler.cc --- a/Shower/Dipole/DipoleShowerHandler.cc +++ b/Shower/Dipole/DipoleShowerHandler.cc @@ -1,1320 +1,1384 @@ // -*- C++ -*- // // DipoleShowerHandler.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 DipoleShowerHandler class. // #include #include "DipoleShowerHandler.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.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 theses to have complete types #include "Herwig/PDF/MPIPDF.h" #include "Herwig/PDF/MinBiasPDF.h" #include "Herwig/PDF/HwRemDecayer.h" #include "Herwig/Shower/Dipole/Utility/DipolePartonSplitter.h" #include "Herwig/MatrixElement/Matchbox/Base/MergerBase.h" #include "Herwig/MatrixElement/Matchbox/Base/SubtractedME.h" #include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h" #include using namespace Herwig; bool DipoleShowerHandler::firstWarn = true; DipoleShowerHandler::DipoleShowerHandler() : ShowerHandler(), chainOrderVetoScales(true), nEmissions(0), discardNoEmissions(false), firstMCatNLOEmission(false), thePowhegDecayEmission(true), realignmentScheme(0), verbosity(0), printEvent(0), nTries(0), didRadiate(false), didRealign(false), theRenormalizationScaleFreeze(1.*GeV), theFactorizationScaleFreeze(2.*GeV), theDoCompensate(false), theFreezeGrid(500000), theDetuning(1.0), maxPt(ZERO), muPt(ZERO), - theInputColouredOffShellInShower() {} + theInputColouredOffShellInShower(), + theZBoundaries(1) {} DipoleShowerHandler::~DipoleShowerHandler() {} IBPtr DipoleShowerHandler::clone() const { return new_ptr(*this); } IBPtr DipoleShowerHandler::fullclone() const { return new_ptr(*this); } void DipoleShowerHandler::cascade(tPVector ) { throw Exception() << "DipoleShowerHandler: Dipoleshower not implemented as second shower." << "Check your setup or contact Herwig authors." << Exception::runerror; } tPPair DipoleShowerHandler::cascade(tSubProPtr sub, XCombPtr, Energy optHardPt, Energy optCutoff) { useMe(); prepareCascade(sub); resetWeights(); if ( !doFSR() && ! doISR() ) return sub->incoming(); eventRecord().clear(); eventRecord().prepare(sub, dynamic_ptr_cast(lastXCombPtr()), newStep(), pdfs(), ShowerHandler::currentHandler()->generator()->currentEvent()->incoming(), firstInteraction(), offShellPartons()); if ( eventRecord().outgoing().empty() && !doISR() ) return sub->incoming(); if ( !eventRecord().incoming().first->coloured() && !eventRecord().incoming().second->coloured() && !doFSR() ) return sub->incoming(); nTries = 0; while ( true ) { try { didRadiate = false; didRealign = false; if ( eventRecord().truncatedShower() ) { throw Exception() << "Inconsistent hard emission set-up in DipoleShowerHandler::cascade. " << "No truncated shower needed with DipoleShowerHandler. Add " << "'set MEMatching:TruncatedShower No' to input file." << Exception::runerror; } hardScales(lastXCombPtr()->lastShowerScale()); if ( verbosity > 1 ) { generator()->log() << "DipoleShowerHandler starting off:\n"; eventRecord().debugLastEvent(generator()->log()); generator()->log() << flush; } unsigned int nEmitted = 0; if ( firstMCatNLOEmission ) { if ( !eventRecord().isMCatNLOHEvent() ) nEmissions = 1; else nEmissions = 0; } if ( !firstMCatNLOEmission ) { doCascade(nEmitted,optHardPt,optCutoff); if ( discardNoEmissions ) { if ( !didRadiate ) throw Veto(); if ( nEmissions ) if ( nEmissions < nEmitted ) throw Veto(); } } else { if ( nEmissions == 1 ) doCascade(nEmitted,optHardPt,optCutoff); } if ( intrinsicPtGenerator ) { if ( eventRecord().incoming().first->coloured() && eventRecord().incoming().second->coloured() ) { SpinOneLorentzRotation rot = intrinsicPtGenerator->kick(eventRecord().incoming(), eventRecord().intermediates()); eventRecord().transform(rot); } } didRealign = realign(); constituentReshuffle(); // Decay and shower any particles that require decaying while ( !eventRecord().decays().empty() ) { map::const_iterator decayIt = eventRecord().decays().begin(); // find the decay to do, one with greatest width and parent showered while(find(eventRecord().outgoing().begin(),eventRecord().outgoing().end(),decayIt->first)== eventRecord().outgoing().end() && find(eventRecord().hard().begin(),eventRecord().hard().end(),decayIt->first)== eventRecord().hard().end()) ++decayIt; assert(decayIt!=eventRecord().decays().end()); PPtr incoming = decayIt->first; eventRecord().currentDecay(decayIt->second); // Use this to record if an emission actually happens bool powhegEmission = !( nEmissions && nEmitted==nEmissions) ? thePowhegDecayEmission : false; // Decay the particle / sort out its pert proc Energy showerScale = eventRecord().decay(incoming, powhegEmission); // Following the decay, the bool powheg emission is updated // to indicate whether or not an emission occurred if ( powhegEmission ) nEmitted += 1; // Check that there is only one particle incoming to the decay assert(eventRecord().currentDecay()->incoming().size()==1); // Prepare the event record for the showering of the decay bool needToShower = eventRecord().prepareDecay(eventRecord().currentDecay(), offShellPartons()); // Only need to shower if we have coloured outgoing particles if ( needToShower ) { // The decays currently considered produce a maximum of 2 chains (with powheg emission) // so all dipole should have the same scale as returned by the decay function. assert( eventRecord().chains().size() <= 2 ); for ( auto & ch : eventRecord().chains()) { for ( auto & dip : ch.dipoles()) { assert ( showerScale > ZERO ); dip.leftScale( showerScale ); dip.rightScale( showerScale ); } } // Perform the cascade doCascade(nEmitted,optHardPt,optCutoff,true); // Do the constituent mass shell reshuffling decayConstituentReshuffle(eventRecord().currentDecay()); } // Update the decays, adding any decays and updating momenta eventRecord().updateDecays(eventRecord().currentDecay()); eventRecord().decays().erase(decayIt); } break; } catch (RedoShower&) { resetWeights(); if ( ++nTries > maxtry() ) throw ShowerTriesVeto(maxtry()); eventRecord().clear(); eventRecord().prepare(sub, dynamic_ptr_cast(lastXCombPtr()), newStep(), pdfs(), ShowerHandler::currentHandler()->generator()->currentEvent()->incoming(), firstInteraction(), offShellPartons()); continue; } catch (...) { throw; } } tPPair incoming=eventRecord().fillEventRecord(newStep(),firstInteraction(),didRealign); setDidRunCascade(true); return incoming; } // Reshuffle the outgoing partons from the hard process onto their constituent mass shells void DipoleShowerHandler::constituentReshuffle() { if ( constituentReshuffler ) { if ( eventRecord().decays().empty() ) { constituentReshuffler->reshuffle(eventRecord().outgoing(), eventRecord().incoming(), eventRecord().intermediates()); return; } else { PList decaying; for(auto const & dec : eventRecord().decays()) decaying.push_back(dec.first); constituentReshuffler->hardProcDecayReshuffle( decaying, eventRecord().outgoing(), eventRecord().hard(), eventRecord().incoming(), eventRecord().intermediates()); } } // After reshuffling the hard process, the decays need to be updated // as this is not done in reshuffle vector > decays; for(auto const & dec : eventRecord().decays() ) decays.push_back({dec.first,dec.second}); for(auto const & dec : decays) { PPtr unstable = dec.first; PList::iterator pos = find(eventRecord().intermediates().begin(), eventRecord().intermediates().end(), dec.first); // Update the PPtr in theDecays if(pos!=eventRecord().intermediates().end()) { unstable = *pos; while(!unstable->children().empty()) { unstable = unstable->children()[0]; } eventRecord().decays().erase(dec.first); eventRecord().decays()[unstable] = dec.second; // Update the momenta of any other particles in the decay chain // (for externally provided events) if ( !(eventRecord().decays()[unstable]->outgoing().empty()) ) eventRecord().updateDecayChainMom( unstable , eventRecord().decays()[unstable]); } else { if ( !(eventRecord().decays()[unstable]->outgoing().empty()) ) { // Update the momenta of any other particles in the decay chain // (for externally provided events) // Note this needs to be done for all decaying particles in the // outgoing/hard regardless of whether that particle radiated // or was involved in the reshuffling, this is due to the // transformation performed for IILightKinematics. if ( (find(eventRecord().outgoing().begin(), eventRecord().outgoing().end(), unstable) != eventRecord().outgoing().end()) || (find(eventRecord().hard().begin(), eventRecord().hard().end(), unstable) != eventRecord().hard().end()) ) eventRecord().updateDecayChainMom( unstable , eventRecord().decays()[unstable]); } } } eventRecord().currentDecay(PerturbativeProcessPtr()); } // Reshuffle outgoing partons from a decay process onto their constituent mass shells void DipoleShowerHandler::decayConstituentReshuffle(PerturbativeProcessPtr decayProc) { if ( Debug::level > 2 ){ // Test this function by comparing the // invariant mass of the outgoing decay // systems before and after reshuffling Lorentz5Momentum testOutMomBefore (ZERO,ZERO,ZERO,ZERO); Energy testInvMassBefore = ZERO; for ( auto const & testDecayOutItBefore : decayProc->outgoing() ) { testOutMomBefore += testDecayOutItBefore.first->momentum(); } testInvMassBefore = testOutMomBefore.m(); // decayReshuffle updates both the event record and the decay perturbative process if ( constituentReshuffler ) { constituentReshuffler->decayReshuffle(decayProc, eventRecord().outgoing(), eventRecord().hard(), eventRecord().intermediates()); } Lorentz5Momentum testOutMomAfter (ZERO,ZERO,ZERO,ZERO); Energy testInvMassAfter = ZERO; for ( auto const & testDecayOutItAfter : decayProc->outgoing() ) { testOutMomAfter += testDecayOutItAfter.first->momentum(); } testInvMassAfter = testOutMomAfter.m(); Energy incomingMass = decayProc->incoming()[0].first->momentum().m(); assert( abs(testInvMassBefore-incomingMass)/GeV < 1e-5 ); assert( abs(testInvMassBefore-testInvMassAfter)/GeV < 1e-5); }else{ // decayReshuffle updates both the event record and the decay perturbative process if ( constituentReshuffler ) { constituentReshuffler->decayReshuffle(decayProc, eventRecord().outgoing(), eventRecord().hard(), eventRecord().intermediates()); } return; } } // Sets the scale of each particle in the dipole chains by finding the smallest //of several upper bound energy scales: the CMEnergy of the event, //the transverse mass of outgoing particles, the hardScale (maxPT or maxQ) //calculated for each dipole (in both configurations) and the veto scale for each particle void DipoleShowerHandler::hardScales(Energy2 muf) { // Initalise maximum pt as max CMEnergy of the event maxPt = generator()->maximumCMEnergy(); if ( restrictPhasespace() ) { // First interaction == hard collision (i.e. not a MPI collision) if ( !hardScaleIsMuF() || !firstInteraction() ) { if ( !eventRecord().outgoing().empty() ) { for ( auto const & p : eventRecord().outgoing() ) maxPt = min(maxPt,p->momentum().mt()); } //Look at any non-coloured outgoing particles in the current subprocess else { assert(!eventRecord().hard().empty()); Lorentz5Momentum phard(ZERO,ZERO,ZERO,ZERO); for ( auto const & p : eventRecord().hard()) phard += p->momentum(); Energy mhard = phard.m(); maxPt = mhard; } maxPt *= hardScaleFactor(); } else { maxPt = hardScaleFactor()*sqrt(muf); } muPt = maxPt; } else { muPt = hardScaleFactor()*sqrt(muf); } for ( auto & ch : eventRecord().chains()) { // Note that minVetoScale is a value for each DipoleChain, not each dipole // It will contain the minimum veto scale from all of the dipoles in the chain Energy minVetoScale = -1.*GeV; for ( auto & dip : ch.dipoles()) { // max scale per config Energy maxFirst = ZERO; Energy maxSecond = ZERO; // Loop over the kernels for the given dipole. // For each dipole configuration, calculate ptMax (or QMax if virtuality ordering) // for each kernel and find the maximum for ( auto const & k : kernels) { pair conf = {true,false}; if ( k->canHandle(dip.index(conf)) ) { // Look in DipoleChainOrdering for this Energy scale = evolutionOrdering()->hardScale(dip.emitter(conf),dip.spectator(conf), dip.emitterX(conf),dip.spectatorX(conf), *k,dip.index(conf)); maxFirst = max(maxFirst,scale); } conf = {false,true}; if ( k->canHandle(dip.index(conf)) ) { Energy scale = evolutionOrdering()->hardScale(dip.emitter(conf),dip.spectator(conf), dip.emitterX(conf),dip.spectatorX(conf), *k,dip.index(conf)); maxSecond = max(maxSecond,scale); } } // Find the maximum value from comparing the maxScale found from maxPt and the vetoScale of the particle if ( dip.leftParticle()->vetoScale() >= ZERO ) { maxFirst = min(maxFirst,sqrt(dip.leftParticle()->vetoScale())); // minVetoScale is a value for each DipoleChain, not each dipole // It contains the minimum veto scale for all the dipoles in the entire DipoleChain if ( minVetoScale >= ZERO ) minVetoScale = min(minVetoScale,sqrt(dip.leftParticle()->vetoScale())); else minVetoScale = sqrt(dip.leftParticle()->vetoScale()); } if ( dip.rightParticle()->vetoScale() >= ZERO ) { maxSecond = min(maxSecond,sqrt(dip.rightParticle()->vetoScale())); if ( minVetoScale >= ZERO ) minVetoScale = min(minVetoScale,sqrt(dip.rightParticle()->vetoScale())); else minVetoScale = sqrt(dip.rightParticle()->vetoScale()); } // Set the emitterScale for both members of each dipole maxFirst = min(maxPt,maxFirst); dip.emitterScale({true,false},maxFirst); maxSecond = min(maxPt,maxSecond); dip.emitterScale({false,true},maxSecond); } // if the smallest veto scale (i.e. from all of the dipoles) // is smaller than the scale calculated for a particular // particle in a particular dipole, // replace the scale with the veto scale if ( !evolutionOrdering()->independentDipoles() && chainOrderVetoScales && minVetoScale >= ZERO ) { for ( auto & dip : ch.dipoles() ) { dip.leftScale(min(dip.leftScale(),minVetoScale)); dip.rightScale(min(dip.rightScale(),minVetoScale)); } } } } Energy DipoleShowerHandler::getWinner(DipoleSplittingInfo& winner, const Dipole& dip, pair conf, Energy optHardPt, Energy optCutoff) { return getWinner(winner,dip.index(conf), dip.emitterX(conf),dip.spectatorX(conf), conf,dip.emitter(conf),dip.spectator(conf), dip.emitterScale(conf),optHardPt,optCutoff); } Energy DipoleShowerHandler::getWinner(SubleadingSplittingInfo& winner, Energy optHardPt, Energy optCutoff) { return getWinner(winner,winner.index(), winner.emitterX(),winner.spectatorX(), winner.configuration(), winner.emitter(),winner.spectator(), winner.startScale(),optHardPt,optCutoff); } Energy DipoleShowerHandler::getWinner(DipoleSplittingInfo& winner, const DipoleIndex& index, double emitterX, double spectatorX, pair conf, tPPtr emitter, tPPtr spectator, Energy startScale, Energy optHardPt, Energy optCutoff) { if ( !index.initialStateEmitter() && !doFSR() ) { winner.didStopEvolving(); return 0.0*GeV; } if ( index.initialStateEmitter() && !doISR() ) { winner.didStopEvolving(); return 0.0*GeV; } // Currently do not split IF dipoles so // don't evaluate them in order to avoid // exceptions in the log if ( index.incomingDecayEmitter() ) { winner.didStopEvolving(); return 0.0*GeV; } DipoleSplittingInfo candidate; candidate.index(index); candidate.configuration(conf); candidate.emitterX(emitterX); candidate.spectatorX(spectatorX); if ( generators().find(candidate.index()) == generators().end() ) getGenerators(candidate.index(),theSplittingReweight); // // NOTE -- needs proper fixing at some point // // For some very strange reason, equal_range gives back // key ranges it hasn't been asked for. This particularly // happens e.g. for FI dipoles of the same kind, but different // PDF (hard vs MPI PDF). I can't see a reason for this, // as DipoleIndex properly implements comparison for equality // and (lexicographic) ordering; for the time being, we // use equal_range, extented by an explicit check for wether // the key is indeed what we wanted. See line after (*) comment // below. // // SW - Update 04/01/2016: Note - This caused a bug for me as I did not // include equality checks on the decay booleans in the == definition pair gens = generators().equal_range(candidate.index()); Energy winnerScale = 0.0*GeV; GeneratorMap::iterator winnerGen = generators().end(); for ( GeneratorMap::iterator gen = gens.first; gen != gens.second; ++gen ) { // (*) see NOTE above if ( !(gen->first == candidate.index()) ) continue; if ( startScale <= gen->second->splittingKinematics()->IRCutoff() ) continue; Energy dScale = gen->second->splittingKinematics()->dipoleScale(emitter->momentum(), spectator->momentum()); // in very exceptional cases happening in DIS if ( std::isnan( double(dScale/MeV) ) ) throw RedoShower(); candidate.scale(dScale); // Calculate the mass of the recoil system // for decay dipoles if ( candidate.index().incomingDecaySpectator() || candidate.index().incomingDecayEmitter() ) { Energy recoilMass = gen->second->splittingKinematics()->recoilMassKin(emitter->momentum(), spectator->momentum()); candidate.recoilMass(recoilMass); } // Store emitter and spectator masses, needed in kinematics if ( candidate.index().emitterData()->mass() != ZERO ) { if ( !candidate.index().offShellEmitter() ) candidate.emitterMass( emitter->nominalMass() ); else candidate.emitterMass( emitter->mass() ); } if ( candidate.index().spectatorData()->mass() != ZERO ) { if ( !candidate.index().offShellSpectator() ) candidate.spectatorMass( spectator->nominalMass() ); else candidate.spectatorMass( spectator->mass() ); } candidate.continuesEvolving(); Energy hardScale = evolutionOrdering()->maxPt(startScale,candidate,*(gen->second->splittingKernel())); Energy maxPossible = gen->second->splittingKinematics()->ptMax(candidate.scale(), candidate.emitterX(), candidate.spectatorX(), candidate, *gen->second->splittingKernel()); Energy ircutoff = optCutoff < gen->second->splittingKinematics()->IRCutoff() ? gen->second->splittingKinematics()->IRCutoff() : optCutoff; if ( maxPossible <= ircutoff ) { continue; } if ( maxPossible >= hardScale ){ candidate.hardPt(hardScale); } else { hardScale = maxPossible; candidate.hardPt(maxPossible); } gen->second->generate(candidate,currentWeights(),optHardPt,optCutoff); Energy nextScale = evolutionOrdering()->evolutionScale( gen->second->lastSplitting(),*(gen->second->splittingKernel())); if ( nextScale > winnerScale ) { winner.fill(candidate); gen->second->completeSplitting(winner); winnerGen = gen; winnerScale = nextScale; } reweight(reweight() * gen->second->splittingWeight()); } if ( winnerGen == generators().end() ) { winner.didStopEvolving(); return 0.0*GeV; } if ( winner.stoppedEvolving() ) return 0.0*GeV; return winnerScale; } void DipoleShowerHandler::doCascade(unsigned int& emDone, Energy optHardPt, Energy optCutoff, const bool decay) { if ( nEmissions ) if ( emDone == nEmissions ) return; DipoleSplittingInfo winner; DipoleSplittingInfo dipoleWinner; while ( eventRecord().haveChain() ) { + // allow the dipole chain to be rearranged according to arXiv:1801.06113 + if( _rearrange && ( _rearrangeNEmissions < 0 || _rearrangeNEmissions >= emDone ) ){ + eventRecord().currentChain().rearrange(_dipmax,_diplong); + } + if ( verbosity > 2 ) { generator()->log() << "DipoleShowerHandler selecting splittings for the chain:\n" << eventRecord().currentChain() << flush; } list::iterator winnerDip = eventRecord().currentChain().dipoles().end(); Energy winnerScale = 0.0*GeV; Energy nextLeftScale = 0.0*GeV; Energy nextRightScale = 0.0*GeV; for ( list::iterator dip = eventRecord().currentChain().dipoles().begin(); dip != eventRecord().currentChain().dipoles().end(); ++dip ) { nextLeftScale = getWinner(dipoleWinner,*dip,{true,false},optHardPt,optCutoff); if ( nextLeftScale > winnerScale ) { winnerScale = nextLeftScale; winner = dipoleWinner; winnerDip = dip; } nextRightScale = getWinner(dipoleWinner,*dip,{false,true},optHardPt,optCutoff); if ( nextRightScale > winnerScale ) { winnerScale = nextRightScale; winner = dipoleWinner; winnerDip = dip; } if ( evolutionOrdering()->independentDipoles() ) { Energy dipScale = max(nextLeftScale,nextRightScale); if ( dip->leftScale() > dipScale ) dip->leftScale(dipScale); if ( dip->rightScale() > dipScale ) dip->rightScale(dipScale); } } if ( verbosity > 1 ) { if ( winnerDip != eventRecord().currentChain().dipoles().end() ) generator()->log() << "DipoleShowerHandler selected the splitting:\n" << winner << " for the dipole\n" << (*winnerDip) << flush; else generator()->log() << "DipoleShowerHandler could not select a splitting above the IR cutoff\n" << flush; } // pop the chain if no dipole did radiate if ( winnerDip == eventRecord().currentChain().dipoles().end() ) { eventRecord().popChain(); if ( theEventReweight && eventRecord().chains().empty() ) if ( (theEventReweight->firstInteraction() && firstInteraction()) || (theEventReweight->secondaryInteractions() && !firstInteraction()) ) { double w = theEventReweight->weightCascade(eventRecord().incoming(), eventRecord().outgoing(), eventRecord().hard(),theGlobalAlphaS); reweight(reweight()*w); } continue; } // otherwise perform the splitting // but first see if the emission would produce a configuration in the ME region. if ( theMergingHelper && eventHandler()->currentCollision() && !decay && firstInteraction() ) { if (theMergingHelper->maxLegs()>eventRecord().outgoing().size()+ eventRecord().hard().size() +2){//incoming if (theMergingHelper->mergingScale()emissionProbability() < UseRandom::rnd()) { theMergingHelper->setEmissionProbability(0.); const bool transparent=true; if (transparent) { pair::iterator,list::iterator> tmpchildren; DipoleSplittingInfo tmpwinner=winner; DipoleChain* tmpfirstChain = nullptr; DipoleChain* tmpsecondChain = nullptr; auto New=eventRecord().tmpsplit(winnerDip,tmpwinner, tmpchildren,tmpfirstChain, tmpsecondChain); if (theMergingHelper->matrixElementRegion(New.first, New.second, winnerScale, theMergingHelper->mergingScale())) { optHardPt=winnerScale; continue; } }else{ optHardPt=winnerScale; continue; } } } } if(theMergingHelper&&firstInteraction()) optHardPt=ZERO; didRadiate = true; eventRecord().isMCatNLOSEvent(false); eventRecord().isMCatNLOHEvent(false); pair::iterator,list::iterator> children; DipoleChain* firstChain = nullptr; DipoleChain* secondChain = nullptr; // Note: the dipoles are updated in eventRecord().split(....) after the splitting, // hence the entire cascade is handled in doCascade // The dipole scales are updated in dip->split(....) if ( decay ) winner.isDecayProc( true ); eventRecord().split(winnerDip,winner,children,firstChain,secondChain); assert(firstChain && secondChain); evolutionOrdering()->setEvolutionScale(winnerScale,winner,*firstChain,children); if ( !secondChain->dipoles().empty() ) evolutionOrdering()->setEvolutionScale(winnerScale,winner,*secondChain,children); if ( verbosity > 1 ) { generator()->log() << "DipoleShowerHandler did split the last selected dipole into:\n" << (*children.first) << (*children.second) << flush; } if ( verbosity > 2 ) { generator()->log() << "After splitting the last selected dipole, " << "DipoleShowerHandler encountered the following chains:\n" << (*firstChain) << (*secondChain) << flush; } if ( theEventReweight ) if ( (theEventReweight->firstInteraction() && firstInteraction()) || (theEventReweight->secondaryInteractions() && !firstInteraction()) ) { double w = theEventReweight->weight(eventRecord().incoming(), eventRecord().outgoing(), eventRecord().hard(),theGlobalAlphaS); reweight(reweight()*w); } if ( nEmissions ) if ( ++emDone == nEmissions ) return; } } bool DipoleShowerHandler::realign() { if ( !didRadiate && !intrinsicPtGenerator ) return false; if ( eventRecord().incoming().first->coloured() || eventRecord().incoming().second->coloured() ) { if ( eventRecord().incoming().first->momentum().perp2()/GeV2 < 1e-10 && eventRecord().incoming().second->momentum().perp2()/GeV2 < 1e-10 ) return false; pair inMomenta (eventRecord().incoming().first->momentum(), eventRecord().incoming().second->momentum()); SpinOneLorentzRotation transform((inMomenta.first+inMomenta.second).findBoostToCM()); Axis dir = (transform * inMomenta.first).vect().unit(); Axis rot (-dir.y(),dir.x(),0); double theta = dir.theta(); if ( lastParticles().first->momentum().z() < ZERO ) theta = -theta; transform.rotate(-theta,rot); inMomenta.first = transform*inMomenta.first; inMomenta.second = transform*inMomenta.second; assert(inMomenta.first.z() > ZERO && inMomenta.second.z() < ZERO); Energy2 sHat = (eventRecord().incoming().first->momentum() + eventRecord().incoming().second->momentum()).m2(); pair masses(eventRecord().incoming().first->mass(), eventRecord().incoming().second->mass()); pair qs; if ( !eventRecord().incoming().first->coloured() ) { assert(masses.second == ZERO); qs.first = eventRecord().incoming().first->momentum().z(); qs.second = (sHat-sqr(masses.first))/(2.*(qs.first+sqrt(sqr(masses.first)+sqr(qs.first)))); } else if ( !eventRecord().incoming().second->coloured() ) { assert(masses.first == ZERO); qs.second = eventRecord().incoming().second->momentum().z(); qs.first = (sHat-sqr(masses.second))/(2.*(qs.second+sqrt(sqr(masses.second)+sqr(qs.second)))); } else { assert(masses.first == ZERO && masses.second == ZERO); if ( realignmentScheme == 0 ) { double yX = eventRecord().pX().rapidity(); double yInt = (transform*eventRecord().pX()).rapidity(); double dy = yX-yInt; qs.first = (sqrt(sHat)/2.)*exp(dy); qs.second = (sqrt(sHat)/2.)*exp(-dy); } else if ( realignmentScheme == 1 ) { Energy sS = sqrt((lastParticles().first->momentum() + lastParticles().second->momentum()).m2()); qs.first = eventRecord().fractions().first * sS / 2.; qs.second = eventRecord().fractions().second * sS / 2.; } } double beta = (qs.first-qs.second) / ( sqrt(sqr(masses.first)+sqr(qs.first)) + sqrt(sqr(masses.second)+sqr(qs.second)) ); transform.boostZ(beta); Lorentz5Momentum tmp; if ( eventRecord().incoming().first->coloured() ) { tmp = eventRecord().incoming().first->momentum(); tmp = transform * tmp; eventRecord().incoming().first->set5Momentum(tmp); } if ( eventRecord().incoming().second->coloured() ) { tmp = eventRecord().incoming().second->momentum(); tmp = transform * tmp; eventRecord().incoming().second->set5Momentum(tmp); } eventRecord().transform(transform); return true; } return false; } void DipoleShowerHandler::resetAlphaS(Ptr::tptr as) { for ( auto & k : kernels) { if ( !k->alphaS() ) k->alphaS(as); k->renormalizationScaleFreeze(theRenormalizationScaleFreeze); k->factorizationScaleFreeze(theFactorizationScaleFreeze); } // clear the generators to be rebuild // actually, there shouldn't be any generators // when this happens. generators().clear(); } void DipoleShowerHandler::resetReweight(Ptr::tptr rw) { for ( auto & g : generators() ) g.second->splittingReweight(rw); } void DipoleShowerHandler::getGenerators(const DipoleIndex& ind, Ptr::tptr rw) { bool gotone = false; for ( auto & k : kernels ) { if ( k->canHandle(ind) ) { if ( verbosity > 0 ) { generator()->log() << "DipoleShowerHandler encountered the dipole configuration\n" << ind << " in event number " << eventHandler()->currentEvent()->number() << "\nwhich can be handled by the splitting kernel '" << k->name() << "'.\n" << flush; } gotone = true; Ptr::ptr nGenerator = new_ptr(DipoleSplittingGenerator()); nGenerator->doCompensate(theDoCompensate); nGenerator->splittingKernel(k); if ( renormalizationScaleFactor() != 1. ) nGenerator->splittingKernel()->renormalizationScaleFactor(renormalizationScaleFactor()); if ( factorizationScaleFactor() != 1. ) nGenerator->splittingKernel()->factorizationScaleFactor(factorizationScaleFactor()); if ( !nGenerator->splittingReweight() ) nGenerator->splittingReweight(rw); nGenerator->splittingKernel()->freezeGrid(theFreezeGrid); nGenerator->splittingKernel()->detuning(theDetuning); GeneratorMap::const_iterator equivalent = generators().end(); for ( GeneratorMap::const_iterator eq = generators().begin(); eq != generators().end(); ++eq ) { if ( !eq->second->wrapping() ) if ( k->canHandleEquivalent(ind,*(eq->second->splittingKernel()),eq->first) ) { equivalent = eq; if ( verbosity > 0 ) { generator()->log() << "The dipole configuration " << ind << " can equivalently be handled by the existing\n" << "generator for configuration " << eq->first << " using the kernel '" << eq->second->splittingKernel()->name() << "'\n" << flush; } break; } } if ( equivalent != generators().end() ) { nGenerator->wrap(equivalent->second); } DipoleSplittingInfo dummy; dummy.index(ind); nGenerator->prepare(dummy); generators().insert({ind,nGenerator}); } } if ( !gotone ) { throw Exception() << "DipoleShowerHandler could not " << "find a splitting kernel which is able " << "to handle splittings off the dipole " << ind << ".\n" << "Please check the input files." << Exception::runerror; } } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void DipoleShowerHandler::doinit() { ShowerHandler::doinit(); if ( theGlobalAlphaS ) resetAlphaS(theGlobalAlphaS); // copy off-shell particle ids before showering from input vector to the // set used in the simulation if ( theColouredOffShellInShower.empty() ) { for(unsigned int ix=0;ixsplittingKinematics()->openZBoundaries() == 0 ) + zChoice0 = true; + else if ( k->splittingKinematics()->openZBoundaries() == 1 ) + zChoice1 = true; + else + zChoiceOther = true; + // either inconsistent or other option which cannot be handled by the matching + if ( zChoice0 && zChoice1 ) { + zChoiceOther = true; break; + } + } + if ( zChoiceOther ) + theZBoundaries = 2; + else if ( zChoice1 ) + theZBoundaries = 1; + else if ( zChoice0 ) + theZBoundaries = 0; } void DipoleShowerHandler::dofinish() { ShowerHandler::dofinish(); } void DipoleShowerHandler::doinitrun() { ShowerHandler::doinitrun(); } void DipoleShowerHandler::persistentOutput(PersistentOStream & os) const { os << kernels << theEvolutionOrdering << constituentReshuffler << intrinsicPtGenerator << theGlobalAlphaS << chainOrderVetoScales << nEmissions << discardNoEmissions << firstMCatNLOEmission << thePowhegDecayEmission << realignmentScheme << verbosity << printEvent << ounit(theRenormalizationScaleFreeze,GeV) << ounit(theFactorizationScaleFreeze,GeV) << theShowerApproximation << theDoCompensate << theFreezeGrid << theDetuning << theEventReweight << theSplittingReweight << ounit(maxPt,GeV) << ounit(muPt,GeV)<< theMergingHelper << theColouredOffShellInShower - << theInputColouredOffShellInShower; + << theInputColouredOffShellInShower + << _rearrange << _dipmax << _diplong << _rearrangeNEmissions << theZBoundaries; } void DipoleShowerHandler::persistentInput(PersistentIStream & is, int) { is >> kernels >> theEvolutionOrdering >> constituentReshuffler >> intrinsicPtGenerator >> theGlobalAlphaS >> chainOrderVetoScales >> nEmissions >> discardNoEmissions >> firstMCatNLOEmission >> thePowhegDecayEmission >> realignmentScheme >> verbosity >> printEvent >> iunit(theRenormalizationScaleFreeze,GeV) >> iunit(theFactorizationScaleFreeze,GeV) >> theShowerApproximation >> theDoCompensate >> theFreezeGrid >> theDetuning >> theEventReweight >> theSplittingReweight >> iunit(maxPt,GeV) >> iunit(muPt,GeV)>>theMergingHelper >> theColouredOffShellInShower - >> theInputColouredOffShellInShower; + >> theInputColouredOffShellInShower + >> _rearrange >> _dipmax >> _diplong >> _rearrangeNEmissions >> theZBoundaries; } ClassDescription DipoleShowerHandler::initDipoleShowerHandler; // Definition of the static class description member. void DipoleShowerHandler::Init() { static ClassDocumentation documentation ("The DipoleShowerHandler class manages the showering using " "the dipole shower algorithm.", "The shower evolution was performed using the algorithm described in " "\\cite{Platzer:2009jq} and \\cite{Platzer:2011bc}.", "%\\cite{Platzer:2009jq}\n" "\\bibitem{Platzer:2009jq}\n" "S.~Platzer and S.~Gieseke,\n" "``Coherent Parton Showers with Local Recoils,''\n" " JHEP {\\bf 1101}, 024 (2011)\n" "arXiv:0909.5593 [hep-ph].\n" "%%CITATION = ARXIV:0909.5593;%%\n" "%\\cite{Platzer:2011bc}\n" "\\bibitem{Platzer:2011bc}\n" "S.~Platzer and S.~Gieseke,\n" "``Dipole Showers and Automated NLO Matching in Herwig,''\n" "arXiv:1109.6256 [hep-ph].\n" "%%CITATION = ARXIV:1109.6256;%%"); static RefVector interfaceKernels ("Kernels", "Set the splitting kernels to be used by the dipole shower.", &DipoleShowerHandler::kernels, -1, false, false, true, false, false); static Reference interfaceEvolutionOrdering ("EvolutionOrdering", "Set the evolution ordering to be used.", &DipoleShowerHandler::theEvolutionOrdering, false, false, true, false, false); static Reference interfaceConstituentReshuffler ("ConstituentReshuffler", "The object to be used to reshuffle partons to their constitutent mass shells.", &DipoleShowerHandler::constituentReshuffler, false, false, true, true, false); static Reference interfaceIntrinsicPtGenerator ("IntrinsicPtGenerator", "Set the object in charge to generate intrinsic pt for incoming partons.", &DipoleShowerHandler::intrinsicPtGenerator, false, false, true, true, false); static Reference interfaceGlobalAlphaS ("GlobalAlphaS", "Set a global strong coupling for all splitting kernels.", &DipoleShowerHandler::theGlobalAlphaS, false, false, true, true, false); static Switch interfaceRealignmentScheme ("RealignmentScheme", "The realignment scheme to use.", &DipoleShowerHandler::realignmentScheme, 0, false, false); static SwitchOption interfaceRealignmentSchemePreserveRapidity (interfaceRealignmentScheme, "PreserveRapidity", "Preserve the rapidity of non-coloured outgoing system.", 0); static SwitchOption interfaceRealignmentSchemeEvolutionFractions (interfaceRealignmentScheme, "EvolutionFractions", "Use momentum fractions as generated by the evolution.", 1); static SwitchOption interfaceRealignmentSchemeCollisionFrame (interfaceRealignmentScheme, "CollisionFrame", "Determine realignment from collision frame.", 2); static Switch interfaceChainOrderVetoScales ("ChainOrderVetoScales", "[experimental] Switch the chain ordering for veto scales on or off.", &DipoleShowerHandler::chainOrderVetoScales, true, false, false); static SwitchOption interfaceChainOrderVetoScalesYes (interfaceChainOrderVetoScales, "Yes", "Switch on chain ordering for veto scales.", true); static SwitchOption interfaceChainOrderVetoScalesNo (interfaceChainOrderVetoScales, "No", "Switch off chain ordering for veto scales.", false); interfaceChainOrderVetoScales.rank(-1); static Parameter interfaceNEmissions ("NEmissions", "[debug option] Limit the number of emissions to be generated. Zero does not limit the number of emissions.", &DipoleShowerHandler::nEmissions, 0, 0, 0, false, false, Interface::lowerlim); interfaceNEmissions.rank(-1); static Switch interfaceDiscardNoEmissions ("DiscardNoEmissions", "[debug option] Discard events without radiation.", &DipoleShowerHandler::discardNoEmissions, false, false, false); static SwitchOption interfaceDiscardNoEmissionsYes (interfaceDiscardNoEmissions, "Yes", "Discard events without radiation.", true); static SwitchOption interfaceDiscardNoEmissionsNo (interfaceDiscardNoEmissions, "No", "Do not discard events without radiation.", false); interfaceDiscardNoEmissions.rank(-1); static Switch interfaceFirstMCatNLOEmission ("FirstMCatNLOEmission", "[debug option] Only perform the first MC@NLO emission.", &DipoleShowerHandler::firstMCatNLOEmission, false, false, false); static SwitchOption interfaceFirstMCatNLOEmissionYes (interfaceFirstMCatNLOEmission, "Yes", "Perform only the first MC@NLO emission.", true); static SwitchOption interfaceFirstMCatNLOEmissionNo (interfaceFirstMCatNLOEmission, "No", "Produce all emissions.", false); interfaceFirstMCatNLOEmission.rank(-1); static Parameter interfaceVerbosity ("Verbosity", "[debug option] Set the level of debug information provided.", &DipoleShowerHandler::verbosity, 0, 0, 0, false, false, Interface::lowerlim); interfaceVerbosity.rank(-1); static Parameter interfacePrintEvent ("PrintEvent", "[debug option] The number of events for which debugging information should be provided.", &DipoleShowerHandler::printEvent, 0, 0, 0, false, false, Interface::lowerlim); interfacePrintEvent.rank(-1); static Parameter interfaceRenormalizationScaleFreeze ("RenormalizationScaleFreeze", "The freezing scale for the renormalization scale.", &DipoleShowerHandler::theRenormalizationScaleFreeze, GeV, 1.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceFactorizationScaleFreeze ("FactorizationScaleFreeze", "The freezing scale for the factorization scale.", &DipoleShowerHandler::theFactorizationScaleFreeze, GeV, 2.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Switch interfaceDoCompensate ("DoCompensate", "", &DipoleShowerHandler::theDoCompensate, false, false, false); static SwitchOption interfaceDoCompensateYes (interfaceDoCompensate, "Yes", "", true); static SwitchOption interfaceDoCompensateNo (interfaceDoCompensate, "No", "", false); static Parameter interfaceFreezeGrid ("FreezeGrid", "", &DipoleShowerHandler::theFreezeGrid, 500000, 1, 0, false, false, Interface::lowerlim); static Parameter interfaceDetuning ("Detuning", "A value to detune the overestimate kernel.", &DipoleShowerHandler::theDetuning, 1.0, 1.0, 0, false, false, Interface::lowerlim); static Reference interfaceEventReweight ("EventReweight", "", &DipoleShowerHandler::theEventReweight, false, false, true, true, false); static Reference interfaceSplittingReweight ("SplittingReweight", "Set the splitting reweight.", &DipoleShowerHandler::theSplittingReweight, false, false, true, true, false); static Switch interfacePowhegDecayEmission ("PowhegDecayEmission", "Use Powheg style emission for the decays", &DipoleShowerHandler::thePowhegDecayEmission, true, false, false); static SwitchOption interfacePowhegDecayEmissionYes (interfacePowhegDecayEmission,"Yes","Powheg decay emission on", true); static SwitchOption interfacePowhegDecayEmissionNo (interfacePowhegDecayEmission,"No","Powheg decay emission off", false); static ParVector interfaceOffShellInShower ("OffShellInShower", "PDG codes of the coloured particles that can be off-shell in the process.", &DipoleShowerHandler::theInputColouredOffShellInShower, -1, 0l, -10000000l, 10000000l, false, false, Interface::limited); + + static Switch interfacerearrange + ("Rearrange", + "Allow rearranging of dipole chains according to arXiv:1801.06113", + &DipoleShowerHandler::_rearrange, false, false, false); + + static SwitchOption interfacerearrangeYes + (interfacerearrange,"Yes","_rearrange on", true); + + static SwitchOption interfacerearrangeNo + (interfacerearrange,"No","_rearrange off", false); + + static Parameter interfacedipmax + ("DipMax", + "Allow rearrangment of color chains with ME including dipmax dipoles.", + &DipoleShowerHandler::_dipmax, 0, 0, 0, + false, false, Interface::lowerlim); + + static Parameter interfacediplong + ("DipLong", + "Dipole chains with more than dipmax dipoles are treated as long. \ + diplong=3 rearranges these chains with eeuugg MEs, \ + diplong=4 rearranges these chains with eeuuggg MEs (slower), \ + diplong=5 rearranges these chains with eeuugggg MEs (slow).\ + Note: Numerically there is no difference between the options. ", + &DipoleShowerHandler::_diplong, 0, 0, 0, + false, false, Interface::lowerlim); + + static Parameter interfacedcorrectNemissions + ("RearrangeNEmissions", + "Allow rearrangment of color chains up to the nth emission.", + &DipoleShowerHandler::_rearrangeNEmissions, 0, 0, 0, + false, false, Interface::lowerlim); + } diff --git a/Shower/Dipole/DipoleShowerHandler.h b/Shower/Dipole/DipoleShowerHandler.h --- a/Shower/Dipole/DipoleShowerHandler.h +++ b/Shower/Dipole/DipoleShowerHandler.h @@ -1,572 +1,603 @@ // -*- C++ -*- // // DipoleShowerHandler.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_DipoleShowerHandler_H #define HERWIG_DipoleShowerHandler_H // // This is the declaration of the DipoleShowerHandler class. // #include "Herwig/Shower/ShowerHandler.h" #include "Herwig/Shower/Dipole/DipoleShowerHandler.fh" #include "Herwig/Shower/Dipole/Base/DipoleSplittingInfo.h" #include "Herwig/Shower/Dipole/Base/DipoleSplittingReweight.h" #include "Herwig/Shower/Dipole/Kernels/DipoleSplittingKernel.h" #include "Herwig/Shower/Dipole/Base/DipoleSplittingGenerator.h" #include "Herwig/Shower/Dipole/Base/DipoleEventRecord.h" #include "Herwig/Shower/Dipole/Base/DipoleEvolutionOrdering.h" #include "Herwig/Shower/Dipole/Base/DipoleEventReweight.h" #include "Herwig/Shower/Dipole/Utility/ConstituentReshuffler.h" #include "Herwig/Shower/Dipole/Utility/IntrinsicPtGenerator.h" #include "Herwig/MatrixElement/Matchbox/Base/MergerBase.h" #include "Herwig/MatrixElement/Matchbox/Matching/ShowerApproximation.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer, Stephen Webster * * \brief The DipoleShowerHandler class manages the showering using * the dipole shower algorithm. * * @see \ref DipoleShowerHandlerInterfaces "The interfaces" * defined for DipoleShowerHandler. */ class DipoleShowerHandler: public ShowerHandler { friend class Merger; public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ DipoleShowerHandler(); /** * The destructor. */ virtual ~DipoleShowerHandler(); //@} public: inline void colourPrint(); /** * Indicate a problem in the shower. */ struct RedoShower {}; /** * Insert an additional splitting kernel. */ void addSplitting(Ptr::ptr sp) { kernels.push_back(sp); } /** * Reset the alpha_s for all splitting kernels. */ void resetAlphaS(Ptr::tptr); virtual void cascade(tPVector); /** * Reset the splitting reweight for all splitting kernels. */ void resetReweight(Ptr::tptr); /** * Return true, if the shower handler can generate a truncated * shower for POWHEG style events generated using Matchbox */ virtual bool canHandleMatchboxTrunc() const { return false; } /** * Return true, if this cascade handler will perform reshuffling from hard * process masses. */ virtual bool isReshuffling() const { return false; } /** * Return the relevant hard scale to be used in the profile scales */ virtual Energy hardScale() const { return muPt; } /** * Calculate the alpha_s value the shower uses for Q. */ double as(Energy Q)const{return theGlobalAlphaS->value(sqr(Q));} /** * Return the number of scale dependent active flavours from * the alpha_s object. */ double Nf(Energy Q)const{return theGlobalAlphaS->Nf(sqr(Q));} /** * Set the pointer to the Merging Helper. * Used by the merging factory. */ void setMerger(Ptr::ptr mh){theMergingHelper=mh;} protected: typedef multimap::ptr> GeneratorMap; /** * The main method which manages the showering of a subprocess. */ virtual tPPair cascade(tSubProPtr sub, XCombPtr xcomb) { return cascade(sub,xcomb,ZERO,ZERO); } /** * The main method which manages the showering of a subprocess. */ tPPair cascade(tSubProPtr sub, XCombPtr xcomb, Energy optHardPt, Energy optCutoff); /** * Build splitting generators for the given * dipole index. */ void getGenerators(const DipoleIndex&, Ptr::tptr rw = Ptr::tptr()); /** * Setup the hard scales. */ void hardScales(Energy2 scale); /** * Return the evolution ordering */ Ptr::tptr evolutionOrdering() const { return theEvolutionOrdering; } /** * Reshuffle to constituent mass shells */ void constituentReshuffle(); /** * Reshuffle to constituent mass shells */ void decayConstituentReshuffle( PerturbativeProcessPtr decayProc); /** * Access the generator map */ GeneratorMap& generators() { return theGenerators; } /** * Access the event record */ DipoleEventRecord& eventRecord() { return theEventRecord; } /** * Return the event record */ const DipoleEventRecord& eventRecord() const { return theEventRecord; } /** * Return the splitting kernels. */ const vector::ptr>& splittingKernels() const { return kernels; } /** * Return the set of offshell parton ids. **/ const set& offShellPartons() { return theColouredOffShellInShower; } /** * Realign the event such as to have the incoming partons along thre * beam axes. */ bool realign(); + /** + * The choice of z boundaries; 0 = restricted, 1 = open, 2 = mixed/other + */ + virtual int showerPhaseSpaceOption() const { + return theZBoundaries; + } + protected: /** * Perform the cascade. */ void doCascade(unsigned int& emDone, Energy optHardPt = ZERO, Energy optCutoff = ZERO, const bool decay = false); /** * Set the number of emissions **/ void setNEmissions(unsigned int n){nEmissions=n;} /** * Get the winning splitting for the * given dipole and configuration. */ Energy getWinner(DipoleSplittingInfo& winner, const Dipole& dip, pair conf, Energy optHardPt = ZERO, Energy optCutoff = ZERO); /** * Get the winning splitting for the * given dipole and configuration. */ Energy getWinner(SubleadingSplittingInfo& winner, Energy optHardPt = ZERO, Energy optCutoff = ZERO); /** * Get the winning splitting for the * given dipole and configuration. */ Energy getWinner(DipoleSplittingInfo& winner, const DipoleIndex& index, double emitterX, double spectatorX, pair conf, tPPtr emitter, tPPtr spectator, Energy startScale, Energy optHardPt = ZERO, Energy optCutoff = ZERO); public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). protected: /** @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(); //@} private: /** * The splitting kernels to be used. */ vector::ptr> kernels; /** * The evolution ordering considered */ Ptr::ptr theEvolutionOrdering; /** * The ConstituentReshuffler to be used */ Ptr::ptr constituentReshuffler; /** * The intrinsic pt generator to be used. */ Ptr::ptr intrinsicPtGenerator; /** * A global alpha_s to be used for all splitting kernels. */ Ptr::ptr theGlobalAlphaS; /** * Apply chain ordering to events from matrix * element corrections. */ bool chainOrderVetoScales; /** * Limit the number of emissions. * Limit applied if > 0. */ unsigned int nEmissions; /** * Discard events which did not radiate. */ bool discardNoEmissions; /** * Perform the first MC@NLO emission only. */ bool firstMCatNLOEmission; /** * True if powheg style emissions are to be used in the decays */ bool thePowhegDecayEmission; /** * The realignment scheme */ int realignmentScheme; private: /** * The verbosity level. * 0 - print no info * 1 - print diagnostic information on setting up * splitting generators etc. * 2 - print detailed event information for up to * printEvent events. * 3 - print dipole chains after each splitting. */ int verbosity; /** * See verbosity. */ int printEvent; private: /** * The splitting generators indexed by the dipole * indices they can work on. */ GeneratorMap theGenerators; /** * The evnt record used. */ DipoleEventRecord theEventRecord; /** * The number of shoer tries so far. */ unsigned int nTries; /** * Whether or not we did radiate anything */ bool didRadiate; /** * Whether or not we did realign the event */ bool didRealign; private: /** * A freezing value for the renormalization scale */ Energy theRenormalizationScaleFreeze; /** * A freezing value for the factorization scale */ Energy theFactorizationScaleFreeze; /** * The matching subtraction, if appropriate */ Ptr::tptr theShowerApproximation; /** * True, if sampler should apply compensation */ bool theDoCompensate; /** * Return the number of accepted points after which the grid should * be frozen */ unsigned long theFreezeGrid; /** * The detuning factor applied to the sampling overestimate kernel */ double theDetuning; /** * A pointer to the dipole event reweight object */ Ptr::ptr theEventReweight; /** * A pointer to a global dipole splitting reweight */ Ptr::ptr theSplittingReweight; /** * True if no warnings have been issued yet */ static bool firstWarn; /** * The shower starting scale for the last event encountered */ Energy maxPt; /** * The shower hard scale for the last event encountered */ Energy muPt; /** * The merging helper takes care of merging multiple LO and NLO * cross sections. Here we need to check if an emission would * radiate in the matrix element region of an other multipicity. * If so, the emission is vetoed. */ Ptr::ptr theMergingHelper; /** * PDG codes of the partons which can have an off-shell mass, * this is fast storage for use during running */ set theColouredOffShellInShower; /** * PDG codes of the partons which can have an off-shell mass, * this is a vector that is interfaced so they can be changed */ vector theInputColouredOffShellInShower; + /** + * Allow the dipole chains to be rearranged + */ + bool _rearrange=false; + + /** + * number of maximal ME dipoles in the rearrangement. + */ + unsigned int _dipmax=3; + + /** + * If a chain is considered long (more than dipmax dipoles) + * ME with diplong dipoles are used to test for rearrangement. + */ + unsigned int _diplong=3; - + /** + * Number of emissions to be rearranged. + */ + int _rearrangeNEmissions=-1; + + /** + * The choice of z boundaries; 0 = restricted, 1 = open, 2 = mixed/other + */ + int theZBoundaries; + private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initDipoleShowerHandler; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ DipoleShowerHandler & operator=(const DipoleShowerHandler &); }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of DipoleShowerHandler. */ template <> struct BaseClassTrait { /** Typedef of the first base class of DipoleShowerHandler. */ typedef Herwig::ShowerHandler NthBase; }; /** This template specialization informs ThePEG about the name of * the DipoleShowerHandler class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::DipoleShowerHandler"; } /** * The name of a file containing the dynamic library where the class * DipoleShowerHandler is implemented. It may also include several, space-separated, * libraries if the class DipoleShowerHandler 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_DipoleShowerHandler_H */ diff --git a/Shower/Dipole/Kernels/FFMgx2ggxDipoleKernel.cc b/Shower/Dipole/Kernels/FFMgx2ggxDipoleKernel.cc --- a/Shower/Dipole/Kernels/FFMgx2ggxDipoleKernel.cc +++ b/Shower/Dipole/Kernels/FFMgx2ggxDipoleKernel.cc @@ -1,135 +1,142 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the FFMgx2ggxDipoleKernel class. // #include "FFMgx2ggxDipoleKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; FFMgx2ggxDipoleKernel::FFMgx2ggxDipoleKernel() - : DipoleSplittingKernel(),theSymmetryFactor(0.5) {} + : DipoleSplittingKernel(){} FFMgx2ggxDipoleKernel::~FFMgx2ggxDipoleKernel() {} IBPtr FFMgx2ggxDipoleKernel::clone() const { return new_ptr(*this); } IBPtr FFMgx2ggxDipoleKernel::fullclone() const { return new_ptr(*this); } bool FFMgx2ggxDipoleKernel::canHandle(const DipoleIndex& ind) const { return useThisKernel() && ind.emitterData()->id() == ParticleID::g && ind.spectatorData()->mass() != ZERO && !ind.initialStateEmitter() && !ind.initialStateSpectator() && !ind.incomingDecayEmitter() && !ind.incomingDecaySpectator(); } bool FFMgx2ggxDipoleKernel::canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const { assert(canHandle(a)); if ( !canHandle(b) ) return false; return sk.emitter(b)->id() == ParticleID::g && sk.emission(b)->id() == ParticleID::g && abs(spectator(a)->mass()) == abs(sk.spectator(b)->mass()); } tcPDPtr FFMgx2ggxDipoleKernel::emitter(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr FFMgx2ggxDipoleKernel::emission(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr FFMgx2ggxDipoleKernel::spectator(const DipoleIndex& ind) const { return ind.spectatorData(); } double FFMgx2ggxDipoleKernel::evaluate(const DipoleSplittingInfo& split) const { double ret = alphaPDF(split); // These are the physical variables as used in the // standard form of the kernel (i.e. do not redefine variables or kernel) const double z = split.lastZ(); const Energy pt = split.lastPt(); // Need zPrime to calculate y, // TODO: Should just store y in the dipole splitting info everywhere anyway!!! // The only value stored in dInfo.lastSplittingParameters() should be zPrime const double zPrime = split.lastSplittingParameters()[0]; // Construct mass squared variables // Construct mass squared variables double muj2 = sqr(split.spectatorMass() / split.scale()); double bar = 1. - muj2; // Calculate y double y = sqr(pt)/sqr(split.scale()) / (bar*zPrime*(1.-zPrime)); double vijk = sqrt( sqr(2.*muj2+bar*(1.-y))-4.*muj2 ) / (bar*(1.-y)); double viji = 1.; double zp = 0.5*(1.+viji*vijk); double zm = 0.5*(1.-viji*vijk); // how to choose kappa? double kappa = 0.; - ret *= theSymmetryFactor*3.*(1./(1.-z*(1.-y))+1./(1.-(1.-z)*(1.-y)) + (z*(1.-z)-(1.-kappa)*zp*zm-2.)/vijk); + double S1=1./(1.-z*(1.-y)); + double S2=1./(1.-(1.-z)*(1.-y)); + double NS=(z*(1.-z)-(1.-kappa)*zp*zm-2.)/vijk; + + if( theAsymmetryOption == 0 ){ + ret *= 3.*( S1 + 0.5 * NS); + }else if ( theAsymmetryOption == 1 ){ + ret *= 3.*z*( S1 +S2 + NS ); + }else{ + ret *= 3.*0.5*( S1 + S2 + NS ); + } - return ret > 0. ? ret : 0.; - + return ret > 0. ? ret : 0.; } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FFMgx2ggxDipoleKernel::persistentOutput(PersistentOStream & os) const { - os<>theSymmetryFactor; + is >> theAsymmetryOption; } ClassDescription FFMgx2ggxDipoleKernel::initFFMgx2ggxDipoleKernel; // Definition of the static class description member. void FFMgx2ggxDipoleKernel::Init() { static ClassDocumentation documentation ("FFMgx2ggxDipoleKernel"); - - static Parameter interfaceSymmetryFactor - ("SymmetryFactor", - "The symmetry factor for final state gluon spliitings.", - &FFMgx2ggxDipoleKernel::theSymmetryFactor, 1.0, 0.0, 0, - false, false, Interface::lowerlim); - + + static Parameter interfacetheAsymmetryOption + ("AsymmetryOption", + "The asymmetry option for final state gluon spliitings.", + &FFMgx2ggxDipoleKernel::theAsymmetryOption, 1, 0, 0, + false, false, Interface::lowerlim); } - diff --git a/Shower/Dipole/Kernels/FFMgx2ggxDipoleKernel.h b/Shower/Dipole/Kernels/FFMgx2ggxDipoleKernel.h --- a/Shower/Dipole/Kernels/FFMgx2ggxDipoleKernel.h +++ b/Shower/Dipole/Kernels/FFMgx2ggxDipoleKernel.h @@ -1,187 +1,187 @@ // -*- C++ -*- #ifndef HERWIG_FFMgx2ggxDipoleKernel_H #define HERWIG_FFMgx2ggxDipoleKernel_H // // This is the declaration of the FFMgx2ggxDipoleKernel class. // #include "DipoleSplittingKernel.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer, Martin Stoll, Stephen Webster * * \brief FFMgx2ggxDipoleKernel implements the g -> gg * splitting off a final-final dipole * */ class FFMgx2ggxDipoleKernel: public DipoleSplittingKernel { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ FFMgx2ggxDipoleKernel(); /** * The destructor. */ virtual ~FFMgx2ggxDipoleKernel(); //@} public: /** * Return true, if this splitting kernel * applies to the given dipole index. */ virtual bool canHandle(const DipoleIndex&) const; /** * Return true, if this splitting kernel is * the same for the given index a, as the given * splitting kernel for index b. */ virtual bool canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const; /** * Return the emitter data after splitting, given * a dipole index. */ virtual tcPDPtr emitter(const DipoleIndex&) const; /** * Return the emission data after splitting, given * a dipole index. */ virtual tcPDPtr emission(const DipoleIndex&) const; /** * Return the spectator data after splitting, given * a dipole index. */ virtual tcPDPtr spectator(const DipoleIndex&) const; /** * Evaluate this splitting kernel for the given * dipole splitting. */ virtual double evaluate(const DipoleSplittingInfo&) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** - * Symmetry factor for final state gluon splittings (should be 1/2). + * Asymmetry option for final state gluon splittings. */ - double theSymmetryFactor; + int theAsymmetryOption=1; /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initFFMgx2ggxDipoleKernel; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FFMgx2ggxDipoleKernel & operator=(const FFMgx2ggxDipoleKernel &); }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of FFMgx2ggxDipoleKernel. */ template <> struct BaseClassTrait { /** Typedef of the first base class of FFMgx2ggxDipoleKernel. */ typedef Herwig::DipoleSplittingKernel NthBase; }; /** This template specialization informs ThePEG about the name of * the FFMgx2ggxDipoleKernel class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::FFMgx2ggxDipoleKernel"; } /** * The name of a file containing the dynamic library where the class * FFMgx2ggxDipoleKernel is implemented. It may also include several, space-separated, * libraries if the class FFMgx2ggxDipoleKernel 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_FFMgx2ggxDipoleKernel_H */ diff --git a/Shower/Dipole/Kernels/FFgx2ggxDipoleKernel.cc b/Shower/Dipole/Kernels/FFgx2ggxDipoleKernel.cc --- a/Shower/Dipole/Kernels/FFgx2ggxDipoleKernel.cc +++ b/Shower/Dipole/Kernels/FFgx2ggxDipoleKernel.cc @@ -1,107 +1,113 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the FFgx2ggxDipoleKernel class. // #include "FFgx2ggxDipoleKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; FFgx2ggxDipoleKernel::FFgx2ggxDipoleKernel() - : DipoleSplittingKernel(),theSymmetryFactor(0.5){} + : DipoleSplittingKernel(){} FFgx2ggxDipoleKernel::~FFgx2ggxDipoleKernel() {} IBPtr FFgx2ggxDipoleKernel::clone() const { return new_ptr(*this); } IBPtr FFgx2ggxDipoleKernel::fullclone() const { return new_ptr(*this); } bool FFgx2ggxDipoleKernel::canHandle(const DipoleIndex& ind) const { return useThisKernel() && ind.emitterData()->id() == ParticleID::g && ind.spectatorData()->mass() == ZERO && !ind.initialStateEmitter() && !ind.initialStateSpectator(); } bool FFgx2ggxDipoleKernel::canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const { assert(canHandle(a)); if ( !canHandle(b) ) return false; return sk.emitter(b)->id() == ParticleID::g && sk.emission(b)->id() == ParticleID::g; } tcPDPtr FFgx2ggxDipoleKernel::emitter(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr FFgx2ggxDipoleKernel::emission(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr FFgx2ggxDipoleKernel::spectator(const DipoleIndex& ind) const { return ind.spectatorData(); } double FFgx2ggxDipoleKernel::evaluate(const DipoleSplittingInfo& split) const { double ret = alphaPDF(split); double z = split.lastZ(); double y = sqr(split.lastPt() / split.scale()) / (z*(1.-z)); - ret *=theSymmetryFactor*3.*(1./(1.-z*(1.-y))+1./(1.-(1.-z)*(1.-y))-2.+z*(1.-z)); + double S1=1./(1.-z*(1.-y)); + double S2=1./(1.-(1.-z)*(1.-y)); + double NS=(-2 + z*(1.-z)); - + if( theAsymmetryOption == 0 ){ + ret *= 3.*( S1 + 0.5 * NS); + }else if ( theAsymmetryOption == 1 ){ + ret *= 3.*z*( S1 +S2 + NS ); + }else{ + ret *= 3.*0.5*( S1 + S2 + NS ); + } + return ret > 0. ? ret : 0.; - } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FFgx2ggxDipoleKernel::persistentOutput(PersistentOStream & os) const { - - os<>theSymmetryFactor; + is >> theAsymmetryOption; } ClassDescription FFgx2ggxDipoleKernel::initFFgx2ggxDipoleKernel; // Definition of the static class description member. void FFgx2ggxDipoleKernel::Init() { static ClassDocumentation documentation ("FFgx2ggxDipoleKernel"); - static Parameter interfaceSymmetryFactor - ("SymmetryFactor", - "The symmetry factor for final state gluon spliitings.", - &FFgx2ggxDipoleKernel::theSymmetryFactor, 1.0, 0.0, 0, + static Parameter interfacetheAsymmetryOption + ("AsymmetryOption", + "The asymmetry option for final state gluon spliitings.", + &FFgx2ggxDipoleKernel::theAsymmetryOption, 1, 0, 0, false, false, Interface::lowerlim); } - diff --git a/Shower/Dipole/Kernels/FFgx2ggxDipoleKernel.h b/Shower/Dipole/Kernels/FFgx2ggxDipoleKernel.h --- a/Shower/Dipole/Kernels/FFgx2ggxDipoleKernel.h +++ b/Shower/Dipole/Kernels/FFgx2ggxDipoleKernel.h @@ -1,187 +1,187 @@ // -*- C++ -*- #ifndef HERWIG_FFgx2ggxDipoleKernel_H #define HERWIG_FFgx2ggxDipoleKernel_H // // This is the declaration of the FFgx2ggxDipoleKernel class. // #include "DipoleSplittingKernel.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief FFgx2ggxDipoleKernel implements the g -> gg * splitting off a final-final dipole * */ class FFgx2ggxDipoleKernel: public DipoleSplittingKernel { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ FFgx2ggxDipoleKernel(); /** * The destructor. */ virtual ~FFgx2ggxDipoleKernel(); //@} public: /** * Return true, if this splitting kernel * applies to the given dipole index. */ virtual bool canHandle(const DipoleIndex&) const; /** * Return true, if this splitting kernel is * the same for the given index a, as the given * splitting kernel for index b. */ virtual bool canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const; /** * Return the emitter data after splitting, given * a dipole index. */ virtual tcPDPtr emitter(const DipoleIndex&) const; /** * Return the emission data after splitting, given * a dipole index. */ virtual tcPDPtr emission(const DipoleIndex&) const; /** * Return the spectator data after splitting, given * a dipole index. */ virtual tcPDPtr spectator(const DipoleIndex&) const; /** * Evaluate this splitting kernel for the given * dipole splitting. */ virtual double evaluate(const DipoleSplittingInfo&) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initFFgx2ggxDipoleKernel; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FFgx2ggxDipoleKernel & operator=(const FFgx2ggxDipoleKernel &); /** - * Symmetry factor for final state gluon splittings (should be 1/2). - */ - - double theSymmetryFactor; + * Asymmetry option for final state gluon splittings. + */ + + int theAsymmetryOption=1; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of FFgx2ggxDipoleKernel. */ template <> struct BaseClassTrait { /** Typedef of the first base class of FFgx2ggxDipoleKernel. */ typedef Herwig::DipoleSplittingKernel NthBase; }; /** This template specialization informs ThePEG about the name of * the FFgx2ggxDipoleKernel class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::FFgx2ggxDipoleKernel"; } /** * The name of a file containing the dynamic library where the class * FFgx2ggxDipoleKernel is implemented. It may also include several, space-separated, * libraries if the class FFgx2ggxDipoleKernel 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_FFgx2ggxDipoleKernel_H */ diff --git a/Shower/Dipole/Kernels/FIMDecaygx2ggxDipoleKernel.cc b/Shower/Dipole/Kernels/FIMDecaygx2ggxDipoleKernel.cc --- a/Shower/Dipole/Kernels/FIMDecaygx2ggxDipoleKernel.cc +++ b/Shower/Dipole/Kernels/FIMDecaygx2ggxDipoleKernel.cc @@ -1,155 +1,159 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the FIMDecaygx2ggxDipoleKernel class. // #include "FIMDecaygx2ggxDipoleKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; FIMDecaygx2ggxDipoleKernel::FIMDecaygx2ggxDipoleKernel() - : DipoleSplittingKernel(),theSymmetryFactor(0.5){} + : DipoleSplittingKernel(){} FIMDecaygx2ggxDipoleKernel::~FIMDecaygx2ggxDipoleKernel() {} IBPtr FIMDecaygx2ggxDipoleKernel::clone() const { return new_ptr(*this); } IBPtr FIMDecaygx2ggxDipoleKernel::fullclone() const { return new_ptr(*this); } bool FIMDecaygx2ggxDipoleKernel::canHandle(const DipoleIndex& ind) const { return useThisKernel() && ind.incomingDecaySpectator() && !ind.incomingDecayEmitter() && ind.emitterData()->id() == ParticleID::g && !(ind.spectatorData()->mass() == ZERO) && // Initial state here refers to the entire event !ind.initialStateEmitter() && !ind.initialStateSpectator(); } bool FIMDecaygx2ggxDipoleKernel::canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const { assert(canHandle(a)); if ( !canHandle(b) ) return false; return sk.emission(b)->id() == ParticleID::g && sk.emitter(b)->id() == ParticleID::g && abs(sk.spectator(b)->mass()) == abs(spectator(a)->mass()); } tcPDPtr FIMDecaygx2ggxDipoleKernel::emitter(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr FIMDecaygx2ggxDipoleKernel::emission(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr FIMDecaygx2ggxDipoleKernel::spectator(const DipoleIndex& ind) const { return ind.spectatorData(); } double FIMDecaygx2ggxDipoleKernel::evaluate(const DipoleSplittingInfo& split) const { double ret = alphaPDF(split); // These are the physical variables as used in the standard form of the kernel (i.e. do not redefine variables or kernel) double z = split.lastZ(); Energy pt = split.lastPt(); // Need zPrime to calculate y, // TODO: Should just store y in the dipole splitting info everywhere anyway!!! // The only value stored in dInfo.lastSplittingParameters() should be zPrime //assert(split.lastSplittingParameters().size() == 1 ); double zPrime = split.lastSplittingParameters()[0]; // Construct mass squared variables - double mua2 = sqr( split.spectatorData()->mass() / split.scale() ); + double mua2 = sqr( split.spectatorMass() / split.scale() ); // Recoil system mass double muj2 = sqr(split.recoilMass() / split.scale()); double bar = 1. - muj2; // Calculate y double y = (sqr(pt)/sqr(split.scale())) / (bar*zPrime*(1.-zPrime)); if( sqr(2.*muj2+bar*(1.-y))-4.*muj2 < 0. ){ generator()->logWarning( Exception() << "error in FIMDecaygx2ggxDipoleKernel::evaluate -- " << "muj2 " << muj2 << " y " << y << Exception::warning ); return 0.0; } double vijk = sqrt( sqr(2.*muj2+bar*(1.-y))-4.*muj2 ) / (bar*(1.-y)); double viji = 1.; double vbar = 1.; double zp = 0.5*(1.+viji*vijk); double zm = 0.5*(1.-viji*vijk); // how to choose kappa? double kappa = 0.; - ret *= - theSymmetryFactor - * 3.*( (2.*y + 1.)/((1.+y)-z*(1.-y)) + (2.*y + 1.)/((1.+y)-(1.-z)*(1.-y)) - + (1./vijk)*( z*(1.-z) - (1.-kappa)*zp*zm - 2. ) ) - + - (!strictLargeN() ? 4./3. : 3./2.) - * ( - y/(1.-z*(1.-y)) * ( 2.*(2.*y + 1.)/((1.+y)-z*(1.-y)) - - (vbar/vijk)*(2. + 2.*mua2/((1.-z*(1.-y))*bar)) ) - + - y/(1.-(1.-z)*(1.-y)) * ( 2.*(2.*y + 1.)/((1.+y)-(1.-z)*(1.-y)) - - (vbar/vijk)*(2. + 2.*mua2/((1.-(1.-z)*(1.-y))*bar)) ) - ); - + double S1 = 0.5*3.*(2.*y + 1.)/((1.+y)-z*(1.-y)) + + (!strictLargeN() ? 4./3. : 3./2.)* + y/(1.-z*(1.-y)) * ( 2.*(2.*y + 1.)/((1.+y)-z*(1.-y)) + - (vbar/vijk)*(2. + 2.*mua2/((1.-z*(1.-y))*bar)) ); + double S2 = 0.5*3.*(2.*y + 1.)/((1.+y)-(1.-z)*(1.-y)) + + (!strictLargeN() ? 4./3. : 3./2.)* + y/(1.-(1.-z)*(1.-y)) * ( 2.*(2.*y + 1.)/((1.+y)-(1.-z)*(1.-y)) + - (vbar/vijk)*(2. + 2.*mua2/((1.-(1.-z)*(1.-y))*bar)) ); + double NS = 0.5*3.*(z*(1.-z)-(1.-kappa)*zp*zm - 2.)/vijk; + + + if( theAsymmetryOption == 0 ){ + ret *= 2.*S1 + NS; + }else if ( theAsymmetryOption == 1 ){ + ret *= 2.*z*( S1 + S2 + NS ); + }else{ + ret *= S1 + S2 + NS; + } + return ret > 0. ? ret : 0.; } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FIMDecaygx2ggxDipoleKernel::persistentOutput(PersistentOStream & os) const { - - os<>theSymmetryFactor; + is>>theAsymmetryOption; } ClassDescription FIMDecaygx2ggxDipoleKernel::initFIMDecaygx2ggxDipoleKernel; // Definition of the static class description member. void FIMDecaygx2ggxDipoleKernel::Init() { static ClassDocumentation documentation ("FIMDecaygx2ggxDipoleKernel"); - static Parameter interfaceSymmetryFactor - ("SymmetryFactor", - "The symmetry factor for final state gluon splittings.", - &FIMDecaygx2ggxDipoleKernel::theSymmetryFactor, 1.0, 0.0, 0, + static Parameter interfacetheAsymmetryOption + ("AsymmetryOption", + "The asymmetry option for final state gluon spliitings.", + &FIMDecaygx2ggxDipoleKernel::theAsymmetryOption, 0, 0, 0, false, false, Interface::lowerlim); + } diff --git a/Shower/Dipole/Kernels/FIMDecaygx2ggxDipoleKernel.h b/Shower/Dipole/Kernels/FIMDecaygx2ggxDipoleKernel.h --- a/Shower/Dipole/Kernels/FIMDecaygx2ggxDipoleKernel.h +++ b/Shower/Dipole/Kernels/FIMDecaygx2ggxDipoleKernel.h @@ -1,188 +1,186 @@ // -*- C++ -*- #ifndef HERWIG_FIMDecaygx2ggxDipoleKernel_H #define HERWIG_FIMDecaygx2ggxDipoleKernel_H // // This is the declaration of the FIMDecaygx2ggxDipoleKernel class. // #include "DipoleSplittingKernel.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Stephen Webster * * \brief FIMDecaygx2ggxDipoleKernel implements the g -> gg * splitting off a final-initial decay dipole and includes the * contribution from the splitting of the intial / decay particle * */ class FIMDecaygx2ggxDipoleKernel: public DipoleSplittingKernel { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ FIMDecaygx2ggxDipoleKernel(); /** * The destructor. */ virtual ~FIMDecaygx2ggxDipoleKernel(); //@} public: /** * Return true, if this splitting kernel * applies to the given dipole index. */ virtual bool canHandle(const DipoleIndex&) const; /** * Return true, if this splitting kernel is * the same for the given index a, as the given * splitting kernel for index b. */ virtual bool canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const; /** * Return the emitter data after splitting, given * a dipole index. */ virtual tcPDPtr emitter(const DipoleIndex&) const; /** * Return the emission data after splitting, given * a dipole index. */ virtual tcPDPtr emission(const DipoleIndex&) const; /** * Return the spectator data after splitting, given * a dipole index. */ virtual tcPDPtr spectator(const DipoleIndex&) const; /** * Evaluate this splitting kernel for the given * dipole splitting. */ virtual double evaluate(const DipoleSplittingInfo&) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** - * Symmetry factor for final state gluon splittings (should be 1/2). - */ - - double theSymmetryFactor; - - /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initFIMDecaygx2ggxDipoleKernel; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FIMDecaygx2ggxDipoleKernel & operator=(const FIMDecaygx2ggxDipoleKernel &); + /** + * Asymmetry option for final state gluon splittings. + */ + int theAsymmetryOption=0; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of FIMDecaygx2ggxDipoleKernel. */ template <> struct BaseClassTrait { /** Typedef of the first base class of FIMDecaygx2ggxDipoleKernel. */ typedef Herwig::DipoleSplittingKernel NthBase; }; /** This template specialization informs ThePEG about the name of * the FIMDecaygx2ggxDipoleKernel class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::FIMDecaygx2ggxDipoleKernel"; } /** * The name of a file containing the dynamic library where the class * FIMDecaygx2ggxDipoleKernel is implemented. It may also include several, space-separated, * libraries if the class FIMDecaygx2ggxDipoleKernel 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_FIMDecaygx2ggxDipoleKernel_H */ diff --git a/Shower/Dipole/Kernels/FIMDecaygx2qqxDipoleKernel.cc b/Shower/Dipole/Kernels/FIMDecaygx2qqxDipoleKernel.cc --- a/Shower/Dipole/Kernels/FIMDecaygx2qqxDipoleKernel.cc +++ b/Shower/Dipole/Kernels/FIMDecaygx2qqxDipoleKernel.cc @@ -1,142 +1,142 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the FIMDecaygx2qqxDipoleKernel class. // #include "FIMDecaygx2qqxDipoleKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; FIMDecaygx2qqxDipoleKernel::FIMDecaygx2qqxDipoleKernel() : DipoleSplittingKernel() {} FIMDecaygx2qqxDipoleKernel::~FIMDecaygx2qqxDipoleKernel() {} IBPtr FIMDecaygx2qqxDipoleKernel::clone() const { return new_ptr(*this); } IBPtr FIMDecaygx2qqxDipoleKernel::fullclone() const { return new_ptr(*this); } bool FIMDecaygx2qqxDipoleKernel::canHandle(const DipoleIndex& ind) const { return useThisKernel() && ind.incomingDecaySpectator() && !ind.incomingDecayEmitter() && ind.emitterData()->id() == ParticleID::g && !(ind.spectatorData()->mass() == ZERO) && // Initial state here refers to the entire event !ind.initialStateEmitter() && !ind.initialStateSpectator(); } bool FIMDecaygx2qqxDipoleKernel::canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const { assert(canHandle(a)); if ( !canHandle(b) ) return false; return sk.emitter(b)->id() + sk.emission(b)->id() == 0 && abs(sk.emitter(b)->id()) < 6 && emitter(a)->id() == sk.emitter(b)->id() && abs(sk.spectator(b)->mass()) == abs(spectator(a)->mass()); } tcPDPtr FIMDecaygx2qqxDipoleKernel::emitter(const DipoleIndex&) const { assert(flavour()); assert(abs(flavour()->id()) < 6); return flavour(); } tcPDPtr FIMDecaygx2qqxDipoleKernel::emission(const DipoleIndex&) const { assert(flavour()); assert(abs(flavour()->id()) < 6); return flavour()->CC(); } tcPDPtr FIMDecaygx2qqxDipoleKernel::spectator(const DipoleIndex& ind) const { return ind.spectatorData(); } double FIMDecaygx2qqxDipoleKernel::evaluate(const DipoleSplittingInfo& split) const { double ret = alphaPDF(split); // These are the physical variables as used in the standard form of the kernel (i.e. do not redefine variables or kernel) double z = split.lastZ(); Energy pt = split.lastPt(); // Need zPrime to calculate y, // TODO: Should just store y in the dipole splitting info everywhere anyway!!! // The only value stored in dInfo.lastSplittingParameters() should be zPrime //assert(split.lastSplittingParameters().size() == 1 ); double zPrime = split.lastSplittingParameters()[0]; // Construct mass squared variables - double mua2 = sqr( split.spectatorData()->mass() / split.scale() ); double mui2 = sqr(split.emitterData()->mass() / split.scale()); double mu2 = mui2; + //double mua2 = sqr( split.spectatorMass() / split.scale() ); // Recoil system mass double muj2 = sqr(split.recoilMass() / split.scale()); double bar = 1. - mui2 - mu2 - muj2; // Calculate y double y = (sqr(pt)/sqr(split.scale()) + sqr(1.-zPrime)*mui2 + sqr(zPrime)*mu2) / (bar*zPrime*(1.-zPrime)); if( sqr(2.*muj2+bar*(1.-y))-4.*muj2 < 0. ){ generator()->logWarning( Exception() << "error in FIMDecaygx2qqxDipoleKernel::evaluate -- " << "muj2 " << muj2 << " mui2 " << mui2 << " y " << y << Exception::warning ); return 0.0; } double vijk = sqrt( sqr(2.*muj2+bar*(1.-y))-4.*muj2 ) / (bar*(1.-y)); double viji = sqrt( sqr(bar*y)-4.*sqr(mui2) ) / (bar*y+2.*mui2); - double vbar = sqrt( 1.+sqr(mui2)+sqr(muj2)-2.*(mui2+muj2+mui2*muj2) ) / bar; + //double vbar = sqrt( 1.+sqr(mui2)+sqr(muj2)-2.*(mui2+muj2+mui2*muj2) ) / bar; double zp = 0.5*(1.+viji*vijk); double zm = 0.5*(1.-viji*vijk); // how to choose kappa? double kappa = 0.; ret *= 0.25 / vijk * ( 1. - 2.*( z*(1.-z) - (1.-kappa)*zp*zm - kappa*mui2/(2*mui2+bar*y) ) ); return ret > 0. ? ret : 0.; } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FIMDecaygx2qqxDipoleKernel::persistentOutput(PersistentOStream & ) const { } void FIMDecaygx2qqxDipoleKernel::persistentInput(PersistentIStream & , int) { } ClassDescription FIMDecaygx2qqxDipoleKernel::initFIMDecaygx2qqxDipoleKernel; // Definition of the static class description member. void FIMDecaygx2qqxDipoleKernel::Init() { static ClassDocumentation documentation ("FIMDecaygx2qqxDipoleKernel"); } diff --git a/Shower/Dipole/Kernels/FIMDecayqx2qgxDipoleKernel.cc b/Shower/Dipole/Kernels/FIMDecayqx2qgxDipoleKernel.cc --- a/Shower/Dipole/Kernels/FIMDecayqx2qgxDipoleKernel.cc +++ b/Shower/Dipole/Kernels/FIMDecayqx2qgxDipoleKernel.cc @@ -1,141 +1,144 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the FIMDecayqx2qgxDipoleKernel class. // #include "FIMDecayqx2qgxDipoleKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; FIMDecayqx2qgxDipoleKernel::FIMDecayqx2qgxDipoleKernel() : DipoleSplittingKernel() {} FIMDecayqx2qgxDipoleKernel::~FIMDecayqx2qgxDipoleKernel() {} IBPtr FIMDecayqx2qgxDipoleKernel::clone() const { return new_ptr(*this); } IBPtr FIMDecayqx2qgxDipoleKernel::fullclone() const { return new_ptr(*this); } bool FIMDecayqx2qgxDipoleKernel::canHandle(const DipoleIndex& ind) const { return useThisKernel() && ind.incomingDecaySpectator() && !ind.incomingDecayEmitter() && abs(ind.emitterData()->id()) < 7 && // This line matches to the kernel declared in a .in file for the given emitter flavour abs(ind.emitterData()->id()) == abs(flavour()->id()) && !(ind.spectatorData()->mass() == ZERO) && // Initial state here refers to the entire event !ind.initialStateEmitter() && !ind.initialStateSpectator(); } bool FIMDecayqx2qgxDipoleKernel::canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const { assert(canHandle(a)); if ( !canHandle(b) ) return false; return sk.emission(b)->id() == ParticleID::g && abs(sk.emitter(b)->id()) < 7 && abs(sk.emitter(b)->mass()) == abs(emitter(a)->mass()) && abs(sk.spectator(b)->mass()) == abs(spectator(a)->mass()); } tcPDPtr FIMDecayqx2qgxDipoleKernel::emitter(const DipoleIndex& ind) const { assert(flavour()); assert(abs(flavour()->id()) < 7); return ind.emitterData()->id() > 0 ? (tcPDPtr) flavour() : (tcPDPtr) flavour()->CC(); } tcPDPtr FIMDecayqx2qgxDipoleKernel::emission(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr FIMDecayqx2qgxDipoleKernel::spectator(const DipoleIndex& ind) const { return ind.spectatorData(); } double FIMDecayqx2qgxDipoleKernel::evaluate(const DipoleSplittingInfo& split) const { double ret = alphaPDF(split); // These are the physical variables as used in the standard form of the kernel (i.e. do not redefine variables or kernel) double z = split.lastZ(); Energy pt = split.lastPt(); // Need zPrime to calculate y, // TODO: Should just store y in the dipole splitting info everywhere anyway!!! // The only value stored in dInfo.lastSplittingParameters() should be zPrime //assert(split.lastSplittingParameters().size() == 1 ); double zPrime = split.lastSplittingParameters()[0]; // Construct mass squared variables - double mui2 = sqr(split.emitterData()->mass() / split.scale()); + // Note for q->qg can use the emitterMass + // (i.e. mass of emitter before splitting = mass of emitter after) + double mui2 = sqr(split.emitterMass() / split.scale()); // Recoil system mass double muj2 = sqr(split.recoilMass() / split.scale()); - double mua2 = sqr( split.spectatorData()->mass() / split.scale() ); + // This should be equal to one + double mua2 = sqr( split.spectatorMass() / split.scale() ); double bar = 1. - mui2 - muj2; // Calculate y double y = (sqr(pt)/sqr(split.scale()) + sqr(1.-zPrime)*mui2) / (bar*zPrime*(1.-zPrime)); if( sqr(2.*muj2+bar*(1.-y))-4.*muj2 < 0. ){ generator()->logWarning( Exception() << "error in FIMDecayqx2qgxDipoleKernel::evaluate -- " << "muj2 " << muj2 << " mui2 " << mui2 << " y " << y << Exception::warning ); return 0.0; } double vijk = sqrt( sqr(2.*muj2 + bar*(1.-y))-4.*muj2 ) / (bar*(1.-y)); double vbar = sqrt( 1.+sqr(mui2)+sqr(muj2)-2.*(mui2+muj2+mui2*muj2) ) / bar; ret *= (!strictLargeN() ? 4./3. : 3./2.) * ( ( 2.*(2.*mui2/bar + 2.*y + 1.)/((1.+y)-z*(1.-y)) - (vbar/vijk)*((1.+z) + 2.*mui2/(y*bar)) ) + y/(1.-z*(1.-y)) * ( 2.*(2.*mui2/bar + 2.*y + 1.)/((1.+y)-z*(1.-y)) - (vbar/vijk)*(2. + 2.*mua2/((1.-z*(1.-y))*bar)) ) ); return ret > 0. ? ret : 0.; } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FIMDecayqx2qgxDipoleKernel::persistentOutput(PersistentOStream & ) const { } void FIMDecayqx2qgxDipoleKernel::persistentInput(PersistentIStream & , int) { } ClassDescription FIMDecayqx2qgxDipoleKernel::initFIMDecayqx2qgxDipoleKernel; // Definition of the static class description member. void FIMDecayqx2qgxDipoleKernel::Init() { static ClassDocumentation documentation ("FIMDecayqx2qgxDipoleKernel"); } diff --git a/Shower/Dipole/Kernels/FIgx2ggxDipoleKernel.cc b/Shower/Dipole/Kernels/FIgx2ggxDipoleKernel.cc --- a/Shower/Dipole/Kernels/FIgx2ggxDipoleKernel.cc +++ b/Shower/Dipole/Kernels/FIgx2ggxDipoleKernel.cc @@ -1,106 +1,116 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the FIgx2ggxDipoleKernel class. // #include "FIgx2ggxDipoleKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; FIgx2ggxDipoleKernel::FIgx2ggxDipoleKernel() - : DipoleSplittingKernel(),theSymmetryFactor(0.5) {} + : DipoleSplittingKernel() {} FIgx2ggxDipoleKernel::~FIgx2ggxDipoleKernel() {} IBPtr FIgx2ggxDipoleKernel::clone() const { return new_ptr(*this); } IBPtr FIgx2ggxDipoleKernel::fullclone() const { return new_ptr(*this); } bool FIgx2ggxDipoleKernel::canHandle(const DipoleIndex& ind) const { return useThisKernel() && ind.emitterData()->id() == ParticleID::g && ind.spectatorData()->mass() == ZERO && !ind.initialStateEmitter() && ind.initialStateSpectator(); } bool FIgx2ggxDipoleKernel::canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const { assert(canHandle(a)); if ( !canHandle(b) ) return false; return sk.emitter(b)->id() == ParticleID::g && sk.emission(b)->id() == ParticleID::g && a.spectatorPDF() == b.spectatorPDF(); } tcPDPtr FIgx2ggxDipoleKernel::emitter(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr FIgx2ggxDipoleKernel::emission(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr FIgx2ggxDipoleKernel::spectator(const DipoleIndex& ind) const { return ind.spectatorData(); } double FIgx2ggxDipoleKernel::evaluate(const DipoleSplittingInfo& split) const { double ret = alphaPDF(split); double z = split.lastZ(); double x = 1. / ( 1. + sqr(split.lastPt()/split.scale()) / (z*(1.-z)) ); - ret *=theSymmetryFactor* 3. * ( 1./(1.-z+(1.-x)) + 1./(z+(1.-x)) - 2.+z*(1.-z) + (1.-x)*(1.+x*z*(1.-z)) ); - + double S1=1./(1.-z*(1.-x)); + double S2=1./(1.-(1.-z)*(1.-x)); + double NS=(-2 + z*(1.-z)+(1.-x)*(1.+x*z*(1.-z))); + + if( theAsymmetryOption == 0 ){ + ret *= 3.*( S1 + 0.5 * NS); + }else if ( theAsymmetryOption == 1 ){ + ret *= 3.*z*( S1 +S2 + NS ); + }else{ + ret *= 3.*0.5*( S1 + S2 + NS ); + } + return ret > 0. ? ret : 0.; } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FIgx2ggxDipoleKernel::persistentOutput(PersistentOStream & os) const { - os<>theSymmetryFactor; + is >> theAsymmetryOption; } ClassDescription FIgx2ggxDipoleKernel::initFIgx2ggxDipoleKernel; // Definition of the static class description member. void FIgx2ggxDipoleKernel::Init() { static ClassDocumentation documentation ("FIgx2ggxDipoleKernel"); - static Parameter interfaceSymmetryFactor - ("SymmetryFactor", - "The symmetry factor for final state gluon spliitings.", - &FIgx2ggxDipoleKernel::theSymmetryFactor, 1.0, 0.0, 0, - false, false, Interface::lowerlim); + static Parameter interfacetheAsymmetryOption + ("AsymmetryOption", + "The asymmetry option for final state gluon spliitings.", + &FIgx2ggxDipoleKernel::theAsymmetryOption, 1, 0, 0, + false, false, Interface::lowerlim); } diff --git a/Shower/Dipole/Kernels/FIgx2ggxDipoleKernel.h b/Shower/Dipole/Kernels/FIgx2ggxDipoleKernel.h --- a/Shower/Dipole/Kernels/FIgx2ggxDipoleKernel.h +++ b/Shower/Dipole/Kernels/FIgx2ggxDipoleKernel.h @@ -1,186 +1,186 @@ // -*- C++ -*- #ifndef HERWIG_FIgx2ggxDipoleKernel_H #define HERWIG_FIgx2ggxDipoleKernel_H // // This is the declaration of the FIgx2ggxDipoleKernel class. // #include "DipoleSplittingKernel.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief FIgx2ggxDipoleKernel implements the g -> gg * splitting off a final-initial dipole * */ class FIgx2ggxDipoleKernel: public DipoleSplittingKernel { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ FIgx2ggxDipoleKernel(); /** * The destructor. */ virtual ~FIgx2ggxDipoleKernel(); //@} public: /** * Return true, if this splitting kernel * applies to the given dipole index. */ virtual bool canHandle(const DipoleIndex&) const; /** * Return true, if this splitting kernel is * the same for the given index a, as the given * splitting kernel for index b. */ virtual bool canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const; /** * Return the emitter data after splitting, given * a dipole index. */ virtual tcPDPtr emitter(const DipoleIndex&) const; /** * Return the emission data after splitting, given * a dipole index. */ virtual tcPDPtr emission(const DipoleIndex&) const; /** * Return the spectator data after splitting, given * a dipole index. */ virtual tcPDPtr spectator(const DipoleIndex&) const; /** * Evaluate this splitting kernel for the given * dipole splitting. */ virtual double evaluate(const DipoleSplittingInfo&) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** - * Symmetry factor for final state gluon splittings (should be 1/2). - */ - - double theSymmetryFactor; + * Asymmetry option for final state gluon splittings. + */ + + int theAsymmetryOption=1; /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initFIgx2ggxDipoleKernel; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FIgx2ggxDipoleKernel & operator=(const FIgx2ggxDipoleKernel &); }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of FIgx2ggxDipoleKernel. */ template <> struct BaseClassTrait { /** Typedef of the first base class of FIgx2ggxDipoleKernel. */ typedef Herwig::DipoleSplittingKernel NthBase; }; /** This template specialization informs ThePEG about the name of * the FIgx2ggxDipoleKernel class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::FIgx2ggxDipoleKernel"; } /** * The name of a file containing the dynamic library where the class * FIgx2ggxDipoleKernel is implemented. It may also include several, space-separated, * libraries if the class FIgx2ggxDipoleKernel 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_FIgx2ggxDipoleKernel_H */ diff --git a/Shower/Dipole/Kinematics/DipoleSplittingKinematics.cc b/Shower/Dipole/Kinematics/DipoleSplittingKinematics.cc --- a/Shower/Dipole/Kinematics/DipoleSplittingKinematics.cc +++ b/Shower/Dipole/Kinematics/DipoleSplittingKinematics.cc @@ -1,327 +1,327 @@ // -*- C++ -*- // // DipoleSplittingKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 DipoleSplittingKinematics class. // #include "DipoleSplittingKinematics.h" #include "Herwig/Shower/Dipole/Base/DipoleSplittingInfo.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/RandomHelpers.h" #include using namespace Herwig; DipoleSplittingKinematics::DipoleSplittingKinematics() : HandlerBase(), theIRCutoff(1.0*GeV), theXMin(1.e-5), theJacobian(0.0), theLastPt(0.0*GeV), theLastZ(0.0), theLastPhi(0.0), theLastEmitterZ(1.0), theLastSpectatorZ(1.0), - theLastSplittingParameters(),theOpenZBoundaries(0) {} + theLastSplittingParameters(),theOpenZBoundaries(1) {} DipoleSplittingKinematics::~DipoleSplittingKinematics() {} void DipoleSplittingKinematics::persistentOutput(PersistentOStream & os) const { os << ounit(theIRCutoff,GeV) << theXMin << theMCCheck<> iunit(theIRCutoff,GeV) >> theXMin >> theMCCheck>>theOpenZBoundaries; } void DipoleSplittingKinematics::prepareSplitting(DipoleSplittingInfo& dInfo) { dInfo.splittingKinematics(this); if ( lastPt() > IRCutoff() ) dInfo.lastPt(lastPt()); else { dInfo.lastPt(0.0*GeV); dInfo.didStopEvolving(); } dInfo.lastZ(lastZ()); dInfo.lastPhi(lastPhi()); dInfo.lastEmitterZ(lastEmitterZ()); dInfo.lastSpectatorZ(lastSpectatorZ()); dInfo.splittingParameters().resize(lastSplittingParameters().size()); copy(lastSplittingParameters().begin(),lastSplittingParameters().end(), dInfo.splittingParameters().begin()); } Energy DipoleSplittingKinematics::ptMax(Energy dScale, double emX, double specX, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split) const { return ptMax(dScale, emX, specX, dInfo.index(), split); } Energy DipoleSplittingKinematics::ptMax(Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel& split, tPPtr, tPPtr) const { return ptMax(dScale, emX, specX, dIndex, split); } Energy DipoleSplittingKinematics::QMax(Energy dScale, double emX, double specX, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split) const { return QMax(dScale, emX, specX, dInfo.index(), split); } Energy DipoleSplittingKinematics::QMax(Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel& split, tPPtr, tPPtr) const { return QMax(dScale, emX, specX, dIndex, split); } Energy DipoleSplittingKinematics::generatePt(double r, Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel& split, double& weight) const { Energy maxPt = ptMax(dScale,emX,specX,dIndex,split); if ( maxPt <= IRCutoff() ) { weight = 0.0; return ZERO; } weight *= log(sqr(maxPt/IRCutoff())); return IRCutoff()*pow(maxPt/IRCutoff(),r); } double DipoleSplittingKinematics::ptToRandom(Energy pt, Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel& split) const { Energy maxPt = ptMax(dScale,emX,specX,dIndex,split); assert(pt >= IRCutoff() && pt <= maxPt); return log(pt/IRCutoff())/log(maxPt/IRCutoff()); } double DipoleSplittingKinematics::generateZ(double r, Energy pt, int sampling, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split, double& weight) const { pair zLims = zBoundaries(pt,dInfo,split); if(zLims.first==zLims.second){ weight = 0.0; return 0.0; } using namespace RandomHelpers; if ( sampling == FlatZ ) { pair kw = generate(flat(zLims.first,zLims.second),r); if ( kw.second != 0. ) { weight *= kw.second; return kw.first; } else { assert( kw.first < zLims.first || kw.first > zLims.second ); weight *= kw.second; return -1.; } } if ( sampling == OneOverZ ) { pair kw = generate(inverse(0.0,zLims.first,zLims.second),r); if ( kw.second != 0. ) { weight *= kw.second; return kw.first; } else { assert( kw.first < zLims.first || kw.first > zLims.second ); weight *= kw.second; return -1.; } } if ( sampling == OneOverOneMinusZ ) { pair kw = generate(inverse(1.0,zLims.first,zLims.second),r); if ( kw.second != 0. ) { weight *= kw.second; return kw.first; } else { assert( kw.first < zLims.first || kw.first > zLims.second ); weight *= kw.second; return -1.; } } if ( sampling == OneOverZOneMinusZ ) { pair kw = generate(inverse(0.0,zLims.first,zLims.second) + inverse(1.0,zLims.first,zLims.second),r); if ( kw.second != 0. ) { weight *= kw.second; return kw.first; } else { assert( kw.first < zLims.first || kw.first > zLims.second ); weight *= kw.second; return -1.; } } weight = 0.0; return 0.0; } Lorentz5Momentum DipoleSplittingKinematics::getKt(const Lorentz5Momentum& p1, const Lorentz5Momentum& p2, Energy pt, double phi, bool spacelike) const { Lorentz5Momentum P; if ( !spacelike ) P = p1 + p2; else P = p1 - p2; Energy2 Q2 = abs(P.m2()); Lorentz5Momentum Q = !spacelike ? Lorentz5Momentum(ZERO,ZERO,ZERO,sqrt(Q2),sqrt(Q2)) : Lorentz5Momentum(ZERO,ZERO,sqrt(Q2),ZERO,-sqrt(Q2)); if ( spacelike && Q.z() < P.z() ) Q.setZ(-Q.z()); bool boost = abs((P-Q).vect().mag2()/GeV2) > 1e-10 || abs((P-Q).t()/GeV) > 1e-5; boost &= (P*Q-Q.mass2())/GeV2 > 1e-8; Lorentz5Momentum inFrame1; if ( boost ) inFrame1 = p1 + ((P*p1-Q*p1)/(P*Q-Q.mass2()))*(P-Q); else inFrame1 = p1; Energy ptx = inFrame1.x(); Energy pty = inFrame1.y(); Energy q = 2.*inFrame1.z(); Energy Qp = sqrt(4.*(sqr(ptx)+sqr(pty))+sqr(q)); Energy Qy = sqrt(4.*sqr(pty)+sqr(q)); double cPhi = cos(phi); double sPhi = sqrt(1.-sqr(cPhi)); if ( phi > Constants::pi ) sPhi = -sPhi; Lorentz5Momentum kt; if ( !spacelike ) { kt.setT(ZERO); kt.setX(pt*Qy*cPhi/Qp); kt.setY(-pt*(4*ptx*pty*cPhi/Qp+q*sPhi)/Qy); kt.setZ(2.*pt*(-ptx*q*cPhi/Qp + pty*sPhi)/Qy); } else { kt.setT(2.*pt*(ptx*q*cPhi+pty*Qp*sPhi)/(q*Qy)); kt.setX(pt*(Qp*q*cPhi+4.*ptx*pty*sPhi)/(q*Qy)); kt.setY(pt*Qy*sPhi/q); kt.setZ(ZERO); } if ( boost ) kt = kt + ((P*kt-Q*kt)/(P*Q-Q.mass2()))*(P-Q); kt.setMass(-pt); kt.rescaleRho(); return kt; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). AbstractClassDescription DipoleSplittingKinematics::initDipoleSplittingKinematics; // Definition of the static class description member. void DipoleSplittingKinematics::Init() { static ClassDocumentation documentation ("DipoleSplittingKinematics is the base class for dipole splittings " "as performed in the dipole shower."); static Parameter interfaceIRCutoff ("IRCutoff", "The IR cutoff to be used by this splitting kinematics.", &DipoleSplittingKinematics::theIRCutoff, GeV, 1.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceXMin ("XMin", "The minimum momentum fraction for incoming partons", &DipoleSplittingKinematics::theXMin, 1.0e-5, 0.0, 1.0, false, false, Interface::limited); static Reference interfaceMCCheck ("MCCheck", "[debug option] MCCheck", &DipoleSplittingKinematics::theMCCheck, false, false, true, true, false); interfaceMCCheck.rank(-1); static Switch interfaceOpenZBoundaries ("OpenZBoundaries", "", &DipoleSplittingKinematics::theOpenZBoundaries, 0, false, false); static SwitchOption interfaceOpenZBoundarieshardScale (interfaceOpenZBoundaries, "Hard", "", 0); static SwitchOption interfaceOpenZBoundariesfull (interfaceOpenZBoundaries, "Full", "", 1); static SwitchOption interfaceOpenZBoundariesDipoleScale (interfaceOpenZBoundaries, "DipoleScale", "", 2); } diff --git a/Shower/Dipole/Kinematics/DipoleSplittingKinematics.h b/Shower/Dipole/Kinematics/DipoleSplittingKinematics.h --- a/Shower/Dipole/Kinematics/DipoleSplittingKinematics.h +++ b/Shower/Dipole/Kinematics/DipoleSplittingKinematics.h @@ -1,648 +1,643 @@ // -*- C++ -*- // // DipoleSplittingKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_DipoleSplittingKinematics_H #define HERWIG_DipoleSplittingKinematics_H // // This is the declaration of the DipoleSplittingKinematics class. // #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/Vectors/Lorentz5Vector.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Utilities/UtilityBase.h" #include "Herwig/Shower/Dipole/Utility/DipoleMCCheck.h" namespace Herwig { using namespace ThePEG; class DipoleIndex; class DipoleSplittingInfo; class DipoleSplittingKernel; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief DipoleSplittingKinematics is the base class for dipole splittings * as performed in the dipole shower. * * @see \ref DipoleSplittingKinematicsInterfaces "The interfaces" * defined for DipoleSplittingKinematics. */ class DipoleSplittingKinematics: public HandlerBase { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ DipoleSplittingKinematics(); /** * The destructor. */ virtual ~DipoleSplittingKinematics(); //@} 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 kappaSupport(const DipoleSplittingInfo&) const { return {0.0,1.0}; } /** * Return the boundaries in between the momentum * fraction random number is to be sampled. */ virtual pair xiSupport(const DipoleSplittingInfo&) 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 { // MEMinBias produces non-zero zeros. if(abs(pEmitter*pSpectator)<0.0000001*GeV2)return ZERO; assert(pEmitter*pSpectator >= ZERO); return sqrt(2.*pEmitter*pSpectator); } /** * Return the mass of the system absorbing * the recoil in the dipole splitting. * This is overloaded in the decay dipoles. */ virtual Energy recoilMassKin(const Lorentz5Momentum&, const Lorentz5Momentum& pSpectator) const { return pSpectator.m(); } /** * Return the maximum pt for the given dipole scale. */ virtual Energy ptMax(Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel& split) const =0; /** * 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 emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel& split, tPPtr emitter, tPPtr spectator) const; /** * Return the maximum virtuality for the given dipole scale. */ virtual Energy QMax(Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel& split) const =0; /** * 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 dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel& split, tPPtr emitter, tPPtr spectator) const; /** * Return the pt given a virtuality. */ virtual Energy PtFromQ(Energy scale, const DipoleSplittingInfo&) const = 0; /** * Return the virtuality given a pt. */ virtual Energy QFromPt(Energy scale, const DipoleSplittingInfo&) const = 0; /** * Return the infrared cutoff. */ virtual Energy IRCutoff() const { return theIRCutoff; } /** * Return the minimum momentum fraction for * incoming partons */ double xMin() const { return theXMin; } /** * Generate a pt */ Energy generatePt(double r, Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel& split, double& weight) 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& split) const; /** * Return the boundaries on the momentum fraction */ virtual pair zBoundaries(Energy pt, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split) const = 0; /** * Enumerate the variants of sampling z */ enum ZSamplingOptions { FlatZ = 0, OneOverZ, OneOverOneMinusZ, OneOverZOneMinusZ }; /** * Generate a z value flat */ double generateZ(double r, Energy pt, int sampling, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split, double& weight) 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& info, const DipoleSplittingKernel&) = 0; /** * Get the splitting phasespace weight associated to * the last call to generateSplitting. This is taken to * be the single particle phasespace times 16 \pi^2 divided * by the relevant propagator invariant. */ double jacobian() const { return theJacobian; } /** * Return true, if this splitting kinematics * class is capable of delivering an overestimate * to the jacobian. */ virtual bool haveOverestimate() const { return false; } /** * Return the overestimated jacobian for the * last generated parameters. */ virtual double jacobianOverestimate() const { return -1.; } /** * Return the last generated pt */ Energy lastPt() const { return theLastPt; } /** * Return the last generated momentum fraction. */ double lastZ() const { return theLastZ; } /** * Return the last calculated zPrime for massive FF and decay dipoles. */ // Do not need in current implementation, // using lastSplittingParameters instead. //double lastZPrime() const { return theLastZPrime; } /** * Return the last generated azimuthal angle. */ double lastPhi() const { return theLastPhi; } /** * Return the momentum fraction, by which the emitter's * momentum fraction should be divided after the splitting. */ double lastEmitterZ() const { return theLastEmitterZ; } /** * Return the momentum fraction, by which the spectator's * momentum fraction should be divided after the splitting. */ double lastSpectatorZ() const { return theLastSpectatorZ; } /** * Return any additional parameters needed to * evaluate the splitting kernel or to generate the * full splitting. */ const vector& lastSplittingParameters() const { return theLastSplittingParameters; } /** * Complete a DipoleSplittingInfo object with * the parameters generated by the last call to * generateSplitting() */ void prepareSplitting(DipoleSplittingInfo& dInfo); public: /** * 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) = 0; /** * Return the emitter's momentum after the splitting. */ const Lorentz5Momentum& lastEmitterMomentum() const { return theEmitterMomentum; } /** * Return the spectator's momentum after the splitting. */ const Lorentz5Momentum& lastSpectatorMomentum() const { return theSpectatorMomentum; } /** * Return the emission's momentum. */ const Lorentz5Momentum& lastEmissionMomentum() const { return theEmissionMomentum; } /* * Return true, if there is a transformation which should * be applied to all other final state particles except the ones * involved in the splitting after having performed the splitting. */ virtual bool doesTransform () const { return false; } /* + * Use the Dipole scale instead of hardpt for z-boundaries. + */ + int openZBoundaries() const { return theOpenZBoundaries; } + + /* * perform the transformation if required. */ virtual Lorentz5Momentum transform (const Lorentz5Momentum& p) const { return p; } /* * Return true if this splitting is of a dipole which contains * a decayed parton and requires the remnant to absorb the recoil. */ virtual bool isDecay() const { return false; } /** * Perform the recoil in the case of a decayed parton */ //virtual Lorentz5Momentum decayRecoil ( const Lorentz5Momentum& p, const int) { return p; } /** * Perform the recoil in the case of a decayed parton */ virtual void decayRecoil ( PList& ) {}; // {;} protected: /** * Calculate a transverse momentum for the given momenta, * invariant pt and azimuth. */ Lorentz5Momentum getKt(const Lorentz5Momentum& p1, const Lorentz5Momentum& p2, Energy pt, double phi, bool spacelike = false) const; /** * Set the splitting phasespace weight associated to * the last call to generateSplitting. This is taken to * be the single particle phasespace times 16 \pi^2 divided * by the relevant propagator invariant. */ void jacobian(double w) { theJacobian = w; } /** * Set the last generated pt */ void lastPt(Energy p) { theLastPt = p; } /** * Set the last generated momentum fraction. */ void lastZ(double z) { theLastZ = z; } /** * Set the last calculated zPrime for massive FF and decay dipoles. */ // Do not need in current implementation, // using lastSplittingParameters instead. //void lastZPrime(double zPrime) { theLastZPrime = zPrime; } /** * Set the last generated azimuthal angle. */ void lastPhi(double p) { theLastPhi = p; } /** * Set the momentum fraction, by which the emitter's * momentum fraction should be divided after the splitting. */ void lastEmitterZ(double z) { theLastEmitterZ = z; } /** * Set the momentum fraction, by which the spectator's * momentum fraction should be divided after the splitting. */ void lastSpectatorZ(double z) { theLastSpectatorZ = z; } /** * Access any additional parameters needed to * evaluate the splitting kernel or to generate the * full splitting. */ vector& splittingParameters() { return theLastSplittingParameters; } /** * Set the emitter's momentum after the splitting. */ void emitterMomentum(const Lorentz5Momentum& p) { theEmitterMomentum = p; } /** * Set the spectator's momentum after the splitting. */ void spectatorMomentum(const Lorentz5Momentum& p) { theSpectatorMomentum = p; } /** * Set the emission's momentum. */ void emissionMomentum(const Lorentz5Momentum& p) { theEmissionMomentum = p; } /** * Set the momentum of the recoil system before the splitting. * 25/05/2016 - Not currently used. */ //void recoilMomentum( const Lorentz5Momentum& mom ) { theRecoilMomentum = mom; } /** * Set the momentum of the recoil system after the splitting. */ void splitRecoilMomentum( const Lorentz5Momentum& mom ) { theSplitRecoilMomentum = mom; } /** * Return the momentum of the recoil system before splitting. * 25/05/2016 - Not currently used. */ //const Lorentz5Momentum& recoilMomentum() const { return theRecoilMomentum; } /** * Return the momentum of the recoil system after splitting. */ const Lorentz5Momentum& splitRecoilMomentum() const { return theSplitRecoilMomentum; } - - - /* - * Use the Dipole scale instead of hardpt for z-boundaries. - */ - - int openZBoundaries() const { return theOpenZBoundaries; } - - - 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(); 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); //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The infrared cutoff associated to this * splitting kinematics. */ Energy theIRCutoff; /** * The minimum momentum fraction for * incoming partons */ double theXMin; /** * The last calculated splitting phase space weight. */ double theJacobian; /** * The last generated pt */ Energy theLastPt; /** * The last generated momentum fraction. */ double theLastZ; /** * The last calculated zPrime required for massive FF * and decay kinematics dipoles. * zPrime := qi.nk / (qi+qj).nk (qj = emission momentum) */ // Do not need in current implementation, // using lastSplittingParameters instead. //double theLastZPrime; /** * The last generated azimuthal angle. */ double theLastPhi; /** * The momentum fraction, by which the emitter's * momentum fraction should be divided after the splitting. */ double theLastEmitterZ; /** * The momentum fraction, by which the spectator's * momentum fraction should be divided after the splitting. */ double theLastSpectatorZ; /** * Any additional parameters needed to * evaluate the splitting kernel or to generate the * full splitting. */ vector theLastSplittingParameters; /** * The emitter's momentum after the splitting. */ Lorentz5Momentum theEmitterMomentum; /** * The emission's momentum after the splitting. */ Lorentz5Momentum theEmissionMomentum; /** * The spectator's momentum after the splitting. */ Lorentz5Momentum theSpectatorMomentum; /** * The momentum of the recoil system used in decay dipole kinematics. * 25/05/2016 - Not currently used */ //Lorentz5Momentum theRecoilMomentum; /** * The momentum of the recoil system after the splitting, used in decay dipole kinematics. */ Lorentz5Momentum theSplitRecoilMomentum; int theOpenZBoundaries; protected: /** * Pointer to a check histogram object */ Ptr::ptr theMCCheck; private: /** * The static object used to initialize the description of this class. * Indicates that this is an abstract class. */ static AbstractClassDescription initDipoleSplittingKinematics; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ DipoleSplittingKinematics & operator=(const DipoleSplittingKinematics &); }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of DipoleSplittingKinematics. */ template <> struct BaseClassTrait { /** Typedef of the first base class of DipoleSplittingKinematics. */ typedef HandlerBase NthBase; }; /** This template specialization informs ThePEG about the name of * the DipoleSplittingKinematics class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::DipoleSplittingKinematics"; } /** * The name of a file containing the dynamic library where the class * DipoleSplittingKinematics is implemented. It may also include several, space-separated, * libraries if the class DipoleSplittingKinematics 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_DipoleSplittingKinematics_H */ diff --git a/Shower/Dipole/Kinematics/FILightKinematics.cc b/Shower/Dipole/Kinematics/FILightKinematics.cc --- a/Shower/Dipole/Kinematics/FILightKinematics.cc +++ b/Shower/Dipole/Kinematics/FILightKinematics.cc @@ -1,187 +1,187 @@ // -*- C++ -*- // // FILightKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 FILightKinematics class. // #include "FILightKinematics.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "Herwig/Shower/Dipole/Base/DipoleSplittingInfo.h" using namespace Herwig; FILightKinematics::FILightKinematics() : DipoleSplittingKinematics() {} FILightKinematics::~FILightKinematics() {} IBPtr FILightKinematics::clone() const { return new_ptr(*this); } IBPtr FILightKinematics::fullclone() const { return new_ptr(*this); } Energy FILightKinematics::ptMax(Energy dScale, double, double specX, const DipoleIndex&, const DipoleSplittingKernel&) const { return dScale * sqrt((1.-specX)/specX) /2.; } Energy FILightKinematics::QMax(Energy dScale, double, double specX, const DipoleIndex&, const DipoleSplittingKernel&) const { return dScale * sqrt((1.-specX)/specX); } Energy FILightKinematics::PtFromQ(Energy scale, const DipoleSplittingInfo& split) const { double z = split.lastZ(); return scale*sqrt(z*(1.-z)); } Energy FILightKinematics::QFromPt(Energy scale, const DipoleSplittingInfo& split) const { double z = split.lastZ(); return scale/sqrt(z*(1.-z)); } pair FILightKinematics::zBoundaries(Energy pt, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel&) const { Energy hard=dInfo.hardPt(); if(openZBoundaries()==1) - hard=dInfo.scale()*sqrt((1.-dInfo.spectatorX())/dInfo.spectatorX()/2.); + hard=dInfo.scale()*sqrt((1.-dInfo.spectatorX())/dInfo.spectatorX())/2.; if(openZBoundaries()==2) - hard=dInfo.scale()*min(1.,sqrt((1.-dInfo.spectatorX())/dInfo.spectatorX())/2.); + hard=dInfo.scale()*min(1.,sqrt((1.-dInfo.spectatorX())/dInfo.spectatorX())/2.); if(hard info.hardPt() ) { jacobian(0.0); return false; } double z = 0.0; if ( info.index().emitterData()->id() == ParticleID::g ) { if ( info.emissionData()->id() != ParticleID::g ) { z = generateZ(xi,pt,FlatZ, info,split,weight); } else { z = generateZ(xi,pt,OneOverZOneMinusZ, info,split,weight); } } else { z = generateZ(xi,pt,OneOverOneMinusZ, info,split,weight); } double x = 1./(1.+sqr(pt/info.scale())/(z*(1.-z))); if ( z < 0.0 || z > 1.0 || x < info.spectatorX() || x > 1.0 ) { jacobian(0.0); return false; } double phi = 2.*Constants::pi*rphi; jacobian(weight); lastPt(pt); lastZ(z); lastPhi(phi); lastSpectatorZ(x); if ( theMCCheck ) theMCCheck->book(1.,info.spectatorX(),info.scale(),info.hardPt(),pt,z,jacobian()); return true; } void FILightKinematics::generateKinematics(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo& dInfo) { Energy pt = dInfo.lastPt(); double z = dInfo.lastZ(); double x = 1./(1.+sqr(pt/dInfo.scale())/(z*(1.-z))); Lorentz5Momentum kt = getKt (pSpectator, pEmitter, pt, dInfo.lastPhi(),true); Lorentz5Momentum em = z*pEmitter + (1.-z)*((1.-x)/x)*pSpectator + kt; Lorentz5Momentum emm = (1.-z)*pEmitter + z*((1.-x)/x)*pSpectator - kt; Lorentz5Momentum spe = (1./x)*pSpectator; em.setMass(ZERO); em.rescaleEnergy(); emm.setMass(ZERO); emm.rescaleEnergy(); spe.setMass(ZERO); spe.rescaleEnergy(); emitterMomentum(em); emissionMomentum(emm); spectatorMomentum(spe); } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FILightKinematics::persistentOutput(PersistentOStream & ) const { } void FILightKinematics::persistentInput(PersistentIStream & , int) { } ClassDescription FILightKinematics::initFILightKinematics; // Definition of the static class description member. void FILightKinematics::Init() { static ClassDocumentation documentation ("FILightKinematics implements massless splittings " "off a final-initial dipole."); } diff --git a/Shower/Dipole/Kinematics/FIMassiveDecayKinematics.cc b/Shower/Dipole/Kinematics/FIMassiveDecayKinematics.cc --- a/Shower/Dipole/Kinematics/FIMassiveDecayKinematics.cc +++ b/Shower/Dipole/Kinematics/FIMassiveDecayKinematics.cc @@ -1,504 +1,512 @@ // -*- C++ -*- // // FIMassiveDecayKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 FIMassiveDecayKinematics class. // #include "FIMassiveDecayKinematics.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "Herwig/Shower/Dipole/Base/DipoleSplittingInfo.h" #include "Herwig/Shower/Dipole/Kernels/DipoleSplittingKernel.h" #include "ThePEG/Interface/Switch.h" using namespace Herwig; FIMassiveDecayKinematics::FIMassiveDecayKinematics() : DipoleSplittingKinematics(), theFullJacobian(true) {} FIMassiveDecayKinematics::~FIMassiveDecayKinematics() {} IBPtr FIMassiveDecayKinematics::clone() const { return new_ptr(*this); } IBPtr FIMassiveDecayKinematics::fullclone() const { return new_ptr(*this); } pair FIMassiveDecayKinematics::kappaSupport(const DipoleSplittingInfo&) const { return {0.0,1.0}; } pair FIMassiveDecayKinematics::xiSupport(const DipoleSplittingInfo& split) const { double c = sqrt(1.-4.*sqr(IRCutoff()/generator()->maximumCMEnergy())); if ( split.index().emitterData()->id() == ParticleID::g ) { if ( split.emissionData()->id() != ParticleID::g ){ return {0.5*(1.-c),0.5*(1.+c)}; } double b = log((1.+c)/(1.-c)); return {-b,b}; } return {-log(0.5*(1.+c)),-log(0.5*(1.-c))}; } Energy FIMassiveDecayKinematics::dipoleScale(const Lorentz5Momentum&, const Lorentz5Momentum& pSpectator) const { return pSpectator.m(); } Energy FIMassiveDecayKinematics::recoilMassKin(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator) const { Lorentz5Momentum pk = pSpectator - pEmitter; Energy pkmass = pk.m(); return pkmass; } Energy FIMassiveDecayKinematics::ptMax(Energy dScale, double, double, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split) const { DipoleIndex ind = dInfo.index(); double mui2 = 0.; // g->gg and g->qqbar if ( abs(split.emitter(ind)->id()) == abs(split.emission(ind)->id()) ) { mui2 = sqr(split.emitter(ind)->mass() / dScale); } // Otherwise have X->Xg (should work for SUSY) else { mui2 = sqr(dInfo.emitterMass()/dScale); } double mu2 = sqr(split.emission(ind)->mass() / dScale); // Mass of recoil system double muj = dInfo.recoilMass() / dScale; return rootOfKallen( mui2, mu2, sqr(1.-muj) ) / ( 2.-2.*muj ) * dScale; } Energy FIMassiveDecayKinematics::ptMax(Energy dScale, double, double, const DipoleIndex& ind, const DipoleSplittingKernel& split, tPPtr emitter, tPPtr spectator) const { double mui2 = 0.; // g->gg and g->qqbar if ( abs(split.emitter(ind)->id()) == abs(split.emission(ind)->id()) ) { mui2 = sqr(split.emitter(ind)->mass() / dScale); } // Otherwise have X->Xg (should work for SUSY) else { mui2 = sqr(emitter->mass()/dScale); } double mu2 = sqr(split.emission(ind)->mass() / dScale); // Mass of recoil system double muj = recoilMassKin(emitter->momentum(),spectator->momentum()) / dScale; return rootOfKallen( mui2, mu2, sqr(1.-muj) ) / ( 2.-2.*muj ) * dScale; } Energy FIMassiveDecayKinematics::QMax(Energy dScale, double, double, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel&) const { assert(false && "implementation missing"); // Mass of recoil system double Muj2 = sqr( dInfo.recoilMass() / dScale ); double Muj = sqrt( Muj2 ); return dScale * ( 1.-2.*Muj+Muj2 ); } // The name of this function is misleading // scale here is defined as sqr(scale) = sqr(qi+qj) // Here, scale is Q Energy FIMassiveDecayKinematics::PtFromQ(Energy scale, const DipoleSplittingInfo& split) const { double zPrime = split.lastSplittingParameters()[0]; // masses Energy2 mi2 = ZERO; // g->gg and g->qqbar if ( abs(split.emitterData()->id()) == abs(split.emissionData()->id()) ) { mi2 = sqr( split.emitterData()->mass()); } // Otherwise have X->Xg (should work for SUSY) else { mi2 = sqr(split.emitterMass()); } Energy2 m2 = sqr(split.emissionData()->mass()); Energy2 pt2 = zPrime*(1.-zPrime)*sqr(scale) - (1-zPrime)*mi2 - zPrime*m2; assert(pt2 >= ZERO); return sqrt(pt2); } // This is simply the inverse of PtFromQ Energy FIMassiveDecayKinematics::QFromPt(Energy pt, const DipoleSplittingInfo& split) const { double zPrime = split.lastSplittingParameters()[0]; // masses Energy2 mi2 = ZERO; // g->gg and g->qqbar if ( abs(split.emitterData()->id()) == abs(split.emissionData()->id()) ) { mi2 = sqr( split.emitterData()->mass()); } // Otherwise have X->Xg (should work for SUSY) else { mi2 = sqr(split.emitterMass()); } Energy2 m2 = sqr(split.emissionData()->mass()); Energy2 Q2 = (sqr(pt) + (1-zPrime)*mi2 + zPrime*m2)/(zPrime*(1.-zPrime)); return sqrt(Q2); } double FIMassiveDecayKinematics::ptToRandom(Energy pt, Energy, double,double, const DipoleIndex&, const DipoleSplittingKernel&) const { return log(pt/IRCutoff()) / log(0.5 * generator()->maximumCMEnergy()/IRCutoff()); } bool FIMassiveDecayKinematics::generateSplitting(double kappa, double xi, double rphi, DipoleSplittingInfo& info, const DipoleSplittingKernel&) { // scaled masses double Mui2 = sqr(info.emitterMass() / info.scale()); double Muj2 = sqr(info.recoilMass() / info.scale()); double muj2 = Muj2; double mui2 = 0.; // g->gg and g->qqbar if ( abs(info.emitterData()->id()) == abs(info.emissionData()->id()) ) { mui2 = sqr(info.emitterData()->mass()/info.scale()); } // Otherwise have X->Xg (should work for SUSY) else { mui2 = Mui2; } double mu2 = sqr(info.emissionData()->mass()/info.scale() ); // To solve issue with scale during presampling // need to enforce that Qijk-mij2-mk2 = 2*pij.pk > 0, // so combine checks by comparing against square root. if ( 1.-Mui2-Muj2 < sqrt(4.*Mui2*Muj2) ) { jacobian(0.0); return false; } Energy2 Qijk = sqr(info.scale()); double suijk = 0.5*( 1. - Mui2 - Muj2 + sqrt( sqr(1.-Mui2-Muj2) - 4.*Mui2*Muj2 ) ); // Calculate pt Energy pt = IRCutoff() * pow(0.5 * generator()->maximumCMEnergy()/IRCutoff(),kappa); Energy2 pt2 = sqr(pt); if ( pt > info.hardPt() || pt < IRCutoff() ) { jacobian(0.0); return false; } // Generate zPrime (i.e. the new definition of z specific to massive FF and decays) double zPrime; if ( info.index().emitterData()->id() == ParticleID::g ) { if ( info.emissionData()->id() != ParticleID::g ) { zPrime = xi; } else { zPrime = exp(xi)/(1.+exp(xi)); } } else { zPrime = 1.-exp(-xi); } // new: 2011-08-31 // 2011-11-08: this does happen if( sqrt(mui2)+sqrt(mu2)+sqrt(muj2) > 1. ){ jacobian(0.0); return false; } // Have derived and checked the equations for zp1 and zm1, these apply to zPrime // phasespace constraint to incorporate ptMax - Energy hard=info.hardPt(); + Energy hard = info.hardPt(); + + if(openZBoundaries()>0){ + // From ptMax(..) + hard = rootOfKallen( mui2, mu2, sqr(1.-sqrt(muj2)) ) / + ( 2.-2.*sqrt(muj2) ) * info.scale(); + assert(pt<=hard); + } + double ptRatio = sqrt(1.-sqr(pt/hard)); double zp1 = ( 1.+mui2-mu2+muj2-2.*sqrt(muj2) + rootOfKallen(mui2,mu2,sqr(1-sqrt(muj2))) * ptRatio) / ( 2.*sqr(1.-sqrt(muj2)) ); double zm1 = ( 1.+mui2-mu2+muj2-2.*sqrt(muj2) - rootOfKallen(mui2,mu2,sqr(1-sqrt(muj2))) * ptRatio) / ( 2.*sqr(1.-sqrt(muj2)) ); if ( zPrime > zp1 || zPrime < zm1 ) { jacobian(0.0); return false; } // Calculate A:=xij*w double A = (1./(suijk*zPrime*(1.-zPrime))) * ( pt2/Qijk + zPrime*mu2 + (1.-zPrime)*mui2 - zPrime*(1.-zPrime)*Mui2 ); // Calculate y from A (can also write explicitly in terms of qt, zPrime and masses however we need A anyway) double bar = 1.-mui2-mu2-muj2; double y = (1./bar) * (A*suijk + Mui2 - mui2 - mu2 ); // kinematic phasespace boundaries for y // same as in Dittmaier hep-ph/9904440v2 (equivalent to CS) double ym = 2.*sqrt(mui2)*sqrt(mu2)/bar; double yp = 1. - 2.*sqrt(muj2)*(1.-sqrt(muj2))/bar; if ( y < ym || y > yp ) { jacobian(0.0); return false; } // Calculate xk and xij double lambdaK = 1. + (Muj2/suijk); double lambdaIJ = 1. + (Mui2/suijk); double xk = (1./(2.*lambdaK)) * ( (lambdaK + (Muj2/suijk)*lambdaIJ - A) + sqrt( sqr(lambdaK + (Muj2/suijk)*lambdaIJ - A) - 4.*lambdaK*lambdaIJ*Muj2/suijk) ); double xij = 1. - ( (Muj2/suijk) * (1.-xk) / xk ); // Transform to standard z definition as used in the kernels (i.e. that used in CS and standard sudakov parametrisations) double z = ( (zPrime*xij*xk*suijk/2.) + (Muj2/ ( 2.*xk*xij*suijk*zPrime))*(pt2/Qijk + mui2) ) / ( (xij*xk*suijk/2.) + (Muj2/(2.*xk*xij))*(Mui2/suijk + A) ); // These apply to z, not zPrime double zm = ( (2.*mui2+bar*y)*(1.-y) - sqrt(y*y-ym*ym)*sqrt(sqr(2.*muj2+bar-bar*y)-4.*muj2) ) / ( 2.*(1.-y)*(mui2+mu2+bar*y) ); double zp = ( (2.*mui2+bar*y)*(1.-y) + sqrt(y*y-ym*ym)*sqrt(sqr(2.*muj2+bar-bar*y)-4.*muj2) ) / ( 2.*(1.-y)*(mui2+mu2+bar*y) ); if ( z < zm || z > zp ) { jacobian(0.0); return false; } double phi = 2.*Constants::pi*rphi; double mapZJacobian; if ( info.index().emitterData()->id() == ParticleID::g ) { if ( info.emissionData()->id() != ParticleID::g ) { mapZJacobian = 1.; } else { mapZJacobian = z*(1.-z); } } else { mapZJacobian = 1.-z; } // Compute and store the jacobian double jac = 0.0; double propCntrb = 1./ ( 1. + (mui2+mu2-Mui2)/(bar*y) ); // TODO - SW - Tidy up notation everywhere alongside writing for the manual // The full jacobian including the z->zprime jacobian if ( theFullJacobian ) { // Sort out variables Energy2 sbar = Qijk*bar; Energy2 sijk = Qijk*suijk; Energy2 mi2 = Qijk*mui2; Energy2 mj2 = Qijk*mu2; Energy2 mk2 = Qijk*muj2; // Compute dy/dzPrime and pt2* dy/dpt2 double dyBydzPrime = (1./sbar) * ( -pt2*(1.-2.*zPrime)/sqr(zPrime*(1.-zPrime)) - mi2/sqr(zPrime) + mj2/sqr(1.-zPrime) ); InvEnergy2 dyBydpt2 = 1./(sbar*zPrime*(1.-zPrime)); // Compute dA/dzPrime and dA/dpt2 double dABydzPrime = (sbar/sijk) * dyBydzPrime; InvEnergy2 dABydpt2 = (sbar/sijk) * dyBydpt2; // Compute dxk/dzPrime, dxk/dpt2, dxij/dzPrime and dxij/dpt2 double factor = (0.5/lambdaK) * (-1. - (1./sqrt( sqr(lambdaK + (mk2/sijk)*lambdaIJ - A) - 4.*lambdaK*lambdaIJ*mk2/sijk)) * (lambdaK + (mk2/sijk)*lambdaIJ - A)); double dxkBydzPrime = factor * dABydzPrime; InvEnergy2 dxkBydpt2 = factor * dABydpt2; double dxijBydzPrime = (mk2/sijk) * (1./sqr(xk)) * dxkBydzPrime; InvEnergy2 dxijBydpt2 = (mk2/sijk) * (1./sqr(xk)) * dxkBydpt2; Energy2 dqiDotqkBydzPrime = xij*xk*0.5*sijk + zPrime*dxijBydzPrime*xk*0.5*sijk + zPrime*xij*dxkBydzPrime*0.5*sijk + 0.5*(mk2/sijk)*(pt2 + mi2) * (-1./(xk*xij*sqr(zPrime)) - dxkBydzPrime/(zPrime*xij*sqr(xk)) - dxijBydzPrime/(zPrime*xk*sqr(xij))); double dqiDotqkBydpt2 = dxijBydpt2*zPrime*xk*0.5*sijk + zPrime*xij*dxkBydpt2*0.5*sijk + (0.5*mk2/sijk) * (1./(zPrime*xk*xij)) * (1. + (pt2+mi2)*(-dxkBydpt2/xk - dxijBydpt2/xij) ); // Compute dzBydzPrime and dzBydpt2 Energy2 qiDotqk = (zPrime*xij*xk*sijk*0.5) + (mk2/ ( 2.*xk*xij*sijk*zPrime))*(pt2 + mi2); double dzBydzPrime = (1./sbar) * ( 2.*qiDotqk*dyBydzPrime/sqr(1.-y) + (1./(1.-y)) * 2.*dqiDotqkBydzPrime ); InvEnergy2 dzBydpt2 = (1./sbar) * ( 2.*qiDotqk*dyBydpt2/sqr(1.-y) + (1./(1.-y)) * 2.*dqiDotqkBydpt2 ); double pt2Jac = pt2*abs(dzBydpt2*dyBydzPrime - dzBydzPrime*dyBydpt2); // Include the other terms and calculate the jacobian jac = propCntrb * bar / rootOfKallen(1.,Mui2,Muj2) * (1.-y)/y * pt2Jac; } else { double jacPt2 = 1. / ( 1. + sqr(1.-zPrime)*Qijk*mui2/pt2 + zPrime*zPrime*Qijk*mu2/pt2 ); jac = propCntrb * bar / rootOfKallen(1.,Mui2,Muj2) * (1.-y) * jacPt2; } jacobian(jac * mapZJacobian * 2. * log(0.5 * generator()->maximumCMEnergy()/IRCutoff()) ); // Record the physical variables, as used by the CS kernel definitions lastPt(pt); lastZ(z); lastPhi(phi); // Record zPrime for use in kinematics generation splittingParameters().clear(); splittingParameters().push_back(zPrime); if ( theMCCheck ) { theMCCheck->book(1.,1.,info.scale(),info.hardPt(),pt,z,jacobian()); } return true; } void FIMassiveDecayKinematics::generateKinematics(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo& dInfo) { // The only value stored in dInfo.lastSplittingParameters() should be zPrime assert(dInfo.lastSplittingParameters().size() == 1 ); double zPrime = dInfo.lastSplittingParameters()[0]; Energy pt = dInfo.lastPt(); Energy2 pt2 = sqr(pt); // Momentum of the recoil system Lorentz5Momentum pk = pSpectator - pEmitter; Lorentz5Momentum pij = pEmitter; // scaled masses double Mui2 = sqr(dInfo.emitterMass() / dInfo.scale()); double Muk2 = sqr(dInfo.recoilMass() / dInfo.scale()); //double muk2 = Muk2; Energy mi = ZERO; // g->gg and g->qqbar if ( abs(dInfo.emitterData()->id()) == abs(dInfo.emissionData()->id()) ) { mi = dInfo.emitterData()->mass(); } // Otherwise have X->Xg (should work for SUSY) else { mi = dInfo.emitterMass(); } double mui2 = sqr(mi/dInfo.scale()); double mu2 = sqr(dInfo.emissionData()->mass()/dInfo.scale() ); Energy2 Qijk = sqr(dInfo.scale()); double suijk = 0.5*( 1. - Mui2 - Muk2 + sqrt( sqr(1.-Mui2-Muk2) - 4.*Mui2*Muk2 ) ); double suijk2 = sqr(suijk); // Calculate A:=xij*w double A = (1./(suijk*zPrime*(1.-zPrime))) * ( pt2/Qijk + zPrime*mu2 + (1.-zPrime)*mui2 - zPrime*(1.-zPrime)*Mui2 ); // Calculate the scaling factors, xk and xij double lambdaK = 1. + (Muk2/suijk); double lambdaIJ = 1. + (Mui2/suijk); double xk = (1./(2.*lambdaK)) * ( (lambdaK + (Muk2/suijk)*lambdaIJ - A) + sqrt( sqr(lambdaK + (Muk2/suijk)*lambdaIJ - A) - 4.*lambdaK*lambdaIJ*Muk2/suijk) ); double xij = 1. - ( (Muk2/suijk) * (1.-xk) / xk ); // Construct reference momenta nk, nij, nt Lorentz5Momentum nij = ( suijk2 / (suijk2-Mui2*Muk2) ) * (pij - (Mui2/suijk)*pk); Lorentz5Momentum nk = ( suijk2 / (suijk2-Mui2*Muk2) ) * (pk - (Muk2/suijk)*pij); // Following notation in notes, qt = sqrt(wt)*nt Lorentz5Momentum qt = getKt(nij,nk,pt,dInfo.lastPhi()); // Construct qij, qk, qi and qj Lorentz5Momentum qij = xij*nij + (Mui2/(xij*suijk))*nk; Lorentz5Momentum qk = xk*nk + (Muk2/(xk*suijk))*nij; // No need to actually calculate nt and wt: Lorentz5Momentum qi = zPrime*qij + ((pt2/Qijk + mui2 - zPrime*zPrime*Mui2)/(xij*suijk*zPrime))*nk + qt; Lorentz5Momentum qj = (1.-zPrime)*qij + ((pt2/Qijk + mu2 - sqr(1.-zPrime)*Mui2)/(xij*suijk*(1.-zPrime)))*nk - qt; qi.setMass(mi); qi.rescaleEnergy(); qj.setMass(dInfo.emissionData()->mass()); qj.rescaleEnergy(); emitterMomentum(qi); emissionMomentum(qj); spectatorMomentum(pSpectator); // Required for absorbing recoil in DipoleEventRecord::update splitRecoilMomentum(qk); } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FIMassiveDecayKinematics::persistentOutput(PersistentOStream & os) const { os << theFullJacobian; } void FIMassiveDecayKinematics::persistentInput(PersistentIStream & is, int) { is >> theFullJacobian; } ClassDescription FIMassiveDecayKinematics::initFIMassiveDecayKinematics; // Definition of the static class description member. void FIMassiveDecayKinematics::Init() { static ClassDocumentation documentation ("FIMassiveDecayKinematics implements implements massive splittings " "off a final-initial decay dipole."); static Switch interfaceFullJacobian ("FullJacobian", "Use the full jacobian expression for the FI Decay kinematics.", &FIMassiveDecayKinematics::theFullJacobian, true, false, false); static SwitchOption interfaceFullJacobianYes (interfaceFullJacobian, "Yes", "Use the full jacobian.", true); static SwitchOption interfaceFullJacobianNo (interfaceFullJacobian, "No", "Do not use the full jacobian.", false); interfaceFullJacobian.rank(-1); } diff --git a/Shower/Dipole/Makefile.am b/Shower/Dipole/Makefile.am --- a/Shower/Dipole/Makefile.am +++ b/Shower/Dipole/Makefile.am @@ -1,22 +1,23 @@ -SUBDIRS = Base Kernels Kinematics Utility AlphaS Merging +SUBDIRS = Base Kernels Kinematics Utility AlphaS Merging Colorea pkglib_LTLIBRARIES = HwDipoleShower.la -HwDipoleShower_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 8:2:0 +HwDipoleShower_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 9:0:0 HwDipoleShower_la_LIBADD = \ Base/libHwDipoleShowerBase.la \ Kernels/libHwDipoleShowerKernels.la \ Kinematics/libHwDipoleShowerKinematics.la \ Utility/libHwDipoleShowerUtility.la \ - Merging/libHwDipoleShowerMerging.la + Merging/libHwDipoleShowerMerging.la \ + Colorea/libHwDipoleShowerColorea.la HwDipoleShower_la_SOURCES = \ DipoleShowerHandler.h DipoleShowerHandler.fh DipoleShowerHandler.cc pkglib_LTLIBRARIES += HwKrknloEventReweight.la HwKrknloEventReweight_la_SOURCES = \ KrkNLO/KrknloEventReweight.h KrkNLO/KrknloEventReweight.cc HwKrknloEventReweight_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 1:0:0 diff --git a/Shower/Dipole/Merging/Merger.cc b/Shower/Dipole/Merging/Merger.cc --- a/Shower/Dipole/Merging/Merger.cc +++ b/Shower/Dipole/Merging/Merger.cc @@ -1,1622 +1,1614 @@ // -*- C++ -*- // // Merger.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 Merger class. // #include "Merger.h" #include "Node.h" #include "MergingFactory.h" // other includes when needed below. using namespace Herwig; IBPtr Merger::clone() const { return new_ptr( *this ); } IBPtr Merger::fullclone() const { return new_ptr( *this ); } namespace { double decideClustering(const NodePtr sub,const NodePtr head,bool& pro){ if( sub != head ){// at least one history step -> unitarisation if ( UseRandom::rndbool() ){ pro = true; return -2.; } else{ pro = false; return 2.; } } // no ordered history -> no projection else{ pro = false; return 1.; } } } CrossSection Merger::MergingDSigDRBornStandard( ){ // get the history for the process const NodePtr productionNode = currentNode()-> getHistory( true, DSH()->hardScaleFactor() ); // decide if to cluster weight = decideClustering(productionNode, currentNode(), projected); // check if we only want to calculate the current multiplicity. if(notOnlyMulti()) return ZERO; // Check for cuts on the production proces. if ( !productionNode->xcomb()->willPassCuts() ) return ZERO; // calculate the staring scale for the production node Energy startscale = CKKW_StartScale( productionNode ); // fill history with caluclation of sudakov supression fillHistory( startscale , productionNode , currentNode() ); // fill the projector -> return the scale of the last splitting currentNode()->runningPt( fillProjector( projected ? 1 : 0 ) ); // the weight has three components to get shower history weight weight *= history.back().weight* // Sudakov suppression alphaReweight()* // alpha_s reweight pdfReweight(); // pdf reweight // If weight is zero return. if( weight == ZERO ) return ZERO; //calculate the cross section return weight*TreedSigDR( startscale , 1. ); } CrossSection Merger::MergingDSigDRVirtualStandard( ){ // get the history for the process const NodePtr productionNode = currentNode()-> getHistory( true , DSH()->hardScaleFactor() ); // decide if to cluster weight = decideClustering(productionNode,currentNode(),projected); // Check for cuts on the production proces. if ( !productionNode->xcomb()->willPassCuts() )return ZERO; // calculate the staring scale Energy startscale = CKKW_StartScale( productionNode ); // fill history with caluclation of sudakov supression fillHistory( startscale , productionNode , currentNode() ); // fill the projector -> return the scale of the last splitting currentNode()->runningPt( fillProjector( projected ? 1 : 0 ) ); // the weight has three components to get shower history weight double ww1 = history.back().weight; double ww2 = alphaReweight(true); double ww3 = pdfReweight(); weight *= ww1*ww2*ww3; // If weight is zero return. if( weight == 0. )return ZERO; // calculate the cross section for virtual contribution // and various insertion operators. CrossSection matrixElement = LoopdSigDR( startscale ); // Now calculate the expansion of the shower history. // first: the born contibution: CrossSection bornWeight = currentME()->dSigHatDRB(); // second: expansion of pdf ,alpha_s-ratio and sudakov suppression. double w1 = -sumPdfReweightExpansion(); double w2 = -sumAlphaSReweightExpansion(); double w3 = -sumFillHistoryExpansion(); // put together the expansion weights. CrossSection expansionweight = bornWeight*SM().alphaS()/( 2.*ThePEG::Constants::pi ); if (theShowerExpansionWeights == 0){ expansionweight *=0.; }else if ( theShowerExpansionWeights == 1 ){ expansionweight *=w1+w2+w3; }else if ( theShowerExpansionWeights == 2 ){ expansionweight *=w1+w2+w3*pow(as( startscale*DSH()->renFac() )/SM().alphaS(),currentME()->orderInAlphaS())/ww2; }else if ( theShowerExpansionWeights == 3 ){ expansionweight *=(w1+w2+w3)*pow(as( startscale*DSH()->renFac() )/SM().alphaS(),currentME()->orderInAlphaS())/ww2; }else if ( theShowerExpansionWeights == 4 ){ expansionweight *= w1+w3+w2*pow(as( startscale*DSH()->renFac() )/SM().alphaS(),currentME()->orderInAlphaS())/ww2; }else assert(false && theShowerExpansionWeights); // [ DEBUG ] if ( currentNode()->legsize() == 5 && Debug::level > 2 ) debugVirt(weight,w1,w2,w3,matrixElement,ww1,ww2,ww3,productionNode,bornWeight); // return with correction that ME was calculated with fixed alpha_s return weight* as( startscale*DSH()->renFac() )/ SM().alphaS()* ( matrixElement+expansionweight ); } CrossSection Merger::MergingDSigDRRealStandard(){ if ( currentNode()->children().empty() ) { throw Exception() << "Real emission contribution without underlying born." << "These are finite contibutions already handled in LO merging." << Exception::abortnow; } // check for IR Safe Cutoff if( !currentNode()->allAbove( theIRSafePT ) )return ZERO; auto inOutPair = currentNode()->getInOut(); NodePtr randomChild = currentNode()->randomChild(); bool meRegion =matrixElementRegion( inOutPair.first , inOutPair.second , randomChild->pT() , theMergePt ); if ( meRegion )return MergingDSigDRRealAllAbove( ); if ( UseRandom::rndbool() ) return 2.*MergingDSigDRRealBelowSubReal( ); return 2.*MergingDSigDRRealBelowSubInt( ); } CrossSection Merger::MergingDSigDRRealAllAbove( ){ //If all dipoles pts are above , we cluster to this dipole. NodePtr CLNode = currentNode()->randomChild(); // Check if phase space poing is in ME region--> else rm PSP if ( !CLNode->children().empty() ) { auto inOutPair = CLNode->getInOut(); NodePtr randomChild = CLNode->randomChild(); if( !matrixElementRegion( inOutPair.first , inOutPair.second , randomChild->pT() , theMergePt ) )return ZERO; } // first find the history for the acctual Node NodePtr productionNode = currentNode()-> getHistory( true , DSH()->hardScaleFactor() ); // If CLNode is not part of the history , dont calculate the Real contribution // else multiply the real contribution with N ( number of children ). // this returns the sudakov suppression according to // the clustering of the born parts. bool inhist = CLNode->isInHistoryOf( productionNode ); if(productionNode== currentNode())assert(!inhist); // get the history for the clustered Node. productionNode = CLNode-> getHistory( false , DSH()->hardScaleFactor() ); // decide if to cluster weight = decideClustering(productionNode,CLNode,projected); // Check for cuts on the production process. if ( !productionNode->xcomb()->willPassCuts() )return ZERO; // calculate the staring scale Energy startscale = CKKW_StartScale( productionNode ); // fill history with caluclation of sudakov supression fillHistory( startscale , productionNode , CLNode ); // fill the projector -> return the scale of the last splitting currentNode()->runningPt( fillProjector( projected ? 2 : 1 ) ); // the weight has three components to get shower history weight weight *= history.back().weight*alphaReweight(true)*pdfReweight(); if( weight == 0. )return ZERO; // The inhist flag produces the correct cluster density. CrossSection me = ( inhist?TreedSigDR( startscale ):ZERO ); // calculate the dipole CrossSection dip = CLNode->calcDip( startscale* currentME()->renFac() ); CrossSection res = weight*as( startscale*DSH()->renFac() )/SM().alphaS()* currentNode()->children().size()* ( me - dip ); // [ DEBUG ] if ( currentNode()->legsize() == 6&&Debug::level > 2 ) debugReal("RAA",weight,me,dip); return res; } CrossSection Merger::MergingDSigDRRealBelowSubReal( ){ // Choose a random child to produce history from. NodePtr HistNode = currentNode()->randomChild(); // Check that this subleading point is in ME region. if ( !HistNode->children().empty() ) { auto inOutPair = HistNode->getInOut(); NodePtr randomChild = HistNode->randomChild(); // Here we make sure that clustering and splitting are invertible if( !matrixElementRegion( inOutPair.first , inOutPair.second , randomChild->pT() , theMergePt ) )return ZERO; } // As the HistNode is now in ME region, we can cluster according to LO merging. // In this clustering we do not require a orering for the last step to the currentNode. const NodePtr productionNode = HistNode-> getHistory( false , DSH()->hardScaleFactor() ); // If the real emission contribution should be unitarised, we decide here if we cluster. // This applies to NLO corrections for the first emission w.r.t. the production process the first time. weight = decideClustering(productionNode,HistNode,projected); // The production node needs to fulfill the cut criterion of the production process. if ( !productionNode->xcomb()->willPassCuts() && !currentNode()->xcomb()->willPassCuts() )return ZERO; // Calculate the starting scale w.r.t. the production process. Energy startscale = CKKW_StartScale( productionNode ); // If the production process does not fullfill the cut criterion use the real emission point (DEBUG) if (!productionNode->xcomb()->willPassCuts()) startscale = CKKW_StartScale( currentNode() ); // DEBUG trial //currentNode()->xcomb()->lastProjector( productionNode->xcomb()); // Calculate the sudakov weights starting from the production node to the histNode fillHistory( startscale , productionNode , HistNode ); // Set the running Pt of the process as it is used in the vetoed parton shower. currentNode()->runningPt( fillProjector( projected ? 1 : 0 ) ); currentNode()->runningPt(max(HistNode->pT(),theMergePt)); // Calculate the alpha_S ratios and pdf ratios. weight *= history.back().weight*alphaReweight(true)*pdfReweight(); if( weight == 0. )return ZERO; // Start calculation of subtraction contribution. CrossSection sumPS = ZERO; // Iterate over all subtraction contributions. for( auto const & child : currentNode()->children() ){ if ( child->allAbove( mergePt() ) && child->xcomb()->willPassCuts() ){ Energy relevantScale=child->children().empty()?CKKW_StartScale( child ):child->maxChildPt(); if( ( child )->pT()>mergePt()/theRealSubtractionRatio ){ if( child ->pT()inShowerPS(relevantScale))){ //DEBUG: CKKW_StartScale( child);???? sumPS += child->calcPs( startscale* currentME()->renFac() ); } }else{ if( child ->pT()calcDip( startscale* currentME()->renFac() ); } } } } CrossSection me = ZERO; if(currentNode()->xcomb()->willPassCuts()){ me = TreedSigDR( startscale ); } // [ DEBUG ] if ( currentNode()->legsize() == 6&&Debug::level > 2 ) debugReal("RBSR",weight,me,sumPS); //Here we subtract the PS ( and below the dynamical cutoff the Dip ) return weight*as( startscale*DSH()->renFac() )/SM().alphaS()* ( me-sumPS ); } CrossSection Merger::MergingDSigDRRealBelowSubInt( ){ if( currentNode()->children().empty() )return ZERO; NodePtr CLNode = currentNode()->randomChild(); if( CLNode->pT()children().empty() ) { auto inOutPair = CLNode->getInOut( ); NodePtr randomChild = CLNode->randomChild(); // Here we make sure that clustering and splitting are invertible if( !matrixElementRegion( inOutPair.first , inOutPair.second , randomChild->pT() , theMergePt ) )return ZERO; } const NodePtr productionNode = CLNode-> getHistory( false , DSH()->hardScaleFactor() ); weight = decideClustering(productionNode,CLNode,projected); if ( !CLNode->allAbove( mergePt() ) )return ZERO; if ( !productionNode->xcomb()->willPassCuts() )return ZERO; Energy startscale = CKKW_StartScale( productionNode ); fillHistory( startscale , productionNode , CLNode ); currentNode()->runningPt( fillProjector( projected ? 2 : 1 ) ); weight *= history.back().weight*alphaReweight(true)*pdfReweight(); if( weight == 0. )return ZERO; pair DipAndPs = CLNode->calcDipandPS( startscale* currentME()->renFac() ); // [ DEBUG ] if ( currentNode()->legsize() == 6&&Debug::level > 2 ) debugReal("RBSI",weight,DipAndPs.second,DipAndPs.first); Energy relevantScale=CLNode->children().empty()?CKKW_StartScale( CLNode ):CLNode->maxChildPt(); bool calcPScontribution=CLNode->pT()inShowerPS(relevantScale)); //Here we add the PS and subtrac the Dip ( only above the dynamical cutoff ) return weight*as( startscale*DSH()->renFac() )/SM().alphaS()* currentNode()->children().size()*( (calcPScontribution?DipAndPs.second:ZERO)-DipAndPs.first ); } CrossSection Merger::MergingDSigDRBornGamma( ){ double weightCL = 0.; weight = 1.; if ( !currentNode()->children().empty() ) { auto const inOutPair = currentNode()->getInOut(); // Here we make sure that clustering and splitting are invertible. NodePtr randomChild = currentNode()->randomChild(); // Check if point is part of the ME region. if( !matrixElementRegion( inOutPair.first , inOutPair.second , randomChild->pT() , theMergePt ) )weight *= 0.; } const NodePtr productionNode = currentNode()->getHistory( true , DSH()->hardScaleFactor() ); NodePtr CLNode; NodePtr BornCL; if( !currentNode()->children().empty() ){ if ( UseRandom::rndbool() ){ CLNode = currentNode()->randomChild(); bool inhist = CLNode->isInHistoryOf( productionNode ); weight *= inhist?( -2.*int( currentNode()->children().size() ) ):0.; projected = true; weightCL = 2.*int( currentNode()->children().size() ); BornCL = CLNode-> getHistory( false , DSH()->hardScaleFactor() ); }else{ weight = 2.; projected = false; } }else{ weight = 1.; projected = false; } if ( treefactory()->onlymulti() != -1&& treefactory()->onlymulti() != int( currentNode()->legsize()-(projected ? 1 : 0) ) ) return ZERO; if( !currentNode()->allAbove( mergePt()*(1.-1e-6) ) )weight = 0.; if( CLNode&&!CLNode->allAbove( mergePt()*(1.-1e-6) ) )weightCL = 0.; if ( !productionNode->xcomb()->willPassCuts() ){ return ZERO; } CrossSection res = ZERO; bool maxMulti = currentNode()->legsize() == int( maxLegsLO() ); if( weight != 0. ){ Energy startscale = CKKW_StartScale( productionNode ); fillHistory( startscale , productionNode , currentNode() ); currentNode()->runningPt( fillProjector( (projected ? 1 : 0) ) ); weight *= history.back().weight*alphaReweight()*pdfReweight(); if( weight == 0.&&weightCL == 0. )return ZERO; res += weight*TreedSigDR( startscale , ( !maxMulti&&!projected )?theGamma:1. ); } if( CLNode&&theGamma != 1. ){ Energy startscale = CKKW_StartScale( BornCL ); fillHistory( startscale , BornCL , CLNode ); currentNode()->runningPt( fillProjector( projected ? 1 : 0 ) ); weightCL *= history.back().weight*alphaReweight()*pdfReweight(); CrossSection diff = ZERO; currentME()->factory()->setAlphaParameter( 1. ); diff -= weightCL*CLNode->dipole()->dSigHatDR( sqr( startscale* currentME()->renFac() ) ); currentME()->factory()->setAlphaParameter( theGamma ); string alp = ( CLNode->dipole()->aboveAlpha()?"Above":"Below" ); diff += weightCL*CLNode->dipole()->dSigHatDR( sqr( startscale* currentME()->renFac() ) ); currentME()->factory()->setAlphaParameter( 1. ); res += diff; } return res; } CrossSection Merger::TreedSigDR( Energy startscale , double diffAlpha ){ currentME()->setScale( sqr( startscale ) , sqr( startscale ) ); CrossSection res = currentME()->dSigHatDRB(); /*bool useDipolesForME=false; if (useDipolesForME && !currentNode()->children().empty()){ res=ZERO; for (auto const & child : currentNode()->children() ) res-=child->dipole()->dSigHatDR(sqr( startscale )); } */ if ( projected && emitDipoleMEDiff ) { CrossSection resDip=ZERO; for (auto const & child : currentNode()->children() ) resDip-=child->dipole()->dSigHatDR(sqr( startscale )); setEmissionProbability(1.-min(resDip/res,res/resDip)); }else{ setEmissionProbability(0.); } if ( diffAlpha != 1. ) { res += currentME()->dSigHatDRAlphaDiff( diffAlpha ); } if( std::isnan( double( res/nanobarn ) ) ){ generator()->logWarning(Exception() << "Merger: TreedSigDR is nan" << Exception::warning); res = ZERO;}; return res; } CrossSection Merger::LoopdSigDR( Energy startscale ){ currentME()->setScale( sqr( startscale ) , sqr( startscale ) ); currentME()->doOneLoopNoBorn(); CrossSection res = currentME()->dSigHatDRV()+ currentME()->dSigHatDRI(); currentME()->noOneLoopNoBorn(); return res; } Energy Merger::fillProjector( int pjs ){ // in the shower handler the scale is multiplied // by DSH()->hardScaleFactor() so here we need // to devide by the factor. double xiQSh = history.begin()->node->legsize() == N0()?DSH()->hardScaleFactor():1.; if( pjs == 0 ){ return ( history.size() == 1?1.:( 1./xiQSh ) )*history.back().scale; } for( auto const & hs : history ) if ( isProjectorStage( hs.node , pjs )&&pjs != 0 ){ currentNode()->xcomb()->lastProjector( hs.node->xcomb() ); return ( hs.node == history[0].node?1.:( 1./xiQSh ) )*hs.scale; } throw Exception() << "Could not fill projector." << Exception::abortnow; return ZERO; } double Merger::pdfReweight(){ // TODO factorization scale inside double res = 1.; // consider both sides. for( int side : {0 , 1} ){ // The side scale defines the scale that the leg is changig thou the history. // We start reweighting at the seed process. // We only need to calculate the pdf if the emission whould change the leg, // otherwise the leg remains the same. // If no emission is prduced from this leg the pdf ratios from this leg are always 1. Energy sidescale=history[0].scale*( history[0].node->legsize() == N0() ? currentME()->facFac(): DSH()->facFac()); bool sidechanged=false; // only if the incoming parton is coloured. if( history[0].node->xcomb()->mePartonData()[side]->coloured() ){ // go though the history. for ( auto const & hs : history ){ //pdf-ratio only to the last step if ( !hs.node->parent() ) continue; if ( hs.node == history.back().node ) continue; if ( !hs.node->dipole() ){ throw Exception() << "\nMerger: pdfReweight: history step has no dipol. " << Exception::abortnow; return 0.; } // if the emitter is the side the emission changes the momentum fraction. if(!(hs.node->dipole()->bornEmitter()==side|| // II dipoles dont change the momentum fraction of the spectator only FI ( hs.node->dipole()->bornSpectator()==side && hs.node->dipole()->bornEmitter()>1))) continue; const bool fromIsME = false; const bool toIsME = history[0].node == hs.node; res *= pdfratio( hs.node, //numerator sidescale, // denominator DSH()->facFac()*hs.node->pT(), side, fromIsME, toIsME); sidescale= DSH()->facFac()*hs.node->pT(); sidechanged=true; } const bool fromIsME = true; const bool toIsME = !sidechanged && history[0].node->legsize() == N0(); res *= pdfratio( history.back().node, sidescale, history[0].scale * currentME()->facFac(), side, fromIsME, toIsME ); } } if ( std::isnan( res ) ) generator()->logWarning(Exception() << "Merger: pdfReweight is nan." << Exception::warning); return res; } double Merger::cmwAlphaS(Energy q)const{ using Constants::pi; // No cmw-scheme if (theCMWScheme==0) return as( q ); // Linear cmw-scheme else if(theCMWScheme==1){ double als=as( q ); return als * (1.+(3.*(67./18.-1./6.*sqr(pi)) -5./9.*Nf(q))* als/2./pi); } // cmw-scheme as factor in argument. else if(theCMWScheme==2){ double kg=exp(-(67.-3.*sqr(pi)-10/3*Nf(q)) /( 2. *(33.-2.*Nf(q)))); //Note factor 2 since we here dealing with Energy return as(max(kg*q,1_GeV)); }else{ throw Exception() << "This CMW-Scheme is not implemented." << Exception::abortnow; } return -1; } double Merger::alphaReweight(bool nocmw){ double res = 1.; Energy Q_R = ( history[0].node->legsize() == N0()? currentME()->renFac(): DSH()->renFac() )* history[0].scale; using Constants::pi; const auto Q_qed=history[0].node->nodeME()->factory()->scaleChoice()->renormalizationScaleQED(); const auto Oew=history[0].node->nodeME()->orderInAlphaEW(); const auto Oqcd=history[0].node->nodeME()->orderInAlphaS(); if (!history[0].node->children().empty()) { assert(Oqcd!=0); } res *= pow( SM().alphaEMME( Q_qed )/ SM().alphaEMMZ() , Oew ); res *= pow( (nocmw?as(Q_R):cmwAlphaS(Q_R)) / SM().alphaS() , Oqcd ); for ( auto const & hs : history ) if ( hs.node!= history.back().node ){ Energy q_i = DSH()->renFac()* hs.node->pT(); res *= cmwAlphaS(q_i) / SM().alphaS(); } if ( std::isnan( res ) ) generator()->logWarning(Exception() << "Merger: alphaReweight is nan. "<< Exception::warning); return res; } void Merger::fillHistory( Energy scale , NodePtr begin , NodePtr endNode ){ history.clear(); double sudakov0_n = 1.; history.push_back( {begin , sudakov0_n , scale} ); double xiQSh = history.begin()->node->legsize() == N0()? DSH()->hardScaleFactor():1.; scale *= xiQSh; if ( begin->parent()||!isUnitarized ) { while ( begin->parent() && ( begin != endNode ) ) { if ( !dosudakov( begin , scale , begin->pT() , sudakov0_n ) ){ history.push_back( { begin->parent() , 0. , scale } ); } if ( std::isnan( sudakov0_n ) ) generator()->logWarning(Exception() << "Merger: sudakov"<pT()/GeV<<"0_n is nan. " << Exception::warning); scale = begin->pT(); history.push_back( { begin->parent() , sudakov0_n , begin->pT() } ); begin = begin->parent(); } Energy notunirunning = scale; if ( !isUnitarized&&N()+N0() > int( currentNode()->legsize() ) ) { if ( !dosudakov( begin , notunirunning , mergePt() , sudakov0_n ) ){ history.back().weight = 0.; }else{ history.back().weight = sudakov0_n; } } } if( history.size() == 1 )scale /= DSH()->hardScaleFactor(); } double Merger::sumPdfReweightExpansion()const{ double res = 0.; Energy beam1Scale = history[0].scale* ( history[0].node->legsize() == N0()? currentME()->facFac(): DSH()->facFac() ); Energy beam2Scale = history[0].scale* ( history[0].node->legsize() == N0()? currentME()->facFac(): DSH()->facFac() ); for ( auto const & hs : history ){ //pdf expansion only to the last step if( !hs.node->parent() )continue; if( hs.node->xcomb()->mePartonData()[0]->coloured()&& hs.node->nodeME()->lastX1()>0.99 )return 0.; if( hs.node->xcomb()->mePartonData()[1]->coloured()&& hs.node->nodeME()->lastX2()>0.99 )return 0.; if( hs.node->nodeME()->lastX1()<0.00001 )return 0.; if( hs.node->nodeME()->lastX2()<0.00001 )return 0.; if ( hs.node->dipole()->bornEmitter() == 0 ){ res += pdfExpansion( hs.node , 0 , beam1Scale , ( hs.node->pT() ) , hs.node->nodeME()->lastX1() , Nf( history[0].scale ) , history[0].scale ); beam1Scale = ( hs.node->pT() )*DSH()->facFac(); } else if ( hs.node->dipole()->bornEmitter() == 1 ){ res += pdfExpansion( hs.node , 1 , beam2Scale , ( hs.node->pT() ) , hs.node->nodeME()->lastX2() , Nf( history[0].scale ) , history[0].scale ); beam2Scale = ( hs.node->pT() )*DSH()->facFac(); } // if we're here we know hs.node->dipole()->bornEmitter() > 1 // works only in collinear scheme else if ( hs.node->dipole()->bornSpectator() == 0 ){ res += pdfExpansion( hs.node , 0 , beam1Scale , ( hs.node->pT() ) , hs.node->nodeME()->lastX1() , Nf( history[0].scale ) , history[0].scale ); beam1Scale = ( hs.node->pT() )*DSH()->facFac(); } else if ( hs.node->dipole()->bornSpectator() == 1 ){ res += pdfExpansion( hs.node , 1 , beam2Scale , ( hs.node->pT() ) , hs.node->nodeME()->lastX2() , Nf( history[0].scale ) , history[0].scale ); beam2Scale = ( hs.node->pT() )*DSH()->facFac(); } } if ( currentNode()->xcomb()->mePartonData()[0]->coloured() ){ res += pdfExpansion( history.back().node , 0 , beam1Scale , history[0].scale* currentME()->facFac() , ( history.back() ).node->nodeME()->lastX1() , Nf( history[0].scale ) , history[0].scale ); } if ( currentNode()->xcomb()->mePartonData()[1]->coloured() ) { res += pdfExpansion( history.back().node , 1 , beam2Scale , history[0].scale* currentME()->facFac() , ( history.back() ).node->nodeME()->lastX2() , Nf( history[0].scale ) , history[0].scale ); } return res; } #include "Herwig/MatrixElement/Matchbox/Phasespace/RandomHelpers.h" double Merger::pdfExpansion( NodePtr node , int side , Energy running , Energy next , double x , int nlp , Energy fixedScale ) const { tcPDPtr particle , parton; tcPDFPtr pdf; if ( side == 0 ) { particle = node->nodeME()->lastParticles().first->dataPtr(); parton = node->nodeME()->lastPartons().first->dataPtr(); pdf = node->xcomb()->partonBins().first->pdf(); }else{ assert( side == 1 ); particle = node->nodeME()->lastParticles().second->dataPtr(); parton = node->nodeME()->lastPartons().second->dataPtr(); pdf = node->xcomb()->partonBins().second->pdf(); } //copied from PKOperator double res = 0.; int number = 10; for ( int nr = 0;nr zw = generate( ( piecewise() , flat( 0.0 , x ) , match( inverse( 0.0 , x , 1.0 ) + inverse( 1.0+eps , x , 1.0 ) ) ) , r ); double z = zw.first; double mapz = zw.second; double PDFxparton = pdf->xfx( particle , parton , sqr( fixedScale ) , x )/x; - double CA = SM().Nc(); - double CF = ( SM().Nc()*SM().Nc()-1.0 )/( 2.*SM().Nc() ); + static double CA = SM().Nc(); + static double CF = ( SM().Nc()*SM().Nc()-1.0 )/( 2.*SM().Nc() ); if ( abs( parton->id() ) < 7 ) { double PDFxByzgluon = pdf->xfx( particle , getParticleData( ParticleID::g ) , sqr( fixedScale ) , x/z )*z/x; double PDFxByzparton = pdf->xfx( particle , parton , sqr( fixedScale ) , x/z )*z/x; assert( abs( parton->id() ) < 7 ); restmp += CF*( 3./2.+2.*log( 1.-x ) ) * PDFxparton; if ( z > x ) { restmp += 0.5 * ( sqr( z ) + sqr( 1.-z ) ) * PDFxByzgluon / z; restmp += CF*2.*( PDFxByzparton - z*PDFxparton )/( z*( 1.-z ) ); restmp -= CF*PDFxByzparton * ( 1.+z )/z; } }else{ assert( parton->id() == ParticleID::g ); double PDFxByzgluon = pdf->xfx( particle , getParticleData( ParticleID::g ) , sqr( fixedScale ) , x/z )*z/x; // Pqg if ( z > x ){ double factor = CF * ( 1. + sqr( 1.-z ) ) / sqr( z ); for ( int f = -nlp; f <= nlp; ++f ) { if ( f == 0 ) continue; restmp += pdf->xfx( particle , getParticleData( f ) , sqr( fixedScale ) , x/z )*z/x*factor; } } // Pgg restmp += ( ( 11./6. ) * CA - ( 1./3. )*Nf( history[0].scale ) + 2.*CA*log( 1.-x ) ) *PDFxparton; if ( z > x ) { restmp += 2. * CA * ( PDFxByzgluon - z*PDFxparton ) / ( z*( 1.-z ) ); restmp += 2.* CA *( ( 1.-z )/z - 1. + z*( 1.-z ) ) * PDFxByzgluon / z; } } if ( PDFxparton<1e-8 ) restmp = 0.; else res += 1*restmp*log( sqr( running/next ) )/PDFxparton*mapz; } return res/number; } double Merger::sumAlphaSReweightExpansion()const{ double res = 0.; const auto Oqcd=history[0].node->nodeME()->orderInAlphaS(); res += alphasExpansion( history[0].scale* DSH()->renFac() , history[0].scale* currentME()->renFac() )* Oqcd; // dsig is calculated with fixed alpha_s for ( auto const & hs : history ){ //expansion only to the last step if( !hs.node->parent() )continue; res += alphasExpansion( hs.node->pT()*DSH()->renFac() ,currentME()->renFac()*history[0].scale ); } return res; } double Merger::sumFillHistoryExpansion(){ double res = 0.; double xiQSh = history[0].node->legsize() == N0()?DSH()->hardScaleFactor():1.; for ( auto const & hs : history ){ if( !hs.node->parent() )continue; doHistExpansion( hs.node , ( hs.node == history[0].node?xiQSh:1. )*hs.scale , hs.node->pT() , history[0].scale , res ); } return res; } MergingFactoryPtr Merger::treefactory()const{return theTreeFactory;} void Merger::doinit(){ if ( !DSH()->hardScaleIsMuF() ) { throw Exception() << "Merger: Merging is currently only sensible " << "if we are using the hardScale as MuF." << Exception::abortnow; } + DSH()->init(); + + if ( !( DSH()->showerPhaseSpaceOption() == 0 || + DSH()->showerPhaseSpaceOption() == 1) ){ + throw InitException() << "Merger::doinit(): Choice of shower phase space cannot be handled by the merging"; + } } namespace{ void setXCombScales(StdXCombPtr xc,Energy2 scale){ xc->lastShowerScale ( scale ); xc->partonBinInstances().first->scale ( scale ); xc->partonBinInstances().second->scale ( scale ); } } CrossSection Merger::MergingDSigDR() { history.clear(); assert(currentNode()==theFirstNodeMap[ currentME()]); if(DSH()->doesSplitHardProcess()){ throw Exception() << "Merger: The splithardprocess option is currently not supported." << Exception::abortnow; } //get the PDF's (from ShowerHandler.cc) if (!DSH()->getPDFA()||!DSH()->firstPDF().particle()){ tSubProPtr sub = currentNode()->xcomb()->construct(); const auto pb=currentNode()->xcomb()->partonBins(); tcPDFPtr first = DSH()->getPDFA() ? tcPDFPtr(DSH()->getPDFA()) : DSH()->firstPDF().pdf(); tcPDFPtr second = DSH()->getPDFB() ? tcPDFPtr(DSH()->getPDFB()) : DSH()->secondPDF().pdf(); DSH()->resetPDFs( {first,second },pb ); } DSH()->eventHandler( generator()->eventHandler() ); CrossSection res = ZERO; if( currentNode()->subtractedReal() ){ res = MergingDSigDRRealStandard(); theCurrentMaxLegs = maxLegsNLO(); }else if( currentNode()->virtualContribution() ){ res = MergingDSigDRVirtualStandard(); theCurrentMaxLegs = maxLegsNLO(); }else if( theGamma!= 1. ){ res = MergingDSigDRBornGamma(); theCurrentMaxLegs = maxLegsLO(); }else{ res = MergingDSigDRBornStandard(); theCurrentMaxLegs = maxLegsLO(); } auto lxc= currentME()->lastXCombPtr(); setXCombScales(lxc,sqr( currentNode()->runningPt())); auto lp= currentME()->lastXCombPtr()->lastProjector(); if( lp ) setXCombScales( lp, sqr( currentNode()->runningPt())); if ( res == ZERO ){ history.clear(); return ZERO; } cleanup( currentNode() ); lxc->subProcess( SubProPtr() ); history.clear(); if( !std::isfinite( double( res/nanobarn ) ) ){ generator()->logWarning(Exception() << "Merger weight is " << res/nanobarn<< " -> setting to 0" << Exception::warning); return ZERO; } return res; } #include "Herwig/PDF/HwRemDecayer.h" void Merger::CKKW_PrepareSudakov( NodePtr node , Energy running ){ tSubProPtr sub = node->xcomb()->construct(); const auto pb=node->xcomb()->partonBins(); DSH()->setCurrentHandler(); DSH()->currentHandler()->generator()->currentEventHandler(currentNode()->xcomb()->eventHandlerPtr() ); DSH()->currentHandler()->remnantDecayer()->setHadronContent( currentNode()->xcomb()->lastParticles() ); DSH()->eventRecord().clear(); DSH()->eventRecord().slimprepare( sub , dynamic_ptr_cast( node->xcomb() ) , DSH()->pdfs() , currentNode()->xcomb()->lastParticles(), DSH()->offShellPartons() ); DSH()->hardScales( sqr( running ) ); } Energy Merger::CKKW_StartScale( NodePtr node ) const { Energy res = generator()->maximumCMEnergy(); const int N=node->legsize(); const auto & data=node->nodeME()->mePartonData(); const auto & momenta=node->nodeME()->lastMEMomenta(); if( !node->children().empty() ){ for ( int i = 0; icoloured() )continue; for ( int j = 2; jcoloured() )continue; for ( int k = 0; kcoloured() || i == k || j == k )continue; if(i<2){ if(k<2) { res = min( res , IILTK->lastPt( momenta[i] , momenta[j] , momenta[k] )); } else { res = min( res , (data[k]->mass()+data[j]->mass()+data[i]->mass()>ZERO)? IFMTK->lastPt( momenta[i] , momenta[j] , momenta[k] ): IFLTK->lastPt( momenta[i] , momenta[j] , momenta[k] )); } }else{ if(k<2) { res = min( res , (data[k]->mass()+data[j]->mass()+data[i]->mass()>ZERO)? FIMTK->lastPt( momenta[i] , momenta[j] , momenta[k] ): FILTK->lastPt( momenta[i] , momenta[j] , momenta[k] )); } else { res = min( res , (data[k]->mass()+data[j]->mass()+data[i]->mass()>ZERO)? FFMTK->lastPt( momenta[i] , momenta[j] , momenta[k] ): FFLTK->lastPt( momenta[i] , momenta[j] , momenta[k] )); } } } } } }else{ node->nodeME()->factory()->scaleChoice()->setXComb( node->xcomb() ); res = sqrt( node->nodeME()->factory()->scaleChoice()->renormalizationScale() ); } node->nodeME()->factory()->scaleChoice()->setXComb( node->xcomb() ); res = max( res , sqrt( node->nodeME()->factory()->scaleChoice()->renormalizationScale() ) ); return res; } double Merger::alphasExpansion( Energy next , Energy fixedScale ) const { double betaZero = ( 11./6. )*SM().Nc() - ( 1./3. )*Nf( history[0].scale ); double K=3.*( 67./18.-1./6.*sqr(Constants::pi) ) -5./9.*Nf( history[0].scale); return ( betaZero*log( sqr( fixedScale/next ) ) )+( theCMWScheme>0?K:0. ); } double Merger::pdfratio( NodePtr node , Energy numerator_scale , Energy denominator_scale , int side , bool fromIsME, bool toIsME ){ StdXCombPtr bXc = node->xcomb(); if( !bXc->mePartonData()[side]->coloured() ) throw Exception() << "Merger: pdf-ratio required for non-coloured particle." << Exception::abortnow; double from = 1.; double to = 1.; if ( side == 0 ){ if ( denominator_scale == numerator_scale && fromIsME==toIsME ) { return 1.; } if (fromIsME) { from = node->nodeME()->pdf1( sqr( denominator_scale ) ); }else{ from = DSH()->firstPDF().xfx(node->xcomb()->lastPartons().first->dataPtr(), sqr( denominator_scale ), node->xcomb()->lastX1())/node->xcomb()->lastX1(); } if (toIsME) { to = node->nodeME()->pdf1( sqr( numerator_scale ) ); }else{ to = DSH()->firstPDF().xfx(node->xcomb()->lastPartons().first->dataPtr(), sqr( numerator_scale ), node->xcomb()->lastX1())/node->xcomb()->lastX1(); } if ( ( to < 1e-8||from < 1e-8 )&&( to/from>10000000. ) ){ generator()->logWarning(Exception() << "Merger: pdfratio to = " << to << " from = " << from << Exception::warning); return 0.; } } else{ if ( denominator_scale == numerator_scale && fromIsME==toIsME ) { return 1.; } if (fromIsME) { from = node->nodeME()->pdf2( sqr( denominator_scale ) ); }else{ from =DSH()->secondPDF().xfx(node->xcomb()->lastPartons().second->dataPtr(), sqr( denominator_scale ), node->xcomb()->lastX2())/node->xcomb()->lastX2(); } if (toIsME) { to = node->nodeME()->pdf2( sqr( numerator_scale ) ); }else{ to = DSH()->secondPDF().xfx(node->xcomb()->lastPartons().second->dataPtr(), sqr( numerator_scale ), node->xcomb()->lastX2())/node->xcomb()->lastX2(); } if ( ( to < 1e-8||from < 1e-8 )&&( to/from>10000000. ) ){ generator()->logWarning(Exception() << "Merger: pdfratio to = " << to << " from = " << from << Exception::warning); return 0.;} } return to/from; } bool Merger::dosudakov( NodePtr node , Energy running , Energy next , double& sudakov0_n ) { CKKW_PrepareSudakov( node , running ); for( DipoleChain const & chain : DSH()->eventRecord().chains() ){ for( Dipole const & dip : chain.dipoles() ){ sudakov0_n *= singlesudakov( dip , next , running , { true , false } ); sudakov0_n *= singlesudakov( dip , next , running , { false , true } ); if ( sudakov0_n == 0.0 ){ cleanup( node ); return false; } } } cleanup( node ); return true; } bool Merger::doHistExpansion( NodePtr node , Energy running , Energy next , Energy fixedScale , double& histExpansion ) { CKKW_PrepareSudakov( node , running ); for( DipoleChain const & chain : DSH()->eventRecord().chains() ){ for( Dipole const & dip : chain.dipoles() ){ histExpansion += singleHistExpansion( dip , next , running , fixedScale , { true , false } );; histExpansion += singleHistExpansion( dip , next , running , fixedScale , { false , true } ); } } cleanup( node ); return true; } bool Merger::isProjectorStage( NodePtr node , int pjs )const{ return ( pjs == int( ( currentNode()->legsize() - node->legsize() ) ) ); } void Merger::cleanup( NodePtr node ) { DSH()->eventRecord().clear(); if( !node->xcomb()->subProcess() )return; ParticleVector vecfirst = node->xcomb()->subProcess()->incoming().first->children(); for( auto const & particle : vecfirst ) node->xcomb()->subProcess()->incoming().first->abandonChild( particle ); ParticleVector vecsecond = node->xcomb()->subProcess()->incoming().second->children(); for( auto const & particle : vecsecond ) node->xcomb()->subProcess()->incoming().second->abandonChild( particle ); node->xcomb()->subProcess( SubProPtr() ); } double Merger::singlesudakov( Dipole dip , Energy next , Energy running , pair conf ){ double res = 1.; tPPtr emitter = dip.emitter( conf ); tPPtr spectator = dip.spectator( conf ); DipoleSplittingInfo candidate( dip.index( conf ) , conf , dip.emitterX( conf ) , dip.spectatorX( conf ) , emitter , spectator ); if ( DSH()->generators().find( candidate.index() ) == DSH()->generators().end() ) DSH()->getGenerators( candidate.index() ); auto const & gens = DSH()->generators().equal_range( candidate.index() ); for ( auto gen = gens.first; gen != gens.second; ++gen ) { if ( !( gen->first == candidate.index() ) ) continue; Energy dScale = gen->second->splittingKinematics()->dipoleScale( emitter->momentum() , spectator->momentum() ); candidate.scale( dScale ); candidate.continuesEvolving(); - Energy ptMax = gen->second->splittingKinematics()->ptMax( candidate.scale() , candidate.emitterX() , candidate.spectatorX() , - candidate.index() , *gen->second->splittingKernel() ); + + Energy ptMax = gen->second->splittingKinematics()->ptMax( + candidate.scale() , + candidate.emitterX() , + candidate.spectatorX() , + candidate , + *gen->second->splittingKernel() ); candidate.hardPt( min( running , ptMax ) ); if ( candidate.hardPt()>next ){ res *= gen->second->sudakov( candidate , next ); } } return res; } double Merger::singleHistExpansion( Dipole dip , Energy next , Energy running , Energy fixedScale , pair conf ){ double res = 0.; tPPtr emitter = dip.emitter( conf ); tPPtr spectator = dip.spectator( conf ); DipoleSplittingInfo candidate( dip.index( conf ) , conf , dip.emitterX( conf ) , dip.spectatorX( conf ) , emitter , spectator ); if ( DSH()->generators().find( candidate.index() ) == DSH()->generators().end() ) DSH()->getGenerators( candidate.index() ); auto const & gens = DSH()->generators().equal_range( candidate.index() ); for ( auto gen = gens.first; gen != gens.second; ++gen ) { if ( !( gen->first == candidate.index() ) ) continue; Energy dScale = gen->second->splittingKinematics()->dipoleScale( emitter->momentum() , spectator->momentum() ); candidate.scale( dScale ); candidate.continuesEvolving(); Energy ptMax = gen->second-> splittingKinematics()->ptMax( - candidate.scale() , candidate.emitterX() , - candidate.spectatorX() , candidate.index() , + candidate.scale() , + candidate.emitterX() , + candidate.spectatorX() , + candidate , *gen->second->splittingKernel() ); candidate.hardPt( min( running , ptMax ) ); if ( candidate.hardPt()>next ){ res += gen->second->sudakovExpansion( candidate , next , fixedScale ); } } return res; } void Merger::firstNodeMap( MatchboxMEBasePtr a , NodePtr b ){ theFirstNodeMap.insert( { a , b } ); } map Merger::firstNodeMap()const{return theFirstNodeMap;} void Merger::setXComb( tStdXCombPtr xc ){ currentNode()->setXComb( xc ); } void Merger::setKinematics( ){ currentNode()->setKinematics(); } void Merger::clearKinematics( ){ currentNode()->clearKinematics(); } void Merger::flushCaches(){ if (currentNode()&¤tNode()->xcomb()->lastParticles().first) { currentNode()->flushCaches(); } } bool Merger::generateKinematics( const double * r ){ return currentNode()->firstgenerateKinematics( r , ! currentNode()->subtractedReal() ); } bool Merger::matrixElementRegion( PVector incoming , PVector outgoing , Energy winnerScale , Energy cutscale )const{ Energy ptx = Constants::MaxEnergy; bool foundwinnerpt = false; using namespace boost; //FF for( auto const & em : outgoing ){ if ( ! em->coloured() ) continue; for( auto const & emm : outgoing ){ if ( !emm->coloured() ) continue; if ( em == emm ) continue; for( auto const & spe : outgoing ){ if ( !spe->coloured() ) continue; if ( em == spe||emm == spe ) continue; if ( !( em->id() == -emm->id()||emm->id()>6 ) )continue; Energy pt = ZERO; if ( em->momentum().m()<= 10_MeV && emm->momentum().m()<= 10_MeV && spe->momentum().m()<= 10_MeV ) { pt = FFLTK->lastPt( em->momentum() , emm->momentum() , spe->momentum() ); }else{ pt = FFMTK->lastPt( em->momentum() , emm->momentum() , spe->momentum() ); } if ( abs( pt-winnerScale ) < 10_MeV ) { foundwinnerpt = true; } ptx = min( ptx , pt ); } } } //FI for( auto const & spe : incoming ){ if ( ! spe->coloured() ) continue; for( auto const & emm : outgoing ){ if ( ! emm->coloured() ) continue; for( auto const & em : outgoing ){ if ( ! em->coloured() ) continue; if ( em == emm ) continue; if ( !( em->id() == -emm->id() || emm->id()>6 ) )continue; Energy pt = ZERO; if ( em->momentum().m()<= 10_MeV && emm->momentum().m()<= 10_MeV && spe->momentum().m()<= 10_MeV ) { pt = FILTK->lastPt( em->momentum() , emm->momentum() , spe->momentum() ); }else{ pt = FIMTK->lastPt( em->momentum() , emm->momentum() , spe->momentum() ); } if ( abs( pt-winnerScale )<10_MeV ) { foundwinnerpt = true; } if( pt > ZERO ) ptx = min( ptx , pt ); } } } //IF for( auto const & em : incoming ){ if ( ! em->coloured() ) continue; for( auto const & emm : outgoing ){ if ( ! emm->coloured() ) continue; for( auto const & spe : outgoing ){ if ( ! spe->coloured() ) continue; if ( emm == spe ) continue; if ( !( em->id()>6|| em->id() == emm->id() ||emm->id()>6 ) )continue; Energy pt = ZERO; if ( em->momentum().m()<= 10_MeV && emm->momentum().m()<= 10_MeV && spe->momentum().m()<= 10_MeV ) { //massless pt = IFLTK->lastPt( em->momentum() , emm->momentum() , spe->momentum() ); }else{ //massiv pt = IFMTK->lastPt( em->momentum() , emm->momentum() , spe->momentum() ); } if ( abs( pt-winnerScale )< 10_MeV ) { foundwinnerpt = true; } ptx = min( ptx , pt ); } } } //II for( auto const & em : incoming ){ if ( ! em->coloured() ) continue; for( auto const & spe : incoming ){ if ( ! spe->coloured() ) continue; if ( em == spe ) continue; for( auto const & emm : outgoing ){ if ( ! emm->coloured() ) continue; if ( !( em->id()>6||em->id() == emm->id() ||emm->id()>6 ) )continue; Energy pt = IILTK->lastPt( em->momentum() , emm->momentum() , spe->momentum() ); if ( abs( pt-winnerScale )< 10_MeV ) { foundwinnerpt = true; } ptx = min( ptx , pt ); } } } if( !foundwinnerpt ){ generator()->logWarning( Exception() << "Merger: Could not find winner with pt." << "Run with -d3 to get phase space points. " << Exception::warning ); if( Debug::level > 2 ) { generator()->log() << "\nWarning: could not find winner with pt: " << winnerScale/GeV; for( auto const & emm : incoming ){ generator()->log() << "\n" << emm->id() << " " << emm->momentum()/GeV << " " << emm->momentum().m()/GeV << flush; } for( auto const & emm : outgoing ){ generator()->log() <<"\n" << emm->id() << " " << emm->momentum()/GeV << " " << emm->momentum().m()/GeV << flush; } } } return ( ptx>cutscale ) ; } bool Merger::notOnlyMulti() const { return ( treefactory()->onlymulti() != -1&& treefactory()->onlymulti() != int( currentNode()->legsize()-( projected ? 1 : 0 ) ) ); } int Merger::M()const{return theTreeFactory->M();} int Merger::N()const{return theTreeFactory->N();} void Merger::debugVirt(double weight,double w1,double w2,double w3, CrossSection matrixElement,double ww1,double ww2, double ww3, NodePtr node,CrossSection bornWeight)const{ Energy minPT = Constants::MaxEnergy; for( auto const & no :currentNode()->children() )minPT = min( no->pT() , minPT ); generator()->log() << "\nVIRT " << minPT/GeV << " " << weight << " " << w1; generator()->log() << " " << w2; generator()->log() << " " << w3; generator()->log() << " " << ( matrixElement/nanobarn ) << " " << ww1 << " " << ww2 << " " << ww3 << " " << node->pT()/GeV << " " << node->nodeME()->mePartonData()[3]->mass()/GeV << " " << ( bornWeight*SM().alphaS()/( 2.*ThePEG::Constants::pi )/nanobarn ); } void Merger::debugReal(string realstr, double weight, CrossSection me, CrossSection dip)const { Energy minPT = Constants::MaxEnergy; for( auto const & no :currentNode()->children() )minPT = min( no->pT() , minPT ); generator()->log() << "\n"<> theShowerExpansionWeights >> theCMWScheme >> projected >> isUnitarized >> isNLOUnitarized >> - theOpenZBoundaries >> theChooseHistory >> theN0 >> theOnlyN >> weight >> theGamma >> theSmearing >> iunit( theIRSafePT , GeV ) >> iunit( theMergePt , GeV ) >> iunit( theCentralMergePt , GeV ) >> theLargeNBasis >> FFLTK >> FILTK >> IFLTK >> IILTK >> FFMTK >> FIMTK >> IFMTK >> theDipoleShowerHandler >> theTreeFactory >> theFirstNodeMap >> theRealSubtractionRatio >> emitDipoleMEDiff; } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct ( the class and its base class ) , and that the constructor // arguments are correct ( the class name and the name of the dynamically // loadable library where the class implementation can be found ). #include "ThePEG/Utilities/DescribeClass.h" DescribeClass describeHerwigMerger( "Herwig::Merger" , "HwDipoleShower.so" ); //ClassDescription Merger::initMerger; // Definition of the static class description member. #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Switch.h" void Merger::Init() { static ClassDocumentation documentation ( "The Merger class takes care of merging multiple LO & NLO cross sections." ); ////////////////////////////////////////////////// static Switch interfaceShowerExpansionWeights ( "ShowerExpansionWeights" , "Calculate the expansions of the shower history to be NLO accurate, in different schemes." , &Merger::theShowerExpansionWeights , 3 , false , false ); static SwitchOption interfaceShowerExpansionWeightsScheme0 ( interfaceShowerExpansionWeights , "NoWeights" , "Switch off the expansion." , 0 ); static SwitchOption interfaceShowerExpansionWeightsScheme1 ( interfaceShowerExpansionWeights , "FlatAndHistoryReweighted" , "Sum alphaS expansion and weight with same Historyweight as LO." , 1 ); static SwitchOption interfaceShowerExpansionWeightsScheme2 ( interfaceShowerExpansionWeights , "NoAlphaSReweightForSudakovExpansion" , "Switch off the expansion." , 2 ); static SwitchOption interfaceShowerExpansionWeightsScheme3 ( interfaceShowerExpansionWeights , "NoAlphaSReweightForAllExpansions" , "Switch off the expansion." , 3 ); static SwitchOption interfaceShowerExpansionWeightsScheme4 ( interfaceShowerExpansionWeights , "NoAlphaSReweightForAlphaSExpansion" , "Switch off the expansion." , 4 ); - /////////////////////////////////////////////////////////////////////7 - + ///////////////////////////////////////////////////////////////////// static Switch interfacetheCMWScheme ( "CMWScheme" , "Use CMW-Scheme to calculate the alpha_s for the shower expressions." , &Merger::theCMWScheme , 0 , false , false ); static SwitchOption interfacetheCMWSchemeNo (interfacetheCMWScheme, "No", "No CMW-Scheme", 0); static SwitchOption interfacetheCMWSchemeLinear (interfacetheCMWScheme, "Linear", "Linear CMW multiplication: alpha_s(q) -> alpha_s(q)(1+K_g*alpha_s(q)/2pi )", 1); static SwitchOption interfacetheCMWSchemeFactor (interfacetheCMWScheme, "Factor", "Use factor in alpha_s argument: alpha_s(q) -> alpha_s(fac*q) with fac=exp(-(67-3pi^2-10/3*Nf)/(33-2Nf)) ", 2); - static Parameter interfaceMergerScale ( "MergingScale" , "The MergingScale." , &Merger::theCentralMergePt , GeV , 20.0*GeV , 0.0*GeV , 0*GeV , false , false , Interface::lowerlim ); - - static Parameter interfacegamma ( "gamma" , "gamma parameter." , &Merger::theGamma , 1.0 , 0.0 , 0 , false , false , Interface::lowerlim ); interfacegamma.rank(-1); - - static Switch interfaceOpenZBoundariesM - ("OpenZBoundaries", "", - &Merger::theOpenZBoundaries, 0, false, false); - static SwitchOption interfaceOpenZBoundariesMhardScale - (interfaceOpenZBoundariesM, "Hard", "", 0); - static SwitchOption interfaceOpenZBoundariesMfull - (interfaceOpenZBoundariesM, "Full", "", 1); - static SwitchOption interfaceOpenZBoundariesMDipoleScale - (interfaceOpenZBoundariesM, "DipoleScale", "", 2); - - - static Switch interfaceemitDipoleMEDiff ( "emitDipoleMEDiff" , "Allow emissions of the unitarisation contribution with prob. 1-min(B_n/sum Dip_n,sum Dip_n/B_n)" , &Merger::emitDipoleMEDiff , false , false , false ); static SwitchOption interfaceemitDipoleMEDiffYes ( interfaceemitDipoleMEDiff , "Yes" , "" , true ); static SwitchOption interfaceemitDipoleMEDiffNo ( interfaceemitDipoleMEDiff , "No" , "" , false ); interfaceemitDipoleMEDiff.rank(-1); - - - static Parameter interfaceIRSafePT ( "IRSafePT" , "Set the pt for which a matrixelement should be treated as IR-safe." , &Merger::theIRSafePT , GeV , 0.0 * GeV , ZERO , Constants::MaxEnergy , true , false , Interface::limited ); interfaceIRSafePT.setHasDefault( false ); static Parameter interfacemergePtsmearing( "MergingScaleSmearing" , "Set the percentage the merging pt should be smeared." , &Merger::theSmearing , 0. , 0. , 0.0 , 0.5 , true , false , Interface::limited ); static Parameter interfacechooseHistory( "chooseHistory" , "Various ways of choosing the history weights: 0(default):dipole xs, 1:dipole/born, 2:flat, 3: 1/pt_dip" , &Merger::theChooseHistory , 3 , -1 , 0 , false , false , Interface::lowerlim ); static Parameter interfacetheRealSubtractionRatio( "RealSubtractionRatio" , "If the pt of the Dipole divided by the merging scale is lower than the ratio, the dipole is used to subtract the real emission. Otherwise the shower approximation is used, " , &Merger::theRealSubtractionRatio , 0. , 0. , 1. , 10.0 , true , false , Interface::limited ); } diff --git a/Shower/Dipole/Merging/Merger.h b/Shower/Dipole/Merging/Merger.h --- a/Shower/Dipole/Merging/Merger.h +++ b/Shower/Dipole/Merging/Merger.h @@ -1,410 +1,408 @@ /// -*- C++ -*- // /// Merger.h is a part of Herwig - A multi-purpose Monte Carlo event generator /// Copyright (C) 2002-2017 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_Merger_H #define HERWIG_Merger_H // /// This is the declaration of the Merger class. // #include "MergingFactory.fh" #include "Node.fh" #include "ThePEG/Handlers/HandlerBase.h" #include "Herwig/Shower/Dipole/DipoleShowerHandler.h" //#include "Herwig/Shower/Dipole/Base/DipoleSplittingGenerator.h" #include "Herwig/MatrixElement/Matchbox/Base/MergerBase.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/FFLightTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/IFLightTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/FFMassiveTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/IFMassiveTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/FILightTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/IILightTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/FIMassiveTildeKinematics.h" #include "ThePEG/Cuts/JetFinder.h" #include "ThePEG/Cuts/Cuts.h" namespace Herwig { using namespace ThePEG; class Merger; ThePEG_DECLARE_POINTERS(Merger , MergerPtr ); typedef vector NodePtrVec; //definition of a history step struct HistoryStep { /// containing the full information NodePtr node; /// current sudakov weight of the history double weight; /// current scale of the history Energy scale; }; typedef vector< HistoryStep > History; typedef multimap::ptr> GeneratorMap2; /** * \ingroup DipoleShower * \author Johannes Bellm * * \brief Merger handles the Merger ....... //TODO . * * @see \ref MergerInterfaces "The interfaces" * defined for Merger. */ class Merger: public MergerBase { friend class MergingFactory; friend class Node; public: // define the ME region for a particle vector. bool matrixElementRegion(PVector incoming, PVector outgoing, Energy winnerScale = ZERO, Energy cutscale = ZERO)const; /// return the current merging scale, /// gets smeared around the central merging scale in generate kinematics. Energy mergingScale()const{return theMergePt;} /// return the current merging pt (should be unified with mergingScale) Energy mergePt()const {return theMergePt;} /// legsize of highest process with NLO corrections int M()const; /// legsize of the highest LO merged process int N()const; /// legsize of the production process int N0()const{return theN0;} /// cross section of as given by the merging CrossSection MergingDSigDR(); /// ***** virtual functions of the base class ****/// /// set the current xcomb, called from ME void setXComb( tStdXCombPtr ); /// set kinematics, called from ME void setKinematics(); /// clear kinematics, called from ME void clearKinematics(); /// generate kinematics, called from ME bool generateKinematics( const double * ); /// generate kinematics, called from ME void flushCaches(); /// return the current maximum legs, the shower should veto size_t maxLegs() const {return theCurrentMaxLegs;} /// set the current ME void setME(MatchboxMEBasePtr me){ theCurrentME=me; assert(theFirstNodeMap.count(theCurrentME)); theCurrentNode=theFirstNodeMap[theCurrentME]; } /// allow emissions with a given probability.in the ME region double emissionProbability() const{ return theEmissionProbability; } /// set a probability of allowed emission into ME region. void setEmissionProbability(double x){theEmissionProbability=x;} protected: /// the merging factory needs to set the legsize of the production process void N0(int n){ theN0=n;} /// return the large-N basis (TODO: implement check if born ME works with the choice) Ptr::ptr largeNBasis()const{return theLargeNBasis;} /// smear the merging pt void smearMergePt(){ const double factor = 1. + (-1. + 2.*UseRandom::rnd() ) * smear(); theMergePt = factor * centralMergePt(); } /// true if the phase space for initial emissions should not be restricted in z. - int openZBoundaries()const{return theOpenZBoundaries;} + int openZBoundaries()const{return DSH()->showerPhaseSpaceOption();} /// return the current ME MatchboxMEBasePtr currentME() const { return theCurrentME; } /// return the current Node NodePtr currentNode() const { return theCurrentNode; } /// the gamma parameter to subtract dipoles above a alpha parameter /// and subtract the corresponding IPK operator double gamma()const{return theGamma;} private: /// calculate a single sudakov step for a given dipole double singlesudakov(Dipole, Energy, Energy, pair); /// calculate the sudakov supression for a clusternode between /// the current running scale and next scale bool dosudakov(NodePtr Born, Energy running, Energy next, double& sudakov0_n); /// cleanup void cleanup(NodePtr); /// return true if the cluster node has the matching number of /// legs to the current projector stage bool isProjectorStage( NodePtr , int )const; /** * Calculate the staring scale: * if Node is part of the production process, calculate according to the * scale choice object in the merging scale objekt, else * return max(scale as scalechoice , min(Mass(i, j))) */ Energy CKKW_StartScale(NodePtr) const; /// prepare the sudakov calculation void CKKW_PrepareSudakov(NodePtr, Energy); /// number of active flavours as given by the shower double Nf(Energy scale)const{return DSH()->Nf(scale);} /// pointer to the factory MergingFactoryPtr treefactory() const; /// map from ME to first clusternode map firstNodeMap() const ; /// set the current merging pt, smeared in generate kinematics void mergePt(Energy x) {theMergePt = x;} /// return the central merging pt Energy centralMergePt() const {return theCentralMergePt;} private: /// calculate the history weighted born cross section CrossSection MergingDSigDRBornStandard(); /** * calculate the history weighted born cross section * add the difference of IPK with and without alpha parameter * subtract the dipoles above the alpha parameter */ CrossSection MergingDSigDRBornGamma(); /// calculate the history weighted virtual contribution CrossSection MergingDSigDRVirtualStandard(); /** * calculate the history weighted real contribution * splitted into 3 differnt contibutions */ CrossSection MergingDSigDRRealStandard(); /// calculate the history weighted real contribution /// all dipoles above: /// N*(R rnd(i)-Dip_i) history_i U(\phi^n_i) CrossSection MergingDSigDRRealAllAbove(); /// calculate the history weighted real contribution /// not all dipoles above: /// (R - sum PS_i) history_rnd U(\phi^n+1) CrossSection MergingDSigDRRealBelowSubReal(); /// calculate the history weighted real contribution /// not all dipoles above: /// rnd(i)-> N*(PS_i - Dip_i) history_i U(\phi^n_i) CrossSection MergingDSigDRRealBelowSubInt(); /// max legssize the shower should veto for LO size_t maxLegsLO() const {return N0()+N();} /// Calculate the LO partonic cross section. /// if diffalpha != 1, add the difference of IPK(1)-IPK(diffalpha) CrossSection TreedSigDR(Energy startscale, double diffalpha=1.); /// fill the projecting xcomb Energy fillProjector(int); /// fill the history, including calculation of sudakov supression void fillHistory(Energy, NodePtr, NodePtr ); /// calculate the pdf ratio for the given clusternode double pdfratio(NodePtr, Energy, Energy, int, bool fromIsME, bool toIsME); /// return the pdf-ratio reweight for the history double pdfReweight(); /// return the alpha_s reweight for the history double alphaReweight(bool nocmw=false); /// max legssize the shower should veto for NLO size_t maxLegsNLO()const {return N0()+M();} /// calculate the virtual contribution. CrossSection LoopdSigDR(Energy startscale ); /// calculate alpha_s expansion of the pdf-ratios double sumPdfReweightExpansion()const; /// calculate alpha_s expansion of the alpha_s-ratios, including K_g double sumAlphaSReweightExpansion()const; /// calculate alpha_s expansion of the sudakov exponents double sumFillHistoryExpansion(); /// calculate alpha_s expansion of the single step alpha_s-ratio, including K_g double alphasExpansion( Energy next, Energy fixedScale)const; /// calculate alpha_s expansion of the single step pdf-ratio double pdfExpansion(NodePtr, int, Energy, Energy, double, int, Energy)const; /// calculate alpha_s expansion of the single step sudakov exponent bool doHistExpansion(NodePtr Born, Energy running, Energy next, Energy fixedScale, double& HistExpansion); /// calculate alpha_s expansion of the single dipole sudakov exponent double singleHistExpansion(Dipole, Energy, Energy, Energy, pair); //alpha_s as given in the shower double as(Energy q)const{return DSH()->as(q);} // set the pointer to the Mergingfactory. void setFactory(MergingFactoryPtr f){theTreeFactory=f;} // set the pointer to the DipoleShower. void setDipoleShower(DipoleShowerHandlerPtr dsh){theDipoleShowerHandler=dsh;} //return the dipole shower handler DipoleShowerHandlerPtr DSH(){return theDipoleShowerHandler;} //return the const dipole shower handler cDipoleShowerHandlerPtr DSH()const{return theDipoleShowerHandler;} /// insert map from ME to first clusternode void firstNodeMap(MatchboxMEBasePtr, NodePtr); /// history choice: weighted history choice int chooseHistory()const {return theChooseHistory;} /// the smearing factor for the merging scale double smear()const{return theSmearing;} /// return the large-N colour basis void largeNBasis(Ptr::ptr x){theLargeNBasis=x;} /// helper function to check the only multi condition. bool notOnlyMulti()const; /// Calculate the CMW AlphaS double cmwAlphaS(Energy q)const; /// debug output for virtual void debugVirt(double, double, double, double, CrossSection, double, double, double, NodePtr,CrossSection) const; /// debug output for reals void debugReal( string, double, CrossSection, CrossSection) const; private: /// calculate the history expansion unsigned int theShowerExpansionWeights = 2; /// use CMW scheme unsigned int theCMWScheme = 0; /// true if current point should be projected bool projected = true; /// true if LO cross sections should be unitarised bool isUnitarized = true; /// true if NLO contributions should be unitarised bool isNLOUnitarized = true; - /// no z-restricions on initial state emissions in clustering - int theOpenZBoundaries = 0; /// history weight choice int theChooseHistory = 0; /// legsize of production process int theN0 = 0; /// calculate only the N particle contribution int theOnlyN = -1; /// the current maxlegs (either LO or NLO maxlegs) size_t theCurrentMaxLegs = -1; /// current weight and weight of clustered born double weight = 1.0; double weightCB = 1.0; /// subtract the dipole contribution above a given gamma double theGamma = 1.0; /// smearing factor for merging scale double theSmearing = 0.; /** * Allow emissions for the unitarising LO contributions * according to the prob 1-min(B_n/sum Dip_n,Dip_n/B_n) */ bool emitDipoleMEDiff = false; /// The conditional emission probability if emitDipoleMEDiff is true. double theEmissionProbability = 0.; /// cutoff for real emission contribution Energy theIRSafePT = 1_GeV; /// current merging scale Energy theMergePt = 4_GeV; /// central merging scale Energy theCentralMergePt = 4_GeV; /// below mergingscale/theRealSubtractionRatio the dipoles are used to subtract. /// above the shower approximation is in use. double theRealSubtractionRatio=3.; /// current cluster histoy including sudakov weights History history; /// pointer to the large-N basis Ptr::ptr theLargeNBasis; /// current Node NodePtr theCurrentNode; /// current ME MatchboxMEBasePtr theCurrentME; /// Tilde kinematics pointers, only to use lastPt(emitter, emission, spectator) Ptr::ptr FFLTK = new_ptr( FFLightTildeKinematics() ); Ptr::ptr FILTK = new_ptr( FILightTildeKinematics() ); Ptr::ptr IFLTK = new_ptr( IFLightTildeKinematics() ); Ptr::ptr IILTK = new_ptr( IILightTildeKinematics() ); Ptr::ptr FFMTK = new_ptr( FFMassiveTildeKinematics() ); Ptr::ptr FIMTK = new_ptr( FIMassiveTildeKinematics() ); Ptr::ptr IFMTK = new_ptr( IFMassiveTildeKinematics() ); //pointer to the shower handler DipoleShowerHandlerPtr theDipoleShowerHandler; /// pointer to the MergingFactory MergingFactoryPtr theTreeFactory; /// map from ME to first Node map theFirstNodeMap; /// map from ME to highest ME weight so far map theHighMeWeightMap; 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(); //@} 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 assignment operator is private and must never be called. * In fact, it should not even be implemented. */ Merger & operator=(const Merger &) = delete; }; } #endif /* HERWIG_Merger_H */ diff --git a/Shower/Dipole/Merging/MergingFactory.cc b/Shower/Dipole/Merging/MergingFactory.cc --- a/Shower/Dipole/Merging/MergingFactory.cc +++ b/Shower/Dipole/Merging/MergingFactory.cc @@ -1,646 +1,683 @@ // -*- C++ -*- // // MergeboxFactory.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 MergeboxFactory class. // #include "MergingFactory.h" #include "Node.h" #include "ThePEG/Repository/Repository.h" #include "ThePEG/Utilities/ColourOutput.h" using namespace Herwig; using std::ostream_iterator; IBPtr MergingFactory::clone() const { return new_ptr(*this); } IBPtr MergingFactory::fullclone() const { return new_ptr(*this); } void MergingFactory::doinit(){ MatchboxFactory::doinit(); if (subProcessGroups()) { throw InitException() << "There are no subprocess groups in merging!"; } } void MergingFactory::productionMode() { if(M()<0) for ( vector::ptr>::iterator amp = amplitudes().begin(); amp != amplitudes().end(); ++amp ) { Repository::clog() << "One-loop contributions from '" << (**amp).name() << "' are not required and will be disabled.\n" << flush; (**amp).disableOneLoop(); } MatchboxFactory::productionMode(); } void MergingFactory::fillMEsMap() { olpProcesses().clear(); assert( getProcesses().size() == 1 ); processMap[0] = getProcesses()[0]; if ( MH()->M() >= 0 ) setHighestVirt(processMap[0].size()+MH()->M()); MH()->N0(processMap[0].size()); for ( int i = 1 ; i <= MH()->N() ; ++i ) { processMap[i] = processMap[i - 1]; processMap[i].push_back("j"); } for ( int i = 0 ; i <= MH()->N() ; ++i ) { const bool below_maxNLO = i < MH()->M() + 1; vector ames = makeMEs(processMap[i], orderInAlphaS() + i, below_maxNLO ); copy(ames.begin(), ames.end(), back_inserter(pureMEsMap()[i])); } } #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" void MergingFactory::prepare_BV(int i) { // check if we have virtual contributions bool haveVirtuals = true; for ( auto born : pureMEsMap()[i]) { prepareME(born); if ( born->isOLPTree() ) { int id = orderOLPProcess(born->subProcess(), born->matchboxAmplitude(), ProcessType::treeME2); born->olpProcess(ProcessType::treeME2,id); id = orderOLPProcess(born->subProcess(), born->matchboxAmplitude(), ProcessType::colourCorrelatedME2); born->olpProcess(ProcessType::colourCorrelatedME2,id); bool haveGluon = false; for ( const auto & p : born->subProcess().legs ) if ( p->id() == 21 ) { haveGluon = true; break; } if ( haveGluon ) { id = orderOLPProcess(born->subProcess(), born->matchboxAmplitude(), ProcessType::spinColourCorrelatedME2); born->olpProcess(ProcessType::spinColourCorrelatedME2,id); } } if ( born->isOLPLoop() && i <= MH()->M() ) { int id = orderOLPProcess(born->subProcess(), born->matchboxAmplitude(), ProcessType::oneLoopInterference); born->olpProcess(ProcessType::oneLoopInterference,id); if ( !born->onlyOneLoop() && born->needsOLPCorrelators() ) { id = orderOLPProcess(born->subProcess(), born->matchboxAmplitude(), ProcessType::colourCorrelatedME2); born->olpProcess(ProcessType::colourCorrelatedME2,id); } } haveVirtuals &= born->haveOneLoop(); } // check for consistent conventions on virtuals, if we are to include MH()->M() if (!(i > MH()->M()||haveVirtuals)) throw InitException() << MH()->M() << " NLO corrections requested,\n" << "but no virtual contributions are found."; } void MergingFactory::prepare_R(int i) { for ( auto real : pureMEsMap()[i]) prepareME(real); } #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" void MergingFactory::getVirtuals(MatchboxMEBasePtr nlo, bool clone){ const auto & partons = nlo->diagrams().front()->partons(); for ( auto I : DipoleRepository::insertionIOperators(dipoleSet()) ) if ( I->apply(partons) ){ auto myI = I; if ( clone ) myI = I->cloneMe(); nlo->virtuals().push_back(myI); } for ( auto PK : DipoleRepository::insertionPKOperators(dipoleSet()) ) if ( PK->apply(partons) ){ auto myPK = PK; if ( clone ) myPK = PK->cloneMe(); nlo->virtuals().push_back(myPK); } } void MergingFactory::pushB(MatchboxMEBasePtr born, int i) { MatchboxMEBasePtr bornme = born->cloneMe(); bornme->maxMultCKKW(1); bornme->minMultCKKW(0); string pname = fullName() + "/" + bornme->name() + ".Born"; if ( !(generator()->preinitRegister(bornme, pname)) ) throw InitException() << "Born ME "<< pname << " already existing."; if (MH()->gamma()!=1.) getVirtuals(bornme,false); NodePtr clusternode = new_ptr(Node(bornme, 0, MH())); clusternode->deepHead(clusternode); MH()->firstNodeMap(bornme,clusternode); bornme->merger(MH()); vector current = {{clusternode}}; vector children; unsigned int k = 1; while ( ! thePureMEsMap[i - k].empty() ) { for ( auto tmp : current ){//j tmp->birth(thePureMEsMap[i - k]); for ( auto tmpchild : tmp->children() ) {//m children.push_back(tmpchild); } } current = children; children.clear(); ++k; } if ( MH()->N() > i ) bornme->needsCorrelations(); else bornme->needsNoCorrelations(); bornme->cloneDependencies(); MEs().push_back(bornme); } void MergingFactory::pushV(MatchboxMEBasePtr born, int i) { MatchboxMEBasePtr nlo = born->cloneMe(); string pname = fullName() + "/" + nlo->name() + ".Virtual"; if ( !(generator()->preinitRegister(nlo, pname)) ) throw InitException() << "Virtual ME "<< pname << " already existing."; ////////////////////////////////////NLO/////////////////////////// nlo->virtuals().clear(); getVirtuals(nlo , false); if ( nlo->virtuals().empty() ) throw InitException() << "No insertion operators have been found for " << born->name() << ".\n"; nlo->doOneLoopNoBorn(); ////////////////////////////////////NLO/////////////////////////// NodePtr clusternode = new_ptr(Node(nlo, 0,MH())); clusternode->deepHead(clusternode); clusternode->virtualContribution(true); MH()->firstNodeMap(nlo,clusternode); nlo->merger(MH()); vector current = {{clusternode}}; vector children; unsigned int k = 1; while ( ! thePureMEsMap[i - k].empty() ) { for ( auto tmp : current ){ tmp->birth(thePureMEsMap[i - k]); for ( auto tmpchild : tmp->children()) children.push_back(tmpchild); } current = children; children.clear(); ++k; } if ( nlo->isOLPLoop() ) { int id = orderOLPProcess(nlo->subProcess(), born->matchboxAmplitude(), ProcessType::oneLoopInterference); nlo->olpProcess(ProcessType::oneLoopInterference,id); if ( !nlo->onlyOneLoop() && nlo->needsOLPCorrelators() ) { id = orderOLPProcess(nlo->subProcess(), born->matchboxAmplitude(), ProcessType::colourCorrelatedME2); nlo->olpProcess(ProcessType::colourCorrelatedME2,id); } } nlo->needsCorrelations(); nlo->cloneDependencies(); MEs().push_back(nlo); } void MergingFactory::pushR(MatchboxMEBasePtr born, int i) { MatchboxMEBasePtr bornme = born->cloneMe(); string pname = fullName() + "/" + bornme->name() + ".Real"; if ( !(generator()->preinitRegister(bornme, pname)) ) throw InitException() << "Subtracted ME " << pname << " already existing."; NodePtr clusternode = new_ptr(Node(bornme, 1, MH())); clusternode->deepHead(clusternode); clusternode->subtractedReal(true); MH()->firstNodeMap(bornme,clusternode); bornme->merger(MH()); vector current = {{clusternode}}; vector children; unsigned int k = 1; while ( ! thePureMEsMap[i - k].empty() ) { for ( auto tmp : current ){ tmp->birth(thePureMEsMap[i - k]); for ( auto tmpchild : tmp->children()) children.push_back(tmpchild); } current = children; children.clear(); ++k; } if(clusternode->children().empty()){ // This is a finite real contribution. // This process is included in the LO merging. return; } if ( MH()->N() > i ) bornme->needsCorrelations(); else bornme->needsNoCorrelations(); bornme->cloneDependencies(pname); MEs().push_back(bornme); } // MergingFactory should never order OLPs here, // they're done elsewhere. void MergingFactory::orderOLPs() {} #include "ThePEG/Utilities/StringUtils.h" vector MergingFactory::parseProcess(string in) { vector process = StringUtils::split(in); if ( process.size() < 3 ) throw Exception() << "MatchboxFactory: Invalid process."<< Exception::runerror; for ( string & p : process) { p = StringUtils::stripws(p); } theN = 0; bool prodprocess = true; vector result; for ( const string & p : process ) { if ( p == "->" ) continue; if (p=="[") { prodprocess = false; } else if (p=="]") { prodprocess = false; // TODO what if there's stuff after the bracket? assert( p == process.back() ); break; } else if (p=="[j") { prodprocess = false; ++theN; } else if (p=="j" && !prodprocess) { ++theN; prodprocess = false; } else if (p=="j]") { ++theN; prodprocess = false; // TODO what if there's stuff after the bracket? assert( p == process.back() ); break; } else if ( prodprocess ) { result.push_back(p); } else { throw InitException() << "Unknown particle class \"" << p << '"' << " in the process definition merging bracket.\n" << "Only jets (\"j\") are supported at the moment."; } } return result; } #include "Herwig/Utilities/Progress.h" void MergingFactory::setup() { useMe(); DipoleShowerHandlerPtr dsh=dynamic_ptr_cast(this->CKKWHandler()); - if(! dsh )throw InitException() << "The showerhandlerfor the MergingFactory must be the DipoleShower. "; + if(! dsh )throw InitException() << "The showerhandler for the MergingFactory must be the DipoleShower. "; dsh->setMerger(MH()); MH()->setFactory(this); MH()->setDipoleShower(dsh); if(!ransetup){ generator()->log() <<"\nStarting merging setup.\n\n"; olpProcesses().clear(); externalAmplitudes().clear(); // We set the couplings in the ME to be fixed // and reweight in the history weight for this. setFixedCouplings(true); setFixedQEDCouplings(true); // rebind the particle data objects, can't use rebind() function for ( auto & g : particleGroups()) { for ( auto & p : g.second) { p = getParticleData(p->id()); } } const PDVector& partons = particleGroups()["j"]; unsigned int nl = 0; for ( const auto p : partons ) { const Energy mass = p->hardProcessMass(); const long pid = p->id(); if ( abs(pid) < 7 && mass == ZERO ) ++nl; if ( pid > 0 && pid < 7 && mass == ZERO ) nLightJetVec( pid ); if ( pid > 0 && pid < 7 && mass != ZERO ) nHeavyJetVec( pid ); } nLight(nl/2); const PDVector& partonsInP = particleGroups()["p"]; for ( const auto pip : partonsInP ) if ( pip->id() > 0 && pip->id() < 7 && pip->hardProcessMass() == ZERO ) nLightProtonVec( pip->id() ); // fill the amplitudes if ( !amplitudes().empty() ) fillMEsMap(); // Use the colour basis of the first element of amplitudes // to set the large N colour basis for the MergingHelper assert(!amplitudes().empty() ); if ( !amplitudes()[0]->colourBasis() ) throw Exception() << "MergingFactory::setup(): Expecting a colour basis object." << Exception::runerror; auto largeNBasis = amplitudes()[0]->colourBasis()->cloneMe(); largeNBasis->clear(); largeNBasis->doLargeN(); MH()->largeNBasis(largeNBasis); // prepare the Born and virtual matrix elements for ( int i = 0 ; i <= max(0, MH()->N()) ; ++i ) prepare_BV(i); // prepare the real emission matrix elements for ( int i = 0 ; i <= MH()->N() ; ++i ) prepare_R(i); if (MH()->N()<=MH()->M()) { throw InitException() << "Merging: The number of NLOs need to be" << "\nsmaller than the number of LO processes.\n"; } // Order the external Amplitudes. orderOLPs(); // start creating matrix elements MEs().clear(); // count the subprocesses size_t numb = 0; size_t numv = 0; size_t numr = 0; for (int i = 0; i <= max(0, MH()->N()) ; ++i ) { for ( auto born : thePureMEsMap[i] ) { if (bornContributions() ) { numb++; } } } for (int i = 0 ; i <=max(0, MH()->N()); ++i ) for ( auto virt : thePureMEsMap[i] ) if ( virtualContributions() && i <= MH()->M()) { numv++; } for (int i = 1; i <= max(0, MH()->N()) ; ++i ) for ( auto real : thePureMEsMap[i] ) if (realContributions() && i <= MH()->M() + 1 ){ numr++; } + + + if(int(numb+numv+numr) < theChunk){ + throw InitException() << "You try to chunk (Chunk="< 0 && theChunkPart == 0 ) + throw InitException() <<" Set the ChunkPart ( = "<log() << ANSI::yellow + << "\n\nWarning: \nYou split up the runs into theChunks. This is no standard feature." + << "\nYou are now responsible to make sure to run all theChunk parts." + << "\nThis setup run is for: " << theChunkPart << "/" << theChunk<<"\n\n "; + + + generator()->log() << ANSI::red << "Preparing Merging: "; generator()->log() << ANSI::green << numb << " x Born " << ANSI::red; if (MH()->M()>-1) { generator()->log() << ANSI::yellow << numv << " x Virtual "; generator()->log() << ANSI::blue << numr << " x Real " << ANSI::red << flush; } + int countchunk=0; + progress_display progressBar{ numb+numv+numr, generator()->log() }; - for (int i = 0; i <= max(0, MH()->N()) ; ++i ){ - for ( auto born : thePureMEsMap[i]){ - if (bornContributions() ){ - pushB(born, i); - generator()->log() << ANSI::green; - ++progressBar; - generator()->log() << ANSI::reset; - } + + // insert the born contributions to ME vector + for (int i = 0; i <= max(0, MH()->N()) ; ++i ) + for ( auto born : thePureMEsMap[i]) + if (bornContributions() ){ + countchunk++; // theChunkPart is in [1,...,theChunk] + if ( theChunk == 0 || theChunkPart == countchunk ) pushB( born , i ); + if ( countchunk == theChunk ) countchunk=0; + generator()->log() << ANSI::green; + ++progressBar; + generator()->log() << ANSI::reset; } - } + // insert the virtual contributions to ME vector + for (int i = 0 ; i <=max(0, MH()->N()); ++i ) + for ( auto virt : thePureMEsMap[i]) + if ( virtualContributions() && i <= MH()->M()){ + countchunk++;// theChunkPart is in [1,...,theChunk] + if ( theChunk == 0 || theChunkPart == countchunk ) pushV(virt, i); + if ( countchunk == theChunk ) countchunk=0; + generator()->log() << ANSI::yellow; + ++progressBar; + } + // insert the real contributions to ME vector + for (int i = 1; i <= max(0, MH()->N()) ; ++i ) + for ( auto real : thePureMEsMap[i] ) + if (realContributions()&& i <= MH()->M() + 1 ){ + countchunk++;// theChunkPart is in [1,...,theChunk] + if ( theChunk == 0 || theChunkPart == countchunk ) pushR(real, i); + if ( countchunk == theChunk ) countchunk=0; + generator()->log() << ANSI::blue; + ++progressBar; + } - - - - for (int i = 0 ; i <=max(0, MH()->N()); ++i ) - for ( auto virt : thePureMEsMap[i]) - if ( virtualContributions() && i <= MH()->M()){ - pushV(virt, i); - generator()->log() << ANSI::yellow; - ++progressBar; - } - - for (int i = 1; i <= max(0, MH()->N()) ; ++i ) - for ( auto real : thePureMEsMap[i] ) - if (realContributions()&& i <= MH()->M() + 1 ){ - pushR(real, i); - generator()->log() << ANSI::blue; - ++progressBar; - } generator()->log() << ANSI::reset; if ( !externalAmplitudes().empty() ) { generator()->log() << "Initializing external amplitudes." << endl; progress_display progressBar{ externalAmplitudes().size(), generator()->log() }; for ( const auto ext : externalAmplitudes() ) { if ( ! ext->initializeExternal() ) { throw InitException() << "error: failed to initialize amplitude '" << ext->name() << "'\n"; } ++progressBar; } generator()->log() << "---------------------------------------------------" << endl; } if ( !olpProcesses().empty() ) { generator()->log() << "Initializing one-loop provider(s)." << endl; map::tptr, map, int> > olps; for (const auto oit : olpProcesses()) { olps[oit.first] = oit.second; } progress_display progressBar{ olps.size(), generator()->log() }; for ( const auto olpit : olps ) { if ( !olpit.first->startOLP(olpit.second) ) { throw InitException() << "error: failed to start OLP for amplitude '" << olpit.first->name() << "'\n"; } ++progressBar; } generator()->log() << "---------------------------------------------------\n" << flush; } generator()->log() <<"\nGenerated "<log() << "---------------------------------------------------\n" << flush; generator()->log() <<"\n\n" << ANSI::red <<"Note: Due to the unitarization of the higher " <<"\nmultiplicities, the individual cross sections " <<"\ngiven in the integration and run step are not" <<"\nmeaningful without merging." << ANSI::reset << endl; ransetup=true; } } #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" void MergingFactory::persistentOutput(PersistentOStream & os) const { os << theonlymulti << ransetup - << processMap << theMergingHelper <> theonlymulti >> ransetup - >> processMap >> theMergingHelper >>theM>>theN>>theNonQCDCuts; + >> processMap >> theMergingHelper >>theM>>theN>>theNonQCDCuts>>theChunk>>theChunkPart; } #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Command.h" void MergingFactory::Init() { static Parameter interfaceonlymulti("onlymulti", "Calculate only the ME with k additional partons.", &MergingFactory::theonlymulti, -1, -1, 0, false, false, Interface::lowerlim); static Switch interface_Unitarized("Unitarized", "Unitarize the cross section (default is unitarised. NLO merging must be unitarised).", &MergingFactory::unitarized, true, false, false); static SwitchOption interface_UnitarizedYes(interface_Unitarized, "Yes", "Switch on the unitarized cross section.", true); static SwitchOption interface_UnitarizedNo(interface_Unitarized, "No", "Switch off the unitarized cross section.", false); static Reference interfaceMergingHelper("MergingHelper", "Pointer to the Merging Helper.", &MergingFactory::theMergingHelper, false, false, true, true, false); static Parameter interfaceaddNLOLegs("NLOProcesses", "Set the number of virtual corrections to consider. 0 is default for no virtual correction.", &MergingFactory::theM, 0, 0, 0, false, false, Interface::lowerlim); static Reference interfaceNonQcdCuts("NonQCDCuts", "Cut on non-QCD modified observables. Be carefull!", &MergingFactory::theNonQCDCuts, false, false, true, true, false); + + + static Parameter interfacetheChunk("Chunk", + "Cut the number of subprocesses into n theChunks.", + &MergingFactory::theChunk, -1, -1, 0, + false, false, Interface::lowerlim); + + static Parameter interfacetheChunkPart("ChunkPart", + "If theChunk is larger then 0, set this parameter to the n'th part. Make sure to add the ChunksParts afterwards.", + &MergingFactory::theChunkPart, -1, -1, 0, + false, false, Interface::lowerlim); } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct (the class and its base class), and that the constructor // arguments are correct (the class name and the name of the dynamically // loadable library where the class implementation can be found). DescribeClass describeHerwigMergingFactory("Herwig::MergingFactory", "HwDipoleShower.so"); diff --git a/Shower/Dipole/Merging/MergingFactory.h b/Shower/Dipole/Merging/MergingFactory.h --- a/Shower/Dipole/Merging/MergingFactory.h +++ b/Shower/Dipole/Merging/MergingFactory.h @@ -1,168 +1,179 @@ /// -*- C++ -*- // /// MergingFactory.h is a part of Herwig - A multi-purpose Monte Carlo event generator /// Copyright (C) 2002-2017 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_MergingFactory_H #define HERWIG_MergingFactory_H // /// This is the declaration of the MergingFactory class. // #include "MergingFactory.fh" #include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h" #include "Node.fh" #include "Merger.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Johannes Bellm * * \brief MergingFactory automatically sets up a NLO * QCD merging. * * @see \ref MergingFactoryInterfaces "The interfaces" * defined for MergeboxFactory. */ class MergingFactory : public MatchboxFactory { public: ///Check consistency and switch to porduction mode. void productionMode(); /// main method to setup the ME vector virtual void setup(); /// fill all amplitudes, stored in pureMEsMap void fillMEsMap(); /// prepare the Born and virtual matrix elements. void prepare_BV(int i); /// prepare the real emission matrix elements. void prepare_R(int i); /// push the born contributions to the ME vector. void pushB(MatchboxMEBasePtr, int); //push the virtual contributions to the ME vector. void pushV(MatchboxMEBasePtr, int); /// push the real contributions to the ME vector. void pushR(MatchboxMEBasePtr, int); /// order matrix elements from one loop provider. void orderOLPs(); /// Debugging: push only multiplicities to the ME vector /// in range of specified mulltiplicity. int onlymulti()const { return theonlymulti==-1?-1:(theonlymulti+processMap.find(0)->second.size()); } /// pointer to the merging helper. MergerPtr MH() {return theMergingHelper;} /// maximal NLO mulitplicity: 0=NLO corrections to the productio process. int M() const {return theM-1;} /// leg size of highest multiplicity. int N() const {return theN;} /// Return the Map of matrix elements to be considered /// (the Key is the number of additional jets) const map >& pureMEsMap() const { return thePureMEsMap; } /// Access the Map of matrix elements to be considered /// (the Key is the number of additional jets) map >& pureMEsMap() { return thePureMEsMap; } //Parse a process description virtual vector parseProcess(string); // fill the virtuals vector (these are IPK-operators) void getVirtuals(MatchboxMEBasePtr nlo, bool clone ); // In the merged setup we only produce single phase space points. bool subProcessGroups() const { return false;} // Cut on non-QCD observables. Ptr::ptr nonQCDCuts(){return theNonQCDCuts;} 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); //@} static void Init(); protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** * 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: /// unitarise the LO contributions. bool unitarized = true; /// did run setup. bool ransetup = false; /// Debugging: push only multiplicities to the ME vector /// in range of specified mulltiplicity. int theonlymulti = -1; /// maximal legsize for NLO corrections. int theM = -1; /// maximal legsize for LO contributions. int theN = -1; /// map for processes. map< int, vector > processMap; //The matrix elements: int = number of additional jets map< int, vector > thePureMEsMap; /// the merging helper MergerPtr theMergingHelper; /// Cut on non-QCD modified observables. - Ptr::ptr theNonQCDCuts; + Ptr::ptr theNonQCDCuts; + + /// For more complicated processes the number of subprocesses is large. + /// This parameter allows to chunk the suprocesses into same sized cunks. + /// It is in the responsibility of the user to add all chunk parts afterwards. + /// The user also needs to take care that, e.g. output can be compined. + int theChunk=0; + /// This parameter selects a part chunkpart of the chunked subprocesses. + /// The user needs to take care to sum all chunkparts afterwards. + int theChunkPart=0; + + /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MergingFactory & operator=(const MergingFactory &) = delete; }; } #endif /* HERWIG_MergingFactory_H */ diff --git a/Shower/Dipole/Merging/Node.cc b/Shower/Dipole/Merging/Node.cc --- a/Shower/Dipole/Merging/Node.cc +++ b/Shower/Dipole/Merging/Node.cc @@ -1,553 +1,489 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the Node class. // #include "Node.h" #include "MergingFactory.h" #include "Merger.h" using namespace Herwig; Node::Node(MatchboxMEBasePtr nodeME, int cutstage, MergerPtr mh) :Interfaced(), thenodeMEPtr(nodeME), thedipol(), theparent(), theCutStage(cutstage), isOrdered(true), theSubtractedReal(false), theVirtualContribution(false), theMergingHelper(mh) { nodeME->maxMultCKKW(1); nodeME->minMultCKKW(0); } Node::Node(NodePtr deephead, NodePtr head, SubtractionDipolePtr dipol, MatchboxMEBasePtr nodeME, int cutstage) :Interfaced(), thenodeMEPtr(nodeME), thedipol(dipol), theparent(head), theDeepHead(deephead), theCutStage(cutstage), isOrdered(true), theSubtractedReal(false), theVirtualContribution(false), theMergingHelper() //The subnodes have no merging helper { } Node::~Node() { } SubtractionDipolePtr Node::dipole() const { return thedipol; } /** returns the matrix element pointer */ const MatchboxMEBasePtr Node::nodeME() const { return thenodeMEPtr; } /** access the matrix element pointer */ MatchboxMEBasePtr Node::nodeME() { return thenodeMEPtr; } pair Node::getInOut( ){ PVector in; const auto me= nodeME(); const auto pd=me->mePartonData(); for( auto i : {0 , 1} ) in.push_back(pd[i]->produceParticle( me->lastMEMomenta()[i] ) ); PVector out; for ( size_t i = 2;i< pd.size();i++ ){ PPtr p = pd[i]->produceParticle( me->lastMEMomenta()[i] ); out.push_back( p ); } return { in , out }; } int Node::legsize() const {return nodeME()->legsize();} NodePtr Node::randomChild() { return thechildren[UseRandom::irnd(thechildren.size())]; } bool Node::allAbove(Energy pt) { for (NodePtr child : thechildren) if ( child->pT() < pt ) return false; return true; } Energy Node::maxChildPt(){ Energy maxi=-1*GeV; for (NodePtr child : thechildren)maxi=max(child->pT(),maxi); return maxi; } bool Node::isInHistoryOf(NodePtr other) { while (other->parent()) { if (other == this) return true; other = other->parent(); } return false; } void Node::flushCaches() { if (didflush) return; didflush=true; for ( auto const & ch: thechildren) { ch->xcomb()->clean(); ch->nodeME()->flushCaches(); ch->flushCaches(); } } void Node::setKinematics() { for (auto const & ch: thechildren) { ch->dipole()->setXComb(ch->xcomb()); ch->dipole()->setKinematics(); ch->nodeME()->setKinematics(); ch->setKinematics(); } } void Node::clearKinematics() { for (auto const & ch: thechildren) { ch->dipole()->setXComb(ch->xcomb()); ch->nodeME()->clearKinematics(); ch->dipole()->clearKinematics(); ch->clearKinematics(); } } bool Node::generateKinematics(const double *r, bool directCut) { didflush=false; // If there are no children to the child process we are done. if(children().empty()) return true; assert(parent()); if ( ! directCut && pT() < deepHead()->MH()->mergePt()) { // Real emission: // If there are children to the child process, // we now require that all subsequent children // with pt < merging scale are in their ME region. // Since the possible children of the real emission // contribution are now in their ME region, // it is clear that a second clustering is possible // -- modulo phase space restrictions. // Therefore the real emission contribution // are unitarised and the cross section is // hardly modified. auto inOutPair = getInOut(); NodePtr rc = randomChild(); rc->dipole()->setXComb(rc->xcomb()); if(!rc->dipole()->generateKinematics(r))assert(false); // If not in ME -> return false if(!deepHead()->MH()->matrixElementRegion( inOutPair.first , inOutPair.second , rc->pT() , deepHead()->MH()->mergePt() ) )return false; } for (auto & ch : children() ) { ch->dipole()->setXComb(ch->xcomb()); if ( !ch->dipole()->generateKinematics(r) ) { assert(false); } ch->generateKinematics( r, true); } return true; } bool Node::firstgenerateKinematics(const double *r, bool directCut) { didflush=false; // This is called form the merging helper for the first node. So: assert(!parent()); assert(xcomb()); if(MH()->treefactory()->nonQCDCuts()){ tcPDVector outdata(xcomb()->mePartonData().begin()+2, xcomb()->mePartonData().end()); vector outmomenta(xcomb()->meMomenta().begin()+2, xcomb()->meMomenta().end()); if ( !MH()->treefactory()->nonQCDCuts()->passCuts(outdata,outmomenta, xcomb()->mePartonData()[0], xcomb()->mePartonData()[1]) ) return false; } ///// This should not be needed!!! ///// ( Warning inMerger::matrixElementRegion gets triggered.) flushCaches(); //Set here the new merge Pt for the next phase space point.( Smearing!!!) MH()->smearMergePt(); // If there are no children to this node, we are done here: if (children().empty()) return true; // directCut is for born and for virtual contributions. // if directCut is true, then cut on the first ME region. // call recursiv generate kinematics for subsequent nodes. if ( directCut ){ auto inOutPair = getInOut(); NodePtr rc = randomChild(); rc->dipole()->setXComb(rc->xcomb()); if ( !rc->dipole()->generateKinematics(r) ) { return false; } rc->nodeME()->setXComb(rc->xcomb()); if(MH()->gamma() == 1.){ if(!MH()->matrixElementRegion( inOutPair.first , inOutPair.second , rc->pT() , MH()->mergePt() ) ){ return false; } }else{ // Different treatment if gamma is not 1. // Since the dipoles need to be calculated always // their alpha region is touched. // AlphaRegion != MERegion !!! bool inAlphaPS = false; for (auto const & ch: thechildren) { ch->dipole()->setXComb(ch->xcomb()); if ( !ch->dipole()->generateKinematics(r) ) return false; MH()->treefactory()->setAlphaParameter( MH()->gamma() ); inAlphaPS |= ch->dipole()->aboveAlpha(); MH()->treefactory()->setAlphaParameter( 1. ); } NodePtr rc = randomChild(); if(!inAlphaPS&& !MH()->matrixElementRegion( inOutPair.first , inOutPair.second , rc->pT() , MH()->mergePt() ) ) return false; } } for (auto const & ch: thechildren) { ch->dipole()->setXComb(ch->xcomb()); if ( !ch->dipole()->generateKinematics(r) ) { cout<<"\nCould not generate dipole kinematics";;return false; } if( ! ch->generateKinematics(r,directCut) )return false; } return true; } StdXCombPtr Node::xcomb() const { assert(thexcomb); return thexcomb; } StdXCombPtr Node::xcomb(){ if(thexcomb)return thexcomb; assert(parent()); thexcomb=dipole()->makeBornXComb(parent()->xcomb()); xcomb()->head(parent()->xcomb()); dipole()->setXComb(thexcomb); return thexcomb; } void Node::setXComb(tStdXCombPtr xc) { assert ( !parent() ); thexcomb=xc; assert(thexcomb->lastParticles().first); } #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" void Node::birth(const vector & vec) { // produce the children vector dipoles = nodeME()->getDipoles(DipoleRepository::dipoles( nodeME()->factory()->dipoleSet()), vec, true); for ( auto const & dip : dipoles ) { dip->doSubtraction(); NodePtr node = new_ptr(Node(theDeepHead, this, dip, dip->underlyingBornME(), theDeepHead->cutStage())); thechildren.push_back(node); } } -namespace{ - - /** - * Triangular / Kallen function - */ - double rootOfKallen (double a, double b, double c) { - return sqrt( a*a + b*b + c*c - 2.*( a*b+a*c+b*c ) ); } - -} - vector Node::getNextOrderedNodes(bool normal, double hardScaleFactor) const { vector temp = children(); vector res; for (NodePtr const & child : children()) { if(deepHead()->MH()->mergePt()>child->pT()) { res.clear(); return res; } } for (NodePtr const & child: children()) { if (parent()&& normal) { if ( child->pT() < pT() ) { continue; } } if ( child->children().size() != 0 ) { for (NodePtr itChild: child->children()) { if( itChild->pT() > child->pT()&&child->inShowerPS(itChild->pT()) ) { res.push_back(child); break; } } } else { const auto sc=child->nodeME()->factory()->scaleChoice(); sc->setXComb(child->xcomb()); if ( sqr(hardScaleFactor)* sc->renormalizationScale() >= sqr(child->pT()) && child->inShowerPS(hardScaleFactor*sqrt(sc->renormalizationScale()))) { res.push_back(child); } } } return res; } bool Node::inShowerPS(Energy hardpT)const { // Here we decide if the current phase space // point can be reached from the underlying Node. // Full phase space available -> Tilde Kinematic is always fine. if(deepHead()->MH()->openZBoundaries()==1) return true; + double z_ = dipole()->lastZ(); // restrict according to hard scale if(deepHead()->MH()->openZBoundaries()==0){ pair zbounds = dipole()->tildeKinematics()->zBounds(pT(), hardpT); return (zbounds.firstMH()->openZBoundaries()==2); - - if( dipole()->bornEmitter()>1&& dipole()->bornSpectator()>1 ) return true; - - - bool isMassiv = (dipole()->tildeKinematics()->realEmitterData()->hardProcessMass() - +dipole()->tildeKinematics()->realEmissionData()->hardProcessMass() - +dipole()->tildeKinematics()->realSpectatorData()->hardProcessMass())!=ZERO; - - Energy scale=sqrt(2.*dipole()->tildeKinematics()->bornEmitterMomentum()* - dipole()->tildeKinematics()->bornSpectatorMomentum()); - - Energy hard=ZERO; - - assert(scale>=ZERO); - // II - if( dipole()->bornEmitter()<2&& dipole()->bornSpectator()<2 ) { - hard = min(scale,(1.-dipole()->tildeKinematics()->emitterX()) - *scale/(2.*sqrt(dipole()->tildeKinematics()->emitterX()))); - }else - // IF - if( dipole()->bornEmitter()<2&& dipole()->bornSpectator() >= 2){ - if(isMassiv){ - hard = scale * min(1.,sqrt(1.-dipole()->tildeKinematics()->emitterX()) /2.); - } - else{ - hard = scale * min(1.,sqrt((1.-dipole()->tildeKinematics()->emitterX())/ - dipole()->tildeKinematics()->emitterX()) /2.); - } - } - // FI - else{ - if(isMassiv){ - Energy2 mi2 = sqr(dipole()->tildeKinematics()->realEmitterData()->hardProcessMass()); - Energy2 m2 = sqr(dipole()->tildeKinematics()->realEmissionData()->hardProcessMass()); - Energy2 Mi2 = sqr(dipole()->tildeKinematics()->bornEmitterData()->hardProcessMass()); - Energy2 scale=2.*dipole()->tildeKinematics()->bornEmitterMomentum()* - dipole()->tildeKinematics()->bornSpectatorMomentum(); - Energy2 s = scale * (1.-dipole()->tildeKinematics()->spectatorX())/ - dipole()->tildeKinematics()->spectatorX() + Mi2; - Energy2 sdip = scale + Mi2; - hard = .5 * sqrt(s) * rootOfKallen( s/s, mi2/s, m2/s ); - hard = min( .5 * sqrt(sdip) * rootOfKallen( sdip/sdip, mi2/sdip, m2/sdip ),hard); - } - else{ - hard = scale*min(1.,sqrt((1.-dipole()->tildeKinematics()->spectatorX())/ - dipole()->tildeKinematics()->spectatorX())/2.); - } - } - - pair zbounds = - dipole()->tildeKinematics()->zBounds(pT(), hard); + assert(false); - return (zbounds.first temp = getNextOrderedNodes(normal, hardScaleFactor); Energy minpt = Constants::MaxEnergy; Selector subprosel; while (temp.size() != 0) { minpt = Constants::MaxEnergy; subprosel.clear(); for (NodePtr const & child : temp) { assert(deepHead()->MH()->largeNBasis()); if( child->dipole()->underlyingBornME()->largeNColourCorrelatedME2( {child->dipole()->bornEmitter(), child->dipole()->bornSpectator()}, deepHead()->MH()->largeNBasis()) != 0. ) { double weight = 1.; if ( deepHead()->MH()->chooseHistory() == 0 ) weight = abs(child->dipole()->dSigHatDR()/nanobarn); else if ( deepHead()->MH()->chooseHistory() == 1 ) weight = abs(child->dipole()->dSigHatDR()/child->nodeME()->dSigHatDRB()); else if ( deepHead()->MH()->chooseHistory() == 2 ) weight = 1.; else if ( deepHead()->MH()->chooseHistory() == 3 ) weight = 1_GeV/child->pT(); else assert(false); if(weight != 0.) { subprosel.insert(weight , child); minpt = min(minpt, child->pT()); } } } if (subprosel.empty()) return res; res = subprosel.select(UseRandom::rnd()); temp = res->getNextOrderedNodes(true, hardScaleFactor); } return res; } pair Node::calcDipandPS(Energy scale)const { return dipole()->dipandPs(sqr(scale), deepHead()->MH()->largeNBasis()); } CrossSection Node::calcPs(Energy scale)const { return dipole()->ps(sqr(scale), deepHead()->MH()->largeNBasis()); } CrossSection Node::calcDip(Energy scale)const { return dipole()->dip(sqr(scale)); } IBPtr Node::clone() const { return new_ptr(*this); } IBPtr Node::fullclone() const { return new_ptr(*this); } #include "ThePEG/Persistency/PersistentOStream.h" void Node::persistentOutput(PersistentOStream & os) const { os << thexcomb<< thenodeMEPtr<< thedipol<< thechildren<< theparent<< theProjector<< theDeepHead<< theCutStage<< ounit(theRunningPt, GeV)<< theSubtractedReal<< theVirtualContribution<< theMergingHelper; } #include "ThePEG/Persistency/PersistentIStream.h" void Node::persistentInput(PersistentIStream & is, int) { is >> thexcomb>> thenodeMEPtr>> thedipol>> thechildren>> theparent>> theProjector>> theDeepHead>> theCutStage>> iunit(theRunningPt, GeV)>> theSubtractedReal>> theVirtualContribution>> theMergingHelper; } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct (the class and its base class), and that the constructor // arguments are correct (the class name and the name of the dynamically // loadable library where the class implementation can be found). #include "ThePEG/Utilities/DescribeClass.h" DescribeClass describeHerwigNode("Herwig::Node", "HwDipoleShower.so"); void Node::Init() { static ClassDocumentation documentation("There is no documentation for the Node class"); } diff --git a/Shower/QTilde/Base/ShowerParticle.cc b/Shower/QTilde/Base/ShowerParticle.cc --- a/Shower/QTilde/Base/ShowerParticle.cc +++ b/Shower/QTilde/Base/ShowerParticle.cc @@ -1,584 +1,583 @@ // -*- C++ -*- // // ShowerParticle.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 ShowerParticle class. // #include "ShowerParticle.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h" #include using namespace Herwig; PPtr ShowerParticle::clone() const { return new_ptr(*this); } PPtr ShowerParticle::fullclone() const { return new_ptr(*this); } ClassDescription ShowerParticle::initShowerParticle; // Definition of the static class description member. void ShowerParticle::vetoEmission(ShowerPartnerType, Energy scale) { scales_.QED = min(scale,scales_.QED ); scales_.QED_noAO = min(scale,scales_.QED_noAO ); scales_.QCD_c = min(scale,scales_.QCD_c ); scales_.QCD_c_noAO = min(scale,scales_.QCD_c_noAO ); scales_.QCD_ac = min(scale,scales_.QCD_ac ); scales_.QCD_ac_noAO = min(scale,scales_.QCD_ac_noAO); + if(spinInfo()) spinInfo()->undecay(); } void ShowerParticle::addPartner(EvolutionPartner in ) { partners_.push_back(in); } namespace { LorentzRotation boostToShower(Lorentz5Momentum & porig, tShowerBasisPtr basis) { LorentzRotation output; assert(basis); if(basis->frame()==ShowerBasis::BackToBack) { // we are doing the evolution in the back-to-back frame // work out the boostvector Boost boostv(-(basis->pVector()+basis->nVector()).boostVector()); // momentum of the parton Lorentz5Momentum ptest(basis->pVector()); // construct the Lorentz boost output = LorentzRotation(boostv); ptest *= output; Axis axis(ptest.vect().unit()); // now rotate so along the z axis as needed for the splitting functions if(axis.perp2()>1e-10) { double sinth(sqrt(1.-sqr(axis.z()))); output.rotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); } else if(axis.z()<0.) { output.rotate(Constants::pi,Axis(1.,0.,0.)); } porig = output*basis->pVector(); porig.setX(ZERO); porig.setY(ZERO); } else { output = LorentzRotation(-basis->pVector().boostVector()); porig = output*basis->pVector(); porig.setX(ZERO); porig.setY(ZERO); porig.setZ(ZERO); } return output; } RhoDMatrix bosonMapping(ShowerParticle & particle, const Lorentz5Momentum & porig, VectorSpinPtr vspin, const LorentzRotation & rot, Helicity::Direction dir) { // rotate the original basis vector sbasis; for(unsigned int ix=0;ix<3;++ix) { sbasis.push_back(vspin->getProductionBasisState(ix)); sbasis.back().transform(rot); } // splitting basis vector fbasis; bool massless(particle.id()==ParticleID::g||particle.id()==ParticleID::gamma); VectorWaveFunction wave(porig,particle.dataPtr(),dir==outgoing ? incoming : outgoing); for(unsigned int ix=0;ix<3;++ix) { if(massless&&ix==1) { fbasis.push_back(LorentzPolarizationVector()); } else { wave.reset(ix,vector_phase); fbasis.push_back(wave.wave()); } } // work out the mapping RhoDMatrix mapping=RhoDMatrix(PDT::Spin1,false); for(unsigned int ix=0;ix<3;++ix) { for(unsigned int iy=0;iy<3;++iy) { mapping(ix,iy)= -conj(sbasis[ix].dot(fbasis[iy])); if(particle.id()<0) mapping(ix,iy)=conj(mapping(ix,iy)); } } return mapping; } RhoDMatrix fermionMapping(ShowerParticle & particle, const Lorentz5Momentum & porig, FermionSpinPtr fspin, const LorentzRotation & rot) { // extract the original basis states vector > sbasis; for(unsigned int ix=0;ix<2;++ix) { sbasis.push_back(fspin->getProductionBasisState(ix)); sbasis.back().transform(rot); } // calculate the states in the splitting basis vector > fbasis; SpinorWaveFunction wave(porig,particle.dataPtr(), particle.id()>0 ? incoming : outgoing); for(unsigned int ix=0;ix<2;++ix) { wave.reset(ix); fbasis.push_back(wave.dimensionedWave()); } RhoDMatrix mapping=RhoDMatrix(PDT::Spin1Half,false); for(unsigned int ix=0;ix<2;++ix) { if(fbasis[0].s2()==complex()) { mapping(ix,0) = sbasis[ix].s3()/fbasis[0].s3(); mapping(ix,1) = sbasis[ix].s2()/fbasis[1].s2(); } else { mapping(ix,0) = sbasis[ix].s2()/fbasis[0].s2(); mapping(ix,1) = sbasis[ix].s3()/fbasis[1].s3(); } } return mapping; } FermionSpinPtr createFermionSpinInfo(ShowerParticle & particle, const Lorentz5Momentum & porig, const LorentzRotation & rot, Helicity::Direction dir) { // calculate the splitting basis for the branching // and rotate back to construct the basis states LorentzRotation rinv = rot.inverse(); SpinorWaveFunction wave; if(particle.id()>0) wave=SpinorWaveFunction(porig,particle.dataPtr(),incoming); else wave=SpinorWaveFunction(porig,particle.dataPtr(),outgoing); FermionSpinPtr fspin = new_ptr(FermionSpinInfo(particle.momentum(),dir==outgoing)); for(unsigned int ix=0;ix<2;++ix) { wave.reset(ix); LorentzSpinor basis = wave.dimensionedWave(); basis.transform(rinv); fspin->setBasisState(ix,basis); - fspin->setDecayState(ix,basis); } particle.spinInfo(fspin); return fspin; } VectorSpinPtr createVectorSpinInfo(ShowerParticle & particle, const Lorentz5Momentum & porig, const LorentzRotation & rot, Helicity::Direction dir) { // calculate the splitting basis for the branching // and rotate back to construct the basis states LorentzRotation rinv = rot.inverse(); bool massless(particle.id()==ParticleID::g||particle.id()==ParticleID::gamma); VectorWaveFunction wave(porig,particle.dataPtr(),dir); VectorSpinPtr vspin = new_ptr(VectorSpinInfo(particle.momentum(),dir==outgoing)); for(unsigned int ix=0;ix<3;++ix) { LorentzPolarizationVector basis; if(massless&&ix==1) { basis = LorentzPolarizationVector(); } else { wave.reset(ix,vector_phase); basis = wave.wave(); } basis *= rinv; vspin->setBasisState(ix,basis); - vspin->setDecayState(ix,basis); } particle.spinInfo(vspin); vspin-> DMatrix() = RhoDMatrix(PDT::Spin1); vspin->rhoMatrix() = RhoDMatrix(PDT::Spin1); if(massless) { vspin-> DMatrix()(0,0) = 0.5; vspin->rhoMatrix()(0,0) = 0.5; vspin-> DMatrix()(2,2) = 0.5; vspin->rhoMatrix()(2,2) = 0.5; } return vspin; } } RhoDMatrix ShowerParticle::extractRhoMatrix(bool forward) { // get the spin density matrix and the mapping RhoDMatrix mapping; SpinPtr inspin; bool needMapping = getMapping(inspin,mapping); // set the decayed flag inspin->decay(); // get the spin density matrix RhoDMatrix rho = forward ? inspin->rhoMatrix() : inspin->DMatrix(); // map to the shower basis if needed if(needMapping) { RhoDMatrix rhop(rho.iSpin(),false); for(int ixb=0;ixbperturbative()) { // mapping is the identity output=this->spinInfo(); mapping=RhoDMatrix(this->dataPtr()->iSpin()); if(output) { return false; } else { Lorentz5Momentum porig; LorentzRotation rot = boostToShower(porig,showerBasis()); Helicity::Direction dir = this->isFinalState() ? outgoing : incoming; if(this->dataPtr()->iSpin()==PDT::Spin0) { assert(false); } else if(this->dataPtr()->iSpin()==PDT::Spin1Half) { output = createFermionSpinInfo(*this,porig,rot,dir); } else if(this->dataPtr()->iSpin()==PDT::Spin1) { output = createVectorSpinInfo(*this,porig,rot,dir); } else { assert(false); } return false; } } // if particle is final-state and is from the hard process else if(this->isFinalState()) { assert(this->perturbative()==1 || this->perturbative()==2); // get transform to shower frame Lorentz5Momentum porig; LorentzRotation rot = boostToShower(porig,showerBasis()); // the rest depends on the spin of the particle PDT::Spin spin(this->dataPtr()->iSpin()); mapping=RhoDMatrix(spin,false); // do the spin dependent bit if(spin==PDT::Spin0) { ScalarSpinPtr sspin=dynamic_ptr_cast(this->spinInfo()); if(!sspin) { ScalarWaveFunction::constructSpinInfo(this,outgoing,true); } output=this->spinInfo(); return false; } else if(spin==PDT::Spin1Half) { FermionSpinPtr fspin=dynamic_ptr_cast(this->spinInfo()); // spin info exists get information from it if(fspin) { output=fspin; mapping = fermionMapping(*this,porig,fspin,rot); return true; } // spin info does not exist create it else { output = createFermionSpinInfo(*this,porig,rot,outgoing); return false; } } else if(spin==PDT::Spin1) { VectorSpinPtr vspin=dynamic_ptr_cast(this->spinInfo()); // spin info exists get information from it if(vspin) { output=vspin; mapping = bosonMapping(*this,porig,vspin,rot,outgoing); return true; } else { output = createVectorSpinInfo(*this,porig,rot,outgoing); return false; } } // not scalar/fermion/vector else assert(false); } // incoming to hard process else if(this->perturbative()==1 && !this->isFinalState()) { // get the basis vectors // get transform to shower frame Lorentz5Momentum porig; LorentzRotation rot = boostToShower(porig,showerBasis()); porig *= this->x(); // the rest depends on the spin of the particle PDT::Spin spin(this->dataPtr()->iSpin()); mapping=RhoDMatrix(spin); // do the spin dependent bit if(spin==PDT::Spin0) { cerr << "testing spin 0 not yet implemented " << endl; assert(false); } // spin-1/2 else if(spin==PDT::Spin1Half) { FermionSpinPtr fspin=dynamic_ptr_cast(this->spinInfo()); // spin info exists get information from it if(fspin) { output=fspin; mapping = fermionMapping(*this,porig,fspin,rot); return true; } // spin info does not exist create it else { output = createFermionSpinInfo(*this,porig,rot,incoming); return false; } } // spin-1 else if(spin==PDT::Spin1) { VectorSpinPtr vspin=dynamic_ptr_cast(this->spinInfo()); // spinInfo exists map it if(vspin) { output=vspin; mapping = bosonMapping(*this,porig,vspin,rot,incoming); return true; } // create the spininfo else { output = createVectorSpinInfo(*this,porig,rot,incoming); return false; } } assert(false); } // incoming to decay else if(this->perturbative() == 2 && !this->isFinalState()) { // get the basis vectors Lorentz5Momentum porig; LorentzRotation rot=boostToShower(porig,showerBasis()); // the rest depends on the spin of the particle PDT::Spin spin(this->dataPtr()->iSpin()); mapping=RhoDMatrix(spin); // do the spin dependent bit if(spin==PDT::Spin0) { cerr << "testing spin 0 not yet implemented " << endl; assert(false); } // spin-1/2 else if(spin==PDT::Spin1Half) { // FermionSpinPtr fspin=dynamic_ptr_cast(this->spinInfo()); // // spin info exists get information from it // if(fspin) { // output=fspin; // mapping = fermionMapping(*this,porig,fspin,rot); // return true; // // spin info does not exist create it // else { // output = createFermionSpinInfo(*this,porig,rot,incoming); // return false; // } // } assert(false); } // // spin-1 // else if(spin==PDT::Spin1) { // VectorSpinPtr vspin=dynamic_ptr_cast(this->spinInfo()); // // spinInfo exists map it // if(vspin) { // output=vspin; // mapping = bosonMapping(*this,porig,vspin,rot); // return true; // } // // create the spininfo // else { // output = createVectorSpinInfo(*this,porig,rot,incoming); // return false; // } // } // assert(false); assert(false); } else assert(false); return true; } void ShowerParticle::constructSpinInfo(bool timeLike) { // now construct the required spininfo and calculate the basis states PDT::Spin spin(dataPtr()->iSpin()); if(spin==PDT::Spin0) { ScalarWaveFunction::constructSpinInfo(this,outgoing,timeLike); } // calculate the basis states and construct the SpinInfo for a spin-1/2 particle else if(spin==PDT::Spin1Half) { // outgoing particle if(id()>0) { vector > stemp; SpinorBarWaveFunction::calculateWaveFunctions(stemp,this,outgoing); SpinorBarWaveFunction::constructSpinInfo(stemp,this,outgoing,timeLike); } // outgoing antiparticle else { vector > stemp; SpinorWaveFunction::calculateWaveFunctions(stemp,this,outgoing); SpinorWaveFunction::constructSpinInfo(stemp,this,outgoing,timeLike); } } // calculate the basis states and construct the SpinInfo for a spin-1 particle else if(spin==PDT::Spin1) { bool massless(id()==ParticleID::g||id()==ParticleID::gamma); vector vtemp; VectorWaveFunction::calculateWaveFunctions(vtemp,this,outgoing,massless,vector_phase); VectorWaveFunction::constructSpinInfo(vtemp,this,outgoing,timeLike,massless); } else { throw Exception() << "Spins higher than 1 are not yet implemented in " << "FS_QtildaShowerKinematics1to2::constructVertex() " << Exception::runerror; } } void ShowerParticle::initializeDecay() { Lorentz5Momentum p, n, ppartner, pcm; assert(perturbative()!=1); // this is for the initial decaying particle if(perturbative()==2) { ShowerBasisPtr newBasis; p = momentum(); Lorentz5Momentum ppartner(partner()->momentum()); // removed to make inverse recon work properly //if(partner->thePEGBase()) ppartner=partner->thePEGBase()->momentum(); pcm=ppartner; Boost boost(p.findBoostToCM()); pcm.boost(boost); n = Lorentz5Momentum( ZERO,0.5*p.mass()*pcm.vect().unit()); n.boost( -boost); newBasis = new_ptr(ShowerBasis()); newBasis->setBasis(p,n,ShowerBasis::Rest); showerBasis(newBasis,false); } else { showerBasis(dynamic_ptr_cast(parents()[0])->showerBasis(),true); } } void ShowerParticle::initializeInitialState(PPtr parent) { // For the time being we are considering only 1->2 branching Lorentz5Momentum p, n, pthis, pcm; assert(perturbative()!=2); if(perturbative()==1) { ShowerBasisPtr newBasis; // find the partner and its momentum if(!partner()) return; if(partner()->isFinalState()) { Lorentz5Momentum pa = -momentum()+partner()->momentum(); Lorentz5Momentum pb = momentum(); Energy scale=parent->momentum().t(); Lorentz5Momentum pbasis(ZERO,parent->momentum().vect().unit()*scale); Axis axis(pa.vect().unit()); LorentzRotation rot; double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); if(axis.perp2()>1e-20) { rot.setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); rot.rotateX(Constants::pi); } if(abs(1.-pa.e()/pa.vect().mag())>1e-6) rot.boostZ( pa.e()/pa.vect().mag()); pb *= rot; if(pb.perp2()/GeV2>1e-20) { Boost trans = -1./pb.e()*pb.vect(); trans.setZ(0.); rot.boost(trans); } pbasis *=rot; rot.invert(); n = rot*Lorentz5Momentum(ZERO,-pbasis.vect()); p = rot*Lorentz5Momentum(ZERO, pbasis.vect()); } else { pcm = parent->momentum(); p = Lorentz5Momentum(ZERO, pcm.vect()); n = Lorentz5Momentum(ZERO, -pcm.vect()); } newBasis = new_ptr(ShowerBasis()); newBasis->setBasis(p,n,ShowerBasis::BackToBack); showerBasis(newBasis,false); } else { showerBasis(dynamic_ptr_cast(children()[0])->showerBasis(),true); } } void ShowerParticle::initializeFinalState() { // set the basis vectors Lorentz5Momentum p,n; if(perturbative()!=0) { ShowerBasisPtr newBasis; // find the partner() and its momentum if(!partner()) return; Lorentz5Momentum ppartner(partner()->momentum()); // momentum of the emitting particle p = momentum(); Lorentz5Momentum pcm; // if the partner is a final-state particle then the reference // vector is along the partner in the rest frame of the pair if(partner()->isFinalState()) { Boost boost=(p + ppartner).findBoostToCM(); pcm = ppartner; pcm.boost(boost); n = Lorentz5Momentum(ZERO,pcm.vect()); n.boost( -boost); } else if(!partner()->isFinalState()) { // if the partner is an initial-state particle then the reference // vector is along the partner which should be massless if(perturbative()==1) { n = Lorentz5Momentum(ZERO,ppartner.vect()); } // if the partner is an initial-state decaying particle then the reference // vector is along the backwards direction in rest frame of decaying particle else { Boost boost=ppartner.findBoostToCM(); pcm = p; pcm.boost(boost); n = Lorentz5Momentum( ZERO, -pcm.vect()); n.boost( -boost); } } newBasis = new_ptr(ShowerBasis()); newBasis->setBasis(p,n,ShowerBasis::BackToBack); showerBasis(newBasis,false); } else if(initiatesTLS()) { showerBasis(dynamic_ptr_cast(parents()[0]->children()[0])->showerBasis(),true); } else { showerBasis(dynamic_ptr_cast(parents()[0])->showerBasis(),true); } } void ShowerParticle::setShowerMomentum(bool timeLike) { Energy m = this->mass() > ZERO ? this->mass() : this->data().mass(); // calculate the momentum of the assuming on-shell Energy2 pt2 = sqr(this->showerParameters().pt); double alpha = timeLike ? this->showerParameters().alpha : this->x(); double beta = 0.5*(sqr(m) + pt2 - sqr(alpha)*showerBasis()->pVector().m2())/(alpha*showerBasis()->p_dot_n()); Lorentz5Momentum porig=showerBasis()->sudakov2Momentum(alpha,beta, this->showerParameters().ptx, this->showerParameters().pty); porig.setMass(m); this->set5Momentum(porig); } diff --git a/Shower/QTilde/Base/ShowerTree.cc b/Shower/QTilde/Base/ShowerTree.cc --- a/Shower/QTilde/Base/ShowerTree.cc +++ b/Shower/QTilde/Base/ShowerTree.cc @@ -1,912 +1,913 @@ // -*- C++ -*- // // ShowerTree.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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. // #include "ThePEG/EventRecord/MultiColour.h" #include "ThePEG/Repository/EventGenerator.h" #include "ShowerTree.h" #include "Herwig/Shower/QTilde/Base/ShowerParticle.h" #include "Herwig/Shower/ShowerHandler.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/Handlers/EventHandler.h" #include "ThePEG/Handlers/XComb.h" #include #include "ThePEG/Repository/CurrentGenerator.h" #include "ThePEG/PDT/StandardMatchers.h" using namespace Herwig; using namespace ThePEG; bool ShowerTree::_spaceTime = false; Energy2 ShowerTree::_vmin2 = 0.1*GeV2; namespace { void findBeam(tPPtr & beam, PPtr incoming) { while(!beam->children().empty()) { bool found=false; for(unsigned int ix=0;ixchildren().size();++ix) { if(beam->children()[ix]==incoming) { found = true; break; } } if(found) break; beam = beam->children()[0]; } } } ShowerTree::ShowerTree(PerturbativeProcessPtr process) : _parent(), _hasShowered(false) { // get the incoming and outgoing particles and make copies vector original,copy; for(unsigned int ix=0;ixincoming().size();++ix) { original.push_back(process->incoming()[ix].first); copy .push_back(new_ptr(Particle(*original.back()))); } for(unsigned int ix=0;ixoutgoing().size();++ix) { original.push_back(process->outgoing()[ix].first); copy .push_back(new_ptr(Particle(*original.back()))); } // isolate the colour colourIsolate(original,copy); // hard process unsigned int itype(1); if(process->incoming().size()==2) { _wasHard = true; // set the beams and incoming particles tPPair beam = CurrentGenerator::current().currentEvent()->incoming(); findBeam(beam.first ,process->incoming()[0].first); findBeam(beam.second,process->incoming()[1].first); _incoming = make_pair(process->incoming()[0].first, process->incoming()[1].first); double x1(_incoming.first ->momentum().rho()/beam.first ->momentum().rho()); double x2(_incoming.second->momentum().rho()/beam.second->momentum().rho()); // must have two incoming particles assert(_incoming.first && _incoming.second); // set the parent tree _parent=ShowerTreePtr(); for(unsigned int ix=0;ix<2;++ix) { ShowerParticlePtr temp=new_ptr(ShowerParticle(*copy[ix],itype,false)); fixColour(temp); temp->x(ix==0 ? x1 : x2); _incomingLines.insert(make_pair(new_ptr(ShowerProgenitor(original[ix], copy[ix],temp)),temp)); } } // decay process else if(process->incoming().size()==1) { _wasHard = false; itype=2; // create the parent shower particle ShowerParticlePtr sparent(new_ptr(ShowerParticle(*copy[0],itype,false))); fixColour(sparent); _incomingLines.insert(make_pair(new_ptr(ShowerProgenitor(original[0],copy[0],sparent)) ,sparent)); // return if not decayed if(original.size()==1) return; } else assert(false); // create the children assert(copy.size() == original.size()); for (unsigned int ix=process->incoming().size();ixid()==progenitor->id(); } ShowerParticlePtr newpart; if(matches[0]&&matches[1]) { if(parent->showerKinematics()->z()>0.5) newpart=children[0]; else newpart=children[1]; } else if(matches[0]) newpart=children[0]; else if(matches[1]) newpart=children[1]; _outgoingLines[progenitor]=newpart; } void ShowerTree::updateInitialStateShowerProduct(ShowerProgenitorPtr progenitor, ShowerParticlePtr newParent) { _incomingLines[progenitor]=newParent; } void ShowerTree::insertHard(StepPtr pstep, bool ISR, bool) { assert(_incomingLines.size()==2); colourLines().clear(); map::const_iterator cit; // construct the map of colour lines for hard process for(cit=_incomingLines.begin();cit!=_incomingLines.end();++cit) { if(!cit->first->perturbative()) continue; mapColour(cit->first->original(),cit->first->copy()); } map::const_iterator cjt; for(cjt=_outgoingLines.begin();cjt!=_outgoingLines.end();++cjt) { if(!cjt->first->perturbative()) continue; mapColour(cjt->first->original(),cjt->first->copy()); } // initial-state radiation if(ISR) { for(cit=incomingLines().begin();cit!=incomingLines().end();++cit) { ShowerParticlePtr init=(*cit).first->progenitor(); assert(init->thePEGBase()); PPtr original = (*cit).first->original(); if(original->parents().empty()) continue; PPtr hadron= original->parents()[0]; assert(!original->children().empty()); PPtr copy=cit->first->copy(); ParticleVector intermediates=original->children(); for(unsigned int ix=0;ixabandonChild(intermediates[ix]); copy->abandonChild(intermediates[ix]); } // if not from a matrix element correction if(cit->first->perturbative()) { // break mother/daugther relations init->addChild(original); hadron->abandonChild(original); // if particle showers add shower if(cit->first->hasEmitted()) { addInitialStateShower(init,hadron,pstep,false); } // no showering for this particle else { updateColour(init,false); hadron->addChild(init); pstep->addIntermediate(init); init->setLifeLength(Lorentz5Distance()); init->setVertex(LorentzPoint()); } } // from matrix element correction else { // break mother/daugther relations hadron->abandonChild(original); copy->addChild(original); updateColour(copy,false); init->addChild(copy); pstep->addIntermediate(copy); copy->setLifeLength(Lorentz5Distance()); copy->setVertex(LorentzPoint()); // if particle showers add shower if(cit->first->hasEmitted()) { addInitialStateShower(init,hadron,pstep,false); } // no showering for this particle else { updateColour(init,false); hadron->addChild(init); pstep->addIntermediate(init); init->setLifeLength(Lorentz5Distance()); init->setVertex(LorentzPoint()); } } } } else { for(cit=incomingLines().begin();cit!=incomingLines().end();++cit) { ShowerParticlePtr init=(*cit).first->progenitor(); assert(init->thePEGBase()); PPtr original = (*cit).first->original(); if(original->parents().empty()) continue; PPtr hadron= original->parents()[0]; assert(!original->children().empty()); PPtr copy=cit->first->copy(); ParticleVector intermediates=original->children(); for(unsigned int ix=0;ixabandonChild(intermediates[ix]); copy->abandonChild(intermediates[ix]); } // break mother/daugther relations init->addChild(original); hadron->abandonChild(original); // no showering for this particle updateColour(init,false); hadron->addChild(init); pstep->addIntermediate(init); init->setLifeLength(Lorentz5Distance()); init->setVertex(LorentzPoint()); original->setLifeLength(Lorentz5Distance()); original->setVertex(LorentzPoint()); } } // final-state radiation for(cjt=outgoingLines().begin();cjt!=outgoingLines().end();++cjt) { ShowerParticlePtr init=(*cjt).first->progenitor(); assert(init->thePEGBase()); // ZERO the distance of original (*cjt).first->original()->setLifeLength(Lorentz5Distance()); (*cjt).first->original()->setVertex(LorentzPoint()); // if not from a matrix element correction if(cjt->first->perturbative()) { // register the shower particle as a // copy of the one from the hard process tParticleVector parents=init->parents(); for(unsigned int ix=0;ixabandonChild(init); (*cjt).first->original()->addChild(init); pstep->addDecayProduct(init); } // from a matrix element correction else { if(cjt->first->original()==_incoming.first|| cjt->first->original()==_incoming.second) { updateColour((*cjt).first->copy(),false); (*cjt).first->original()->parents()[0]-> addChild((*cjt).first->copy()); pstep->addDecayProduct((*cjt).first->copy()); (*cjt).first->copy()->addChild(init); pstep->addDecayProduct(init); } else { updateColour((*cjt).first->copy(),false); (*cjt).first->original()->addChild((*cjt).first->copy()); pstep->addDecayProduct((*cjt).first->copy()); (*cjt).first->copy()->addChild(init); pstep->addDecayProduct(init); } // ZERO the distance of copy ??? \todo change if add space-time (*cjt).first->copy()->setLifeLength(Lorentz5Distance()); (*cjt).first->copy()->setVertex(LorentzPoint()); } // copy so travels no distance init->setLifeLength(Lorentz5Distance()); init->setVertex(init->parents()[0]->decayVertex()); // sort out the colour updateColour(init,false); // insert shower products addFinalStateShower(init,pstep); } colourLines().clear(); } void ShowerTree::addFinalStateShower(PPtr p, StepPtr s) { // if endpoint assume doesn't travel if(p->children().empty()) { if(p->dataPtr()->stable()||ShowerHandler::currentHandler()->decaysInShower(p->id())) p->setLifeLength(Lorentz5Distance()); else { - Length ctau = p->dataPtr()->generateLifeTime(p->mass(), p->dataPtr()->width()); - Lorentz5Distance lifeLength(ctau,p->momentum().vect()*(ctau/p->mass())); + Energy mass = p->mass()!=ZERO ? p->mass() : p->dataPtr()->mass(); + Length ctau = p->dataPtr()->generateLifeTime(mass, p->dataPtr()->width()); + Lorentz5Distance lifeLength(ctau,p->momentum().vect()*(ctau/mass)); p->setLifeLength(lifeLength); } return; } // set the space-time distance else { p->setLifeLength(spaceTimeDistance(p)); } ParticleVector::const_iterator child; for(child=p->children().begin(); child != p->children().end(); ++child) { updateColour(*child,false); s->addDecayProduct(*child); (**child).setVertex(p->decayVertex()); addFinalStateShower(*child,s); } } void ShowerTree::addInitialStateShower(PPtr p, PPtr hadron, StepPtr s, bool addchildren) { // Each parton here should only have one parent if(!p->parents().empty()) { if(p->parents().size()!=1) throw Exception() << "Particle must only have one parent in ShowerTree" << "::addInitialStateShower" << Exception::runerror; // set the space-time distances if(addchildren) { p->setLifeLength(spaceTimeDistance(p)); p->setVertex(p->children()[0]->vertex()-p->lifeLength()); } else { p->setLifeLength(spaceTimeDistance(p)); p->setVertex(-p->lifeLength()); } // recurse addInitialStateShower(p->parents()[0],hadron,s); } else { hadron->addChild(p); s->addIntermediate(p); p->setVertex(p->children()[0]->vertex()); p->setLifeLength(Lorentz5Distance()); } updateColour(p,false); // if not adding children return if(!addchildren) return; // add children ParticleVector::const_iterator child; for(child = p->children().begin(); child != p->children().end(); ++child) { // if a final-state particle update the colour ShowerParticlePtr schild = dynamic_ptr_cast(*child); (**child).setVertex(p->decayVertex()); if(schild && schild->isFinalState()) updateColour(*child,false); // if there are grandchildren of p if(!(*child)->children().empty()) { // Add child as intermediate s->addIntermediate(*child); // If child is shower particle and final-state, add children if(schild && schild->isFinalState()) addFinalStateShower(schild,s); } else s->addDecayProduct(*child); } } void ShowerTree::update(PerturbativeProcessPtr newProcess) { // must be one incoming particle assert(_incomingLines.size()==1); colourLines().clear(); // copy the particles and isolate the colour vector original,copy; for(unsigned int ix=0;ixincoming().size();++ix) { original.push_back(newProcess->incoming()[ix].first); copy .push_back(new_ptr(Particle(*original.back()))); } for(unsigned int ix=0;ixoutgoing().size();++ix) { original.push_back(newProcess->outgoing()[ix].first); copy .push_back(new_ptr(Particle(*original.back()))); } // isolate the colour colourIsolate(original,copy); // make the new progenitor ShowerParticlePtr stemp=new_ptr(ShowerParticle(*copy[0],2,false)); fixColour(stemp); ShowerProgenitorPtr newprog=new_ptr(ShowerProgenitor(original[0],copy[0],stemp)); _incomingLines.clear(); _incomingLines.insert(make_pair(newprog,stemp)); // create the children assert(copy.size() == original.size()); for (unsigned int ix=newProcess->incoming().size();ix_treelinks.empty()) final = _parent->_treelinks[this].second; else final=_incomingLines.begin()->first->original(); // construct the map of colour lines PPtr copy=_incomingLines.begin()->first->copy(); mapColour(final,copy); // now this is the ONE instance of the particle which should have a life length // \todo change if space-time picture added // set the lifelength, need this so that still in right direction after // any ISR recoils Length ctau = copy->lifeTime(); Lorentz5Distance lifeLength(ctau,final->momentum().vect()*(ctau/final->mass())); final->setLifeLength(lifeLength); // initial-state radiation if(ISR&&!_incomingLines.begin()->first->progenitor()->children().empty()) { ShowerParticlePtr init=_incomingLines.begin()->first->progenitor(); updateColour(init,false); final->addChild(init); pstep->addDecayProduct(init); // just a copy doesn't travel init->setLifeLength(Lorentz5Distance()); init->setVertex(final->decayVertex()); // insert shower products addFinalStateShower(init,pstep); // sort out colour final=_incomingLines.begin()->second; colourLines().clear(); mapColour(final,copy); } // get the decaying particles // make the copy tColinePair cline=make_pair(copy->colourLine(),copy->antiColourLine()); updateColour(copy,false); // sort out sinks and sources if needed if(cline.first) { if(cline.first->sourceNeighbours().first) { copy->colourLine()->setSourceNeighbours(cline.first->sourceNeighbours().first, cline.first->sourceNeighbours().second); } else if (cline.first->sinkNeighbours().first) { copy->colourLine()->setSinkNeighbours(cline.first->sinkNeighbours().first, cline.first->sinkNeighbours().second); } } if(cline.second) { if(cline.second->sourceNeighbours().first) { copy->antiColourLine()->setSourceNeighbours(cline.second->sourceNeighbours().first, cline.second->sourceNeighbours().second); } else if (cline.second->sinkNeighbours().first) { copy->antiColourLine()->setSinkNeighbours(cline.second->sinkNeighbours().first, cline.second->sinkNeighbours().second); } } // copy of the one from the hard process tParticleVector dpar=copy->parents(); for(unsigned int ix=0;ixabandonChild(copy); final->addChild(copy); pstep->addDecayProduct(copy); // just a copy does not move copy->setLifeLength(Lorentz5Distance()); copy->setVertex(final->decayVertex()); // final-state radiation map::const_iterator cit; for(cit=outgoingLines().begin();cit!=outgoingLines().end();++cit) { ShowerParticlePtr init=cit->first->progenitor(); // ZERO the distance init->setLifeLength(Lorentz5Distance()); if(!init->thePEGBase()) throw Exception() << "Final-state particle must have a ThePEGBase" << " in ShowerTree::insertDecay()" << Exception::runerror; // if not from matrix element correction if(cit->first->perturbative()) { // add the child updateColour(cit->first->copy(),false); PPtr orig=cit->first->original(); orig->setLifeLength(Lorentz5Distance()); orig->setVertex(copy->decayVertex()); copy->addChild(orig); pstep->addDecayProduct(orig); orig->addChild(cit->first->copy()); pstep->addDecayProduct(cit->first->copy()); // register the shower particle as a // copy of the one from the hard process tParticleVector parents=init->parents(); for(unsigned int ix=0;ixabandonChild(init);} (*cit).first->copy()->addChild(init); pstep->addDecayProduct(init); updateColour(init,false); } // from a matrix element correction else { if(copy->children().end()== find(copy->children().begin(),copy->children().end(), cit->first->original())) { updateColour(cit->first->original(),false); copy->addChild(cit->first->original()); pstep->addDecayProduct(cit->first->original()); } updateColour(cit->first->copy(),false); cit->first->original()->addChild(cit->first->copy()); pstep->addDecayProduct(cit->first->copy()); // register the shower particle as a // copy of the one from the hard process tParticleVector parents=init->parents(); for(unsigned int ix=0;ixabandonChild(init);} (*cit).first->copy()->addChild(init); pstep->addDecayProduct(init); updateColour(init,false); } // ZERO the distances as just copies cit->first->copy()->setLifeLength(Lorentz5Distance()); init->setLifeLength(Lorentz5Distance()); cit->first->copy()->setVertex(copy->decayVertex()); init->setVertex(copy->decayVertex()); // insert shower products addFinalStateShower(init,pstep); } colourLines().clear(); } void ShowerTree::clear() { // reset the has showered flag _hasShowered=false; // clear the colour map colourLines().clear(); map::const_iterator cit; map::const_iterator cjt; // abandon the children of the outgoing particles for(cit=_outgoingLines.begin();cit!=_outgoingLines.end();++cit) { ShowerParticlePtr orig=cit->first->progenitor(); orig->set5Momentum(cit->first->copy()->momentum()); ParticleVector children=orig->children(); for(unsigned int ix=0;ixabandonChild(children[ix]); _outgoingLines[cit->first]=orig; cit->first->hasEmitted(false); cit->first->reconstructed(ShowerProgenitor::notReconstructed); } // forward products _forward.clear(); for(cit=_outgoingLines.begin();cit!=_outgoingLines.end();++cit) _forward.insert(cit->first->progenitor()); // if a decay if(!_wasHard) { ShowerParticlePtr orig=_incomingLines.begin()->first->progenitor(); orig->set5Momentum(_incomingLines.begin()->first->copy()->momentum()); ParticleVector children=orig->children(); for(unsigned int ix=0;ixabandonChild(children[ix]); _incomingLines.begin()->first->reconstructed(ShowerProgenitor::notReconstructed); } // if a hard process else { for(cjt=_incomingLines.begin();cjt!=_incomingLines.end();++cjt) { tPPtr parent = cjt->first->original()->parents().empty() ? tPPtr() : cjt->first->original()->parents()[0]; ShowerParticlePtr temp= new_ptr(ShowerParticle(*cjt->first->copy(), cjt->first->progenitor()->perturbative(), cjt->first->progenitor()->isFinalState())); fixColour(temp); temp->x(cjt->first->progenitor()->x()); cjt->first->hasEmitted(false); if(!(cjt->first->progenitor()==cjt->second)&&cjt->second&&parent) parent->abandonChild(cjt->second); cjt->first->progenitor(temp); _incomingLines[cjt->first]=temp; cjt->first->reconstructed(ShowerProgenitor::notReconstructed); } } clearTransforms(); } void ShowerTree::resetShowerProducts() { map::const_iterator cit; map::const_iterator cjt; _forward.clear(); for(cjt=_outgoingLines.begin();cjt!=_outgoingLines.end();++cjt) _forward.insert(cjt->second); } void ShowerTree::updateAfterShower(ShowerDecayMap & decay) { // update the links map::const_iterator mit; map >::iterator tit; for(tit=_treelinks.begin();tit!=_treelinks.end();++tit) { if(tit->second.first) { mit=_outgoingLines.find(tit->second.first); if(mit!=_outgoingLines.end()) tit->second.second=mit->second; } } // get the particles coming from those in the hard process set hard; for(mit=_outgoingLines.begin();mit!=_outgoingLines.end();++mit) hard.insert(mit->second); // find the shower particles which should be decayed in the // shower but didn't come from the hard process set::const_iterator cit; // TODO construct _forward here? for(cit=_forward.begin();cit!=_forward.end();++cit) { if((ShowerHandler::currentHandler()->decaysInShower((**cit).id())&& !(**cit).dataPtr()->stable()) && hard.find(*cit)==hard.end()) { PerturbativeProcessPtr newProcess(new_ptr(PerturbativeProcess())); newProcess->incoming().push_back(make_pair(*cit,PerturbativeProcessPtr())); ShowerTreePtr newtree=new_ptr(ShowerTree(newProcess)); newtree->setParents(); newtree->_parent=this; Energy width=(**cit).dataPtr()->generateWidth((**cit).mass()); decay.insert(make_pair(width,newtree)); _treelinks.insert(make_pair(newtree, make_pair(tShowerProgenitorPtr(),*cit))); } } } void ShowerTree::addFinalStateBranching(ShowerParticlePtr parent, const ShowerParticleVector & children) { assert(children.size()==2); _forward.erase(parent); for(unsigned int ix=0; ix >::const_iterator tit; for(tit=_treelinks.begin();tit!=_treelinks.end();++tit) tit->first->_parent=this; } vector ShowerTree::extractProgenitors() { // extract the particles from the ShowerTree map::const_iterator mit; vector ShowerHardJets; for(mit=incomingLines().begin();mit!=incomingLines().end();++mit) ShowerHardJets.push_back((*mit).first); map::const_iterator mjt; for(mjt=outgoingLines().begin();mjt!=outgoingLines().end();++mjt) ShowerHardJets.push_back((*mjt).first); return ShowerHardJets; } void ShowerTree::transform(const LorentzRotation & boost, bool applyNow) { if(applyNow) { // now boost all the particles map::const_iterator cit; // incoming for(cit=_incomingLines.begin();cit!=_incomingLines.end();++cit) { cit->first->progenitor()->deepTransform(boost); cit->first->copy()->deepTransform(boost); } // outgoing map::const_iterator cjt; for(cjt=_outgoingLines.begin();cjt!=_outgoingLines.end();++cjt) { cjt->first->progenitor()->deepTransform(boost); cjt->first->copy()->deepTransform(boost); } } else { _transforms.transform(boost); } // child trees for(map >::const_iterator tit=_treelinks.begin();tit!=_treelinks.end();++tit) tit->first->transform(boost,applyNow); } void ShowerTree::applyTransforms() { // now boost all the particles map::const_iterator cit; // incoming for(cit=_incomingLines.begin();cit!=_incomingLines.end();++cit) { cit->first->progenitor()->deepTransform(_transforms); cit->first->copy()->deepTransform(_transforms); } // outgoing map::const_iterator cjt; for(cjt=_outgoingLines.begin();cjt!=_outgoingLines.end();++cjt) { cjt->first->progenitor()->deepTransform(_transforms); cjt->first->copy()->deepTransform(_transforms); } // child trees for(map >::const_iterator tit=_treelinks.begin();tit!=_treelinks.end();++tit) tit->first->applyTransforms(); _transforms = LorentzRotation(); } void ShowerTree::clearTransforms() { _transforms = LorentzRotation(); // // child trees // for(map >::const_iterator // tit=_treelinks.begin();tit!=_treelinks.end();++tit) // tit->first->clearTransforms(); } void ShowerTree::fixColour(tShowerParticlePtr part) { if(!part->colourInfo()->colourLines().empty()) { if(part->colourInfo()->colourLines().size()==1) { ColinePtr line=part->colourLine(); if(line) { line->removeColoured(part); line->addColoured(part); } } else { Ptr::pointer colour = dynamic_ptr_cast::pointer>(part->colourInfo()); vector lines = colour->colourLines(); for(unsigned int ix=0;ix(lines[ix]); if(line) { line->removeColoured(part); line->addColoured(part); } } } } if(!part->colourInfo()->antiColourLines().empty()) { if(part->colourInfo()->antiColourLines().size()==1) { ColinePtr line=part->antiColourLine(); if(line) { line->removeAntiColoured(part); line->addAntiColoured(part); } } else { Ptr::pointer colour = dynamic_ptr_cast::pointer>(part->colourInfo()); vector lines = colour->antiColourLines(); for(unsigned int ix=0;ix(lines[ix]); if(line) { line->removeAntiColoured(part); line->addAntiColoured(part); } } } } } vector ShowerTree::extractProgenitorParticles() { vector particles; // incoming particles for(map::const_iterator cit=incomingLines().begin(); cit!=incomingLines().end();++cit) particles.push_back(cit->first->progenitor()); // outgoing particles for(map::const_iterator cjt=outgoingLines().begin(); cjt!=outgoingLines().end();++cjt) particles.push_back(cjt->first->progenitor()); return particles; } Lorentz5Distance ShowerTree::spaceTimeDistance(tPPtr particle) { if(!_spaceTime) return Lorentz5Distance(); Energy2 q2 = particle->mass() > ZERO ? sqr(particle->mass()) : -sqr(particle->mass()); const tcPDPtr data = particle->dataPtr(); // calculate width imposing min value Energy conMass = max(data->constituentMass(),200*MeV); Energy width = max(data->generateWidth(particle->mass()),_vmin2/conMass); // offshellness Energy2 offShell = q2-sqr(data->constituentMass()); if(abs(offShell)<1e-10*GeV2) offShell = ZERO; InvEnergy2 fact = UseRandom::rndExp(1./sqrt((sqr(offShell)+sqr(q2*width/conMass)))); Lorentz5Distance output = (hbarc*fact)*particle->momentum(); return output; } void ShowerTree::constructTrees(ShowerTreePtr & hardTree, ShowerDecayMap & decayTrees, PerturbativeProcessPtr hard, DecayProcessMap decay) { map treeMap; // convert the hard process if(hardTree) { if(hardTree->isDecay()) hardTree->update(hard); } else { hardTree = new_ptr(ShowerTree(hard)); } treeMap.insert(make_pair(hard,hardTree)); for(DecayProcessMap::const_iterator it=decay.begin();it!=decay.end();++it) { ShowerTreePtr newTree = new_ptr(ShowerTree(it->second)); treeMap.insert(make_pair(it->second,newTree)); decayTrees.insert(make_pair(it->first,newTree)); } // set up the links between the trees for(map::const_iterator it=treeMap.begin(); it!=treeMap.end();++it) { // links to daughter trees map::const_iterator mit; for(mit=it->second->_outgoingLines.begin(); mit!=it->second->_outgoingLines.end();++mit) { unsigned int iloc=0; for(;ilocfirst->outgoing().size();++iloc) { if(it->first->outgoing()[iloc].first==mit->first->original()) break; } if(it->first->outgoing()[iloc].second) it->second->_treelinks.insert(make_pair(treeMap[it->first->outgoing()[iloc].second], make_pair(mit->first,mit->first->progenitor()))); } // links to parent trees if(it->first->incoming()[0].second) { it->second->_parent = treeMap[it->first->incoming()[0].second]; } } } namespace { Lorentz5Momentum sumMomenta(tPPtr particle) { if(particle->children().empty()) return particle->momentum(); Lorentz5Momentum output; for(unsigned int ix=0;ixchildren().size();++ix) { output += sumMomenta(particle->children()[ix]); } return output; } } void ShowerTree::checkMomenta() { vector pin; for(map::const_iterator it=_incomingLines.begin(); it!=_incomingLines.end();++it) { if(isDecay()) { tPPtr parent = it->first->progenitor(); pin.push_back(parent->momentum()); while(!parent->children().empty()) { pin.back() -= sumMomenta(parent->children()[1]); parent = parent->children()[0]; } } else { tPPtr parent = it->second; pin.push_back(parent->momentum()); while(!parent->children().empty()&&parent->children().size()==2) { pin.back() -= sumMomenta(parent->children()[1]); parent = parent->children()[0]; if(parent==it->first->progenitor()) break; } } } vector pout; for(map::const_iterator it= _outgoingLines.begin(); it!=_outgoingLines.end();++it) { pout.push_back(sumMomenta(it->first->progenitor())); } Lorentz5Momentum psum; for(unsigned int ix=0;ix< pin.size();++ix) { CurrentGenerator::log() << "pin " << ix << pin[ix]/GeV << "\n"; psum +=pin[ix]; } CurrentGenerator::log() << "In total " << psum/GeV << " " << psum.m()/GeV << "\n"; Lorentz5Momentum psum2; for(unsigned int ix=0;ix< pout.size();++ix) { CurrentGenerator::log() << "pout " << ix << pout[ix]/GeV << "\n"; psum2 +=pout[ix]; } CurrentGenerator::log() << "Out total " << psum2/GeV << " " << psum2.m()/GeV << "\n"; CurrentGenerator::log() << "Total " << (psum-psum2)/GeV << "\n"; } RealEmissionProcessPtr ShowerTree::perturbativeProcess() { RealEmissionProcessPtr output(new_ptr(RealEmissionProcess())); // add the incoming particles unsigned int ix=0; pair x; for(map::const_iterator it=_incomingLines.begin(); it!=_incomingLines.end();++it) { output->bornIncoming().push_back(it->first->progenitor()); if(!it->first->original()->parents().empty()) output->hadrons().push_back(it->first->original()->parents()[0]); else output->hadrons().push_back(it->first->progenitor()); if(ix==0) x.first = it->second->x(); else x.second = it->second->x(); ++ix; } output->x(x); // add the outgoing particles for(map::const_iterator it= _outgoingLines.begin(); it!=_outgoingLines.end();++it) { output->bornOutgoing().push_back(it->first->progenitor()); } return output; } void ShowerTree::setVetoes(const map & pTs, unsigned int type) { if(type==1||type==3) { for(map::const_iterator it=_incomingLines.begin(); it!=_incomingLines.end();++it) { for(map::const_iterator jt=pTs.begin();jt!=pTs.end();++jt) it->first->maximumpT(jt->second,jt->first); } } if(type==2||type==3) { for(map::const_iterator it= _outgoingLines.begin(); it!=_outgoingLines.end();++it) { for(map::const_iterator jt=pTs.begin();jt!=pTs.end();++jt) it->first->maximumpT(jt->second,jt->first); } } } diff --git a/Shower/QTilde/Couplings/ShowerAlphaQCD.cc b/Shower/QTilde/Couplings/ShowerAlphaQCD.cc --- a/Shower/QTilde/Couplings/ShowerAlphaQCD.cc +++ b/Shower/QTilde/Couplings/ShowerAlphaQCD.cc @@ -1,383 +1,383 @@ // -*- C++ -*- // // ShowerAlphaQCD.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 ShowerAlphaQCD class. // #include "ShowerAlphaQCD.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/ParVector.h" #include "ThePEG/Interface/Command.h" #include "ThePEG/Interface/Deleted.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Utilities/Throw.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Config/Constants.h" #include "Herwig/Utilities/AlphaS.h" using namespace Herwig; using Herwig::Math::alphaS; using Herwig::Math::derivativeAlphaS; DescribeClass describeShowerAlphaQCD("Herwig::ShowerAlphaQCD","HwShower.so"); IBPtr ShowerAlphaQCD::clone() const { return new_ptr(*this); } IBPtr ShowerAlphaQCD::fullclone() const { return new_ptr(*this); } void ShowerAlphaQCD::persistentOutput(PersistentOStream & os) const { os << _asType << _asMaxNP << ounit(_qmin,GeV) << _nloop << _thresopt << _alphain << _tolerance << _maxtry << _alphamin << ounit(_thresholds,GeV) << ounit(_lambda,GeV) << _val0 << ounit(_optInputScale,GeV) << ounit(_quarkMasses,GeV); } void ShowerAlphaQCD::persistentInput(PersistentIStream & is, int) { is >> _asType >> _asMaxNP >> iunit(_qmin,GeV) >> _nloop >> _thresopt >> _alphain >> _tolerance >> _maxtry >> _alphamin >> iunit(_thresholds,GeV) >> iunit(_lambda,GeV) >> _val0 >> iunit(_optInputScale,GeV) >> iunit(_quarkMasses,GeV); } void ShowerAlphaQCD::Init() { static ClassDocumentation documentation ("This (concrete) class describes the QCD alpha running."); static Switch intAsType ("NPAlphaS", "Behaviour of AlphaS in the NP region", &ShowerAlphaQCD::_asType, 1, false, false); static SwitchOption intAsTypeZero (intAsType, "Zero","zero below Q_min", 1); static SwitchOption intAsTypeConst (intAsType, "Const","const as(qmin) below Q_min", 2); static SwitchOption intAsTypeLin (intAsType, "Linear","growing linearly below Q_min", 3); static SwitchOption intAsTypeQuad (intAsType, "Quadratic","growing quadratically below Q_min", 4); static SwitchOption intAsTypeExx1 (intAsType, "Exx1", "quadratic from AlphaMaxNP down to as(Q_min)", 5); static SwitchOption intAsTypeExx2 (intAsType, "Exx2", "const = AlphaMaxNP below Q_min", 6); // default such that as(qmin) = 1 in the current parametrization. // min = Lambda3 static Parameter intQmin ("Qmin", "Q < Qmin is treated with NP parametrization as of (unit [GeV])," " if negative it is solved for at initialisation such that alpha_S(Qmin)=AlphaMaxNP", &ShowerAlphaQCD::_qmin, GeV, 0.630882*GeV, 0.330445*GeV, 100.0*GeV,false,false,false); static Parameter interfaceAlphaMaxNP ("AlphaMaxNP", "Max value of alpha in NP region, only relevant if NPAlphaS = 5,6", &ShowerAlphaQCD::_asMaxNP, 1.0, 0., 100.0, false, false, Interface::limited); static Parameter interfaceNumberOfLoops ("NumberOfLoops", "The number of loops to use in the alpha_S calculation", &ShowerAlphaQCD::_nloop, 3, 1, 3, false, false, Interface::limited); static Deleted delInputOption ("InputOption", "The old default (1) is now the only choice"); static Deleted delAlphaMZ ("AlphaMZ", "Renamed to AlphaIn."); static Parameter interfaceAlphaMZ ("AlphaIn", "The input value of the strong coupling at the chosen InputScale (default: MZ)", &ShowerAlphaQCD::_alphain, 0.118, 0.1, 0.2, false, false, Interface::limited); static Parameter interfaceTolerance ("Tolerance", "The tolerance for discontinuities in alphaS at thresholds.", &ShowerAlphaQCD::_tolerance, 1e-10, 1e-20, 1e-4, false, false, Interface::limited); static Parameter interfaceMaximumIterations ("MaximumIterations", "The maximum number of iterations for the Newton-Raphson method to converge.", &ShowerAlphaQCD::_maxtry, 100, 10, 1000, false, false, Interface::limited); static Switch interfaceThresholdOption ("ThresholdOption", "Whether to use the consistuent or normal masses for the thresholds", &ShowerAlphaQCD::_thresopt, true, false, false); static SwitchOption interfaceThresholdOptionCurrent (interfaceThresholdOption, "Current", "Use the current masses", true); static SwitchOption interfaceThresholdOptionConstituent (interfaceThresholdOption, "Constituent", "Use the constitent masses.", false); static Command interfaceValue ("Value", "", &ShowerAlphaQCD::value, false); static Command interfacecheck ("check", "check", &ShowerAlphaQCD::check, false); static Parameter interfaceInputScale ("InputScale", "An optional input scale. MZ will be used if not set.", &ShowerAlphaQCD::_optInputScale, GeV, 91.1876_GeV, ZERO, 0*GeV, false, false, Interface::lowerlim); static ParVector interfaceQuarkMasses ("QuarkMasses", "The quark masses to be used instead of the masses set in the particle data.", &ShowerAlphaQCD::_quarkMasses, GeV, -1, 0.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); } void ShowerAlphaQCD::doinit() { ShowerAlpha::doinit(); // calculate the value of 5-flavour lambda // evaluate the initial // value of Lambda from alphas if needed using Newton-Raphson _lambda[2]=computeLambda(_optInputScale,_alphain,5); // compute the threshold matching // top threshold for(int ix=1;ix<4;++ix) { if ( _quarkMasses.empty() ) { if(_thresopt) _thresholds[ix]=getParticleData(ix+3)->mass(); else _thresholds[ix]=getParticleData(ix+3)->constituentMass(); } else { // starting at zero rather than one, cf the other alphas's _thresholds[ix] = _quarkMasses[ix+2]; } } // compute 6 flavour lambda by matching at top mass using Newton Raphson _lambda[3]=computeLambda(_thresholds[3],alphaS(_thresholds[3],_lambda[2],5,_nloop),6); // bottom threshold // compute 4 flavour lambda by matching at bottom mass using Newton Raphson _lambda[1]=computeLambda(_thresholds[2],alphaS(_thresholds[2],_lambda[2],5,_nloop),4); // charm threshold // compute 3 flavour lambda by matching at charm mass using Newton Raphson _lambda[0]=computeLambda(_thresholds[1],alphaS(_thresholds[1],_lambda[1],4,_nloop),3); // if qmin less than zero solve for alphaS(_qmin) = 1. if(_qmin() << "The value of Qmin is less than Lambda_3 in" << " ShowerAlphaQCD::doinit " << Exception::abortnow; Energy high = 10*GeV; while (value(sqr(high))>_asMaxNP) high *=2.; double as; do { _qmin = 0.5*(low+high); as = value(sqr(_qmin)); if(_asMaxNP>as) high = _qmin; else if(_asMaxNP _tolerance ); } // final threshold is qmin _thresholds[0]=_qmin; // value of alphaS at threshold pair nflam = getLamNfTwoLoop(_qmin); _val0 = alphaS(_qmin, nflam.second, nflam.first, _nloop); // compute the maximum value of as if ( _asType < 5 ) _alphamin = _val0; else _alphamin = max(_asMaxNP, _val0); // check consistency lambda_3 < qmin if(_lambda[0]>_qmin) Throw() << "The value of Qmin is less than Lambda_3 in" << " ShowerAlphaQCD::doinit " << Exception::abortnow; } string ShowerAlphaQCD::check(string args) { doinit(); istringstream argin(args); double Q_low, Q_high; long n_steps; argin >> Q_low >> Q_high >> n_steps; string fname; argin >> fname; - generator()->log() << "checking alpha_s in range [" << Q_low << "," << Q_high << "] GeV in " - << n_steps << " steps.\nResults are written to " << fname << "\n"; + Repository::clog() << "checking alpha_s in range [" << Q_low << "," << Q_high << "] GeV in " + << n_steps << " steps.\nResults are written to " << fname << "\n"; double step_width = (Q_high-Q_low)/n_steps; ofstream out (fname.c_str()); for (long k = 0; k <= n_steps; ++k) { Energy Q = Q_low*GeV + k*step_width*GeV; out << (Q/GeV) << " " << value(Q*Q) << "\n"; } return "alpha_s check finished"; } double ShowerAlphaQCD::value(const Energy2 scale) const { Energy q = scaleFactor()*sqrt(scale); double val(0.); // normal case if (q >= _qmin) { pair nflam = getLamNfTwoLoop(q); val = alphaS(q, nflam.second, nflam.first, _nloop); } // special handling if the scale is less than Qmin else { switch (_asType) { case 1: // flat, zero; the default type with no NP effects. val = 0.; break; case 2: // flat, non-zero alpha_s = alpha_s(q2min). val = _val0; break; case 3: // linear in q val = _val0*q/_qmin; break; case 4: // quadratic in q val = _val0*sqr(q/_qmin); break; case 5: // quadratic in q, starting off at asMaxNP, ending on as(qmin) val = (_val0 - _asMaxNP)*sqr(q/_qmin) + _asMaxNP; break; case 6: // just asMaxNP and constant val = _asMaxNP; break; } } return val; } double ShowerAlphaQCD::overestimateValue() const { return _alphamin; } double ShowerAlphaQCD::ratio(const Energy2 scale, double factor) const { Energy q = scaleFactor()*factor*sqrt(scale); double val(0.); // normal case if (q >= _qmin) { pair nflam = getLamNfTwoLoop(q); val = alphaS(q, nflam.second, nflam.first, _nloop); } // special handling if the scale is less than Qmin else { switch (_asType) { case 1: // flat, zero; the default type with no NP effects. val = 0.; break; case 2: // flat, non-zero alpha_s = alpha_s(q2min). val = _val0; break; case 3: // linear in q val = _val0*q/_qmin; break; case 4: // quadratic in q val = _val0*sqr(q/_qmin); break; case 5: // quadratic in q, starting off at asMaxNP, ending on as(qmin) val = (_val0 - _asMaxNP)*sqr(q/_qmin) + _asMaxNP; break; case 6: // just asMaxNP and constant val = _asMaxNP; break; } } // denominator return val/_alphamin; } string ShowerAlphaQCD::value (string scale) { istringstream readscale(scale); double inScale; readscale >> inScale; Energy theScale = inScale * GeV; initialize(); ostringstream showvalue (""); showvalue << "alpha_s (" << theScale/GeV << " GeV) = " << value (sqr(theScale)); return showvalue.str(); } pair ShowerAlphaQCD::getLamNfTwoLoop(Energy q) const { short nf = 6; // get lambda and nf according to the thresholds if (q < _thresholds[1]) nf = 3; else if (q < _thresholds[2]) nf = 4; else if (q < _thresholds[3]) nf = 5; return pair(nf, _lambda[nf-3]); } Energy ShowerAlphaQCD::computeLambda(Energy match, double alpha, unsigned int nflav) const { Energy lamtest=200.0*MeV; double xtest; unsigned int ntry=0; do { ++ntry; xtest = log(sqr(match/lamtest)); xtest += (alpha-alphaS(match,lamtest,nflav,_nloop))/derivativeAlphaS(match,lamtest,nflav,_nloop); Energy newLambda = match/exp(0.5*xtest); lamtest = newLambda _tolerance && ntry < _maxtry); return lamtest; } diff --git a/Shower/QTilde/Kinematics/KinematicsReconstructor.cc b/Shower/QTilde/Kinematics/KinematicsReconstructor.cc --- a/Shower/QTilde/Kinematics/KinematicsReconstructor.cc +++ b/Shower/QTilde/Kinematics/KinematicsReconstructor.cc @@ -1,2942 +1,2942 @@ // -*- C++ -*- // // KinematicsReconstructor.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 KinematicsReconstructor class. // #include "KinematicsReconstructor.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/EventRecord/Event.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/RefVector.h" #include "Herwig/Shower/QTilde/Base/PartnerFinder.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/Shower/QTilde/SplittingFunctions/SplittingFunction.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/EventRecord/ColourLine.h" #include "ThePEG/Utilities/DescribeClass.h" #include "Herwig/Shower/QTilde/QTildeShowerHandler.h" #include using namespace Herwig; DescribeClass describeKinematicsReconstructor("Herwig::KinematicsReconstructor", "HwShower.so"); namespace { /** * Struct to order the jets in off-shellness */ struct JetOrdering { bool operator() (const JetKinStruct & j1, const JetKinStruct & j2) { Energy diff1 = j1.q.m()-j1.p.m(); Energy diff2 = j2.q.m()-j2.p.m(); if(diff1!=diff2) { return diff1>diff2; } else if( j1.q.e() != j2.q.e() ) return j1.q.e()>j2.q.e(); else return j1.parent->uniqueId>j2.parent->uniqueId; } }; } void KinematicsReconstructor::persistentOutput(PersistentOStream & os) const { os << _reconopt << _initialBoost << ounit(_minQ,GeV) << _noRescale << _noRescaleVector << _finalStateReconOption << _initialStateReconOption; } void KinematicsReconstructor::persistentInput(PersistentIStream & is, int) { is >> _reconopt >> _initialBoost >> iunit(_minQ,GeV) >> _noRescale >> _noRescaleVector >> _finalStateReconOption >> _initialStateReconOption; } void KinematicsReconstructor::Init() { static ClassDocumentation documentation ( "This class is responsible for the kinematics reconstruction of the showering,", " including the kinematics reshuffling necessary to compensate for the recoil" "of the emissions." ); static Switch interfaceReconstructionOption ("ReconstructionOption", "Option for the kinematics reconstruction", &KinematicsReconstructor::_reconopt, 0, false, false); static SwitchOption interfaceReconstructionOptionGeneral (interfaceReconstructionOption, "General", "Use the general solution which ignores the colour structure for all processes", 0); static SwitchOption interfaceReconstructionOptionColour (interfaceReconstructionOption, "Colour", "Use the colour structure of the process to determine the reconstruction procedure.", 1); static SwitchOption interfaceReconstructionOptionColour2 (interfaceReconstructionOption, "Colour2", "Make the most use possible of the colour structure of the process to determine the reconstruction procedure. " "Start with FF, then IF then II colour connections", 2); static SwitchOption interfaceReconstructionOptionColour3 (interfaceReconstructionOption, "Colour3", "Make the most use possible of the colour structure of the process to determine the reconstruction procedure. " "Do the colour connections in order of the pT's emitted in the shower starting with the hardest." " The colour partner is fully reconstructed at the same time.", 3); static SwitchOption interfaceReconstructionOptionColour4 (interfaceReconstructionOption, "Colour4", "Make the most use possible of the colour structure of the process to determine the reconstruction procedure. " "Do the colour connections in order of the pT's emitted in the shower starting with the hardest, while leaving" " the colour partner on mass-shell", 4); static Parameter interfaceMinimumQ2 ("MinimumQ2", "The minimum Q2 for the reconstruction of initial-final systems", &KinematicsReconstructor::_minQ, GeV, 0.001*GeV, 1e-6*GeV, 10.0*GeV, false, false, Interface::limited); static RefVector interfaceNoRescale ("NoRescale", "Particles which shouldn't be rescaled to be on shell by the shower", &KinematicsReconstructor::_noRescaleVector, -1, false, false, true, false, false); static Switch interfaceInitialInitialBoostOption ("InitialInitialBoostOption", "Option for how the boost from the system before ISR to that after ISR is applied.", &KinematicsReconstructor::_initialBoost, 0, false, false); static SwitchOption interfaceInitialInitialBoostOptionOneBoost (interfaceInitialInitialBoostOption, "OneBoost", "Apply one boost from old CMS to new CMS", 0); static SwitchOption interfaceInitialInitialBoostOptionLongTransBoost (interfaceInitialInitialBoostOption, "LongTransBoost", "First apply a longitudinal and then a transverse boost", 1); static Switch interfaceFinalStateReconOption ("FinalStateReconOption", "Option for how to reconstruct the momenta of the final-state system", &KinematicsReconstructor::_finalStateReconOption, 0, false, false); static SwitchOption interfaceFinalStateReconOptionDefault (interfaceFinalStateReconOption, "Default", "All the momenta are rescaled in the rest frame", 0); static SwitchOption interfaceFinalStateReconOptionMostOffShell (interfaceFinalStateReconOption, "MostOffShell", "All particles put on the new-mass shell and then the most off-shell and" " recoiling system are rescaled to ensure 4-momentum is conserved.", 1); static SwitchOption interfaceFinalStateReconOptionRecursive (interfaceFinalStateReconOption, "Recursive", "Recursively put on shell by putting the most off-shell particle which" " hasn't been rescaled on-shell by rescaling the particles and the recoiling system. ", 2); static SwitchOption interfaceFinalStateReconOptionRestMostOffShell (interfaceFinalStateReconOption, "RestMostOffShell", "The most off-shell is put on shell by rescaling it and the recoiling system," " the recoiling system is then put on-shell in its rest frame.", 3); static SwitchOption interfaceFinalStateReconOptionRestRecursive (interfaceFinalStateReconOption, "RestRecursive", "As 3 but recursive treated the currently most-off shell," " only makes a difference if more than 3 partons.", 4); static Switch interfaceInitialStateReconOption ("InitialStateReconOption", "Option for the reconstruction of initial state radiation", &KinematicsReconstructor::_initialStateReconOption, 0, false, false); static SwitchOption interfaceInitialStateReconOptionRapidity (interfaceInitialStateReconOption, "Rapidity", "Preserve shat and rapidity", 0); static SwitchOption interfaceInitialStateReconOptionLongitudinal (interfaceInitialStateReconOption, "Longitudinal", "Preserve longitudinal momentum", 1); static SwitchOption interfaceInitialStateReconOptionSofterFraction (interfaceInitialStateReconOption, "SofterFraction", "Preserve the momentum fraction of the parton which has emitted softer.", 2); } void KinematicsReconstructor::doinit() { Interfaced::doinit(); _noRescale = set(_noRescaleVector.begin(),_noRescaleVector.end()); } bool KinematicsReconstructor:: reconstructTimeLikeJet(const tShowerParticlePtr particleJetParent) const { assert(particleJetParent); bool emitted=true; // if this is not a fixed point in the reconstruction if( !particleJetParent->children().empty() ) { // if not a reconstruction fixpoint, dig deeper for all children: for ( ParticleVector::const_iterator cit = particleJetParent->children().begin(); cit != particleJetParent->children().end(); ++cit ) reconstructTimeLikeJet(dynamic_ptr_cast(*cit)); } // it is a reconstruction fixpoint, ie kinematical data has to be available else { // check if the parent was part of the shower ShowerParticlePtr jetGrandParent; if(!particleJetParent->parents().empty()) jetGrandParent= dynamic_ptr_cast (particleJetParent->parents()[0]); // update if so if (jetGrandParent) { if (jetGrandParent->showerKinematics()) { if(particleJetParent->id()==_progenitor->id()&& - !_progenitor->data().stable()) { + !_progenitor->data().stable()&&abs(_progenitor->data().id())!=ParticleID::tauminus) { jetGrandParent->showerKinematics()->reconstructLast(particleJetParent, _progenitor->mass()); } else { jetGrandParent->showerKinematics()->reconstructLast(particleJetParent); } } } // otherwise else { Energy dm = particleJetParent->data().constituentMass(); if (abs(dm-particleJetParent->momentum().m())>0.001*MeV - &&particleJetParent->dataPtr()->stable() + &&(particleJetParent->dataPtr()->stable() || abs(particleJetParent->id())==ParticleID::tauminus) &&particleJetParent->id()!=ParticleID::gamma &&_noRescale.find(particleJetParent->dataPtr())==_noRescale.end()) { Lorentz5Momentum dum = particleJetParent->momentum(); dum.setMass(dm); dum.rescaleEnergy(); particleJetParent->set5Momentum(dum); } else { emitted=false; } } } // recursion has reached an endpoint once, ie we can reconstruct the // kinematics from the children. if( !particleJetParent->children().empty() ) particleJetParent->showerKinematics() ->reconstructParent( particleJetParent, particleJetParent->children() ); return emitted; } bool KinematicsReconstructor:: reconstructHardJets(ShowerTreePtr hard, const map > & intrinsic, ShowerInteraction type, bool switchRecon) const { _currentTree = hard; _intrinsic=intrinsic; // extract the particles from the ShowerTree vector ShowerHardJets=hard->extractProgenitors(); for(unsigned int ix=0;ixprogenitor()] = vector(); } for(map >::const_iterator tit = _currentTree->treelinks().begin(); tit != _currentTree->treelinks().end();++tit) { _treeBoosts[tit->first] = vector(); } try { // old recon method, using new member functions if(_reconopt == 0 || switchRecon ) { reconstructGeneralSystem(ShowerHardJets); } // reconstruction based on coloured systems else if( _reconopt == 1) { reconstructColourSinglets(ShowerHardJets,type); } // reconstruction of FF, then IF, then II else if( _reconopt == 2) { reconstructFinalFirst(ShowerHardJets); } // reconstruction based on coloured systems else if( _reconopt == 3 || _reconopt == 4) { reconstructColourPartner(ShowerHardJets); } else assert(false); } catch(KinematicsReconstructionVeto) { _progenitor=tShowerParticlePtr(); _intrinsic.clear(); for(map >::const_iterator bit=_boosts.begin();bit!=_boosts.end();++bit) { for(vector::const_reverse_iterator rit=bit->second.rbegin();rit!=bit->second.rend();++rit) { LorentzRotation rot = rit->inverse(); bit->first->transform(rot); } } _boosts.clear(); for(map >::const_iterator bit=_treeBoosts.begin();bit!=_treeBoosts.end();++bit) { for(vector::const_reverse_iterator rit=bit->second.rbegin();rit!=bit->second.rend();++rit) { LorentzRotation rot = rit->inverse(); bit->first->transform(rot,false); } } _currentTree = tShowerTreePtr(); _treeBoosts.clear(); return false; } catch (Exception & ex) { _progenitor=tShowerParticlePtr(); _intrinsic.clear(); _currentTree = tShowerTreePtr(); _boosts.clear(); _treeBoosts.clear(); throw ex; } _progenitor=tShowerParticlePtr(); _intrinsic.clear(); // ensure x<1 for(map::const_iterator cit=hard->incomingLines().begin();cit!=hard->incomingLines().end();++cit) { tPPtr parent = cit->first->progenitor(); while (!parent->parents().empty()) { parent = parent->parents()[0]; } tPPtr hadron; if ( cit->first->original()->parents().empty() ) { hadron = cit->first->original(); } else { hadron = cit->first->original()->parents()[0]; } if( ! (hadron->id() == parent->id() && hadron->children().size() <= 1) && parent->momentum().rho() > hadron->momentum().rho()) { _progenitor=tShowerParticlePtr(); _intrinsic.clear(); for(map >::const_iterator bit=_boosts.begin();bit!=_boosts.end();++bit) { for(vector::const_reverse_iterator rit=bit->second.rbegin();rit!=bit->second.rend();++rit) { LorentzRotation rot = rit->inverse(); bit->first->transform(rot); } } _boosts.clear(); for(map >::const_iterator bit=_treeBoosts.begin();bit!=_treeBoosts.end();++bit) { for(vector::const_reverse_iterator rit=bit->second.rbegin();rit!=bit->second.rend();++rit) { LorentzRotation rot = rit->inverse(); bit->first->transform(rot,false); } } _currentTree = tShowerTreePtr(); _treeBoosts.clear(); return false; } } _boosts.clear(); _treeBoosts.clear(); _currentTree = tShowerTreePtr(); return true; } double KinematicsReconstructor::solveKfactor(const Energy & root_s, const JetKinVect & jets) const { Energy2 s = sqr(root_s); // must be at least two jets if ( jets.size() < 2) throw KinematicsReconstructionVeto(); // sum of jet masses must be less than roots if(momConsEq( 0.0, root_s, jets )>ZERO) throw KinematicsReconstructionVeto(); // if two jets simple solution if ( jets.size() == 2 ) { static const Energy2 eps = 1.0e-4 * MeV2; if ( sqr(jets[0].p.x()+jets[1].p.x()) < eps && sqr(jets[0].p.y()+jets[1].p.y()) < eps && sqr(jets[0].p.z()+jets[1].p.z()) < eps ) { Energy test = (jets[0].p+jets[1].p).vect().mag(); if(test > 1.0e-4 * MeV) throw KinematicsReconstructionVeto(); if ( jets[0].p.vect().mag2() < eps ) throw KinematicsReconstructionVeto(); Energy2 m1sq(jets[0].q.m2()),m2sq(jets[1].q.m2()); return sqrt( ( sqr(s - m1sq - m2sq) - 4.*m1sq*m2sq ) /(4.*s*jets[0].p.vect().mag2()) ); } else throw KinematicsReconstructionVeto(); } // i.e. jets.size() > 2, numerically // check convergence, if it's a problem maybe use Newton iteration? else { double k1 = 0.,k2 = 1.,k = 0.; if ( momConsEq( k1, root_s, jets ) < ZERO ) { while ( momConsEq( k2, root_s, jets ) < ZERO ) { k1 = k2; k2 *= 2; } while ( fabs( (k1 - k2)/(k1 + k2) ) > 1.e-10 ) { if( momConsEq( k2, root_s, jets ) == ZERO ) { return k2; } else { k = (k1+k2)/2.; if ( momConsEq( k, root_s, jets ) > ZERO ) { k2 = k; } else { k1 = k; } } } return k1; } else throw KinematicsReconstructionVeto(); } throw KinematicsReconstructionVeto(); } bool KinematicsReconstructor:: reconstructSpaceLikeJet( const tShowerParticlePtr p) const { bool emitted = true; tShowerParticlePtr child; tShowerParticlePtr parent; if(!p->parents().empty()) parent = dynamic_ptr_cast(p->parents()[0]); if(parent) { emitted=true; reconstructSpaceLikeJet(parent); } // if branching reconstruct time-like child if(p->children().size()==2) child = dynamic_ptr_cast(p->children()[1]); if(p->perturbative()==0 && child) { dynamic_ptr_cast(p->children()[0])-> showerKinematics()->reconstructParent(p,p->children()); if(!child->children().empty()) { _progenitor=child; reconstructTimeLikeJet(child); // calculate the momentum of the particle Lorentz5Momentum pnew=p->momentum()-child->momentum(); pnew.rescaleMass(); p->children()[0]->set5Momentum(pnew); } } return emitted; } Boost KinematicsReconstructor:: solveBoostBeta( const double k, const Lorentz5Momentum & newq, const Lorentz5Momentum & oldp ) { // try something different, purely numerical first: // a) boost to rest frame of newq, b) boost with kp/E Energy q = newq.vect().mag(); Energy2 qs = sqr(q); Energy2 Q2 = newq.m2(); Energy kp = k*(oldp.vect().mag()); Energy2 kps = sqr(kp); // usually we take the minus sign, since this boost will be smaller. // we only require |k \vec p| = |\vec q'| which leaves the sign of // the boost open but the 'minus' solution gives a smaller boost // parameter, i.e. the result should be closest to the previous // result. this is to be changed if we would get many momentum // conservation violations at the end of the shower from a hard // process. double betam = (q*sqrt(qs + Q2) - kp*sqrt(kps + Q2))/(kps + qs + Q2); // move directly to 'return' Boost beta = -betam*(k/kp)*oldp.vect(); // note that (k/kp)*oldp.vect() = oldp.vect()/oldp.vect().mag() but cheaper. // leave this out if it's running properly! if ( betam >= 0 ) return beta; else return Boost(0., 0., 0.); } bool KinematicsReconstructor:: reconstructDecayJets(ShowerTreePtr decay, ShowerInteraction) const { _currentTree = decay; // extract the particles from the ShowerTree vector ShowerHardJets=decay->extractProgenitors(); for(unsigned int ix=0;ixprogenitor()] = vector(); } for(map >::const_iterator tit = _currentTree->treelinks().begin(); tit != _currentTree->treelinks().end();++tit) { _treeBoosts[tit->first] = vector(); } try { bool radiated[2]={false,false}; // find the decaying particle and check if particles radiated ShowerProgenitorPtr initial; for(unsigned int ix=0;ixprogenitor()->isFinalState()) { radiated[1] |=ShowerHardJets[ix]->hasEmitted(); } else { initial=ShowerHardJets[ix]; radiated[0]|=ShowerHardJets[ix]->hasEmitted(); } } // find boost to the rest frame if needed Boost boosttorest=-initial->progenitor()->momentum().boostVector(); double gammarest = initial->progenitor()->momentum().e()/ initial->progenitor()->momentum().mass(); // check if need to boost to rest frame bool gottaBoost = (boosttorest.mag() > 1e-12); // if initial state radiation reconstruct the jet and set up the basis vectors Lorentz5Momentum pjet; Lorentz5Momentum nvect; // find the partner ShowerParticlePtr partner = initial->progenitor()->partner(); Lorentz5Momentum ppartner[2]; if(partner) ppartner[0]=partner->momentum(); // get the n reference vector if(partner) { if(initial->progenitor()->showerKinematics()) { nvect = initial->progenitor()->showerBasis()->getBasis()[1]; } else { Lorentz5Momentum ppartner=initial->progenitor()->partner()->momentum(); if(gottaBoost) ppartner.boost(boosttorest,gammarest); nvect = Lorentz5Momentum( ZERO,0.5*initial->progenitor()->mass()* ppartner.vect().unit()); nvect.boost(-boosttorest,gammarest); } } // if ISR if(radiated[0]) { // reconstruct the decay jet reconstructDecayJet(initial->progenitor()); // momentum of decaying particle after ISR pjet=initial->progenitor()->momentum() -decay->incomingLines().begin()->second->momentum(); pjet.rescaleMass(); } // boost initial state jet and basis vector if needed if(gottaBoost) { pjet.boost(boosttorest,gammarest); nvect.boost(boosttorest,gammarest); ppartner[0].boost(boosttorest,gammarest); } // loop over the final-state particles and do the reconstruction JetKinVect possiblepartners; JetKinVect jetKinematics; bool atLeastOnce = radiated[0]; LorentzRotation restboost(boosttorest,gammarest); Energy inmass(ZERO); for(unsigned int ix=0;ixprogenitor()->isFinalState()) { inmass=ShowerHardJets[ix]->progenitor()->mass(); continue; } // do the reconstruction JetKinStruct tempJetKin; tempJetKin.parent = ShowerHardJets[ix]->progenitor(); if(ShowerHardJets.size()==2) { Lorentz5Momentum dum=ShowerHardJets[ix]->progenitor()->momentum(); dum.setMass(inmass); dum.rescaleRho(); tempJetKin.parent->set5Momentum(dum); } tempJetKin.p = ShowerHardJets[ix]->progenitor()->momentum(); if(gottaBoost) tempJetKin.p.boost(boosttorest,gammarest); _progenitor=tempJetKin.parent; if(ShowerHardJets[ix]->reconstructed()==ShowerProgenitor::notReconstructed) { atLeastOnce |= reconstructTimeLikeJet(tempJetKin.parent); ShowerHardJets[ix]->reconstructed(ShowerProgenitor::done); } if(gottaBoost) deepTransform(tempJetKin.parent,restboost); tempJetKin.q = ShowerHardJets[ix]->progenitor()->momentum(); jetKinematics.push_back(tempJetKin); } if(partner) ppartner[1]=partner->momentum(); // calculate the rescaling parameters double k1,k2; Lorentz5Momentum qt; if(!solveDecayKFactor(initial->progenitor()->mass(),nvect,pjet, jetKinematics,partner,ppartner,k1,k2,qt)) { for(map >::const_iterator bit=_boosts.begin();bit!=_boosts.end();++bit) { for(vector::const_reverse_iterator rit=bit->second.rbegin();rit!=bit->second.rend();++rit) { LorentzRotation rot = rit->inverse(); bit->first->transform(rot); } } _boosts.clear(); for(map >::const_iterator bit=_treeBoosts.begin();bit!=_treeBoosts.end();++bit) { for(vector::const_reverse_iterator rit=bit->second.rbegin();rit!=bit->second.rend();++rit) { LorentzRotation rot = rit->inverse(); bit->first->transform(rot,false); } } _treeBoosts.clear(); _currentTree = tShowerTreePtr(); return false; } // apply boosts and rescalings to final-state jets for(JetKinVect::iterator it = jetKinematics.begin(); it != jetKinematics.end(); ++it) { LorentzRotation Trafo = LorentzRotation(); if(it->parent!=partner) { // boost for rescaling if(atLeastOnce) { map >::const_iterator tit; for(tit = _currentTree->treelinks().begin(); tit != _currentTree->treelinks().end();++tit) { if(tit->second.first && tit->second.second==it->parent) break; } if(it->parent->children().empty()&&!it->parent->spinInfo() && tit==_currentTree->treelinks().end()) { Lorentz5Momentum pnew(k2*it->p.vect(), sqrt(sqr(k2*it->p.vect().mag())+it->q.mass2()), it->q.mass()); it->parent->set5Momentum(pnew); } else { // rescaling boost can't ever work in this case if(k2<0. && it->q.mass()==ZERO) throw KinematicsReconstructionVeto(); Trafo = solveBoost(k2, it->q, it->p); } } if(gottaBoost) Trafo.boost(-boosttorest,gammarest); if(atLeastOnce || gottaBoost) deepTransform(it->parent,Trafo); } else { Lorentz5Momentum pnew=ppartner[0]; pnew *=k1; pnew-=qt; pnew.setMass(ppartner[1].mass()); pnew.rescaleEnergy(); LorentzRotation Trafo=solveBoost(1.,ppartner[1],pnew); if(gottaBoost) Trafo.boost(-boosttorest,gammarest); deepTransform(partner,Trafo); } } } catch(KinematicsReconstructionVeto) { for(map >::const_iterator bit=_boosts.begin();bit!=_boosts.end();++bit) { for(vector::const_reverse_iterator rit=bit->second.rbegin();rit!=bit->second.rend();++rit) { LorentzRotation rot = rit->inverse(); bit->first->transform(rot); } } _boosts.clear(); for(map >::const_iterator bit=_treeBoosts.begin();bit!=_treeBoosts.end();++bit) { for(vector::const_reverse_iterator rit=bit->second.rbegin();rit!=bit->second.rend();++rit) { LorentzRotation rot = rit->inverse(); bit->first->transform(rot,false); } } _treeBoosts.clear(); _currentTree = tShowerTreePtr(); return false; } catch (Exception & ex) { _currentTree = tShowerTreePtr(); _boosts.clear(); _treeBoosts.clear(); throw ex; } _boosts.clear(); _treeBoosts.clear(); _currentTree = tShowerTreePtr(); return true; } bool KinematicsReconstructor:: reconstructDecayJet( const tShowerParticlePtr p) const { if(p->children().empty()) return false; tShowerParticlePtr child; // if branching reconstruct time-like child child = dynamic_ptr_cast(p->children()[1]); if(child) { _progenitor=child; reconstructTimeLikeJet(child); // calculate the momentum of the particle Lorentz5Momentum pnew=p->momentum()-child->momentum(); pnew.rescaleMass(); p->children()[0]->set5Momentum(pnew); child=dynamic_ptr_cast(p->children()[0]); reconstructDecayJet(child); return true; } return false; } bool KinematicsReconstructor:: solveDecayKFactor(Energy mb, const Lorentz5Momentum & n, const Lorentz5Momentum & pjet, const JetKinVect & jetKinematics, ShowerParticlePtr partner, Lorentz5Momentum ppartner[2], double & k1, double & k2, Lorentz5Momentum & qt) const { Energy2 pjn = partner ? pjet.vect()*n.vect() : ZERO; Energy2 pcn = partner ? ppartner[0].vect()*n.vect() : 1.*MeV2; Energy2 nmag = n.vect().mag2(); Lorentz5Momentum pn = partner ? (pjn/nmag)*n : Lorentz5Momentum(); qt=pjet-pn; qt.setE(ZERO); Energy2 pt2=qt.vect().mag2(); Energy Ejet = pjet.e(); // magnitudes of the momenta for fast access vector pmag; Energy total(Ejet); for(unsigned int ix=0;ixmb) return false; Energy2 pcmag=ppartner[0].vect().mag2(); // used newton-raphson to get the rescaling static const Energy eps=1e-8*GeV; long double d1(1.),d2(1.); Energy roots, ea, ec, ds; unsigned int ix=0; do { ++ix; d2 = d1 + pjn/pcn; roots = Ejet; ds = ZERO; for(unsigned int iy=0;iyeps && ix<100); k1=d1; k2=d2; // return true if N-R succeed, otherwise false return ix<100; } bool KinematicsReconstructor:: deconstructDecayJets(HardTreePtr decay,ShowerInteraction) const { // extract the momenta of the particles vector pin; vector pout; // on-shell masses of the decay products vector mon; Energy mbar(-GeV); // the hard branchings of the particles set::iterator cit; set branchings=decay->branchings(); // properties of the incoming particle bool ISR = false; HardBranchingPtr initial; Lorentz5Momentum qisr; // find the incoming particle, both before and after // any ISR for(cit=branchings.begin();cit!=branchings.end();++cit){ if((*cit)->status()==HardBranching::Incoming|| (*cit)->status()==HardBranching::Decay) { // search back up isr if needed HardBranchingPtr branch = *cit; while(branch->parent()) branch=branch->parent(); initial=branch; // momentum or original parent pin.push_back(branch->branchingParticle()->momentum()); // ISR? ISR = !branch->branchingParticle()->children().empty(); // ISR momentum qisr = pin.back()-(**cit).branchingParticle()->momentum(); qisr.rescaleMass(); } } assert(pin.size()==1); // compute boost to rest frame Boost boostv=-pin[0].boostVector(); // partner for ISR ShowerParticlePtr partner; Lorentz5Momentum ppartner; if(initial->branchingParticle()->partner()) { partner=initial->branchingParticle()->partner(); ppartner=partner->momentum(); } // momentum of the decay products for(cit=branchings.begin();cit!=branchings.end();++cit) { if((*cit)->status()!=HardBranching::Outgoing) continue; // find the mass of the particle // including special treatment for off-shell resonances // to preserve off-shell mass Energy mass; if(!(**cit).branchingParticle()->dataPtr()->stable()) { HardBranchingPtr branch=*cit; while(!branch->children().empty()) { for(unsigned int ix=0;ixchildren().size();++ix) { if(branch->children()[ix]->branchingParticle()->id()== (**cit).branchingParticle()->id()) { branch = branch->children()[ix]; continue; } } }; mass = branch->branchingParticle()->mass(); } else { mass = (**cit).branchingParticle()->dataPtr()->mass(); } // if not evolution partner of decaying particle if((*cit)->branchingParticle()!=partner) { pout.push_back((*cit)->branchingParticle()->momentum()); mon.push_back(mass); } // evolution partner of decaying particle else { mbar = mass; } } // boost all the momenta to the rest frame of the decaying particle for(unsigned int ix=0;ixbranchingParticle()->partner()) { ppartner.boost(boostv); qisr.boost(boostv); } // compute the rescaling factors double k1,k2; if(!ISR) { if(partner) { pout.push_back(ppartner); mon.push_back(mbar); } k1=k2=inverseRescalingFactor(pout,mon,pin[0].mass()); if(partner) { pout.pop_back(); mon.pop_back(); } } else { if(!inverseDecayRescalingFactor(pout,mon,pin[0].mass(), ppartner,mbar,k1,k2)) return false; } // now calculate the p reference vectors unsigned int ifinal=0; for(cit=branchings.begin();cit!=branchings.end();++cit) { if((**cit).status()!=HardBranching::Outgoing) continue; // for partners other than colour partner of decaying particle if((*cit)->branchingParticle()!=partner) { Lorentz5Momentum pvect = (*cit)->branchingParticle()->momentum(); pvect.boost(boostv); pvect /= k1; pvect.setMass(mon[ifinal]); ++ifinal; pvect.rescaleEnergy(); pvect.boost(-boostv); (*cit)->pVector(pvect); (*cit)->showerMomentum(pvect); } // for colour partner of decaying particle else { Lorentz5Momentum pvect = (*cit)->branchingParticle()->momentum(); pvect.boost(boostv); Lorentz5Momentum qtotal; for(unsigned int ix=0;ixpVector(pvect); (*cit)->showerMomentum(pvect); } } // For initial-state if needed if(initial) { tShowerParticlePtr newPartner=initial->branchingParticle()->partner(); if(newPartner) { tHardBranchingPtr branch; for( set::iterator clt = branchings.begin(); clt != branchings.end(); ++clt ) { if((**clt).branchingParticle()==newPartner) { initial->colourPartner(*clt); branch=*clt; break; } } Lorentz5Momentum pvect = initial->branchingParticle()->momentum(); initial->pVector(pvect); Lorentz5Momentum ptemp = branch->pVector(); ptemp.boost(boostv); Lorentz5Momentum nvect = Lorentz5Momentum( ZERO, 0.5*initial->branchingParticle()->mass()* ptemp.vect().unit()); nvect.boost(-boostv); initial->nVector(nvect); } } // calculate the reference vectors, then for outgoing particles for(cit=branchings.begin();cit!=branchings.end();++cit){ if((**cit).status()!=HardBranching::Outgoing) continue; // find the partner branchings tShowerParticlePtr newPartner=(*cit)->branchingParticle()->partner(); if(!newPartner) continue; tHardBranchingPtr branch; for( set::iterator clt = branchings.begin(); clt != branchings.end(); ++clt ) { if(cit==clt) continue; if((**clt).branchingParticle()==newPartner) { (**cit).colourPartner(*clt); branch=*clt; break; } } if((**decay->incoming().begin()).branchingParticle()==newPartner) { (**cit).colourPartner(*decay->incoming().begin()); branch = *decay->incoming().begin(); } // final-state colour partner if(branch->status()==HardBranching::Outgoing) { Boost boost=((*cit)->pVector()+branch->pVector()).findBoostToCM(); Lorentz5Momentum pcm = branch->pVector(); pcm.boost(boost); Lorentz5Momentum nvect = Lorentz5Momentum(ZERO,pcm.vect()); nvect.boost( -boost); (*cit)->nVector(nvect); } // initial-state colour partner else { Boost boost=branch->pVector().findBoostToCM(); Lorentz5Momentum pcm = (*cit)->pVector(); pcm.boost(boost); Lorentz5Momentum nvect = Lorentz5Momentum( ZERO, -pcm.vect()); nvect.boost( -boost); (*cit)->nVector(nvect); } } // now compute the new momenta // and calculate the shower variables for(cit=branchings.begin();cit!=branchings.end();++cit) { if((**cit).status()!=HardBranching::Outgoing) continue; LorentzRotation B=LorentzRotation(-boostv); LorentzRotation A=LorentzRotation(boostv),R; if((*cit)->branchingParticle()==partner) { Lorentz5Momentum qnew; Energy2 dot=(*cit)->pVector()*(*cit)->nVector(); double beta = 0.5*((*cit)->branchingParticle()->momentum().m2() -sqr((*cit)->pVector().mass()))/dot; qnew=(*cit)->pVector()+beta*(*cit)->nVector(); qnew.rescaleMass(); // compute the boost R=B*solveBoost(A*qnew,A*(*cit)->branchingParticle()->momentum())*A; } else { Lorentz5Momentum qnew; if((*cit)->branchingParticle()->partner()) { Energy2 dot=(*cit)->pVector()*(*cit)->nVector(); double beta = 0.5*((*cit)->branchingParticle()->momentum().m2() -sqr((*cit)->pVector().mass()))/dot; qnew=(*cit)->pVector()+beta*(*cit)->nVector(); qnew.rescaleMass(); } else { qnew = (*cit)->pVector(); } // compute the boost R=B*solveBoost(A*qnew,A*(*cit)->branchingParticle()->momentum())*A; } // reconstruct the momenta (*cit)->setMomenta(R,1.0,Lorentz5Momentum()); } if(initial) { initial->setMomenta(LorentzRotation(),1.0,Lorentz5Momentum()); } return true; } double KinematicsReconstructor:: inverseRescalingFactor(vector pout, vector mon, Energy roots) const { double lambda=1.; if(pout.size()==2) { double mu_q1(pout[0].m()/roots), mu_q2(pout[1].m()/roots); double mu_p1(mon[0]/roots) , mu_p2(mon[1]/roots); lambda = ((1.+mu_q1+mu_q2)*(1.-mu_q1-mu_q2)*(mu_q1-1.-mu_q2)*(mu_q2-1.-mu_q1))/ ((1.+mu_p1+mu_p2)*(1.-mu_p1-mu_p2)*(mu_p1-1.-mu_p2)*(mu_p2-1.-mu_p1)); if(lambda<0.) throw Exception() << "Rescaling factor is imaginary in KinematicsReconstructor::" << "inverseRescalingFactor lambda^2= " << lambda << Exception::eventerror; lambda = sqrt(lambda); } else { unsigned int ntry=0; // compute magnitudes once for speed vector pmag; for(unsigned int ix=0;ix root(pout.size()); do { // compute new energies Energy sum(ZERO); for(unsigned int ix=0;ix::const_iterator it=tree->branchings().begin(); it!=tree->branchings().end();++it) { if((**it).status()==HardBranching::Incoming) in .jets.push_back(*it); else out.jets.push_back(*it); } LorentzRotation toRest,fromRest; bool applyBoost(false); // do the initial-state reconstruction deconstructInitialInitialSystem(applyBoost,toRest,fromRest, tree,in.jets,type); // do the final-state reconstruction deconstructFinalStateSystem(toRest,fromRest,tree, out.jets,type); // only at this point that we can be sure all the reference vectors // are correct for(set::const_iterator it=tree->branchings().begin(); it!=tree->branchings().end();++it) { if((**it).status()==HardBranching::Incoming) continue; if((**it).branchingParticle()->coloured()) (**it).setMomenta(LorentzRotation(),1.,Lorentz5Momentum(),false); } for(set::const_iterator it=tree->incoming().begin(); it!=tree->incoming().end();++it) { (**it).setMomenta(LorentzRotation(),1.,Lorentz5Momentum(),false); } return true; } bool KinematicsReconstructor::deconstructHardJets(HardTreePtr tree, ShowerInteraction type) const { // inverse of old recon method if(_reconopt == 0) { return deconstructGeneralSystem(tree,type); } else if(_reconopt == 1) { return deconstructColourSinglets(tree,type); } else if(_reconopt == 2) { throw Exception() << "Inverse reconstruction is not currently supported for ReconstructionOption Colour2 " << "in KinematicsReconstructor::deconstructHardJets(). Please use one of the other options\n" << Exception::runerror; } else if(_reconopt == 3 || _reconopt == 4 ) { return deconstructColourPartner(tree,type); } else assert(false); } bool KinematicsReconstructor:: deconstructColourSinglets(HardTreePtr tree, ShowerInteraction type) const { // identify the colour singlet systems unsigned int nnun(0),nnii(0),nnif(0),nnf(0),nni(0); vector systems(identifySystems(tree->branchings(),nnun,nnii,nnif,nnf,nni)); // now decide what to do LorentzRotation toRest,fromRest; bool applyBoost(false); bool general(false); // initial-initial connection and final-state colour singlet systems // Drell-Yan type if(nnun==0&&nnii==1&&nnif==0&&nnf>0&&nni==0) { // reconstruct initial-initial system for(unsigned int ix=0;ix0&&nni==1)|| (nnif==2&& nni==0))) { for(unsigned int ix=0;ix0&&nni==2) { // only FS needed // but need to boost to rest frame if QED ISR Lorentz5Momentum ptotal; for(unsigned int ix=0;ixbranchingParticle()->momentum(); } toRest = LorentzRotation(ptotal.findBoostToCM()); fromRest = toRest; fromRest.invert(); if(type!=ShowerInteraction::QCD) { combineFinalState(systems); general=false; } } // general type else { general = true; } // final-state systems except for general recon if(!general) { for(unsigned int ix=0;ix::const_iterator it=tree->branchings().begin(); it!=tree->branchings().end();++it) { if((**it).status()==HardBranching::Incoming) continue; if((**it).branchingParticle()->coloured()) (**it).setMomenta(LorentzRotation(),1.,Lorentz5Momentum(),false); } for(set::const_iterator it=tree->incoming().begin(); it!=tree->incoming().end();++it) { (**it).setMomenta(LorentzRotation(),1.,Lorentz5Momentum(),false); } return true; } else { return deconstructGeneralSystem(tree,type); } return true; } bool KinematicsReconstructor:: deconstructColourPartner(HardTreePtr tree, ShowerInteraction type) const { Lorentz5Momentum ptotal; HardBranchingPtr emitter; ColourSingletShower incomingShower,outgoingShower; for(set::const_iterator it=tree->branchings().begin(); it!=tree->branchings().end();++it) { if((**it).status()==HardBranching::Incoming) { incomingShower.jets.push_back(*it); ptotal += (*it)->branchingParticle()->momentum(); // check for emitting particle if((**it).parent() ) { if(!emitter) emitter = *it; else throw Exception() << "Only one emitting particle allowed in " << "KinematicsReconstructor::deconstructColourPartner()" << Exception::runerror; } } else if ((**it).status()==HardBranching::Outgoing) { outgoingShower.jets.push_back(*it); // check for emitting particle if(!(**it).children().empty() ) { if(!emitter) emitter = *it; else throw Exception() << "Only one emitting particle allowed in " << "KinematicsReconstructor::deconstructColourPartner()" << Exception::runerror; } } } assert(emitter); assert(emitter->colourPartner()); ColourSingletShower system; system.jets.push_back(emitter); system.jets.push_back(emitter->colourPartner()); LorentzRotation toRest,fromRest; bool applyBoost(false); // identify the colour singlet system if(emitter->status() == HardBranching::Outgoing && emitter->colourPartner()->status() == HardBranching::Outgoing ) { system.type=F; // need to boost to rest frame if QED ISR if( !incomingShower.jets[0]->branchingParticle()->coloured() && !incomingShower.jets[1]->branchingParticle()->coloured() ) { Boost boost = ptotal.findBoostToCM(); toRest = LorentzRotation( boost); fromRest = LorentzRotation(-boost); } else findInitialBoost(ptotal,ptotal,toRest,fromRest); deconstructFinalStateSystem(toRest,fromRest,tree, system.jets,type); } else if (emitter->status() == HardBranching::Incoming && emitter->colourPartner()->status() == HardBranching::Incoming) { system.type=II; deconstructInitialInitialSystem(applyBoost,toRest,fromRest,tree,system.jets,type); // make sure the recoil gets applied deconstructFinalStateSystem(toRest,fromRest,tree, outgoingShower.jets,type); } else if ((emitter->status() == HardBranching::Outgoing && emitter->colourPartner()->status() == HardBranching::Incoming ) || (emitter->status() == HardBranching::Incoming && emitter->colourPartner()->status() == HardBranching::Outgoing)) { system.type=IF; // enusre incoming first if(system.jets[0]->status() == HardBranching::Outgoing) swap(system.jets[0],system.jets[1]); deconstructInitialFinalSystem(tree,system.jets,type); } else { throw Exception() << "Unknown type of system in " << "KinematicsReconstructor::deconstructColourPartner()" << Exception::runerror; } // only at this point that we can be sure all the reference vectors // are correct for(set::const_iterator it=tree->branchings().begin(); it!=tree->branchings().end();++it) { if((**it).status()==HardBranching::Incoming) continue; if((**it).branchingParticle()->coloured()) (**it).setMomenta(LorentzRotation(),1.,Lorentz5Momentum(),false); } for(set::const_iterator it=tree->incoming().begin(); it!=tree->incoming().end();++it) { (**it).setMomenta(LorentzRotation(),1.,Lorentz5Momentum(),false); } for(set::const_iterator it=tree->branchings().begin(); it!=tree->branchings().end();++it) { if((**it).status()!=HardBranching::Incoming) continue; if(*it==system.jets[0] || *it==system.jets[1]) continue; if((**it).branchingParticle()->momentum().z()>ZERO) { (**it).z((**it).branchingParticle()->momentum().plus()/(**it).beam()->momentum().plus()); } else { (**it).z((**it).branchingParticle()->momentum().minus()/(**it).beam()->momentum().minus()); } } return true; } void KinematicsReconstructor:: reconstructInitialFinalSystem(vector jets) const { Lorentz5Momentum pin[2],pout[2],pbeam; for(unsigned int ix=0;ixprogenitor()->isFinalState()) { pout[0] +=jets[ix]->progenitor()->momentum(); _progenitor = jets[ix]->progenitor(); if(jets[ix]->reconstructed()==ShowerProgenitor::notReconstructed) { reconstructTimeLikeJet(jets[ix]->progenitor()); jets[ix]->reconstructed(ShowerProgenitor::done); } } // initial-state parton else { pin[0] +=jets[ix]->progenitor()->momentum(); if(jets[ix]->progenitor()->showerKinematics()) { pbeam = jets[ix]->progenitor()->showerBasis()->getBasis()[0]; } else { if ( jets[ix]->original()->parents().empty() ) { pbeam = jets[ix]->progenitor()->momentum(); } else { pbeam = jets[ix]->original()->parents()[0]->momentum(); } } if(jets[ix]->reconstructed()==ShowerProgenitor::notReconstructed) { reconstructSpaceLikeJet(jets[ix]->progenitor()); jets[ix]->reconstructed(ShowerProgenitor::done); } assert(!jets[ix]->original()->parents().empty()); } } // add intrinsic pt if needed addIntrinsicPt(jets); // momenta after showering for(unsigned int ix=0;ixprogenitor()->isFinalState()) pout[1] += jets[ix]->progenitor()->momentum(); else pin[1] += jets[ix]->progenitor()->momentum(); } // work out the boost to the Breit frame Lorentz5Momentum pa = pout[0]-pin[0]; Axis axis(pa.vect().unit()); LorentzRotation rot; double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); if ( sinth > 1.e-9 ) rot.setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); rot.rotateX(Constants::pi); rot.boostZ( pa.e()/pa.vect().mag()); Lorentz5Momentum ptemp=rot*pbeam; Boost trans = -1./ptemp.e()*ptemp.vect(); trans.setZ(0.); if ( trans.mag2() - 1. >= 0. ) throw KinematicsReconstructionVeto(); rot.boost(trans); pa *=rot; // project and calculate rescaling // reference vectors Lorentz5Momentum n1(ZERO,ZERO,-pa.z(),-pa.z()); Lorentz5Momentum n2(ZERO,ZERO, pa.z(),-pa.z()); Energy2 n1n2 = n1*n2; // decompose the momenta Lorentz5Momentum qbp=rot*pin[1],qcp=rot*pout[1]; qbp.rescaleMass(); qcp.rescaleMass(); double a[2],b[2]; a[0] = n2*qbp/n1n2; b[0] = n1*qbp/n1n2; Lorentz5Momentum qperp = qbp-a[0]*n1-b[0]*n2; b[1] = 0.5; a[1] = 0.5*(qcp.m2()-qperp.m2())/n1n2/b[1]; double kb; if(a[0]!=0.) { double A(0.5*a[0]),B(b[0]*a[0]-a[1]*b[1]-0.25),C(-0.5*b[0]); if(sqr(B)-4.*A*C<0.) throw KinematicsReconstructionVeto(); kb = 0.5*(-B+sqrt(sqr(B)-4.*A*C))/A; } else { kb = 0.5*b[0]/(b[0]*a[0]-a[1]*b[1]-0.25); } // changed to improve stability if(kb==0.) throw KinematicsReconstructionVeto(); if ( a[1]>b[1] && abs(a[1]) < 1e-12 ) throw KinematicsReconstructionVeto(); if ( a[1]<=b[1] && abs(0.5+b[0]/kb) < 1e-12 ) throw KinematicsReconstructionVeto(); double kc = (a[1]>b[1]) ? (a[0]*kb-0.5)/a[1] : b[1]/(0.5+b[0]/kb); if(kc==0.) throw KinematicsReconstructionVeto(); Lorentz5Momentum pnew[2] = { a[0]*kb*n1+b[0]/kb*n2+qperp, a[1]*kc*n1+b[1]/kc*n2+qperp}; LorentzRotation rotinv=rot.inverse(); for(unsigned int ix=0;ixprogenitor()->isFinalState()) { deepTransform(jets[ix]->progenitor(),rot); deepTransform(jets[ix]->progenitor(),solveBoost(pnew[1],qcp)); Energy delta = jets[ix]->progenitor()->momentum().m()-jets[ix]->progenitor()->momentum().mass(); if ( abs(delta) > MeV ) throw KinematicsReconstructionVeto(); deepTransform(jets[ix]->progenitor(),rotinv); } else { tPPtr parent; boostChain(jets[ix]->progenitor(),rot,parent); boostChain(jets[ix]->progenitor(),solveBoostZ(pnew[0],qbp),parent); // check the first boost worked, and if not apply small correction to // fix energy/momentum conservation // this is a kludge but it reduces momentum non-conservation dramatically Lorentz5Momentum pdiff = pnew[0]-jets[ix]->progenitor()->momentum(); Energy2 delta = sqr(pdiff.x())+sqr(pdiff.y())+sqr(pdiff.z())+sqr(pdiff.t()); unsigned int ntry=0; while(delta>1e-6*GeV2 && ntry<5 ) { ntry +=1; boostChain(jets[ix]->progenitor(),solveBoostZ(pnew[0],jets[ix]->progenitor()->momentum()),parent); pdiff = pnew[0]-jets[ix]->progenitor()->momentum(); delta = sqr(pdiff.x())+sqr(pdiff.y())+sqr(pdiff.z())+sqr(pdiff.t()); } // apply test in breit-frame Lorentz5Momentum ptest1 = parent->momentum(); Lorentz5Momentum ptest2 = rot*pbeam; if(ptest1.z()/ptest2.z()<0. || ptest1.z()/ptest2.z()>1.) throw KinematicsReconstructionVeto(); boostChain(jets[ix]->progenitor(),rotinv,parent); } } } bool KinematicsReconstructor::addIntrinsicPt(vector jets) const { bool added=false; // add the intrinsic pt if needed for(unsigned int ix=0;ixprogenitor()->isFinalState()|| jets[ix]->hasEmitted()|| jets[ix]->reconstructed()==ShowerProgenitor::dontReconstruct) continue; if(_intrinsic.find(jets[ix])==_intrinsic.end()) continue; pair pt=_intrinsic[jets[ix]]; Energy etemp = jets[ix]->original()->parents()[0]->momentum().z(); Lorentz5Momentum p_basis(ZERO, ZERO, etemp, abs(etemp)), n_basis(ZERO, ZERO,-etemp, abs(etemp)); double alpha = jets[ix]->progenitor()->x(); double beta = 0.5*(sqr(jets[ix]->progenitor()->data().mass())+ sqr(pt.first))/alpha/(p_basis*n_basis); Lorentz5Momentum pnew=alpha*p_basis+beta*n_basis; pnew.setX(pt.first*cos(pt.second)); pnew.setY(pt.first*sin(pt.second)); pnew.rescaleMass(); jets[ix]->progenitor()->set5Momentum(pnew); added = true; } return added; } namespace { double defaultSolveBoostGamma(const double & betam,const Energy2 & kps, const Energy2 & qs, const Energy2 & Q2, const Energy & kp, const Energy & q, const Energy & qE) { if(betam<0.5) { return 1./sqrt(1.-sqr(betam)); } else { return ( kps+ qs + Q2)/ sqrt(2.*kps*qs + kps*Q2 + qs*Q2 + sqr(Q2) + 2.*q*qE*kp*sqrt(kps + Q2)); } } } LorentzRotation KinematicsReconstructor:: solveBoost(const double k, const Lorentz5Momentum & newq, const Lorentz5Momentum & oldp ) const { Energy q = newq.vect().mag(); Energy2 qs = sqr(q); Energy2 Q2 = newq.mass2(); Energy kp = k*(oldp.vect().mag()); Energy2 kps = sqr(kp); double betam = (q*newq.e() - kp*sqrt(kps + Q2))/(kps + qs + Q2); if ( abs(betam) - 1. >= 0. ) throw KinematicsReconstructionVeto(); Boost beta = -betam*(k/kp)*oldp.vect(); double gamma = 0.; if(Q2/sqr(oldp.e())>1e-4) { gamma = defaultSolveBoostGamma(betam,kps,qs,Q2,kp,q,newq.e()); } else { if(k>0) { gamma = 4.*kps*qs/sqr(kps +qs) + 2.*sqr(kps-qs)*Q2/pow<3,1>(kps +qs) - 0.25*( sqr(kps) + 14.*kps*qs + sqr(qs))*sqr(kps-qs)/(pow<4,1>(kps +qs)*kps*qs)*sqr(Q2); } else { gamma = 0.25*sqr(Q2)/(kps*qs)*(1. - 0.5*(kps+qs)/(kps*qs)*Q2); } if(gamma<=0.) throw KinematicsReconstructionVeto(); gamma = 1./sqrt(gamma); if(gamma>2.) gamma = defaultSolveBoostGamma(betam,kps,qs,Q2,kp,q,newq.e()); } // note that (k/kp)*oldp.vect() = oldp.vect()/oldp.vect().mag() but cheaper. ThreeVector ax = newq.vect().cross( oldp.vect() ); double delta; if (newq.x()*oldp.x()+newq.y()*oldp.y()+newq.z()*oldp.z()< 1e-16*GeV2) { throw KinematicsReconstructionVeto(); }else{ delta = newq.vect().angle( oldp.vect() ); } LorentzRotation R; using Constants::pi; Energy2 scale1 = sqr(newq.x())+ sqr(newq.y())+sqr(newq.z()); Energy2 scale2 = sqr(oldp.x())+ sqr(oldp.y())+sqr(oldp.z()); if ( ax.mag2()/scale1/scale2 > 1e-28 ) { R.rotate( delta, unitVector(ax) ).boost( beta , gamma ); } else if(abs(delta-pi)/pi < 0.001) { double phi=2.*pi*UseRandom::rnd(); Axis axis(cos(phi),sin(phi),0.); axis.rotateUz(newq.vect().unit()); R.rotate(delta,axis).boost( beta , gamma ); } else { R.boost( beta , gamma ); } return R; } LorentzRotation KinematicsReconstructor::solveBoost(const Lorentz5Momentum & q, const Lorentz5Momentum & p ) const { Energy modp = p.vect().mag(); Energy modq = q.vect().mag(); double betam = (p.e()*modp-q.e()*modq)/(sqr(modq)+sqr(modp)+p.mass2()); if ( abs(betam)-1. >= 0. ) throw KinematicsReconstructionVeto(); Boost beta = -betam*q.vect().unit(); ThreeVector ax = p.vect().cross( q.vect() ); double delta = p.vect().angle( q.vect() ); LorentzRotation R; using Constants::pi; if ( beta.mag2() - 1. >= 0. ) throw KinematicsReconstructionVeto(); if ( ax.mag2()/GeV2/MeV2 > 1e-16 ) { R.rotate( delta, unitVector(ax) ).boost( beta ); } else { R.boost( beta ); } return R; } LorentzRotation KinematicsReconstructor::solveBoostZ(const Lorentz5Momentum & q, const Lorentz5Momentum & p ) const { static const double eps = 1e-6; LorentzRotation R; double beta; Energy2 mt2 = p.mass()eps) { double erat = (q.t()+q.z())/(p.t()+p.z()); Energy2 den = mt2*(erat+1./erat); Energy2 num = (q.z()-p.z())*(q.t()+p.t()) + (p.z()+q.z())*(p.t()-q.t()); beta = num/den; if ( abs(beta) - 1. >= 0. ) throw KinematicsReconstructionVeto(); R.boostZ(beta); } else { double er = sqr(p.t()/q.t()); double x = ratio+0.125*(er+10.+1./er)*sqr(ratio); beta = -(p.t()-q.t())*(p.t()+q.t())/(sqr(p.t())+sqr(q.t()))*(1.+x); double gamma = (4.*sqr(p.t()*q.t()) +sqr(p.t()-q.t())*sqr(p.t()+q.t())* (-2.*x+sqr(x)))/sqr(sqr(p.t())+sqr(q.t())); if ( abs(beta) - 1. >= 0. ) throw KinematicsReconstructionVeto(); gamma = 1./sqrt(gamma); R.boost(0.,0.,beta,gamma); } Lorentz5Momentum ptest = R*p; if(ptest.z()/q.z() < 0. || ptest.t()/q.t() < 0. ) { throw KinematicsReconstructionVeto(); } return R; } void KinematicsReconstructor:: reconstructFinalStateSystem(bool applyBoost, const LorentzRotation & toRest, const LorentzRotation & fromRest, vector jets) const { LorentzRotation trans = applyBoost? toRest : LorentzRotation(); // special for case of individual particle if(jets.size()==1) { deepTransform(jets[0]->progenitor(),trans); deepTransform(jets[0]->progenitor(),fromRest); return; } bool radiated(false); // find the hard process centre-of-mass energy Lorentz5Momentum pcm; // check if radiated and calculate total momentum for(unsigned int ix=0;ixhasEmitted(); pcm += jets[ix]->progenitor()->momentum(); } if(applyBoost) pcm *= trans; // check if in CMF frame Boost beta_cm = pcm.findBoostToCM(); bool gottaBoost(false); if(beta_cm.mag() > 1e-12) { gottaBoost = true; trans.boost(beta_cm); } // collection of pointers to initial hard particle and jet momenta // for final boosts JetKinVect jetKinematics; vector::const_iterator cit; for(cit = jets.begin(); cit != jets.end(); cit++) { JetKinStruct tempJetKin; tempJetKin.parent = (*cit)->progenitor(); if(applyBoost || gottaBoost) { deepTransform(tempJetKin.parent,trans); } tempJetKin.p = (*cit)->progenitor()->momentum(); _progenitor=tempJetKin.parent; if((**cit).reconstructed()==ShowerProgenitor::notReconstructed) { radiated |= reconstructTimeLikeJet((*cit)->progenitor()); (**cit).reconstructed(ShowerProgenitor::done); } else { radiated |= !(*cit)->progenitor()->children().empty(); } tempJetKin.q = (*cit)->progenitor()->momentum(); jetKinematics.push_back(tempJetKin); } // default option rescale everything with the same factor if( _finalStateReconOption == 0 || jetKinematics.size() <= 2 ) { // find the rescaling factor double k = 0.0; if(radiated) { k = solveKfactor(pcm.m(), jetKinematics); // perform the rescaling and boosts for(JetKinVect::iterator it = jetKinematics.begin(); it != jetKinematics.end(); ++it) { LorentzRotation Trafo = solveBoost(k, it->q, it->p); deepTransform(it->parent,Trafo); } } } // different treatment of most off-shell else if ( _finalStateReconOption <= 4 ) { // sort the jets by virtuality std::sort(jetKinematics.begin(),jetKinematics.end(),JetOrdering()); // Bryan's procedures from FORTRAN if( _finalStateReconOption <=2 ) { // loop over the off-shell partons, _finalStateReconOption==1 only first ==2 all JetKinVect::const_iterator jend = _finalStateReconOption==1 ? jetKinematics.begin()+1 : jetKinematics.end(); for(JetKinVect::const_iterator jit=jetKinematics.begin(); jit!=jend;++jit) { // calculate the 4-momentum of the recoiling system Lorentz5Momentum psum; bool done = true; for(JetKinVect::const_iterator it=jetKinematics.begin();it!=jetKinematics.end();++it) { if(it==jit) { done = false; continue; } // first option put on-shell and sum 4-momenta if( _finalStateReconOption == 1 ) { LorentzRotation Trafo = solveBoost(1., it->q, it->p); deepTransform(it->parent,Trafo); psum += it->parent->momentum(); } // second option, sum momenta else { // already rescaled if(done) psum += it->parent->momentum(); // still needs to be rescaled else psum += it->p; } } // set the mass psum.rescaleMass(); // calculate the 3-momentum rescaling factor Energy2 s(pcm.m2()); Energy2 m1sq(jit->q.m2()),m2sq(psum.m2()); Energy4 num = sqr(s - m1sq - m2sq) - 4.*m1sq*m2sq; if(nump.vect().mag2()) ); // boost the off-shell parton LorentzRotation B1 = solveBoost(k, jit->q, jit->p); deepTransform(jit->parent,B1); // boost everything else to rescale LorentzRotation B2 = solveBoost(k, psum, psum); for(JetKinVect::iterator it=jetKinematics.begin();it!=jetKinematics.end();++it) { if(it==jit) continue; deepTransform(it->parent,B2); it->p *= B2; it->q *= B2; } } } // Peter's C++ procedures else { reconstructFinalFinalOffShell(jetKinematics,pcm.m2(), _finalStateReconOption == 4); } } else assert(false); // apply the final boosts if(gottaBoost || applyBoost) { LorentzRotation finalBoosts; if(gottaBoost) finalBoosts.boost(-beta_cm); if(applyBoost) finalBoosts.transform(fromRest); for(JetKinVect::iterator it = jetKinematics.begin(); it != jetKinematics.end(); ++it) { deepTransform(it->parent,finalBoosts); } } } void KinematicsReconstructor:: reconstructInitialInitialSystem(bool & applyBoost, LorentzRotation & toRest, LorentzRotation & fromRest, vector jets) const { bool radiated = false; Lorentz5Momentum pcm; // check whether particles radiated and calculate total momentum for( unsigned int ix = 0; ix < jets.size(); ++ix ) { radiated |= jets[ix]->hasEmitted(); pcm += jets[ix]->progenitor()->momentum(); if(jets[ix]->original()->parents().empty()) return; } pcm.rescaleMass(); // check if intrinsic pt to be added radiated |= !_intrinsic.empty(); // if no radiation return if(!radiated) { for(unsigned int ix=0;ixreconstructed()==ShowerProgenitor::notReconstructed) jets[ix]->reconstructed(ShowerProgenitor::done); } return; } // initial state shuffling applyBoost=false; vector p, pq, p_in; vector pts; for(unsigned int ix=0;ixprogenitor()->momentum()); // reconstruct the jet if(jets[ix]->reconstructed()==ShowerProgenitor::notReconstructed) { radiated |= reconstructSpaceLikeJet(jets[ix]->progenitor()); jets[ix]->reconstructed(ShowerProgenitor::done); } assert(!jets[ix]->original()->parents().empty()); Energy etemp = jets[ix]->original()->parents()[0]->momentum().z(); Lorentz5Momentum ptemp = Lorentz5Momentum(ZERO, ZERO, etemp, abs(etemp)); pq.push_back(ptemp); pts.push_back(jets[ix]->highestpT()); } // add the intrinsic pt if needed radiated |=addIntrinsicPt(jets); for(unsigned int ix=0;ixprogenitor()->momentum()); } double x1 = p_in[0].z()/pq[0].z(); double x2 = p_in[1].z()/pq[1].z(); vector beta=initialStateRescaling(x1,x2,p_in[0]+p_in[1],p,pq,pts); // if not need don't apply boosts if(!(radiated && p.size() == 2 && pq.size() == 2)) return; applyBoost=true; // apply the boosts Lorentz5Momentum newcmf; for(unsigned int ix=0;ixprogenitor(); Boost betaboost(0, 0, beta[ix]); tPPtr parent; boostChain(toBoost, LorentzRotation(0.,0.,beta[ix]),parent); if(parent->momentum().e()/pq[ix].e()>1.|| parent->momentum().z()/pq[ix].z()>1.) throw KinematicsReconstructionVeto(); newcmf+=toBoost->momentum(); } if(newcmf.m() jets, ShowerInteraction) const { assert(jets.size()==2); // put beam with +z first if(jets[0]->beam()->momentum().z() pin,pq; for(unsigned int ix=0;ixbranchingParticle()->momentum()); Energy etemp = jets[ix]->beam()->momentum().z(); pq.push_back(Lorentz5Momentum(ZERO, ZERO,etemp, abs(etemp))); } // calculate the rescaling double x[2]; Lorentz5Momentum pcm=pin[0]+pin[1]; assert(pcm.mass2()>ZERO); pcm.rescaleMass(); vector boost = inverseInitialStateRescaling(x[0],x[1],pcm,pin,pq); set::const_iterator cjt=tree->incoming().begin(); HardBranchingPtr incoming[2]; incoming[0] = *cjt; ++cjt; incoming[1] = *cjt; if((*tree->incoming().begin())->beam()->momentum().z()/pq[0].z()<0.) swap(incoming[0],incoming[1]); // apply the boost the the particles unsigned int iswap[2]={1,0}; for(unsigned int ix=0;ix<2;++ix) { LorentzRotation R(0.,0.,-boost[ix]); incoming[ix]->pVector(pq[ix]); incoming[ix]->nVector(pq[iswap[ix]]); incoming[ix]->setMomenta(R,1.,Lorentz5Momentum()); jets[ix]->showerMomentum(x[ix]*jets[ix]->pVector()); } // and calculate the boosts applyBoost=true; // do one boost if(_initialBoost==0) { toRest = LorentzRotation(-pcm.boostVector()); } else if(_initialBoost==1) { // first the transverse boost Energy pT = sqrt(sqr(pcm.x())+sqr(pcm.y())); double beta = -pT/pcm.t(); toRest=LorentzRotation(Boost(beta*pcm.x()/pT,beta*pcm.y()/pT,0.)); // the longitudinal beta = pcm.z()/sqrt(pcm.m2()+sqr(pcm.z())); toRest.boost(Boost(0.,0.,-beta)); } else assert(false); fromRest = LorentzRotation((jets[0]->showerMomentum()+ jets[1]->showerMomentum()).boostVector()); } void KinematicsReconstructor:: deconstructFinalStateSystem(const LorentzRotation & toRest, const LorentzRotation & fromRest, HardTreePtr tree, vector jets, ShowerInteraction type) const { LorentzRotation trans = toRest; if(jets.size()==1) { Lorentz5Momentum pnew = toRest*(jets[0]->branchingParticle()->momentum()); pnew *= fromRest; jets[0]-> original(pnew); jets[0]->showerMomentum(pnew); // find the colour partners ShowerParticleVector particles; vector ptemp; set::const_iterator cjt; for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) { ptemp.push_back((**cjt).branchingParticle()->momentum()); (**cjt).branchingParticle()->set5Momentum((**cjt).showerMomentum()); particles.push_back((**cjt).branchingParticle()); } dynamic_ptr_cast(ShowerHandler::currentHandler())->partnerFinder() ->setInitialEvolutionScales(particles,false,type,false); // calculate the reference vectors unsigned int iloc(0); set::iterator clt; for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) { // reset the momentum (**cjt).branchingParticle()->set5Momentum(ptemp[iloc]); ++iloc; // sort out the partners tShowerParticlePtr partner = (*cjt)->branchingParticle()->partner(); if(!partner) continue; for(clt=tree->branchings().begin();clt!=tree->branchings().end();++clt) { if((**clt).branchingParticle()==partner) { (**cjt).colourPartner(*clt); break; } } tHardBranchingPtr branch; for(clt=tree->branchings().begin();clt!=tree->branchings().end();++clt) { if(clt==cjt) continue; if((*clt)->branchingParticle()==partner) { branch=*clt; break; } } } return; } vector::iterator cit; vector pout; vector mon; Lorentz5Momentum pin; for(cit=jets.begin();cit!=jets.end();++cit) { pout.push_back((*cit)->branchingParticle()->momentum()); mon.push_back(findMass(*cit)); pin+=pout.back(); } // boost all the momenta to the rest frame of the decaying particle pin.rescaleMass(); pin *=trans; Boost beta_cm = pin.findBoostToCM(); bool gottaBoost(false); if(beta_cm.mag() > 1e-12) { gottaBoost = true; trans.boost(beta_cm); pin.boost(beta_cm); } for(unsigned int ix=0;ixbranchingParticle()->momentum(); pvect.transform(trans); pvect /= lambda; pvect.setMass(mon[ix]); pvect.rescaleEnergy(); if(gottaBoost) pvect.boost(-beta_cm); pvect.transform(fromRest); jets[ix]->pVector(pvect); jets[ix]->showerMomentum(pvect); } // find the colour partners ShowerParticleVector particles; vector ptemp; set::const_iterator cjt; for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) { ptemp.push_back((**cjt).branchingParticle()->momentum()); (**cjt).branchingParticle()->set5Momentum((**cjt).showerMomentum()); particles.push_back((**cjt).branchingParticle()); } dynamic_ptr_cast(ShowerHandler::currentHandler())->partnerFinder() ->setInitialEvolutionScales(particles,false,type,false); // calculate the reference vectors unsigned int iloc(0); set::iterator clt; for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) { // reset the momentum (**cjt).branchingParticle()->set5Momentum(ptemp[iloc]); ++iloc; } for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) { // sort out the partners tShowerParticlePtr partner = (*cjt)->branchingParticle()->partner(); if(!partner) continue; for(clt=tree->branchings().begin();clt!=tree->branchings().end();++clt) { if((**clt).branchingParticle()==partner) { (**cjt).colourPartner(*clt); break; } } tHardBranchingPtr branch; for(clt=tree->branchings().begin();clt!=tree->branchings().end();++clt) { if(clt==cjt) continue; if((*clt)->branchingParticle()==partner) { branch=*clt; break; } } // compute the reference vectors // both incoming, should all ready be done if((**cjt).status()==HardBranching::Incoming && (**clt).status()==HardBranching::Incoming) { continue; } // both outgoing else if((**cjt).status()!=HardBranching::Incoming&& branch->status()==HardBranching::Outgoing) { Boost boost=((*cjt)->pVector()+branch->pVector()).findBoostToCM(); Lorentz5Momentum pcm = branch->pVector(); pcm.boost(boost); Lorentz5Momentum nvect = Lorentz5Momentum(ZERO,pcm.vect()); nvect.boost( -boost); (**cjt).nVector(nvect); } else if((**cjt).status()==HardBranching::Incoming) { Lorentz5Momentum pa = -(**cjt).showerMomentum()+branch->showerMomentum(); Lorentz5Momentum pb = (**cjt).showerMomentum(); Axis axis(pa.vect().unit()); LorentzRotation rot; double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); rot.setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); rot.rotateX(Constants::pi); rot.boostZ( pa.e()/pa.vect().mag()); pb*=rot; Boost trans = -1./pb.e()*pb.vect(); trans.setZ(0.); rot.boost(trans); Energy scale=(**cjt).beam()->momentum().e(); Lorentz5Momentum pbasis(ZERO,(**cjt).beam()->momentum().vect().unit()*scale); Lorentz5Momentum pcm = rot*pbasis; rot.invert(); (**cjt).nVector(rot*Lorentz5Momentum(ZERO,-pcm.vect())); tHardBranchingPtr branch2 = *cjt;; while (branch2->parent()) { branch2=branch2->parent(); branch2->nVector(rot*Lorentz5Momentum(ZERO,-pcm.vect())); } } else if(branch->status()==HardBranching::Incoming) { (**cjt).nVector(Lorentz5Momentum(ZERO,branch->showerMomentum().vect())); } } // now compute the new momenta for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) { if(!(*cjt)->branchingParticle()->isFinalState()) continue; Lorentz5Momentum qnew; if((*cjt)->branchingParticle()->partner()) { Energy2 dot=(*cjt)->pVector()*(*cjt)->nVector(); double beta = 0.5*((*cjt)->branchingParticle()->momentum().m2() -sqr((*cjt)->pVector().mass()))/dot; qnew=(*cjt)->pVector()+beta*(*cjt)->nVector(); qnew.rescaleMass(); } else { qnew = (*cjt)->pVector(); } // qnew is the unshuffled momentum in the rest frame of the p basis vectors, // for the simple case Z->q qbar g this was checked against analytic formulae. // compute the boost LorentzRotation R=solveBoost(qnew, toRest*(*cjt)->branchingParticle()->momentum())*toRest; (*cjt)->setMomenta(R,1.0,Lorentz5Momentum()); } } Energy KinematicsReconstructor::momConsEq(double k, const Energy & root_s, const JetKinVect & jets) const { static const Energy2 eps=1e-8*GeV2; Energy dum = ZERO; for(JetKinVect::const_iterator it = jets.begin(); it != jets.end(); ++it) { Energy2 dum2 = (it->q).m2() + sqr(k)*(it->p).vect().mag2(); if(dum2 < ZERO) { if(dum2 < -eps) throw KinematicsReconstructionVeto(); dum2 = ZERO; } dum += sqrt(dum2); } return dum - root_s; } void KinematicsReconstructor::boostChain(tPPtr p, const LorentzRotation &bv, tPPtr & parent) const { if(!p->parents().empty()) boostChain(p->parents()[0], bv,parent); else parent=p; p->transform(bv); if(p->children().size()==2) { if(dynamic_ptr_cast(p->children()[1])) deepTransform(p->children()[1],bv); } } namespace { bool sortJets(ShowerProgenitorPtr j1, ShowerProgenitorPtr j2) { return j1->highestpT()>j2->highestpT(); } } void KinematicsReconstructor:: reconstructGeneralSystem(vector & ShowerHardJets) const { // find initial- and final-state systems ColourSingletSystem in,out; for(unsigned int ix=0;ixprogenitor()->isFinalState()) out.jets.push_back(ShowerHardJets[ix]); else in.jets.push_back(ShowerHardJets[ix]); } // reconstruct initial-initial system LorentzRotation toRest,fromRest; bool applyBoost(false); // reconstruct initial-initial system reconstructInitialInitialSystem(applyBoost,toRest,fromRest,in.jets); // reconstruct the final-state systems reconstructFinalStateSystem(applyBoost,toRest,fromRest,out.jets); } void KinematicsReconstructor:: reconstructFinalFirst(vector & ShowerHardJets) const { static const Energy2 minQ2 = 1e-4*GeV2; map used; for(unsigned int ix=0;ix outgoing; // first find any particles with final state partners for(unsigned int ix=0;ixprogenitor()->isFinalState()&& ShowerHardJets[ix]->progenitor()->partner()&& ShowerHardJets[ix]->progenitor()->partner()->isFinalState()) outgoing.insert(ShowerHardJets[ix]); } // then find the colour partners if(!outgoing.empty()) { set partners; for(set::const_iterator it=outgoing.begin();it!=outgoing.end();++it) { for(unsigned int ix=0;ixpartner()==ShowerHardJets[ix]->progenitor()) { partners.insert(ShowerHardJets[ix]); break; } } } outgoing.insert(partners.begin(),partners.end()); } // do the final-state reconstruction if needed if(!outgoing.empty()) { assert(outgoing.size()!=1); LorentzRotation toRest,fromRest; vector outgoingJets(outgoing.begin(),outgoing.end()); reconstructFinalStateSystem(false,toRest,fromRest,outgoingJets); } // Now do any initial-final systems which are needed vector IFSystems; // find the systems N.B. can have duplicates // find initial-state with FS partners or FS with IS partners for(unsigned int ix=0;ixprogenitor()->isFinalState()&& ShowerHardJets[ix]->progenitor()->partner()&& ShowerHardJets[ix]->progenitor()->partner()->isFinalState()) { IFSystems.push_back(ColourSingletSystem(IF,ShowerHardJets[ix])); } else if(ShowerHardJets[ix]->progenitor()->isFinalState()&& ShowerHardJets[ix]->progenitor()->partner()&& !ShowerHardJets[ix]->progenitor()->partner()->isFinalState()) { IFSystems.push_back(ColourSingletSystem(IF,ShowerHardJets[ix])); } } // then add the partners for(unsigned int is=0;isprogenitor()->partner()==ShowerHardJets[ix]->progenitor()) { IFSystems[is].jets.push_back(ShowerHardJets[ix]); } } // ensure incoming first if(IFSystems[is].jets[0]->progenitor()->isFinalState()) swap(IFSystems[is].jets[0],IFSystems[is].jets[1]); } if(!IFSystems.empty()) { unsigned int istart = UseRandom::irnd(IFSystems.size()); unsigned int istop=IFSystems.size(); for(unsigned int is=istart;is<=istop;++is) { if(is==IFSystems.size()) { if(istart!=0) { istop = istart-1; is=0; } else break; } // skip duplicates if(used[IFSystems[is].jets[0]] && used[IFSystems[is].jets[1]] ) continue; if(IFSystems[is].jets[0]->original()&&IFSystems[is].jets[0]->original()->parents().empty()) continue; Lorentz5Momentum psum; for(unsigned int ix=0;ixprogenitor()->isFinalState()) psum += IFSystems[is].jets[ix]->progenitor()->momentum(); else psum -= IFSystems[is].jets[ix]->progenitor()->momentum(); } if(-psum.m2()>minQ2) { reconstructInitialFinalSystem(IFSystems[is].jets); for(unsigned int ix=0;ixprogenitor()->isFinalState()) out.jets.push_back(ShowerHardJets[ix]); else in.jets.push_back(ShowerHardJets[ix]); } // reconstruct initial-initial system bool doRecon = false; for(unsigned int ix=0;ix & ShowerHardJets) const { static const Energy2 minQ2 = 1e-4*GeV2; // sort the vector by hardness of emission std::sort(ShowerHardJets.begin(),ShowerHardJets.end(),sortJets); // map between particles and progenitors for easy lookup map progenitorMap; for(unsigned int ix=0;ixprogenitor()] = ShowerHardJets[ix]; } // check that the IF systems can be reconstructed bool canReconstruct = true; for(unsigned int ix=0;ixprogenitor(); tShowerParticlePtr partner = progenitor->partner(); if(!partner) continue; else if((progenitor->isFinalState() && !partner->isFinalState()) || (!progenitor->isFinalState() && partner->isFinalState()) ) { vector jets(2); jets[0] = ShowerHardJets[ix]; jets[1] = progenitorMap[partner]; Lorentz5Momentum psum; for(unsigned int iy=0;iyprogenitor()->isFinalState()) psum += jets[iy]->progenitor()->momentum(); else psum -= jets[iy]->progenitor()->momentum(); } if(-psum.m2() used; for(unsigned int ix=0;ixreconstructed()==ShowerProgenitor::done) continue; // already reconstructed if(used[ShowerHardJets[ix]]) continue; // no partner continue tShowerParticlePtr progenitor = ShowerHardJets[ix]->progenitor(); tShowerParticlePtr partner = progenitor->partner(); if(!partner) { // check if there's a daughter tree which also needs boosting Lorentz5Momentum porig = progenitor->momentum(); map >::const_iterator tit; for(tit = _currentTree->treelinks().begin(); tit != _currentTree->treelinks().end();++tit) { // if there is, boost it if(tit->second.first && tit->second.second==progenitor) { Lorentz5Momentum pnew = tit->first->incomingLines().begin() ->first->progenitor()->momentum(); pnew *= tit->first->transform(); Lorentz5Momentum pdiff = porig-pnew; Energy2 test = sqr(pdiff.x()) + sqr(pdiff.y()) + sqr(pdiff.z()) + sqr(pdiff.t()); LorentzRotation rot; if(test>1e-6*GeV2) rot = solveBoost(porig,pnew); tit->first->transform(rot,false); _treeBoosts[tit->first].push_back(rot); } } ShowerHardJets[ix]->reconstructed(ShowerProgenitor::done); continue; } // do the reconstruction // final-final if(progenitor->isFinalState() && partner->isFinalState() ) { LorentzRotation toRest,fromRest; vector jets(2); jets[0] = ShowerHardJets[ix]; jets[1] = progenitorMap[partner]; if(_reconopt==4 && jets[1]->reconstructed()==ShowerProgenitor::notReconstructed) jets[1]->reconstructed(ShowerProgenitor::dontReconstruct); reconstructFinalStateSystem(false,toRest,fromRest,jets); if(_reconopt==4 && jets[1]->reconstructed()==ShowerProgenitor::dontReconstruct) jets[1]->reconstructed(ShowerProgenitor::notReconstructed); used[jets[0]] = true; if(_reconopt==3) used[jets[1]] = true; } // initial-final else if((progenitor->isFinalState() && !partner->isFinalState()) || (!progenitor->isFinalState() && partner->isFinalState()) ) { vector jets(2); jets[0] = ShowerHardJets[ix]; jets[1] = progenitorMap[partner]; if(jets[0]->progenitor()->isFinalState()) swap(jets[0],jets[1]); if(jets[0]->original()&&jets[0]->original()->parents().empty()) continue; Lorentz5Momentum psum; for(unsigned int iy=0;iyprogenitor()->isFinalState()) psum += jets[iy]->progenitor()->momentum(); else psum -= jets[iy]->progenitor()->momentum(); } if(_reconopt==4 && progenitorMap[partner]->reconstructed()==ShowerProgenitor::notReconstructed) progenitorMap[partner]->reconstructed(ShowerProgenitor::dontReconstruct); reconstructInitialFinalSystem(jets); if(_reconopt==4 && progenitorMap[partner]->reconstructed()==ShowerProgenitor::dontReconstruct) progenitorMap[partner]->reconstructed(ShowerProgenitor::notReconstructed); used[ShowerHardJets[ix]] = true; if(_reconopt==3) used[progenitorMap[partner]] = true; } // initial-initial else if(!progenitor->isFinalState() && !partner->isFinalState() ) { ColourSingletSystem in,out; in.jets.push_back(ShowerHardJets[ix]); in.jets.push_back(progenitorMap[partner]); for(unsigned int iy=0;iyprogenitor()->isFinalState()) out.jets.push_back(ShowerHardJets[iy]); } LorentzRotation toRest,fromRest; bool applyBoost(false); if(_reconopt==4 && in.jets[1]->reconstructed()==ShowerProgenitor::notReconstructed) in.jets[1]->reconstructed(ShowerProgenitor::dontReconstruct); reconstructInitialInitialSystem(applyBoost,toRest,fromRest,in.jets); if(_reconopt==4 && in.jets[1]->reconstructed()==ShowerProgenitor::dontReconstruct) in.jets[1]->reconstructed(ShowerProgenitor::notReconstructed); used[in.jets[0]] = true; if(_reconopt==3) used[in.jets[1]] = true; for(unsigned int iy=0;iyreconstructed()==ShowerProgenitor::notReconstructed) out.jets[iy]->reconstructed(ShowerProgenitor::dontReconstruct); } // reconstruct the final-state systems LorentzRotation finalBoosts; finalBoosts.transform( toRest); finalBoosts.transform(fromRest); for(unsigned int iy=0;iyprogenitor(),finalBoosts); } for(unsigned int iy=0;iyreconstructed()==ShowerProgenitor::dontReconstruct) out.jets[iy]->reconstructed(ShowerProgenitor::notReconstructed); } } } } bool KinematicsReconstructor:: inverseDecayRescalingFactor(vector pout, vector mon,Energy roots, Lorentz5Momentum ppartner, Energy mbar, double & k1, double & k2) const { ThreeVector qtotal; vector pmag; for(unsigned int ix=0;ix1e10) return false; } while (abs(numer)>eps&&itry<100); k1 = abs(k1); k2 = a*k1; return itry<100; } void KinematicsReconstructor:: deconstructInitialFinalSystem(HardTreePtr tree,vector jets, ShowerInteraction type) const { HardBranchingPtr incoming; Lorentz5Momentum pin[2],pout[2],pbeam; HardBranchingPtr initial; Energy mc(ZERO); for(unsigned int ix=0;ixstatus()==HardBranching::Outgoing) { pout[0] += jets[ix]->branchingParticle()->momentum(); mc = jets[ix]->branchingParticle()->thePEGBase() ? jets[ix]->branchingParticle()->thePEGBase()->mass() : jets[ix]->branchingParticle()->dataPtr()->mass(); } // initial-state parton else { pin[0] += jets[ix]->branchingParticle()->momentum(); initial = jets[ix]; pbeam = jets[ix]->beam()->momentum(); Energy scale=pbeam.t(); pbeam = Lorentz5Momentum(ZERO,pbeam.vect().unit()*scale); incoming = jets[ix]; while(incoming->parent()) incoming = incoming->parent(); } } if(jets.size()>2) { pout[0].rescaleMass(); mc = pout[0].mass(); } // work out the boost to the Breit frame Lorentz5Momentum pa = pout[0]-pin[0]; Axis axis(pa.vect().unit()); LorentzRotation rot; double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); if(axis.perp2()>0.) { rot.setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); rot.rotateX(Constants::pi); rot.boostZ( pa.e()/pa.vect().mag()); } // transverse part Lorentz5Momentum paxis=rot*pbeam; Boost trans = -1./paxis.e()*paxis.vect(); trans.setZ(0.); rot.boost(trans); pa *= rot; // reference vectors Lorentz5Momentum n1(ZERO,ZERO,-pa.z(),-pa.z()); Lorentz5Momentum n2(ZERO,ZERO, pa.z(),-pa.z()); Energy2 n1n2 = n1*n2; // decompose the momenta Lorentz5Momentum qbp=rot*pin[0],qcp= rot*pout[0]; double a[2],b[2]; a[0] = n2*qbp/n1n2; b[0] = n1*qbp/n1n2; a[1] = n2*qcp/n1n2; b[1] = n1*qcp/n1n2; Lorentz5Momentum qperp = qbp-a[0]*n1-b[0]*n2; // before reshuffling Energy Q = abs(pa.z()); double c = sqr(mc/Q); Lorentz5Momentum pb(ZERO,ZERO,0.5*Q*(1.+c),0.5*Q*(1.+c)); Lorentz5Momentum pc(ZERO,ZERO,0.5*Q*(c-1.),0.5*Q*(1.+c)); double anew[2],bnew[2]; anew[0] = pb*n2/n1n2; bnew[0] = 0.5*(qbp.m2()-qperp.m2())/n1n2/anew[0]; bnew[1] = pc*n1/n1n2; anew[1] = 0.5*qcp.m2()/bnew[1]/n1n2; Lorentz5Momentum qnewb = (anew[0]*n1+bnew[0]*n2+qperp); Lorentz5Momentum qnewc = (anew[1]*n1+bnew[1]*n2); // initial-state boost LorentzRotation rotinv=rot.inverse(); LorentzRotation transb=rotinv*solveBoostZ(qnewb,qbp)*rot; // final-state boost LorentzRotation transc=rotinv*solveBoost(qnewc,qcp)*rot; // this will need changing for more than one outgoing particle // set the pvectors for(unsigned int ix=0;ixstatus()==HardBranching::Incoming) { jets[ix]->pVector(pbeam); jets[ix]->showerMomentum(rotinv*pb); incoming->pVector(jets[ix]->pVector()); } else { jets[ix]->pVector(rotinv*pc); jets[ix]->showerMomentum(jets[ix]->pVector()); } } // find the colour partners ShowerParticleVector particles; vector ptemp; set::const_iterator cjt; for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) { ptemp.push_back((**cjt).branchingParticle()->momentum()); (**cjt).branchingParticle()->set5Momentum((**cjt).showerMomentum()); particles.push_back((**cjt).branchingParticle()); } dynamic_ptr_cast(ShowerHandler::currentHandler())->partnerFinder() ->setInitialEvolutionScales(particles,false,type,false); unsigned int iloc(0); for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) { // reset the momentum (**cjt).branchingParticle()->set5Momentum(ptemp[iloc]); ++iloc; } for(vector::const_iterator cjt=jets.begin(); cjt!=jets.end();++cjt) { // sort out the partners tShowerParticlePtr partner = (*cjt)->branchingParticle()->partner(); if(!partner) continue; tHardBranchingPtr branch; for(set::const_iterator clt=tree->branchings().begin();clt!=tree->branchings().end();++clt) { if((**clt).branchingParticle()==partner) { (**cjt).colourPartner(*clt); branch=*clt; break; } } // compute the reference vectors // both incoming, should all ready be done if((**cjt).status()==HardBranching::Incoming && branch->status()==HardBranching::Incoming) { Energy etemp = (*cjt)->beam()->momentum().z(); Lorentz5Momentum nvect(ZERO, ZERO,-etemp, abs(etemp)); tHardBranchingPtr branch2 = *cjt; (**cjt).nVector(nvect); while (branch2->parent()) { branch2=branch2->parent(); branch2->nVector(nvect); } } // both outgoing else if((**cjt).status()==HardBranching::Outgoing&& branch->status()==HardBranching::Outgoing) { Boost boost=((*cjt)->pVector()+branch->pVector()).findBoostToCM(); Lorentz5Momentum pcm = branch->pVector(); pcm.boost(boost); Lorentz5Momentum nvect = Lorentz5Momentum(ZERO,pcm.vect()); nvect.boost( -boost); (**cjt).nVector(nvect); } else if((**cjt).status()==HardBranching::Incoming) { Lorentz5Momentum pa = -(**cjt).showerMomentum()+branch->showerMomentum(); Lorentz5Momentum pb = (**cjt).showerMomentum(); Axis axis(pa.vect().unit()); LorentzRotation rot; double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); if(axis.perp2()>1e-20) { rot.setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); rot.rotateX(Constants::pi); } if(abs(1.-pa.e()/pa.vect().mag())>1e-6) rot.boostZ( pa.e()/pa.vect().mag()); pb*=rot; Boost trans = -1./pb.e()*pb.vect(); trans.setZ(0.); rot.boost(trans); Energy scale=(**cjt).beam()->momentum().t(); Lorentz5Momentum pbasis(ZERO,(**cjt).beam()->momentum().vect().unit()*scale); Lorentz5Momentum pcm = rot*pbasis; rot.invert(); Lorentz5Momentum nvect = rot*Lorentz5Momentum(ZERO,-pcm.vect()); (**cjt).nVector(nvect); tHardBranchingPtr branch2 = *cjt; while (branch2->parent()) { branch2=branch2->parent(); branch2->nVector(nvect); } } else if(branch->status()==HardBranching::Incoming) { Lorentz5Momentum nvect=Lorentz5Momentum(ZERO,branch->showerMomentum().vect()); (**cjt).nVector(nvect); } } // now compute the new momenta for(vector::const_iterator cjt=jets.begin(); cjt!=jets.end();++cjt) { if((**cjt).status()==HardBranching::Outgoing) { (**cjt).setMomenta(transc,1.,Lorentz5Momentum()); } } incoming->setMomenta(transb,1.,Lorentz5Momentum()); } void KinematicsReconstructor::deepTransform(PPtr particle, const LorentzRotation & r, bool match, PPtr original) const { if(_boosts.find(particle)!=_boosts.end()) { _boosts[particle].push_back(r); } Lorentz5Momentum porig = particle->momentum(); if(!original) original = particle; for ( int i = 0, N = particle->children().size(); i < N; ++i ) { deepTransform(particle->children()[i],r, particle->children()[i]->id()==original->id()&&match,original); } particle->transform(r); // transform the p and n vectors ShowerParticlePtr sparticle = dynamic_ptr_cast(particle); if(sparticle && sparticle->showerBasis()) { sparticle->showerBasis()->transform(r); } if ( particle->next() ) deepTransform(particle->next(),r,match,original); if(!match) return; if(!particle->children().empty()) return; // force the mass shell if(particle->dataPtr()->stable()) { Lorentz5Momentum ptemp = particle->momentum(); ptemp.rescaleEnergy(); particle->set5Momentum(ptemp); } // check if there's a daughter tree which also needs boosting map >::const_iterator tit; for(tit = _currentTree->treelinks().begin(); tit != _currentTree->treelinks().end();++tit) { // if there is, boost it if(tit->second.first && tit->second.second==original) { Lorentz5Momentum pnew = tit->first->incomingLines().begin() ->first->progenitor()->momentum(); pnew *= tit->first->transform(); Lorentz5Momentum pdiff = porig-pnew; Energy2 test = sqr(pdiff.x()) + sqr(pdiff.y()) + sqr(pdiff.z()) + sqr(pdiff.t()); LorentzRotation rot; if(test>1e-6*GeV2) rot = solveBoost(porig,pnew); tit->first->transform(r*rot,false); _treeBoosts[tit->first].push_back(r*rot); } } } void KinematicsReconstructor::reconstructFinalFinalOffShell(JetKinVect orderedJets, Energy2 s, bool recursive) const { JetKinVect::iterator jit; jit = orderedJets.begin(); ++jit; // 4-momentum of recoiling system Lorentz5Momentum psum; for( ; jit!=orderedJets.end(); ++jit) psum += jit->p; psum.rescaleMass(); // calculate the 3-momentum rescaling factor Energy2 m1sq(orderedJets.begin()->q.m2()),m2sq(psum.m2()); Energy4 num = sqr(s - m1sq - m2sq) - 4.*m1sq*m2sq; if(nump.vect().mag2()) ); // boost the most off-shell LorentzRotation B1 = solveBoost(k, orderedJets.begin()->q, orderedJets.begin()->p); deepTransform(orderedJets.begin()->parent,B1); // boost everything else // first to rescale LorentzRotation B2 = solveBoost(k, psum, psum); // and then to rest frame of new system Lorentz5Momentum pnew = B2*psum; pnew.rescaleMass(); B2.transform(pnew.findBoostToCM()); // apply transform (calling routine ensures at least 3 elements) jit = orderedJets.begin(); ++jit; for(;jit!=orderedJets.end();++jit) { deepTransform(jit->parent,B2); jit->p *= B2; jit->q *= B2; } JetKinVect newJets(orderedJets.begin()+1,orderedJets.end()); // final reconstruction if(newJets.size()==2 || !recursive ) { // rescaling factor double k = solveKfactor(psum.m(), newJets); // rescale jets in the new CMF for(JetKinVect::iterator it = newJets.begin(); it != newJets.end(); ++it) { LorentzRotation Trafo = solveBoost(k, it->q, it->p); deepTransform(it->parent,Trafo); } } // recursive else { std::sort(newJets.begin(),newJets.end(),JetOrdering()); reconstructFinalFinalOffShell(newJets,psum.m2(),recursive); } // finally boost back from new CMF LorentzRotation back(-pnew.findBoostToCM()); for(JetKinVect::iterator it = newJets.begin(); it != newJets.end(); ++it) { deepTransform(it->parent,back); } } Energy KinematicsReconstructor::findMass(HardBranchingPtr branch) const { // KH - 230909 - If the particle has no children then it will // not have showered and so it should be "on-shell" so we can // get it's mass from it's momentum. This means that the // inverseRescalingFactor doesn't give any nans or do things // it shouldn't if it gets e.g. two Z bosons generated with // off-shell masses. This is for sure not the best solution. // PR 1/1/10 modification to previous soln // PR 28/8/14 change to procedure and factorize into a function if(branch->children().empty()) { return branch->branchingParticle()->mass(); } else if(!branch->children().empty() && !branch->branchingParticle()->dataPtr()->stable() ) { for(unsigned int ix=0;ixchildren().size();++ix) { if(branch->branchingParticle()->id()== branch->children()[ix]->branchingParticle()->id()) return findMass(branch->children()[ix]); } } return branch->branchingParticle()->dataPtr()->mass(); } vector KinematicsReconstructor::inverseInitialStateRescaling(double & x1, double & x2, const Lorentz5Momentum & pold, const vector & p, const vector & pq) const { // hadronic CMS Energy2 s = (pq[0] +pq[1] ).m2(); // partonic CMS Energy MDY = pold.m(); // find alpha, beta and pt Energy2 p12=pq[0]*pq[1]; double a[2],b[2]; Lorentz5Momentum pt[2]; for(unsigned int ix=0;ix<2;++ix) { a[ix] = p[ix]*pq[1]/p12; b [ix] = p[ix]*pq[0]/p12; pt[ix] = p[ix]-a[ix]*pq[0]-b[ix]*pq[1]; } // compute kappa // we always want to preserve the mass of the system double k1(1.),k2(1.); if(_initialStateReconOption==0) { double rap=pold.rapidity(); x2 = MDY/sqrt(s*exp(2.*rap)); x1 = sqr(MDY)/s/x2; k1=a[0]/x1; k2=b[1]/x2; } // longitudinal momentum else if(_initialStateReconOption==1) { double A = 1.; double C = -sqr(MDY)/s; double B = 2.*pold.z()/sqrt(s); if(abs(B)>1e-10) { double discrim = 1.-4.*A*C/sqr(B); if(discrim < 0.) throw KinematicsReconstructionVeto(); x1 = B>0. ? 0.5*B/A*(1.+sqrt(discrim)) : 0.5*B/A*(1.-sqrt(discrim)); } else { x1 = -C/A; if( x1 <= 0.) throw KinematicsReconstructionVeto(); x1 = sqrt(x1); } x2 = sqr(MDY)/s/x1; k1=a[0]/x1; k2=b[1]/x2; } // preserve mass and don't scale the softer system // to reproduce the dipole kinematics else if(_initialStateReconOption==2) { // in this case kp = k1 or k2 depending on who's the harder guy k1 = a[0]*b[1]*s/sqr(MDY); if ( pt[0].perp2() < pt[1].perp2() ) swap(k1,k2); x1 = a[0]/k1; x2 = b[1]/k2; } else assert(false); // decompose the momenta double anew[2] = {a[0]/k1,a[1]*k2}; double bnew[2] = {b[0]*k1,b[1]/k2}; vector boost(2); for(unsigned int ix=0;ix<2;++ix) { boost[ix] = getBeta(a [ix]+b [ix], a[ix] -b [ix], anew[ix]+bnew[ix], anew[ix]-bnew[ix]); } return boost; } vector KinematicsReconstructor::initialStateRescaling(double x1, double x2, const Lorentz5Momentum & pold, const vector & p, const vector & pq, const vector& highestpts) const { Energy2 S = (pq[0]+pq[1]).m2(); // find alphas and betas in terms of desired basis Energy2 p12 = pq[0]*pq[1]; double a[2] = {p[0]*pq[1]/p12,p[1]*pq[1]/p12}; double b[2] = {p[0]*pq[0]/p12,p[1]*pq[0]/p12}; Lorentz5Momentum p1p = p[0] - a[0]*pq[0] - b[0]*pq[1]; Lorentz5Momentum p2p = p[1] - a[1]*pq[0] - b[1]*pq[1]; // compute kappa // we always want to preserve the mass of the system Energy MDY = pold.m(); Energy2 A = a[0]*b[1]*S; Energy2 B = Energy2(sqr(MDY)) - (a[0]*b[0]+a[1]*b[1])*S - (p1p+p2p).m2(); Energy2 C = a[1]*b[0]*S; double rad = 1.-4.*A*C/sqr(B); if(rad < 0.) throw KinematicsReconstructionVeto(); double kp = B/(2.*A)*(1.+sqrt(rad)); // now compute k1 // conserve rapidity double k1(0.); double k2(0.); if(_initialStateReconOption==0) { rad = kp*(b[0]+kp*b[1])/(kp*a[0]+a[1]); rad *= pq[0].z()1e-10) { double discrim = 1.-4.*a2*c2/sqr(b2); if(discrim < 0.) throw KinematicsReconstructionVeto(); k1 = b2>0. ? 0.5*b2/a2*(1.+sqrt(discrim)) : 0.5*b2/a2*(1.-sqrt(discrim)); } else { k1 = -c2/a2; if( k1 <= 0.) throw KinematicsReconstructionVeto(); k1 = sqrt(k1); } k2 = kp/k1; } // preserve mass and don't scale the softer system // to reproduce the dipole kinematics else if(_initialStateReconOption==2) { // in this case kp = k1 or k2 depending on who's the harder guy k1 = kp; k2 = 1.; if ( highestpts[0] < highestpts[1] ) swap(k1,k2); } else assert(false); // calculate the boosts vector beta(2); beta[0] = getBeta((a[0]+b[0]), (a[0]-b[0]), (k1*a[0]+b[0]/k1), (k1*a[0]-b[0]/k1)); beta[1] = getBeta((a[1]+b[1]), (a[1]-b[1]), (a[1]/k2+k2*b[1]), (a[1]/k2-k2*b[1])); if (pq[0].z() > ZERO) { beta[0] = -beta[0]; beta[1] = -beta[1]; } return beta; } void KinematicsReconstructor:: reconstructColourSinglets(vector & ShowerHardJets, ShowerInteraction type) const { // identify and catagorize the colour singlet systems unsigned int nnun(0),nnii(0),nnif(0),nnf(0),nni(0); vector systems(identifySystems(set(ShowerHardJets.begin(),ShowerHardJets.end()), nnun,nnii,nnif,nnf,nni)); // now decide what to do // initial-initial connection and final-state colour singlet systems LorentzRotation toRest,fromRest; bool applyBoost(false),general(false); // Drell-Yan type if(nnun==0&&nnii==1&&nnif==0&&nnf>0&&nni==0) { // reconstruct initial-initial system for(unsigned int ix=0;ix0&&nni==1)|| (nnif==2&& nni==0))) { // check these systems can be reconstructed for(unsigned int ix=0;ixprogenitor()->isFinalState()) q += systems[ix].jets[iy]->progenitor()->momentum(); else q -= systems[ix].jets[iy]->progenitor()->momentum(); } q.rescaleMass(); // check above cut if(abs(q.m())>=_minQ) continue; if(nnif==1&&nni==1) { throw KinematicsReconstructionVeto(); } else { general = true; break; } } if(!general) { for(unsigned int ix=0;ix0&&nni==2) { general = type!=ShowerInteraction::QCD; } // general type else { general = true; } // final-state systems except for general recon if(!general) { for(unsigned int ix=0;ix> _splittingGenerator >> _maxtry >> _meCorrMode >> _hardVetoReadOption >> _limitEmissions >> _spinOpt >> _softOpt >> _hardPOWHEG >> iunit(_iptrms,GeV) >> _beta >> iunit(_gamma,GeV) >> iunit(_iptmax,GeV) >> _vetoes >> _fullShowerVetoes >> _nReWeight >> _reWeight >> _trunc_Mode >> _hardEmission >> _reconOpt >> iunit(muPt,GeV) >> ienum(interaction_) >> _reconstructor >> _partnerfinder; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigQTildeShowerHandler("Herwig::QTildeShowerHandler", "HwShower.so"); void QTildeShowerHandler::Init() { static ClassDocumentation documentation ("TheQTildeShowerHandler class is the main class" " for the angular-ordered parton shower", "The Shower evolution was performed using an algorithm described in " "\\cite{Marchesini:1983bm,Marchesini:1987cf,Gieseke:2003rz,Bahr:2008pv}.", "%\\cite{Marchesini:1983bm}\n" "\\bibitem{Marchesini:1983bm}\n" " G.~Marchesini and B.~R.~Webber,\n" " ``Simulation Of QCD Jets Including Soft Gluon Interference,''\n" " Nucl.\\ Phys.\\ B {\\bf 238}, 1 (1984).\n" " %%CITATION = NUPHA,B238,1;%%\n" "%\\cite{Marchesini:1987cf}\n" "\\bibitem{Marchesini:1987cf}\n" " G.~Marchesini and B.~R.~Webber,\n" " ``Monte Carlo Simulation of General Hard Processes with Coherent QCD\n" " Radiation,''\n" " Nucl.\\ Phys.\\ B {\\bf 310}, 461 (1988).\n" " %%CITATION = NUPHA,B310,461;%%\n" "%\\cite{Gieseke:2003rz}\n" "\\bibitem{Gieseke:2003rz}\n" " S.~Gieseke, P.~Stephens and B.~Webber,\n" " ``New formalism for QCD parton showers,''\n" " JHEP {\\bf 0312}, 045 (2003)\n" " [arXiv:hep-ph/0310083].\n" " %%CITATION = JHEPA,0312,045;%%\n" ); static Reference interfaceSplitGen("SplittingGenerator", "A reference to the SplittingGenerator object", &Herwig::QTildeShowerHandler::_splittingGenerator, false, false, true, false); static Parameter interfaceMaxTry ("MaxTry", "The maximum number of attempts to generate the shower from a" " particular ShowerTree", &QTildeShowerHandler::_maxtry, 100, 1, 100000, false, false, Interface::limited); static Parameter interfaceNReWeight ("NReWeight", "The number of attempts for the shower when reweighting", &QTildeShowerHandler::_nReWeight, 100, 10, 10000, false, false, Interface::limited); static Switch ifaceMECorrMode ("MECorrMode", "Choice of the ME Correction Mode", &QTildeShowerHandler::_meCorrMode, 1, false, false); static SwitchOption on (ifaceMECorrMode,"HardPlusSoft","hard+soft on", 1); static SwitchOption hard (ifaceMECorrMode,"Hard","only hard on", 2); static SwitchOption soft (ifaceMECorrMode,"Soft","only soft on", 3); static Switch ifaceHardVetoReadOption ("HardVetoReadOption", "Apply read-in scale veto to all collisions or just the primary one?", &QTildeShowerHandler::_hardVetoReadOption, false, false, false); static SwitchOption AllCollisions (ifaceHardVetoReadOption, "AllCollisions", "Read-in pT veto applied to primary and secondary collisions.", false); static SwitchOption PrimaryCollision (ifaceHardVetoReadOption, "PrimaryCollision", "Read-in pT veto applied to primary but not secondary collisions.", true); static Parameter ifaceiptrms ("IntrinsicPtGaussian", "RMS of intrinsic pT of Gaussian distribution:\n" "2*(1-Beta)*exp(-sqr(intrinsicpT/RMS))/sqr(RMS)", &QTildeShowerHandler::_iptrms, GeV, ZERO, ZERO, 1000000.0*GeV, false, false, Interface::limited); static Parameter ifacebeta ("IntrinsicPtBeta", "Proportion of inverse quadratic distribution in generating intrinsic pT.\n" "(1-Beta) is the proportion of Gaussian distribution", &QTildeShowerHandler::_beta, 0, 0, 1, false, false, Interface::limited); static Parameter ifacegamma ("IntrinsicPtGamma", "Parameter for inverse quadratic:\n" "2*Beta*Gamma/(sqr(Gamma)+sqr(intrinsicpT))", &QTildeShowerHandler::_gamma,GeV, ZERO, ZERO, 100000.0*GeV, false, false, Interface::limited); static Parameter ifaceiptmax ("IntrinsicPtIptmax", "Upper bound on intrinsic pT for inverse quadratic", &QTildeShowerHandler::_iptmax,GeV, ZERO, ZERO, 100000.0*GeV, false, false, Interface::limited); static RefVector ifaceVetoes ("Vetoes", "The vetoes to be checked during showering", &QTildeShowerHandler::_vetoes, -1, false,false,true,true,false); static RefVector interfaceFullShowerVetoes ("FullShowerVetoes", "The vetos to be appliede on the full final state of the shower", &QTildeShowerHandler::_fullShowerVetoes, -1, false, false, true, false, false); static Switch interfaceLimitEmissions ("LimitEmissions", "Limit the number and type of emissions for testing", &QTildeShowerHandler::_limitEmissions, 0, false, false); static SwitchOption interfaceLimitEmissionsNoLimit (interfaceLimitEmissions, "NoLimit", "Allow an arbitrary number of emissions", 0); static SwitchOption interfaceLimitEmissionsOneInitialStateEmission (interfaceLimitEmissions, "OneInitialStateEmission", "Allow one emission in the initial state and none in the final state", 1); static SwitchOption interfaceLimitEmissionsOneFinalStateEmission (interfaceLimitEmissions, "OneFinalStateEmission", "Allow one emission in the final state and none in the initial state", 2); static SwitchOption interfaceLimitEmissionsHardOnly (interfaceLimitEmissions, "HardOnly", "Only allow radiation from the hard ME correction", 3); static SwitchOption interfaceLimitEmissionsOneEmission (interfaceLimitEmissions, "OneEmission", "Allow one emission in either the final state or initial state, but not both", 4); static Switch interfaceTruncMode ("TruncatedShower", "Include the truncated shower?", &QTildeShowerHandler::_trunc_Mode, 1, false, false); static SwitchOption interfaceTruncMode0 (interfaceTruncMode,"No","Truncated Shower is OFF", 0); static SwitchOption interfaceTruncMode1 (interfaceTruncMode,"Yes","Truncated Shower is ON", 1); static Switch interfaceHardEmission ("HardEmission", "Whether to use ME corrections or POWHEG for the hardest emission", &QTildeShowerHandler::_hardEmission, 0, false, false); static SwitchOption interfaceHardEmissionNone (interfaceHardEmission, "None", "No Corrections", 0); static SwitchOption interfaceHardEmissionMECorrection (interfaceHardEmission, "MECorrection", "Old fashioned ME correction", 1); static SwitchOption interfaceHardEmissionPOWHEG (interfaceHardEmission, "POWHEG", "Powheg style hard emission", 2); static Switch interfaceInteractions ("Interactions", "The interactions to be used in the shower", &QTildeShowerHandler::interaction_, ShowerInteraction::Both, false, false); static SwitchOption interfaceInteractionsQCD (interfaceInteractions, "QCD", "Only QCD radiation", ShowerInteraction::QCD); static SwitchOption interfaceInteractionsQED (interfaceInteractions, "QED", "Only QEd radiation", ShowerInteraction::QED); static SwitchOption interfaceInteractionsQCDandQED (interfaceInteractions, "QCDandQED", "Both QED and QCD radiation", ShowerInteraction::Both); static Switch interfaceReconstructionOption ("ReconstructionOption", "Treatment of the reconstruction of the transverse momentum of " "a branching from the evolution scale.", &QTildeShowerHandler::_reconOpt, 0, false, false); static SwitchOption interfaceReconstructionOptionCutOff (interfaceReconstructionOption, "CutOff", "Use the cut-off masses in the calculation", 0); static SwitchOption interfaceReconstructionOptionOffShell5 (interfaceReconstructionOption, "OffShell5", "Try and preserve q2 but if pt negative just zero it", 5); static Switch interfaceSpinCorrelations ("SpinCorrelations", "Treatment of spin correlations in the parton shower", &QTildeShowerHandler::_spinOpt, 1, false, false); static SwitchOption interfaceSpinCorrelationsNo (interfaceSpinCorrelations, "No", "No spin correlations", 0); static SwitchOption interfaceSpinCorrelationsSpin (interfaceSpinCorrelations, "Yes", "Include the azimuthal spin correlations only", 1); static Switch interfaceSoftCorrelations ("SoftCorrelations", "Option for the treatment of soft correlations in the parton shower", &QTildeShowerHandler::_softOpt, 2, false, false); static SwitchOption interfaceSoftCorrelationsNone (interfaceSoftCorrelations, "No", "No soft correlations", 0); static SwitchOption interfaceSoftCorrelationsFull (interfaceSoftCorrelations, "Full", "Use the full eikonal", 1); static SwitchOption interfaceSoftCorrelationsSingular (interfaceSoftCorrelations, "Singular", "Use original Webber-Marchisini form", 2); static Switch interfaceHardPOWHEG ("HardPOWHEG", "Treatment of powheg emissions which are too hard to have a shower interpretation", &QTildeShowerHandler::_hardPOWHEG, false, false, false); static SwitchOption interfaceHardPOWHEGAsShower (interfaceHardPOWHEG, "AsShower", "Still interpret as shower emissions", false); static SwitchOption interfaceHardPOWHEGRealEmission (interfaceHardPOWHEG, "RealEmission", "Generate shower from the real emmission configuration", true); static Reference interfaceKinematicsReconstructor ("KinematicsReconstructor", "Reference to the KinematicsReconstructor object", &QTildeShowerHandler::_reconstructor, false, false, true, false, false); static Reference interfacePartnerFinder ("PartnerFinder", "Reference to the PartnerFinder object", &QTildeShowerHandler::_partnerfinder, false, false, true, false, false); } tPPair QTildeShowerHandler::cascade(tSubProPtr sub, XCPtr xcomb) { // use me for reference in tex file etc useMe(); prepareCascade(sub); // set things up in the base class resetWeights(); hard_=ShowerTreePtr(); decay_.clear(); done_.clear(); - // check if anything needs doing - if ( !doFSR() && ! doISR() ) - return sub->incoming(); // start of the try block for the whole showering process unsigned int countFailures=0; while (countFailuresoutgoing().begin(), currentSubProcess()->outgoing().end()), hard,decay); ShowerTree::constructTrees(hard_,decay_,hard,decay); // if no hard process if(!hard_) throw Exception() << "Shower starting with a decay" << "is not implemented" << Exception::runerror; // perform the shower for the hard process showerHardProcess(hard_,xcomb); done_.push_back(hard_); hard_->updateAfterShower(decay_); // if no decaying particles to shower break out of the loop if(decay_.empty()) break; // shower the decay products while(!decay_.empty()) { // find particle whose production process has been showered ShowerDecayMap::iterator dit = decay_.begin(); while(!dit->second->parent()->hasShowered() && dit!=decay_.end()) ++dit; assert(dit!=decay_.end()); // get the particle ShowerTreePtr decayingTree = dit->second; // remove it from the multimap decay_.erase(dit); // make sure the particle has been decayed QTildeShowerHandler::decay(decayingTree,decay_); // now shower the decay showerDecay(decayingTree); done_.push_back(decayingTree); decayingTree->updateAfterShower(decay_); } // suceeded break out of the loop break; } catch (KinematicsReconstructionVeto) { resetWeights(); ++countFailures; } catch ( ... ) { hard_=ShowerTreePtr(); decay_.clear(); done_.clear(); throw; } } // if loop exited because of too many tries, throw event away if (countFailures >= maxtry()) { resetWeights(); hard_=ShowerTreePtr(); decay_.clear(); done_.clear(); throw Exception() << "Too many tries for main while loop " << "in QTildeShowerHandler::cascade()." << Exception::eventerror; } //enter the particles in the event record fillEventRecord(); // clear storage hard_=ShowerTreePtr(); decay_.clear(); done_.clear(); // non hadronic case return if (!isResolvedHadron(incomingBeams().first ) && !isResolvedHadron(incomingBeams().second) ) return incomingBeams(); // remake the remnants (needs to be after the colours are sorted // out in the insertion into the event record) if ( firstInteraction() ) return remakeRemnant(sub->incoming()); //Return the new pair of incoming partons. remakeRemnant is not //necessary here, because the secondary interactions are not yet //connected to the remnants. return make_pair(findFirstParton(sub->incoming().first ), findFirstParton(sub->incoming().second)); } void QTildeShowerHandler::fillEventRecord() { // create a new step StepPtr pstep = newStep(); assert(!done_.empty()); assert(done_[0]->isHard()); // insert the steps for(unsigned int ix=0;ixfillEventRecord(pstep,doISR(),doFSR()); } } HardTreePtr QTildeShowerHandler::generateCKKW(ShowerTreePtr ) const { return HardTreePtr(); } void QTildeShowerHandler::doinit() { ShowerHandler::doinit(); // check on the reweighting for(unsigned int ix=0;ix<_fullShowerVetoes.size();++ix) { if(_fullShowerVetoes[ix]->behaviour()==1) { _reWeight = true; break; } } if(_reWeight && maximumTries()<_nReWeight) { throw Exception() << "Reweight being performed in the shower but the number of attempts for the" << "shower is less than that for the reweighting.\n" << "Maximum number of attempt for the shower " << fullName() << ":MaxTry is " << maximumTries() << "\nand for reweighting is " << fullName() << ":NReWeight is " << _nReWeight << "\n" << "we recommend the number of attempts is 10 times the number for reweighting\n" << Exception::runerror; } ShowerTree::_vmin2 = vMin(); ShowerTree::_spaceTime = includeSpaceTime(); } void QTildeShowerHandler::doinitrun() { ShowerHandler::doinitrun(); ShowerTree::_vmin2 = vMin(); ShowerTree::_spaceTime = includeSpaceTime(); } void QTildeShowerHandler::generateIntrinsicpT(vector particlesToShower) { _intrinsic.clear(); if ( !ipTon() || !doISR() ) return; // don't do anything for the moment for secondary scatters if( !firstInteraction() ) return; // generate intrinsic pT for(unsigned int ix=0;ixprogenitor()->isFinalState()) continue; if(!particlesToShower[ix]->progenitor()->dataPtr()->coloured()) continue; Energy ipt; if(UseRandom::rnd() > _beta) { ipt=_iptrms*sqrt(-log(UseRandom::rnd())); } else { ipt=_gamma*sqrt(pow(1.+sqr(_iptmax/_gamma), UseRandom::rnd())-1.); } pair pt = make_pair(ipt,UseRandom::rnd(Constants::twopi)); _intrinsic[particlesToShower[ix]] = pt; } } void QTildeShowerHandler::setupMaximumScales(const vector & p, XCPtr xcomb) { // let POWHEG events radiate freely if(_hardEmission==2&&hardTree()) { vector::const_iterator ckt = p.begin(); for (; ckt != p.end(); ckt++) (*ckt)->maxHardPt(Constants::MaxEnergy); return; } // return if no vetos if (!restrictPhasespace()) return; // find out if hard partonic subprocess. bool isPartonic(false); map::const_iterator cit = _currenttree->incomingLines().begin(); Lorentz5Momentum pcm; for(; cit!=currentTree()->incomingLines().end(); ++cit) { pcm += cit->first->progenitor()->momentum(); isPartonic |= cit->first->progenitor()->coloured(); } // find minimum pt from hard process, the maximum pt from all outgoing // coloured lines (this is simpler and more general than // 2stu/(s^2+t^2+u^2)). Maximum scale for scattering processes will // be transverse mass. Energy ptmax = generator()->maximumCMEnergy(); // general case calculate the scale if ( !hardScaleIsMuF() || (hardVetoReadOption()&&!firstInteraction()) ) { // scattering process if(currentTree()->isHard()) { assert(xcomb); // coloured incoming particles if (isPartonic) { map::const_iterator cjt = currentTree()->outgoingLines().begin(); for(; cjt!=currentTree()->outgoingLines().end(); ++cjt) { if (cjt->first->progenitor()->coloured()) ptmax = min(ptmax,cjt->first->progenitor()->momentum().mt()); } } if (ptmax == generator()->maximumCMEnergy() ) ptmax = pcm.m(); if(hardScaleIsMuF()&&hardVetoReadOption()&& !firstInteraction()) { ptmax=min(ptmax,sqrt(xcomb->lastShowerScale())); } } // decay, incoming() is the decaying particle. else { ptmax = currentTree()->incomingLines().begin()->first ->progenitor()->momentum().mass(); } } // hepeup.SCALUP is written into the lastXComb by the // LesHouchesReader itself - use this by user's choice. // Can be more general than this. else { if(currentTree()->isHard()) { assert(xcomb); ptmax = sqrt( xcomb->lastShowerScale() ); } else { ptmax = currentTree()->incomingLines().begin()->first ->progenitor()->momentum().mass(); } } ptmax *= hardScaleFactor(); // set maxHardPt for all progenitors. For partonic processes this // is now the max pt in the FS, for non-partonic processes or // processes with no coloured FS the invariant mass of the IS vector::const_iterator ckt = p.begin(); for (; ckt != p.end(); ckt++) (*ckt)->maxHardPt(ptmax); } void QTildeShowerHandler::setupHardScales(const vector & p, XCPtr xcomb) { if ( hardScaleIsMuF() && (!hardVetoReadOption() || firstInteraction()) ) { Energy hardScale = ZERO; if(currentTree()->isHard()) { assert(xcomb); hardScale = sqrt( xcomb->lastShowerScale() ); } else { hardScale = currentTree()->incomingLines().begin()->first ->progenitor()->momentum().mass(); } hardScale *= hardScaleFactor(); vector::const_iterator ckt = p.begin(); for (; ckt != p.end(); ckt++) (*ckt)->hardScale(hardScale); muPt = hardScale; } } void QTildeShowerHandler::showerHardProcess(ShowerTreePtr hard, XCPtr xcomb) { _hardme = HwMEBasePtr(); // extract the matrix element tStdXCombPtr lastXC = dynamic_ptr_cast(xcomb); if(lastXC) { _hardme = dynamic_ptr_cast(lastXC->matrixElement()); } _decayme = HwDecayerBasePtr(); // set the current tree currentTree(hard); hardTree(HardTreePtr()); // work out the type of event currentTree()->xcombPtr(dynamic_ptr_cast(xcomb)); currentTree()->identifyEventType(); checkFlags(); // generate the showering doShowering(true,xcomb); } RealEmissionProcessPtr QTildeShowerHandler::hardMatrixElementCorrection(bool hard) { // set the initial enhancement factors for the soft correction _initialenhance = 1.; _finalenhance = 1.; // see if we can get the correction from the matrix element // or decayer RealEmissionProcessPtr real; if(hard) { if(_hardme&&_hardme->hasMECorrection()) { _hardme->initializeMECorrection(_currenttree->perturbativeProcess(), _initialenhance,_finalenhance); if(hardMEC()) real = _hardme->applyHardMatrixElementCorrection(_currenttree->perturbativeProcess()); } } else { if(_decayme&&_decayme->hasMECorrection()) { _decayme->initializeMECorrection(_currenttree->perturbativeProcess(), _initialenhance,_finalenhance); if(hardMEC()) real = _decayme->applyHardMatrixElementCorrection(_currenttree->perturbativeProcess()); } } return real; } ShowerParticleVector QTildeShowerHandler::createTimeLikeChildren(tShowerParticlePtr, IdList ids) { // Create the ShowerParticle objects for the two children of // the emitting particle; set the parent/child relationship // if same as definition create particles, otherwise create cc ShowerParticleVector children; for(unsigned int ix=0;ix<2;++ix) { children.push_back(new_ptr(ShowerParticle(ids[ix+1],true))); - if(children[ix]->id()==_progenitor->id()&&!ids[ix+1]->stable()) + if(children[ix]->id()==_progenitor->id()&&!ids[ix+1]->stable()&&abs(ids[ix+1]->id())!=ParticleID::tauminus) children[ix]->set5Momentum(Lorentz5Momentum(_progenitor->progenitor()->mass())); else children[ix]->set5Momentum(Lorentz5Momentum(ids[ix+1]->mass())); } return children; } bool QTildeShowerHandler::timeLikeShower(tShowerParticlePtr particle, ShowerInteraction type, Branching fb, bool first) { // don't do anything if not needed if(_limitEmissions == 1 || hardOnly() || ( _limitEmissions == 2 && _nfs != 0) || ( _limitEmissions == 4 && _nfs + _nis != 0) ) { if(particle->spinInfo()) particle->spinInfo()->develop(); return false; } // generate the emission ShowerParticleVector children; // generate the emission if(!fb.kinematics) fb = selectTimeLikeBranching(particle,type,HardBranchingPtr()); // no emission, return if(!fb.kinematics) { if(particle->spinInfo()) particle->spinInfo()->develop(); return false; } Branching fc[2] = {Branching(),Branching()}; assert(fb.kinematics); // has emitted // Assign the shower kinematics to the emitting particle. particle->showerKinematics(fb.kinematics); // check highest pT if(fb.kinematics->pT()>progenitor()->highestpT()) progenitor()->highestpT(fb.kinematics->pT()); // create the children children = createTimeLikeChildren(particle,fb.ids); // update the children particle->showerKinematics()-> updateChildren(particle, children,fb.type); // update number of emissions ++_nfs; if(_limitEmissions!=0) { if(children[0]->spinInfo()) children[0]->spinInfo()->develop(); if(children[1]->spinInfo()) children[1]->spinInfo()->develop(); if(particle->spinInfo()) particle->spinInfo()->develop(); return true; } // select branchings for children fc[0] = selectTimeLikeBranching(children[0],type,HardBranchingPtr()); fc[1] = selectTimeLikeBranching(children[1],type,HardBranchingPtr()); // shower the first particle if(fc[0].kinematics) timeLikeShower(children[0],type,fc[0],false); if(children[0]->spinInfo()) children[0]->spinInfo()->develop(); // shower the second particle if(fc[1].kinematics) timeLikeShower(children[1],type,fc[1],false); if(children[1]->spinInfo()) children[1]->spinInfo()->develop(); if(_reconOpt>=1) particle->showerKinematics()->updateParent(particle, children,fb.type); // branching has happened if(first&&!children.empty()) particle->showerKinematics()->resetChildren(particle,children); if(particle->spinInfo()) particle->spinInfo()->develop(); return true; } bool QTildeShowerHandler::spaceLikeShower(tShowerParticlePtr particle, PPtr beam, ShowerInteraction type) { //using the pdf's associated with the ShowerHandler assures, that //modified pdf's are used for the secondary interactions via //CascadeHandler::resetPDFs(...) tcPDFPtr pdf; if(firstPDF().particle() == _beam) pdf = firstPDF().pdf(); if(secondPDF().particle() == _beam) pdf = secondPDF().pdf(); Energy freeze = pdfFreezingScale(); // don't do anything if not needed if(_limitEmissions == 2 || hardOnly() || ( _limitEmissions == 1 && _nis != 0 ) || ( _limitEmissions == 4 && _nis + _nfs != 0 ) ) { if(particle->spinInfo()) particle->spinInfo()->develop(); return false; } Branching bb; // generate branching while (true) { bb=_splittingGenerator->chooseBackwardBranching(*particle,beam, _initialenhance, _beam,type, pdf,freeze); // return if no emission if(!bb.kinematics) { if(particle->spinInfo()) particle->spinInfo()->develop(); return false; } // if not vetoed break if(!spaceLikeVetoed(bb,particle)) break; // otherwise reset scale and continue particle->vetoEmission(bb.type,bb.kinematics->scale()); if(particle->spinInfo()) particle->spinInfo()->decayVertex(VertexPtr()); } // assign the splitting function and shower kinematics particle->showerKinematics(bb.kinematics); if(bb.kinematics->pT()>progenitor()->highestpT()) progenitor()->highestpT(bb.kinematics->pT()); // For the time being we are considering only 1->2 branching // particles as in Sudakov form factor tcPDPtr part[2]={bb.ids[0],bb.ids[2]}; // Now create the actual particles, make the otherChild a final state // particle, while the newParent is not ShowerParticlePtr newParent = new_ptr(ShowerParticle(part[0],false)); ShowerParticlePtr otherChild = new_ptr(ShowerParticle(part[1],true,true)); ShowerParticleVector theChildren; theChildren.push_back(particle); theChildren.push_back(otherChild); //this updates the evolution scale particle->showerKinematics()-> updateParent(newParent, theChildren,bb.type); // update the history if needed _currenttree->updateInitialStateShowerProduct(_progenitor,newParent); _currenttree->addInitialStateBranching(particle,newParent,otherChild); // for the reconstruction of kinematics, parent/child // relationships are according to the branching process: // now continue the shower ++_nis; bool emitted = _limitEmissions==0 ? spaceLikeShower(newParent,beam,type) : false; if(newParent->spinInfo()) newParent->spinInfo()->develop(); // now reconstruct the momentum if(!emitted) { if(_intrinsic.find(_progenitor)==_intrinsic.end()) { bb.kinematics->updateLast(newParent,ZERO,ZERO); } else { pair kt=_intrinsic[_progenitor]; bb.kinematics->updateLast(newParent, kt.first*cos(kt.second), kt.first*sin(kt.second)); } } particle->showerKinematics()-> updateChildren(newParent, theChildren,bb.type); if(_limitEmissions!=0) { if(particle->spinInfo()) particle->spinInfo()->develop(); return true; } // perform the shower of the final-state particle timeLikeShower(otherChild,type,Branching(),true); updateHistory(otherChild); if(theChildren[1]->spinInfo()) theChildren[1]->spinInfo()->develop(); // return the emitted if(particle->spinInfo()) particle->spinInfo()->develop(); return true; } void QTildeShowerHandler::showerDecay(ShowerTreePtr decay) { // work out the type of event currentTree()->xcombPtr(StdXCombPtr()); currentTree()->identifyEventType(); _decayme = HwDecayerBasePtr(); _hardme = HwMEBasePtr(); // find the decayer // try the normal way if possible tDMPtr dm = decay->incomingLines().begin()->first->original() ->decayMode(); if(!dm) dm = decay->incomingLines().begin()->first->copy() ->decayMode(); if(!dm) dm = decay->incomingLines().begin()->first->progenitor()->decayMode(); // otherwise make a string and look it up if(!dm) { string tag = decay->incomingLines().begin()->first->original()->dataPtr()->name() + "->"; OrderedParticles outgoing; for(map::const_iterator it=decay->outgoingLines().begin();it!=decay->outgoingLines().end();++it) { if(abs(decay->incomingLines().begin()->first->original()->id()) == ParticleID::t && abs(it->first->original()->id())==ParticleID::Wplus && decay->treelinks().size() == 1) { ShowerTreePtr Wtree = decay->treelinks().begin()->first; for(map::const_iterator it2=Wtree->outgoingLines().begin();it2!=Wtree->outgoingLines().end();++it2) { outgoing.insert(it2->first->original()->dataPtr()); } } else { outgoing.insert(it->first->original()->dataPtr()); } } for(OrderedParticles::const_iterator it=outgoing.begin(); it!=outgoing.end();++it) { if(it!=outgoing.begin()) tag += ","; tag +=(**it).name(); } tag += ";"; dm = findDecayMode(tag); } if(dm) _decayme = dynamic_ptr_cast(dm->decayer()); // set the ShowerTree to be showered currentTree(decay); decay->applyTransforms(); hardTree(HardTreePtr()); // generate the showering doShowering(false,XCPtr()); // if no vetos // force calculation of spin correlations SpinPtr spInfo = decay->incomingLines().begin()->first->progenitor()->spinInfo(); if(spInfo) { if(!spInfo->developed()) spInfo->needsUpdate(); spInfo->develop(); } } bool QTildeShowerHandler::spaceLikeDecayShower(tShowerParticlePtr particle, const ShowerParticle::EvolutionScales & maxScales, Energy minmass,ShowerInteraction type, Branching fb) { // don't do anything if not needed if(_limitEmissions == 1 || hardOnly() || ( _limitEmissions == 3 && _nis != 0) || ( _limitEmissions == 4 && _nfs + _nis != 0) ) { return false; } // generate the emission ShowerParticleVector children; // generate the emission if(!fb.kinematics) fb = selectSpaceLikeDecayBranching(particle,maxScales,minmass,type, HardBranchingPtr()); // no emission, return if(!fb.kinematics) return false; Branching fc[2]; if(particle->virtualMass()==ZERO) particle->virtualMass(_progenitor->progenitor()->mass()); fc[0] = Branching(); fc[1] = Branching(); assert(fb.kinematics); // has emitted // Assign the shower kinematics to the emitting particle. particle->showerKinematics(fb.kinematics); if(fb.kinematics->pT()>progenitor()->highestpT()) progenitor()->highestpT(fb.kinematics->pT()); // create the ShowerParticle objects for the two children children = createTimeLikeChildren(particle,fb.ids); // updateChildren the children particle->showerKinematics()-> updateChildren(particle, children, fb.type); // select branchings for children fc[0] = selectSpaceLikeDecayBranching(children[0],maxScales,minmass, type,HardBranchingPtr()); fc[1] = selectTimeLikeBranching (children[1],type,HardBranchingPtr()); // old default ++_nis; // shower the first particle _currenttree->updateInitialStateShowerProduct(_progenitor,children[0]); _currenttree->addInitialStateBranching(particle,children[0],children[1]); if(fc[0].kinematics) spaceLikeDecayShower(children[0],maxScales,minmass,type,Branching()); // shower the second particle if(fc[1].kinematics) timeLikeShower(children[1],type,fc[1],true); updateHistory(children[1]); // TODO NEED AN UPDATE HERE FOR RECONOPT!=0 // branching has happened return true; } vector QTildeShowerHandler::setupShower(bool hard) { RealEmissionProcessPtr real; // generate hard me if needed if(_hardEmission==1) { real = hardMatrixElementCorrection(hard); if(real&&!real->outgoing().empty()) setupMECorrection(real); } // generate POWHEG hard emission if needed else if(_hardEmission==2) hardestEmission(hard); // set the initial colour partners setEvolutionPartners(hard,interaction_,false); // get the particles to be showered vector particlesToShower = currentTree()->extractProgenitors(); // return the answer return particlesToShower; } void QTildeShowerHandler::setEvolutionPartners(bool hard,ShowerInteraction type, bool clear) { // match the particles in the ShowerTree and hardTree if(hardTree() && !hardTree()->connect(currentTree())) throw Exception() << "Can't match trees in " << "QTildeShowerHandler::setEvolutionPartners()" << Exception::eventerror; // extract the progenitors vector particles = currentTree()->extractProgenitorParticles(); // clear the partners if needed if(clear) { for(unsigned int ix=0;ixpartner(ShowerParticlePtr()); particles[ix]->clearPartners(); } } // sort out the colour partners if(hardTree()) { // find the partner for(unsigned int ix=0;ixparticles()[particles[ix]]->branchingParticle()->partner(); if(!partner) continue; for(map::const_iterator it=hardTree()->particles().begin(); it!=hardTree()->particles().end();++it) { if(it->second->branchingParticle()==partner) { particles[ix]->partner(it->first); break; } } if(!particles[ix]->partner()) throw Exception() << "Can't match partners in " << "QTildeShowerHandler::setEvolutionPartners()" << Exception::eventerror; } } // Set the initial evolution scales partnerFinder()-> setInitialEvolutionScales(particles,!hard,interaction_,!_hardtree); if(hardTree() && _hardPOWHEG) { bool tooHard=false; map::const_iterator eit=hardTree()->particles().end(); for(unsigned int ix=0;ix::const_iterator mit = hardTree()->particles().find(particles[ix]); Energy hardScale(ZERO); ShowerPartnerType type(ShowerPartnerType::Undefined); // final-state if(particles[ix]->isFinalState()) { if(mit!= eit && !mit->second->children().empty()) { hardScale = mit->second->scale(); type = mit->second->type(); } } // initial-state else { if(mit!= eit && mit->second->parent()) { hardScale = mit->second->parent()->scale(); type = mit->second->parent()->type(); } } if(type!=ShowerPartnerType::Undefined) { if(type==ShowerPartnerType::QED) { tooHard |= particles[ix]->scales().QED_noAOscales().QCD_c_noAOscales().QCD_ac_noAOchildren().empty()) { ShowerParticleVector theChildren; for(unsigned int ix=0;ixchildren().size();++ix) { ShowerParticlePtr part = dynamic_ptr_cast (particle->children()[ix]); theChildren.push_back(part); } // update the history if needed if(particle==_currenttree->getFinalStateShowerProduct(_progenitor)) _currenttree->updateFinalStateShowerProduct(_progenitor, particle,theChildren); _currenttree->addFinalStateBranching(particle,theChildren); for(unsigned int ix=0;ixprogenitor()->partner()) return false; progenitor()->progenitor()->initializeFinalState(); if(hardTree()) { map::const_iterator eit=hardTree()->particles().end(), mit = hardTree()->particles().find(progenitor()->progenitor()); if( mit != eit && !mit->second->children().empty() ) { bool output=truncatedTimeLikeShower(progenitor()->progenitor(), mit->second ,type,Branching(),true); if(output) updateHistory(progenitor()->progenitor()); return output; } } // do the shower bool output = hardOnly() ? false : timeLikeShower(progenitor()->progenitor() ,type,Branching(),true) ; if(output) updateHistory(progenitor()->progenitor()); return output; } bool QTildeShowerHandler::startSpaceLikeShower(PPtr parent, ShowerInteraction type) { // initialise the basis vectors if(!progenitor()->progenitor()->partner()) return false; progenitor()->progenitor()->initializeInitialState(parent); if(hardTree()) { map::const_iterator eit =hardTree()->particles().end(), mit = hardTree()->particles().find(progenitor()->progenitor()); if( mit != eit && mit->second->parent() ) { return truncatedSpaceLikeShower( progenitor()->progenitor(), parent, mit->second->parent(), type ); } } // perform the shower return hardOnly() ? false : spaceLikeShower(progenitor()->progenitor(),parent,type); } bool QTildeShowerHandler:: startSpaceLikeDecayShower(const ShowerParticle::EvolutionScales & maxScales, Energy minimumMass,ShowerInteraction type) { // set up the particle basis vectors if(!progenitor()->progenitor()->partner()) return false; progenitor()->progenitor()->initializeDecay(); if(hardTree()) { map::const_iterator eit =hardTree()->particles().end(), mit = hardTree()->particles().find(progenitor()->progenitor()); if( mit != eit && mit->second->parent() ) { HardBranchingPtr branch=mit->second; while(branch->parent()) branch=branch->parent(); return truncatedSpaceLikeDecayShower(progenitor()->progenitor(),maxScales, minimumMass, branch ,type, Branching()); } } // perform the shower return hardOnly() ? false : spaceLikeDecayShower(progenitor()->progenitor(),maxScales,minimumMass,type,Branching()); } bool QTildeShowerHandler::timeLikeVetoed(const Branching & fb, ShowerParticlePtr particle) { // work out type of interaction ShowerInteraction type = convertInteraction(fb.type); // check whether emission was harder than largest pt of hard subprocess if ( restrictPhasespace() && fb.kinematics->pT() > _progenitor->maxHardPt() ) return true; // soft matrix element correction veto if( softMEC()) { if(_hardme && _hardme->hasMECorrection()) { if(_hardme->softMatrixElementVeto(particle, _progenitor->progenitor(), particle->isFinalState(), _progenitor->highestpT(), fb.ids, fb.kinematics->z(), fb.kinematics->scale(), fb.kinematics->pT())) return true; } else if(_decayme && _decayme->hasMECorrection()) { if(_decayme->softMatrixElementVeto(particle, _progenitor->progenitor(), particle->isFinalState(), _progenitor->highestpT(), fb.ids, fb.kinematics->z(), fb.kinematics->scale(), fb.kinematics->pT())) return true; } } // veto on maximum pt if(fb.kinematics->pT()>_progenitor->maximumpT(type)) return true; // general vetos if (fb.kinematics && !_vetoes.empty()) { bool vetoed=false; for (vector::iterator v = _vetoes.begin(); v != _vetoes.end(); ++v) { bool test = (**v).vetoTimeLike(_progenitor,particle,fb,currentTree()); switch((**v).vetoType()) { case ShowerVeto::Emission: vetoed |= test; break; case ShowerVeto::Shower: if(test) throw VetoShower(); break; case ShowerVeto::Event: if(test) throw Veto(); break; } } if(vetoed) return true; } if ( firstInteraction() && profileScales() ) { double weight = profileScales()-> hardScaleProfile(_progenitor->hardScale(),fb.kinematics->pT()); if ( UseRandom::rnd() > weight ) return true; } return false; } bool QTildeShowerHandler::spaceLikeVetoed(const Branching & bb, ShowerParticlePtr particle) { // work out type of interaction ShowerInteraction type = convertInteraction(bb.type); // check whether emission was harder than largest pt of hard subprocess if (restrictPhasespace() && bb.kinematics->pT() > _progenitor->maxHardPt()) return true; // apply the soft correction if( softMEC() && _hardme && _hardme->hasMECorrection() ) { if(_hardme->softMatrixElementVeto(particle, _progenitor->progenitor(), particle->isFinalState(), _progenitor->highestpT(), bb.ids, bb.kinematics->z(), bb.kinematics->scale(), bb.kinematics->pT())) return true; } // the more general vetos // check vs max pt for the shower if(bb.kinematics->pT()>_progenitor->maximumpT(type)) return true; if (!_vetoes.empty()) { bool vetoed=false; for (vector::iterator v = _vetoes.begin(); v != _vetoes.end(); ++v) { bool test = (**v).vetoSpaceLike(_progenitor,particle,bb,currentTree()); switch ((**v).vetoType()) { case ShowerVeto::Emission: vetoed |= test; break; case ShowerVeto::Shower: if(test) throw VetoShower(); break; case ShowerVeto::Event: if(test) throw Veto(); break; } } if (vetoed) return true; } if ( firstInteraction() && profileScales() ) { double weight = profileScales()-> hardScaleProfile(_progenitor->hardScale(),bb.kinematics->pT()); if ( UseRandom::rnd() > weight ) return true; } return false; } bool QTildeShowerHandler::spaceLikeDecayVetoed( const Branching & fb, ShowerParticlePtr particle) { // work out type of interaction ShowerInteraction type = convertInteraction(fb.type); // apply the soft correction if( softMEC() && _decayme && _decayme->hasMECorrection() ) { if(_decayme->softMatrixElementVeto(particle, _progenitor->progenitor(), particle->isFinalState(), _progenitor->highestpT(), fb.ids, fb.kinematics->z(), fb.kinematics->scale(), fb.kinematics->pT())) return true; } // veto on hardest pt in the shower if(fb.kinematics->pT()> _progenitor->maximumpT(type)) return true; // general vetos if (!_vetoes.empty()) { bool vetoed=false; for (vector::iterator v = _vetoes.begin(); v != _vetoes.end(); ++v) { bool test = (**v).vetoSpaceLike(_progenitor,particle,fb,currentTree()); switch((**v).vetoType()) { case ShowerVeto::Emission: vetoed |= test; break; case ShowerVeto::Shower: if(test) throw VetoShower(); break; case ShowerVeto::Event: if(test) throw Veto(); break; } if (vetoed) return true; } } return false; } void QTildeShowerHandler::hardestEmission(bool hard) { HardTreePtr ISRTree; // internal POWHEG in production or decay if( (( _hardme && _hardme->hasPOWHEGCorrection()!=0 ) || ( _decayme && _decayme->hasPOWHEGCorrection()!=0 ) ) ) { RealEmissionProcessPtr real; unsigned int type(0); // production if(_hardme) { assert(hard); real = _hardme->generateHardest( currentTree()->perturbativeProcess(), interaction_); type = _hardme->hasPOWHEGCorrection(); } // decay else { assert(!hard); real = _decayme->generateHardest( currentTree()->perturbativeProcess() ); type = _decayme->hasPOWHEGCorrection(); } if(real) { // set up ther hard tree if(!real->outgoing().empty()) _hardtree = new_ptr(HardTree(real)); // set up the vetos currentTree()->setVetoes(real->pT(),type); } // store initial state POWHEG radiation if(_hardtree && _hardme && _hardme->hasPOWHEGCorrection()==1) ISRTree = _hardtree; } else if (hard) { // Get minimum pT cutoff used in shower approximation Energy maxpt = 1.*GeV; if ( currentTree()->showerApproximation() ) { int colouredIn = 0; int colouredOut = 0; for( map< ShowerProgenitorPtr, tShowerParticlePtr >::iterator it = currentTree()->outgoingLines().begin(); it != currentTree()->outgoingLines().end(); ++it ) { if( it->second->coloured() ) ++colouredOut; } for( map< ShowerProgenitorPtr, ShowerParticlePtr >::iterator it = currentTree()->incomingLines().begin(); it != currentTree()->incomingLines().end(); ++it ) { if( it->second->coloured() ) ++colouredIn; } if ( currentTree()->showerApproximation()->ffPtCut() == currentTree()->showerApproximation()->fiPtCut() && currentTree()->showerApproximation()->ffPtCut() == currentTree()->showerApproximation()->iiPtCut() ) maxpt = currentTree()->showerApproximation()->ffPtCut(); else if ( colouredIn == 2 && colouredOut == 0 ) maxpt = currentTree()->showerApproximation()->iiPtCut(); else if ( colouredIn == 0 && colouredOut > 1 ) maxpt = currentTree()->showerApproximation()->ffPtCut(); else if ( colouredIn == 2 && colouredOut == 1 ) maxpt = min(currentTree()->showerApproximation()->iiPtCut(), currentTree()->showerApproximation()->fiPtCut()); else if ( colouredIn == 1 && colouredOut > 1 ) maxpt = min(currentTree()->showerApproximation()->ffPtCut(), currentTree()->showerApproximation()->fiPtCut()); else maxpt = min(min(currentTree()->showerApproximation()->iiPtCut(), currentTree()->showerApproximation()->fiPtCut()), currentTree()->showerApproximation()->ffPtCut()); } // Generate hardtree from born and real emission subprocesses _hardtree = generateCKKW(currentTree()); // Find transverse momentum of hardest emission if (_hardtree){ for(set::iterator it=_hardtree->branchings().begin(); it!=_hardtree->branchings().end();++it) { if ((*it)->parent() && (*it)->status()==HardBranching::Incoming) maxpt=(*it)->branchingParticle()->momentum().perp(); if ((*it)->children().size()==2 && (*it)->status()==HardBranching::Outgoing){ if ((*it)->branchingParticle()->id()!=21 && abs((*it)->branchingParticle()->id())>5 ){ if ((*it)->children()[0]->branchingParticle()->id()==21 || abs((*it)->children()[0]->branchingParticle()->id())<6) maxpt=(*it)->children()[0]->branchingParticle()->momentum().perp(); else if ((*it)->children()[1]->branchingParticle()->id()==21 || abs((*it)->children()[1]->branchingParticle()->id())<6) maxpt=(*it)->children()[1]->branchingParticle()->momentum().perp(); } else { if ( abs((*it)->branchingParticle()->id())<6){ if (abs((*it)->children()[0]->branchingParticle()->id())<6) maxpt = (*it)->children()[1]->branchingParticle()->momentum().perp(); else maxpt = (*it)->children()[0]->branchingParticle()->momentum().perp(); } else maxpt = (*it)->children()[1]->branchingParticle()->momentum().perp(); } } } } // Hardest (pt) emission should be the first powheg emission. maxpt=min(sqrt(lastXCombPtr()->lastShowerScale()),maxpt); // set maximum pT for subsequent emissions from S events if ( currentTree()->isPowhegSEvent() ) { for( map< ShowerProgenitorPtr, tShowerParticlePtr >::iterator it = currentTree()->outgoingLines().begin(); it != currentTree()->outgoingLines().end(); ++it ) { if( ! it->second->coloured() ) continue; it->first->maximumpT(maxpt, ShowerInteraction::QCD ); } for( map< ShowerProgenitorPtr, ShowerParticlePtr >::iterator it = currentTree()->incomingLines().begin(); it != currentTree()->incomingLines().end(); ++it ) { if( ! it->second->coloured() ) continue; it->first->maximumpT(maxpt, ShowerInteraction::QCD ); } } } else _hardtree = generateCKKW(currentTree()); // if hard me doesn't have a FSR powheg // correction use decay powheg correction if (_hardme && _hardme->hasPOWHEGCorrection()<2) { addFSRUsingDecayPOWHEG(ISRTree); } // connect the trees if(_hardtree) { connectTrees(currentTree(),_hardtree,hard); } } void QTildeShowerHandler::addFSRUsingDecayPOWHEG(HardTreePtr ISRTree) { // check for intermediate colour singlet resonance const ParticleVector inter = _hardme->subProcess()->intermediates(); if (inter.size()!=1 || inter[0]->momentum().m2()/GeV2 < 0 || inter[0]->dataPtr()->iColour()!=PDT::Colour0) { return; } // ignore cases where outgoing particles are not coloured map out = currentTree()->outgoingLines(); if (out.size() != 2 || out. begin()->second->dataPtr()->iColour()==PDT::Colour0 || out.rbegin()->second->dataPtr()->iColour()==PDT::Colour0) { return; } // look up decay mode tDMPtr dm; string tag; string inParticle = inter[0]->dataPtr()->name() + "->"; vector outParticles; outParticles.push_back(out.begin ()->first->progenitor()->dataPtr()->name()); outParticles.push_back(out.rbegin()->first->progenitor()->dataPtr()->name()); for (int it=0; it<2; ++it){ tag = inParticle + outParticles[it] + "," + outParticles[(it+1)%2] + ";"; dm = generator()->findDecayMode(tag); if(dm) break; } // get the decayer HwDecayerBasePtr decayer; if(dm) decayer = dynamic_ptr_cast(dm->decayer()); // check if decayer has a FSR POWHEG correction if (!decayer || decayer->hasPOWHEGCorrection()<2) { return; } // generate the hardest emission // create RealEmissionProcess PPtr in = new_ptr(*inter[0]); RealEmissionProcessPtr newProcess(new_ptr(RealEmissionProcess())); newProcess->bornIncoming().push_back(in); newProcess->bornOutgoing().push_back(out.begin ()->first->progenitor()); newProcess->bornOutgoing().push_back(out.rbegin()->first->progenitor()); // generate the FSR newProcess = decayer->generateHardest(newProcess); HardTreePtr FSRTree; if(newProcess) { // set up ther hard tree if(!newProcess->outgoing().empty()) FSRTree = new_ptr(HardTree(newProcess)); // set up the vetos currentTree()->setVetoes(newProcess->pT(),2); } if(!FSRTree) return; // if there is no ISRTree make _hardtree from FSRTree if (!ISRTree){ vector inBranch,hardBranch; for(map::const_iterator cit =currentTree()->incomingLines().begin(); cit!=currentTree()->incomingLines().end();++cit ) { inBranch.push_back(new_ptr(HardBranching(cit->second,SudakovPtr(), HardBranchingPtr(), HardBranching::Incoming))); inBranch.back()->beam(cit->first->original()->parents()[0]); hardBranch.push_back(inBranch.back()); } if(inBranch[0]->branchingParticle()->dataPtr()->coloured()) { inBranch[0]->colourPartner(inBranch[1]); inBranch[1]->colourPartner(inBranch[0]); } for(set::iterator it=FSRTree->branchings().begin(); it!=FSRTree->branchings().end();++it) { if((**it).branchingParticle()->id()!=in->id()) hardBranch.push_back(*it); } hardBranch[2]->colourPartner(hardBranch[3]); hardBranch[3]->colourPartner(hardBranch[2]); HardTreePtr newTree = new_ptr(HardTree(hardBranch,inBranch, ShowerInteraction::QCD)); _hardtree = newTree; } // Otherwise modify the ISRTree to include the emission in FSRTree else { vector FSROut, ISROut; set::iterator itFSR, itISR; // get outgoing particles for(itFSR =FSRTree->branchings().begin(); itFSR!=FSRTree->branchings().end();++itFSR){ if ((**itFSR).status()==HardBranching::Outgoing) FSROut.push_back((*itFSR)->branchingParticle()); } for(itISR =ISRTree->branchings().begin(); itISR!=ISRTree->branchings().end();++itISR){ if ((**itISR).status()==HardBranching::Outgoing) ISROut.push_back((*itISR)->branchingParticle()); } // find COM frame formed by outgoing particles LorentzRotation eventFrameFSR, eventFrameISR; eventFrameFSR = ((FSROut[0]->momentum()+FSROut[1]->momentum()).findBoostToCM()); eventFrameISR = ((ISROut[0]->momentum()+ISROut[1]->momentum()).findBoostToCM()); // find rotation between ISR and FSR frames int j=0; if (ISROut[0]->id()!=FSROut[0]->id()) j=1; eventFrameISR.rotateZ( (eventFrameFSR*FSROut[0]->momentum()).phi()- (eventFrameISR*ISROut[j]->momentum()).phi() ); eventFrameISR.rotateY( (eventFrameFSR*FSROut[0]->momentum()).theta()- (eventFrameISR*ISROut[j]->momentum()).theta() ); eventFrameISR.invert(); for (itFSR=FSRTree->branchings().begin(); itFSR!=FSRTree->branchings().end();++itFSR){ if ((**itFSR).branchingParticle()->id()==in->id()) continue; for (itISR =ISRTree->branchings().begin(); itISR!=ISRTree->branchings().end();++itISR){ if ((**itISR).status()==HardBranching::Incoming) continue; if ((**itFSR).branchingParticle()->id()== (**itISR).branchingParticle()->id()){ // rotate FSRTree particle to ISRTree event frame (**itISR).branchingParticle()->setMomentum(eventFrameISR* eventFrameFSR* (**itFSR).branchingParticle()->momentum()); (**itISR).branchingParticle()->rescaleMass(); // add the children of the FSRTree particles to the ISRTree if(!(**itFSR).children().empty()){ (**itISR).addChild((**itFSR).children()[0]); (**itISR).addChild((**itFSR).children()[1]); // rotate momenta to ISRTree event frame (**itISR).children()[0]->branchingParticle()->setMomentum(eventFrameISR* eventFrameFSR* (**itFSR).children()[0]->branchingParticle()->momentum()); (**itISR).children()[1]->branchingParticle()->setMomentum(eventFrameISR* eventFrameFSR* (**itFSR).children()[1]->branchingParticle()->momentum()); } } } } _hardtree = ISRTree; } } bool QTildeShowerHandler::truncatedTimeLikeShower(tShowerParticlePtr particle, HardBranchingPtr branch, ShowerInteraction type, Branching fb, bool first) { // select a branching if we don't have one if(!fb.kinematics) fb = selectTimeLikeBranching(particle,type,branch); // must be an emission, the forced one it not a truncated one assert(fb.kinematics); ShowerParticleVector children; Branching fc[2] = {Branching(),Branching()}; // Assign the shower kinematics to the emitting particle. particle->showerKinematics(fb.kinematics); if(fb.kinematics->pT()>progenitor()->highestpT()) progenitor()->highestpT(fb.kinematics->pT()); // create the children children = createTimeLikeChildren(particle,fb.ids); // update the children particle->showerKinematics()-> updateChildren(particle, children,fb.type); // select branchings for children if(!fc[0].kinematics) { // select branching for first particle if(!fb.hard && fb.iout ==1 ) fc[0] = selectTimeLikeBranching(children[0],type,branch); else if(fb.hard && !branch->children()[0]->children().empty() ) fc[0] = selectTimeLikeBranching(children[0],type,branch->children()[0]); else fc[0] = selectTimeLikeBranching(children[0],type,HardBranchingPtr()); } // select branching for the second particle if(!fc[1].kinematics) { // select branching for first particle if(!fb.hard && fb.iout ==2 ) fc[1] = selectTimeLikeBranching(children[1],type,branch); else if(fb.hard && !branch->children()[1]->children().empty() ) fc[1] = selectTimeLikeBranching(children[1],type,branch->children()[1]); else fc[1] = selectTimeLikeBranching(children[1],type,HardBranchingPtr()); } // shower the first particle if(fc[0].kinematics) { // the parent has truncated emission and following line if(!fb.hard && fb.iout == 1) truncatedTimeLikeShower(children[0],branch,type,fc[0],false); // hard emission and subsquent hard emissions else if(fb.hard && !branch->children()[0]->children().empty() ) truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[0],false); // normal shower else timeLikeShower(children[0],type,fc[0],false); } if(children[0]->spinInfo()) children[0]->spinInfo()->develop(); // shower the second particle if(fc[1].kinematics) { // the parent has truncated emission and following line if(!fb.hard && fb.iout == 2) truncatedTimeLikeShower(children[1],branch,type,fc[1],false); // hard emission and subsquent hard emissions else if(fb.hard && !branch->children()[1]->children().empty() ) truncatedTimeLikeShower(children[1],branch->children()[1],type,fc[1],false); else timeLikeShower(children[1],type,fc[1],false); } if(children[1]->spinInfo()) children[1]->spinInfo()->develop(); // branching has happened particle->showerKinematics()->updateParent(particle, children,fb.type); if(first&&!children.empty()) particle->showerKinematics()->resetChildren(particle,children); if(particle->spinInfo()) particle->spinInfo()->develop(); // TODO NEED AN UPDATE HERE FOR RECONOPT!=0 ? return true; } bool QTildeShowerHandler::truncatedSpaceLikeShower(tShowerParticlePtr particle, PPtr beam, HardBranchingPtr branch, ShowerInteraction type) { tcPDFPtr pdf; if(firstPDF().particle() == beamParticle()) pdf = firstPDF().pdf(); if(secondPDF().particle() == beamParticle()) pdf = secondPDF().pdf(); Energy freeze = pdfFreezingScale(); Branching bb; // parameters of the force branching double z(0.); HardBranchingPtr timelike; for( unsigned int ix = 0; ix < branch->children().size(); ++ix ) { if( branch->children()[ix]->status() ==HardBranching::Outgoing) { timelike = branch->children()[ix]; } if( branch->children()[ix]->status() ==HardBranching::Incoming ) z = branch->children()[ix]->z(); } // generate truncated branching tcPDPtr part[2]; if(z>=0.&&z<=1.) { while (true) { if( !isTruncatedShowerON() || hardOnly() ) break; bb = splittingGenerator()->chooseBackwardBranching( *particle, beam, 1., beamParticle(), type , pdf,freeze); if( !bb.kinematics || bb.kinematics->scale() < branch->scale() ) { bb = Branching(); break; } // particles as in Sudakov form factor part[0] = bb.ids[0]; part[1] = bb.ids[2]; double zsplit = bb.kinematics->z(); // apply the vetos for the truncated shower // if doesn't carry most of momentum ShowerInteraction type2 = convertInteraction(bb.type); if(type2==branch->sudakov()->interactionType() && zsplit < 0.5) { particle->vetoEmission(bb.type,bb.kinematics->scale()); continue; } // others if( part[0]->id() != particle->id() || // if particle changes type bb.kinematics->pT() > progenitor()->maximumpT(type2) || // pt veto bb.kinematics->scale() < branch->scale()) { // angular ordering veto particle->vetoEmission(bb.type,bb.kinematics->scale()); continue; } // and those from the base class if(spaceLikeVetoed(bb,particle)) { particle->vetoEmission(bb.type,bb.kinematics->scale()); continue; } break; } } if( !bb.kinematics ) { //do the hard emission ShoKinPtr kinematics = new_ptr(IS_QTildeShowerKinematics1to2( branch->scale(), z, branch->phi(), branch->children()[0]->pT(), branch->sudakov() )); // assign the splitting function and shower kinematics particle->showerKinematics( kinematics ); if(kinematics->pT()>progenitor()->highestpT()) progenitor()->highestpT(kinematics->pT()); // For the time being we are considering only 1->2 branching // Now create the actual particles, make the otherChild a final state // particle, while the newParent is not ShowerParticlePtr newParent = new_ptr( ShowerParticle( branch->branchingParticle()->dataPtr(), false ) ); ShowerParticlePtr otherChild = new_ptr( ShowerParticle( timelike->branchingParticle()->dataPtr(), true, true ) ); ShowerParticleVector theChildren; theChildren.push_back( particle ); theChildren.push_back( otherChild ); particle->showerKinematics()-> updateParent( newParent, theChildren, branch->type()); // update the history if needed currentTree()->updateInitialStateShowerProduct( progenitor(), newParent ); currentTree()->addInitialStateBranching( particle, newParent, otherChild ); // for the reconstruction of kinematics, parent/child // relationships are according to the branching process: // now continue the shower bool emitted=false; if(!hardOnly()) { if( branch->parent() ) { emitted = truncatedSpaceLikeShower( newParent, beam, branch->parent() , type); } else { emitted = spaceLikeShower( newParent, beam , type); } } if( !emitted ) { if( intrinsicpT().find( progenitor() ) == intrinsicpT().end() ) { kinematics->updateLast( newParent, ZERO, ZERO ); } else { pair kt = intrinsicpT()[progenitor()]; kinematics->updateLast( newParent, kt.first*cos( kt.second ), kt.first*sin( kt.second ) ); } } particle->showerKinematics()-> updateChildren( newParent, theChildren,bb.type); if(hardOnly()) return true; // perform the shower of the final-state particle if( timelike->children().empty() ) { timeLikeShower( otherChild , type,Branching(),true); } else { truncatedTimeLikeShower( otherChild, timelike , type,Branching(), true); } updateHistory(otherChild); // return the emitted return true; } // assign the splitting function and shower kinematics particle->showerKinematics( bb.kinematics ); if(bb.kinematics->pT()>progenitor()->highestpT()) progenitor()->highestpT(bb.kinematics->pT()); // For the time being we are considering only 1->2 branching // Now create the actual particles, make the otherChild a final state // particle, while the newParent is not ShowerParticlePtr newParent = new_ptr( ShowerParticle( part[0], false ) ); ShowerParticlePtr otherChild = new_ptr( ShowerParticle( part[1], true, true ) ); ShowerParticleVector theChildren; theChildren.push_back( particle ); theChildren.push_back( otherChild ); particle->showerKinematics()-> updateParent( newParent, theChildren, bb.type); // update the history if needed currentTree()->updateInitialStateShowerProduct( progenitor(), newParent ); currentTree()->addInitialStateBranching( particle, newParent, otherChild ); // for the reconstruction of kinematics, parent/child // relationships are according to the branching process: // now continue the shower bool emitted = truncatedSpaceLikeShower( newParent, beam, branch,type); // now reconstruct the momentum if( !emitted ) { if( intrinsicpT().find( progenitor() ) == intrinsicpT().end() ) { bb.kinematics->updateLast( newParent, ZERO, ZERO ); } else { pair kt = intrinsicpT()[ progenitor() ]; bb.kinematics->updateLast( newParent, kt.first*cos( kt.second ), kt.first*sin( kt.second ) ); } } particle->showerKinematics()-> updateChildren( newParent, theChildren, bb.type); // perform the shower of the final-state particle timeLikeShower( otherChild , type,Branching(),true); updateHistory(otherChild); // return the emitted return true; } bool QTildeShowerHandler:: truncatedSpaceLikeDecayShower(tShowerParticlePtr particle, const ShowerParticle::EvolutionScales & maxScales, Energy minmass, HardBranchingPtr branch, ShowerInteraction type, Branching fb) { // select a branching if we don't have one if(!fb.kinematics) fb = selectSpaceLikeDecayBranching(particle,maxScales,minmass,type,branch); // must be an emission, the forced one it not a truncated one assert(fb.kinematics); ShowerParticleVector children; Branching fc[2]={Branching(),Branching()}; // Assign the shower kinematics to the emitting particle. particle->showerKinematics(fb.kinematics); if(fb.kinematics->pT()>progenitor()->highestpT()) progenitor()->highestpT(fb.kinematics->pT()); // create the ShowerParticle objects for the two children children = createTimeLikeChildren(particle,fb.ids); // updateChildren the children particle->showerKinematics()-> updateChildren(particle, children, fb.type); // select branchings for children if(!fc[0].kinematics) { if(children[0]->id()==particle->id()) { // select branching for first particle if(!fb.hard) fc[0] = selectSpaceLikeDecayBranching(children[0],maxScales,minmass,type,branch); else if(fb.hard && ! branch->children()[0]->children().empty() ) fc[0] = selectSpaceLikeDecayBranching(children[0],maxScales,minmass,type, branch->children()[0]); else fc[0] = selectSpaceLikeDecayBranching(children[0],maxScales,minmass,type, HardBranchingPtr()); } else { // select branching for first particle if(fb.hard && !branch->children()[0]->children().empty() ) fc[0] = selectTimeLikeBranching(children[0],type,branch->children()[0]); else fc[0] = selectTimeLikeBranching(children[0],type,HardBranchingPtr()); } } // select branching for the second particle if(!fc[1].kinematics) { if(children[1]->id()==particle->id()) { // select branching for first particle if(!fb.hard) fc[1] = selectSpaceLikeDecayBranching(children[1],maxScales,minmass,type,branch); else if(fb.hard && ! branch->children()[1]->children().empty() ) fc[1] = selectSpaceLikeDecayBranching(children[1],maxScales,minmass,type, branch->children()[1]); else fc[1] = selectSpaceLikeDecayBranching(children[1],maxScales,minmass,type, HardBranchingPtr()); } else { if(fb.hard && !branch->children()[1]->children().empty() ) fc[1] = selectTimeLikeBranching(children[1],type,branch->children()[1]); else fc[1] = selectTimeLikeBranching(children[1],type,HardBranchingPtr()); } } // old default // update the history if needed currentTree()->updateInitialStateShowerProduct(progenitor(),children[0]); currentTree()->addInitialStateBranching(particle,children[0],children[1]); // shower the first particle if(fc[0].kinematics) { if(children[0]->id()==particle->id()) { if(!fb.hard) truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, branch,type,fc[0]); else if(fb.hard && ! branch->children()[0]->children().empty() ) truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, branch->children()[0],type,fc[0]); else spaceLikeDecayShower( children[0],maxScales,minmass,type,fc[0]); } else { if(fb.hard && !branch->children()[0]->children().empty() ) truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[0],false); // normal shower else timeLikeShower(children[0],type,fc[0],false); } } // shower the second particle if(fc[1].kinematics) { if(children[0]->id()==particle->id()) { if(!fb.hard) truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, branch,type,fc[1]); else if(fb.hard && ! branch->children()[0]->children().empty() ) truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, branch->children()[0],type,fc[1]); else spaceLikeDecayShower( children[0],maxScales,minmass,type,fc[1]); } else { if(fb.hard && !branch->children()[0]->children().empty() ) truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[1],false); // normal shower else timeLikeShower(children[0],type,fc[1],false); } } updateHistory(children[1]); // TODO DO WE NEED A CHECK IF RECONPT !=0 return true; } void QTildeShowerHandler::connectTrees(ShowerTreePtr showerTree, HardTreePtr hardTree, bool hard ) { ShowerParticleVector particles; // find the Sudakovs for(set::iterator cit=hardTree->branchings().begin(); cit!=hardTree->branchings().end();++cit) { // Sudakovs for ISR if((**cit).parent()&&(**cit).status()==HardBranching::Incoming) { ++_nis; - vector br(3); + array br; br[0] = (**cit).parent()->branchingParticle()->id(); br[1] = (**cit). branchingParticle()->id(); br[2] = (**cit).parent()->children()[0]==*cit ? (**cit).parent()->children()[1]->branchingParticle()->id() : (**cit).parent()->children()[0]->branchingParticle()->id(); BranchingList branchings = splittingGenerator()->initialStateBranchings(); if(br[1]<0&&br[0]==br[1]) { br[0] = abs(br[0]); br[1] = abs(br[1]); } else if(br[1]<0) { br[1] = -br[1]; br[2] = -br[2]; } long index = abs(br[1]); SudakovPtr sudakov; for(BranchingList::const_iterator cjt = branchings.lower_bound(index); cjt != branchings.upper_bound(index); ++cjt ) { IdList ids = cjt->second.particles; if(ids[0]->id()==br[0]&&ids[1]->id()==br[1]&&ids[2]->id()==br[2]) { sudakov=cjt->second.sudakov; break; } } if(!sudakov) throw Exception() << "Can't find Sudakov for the hard emission in " << "QTildeShowerHandler::connectTrees() for ISR" << Exception::runerror; (**cit).parent()->sudakov(sudakov); } // Sudakovs for FSR else if(!(**cit).children().empty()) { ++_nfs; - vector br(3); + array br; br[0] = (**cit) .branchingParticle()->id(); br[1] = (**cit).children()[0]->branchingParticle()->id(); br[2] = (**cit).children()[1]->branchingParticle()->id(); BranchingList branchings = splittingGenerator()->finalStateBranchings(); if(br[0]<0) { br[0] = abs(br[0]); br[1] = abs(br[1]); br[2] = abs(br[2]); } long index = br[0]; SudakovPtr sudakov; for(BranchingList::const_iterator cjt = branchings.lower_bound(index); cjt != branchings.upper_bound(index); ++cjt ) { IdList ids = cjt->second.particles; if(ids[0]->id()==br[0]&&ids[1]->id()==br[1]&&ids[2]->id()==br[2]) { sudakov=cjt->second.sudakov; break; } } if(!sudakov) { throw Exception() << "Can't find Sudakov for the hard emission in " << "QTildeShowerHandler::connectTrees()" << Exception::runerror; } (**cit).sudakov(sudakov); } } // calculate the evolution scale for(set::iterator cit=hardTree->branchings().begin(); cit!=hardTree->branchings().end();++cit) { particles.push_back((*cit)->branchingParticle()); } partnerFinder()-> setInitialEvolutionScales(particles,!hard,interaction_,true); hardTree->partnersSet(true); // inverse reconstruction if(hard) { kinematicsReconstructor()-> deconstructHardJets(hardTree,interaction_); } else kinematicsReconstructor()-> deconstructDecayJets(hardTree,interaction_); // now reset the momenta of the showering particles vector particlesToShower=showerTree->extractProgenitors(); // match them map partners; for(set::const_iterator bit=hardTree->branchings().begin(); bit!=hardTree->branchings().end();++bit) { Energy2 dmin( 1e30*GeV2 ); ShowerProgenitorPtr partner; for(vector::const_iterator pit=particlesToShower.begin(); pit!=particlesToShower.end();++pit) { if(partners.find(*pit)!=partners.end()) continue; if( (**bit).branchingParticle()->id() != (**pit).progenitor()->id() ) continue; if( (**bit).branchingParticle()->isFinalState() != (**pit).progenitor()->isFinalState() ) continue; if( (**pit).progenitor()->isFinalState() ) { Energy2 dtest = sqr( (**pit).progenitor()->momentum().x() - (**bit).showerMomentum().x() ) + sqr( (**pit).progenitor()->momentum().y() - (**bit).showerMomentum().y() ) + sqr( (**pit).progenitor()->momentum().z() - (**bit).showerMomentum().z() ) + sqr( (**pit).progenitor()->momentum().t() - (**bit).showerMomentum().t() ); // add mass difference for identical particles (e.g. Z0 Z0 production) dtest += 1e10*sqr((**pit).progenitor()->momentum().m()-(**bit).showerMomentum().m()); if( dtest < dmin ) { partner = *pit; dmin = dtest; } } else { // ensure directions are right if((**pit).progenitor()->momentum().z()/(**bit).showerMomentum().z()>ZERO) { partner = *pit; break; } } } if(!partner) throw Exception() << "Failed to match shower and hard trees in QTildeShowerHandler::hardestEmission" << Exception::eventerror; partners[partner] = *bit; } for(vector::const_iterator pit=particlesToShower.begin(); pit!=particlesToShower.end();++pit) { HardBranchingPtr partner = partners[*pit]; if((**pit).progenitor()->dataPtr()->stable()) { (**pit).progenitor()->set5Momentum(partner->showerMomentum()); (**pit).copy()->set5Momentum(partner->showerMomentum()); } else { Lorentz5Momentum oldMomentum = (**pit).progenitor()->momentum(); Lorentz5Momentum newMomentum = partner->showerMomentum(); LorentzRotation boost( oldMomentum.findBoostToCM(),oldMomentum.e()/oldMomentum.mass()); (**pit).progenitor()->transform(boost); (**pit).copy() ->transform(boost); boost = LorentzRotation(-newMomentum.findBoostToCM(),newMomentum.e()/newMomentum.mass()); (**pit).progenitor()->transform(boost); (**pit).copy() ->transform(boost); } } // correction boosts for daughter trees for(map >::const_iterator tit = showerTree->treelinks().begin(); tit != showerTree->treelinks().end();++tit) { ShowerTreePtr decayTree = tit->first; map::const_iterator cit = decayTree->incomingLines().begin(); // reset the momentum of the decay particle Lorentz5Momentum oldMomentum = cit->first->progenitor()->momentum(); Lorentz5Momentum newMomentum = tit->second.second->momentum(); LorentzRotation boost( oldMomentum.findBoostToCM(),oldMomentum.e()/oldMomentum.mass()); decayTree->transform(boost,true); boost = LorentzRotation(-newMomentum.findBoostToCM(),newMomentum.e()/newMomentum.mass()); decayTree->transform(boost,true); } } void QTildeShowerHandler::doShowering(bool hard,XCPtr xcomb) { // zero number of emissions _nis = _nfs = 0; // if MC@NLO H event and limited emissions // indicate both final and initial state emission if ( currentTree()->isMCatNLOHEvent() && _limitEmissions != 0 ) { _nis = _nfs = 1; } // extract particles to shower vector particlesToShower(setupShower(hard)); // check if we should shower bool colCharge = false; for(unsigned int ix=0;ixprogenitor()->dataPtr()->coloured() || particlesToShower[ix]->progenitor()->dataPtr()->charged()) { colCharge = true; break; } } if(!colCharge) { _currenttree->hasShowered(true); return; } // setup the maximum scales for the shower if (restrictPhasespace()) setupMaximumScales(particlesToShower,xcomb); // set the hard scales for the profiles setupHardScales(particlesToShower,xcomb); // specific stuff for hard processes and decays Energy minmass(ZERO), mIn(ZERO); // hard process generate the intrinsic p_T once and for all if(hard) { generateIntrinsicpT(particlesToShower); } // decay compute the minimum mass of the final-state else { for(unsigned int ix=0;ixprogenitor()->isFinalState()) { if(particlesToShower[ix]->progenitor()->dataPtr()->stable()) minmass += particlesToShower[ix]->progenitor()->dataPtr()->constituentMass(); else minmass += particlesToShower[ix]->progenitor()->mass(); } else { mIn = particlesToShower[ix]->progenitor()->mass(); } } // throw exception if decay can't happen if ( minmass > mIn ) { throw Exception() << "QTildeShowerHandler.cc: Mass of decaying particle is " << "below constituent masses of decay products." << Exception::eventerror; } } // setup for reweighted bool reWeighting = _reWeight && hard && ShowerHandler::currentHandler()->firstInteraction(); double eventWeight=0.; unsigned int nTryReWeight(0); // create random particle vector (only need to do once) vector tmp; unsigned int nColouredIncoming = 0; while(particlesToShower.size()>0){ unsigned int xx=UseRandom::irnd(particlesToShower.size()); tmp.push_back(particlesToShower[xx]); particlesToShower.erase(particlesToShower.begin()+xx); } particlesToShower=tmp; for(unsigned int ix=0;ixprogenitor()->isFinalState() && particlesToShower[ix]->progenitor()->coloured()) ++nColouredIncoming; } bool switchRecon = hard && nColouredIncoming !=1; // main shower loop unsigned int ntry(0); bool reconstructed = false; do { // clear results of last attempt if needed if(ntry!=0) { currentTree()->clear(); setEvolutionPartners(hard,interaction_,true); _nis = _nfs = 0; // if MC@NLO H event and limited emissions // indicate both final and initial state emission if ( currentTree()->isMCatNLOHEvent() && _limitEmissions != 0 ) { _nis = _nfs = 1; } for(unsigned int ix=0; ixprogenitor()->spinInfo(); if(spin && spin->decayVertex() && dynamic_ptr_cast(spin->decayVertex())) { spin->decayVertex(VertexPtr()); } } } // loop over particles for(unsigned int ix=0;ixprogenitor()->isFinalState()) { if(!doFSR()) continue; // perform shower progenitor()->hasEmitted(startTimeLikeShower(interaction_)); } // initial-state radiation else { if(!doISR()) continue; // hard process if(hard) { // get the PDF setBeamParticle(_progenitor->beam()); if(!beamParticle()) { throw Exception() << "Incorrect type of beam particle in " << "QTildeShowerHandler::doShowering(). " << "This should not happen for conventional choices but may happen if you have used a" << " non-default choice and have not changed the create ParticleData line in the input files" << " for this particle to create BeamParticleData." << Exception::runerror; } // perform the shower // set the beam particle tPPtr beamparticle=progenitor()->original(); if(!beamparticle->parents().empty()) beamparticle=beamparticle->parents()[0]; // generate the shower progenitor()->hasEmitted(startSpaceLikeShower(beamparticle, interaction_)); } // decay else { // skip colour and electrically neutral particles if(!progenitor()->progenitor()->dataPtr()->coloured() && !progenitor()->progenitor()->dataPtr()->charged()) { progenitor()->hasEmitted(false); continue; } // perform shower // set the scales correctly. The current scale is the maximum scale for // emission not the starting scale ShowerParticle::EvolutionScales maxScales(progenitor()->progenitor()->scales()); progenitor()->progenitor()->scales() = ShowerParticle::EvolutionScales(); if(progenitor()->progenitor()->dataPtr()->charged()) { progenitor()->progenitor()->scales().QED = progenitor()->progenitor()->mass(); progenitor()->progenitor()->scales().QED_noAO = progenitor()->progenitor()->mass(); } if(progenitor()->progenitor()->hasColour()) { progenitor()->progenitor()->scales().QCD_c = progenitor()->progenitor()->mass(); progenitor()->progenitor()->scales().QCD_c_noAO = progenitor()->progenitor()->mass(); } if(progenitor()->progenitor()->hasAntiColour()) { progenitor()->progenitor()->scales().QCD_ac = progenitor()->progenitor()->mass(); progenitor()->progenitor()->scales().QCD_ac_noAO = progenitor()->progenitor()->mass(); } // perform the shower progenitor()->hasEmitted(startSpaceLikeDecayShower(maxScales,minmass, interaction_)); } } } // do the kinematic reconstruction, checking if it worked reconstructed = hard ? kinematicsReconstructor()-> reconstructHardJets (currentTree(),intrinsicpT(),interaction_, switchRecon && ntry>maximumTries()/2) : kinematicsReconstructor()-> reconstructDecayJets(currentTree(),interaction_); if(!reconstructed) continue; // apply vetos on the full shower for(vector::const_iterator it=_fullShowerVetoes.begin(); it!=_fullShowerVetoes.end();++it) { int veto = (**it).applyVeto(currentTree()); if(veto<0) continue; // veto the shower if(veto==0) { reconstructed = false; break; } // veto the shower and reweight else if(veto==1) { reconstructed = false; break; } // veto the event else if(veto==2) { throw Veto(); } } if(reWeighting) { if(reconstructed) eventWeight += 1.; reconstructed=false; ++nTryReWeight; if(nTryReWeight==_nReWeight) { reWeighting = false; if(eventWeight==0.) throw Veto(); } } } while(!reconstructed&&maximumTries()>++ntry); // check if failed to generate the shower if(ntry==maximumTries()) { if(hard) throw ShowerHandler::ShowerTriesVeto(ntry); else throw Exception() << "Failed to generate the shower after " << ntry << " attempts in QTildeShowerHandler::showerDecay()" << Exception::eventerror; } // handle the weights and apply any reweighting required if(nTryReWeight>0) { tStdEHPtr seh = dynamic_ptr_cast(generator()->currentEventHandler()); static bool first = true; if(seh) { seh->reweight(eventWeight/double(nTryReWeight)); } else if(first) { generator()->log() << "Reweighting the shower only works with internal Herwig7 processes" << "Presumably you are showering Les Houches Events. These will not be" << "reweighted\n"; first = false; } } // tree has now showered _currenttree->hasShowered(true); hardTree(HardTreePtr()); } void QTildeShowerHandler:: convertHardTree(bool hard,ShowerInteraction type) { map cmap; // incoming particles for(map::const_iterator cit=currentTree()->incomingLines().begin();cit!=currentTree()->incomingLines().end();++cit) { map::const_iterator mit = hardTree()->particles().find(cit->first->progenitor()); // put the colour lines in the map ShowerParticlePtr oldParticle = cit->first->progenitor(); ShowerParticlePtr newParticle = mit->second->branchingParticle(); ColinePtr cLine = oldParticle-> colourLine(); ColinePtr aLine = oldParticle->antiColourLine(); if(newParticle->colourLine() && cmap.find(newParticle-> colourLine())==cmap.end()) cmap[newParticle-> colourLine()] = cLine; if(newParticle->antiColourLine() && cmap.find(newParticle->antiColourLine())==cmap.end()) cmap[newParticle->antiColourLine()] = aLine; // check whether or not particle emits bool emission = mit->second->parent(); if(emission) { if(newParticle->colourLine()) { ColinePtr ctemp = newParticle-> colourLine(); ctemp->removeColoured(newParticle); } if(newParticle->antiColourLine()) { ColinePtr ctemp = newParticle->antiColourLine(); ctemp->removeAntiColoured(newParticle); } newParticle = mit->second->parent()->branchingParticle(); } // get the new colour lines ColinePtr newCLine,newALine; // sort out colour lines if(newParticle->colourLine()) { ColinePtr ctemp = newParticle-> colourLine(); ctemp->removeColoured(newParticle); if(cmap.find(ctemp)!=cmap.end()) { newCLine = cmap[ctemp]; } else { newCLine = new_ptr(ColourLine()); cmap[ctemp] = newCLine; } } // and anticolour lines if(newParticle->antiColourLine()) { ColinePtr ctemp = newParticle->antiColourLine(); ctemp->removeAntiColoured(newParticle); if(cmap.find(ctemp)!=cmap.end()) { newALine = cmap[ctemp]; } else { newALine = new_ptr(ColourLine()); cmap[ctemp] = newALine; } } // remove colour lines from old particle if(aLine) { aLine->removeAntiColoured(cit->first->copy()); aLine->removeAntiColoured(cit->first->progenitor()); } if(cLine) { cLine->removeColoured(cit->first->copy()); cLine->removeColoured(cit->first->progenitor()); } // add particle to colour lines if(newCLine) newCLine->addColoured (newParticle); if(newALine) newALine->addAntiColoured(newParticle); // insert new particles cit->first->copy(newParticle); ShowerParticlePtr sp(new_ptr(ShowerParticle(*newParticle,1,false))); cit->first->progenitor(sp); currentTree()->incomingLines()[cit->first]=sp; cit->first->perturbative(!emission); // and the emitted particle if needed if(emission) { ShowerParticlePtr newOut = mit->second->parent()->children()[1]->branchingParticle(); if(newOut->colourLine()) { ColinePtr ctemp = newOut-> colourLine(); ctemp->removeColoured(newOut); assert(cmap.find(ctemp)!=cmap.end()); cmap[ctemp]->addColoured (newOut); } if(newOut->antiColourLine()) { ColinePtr ctemp = newOut->antiColourLine(); ctemp->removeAntiColoured(newOut); assert(cmap.find(ctemp)!=cmap.end()); cmap[ctemp]->addAntiColoured(newOut); } ShowerParticlePtr sout=new_ptr(ShowerParticle(*newOut,1,true)); ShowerProgenitorPtr out=new_ptr(ShowerProgenitor(cit->first->original(),newOut,sout)); out->perturbative(false); currentTree()->outgoingLines().insert(make_pair(out,sout)); } if(hard) { // sort out the value of x if(mit->second->beam()->momentum().z()>ZERO) { sp->x(newParticle->momentum(). plus()/mit->second->beam()->momentum(). plus()); } else { sp->x(newParticle->momentum().minus()/mit->second->beam()->momentum().minus()); } } } // outgoing particles for(map::const_iterator cit=currentTree()->outgoingLines().begin();cit!=currentTree()->outgoingLines().end();++cit) { map >::const_iterator tit; for(tit = currentTree()->treelinks().begin(); tit != currentTree()->treelinks().end();++tit) { if(tit->second.first && tit->second.second==cit->first->progenitor()) break; } map::const_iterator mit = hardTree()->particles().find(cit->first->progenitor()); if(mit==hardTree()->particles().end()) continue; // put the colour lines in the map ShowerParticlePtr oldParticle = cit->first->progenitor(); ShowerParticlePtr newParticle = mit->second->branchingParticle(); ShowerParticlePtr newOut; ColinePtr cLine = oldParticle-> colourLine(); ColinePtr aLine = oldParticle->antiColourLine(); if(newParticle->colourLine() && cmap.find(newParticle-> colourLine())==cmap.end()) cmap[newParticle-> colourLine()] = cLine; if(newParticle->antiColourLine() && cmap.find(newParticle->antiColourLine())==cmap.end()) cmap[newParticle->antiColourLine()] = aLine; // check whether or not particle emits bool emission = !mit->second->children().empty(); if(emission) { if(newParticle->colourLine()) { ColinePtr ctemp = newParticle-> colourLine(); ctemp->removeColoured(newParticle); } if(newParticle->antiColourLine()) { ColinePtr ctemp = newParticle->antiColourLine(); ctemp->removeAntiColoured(newParticle); } newParticle = mit->second->children()[0]->branchingParticle(); newOut = mit->second->children()[1]->branchingParticle(); if(newParticle->id()!=oldParticle->id()&&newParticle->id()==newOut->id()) swap(newParticle,newOut); } // get the new colour lines ColinePtr newCLine,newALine; // sort out colour lines if(newParticle->colourLine()) { ColinePtr ctemp = newParticle-> colourLine(); ctemp->removeColoured(newParticle); if(cmap.find(ctemp)!=cmap.end()) { newCLine = cmap[ctemp]; } else { newCLine = new_ptr(ColourLine()); cmap[ctemp] = newCLine; } } // and anticolour lines if(newParticle->antiColourLine()) { ColinePtr ctemp = newParticle->antiColourLine(); ctemp->removeAntiColoured(newParticle); if(cmap.find(ctemp)!=cmap.end()) { newALine = cmap[ctemp]; } else { newALine = new_ptr(ColourLine()); cmap[ctemp] = newALine; } } // remove colour lines from old particle if(aLine) { aLine->removeAntiColoured(cit->first->copy()); aLine->removeAntiColoured(cit->first->progenitor()); } if(cLine) { cLine->removeColoured(cit->first->copy()); cLine->removeColoured(cit->first->progenitor()); } // special for unstable particles if(newParticle->id()==oldParticle->id() && (tit!=currentTree()->treelinks().end()||!oldParticle->dataPtr()->stable())) { Lorentz5Momentum oldMomentum = oldParticle->momentum(); Lorentz5Momentum newMomentum = newParticle->momentum(); LorentzRotation boost( oldMomentum.findBoostToCM(),oldMomentum.e()/oldMomentum.mass()); if(tit!=currentTree()->treelinks().end()) tit->first->transform(boost,false); oldParticle->transform(boost); boost = LorentzRotation(-newMomentum.findBoostToCM(),newMomentum.e()/newMomentum.mass()); oldParticle->transform(boost); if(tit!=currentTree()->treelinks().end()) tit->first->transform(boost,false); newParticle=oldParticle; } // add particle to colour lines if(newCLine) newCLine->addColoured (newParticle); if(newALine) newALine->addAntiColoured(newParticle); // insert new particles cit->first->copy(newParticle); ShowerParticlePtr sp(new_ptr(ShowerParticle(*newParticle,1,true))); cit->first->progenitor(sp); currentTree()->outgoingLines()[cit->first]=sp; cit->first->perturbative(!emission); // and the emitted particle if needed if(emission) { if(newOut->colourLine()) { ColinePtr ctemp = newOut-> colourLine(); ctemp->removeColoured(newOut); assert(cmap.find(ctemp)!=cmap.end()); cmap[ctemp]->addColoured (newOut); } if(newOut->antiColourLine()) { ColinePtr ctemp = newOut->antiColourLine(); ctemp->removeAntiColoured(newOut); assert(cmap.find(ctemp)!=cmap.end()); cmap[ctemp]->addAntiColoured(newOut); } ShowerParticlePtr sout=new_ptr(ShowerParticle(*newOut,1,true)); ShowerProgenitorPtr out=new_ptr(ShowerProgenitor(cit->first->original(),newOut,sout)); out->perturbative(false); currentTree()->outgoingLines().insert(make_pair(out,sout)); } // update any decay products if(tit!=currentTree()->treelinks().end()) currentTree()->updateLink(tit->first,make_pair(cit->first,sp)); } // reset the tree currentTree()->resetShowerProducts(); // reextract the particles and set the colour partners vector particles = currentTree()->extractProgenitorParticles(); // clear the partners for(unsigned int ix=0;ixpartner(ShowerParticlePtr()); particles[ix]->clearPartners(); } // clear the tree hardTree(HardTreePtr()); // Set the initial evolution scales partnerFinder()-> setInitialEvolutionScales(particles,!hard,type,!_hardtree); } Branching QTildeShowerHandler::selectTimeLikeBranching(tShowerParticlePtr particle, ShowerInteraction type, HardBranchingPtr branch) { Branching fb; unsigned int iout=0; while (true) { // break if doing truncated shower and no truncated shower needed if(branch && (!isTruncatedShowerON()||hardOnly())) break; fb=_splittingGenerator->chooseForwardBranching(*particle,_finalenhance,type); // no emission break if(!fb.kinematics) break; // special for truncated shower if(branch) { // check haven't evolved too far if(fb.kinematics->scale() < branch->scale()) { fb=Branching(); break; } // find the truncated line iout=0; if(fb.ids[1]->id()!=fb.ids[2]->id()) { if(fb.ids[1]->id()==particle->id()) iout=1; else if (fb.ids[2]->id()==particle->id()) iout=2; } else if(fb.ids[1]->id()==particle->id()) { if(fb.kinematics->z()>0.5) iout=1; else iout=2; } // apply the vetos for the truncated shower // no flavour changing branchings if(iout==0) { particle->vetoEmission(fb.type,fb.kinematics->scale()); continue; } double zsplit = iout==1 ? fb.kinematics->z() : 1-fb.kinematics->z(); // only if same interaction for forced branching ShowerInteraction type2 = convertInteraction(fb.type); // and evolution if(type2==branch->sudakov()->interactionType()) { if(zsplit < 0.5 || // hardest line veto fb.kinematics->scale()*zsplit < branch->scale() ) { // angular ordering veto particle->vetoEmission(fb.type,fb.kinematics->scale()); continue; } } // pt veto if(fb.kinematics->pT() > progenitor()->maximumpT(type2)) { particle->vetoEmission(fb.type,fb.kinematics->scale()); continue; } } // standard vetos for all emissions if(timeLikeVetoed(fb,particle)) { particle->vetoEmission(fb.type,fb.kinematics->scale()); if(particle->spinInfo()) particle->spinInfo()->decayVertex(VertexPtr()); continue; } // special for already decayed particles // don't allow flavour changing branchings bool vetoDecay = false; for(map >::const_iterator tit = currentTree()->treelinks().begin(); tit != currentTree()->treelinks().end();++tit) { if(tit->second.first == progenitor()) { map::const_iterator it = currentTree()->outgoingLines().find(progenitor()); if(it!=currentTree()->outgoingLines().end() && particle == it->second && fb.ids[0]!=fb.ids[1] && fb.ids[1]!=fb.ids[2]) { vetoDecay = true; break; } } } if(vetoDecay) { particle->vetoEmission(fb.type,fb.kinematics->scale()); if(particle->spinInfo()) particle->spinInfo()->decayVertex(VertexPtr()); continue; } break; } // normal case if(!branch) { if(fb.kinematics) fb.hard = false; return fb; } // truncated emission if(fb.kinematics) { fb.hard = false; fb.iout = iout; return fb; } // otherwise need to return the hard emission // construct the kinematics for the hard emission ShoKinPtr showerKin = new_ptr(FS_QTildeShowerKinematics1to2( branch->scale(), branch->children()[0]->z(), branch->phi(), branch->children()[0]->pT(), branch->sudakov() )); IdList idlist(3); idlist[0] = particle->dataPtr(); idlist[1] = branch->children()[0]->branchingParticle()->dataPtr(); idlist[2] = branch->children()[1]->branchingParticle()->dataPtr(); fb = Branching( showerKin, idlist, branch->sudakov(),branch->type() ); fb.hard = true; fb.iout=0; // return it return fb; } Branching QTildeShowerHandler::selectSpaceLikeDecayBranching(tShowerParticlePtr particle, const ShowerParticle::EvolutionScales & maxScales, Energy minmass,ShowerInteraction type, HardBranchingPtr branch) { Branching fb; unsigned int iout=0; while (true) { // break if doing truncated shower and no truncated shower needed if(branch && (!isTruncatedShowerON()||hardOnly())) break; // select branching fb=_splittingGenerator->chooseDecayBranching(*particle,maxScales,minmass, _initialenhance,type); // return if no radiation if(!fb.kinematics) break; // special for truncated shower if(branch) { // check haven't evolved too far if(fb.kinematics->scale() < branch->scale()) { fb=Branching(); break; } // find the truncated line iout=0; if(fb.ids[1]->id()!=fb.ids[2]->id()) { if(fb.ids[1]->id()==particle->id()) iout=1; else if (fb.ids[2]->id()==particle->id()) iout=2; } else if(fb.ids[1]->id()==particle->id()) { if(fb.kinematics->z()>0.5) iout=1; else iout=2; } // apply the vetos for the truncated shower // no flavour changing branchings if(iout==0) { particle->vetoEmission(fb.type,fb.kinematics->scale()); continue; } ShowerInteraction type2 = convertInteraction(fb.type); double zsplit = iout==1 ? fb.kinematics->z() : 1-fb.kinematics->z(); if(type2==branch->sudakov()->interactionType()) { if(zsplit < 0.5 || // hardest line veto fb.kinematics->scale()*zsplit < branch->scale() ) { // angular ordering veto particle->vetoEmission(fb.type,fb.kinematics->scale()); continue; } } // pt veto if(fb.kinematics->pT() > progenitor()->maximumpT(type2)) { particle->vetoEmission(fb.type,fb.kinematics->scale()); continue; } } // if not vetoed break if(spaceLikeDecayVetoed(fb,particle)) { // otherwise reset scale and continue particle->vetoEmission(fb.type,fb.kinematics->scale()); continue; } break; } // normal case if(!branch) { if(fb.kinematics) fb.hard = false; return fb; } // truncated emission if(fb.kinematics) { fb.hard = false; fb.iout = iout; return fb; } // otherwise need to return the hard emission // construct the kinematics for the hard emission ShoKinPtr showerKin = new_ptr(Decay_QTildeShowerKinematics1to2( branch->scale(), branch->children()[0]->z(), branch->phi(), branch->children()[0]->pT(), branch->sudakov())); IdList idlist(3); idlist[0] = particle->dataPtr(); idlist[1] = branch->children()[0]->branchingParticle()->dataPtr(); idlist[2] = branch->children()[1]->branchingParticle()->dataPtr(); // create the branching fb = Branching( showerKin, idlist, branch->sudakov(),ShowerPartnerType::QCDColourLine ); fb.hard=true; fb.iout=0; // return it return fb; } void QTildeShowerHandler::checkFlags() { string error = "Inconsistent hard emission set-up in QTildeShowerHandler::showerHardProcess(). "; if ( ( currentTree()->isMCatNLOSEvent() || currentTree()->isMCatNLOHEvent() ) ) { if (_hardEmission ==2 ) throw Exception() << error << "Cannot generate POWHEG matching with MC@NLO shower " << "approximation. Add 'set QTildeShowerHandler:HardEmission 0' to input file." << Exception::runerror; if ( canHandleMatchboxTrunc() ) throw Exception() << error << "Cannot use truncated qtilde shower with MC@NLO shower " << "approximation. Set LHCGenerator:EventHandler" << ":CascadeHandler to '/Herwig/Shower/ShowerHandler' or " << "'/Herwig/Shower/Dipole/DipoleShowerHandler'." << Exception::runerror; } else if ( ((currentTree()->isPowhegSEvent() || currentTree()->isPowhegHEvent()) ) && _hardEmission != 2){ if ( canHandleMatchboxTrunc()) throw Exception() << error << "Unmatched events requested for POWHEG shower " << "approximation. Set QTildeShowerHandler:HardEmission to " << "'POWHEG'." << Exception::runerror; else if (_hardEmissionWarn) { _hardEmissionWarn = false; _hardEmission=2; throw Exception() << error << "Unmatched events requested for POWHEG shower " << "approximation. Changing QTildeShowerHandler:HardEmission from " << _hardEmission << " to 2" << Exception::warning; } } if ( currentTree()->isPowhegSEvent() || currentTree()->isPowhegHEvent()) { if (currentTree()->showerApproximation()->needsTruncatedShower() && !canHandleMatchboxTrunc() ) throw Exception() << error << "Current shower handler cannot generate truncated shower. " << "Set Generator:EventHandler:CascadeHandler to " << "'/Herwig/Shower/PowhegShowerHandler'." << Exception::runerror; } else if ( currentTree()->truncatedShower() && _missingTruncWarn) { _missingTruncWarn=false; throw Exception() << "Warning: POWHEG shower approximation used without " << "truncated shower. Set Generator:EventHandler:" << "CascadeHandler to '/Herwig/Shower/PowhegShowerHandler' and " << "'MEMatching:TruncatedShower Yes'." << Exception::warning; } // else if ( !dipme && _hardEmissionMode > 1 && // firstInteraction()) // throw Exception() << error // << "POWHEG matching requested for LO events. Include " // << "'set Factory:ShowerApproximation MEMatching' in input file." // << Exception::runerror; } tPPair QTildeShowerHandler::remakeRemnant(tPPair oldp){ // get the parton extractor PartonExtractor & pex = *lastExtractor(); // get the new partons tPPair newp = make_pair(findFirstParton(oldp.first ), findFirstParton(oldp.second)); // if the same do nothing if(newp == oldp) return oldp; // Creates the new remnants and returns the new PartonBinInstances // ATTENTION Broken here for very strange configuration PBIPair newbins = pex.newRemnants(oldp, newp, newStep()); newStep()->addIntermediate(newp.first); newStep()->addIntermediate(newp.second); // return the new partons return newp; } PPtr QTildeShowerHandler::findFirstParton(tPPtr seed) const{ if(seed->parents().empty()) return seed; tPPtr parent = seed->parents()[0]; //if no parent there this is a loose end which will //be connected to the remnant soon. if(!parent || parent == incomingBeams().first || parent == incomingBeams().second ) return seed; else return findFirstParton(parent); } void QTildeShowerHandler::decay(ShowerTreePtr tree, ShowerDecayMap & decay) { // must be one incoming particle assert(tree->incomingLines().size()==1); // apply any transforms tree->applyTransforms(); // if already decayed return if(!tree->outgoingLines().empty()) return; // now we need to replace the particle with a new copy after the shower // find particle after the shower map >::const_iterator tit = tree->parent()->treelinks().find(tree); assert(tit!=tree->parent()->treelinks().end()); ShowerParticlePtr newparent=tit->second.second; PerturbativeProcessPtr newProcess = new_ptr(PerturbativeProcess()); newProcess->incoming().push_back(make_pair(newparent,PerturbativeProcessPtr())); DecayProcessMap decayMap; ShowerHandler::decay(newProcess,decayMap); ShowerTree::constructTrees(tree,decay,newProcess,decayMap); } namespace { ShowerProgenitorPtr findFinalStateLine(ShowerTreePtr tree, long id, Lorentz5Momentum momentum) { map::iterator partner; Energy2 dmin(1e30*GeV2); for(map::iterator cit =tree->outgoingLines().begin(); cit!=tree->outgoingLines().end(); ++cit) { if(cit->second->id()!=id) continue; Energy2 test = sqr(cit->second->momentum().x()-momentum.x())+ sqr(cit->second->momentum().y()-momentum.y())+ sqr(cit->second->momentum().z()-momentum.z())+ sqr(cit->second->momentum().t()-momentum.t()); if(testfirst; } ShowerProgenitorPtr findInitialStateLine(ShowerTreePtr tree, long id, Lorentz5Momentum momentum) { map::iterator partner; Energy2 dmin(1e30*GeV2); for(map::iterator cit =tree->incomingLines().begin(); cit!=tree->incomingLines().end(); ++cit) { if(cit->second->id()!=id) continue; Energy2 test = sqr(cit->second->momentum().x()-momentum.x())+ sqr(cit->second->momentum().y()-momentum.y())+ sqr(cit->second->momentum().z()-momentum.z())+ sqr(cit->second->momentum().t()-momentum.t()); if(testfirst; } void fixSpectatorColours(PPtr newSpect,ShowerProgenitorPtr oldSpect, ColinePair & cline,ColinePair & aline, bool reconnect) { cline.first = oldSpect->progenitor()->colourLine(); cline.second = newSpect->colourLine(); aline.first = oldSpect->progenitor()->antiColourLine(); aline.second = newSpect->antiColourLine(); if(!reconnect) return; if(cline.first) { cline.first ->removeColoured(oldSpect->copy()); cline.first ->removeColoured(oldSpect->progenitor()); cline.second->removeColoured(newSpect); cline.first ->addColoured(newSpect); } if(aline.first) { aline.first ->removeAntiColoured(oldSpect->copy()); aline.first ->removeAntiColoured(oldSpect->progenitor()); aline.second->removeAntiColoured(newSpect); aline.first ->addAntiColoured(newSpect); } } void fixInitialStateEmitter(ShowerTreePtr tree, PPtr newEmit,PPtr emitted, ShowerProgenitorPtr emitter, ColinePair cline,ColinePair aline,double x) { // sort out the colours if(emitted->dataPtr()->iColour()==PDT::Colour8) { // emitter if(cline.first && cline.first == emitter->progenitor()->antiColourLine() && cline.second !=newEmit->antiColourLine()) { // sort out not radiating line ColinePtr col = emitter->progenitor()->colourLine(); if(col) { col->removeColoured(emitter->copy()); col->removeColoured(emitter->progenitor()); newEmit->colourLine()->removeColoured(newEmit); col->addColoured(newEmit); } } else if(aline.first && aline.first == emitter->progenitor()->colourLine() && aline.second !=newEmit->colourLine()) { // sort out not radiating line ColinePtr anti = emitter->progenitor()->antiColourLine(); if(anti) { anti->removeAntiColoured(emitter->copy()); anti->removeAntiColoured(emitter->progenitor()); newEmit->colourLine()->removeAntiColoured(newEmit); anti->addAntiColoured(newEmit); } } else assert(false); // emitted if(cline.first && cline.second==emitted->colourLine()) { cline.second->removeColoured(emitted); cline.first->addColoured(emitted); } else if(aline.first && aline.second==emitted->antiColourLine()) { aline.second->removeAntiColoured(emitted); aline.first->addAntiColoured(emitted); } else assert(false); } else { if(emitter->progenitor()->antiColourLine() ) { ColinePtr col = emitter->progenitor()->antiColourLine(); col->removeAntiColoured(emitter->copy()); col->removeAntiColoured(emitter->progenitor()); if(newEmit->antiColourLine()) { newEmit->antiColourLine()->removeAntiColoured(newEmit); col->addAntiColoured(newEmit); } else if (emitted->colourLine()) { emitted->colourLine()->removeColoured(emitted); col->addColoured(emitted); } else assert(false); } if(emitter->progenitor()->colourLine() ) { ColinePtr col = emitter->progenitor()->colourLine(); col->removeColoured(emitter->copy()); col->removeColoured(emitter->progenitor()); if(newEmit->colourLine()) { newEmit->colourLine()->removeColoured(newEmit); col->addColoured(newEmit); } else if (emitted->antiColourLine()) { emitted->antiColourLine()->removeAntiColoured(emitted); col->addAntiColoured(emitted); } else assert(false); } } // update the emitter emitter->copy(newEmit); ShowerParticlePtr sp = new_ptr(ShowerParticle(*newEmit,1,false)); sp->x(x); emitter->progenitor(sp); tree->incomingLines()[emitter]=sp; emitter->perturbative(false); // add emitted sp=new_ptr(ShowerParticle(*emitted,1,true)); ShowerProgenitorPtr gluon=new_ptr(ShowerProgenitor(emitter->original(),emitted,sp)); gluon->perturbative(false); tree->outgoingLines().insert(make_pair(gluon,sp)); } void fixFinalStateEmitter(ShowerTreePtr tree, PPtr newEmit,PPtr emitted, ShowerProgenitorPtr emitter, ColinePair cline,ColinePair aline) { map >::const_iterator tit; // special case if decayed for(tit = tree->treelinks().begin(); tit != tree->treelinks().end();++tit) { if(tit->second.first && tit->second.second==emitter->progenitor()) break; } // sort out the colour lines if(cline.first && cline.first == emitter->progenitor()->antiColourLine() && cline.second !=newEmit->antiColourLine()) { // sort out not radiating line ColinePtr col = emitter->progenitor()->colourLine(); if(col) { col->removeColoured(emitter->copy()); col->removeColoured(emitter->progenitor()); newEmit->colourLine()->removeColoured(newEmit); col->addColoured(newEmit); } } else if(aline.first && aline.first == emitter->progenitor()->colourLine() && aline.second !=newEmit->colourLine()) { // sort out not radiating line ColinePtr anti = emitter->progenitor()->antiColourLine(); if(anti) { anti->removeAntiColoured(emitter->copy()); anti->removeAntiColoured(emitter->progenitor()); newEmit->colourLine()->removeAntiColoured(newEmit); anti->addAntiColoured(newEmit); } } else assert(false); // update the emitter emitter->copy(newEmit); ShowerParticlePtr sp = new_ptr(ShowerParticle(*newEmit,1,true)); emitter->progenitor(sp); tree->outgoingLines()[emitter]=sp; emitter->perturbative(false); // update for decaying particles if(tit!=tree->treelinks().end()) tree->updateLink(tit->first,make_pair(emitter,sp)); // add the emitted particle // sort out the colour if(cline.first && cline.second==emitted->antiColourLine()) { cline.second->removeAntiColoured(emitted); cline.first->addAntiColoured(emitted); } else if(aline.first && aline.second==emitted->colourLine()) { aline.second->removeColoured(emitted); aline.first->addColoured(emitted); } else assert(false); sp=new_ptr(ShowerParticle(*emitted,1,true)); ShowerProgenitorPtr gluon=new_ptr(ShowerProgenitor(emitter->original(), emitted,sp)); gluon->perturbative(false); tree->outgoingLines().insert(make_pair(gluon,sp)); } } void QTildeShowerHandler::setupMECorrection(RealEmissionProcessPtr real) { assert(real); // II emission if(real->emitter() < real->incoming().size() && real->spectator() < real->incoming().size()) { // recoiling system for( map::const_iterator cjt= currentTree()->outgoingLines().begin(); cjt != currentTree()->outgoingLines().end();++cjt ) { cjt->first->progenitor()->transform(real->transformation()); cjt->first->copy()->transform(real->transformation()); } // the the radiating system ShowerProgenitorPtr emitter,spectator; unsigned int iemit = real->emitter(); unsigned int ispect = real->spectator(); int ig = int(real->emitted())-int(real->incoming().size()); emitter = findInitialStateLine(currentTree(), real->bornIncoming()[iemit]->id(), real->bornIncoming()[iemit]->momentum()); spectator = findInitialStateLine(currentTree(), real->bornIncoming()[ispect]->id(), real->bornIncoming()[ispect]->momentum()); // sort out the colours ColinePair cline,aline; fixSpectatorColours(real->incoming()[ispect],spectator,cline,aline,true); // update the spectator spectator->copy(real->incoming()[ispect]); ShowerParticlePtr sp(new_ptr(ShowerParticle(*real->incoming()[ispect],1,false))); sp->x(ispect ==0 ? real->x().first :real->x().second); spectator->progenitor(sp); currentTree()->incomingLines()[spectator]=sp; spectator->perturbative(true); // now for the emitter fixInitialStateEmitter(currentTree(),real->incoming()[iemit],real->outgoing()[ig], emitter,cline,aline,iemit ==0 ? real->x().first :real->x().second); } // FF emission else if(real->emitter() >= real->incoming().size() && real->spectator() >= real->incoming().size()) { assert(real->outgoing()[real->emitted()-real->incoming().size()]->id()==ParticleID::g); // find the emitter and spectator in the shower tree ShowerProgenitorPtr emitter,spectator; int iemit = int(real->emitter())-int(real->incoming().size()); emitter = findFinalStateLine(currentTree(), real->bornOutgoing()[iemit]->id(), real->bornOutgoing()[iemit]->momentum()); int ispect = int(real->spectator())-int(real->incoming().size()); spectator = findFinalStateLine(currentTree(), real->bornOutgoing()[ispect]->id(), real->bornOutgoing()[ispect]->momentum()); map >::const_iterator tit; // first the spectator // special case if decayed for(tit = currentTree()->treelinks().begin(); tit != currentTree()->treelinks().end();++tit) { if(tit->second.first && tit->second.second==spectator->progenitor()) break; } // sort out the colours ColinePair cline,aline; fixSpectatorColours(real->outgoing()[ispect],spectator,cline,aline,true); // update the spectator spectator->copy(real->outgoing()[ispect]); ShowerParticlePtr sp(new_ptr(ShowerParticle(*real->outgoing()[ispect],1,true))); spectator->progenitor(sp); currentTree()->outgoingLines()[spectator]=sp; spectator->perturbative(true); // update for decaying particles if(tit!=currentTree()->treelinks().end()) currentTree()->updateLink(tit->first,make_pair(spectator,sp)); // now the emitting particle int ig = int(real->emitted())-int(real->incoming().size()); fixFinalStateEmitter(currentTree(),real->outgoing()[iemit], real->outgoing()[ig], emitter,cline,aline); } // IF emission else { // scattering process if(real->incoming().size()==2) { ShowerProgenitorPtr emitter,spectator; unsigned int iemit = real->emitter(); unsigned int ispect = real->spectator(); int ig = int(real->emitted())-int(real->incoming().size()); ColinePair cline,aline; // incoming spectator if(ispect<2) { spectator = findInitialStateLine(currentTree(), real->bornIncoming()[ispect]->id(), real->bornIncoming()[ispect]->momentum()); fixSpectatorColours(real->incoming()[ispect],spectator,cline,aline,true); // update the spectator spectator->copy(real->incoming()[ispect]); ShowerParticlePtr sp(new_ptr(ShowerParticle(*real->incoming()[ispect],1,false))); sp->x(ispect ==0 ? real->x().first :real->x().second); spectator->progenitor(sp); currentTree()->incomingLines()[spectator]=sp; spectator->perturbative(true); } // outgoing spectator else { spectator = findFinalStateLine(currentTree(), real->bornOutgoing()[ispect-real->incoming().size()]->id(), real->bornOutgoing()[ispect-real->incoming().size()]->momentum()); // special case if decayed map >::const_iterator tit; for(tit = currentTree()->treelinks().begin(); tit != currentTree()->treelinks().end();++tit) { if(tit->second.first && tit->second.second==spectator->progenitor()) break; } fixSpectatorColours(real->outgoing()[ispect-real->incoming().size()],spectator,cline,aline,true); // update the spectator spectator->copy(real->outgoing()[ispect-real->incoming().size()]); ShowerParticlePtr sp(new_ptr(ShowerParticle(*real->outgoing()[ispect-real->incoming().size()],1,true))); spectator->progenitor(sp); currentTree()->outgoingLines()[spectator]=sp; spectator->perturbative(true); // update for decaying particles if(tit!=currentTree()->treelinks().end()) currentTree()->updateLink(tit->first,make_pair(spectator,sp)); } // incoming emitter if(iemit<2) { emitter = findInitialStateLine(currentTree(), real->bornIncoming()[iemit]->id(), real->bornIncoming()[iemit]->momentum()); fixInitialStateEmitter(currentTree(),real->incoming()[iemit],real->outgoing()[ig], emitter,aline,cline,iemit ==0 ? real->x().first :real->x().second); } // outgoing emitter else { emitter = findFinalStateLine(currentTree(), real->bornOutgoing()[iemit-real->incoming().size()]->id(), real->bornOutgoing()[iemit-real->incoming().size()]->momentum()); fixFinalStateEmitter(currentTree(),real->outgoing()[iemit-real->incoming().size()], real->outgoing()[ig],emitter,aline,cline); } } // decay process else { assert(real->spectator()==0); unsigned int iemit = real->emitter()-real->incoming().size(); int ig = int(real->emitted())-int(real->incoming().size()); ColinePair cline,aline; // incoming spectator ShowerProgenitorPtr spectator = findInitialStateLine(currentTree(), real->bornIncoming()[0]->id(), real->bornIncoming()[0]->momentum()); fixSpectatorColours(real->incoming()[0],spectator,cline,aline,false); // find the emitter ShowerProgenitorPtr emitter = findFinalStateLine(currentTree(), real->bornOutgoing()[iemit]->id(), real->bornOutgoing()[iemit]->momentum()); // recoiling system for( map::const_iterator cjt= currentTree()->outgoingLines().begin(); cjt != currentTree()->outgoingLines().end();++cjt ) { if(cjt->first==emitter) continue; cjt->first->progenitor()->transform(real->transformation()); cjt->first->copy()->transform(real->transformation()); } // sort out the emitter fixFinalStateEmitter(currentTree(),real->outgoing()[iemit], real->outgoing()[ig],emitter,aline,cline); } } // clean up the shower tree _currenttree->resetShowerProducts(); } diff --git a/Shower/QTilde/SplittingFunctions/HalfHalfOneSplitFn.cc b/Shower/QTilde/SplittingFunctions/HalfHalfOneSplitFn.cc --- a/Shower/QTilde/SplittingFunctions/HalfHalfOneSplitFn.cc +++ b/Shower/QTilde/SplittingFunctions/HalfHalfOneSplitFn.cc @@ -1,134 +1,134 @@ // -*- C++ -*- // // HalfHalfOneSplitFn.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 HalfHalfOneSplitFn class. // #include "HalfHalfOneSplitFn.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "Herwig/Decay/TwoBodyDecayMatrixElement.h" using namespace Herwig; DescribeNoPIOClass describeHalfHalfOneSplitFn ("Herwig::HalfHalfOneSplitFn","HwShower.so"); void HalfHalfOneSplitFn::Init() { static ClassDocumentation documentation ("The HalfHalfOneSplitFn class implements the q -> qg splitting function"); } double HalfHalfOneSplitFn::P(const double z, const Energy2 t, const IdList &ids, const bool mass, const RhoDMatrix & ) const { double val = (1. + sqr(z))/(1.-z); if(mass) { Energy m = ids[0]->mass(); val -= 2.*sqr(m)/t; } return colourFactor(ids)*val; } double HalfHalfOneSplitFn::overestimateP(const double z, const IdList & ids) const { return 2.*colourFactor(ids)/(1.-z); } double HalfHalfOneSplitFn::ratioP(const double z, const Energy2 t, const IdList & ids, const bool mass, const RhoDMatrix & ) const { double val = 1. + sqr(z); if(mass) { Energy m = ids[0]->mass(); val -= 2.*sqr(m)*(1.-z)/t; } return 0.5*val; } double HalfHalfOneSplitFn::integOverP(const double z, const IdList & ids, unsigned int PDFfactor) const { switch (PDFfactor) { case 0: return -2.*colourFactor(ids)*Math::log1m(z); case 1: return 2.*colourFactor(ids)*log(z/(1.-z)); case 2: return 2.*colourFactor(ids)/(1.-z); case 3: default: throw Exception() << "HalfHalfOneSplitFn::integOverP() invalid PDFfactor = " << PDFfactor << Exception::runerror; } } double HalfHalfOneSplitFn::invIntegOverP(const double r, const IdList & ids, unsigned int PDFfactor) const { switch (PDFfactor) { case 0: return 1. - exp(- 0.5*r/colourFactor(ids)); case 1: return 1./(1.-exp(-0.5*r/colourFactor(ids))); case 2: return 1.-2.*colourFactor(ids)/r; case 3: default: throw Exception() << "HalfHalfOneSplitFn::invIntegOverP() invalid PDFfactor = " << PDFfactor << Exception::runerror; } } bool HalfHalfOneSplitFn::accept(const IdList &ids) const { // 3 particles and in and out fermion same if(ids.size()!=3 || ids[0]!=ids[1]) return false; if(ids[0]->iSpin()!=PDT::Spin1Half || ids[2]->iSpin()!=PDT::Spin1) return false; return checkColours(ids); } vector > HalfHalfOneSplitFn::generatePhiForward(const double, const Energy2, const IdList & , const RhoDMatrix &) { // no dependence on the spin density matrix, dependence on off-diagonal terms cancels // and rest = splitting function for Tr(rho)=1 as required by defn - return vector >(1,make_pair(0,1.)); + return {{ {0, 1.} }}; } vector > HalfHalfOneSplitFn::generatePhiBackward(const double, const Energy2, const IdList & , const RhoDMatrix &) { // no dependence on the spin density matrix, dependence on off-diagonal terms cancels // and rest = splitting function for Tr(rho)=1 as required by defn - return vector >(1,make_pair(0,1.)); + return {{ {0, 1.} }}; } DecayMEPtr HalfHalfOneSplitFn::matrixElement(const double z, const Energy2 t, const IdList & ids, const double phi, bool timeLike) { // calculate the kernal DecayMEPtr kernal(new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1Half,PDT::Spin1Half,PDT::Spin1))); Energy m = !timeLike ? ZERO : ids[0]->mass(); double mt = m/sqrt(t); double root = sqrt(1.-(1.-z)*sqr(m)/z/t); double romz = sqrt(1.-z); double rz = sqrt(z); Complex phase = exp(Complex(0.,1.)*phi); (*kernal)(0,0,0) = -root/romz*phase; (*kernal)(1,1,2) = -conj((*kernal)(0,0,0)); (*kernal)(0,0,2) = root/romz*z/phase; (*kernal)(1,1,0) = -conj((*kernal)(0,0,2)); (*kernal)(1,0,2) = mt*(1.-z)/rz; (*kernal)(0,1,0) = conj((*kernal)(1,0,2)); (*kernal)(0,1,2) = 0.; (*kernal)(1,0,0) = 0.; return kernal; } diff --git a/Shower/QTilde/SplittingFunctions/HalfOneHalfSplitFn.cc b/Shower/QTilde/SplittingFunctions/HalfOneHalfSplitFn.cc --- a/Shower/QTilde/SplittingFunctions/HalfOneHalfSplitFn.cc +++ b/Shower/QTilde/SplittingFunctions/HalfOneHalfSplitFn.cc @@ -1,143 +1,143 @@ // -*- C++ -*- // // HalfOneHalfSplitFn.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 HalfOneHalfSplitFn class. // #include "HalfOneHalfSplitFn.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "Herwig/Decay/TwoBodyDecayMatrixElement.h" using namespace Herwig; DescribeNoPIOClass describeHalfOneHalfSplitFn ("Herwig::HalfOneHalfSplitFn","HwShower.so"); void HalfOneHalfSplitFn::Init() { static ClassDocumentation documentation ("The HalfOneHalfSplitFn class implements the splitting " "function for q -> g q"); } double HalfOneHalfSplitFn::P(const double z, const Energy2 t, const IdList &ids, const bool mass, const RhoDMatrix & ) const { double val=(2.*(1.-z)+sqr(z))/z; if(mass) { Energy m = ids[0]->mass(); val-=2.*sqr(m)/t; } return colourFactor(ids)*val; } double HalfOneHalfSplitFn::overestimateP(const double z, const IdList &ids) const { return 2.*colourFactor(ids)/z; } double HalfOneHalfSplitFn::ratioP(const double z, const Energy2 t, const IdList &ids,const bool mass, const RhoDMatrix & ) const { double val=2.*(1.-z)+sqr(z); if(mass) { Energy m=ids[0]->mass(); val -=2.*sqr(m)*z/t; } return 0.5*val; } double HalfOneHalfSplitFn::integOverP(const double z, const IdList & ids, unsigned int PDFfactor) const { switch(PDFfactor) { case 0: return 2.*colourFactor(ids)*log(z); case 1: return -2.*colourFactor(ids)/z; case 2: return 2.*colourFactor(ids)*log(z/(1.-z)); case 3: default: throw Exception() << "HalfOneHalfSplitFn::integOverP() invalid PDFfactor = " << PDFfactor << Exception::runerror; } } double HalfOneHalfSplitFn::invIntegOverP(const double r, const IdList & ids, unsigned int PDFfactor) const { switch(PDFfactor) { case 0: return exp(0.5*r/colourFactor(ids)); case 1: return -2.*colourFactor(ids)/r; case 2: return 1./(1.+exp(-0.5*r/colourFactor(ids))); case 3: default: throw Exception() << "HalfOneHalfSplitFn::integOverP() invalid PDFfactor = " << PDFfactor << Exception::runerror; } } bool HalfOneHalfSplitFn::accept(const IdList &ids) const { // 3 particles and in and out fermion same if(ids.size()!=3 || ids[0]!=ids[2]) return false; if(ids[0]->iSpin()!=PDT::Spin1Half || ids[1]->iSpin()!=PDT::Spin1) return false; return checkColours(ids); } vector > HalfOneHalfSplitFn::generatePhiForward(const double, const Energy2, const IdList & , const RhoDMatrix &) { // no dependence on the spin density matrix, dependence on off-diagonal terms cancels // and rest = splitting function for Tr(rho)=1 as required by defn - return vector >(1,make_pair(0,1.)); + return {{ {0, 1.} }}; } vector > HalfOneHalfSplitFn::generatePhiBackward(const double z, const Energy2 t, const IdList & ids, const RhoDMatrix & rho) { assert(rho.iSpin()==PDT::Spin1); double mt = sqr(ids[0]->mass())/t; double diag = (1.+sqr(1.-z))/z - 2.*mt; double off = 2.*(1.-z)/z*(1.-mt*z/(1.-z)); double max = diag+2.*abs(rho(0,2))*off; vector > output; output.push_back(make_pair( 0, (rho(0,0)+rho(2,2))*diag/max)); output.push_back(make_pair( 2, -rho(0,2) * off/max)); output.push_back(make_pair(-2, -rho(2,0) * off/max)); return output; } DecayMEPtr HalfOneHalfSplitFn::matrixElement(const double z, const Energy2 t, const IdList & ids, const double phi, bool timeLike) { // calculate the kernal DecayMEPtr kernal(new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1Half,PDT::Spin1,PDT::Spin1Half))); Energy m = !timeLike ? ZERO : ids[0]->mass(); double mt = m/sqrt(t); double root = sqrt(1.-z*sqr(m)/(1.-z)/t); double romz = sqrt(1.-z); double rz = sqrt(z); Complex phase = exp(-Complex(0.,1.)*phi); (*kernal)(0,0,0) = -root/rz/phase; (*kernal)(1,2,1) = -conj((*kernal)(0,0,0)); (*kernal)(0,2,0) = root/rz*(1.-z)*phase; (*kernal)(1,0,1) = -conj((*kernal)(0,2,0)); (*kernal)(1,2,0) = mt*z/romz; (*kernal)(0,0,1) = conj((*kernal)(1,2,0)); (*kernal)(0,2,1) = 0.; (*kernal)(1,0,0) = 0.; return kernal; } diff --git a/Shower/QTilde/SplittingFunctions/OneHalfHalfSplitFn.cc b/Shower/QTilde/SplittingFunctions/OneHalfHalfSplitFn.cc --- a/Shower/QTilde/SplittingFunctions/OneHalfHalfSplitFn.cc +++ b/Shower/QTilde/SplittingFunctions/OneHalfHalfSplitFn.cc @@ -1,150 +1,150 @@ // -*- C++ -*- // // OneHalfHalfSplitFn.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 OneHalfHalfSplitFn class. // #include "OneHalfHalfSplitFn.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "Herwig/Decay/TwoBodyDecayMatrixElement.h" using namespace Herwig; DescribeNoPIOClass describeOneHalfHalfSplitFn ("Herwig::OneHalfHalfSplitFn","HwShower.so"); void OneHalfHalfSplitFn::Init() { static ClassDocumentation documentation ("The OneHalfHalfSplitFn class implements the splitting function for g->q qbar"); } double OneHalfHalfSplitFn::P(const double z, const Energy2 t, const IdList &ids, const bool mass, const RhoDMatrix &) const { double zz = z*(1.-z); double val=1.-2.*zz; if(mass) { Energy m = ids[1]->mass(); val +=2.*sqr(m)/t; } return colourFactor(ids)*val; } double OneHalfHalfSplitFn::overestimateP(const double, const IdList &ids) const { return colourFactor(ids); } double OneHalfHalfSplitFn::ratioP(const double z, const Energy2 t, const IdList &ids, const bool mass, const RhoDMatrix &) const { double zz = z*(1.-z); double val = 1.-2.*zz; if(mass) { Energy m = ids[1]->mass(); val+= 2.*sqr(m)/t; } return val; } double OneHalfHalfSplitFn::integOverP(const double z, const IdList & ids, unsigned int PDFfactor) const { switch(PDFfactor) { case 0: return colourFactor(ids)*z; case 1: return colourFactor(ids)*log(z); case 2: return -colourFactor(ids)*log(1.-z); case 3: return colourFactor(ids)*log(z/(1.-z)); case 4: return colourFactor(ids)*2.*sqrt(z); case 5: return colourFactor(ids)*(2./3.)*z*sqrt(z); default: throw Exception() << "OneHalfHalfSplitFn::integOverP() invalid PDFfactor = " << PDFfactor << Exception::runerror; } } double OneHalfHalfSplitFn::invIntegOverP(const double r, const IdList & ids, unsigned int PDFfactor) const { switch(PDFfactor) { case 0: return r/colourFactor(ids); case 1: return exp(r/colourFactor(ids)); case 2: return 1.-exp(-r/colourFactor(ids)); case 3: return 1./(1.+exp(-r/colourFactor(ids))); case 4: return 0.25*sqr(r/colourFactor(ids)); case 5: return pow(1.5*r/colourFactor(ids),2./3.); default: throw Exception() << "OneHalfHalfSplitFn::integOverP() invalid PDFfactor = " << PDFfactor << Exception::runerror; } } bool OneHalfHalfSplitFn::accept(const IdList &ids) const { if(ids.size()!=3) return false; if(ids[1]!=ids[2]->CC()) return false; if(ids[1]->iSpin()!=PDT::Spin1Half) return false; if(ids[0]->iSpin()!=PDT::Spin1) return false; return checkColours(ids); } vector > OneHalfHalfSplitFn::generatePhiForward(const double z, const Energy2 t, const IdList & ids, const RhoDMatrix & rho) { assert(rho.iSpin()==PDT::Spin1); double modRho = abs(rho(0,2)); Energy mq = ids[1]->mass(); Energy2 mq2 = sqr(mq); double fact = z*(1.-z)-mq2/t; double max = 1.+2.*fact*(-1.+2.*modRho); vector > output; output.push_back(make_pair( 0,(rho(0,0)+rho(2,2))*(1.-2.*fact)/max)); output.push_back(make_pair(-2,2.*fact*rho(0,2)/max)); output.push_back(make_pair( 2,2.*fact*rho(2,0)/max)); return output; } vector > OneHalfHalfSplitFn::generatePhiBackward(const double, const Energy2, const IdList &, const RhoDMatrix & ) { // no dependance - return vector >(1,make_pair(0,1.)); + return {{ {0, 1.} }}; } DecayMEPtr OneHalfHalfSplitFn::matrixElement(const double z, const Energy2 t, const IdList & ids, const double phi, bool timeLike) { static const Complex ii(0.,1.); // calculate the kernal DecayMEPtr kernal(new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1,PDT::Spin1Half,PDT::Spin1Half))); double mt = !timeLike ? ZERO : ids[1]->mass()/sqrt(t); double root =sqrt(1.-sqr(mt)/z/(1.-z)); (*kernal)(0,0,0) = mt/sqrt(z*(1.-z)); (*kernal)(2,1,1) = (*kernal)(0,0,0); (*kernal)(0,0,1) = -z*root*exp(-ii*phi); (*kernal)(2,1,0) = -conj((*kernal)(0,0,1)); (*kernal)(0,1,0) = (1.-z)*exp(-ii*phi)*root; (*kernal)(2,0,1) = -conj((*kernal)(0,1,0)); (*kernal)(0,1,1) = 0.; (*kernal)(2,0,0) = 0.; return kernal; } diff --git a/Shower/QTilde/SplittingFunctions/SplittingGenerator.cc b/Shower/QTilde/SplittingFunctions/SplittingGenerator.cc --- a/Shower/QTilde/SplittingFunctions/SplittingGenerator.cc +++ b/Shower/QTilde/SplittingFunctions/SplittingGenerator.cc @@ -1,611 +1,617 @@ // -*- C++ -*- // // SplittingGenerator.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SplittingGenerator class. // #include "SplittingGenerator.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Command.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Utilities/StringUtils.h" #include "ThePEG/Repository/Repository.h" #include "Herwig/Shower/QTilde/Base/ShowerParticle.h" #include "Herwig/Shower/ShowerHandler.h" #include "ThePEG/Utilities/Rebinder.h" #include #include "ThePEG/Utilities/DescribeClass.h" using namespace Herwig; namespace { bool checkInteraction(ShowerInteraction allowed, ShowerInteraction splitting) { if(allowed==ShowerInteraction::Both) return true; else if(allowed == splitting) return true; else return false; } } DescribeClass describeSplittingGenerator ("Herwig::SplittingGenerator",""); IBPtr SplittingGenerator::clone() const { return new_ptr(*this); } IBPtr SplittingGenerator::fullclone() const { return new_ptr(*this); } void SplittingGenerator::persistentOutput(PersistentOStream & os) const { os << _bbranchings << _fbranchings << _deTuning; } void SplittingGenerator::persistentInput(PersistentIStream & is, int) { is >> _bbranchings >> _fbranchings >> _deTuning; } void SplittingGenerator::Init() { static ClassDocumentation documentation ("There class is responsible for initializing the Sudakov form factors ", "and generating splittings."); static Command interfaceAddSplitting ("AddFinalSplitting", "Adds another splitting to the list of splittings considered " "in the shower. Command is a->b,c; Sudakov", &SplittingGenerator::addFinalSplitting); static Command interfaceAddInitialSplitting ("AddInitialSplitting", "Adds another splitting to the list of initial splittings to consider " "in the shower. Command is a->b,c; Sudakov. Here the particle a is the " "particle that is PRODUCED by the splitting. b is the initial state " "particle that is splitting in the shower.", &SplittingGenerator::addInitialSplitting); static Command interfaceDeleteSplitting ("DeleteFinalSplitting", "Deletes a splitting from the list of splittings considered " "in the shower. Command is a->b,c; Sudakov", &SplittingGenerator::deleteFinalSplitting); static Command interfaceDeleteInitialSplitting ("DeleteInitialSplitting", "Deletes a splitting from the list of initial splittings to consider " "in the shower. Command is a->b,c; Sudakov. Here the particle a is the " "particle that is PRODUCED by the splitting. b is the initial state " "particle that is splitting in the shower.", &SplittingGenerator::deleteInitialSplitting); static Parameter interfaceDetuning ("Detuning", "The Detuning parameter to make the veto algorithm less efficient to improve the weight variations", &SplittingGenerator::_deTuning, 1.0, 1.0, 10.0, false, false, Interface::limited); } string SplittingGenerator::addSplitting(string arg, bool final) { string partons = StringUtils::car(arg); string sudakov = StringUtils::cdr(arg); vector products; string::size_type next = partons.find("->"); if(next == string::npos) return "Error: Invalid string for splitting " + arg; if(partons.find(';') == string::npos) return "Error: Invalid string for splitting " + arg; tPDPtr parent = Repository::findParticle(partons.substr(0,next)); partons = partons.substr(next+2); do { next = min(partons.find(','), partons.find(';')); tPDPtr pdp = Repository::findParticle(partons.substr(0,next)); partons = partons.substr(next+1); if(pdp) products.push_back(pdp); else return "Error: Could not create splitting from " + arg; } while(partons[0] != ';' && partons.size()); SudakovPtr s; s = dynamic_ptr_cast(Repository::TraceObject(sudakov)); if(!s) return "Error: Could not load Sudakov " + sudakov + '\n'; IdList ids; ids.push_back(parent); for(vector::iterator it = products.begin(); it!=products.end(); ++it) ids.push_back(*it); // check splitting can handle this if(!s->splittingFn()->accept(ids)) return "Error: Sudakov " + sudakov + " SplittingFunction can't handle particles\n"; // add to map addToMap(ids,s,final); return ""; } string SplittingGenerator::deleteSplitting(string arg, bool final) { string partons = StringUtils::car(arg); string sudakov = StringUtils::cdr(arg); vector products; string::size_type next = partons.find("->"); if(next == string::npos) return "Error: Invalid string for splitting " + arg; if(partons.find(';') == string::npos) return "Error: Invalid string for splitting " + arg; tPDPtr parent = Repository::findParticle(partons.substr(0,next)); partons = partons.substr(next+2); do { next = min(partons.find(','), partons.find(';')); tPDPtr pdp = Repository::findParticle(partons.substr(0,next)); partons = partons.substr(next+1); if(pdp) products.push_back(pdp); else return "Error: Could not create splitting from " + arg; } while(partons[0] != ';' && partons.size()); SudakovPtr s; s = dynamic_ptr_cast(Repository::TraceObject(sudakov)); if(!s) return "Error: Could not load Sudakov " + sudakov + '\n'; IdList ids; ids.push_back(parent); for(vector::iterator it = products.begin(); it!=products.end(); ++it) ids.push_back(*it); // check splitting can handle this if(!s->splittingFn()->accept(ids)) return "Error: Sudakov " + sudakov + " Splitting Function can't handle particles\n"; // delete from map deleteFromMap(ids,s,final); return ""; } void SplittingGenerator::addToMap(const IdList &ids, const SudakovPtr &s, bool final) { if(!final) { // search if the branching was already included. auto binsert =BranchingInsert(abs(ids[1]->id()),BranchingElement(s,ids)); // get the range of already inserted splittings. auto eqrange=_bbranchings.equal_range(binsert.first); for(auto it = eqrange.first; it != eqrange.second; ++it){ if((*it).second == binsert.second) throw Exception()<<"SplittingGenerator: Trying to insert existing splitting.\n" << Exception::setuperror; } _bbranchings.insert(binsert); s->addSplitting(ids); } else { // search if the branching was already included. auto binsert =BranchingInsert(abs(ids[0]->id()),BranchingElement(s,ids)); // get the range of already inserted splittings. auto eqrange=_fbranchings.equal_range(binsert.first); for(auto it = eqrange.first; it != eqrange.second; ++it){ if((*it).second ==binsert.second) throw Exception()<<"SplittingGenerator: Trying to insert existing splitting.\n" << Exception::setuperror; } _fbranchings.insert(binsert); s->addSplitting(ids); } } void SplittingGenerator::deleteFromMap(const IdList &ids, const SudakovPtr &s, bool final) { bool didRemove=false; if(!final) { pair range = _bbranchings.equal_range(abs(ids[1]->id())); for(BranchingList::iterator it=range.first; it!=range.second&&it!=_bbranchings.end();++it) { if(it->second.sudakov==s&&it->second.particles==ids) { BranchingList::iterator it2=it; --it; _bbranchings.erase(it2); didRemove=true; } } s->removeSplitting(ids); } else { pair range = _fbranchings.equal_range(abs(ids[0]->id())); for(BranchingList::iterator it=range.first; it!=range.second&&it!=_fbranchings.end();++it) { if(it->second.sudakov==s&&it->second.particles==ids) { BranchingList::iterator it2 = it; --it; _fbranchings.erase(it2); didRemove=true; } } s->removeSplitting(ids); } if (!didRemove) throw Exception()<<"SplittingGenerator: Try to remove non existing splitting.\n" << Exception::setuperror; } Branching SplittingGenerator::chooseForwardBranching(ShowerParticle &particle, double enhance, ShowerInteraction type) const { RhoDMatrix rho; bool rhoCalc(false); Energy newQ = ZERO; ShoKinPtr kinematics = ShoKinPtr(); ShowerPartnerType partnerType(ShowerPartnerType::Undefined); SudakovPtr sudakov = SudakovPtr(); IdList ids; // First, find the eventual branching, corresponding to the highest scale. long index = abs(particle.data().id()); // if no branchings return empty branching struct if( _fbranchings.find(index) == _fbranchings.end() ) return Branching(ShoKinPtr(), IdList(),SudakovPtr(),ShowerPartnerType::Undefined); // otherwise select branching for(BranchingList::const_iterator cit = _fbranchings.lower_bound(index); cit != _fbranchings.upper_bound(index); ++cit) { // check either right interaction or doing both if(!checkInteraction(type,cit->second.sudakov->interactionType())) continue; if(!rhoCalc) { rho = particle.extractRhoMatrix(true); rhoCalc = true; } // whether or not this interaction should be angular ordered bool angularOrdered = cit->second.sudakov->splittingFn()->angularOrdered(); ShoKinPtr newKin; ShowerPartnerType type; IdList particles = particle.id()!=cit->first ? cit->second.conjugateParticles : cit->second.particles; // work out which starting scale we need if(cit->second.sudakov->interactionType()==ShowerInteraction::QED) { type = ShowerPartnerType::QED; Energy startingScale = angularOrdered ? particle.scales().QED : particle.scales().QED_noAO; newKin = cit->second.sudakov-> generateNextTimeBranching(startingScale,particles,rho,enhance, _deTuning); } else if(cit->second.sudakov->interactionType()==ShowerInteraction::QCD) { // special for octets if(particle.dataPtr()->iColour()==PDT::Colour8) { // octet -> octet octet if(cit->second.sudakov->splittingFn()->colourStructure()==OctetOctetOctet) { type = ShowerPartnerType::QCDColourLine; Energy startingScale = angularOrdered ? particle.scales().QCD_c : particle.scales().QCD_c_noAO; newKin= cit->second.sudakov-> generateNextTimeBranching(startingScale,particles,rho,0.5*enhance, _deTuning); startingScale = angularOrdered ? particle.scales().QCD_ac : particle.scales().QCD_ac_noAO; ShoKinPtr newKin2 = cit->second.sudakov-> generateNextTimeBranching(startingScale,particles,rho,0.5*enhance, _deTuning); // pick the one with the highest scale if( ( newKin && newKin2 && newKin2->scale() > newKin->scale()) || (!newKin && newKin2) ) { newKin = newKin2; type = ShowerPartnerType::QCDAntiColourLine; } } // other g -> q qbar else { Energy startingScale = angularOrdered ? max(particle.scales().QCD_c , particle.scales().QCD_ac ) : max(particle.scales().QCD_c_noAO, particle.scales().QCD_ac_noAO); newKin= cit->second.sudakov-> generateNextTimeBranching(startingScale,particles,rho,enhance, _deTuning); type = UseRandom::rndbool() ? ShowerPartnerType::QCDColourLine : ShowerPartnerType::QCDAntiColourLine; } } // everything else q-> qg etc else { Energy startingScale; if(particle.hasColour()) { type = ShowerPartnerType::QCDColourLine; startingScale = angularOrdered ? particle.scales().QCD_c : particle.scales().QCD_c_noAO; } else { type = ShowerPartnerType::QCDAntiColourLine; startingScale = angularOrdered ? particle.scales().QCD_ac : particle.scales().QCD_ac_noAO; } newKin= cit->second.sudakov-> generateNextTimeBranching(startingScale,particles,rho,enhance, _deTuning); } } // shouldn't be anything else else assert(false); // if no kinematics contine if(!newKin) continue; // select highest scale if( newKin->scale() > newQ ) { kinematics = newKin; newQ = newKin->scale(); ids = particles; sudakov = cit->second.sudakov; partnerType = type; } } // return empty branching if nothing happened - if(!kinematics) return Branching(ShoKinPtr(), IdList(),SudakovPtr(), - ShowerPartnerType::Undefined); + if(!kinematics) { + if ( particle.spinInfo() ) particle.spinInfo()->undecay(); + return Branching(ShoKinPtr(), IdList(),SudakovPtr(), + ShowerPartnerType::Undefined); + } // if not hard generate phi kinematics->phi(sudakov->generatePhiForward(particle,ids,kinematics,rho)); // and return it return Branching(kinematics, ids,sudakov,partnerType); } Branching SplittingGenerator:: chooseDecayBranching(ShowerParticle &particle, const ShowerParticle::EvolutionScales & stoppingScales, Energy minmass, double enhance, ShowerInteraction interaction) const { RhoDMatrix rho(particle.dataPtr()->iSpin()); Energy newQ = Constants::MaxEnergy; ShoKinPtr kinematics; SudakovPtr sudakov; ShowerPartnerType partnerType(ShowerPartnerType::Undefined); IdList ids; // First, find the eventual branching, corresponding to the lowest scale. long index = abs(particle.data().id()); // if no branchings return empty branching struct if(_fbranchings.find(index) == _fbranchings.end()) return Branching(ShoKinPtr(), IdList(),SudakovPtr(),ShowerPartnerType::Undefined); // otherwise select branching for(BranchingList::const_iterator cit = _fbranchings.lower_bound(index); cit != _fbranchings.upper_bound(index); ++cit) { // check interaction doesn't change flavour if(cit->second.particles[1]->id()!=index&&cit->second.particles[2]->id()!=index) continue; // check either right interaction or doing both if(!checkInteraction(interaction,cit->second.sudakov->interactionType())) continue; // whether or not this interaction should be angular ordered bool angularOrdered = cit->second.sudakov->splittingFn()->angularOrdered(); ShoKinPtr newKin; IdList particles = particle.id()!=cit->first ? cit->second.conjugateParticles : cit->second.particles; ShowerPartnerType type; // work out which starting scale we need if(cit->second.sudakov->interactionType()==ShowerInteraction::QED) { type = ShowerPartnerType::QED; Energy stoppingScale = angularOrdered ? stoppingScales.QED : stoppingScales.QED_noAO; Energy startingScale = angularOrdered ? particle.scales().QED : particle.scales().QED_noAO; if(startingScale < stoppingScale ) { newKin = cit->second.sudakov-> generateNextDecayBranching(startingScale,stoppingScale,minmass,particles,rho,enhance,_deTuning); } } else if(cit->second.sudakov->interactionType()==ShowerInteraction::QCD) { // special for octets if(particle.dataPtr()->iColour()==PDT::Colour8) { // octet -> octet octet if(cit->second.sudakov->splittingFn()->colourStructure()==OctetOctetOctet) { Energy stoppingColour = angularOrdered ? stoppingScales.QCD_c : stoppingScales.QCD_c_noAO; Energy stoppingAnti = angularOrdered ? stoppingScales.QCD_ac : stoppingScales.QCD_ac_noAO; Energy startingColour = angularOrdered ? particle.scales().QCD_c : particle.scales().QCD_c_noAO; Energy startingAnti = angularOrdered ? particle.scales().QCD_ac : particle.scales().QCD_ac_noAO; type = ShowerPartnerType::QCDColourLine; if(startingColoursecond.sudakov-> generateNextDecayBranching(startingColour,stoppingColour,minmass, particles,rho,0.5*enhance,_deTuning); } ShoKinPtr newKin2; if(startingAntisecond.sudakov-> generateNextDecayBranching(startingAnti,stoppingAnti,minmass,particles,rho,0.5*enhance,_deTuning); } // pick the one with the lowest scale if( (newKin&&newKin2&&newKin2->scale()scale()) || (!newKin&&newKin2) ) { newKin = newKin2; type = ShowerPartnerType::QCDAntiColourLine; } } // other else { assert(false); } } // everything else else { Energy startingScale,stoppingScale; if(particle.hasColour()) { type = ShowerPartnerType::QCDColourLine; stoppingScale = angularOrdered ? stoppingScales.QCD_c : stoppingScales.QCD_c_noAO; startingScale = angularOrdered ? particle.scales().QCD_c : particle.scales().QCD_c_noAO; } else { type = ShowerPartnerType::QCDAntiColourLine; stoppingScale = angularOrdered ? stoppingScales.QCD_ac : stoppingScales.QCD_ac_noAO; startingScale = angularOrdered ? particle.scales().QCD_ac : particle.scales().QCD_ac_noAO; } if(startingScale < stoppingScale ) { newKin = cit->second.sudakov-> generateNextDecayBranching(startingScale,stoppingScale,minmass,particles,rho,enhance,_deTuning); } } } // shouldn't be anything else else assert(false); if(!newKin) continue; // select highest scale if(newKin->scale() < newQ ) { newQ = newKin->scale(); ids = particles; kinematics=newKin; sudakov=cit->second.sudakov; partnerType = type; } } // return empty branching if nothing happened if(!kinematics) return Branching(ShoKinPtr(), IdList(),SudakovPtr(), ShowerPartnerType::Undefined); // and generate phi kinematics->phi(sudakov->generatePhiDecay(particle,ids,kinematics,rho)); // and return it return Branching(kinematics, ids,sudakov,partnerType); } Branching SplittingGenerator:: chooseBackwardBranching(ShowerParticle &particle,PPtr , double enhance, Ptr::transient_const_pointer beam, ShowerInteraction type, tcPDFPtr pdf, Energy freeze) const { RhoDMatrix rho; bool rhoCalc(false); Energy newQ=ZERO; ShoKinPtr kinematics=ShoKinPtr(); ShowerPartnerType partnerType(ShowerPartnerType::Undefined); SudakovPtr sudakov; IdList ids; // First, find the eventual branching, corresponding to the highest scale. long index = abs(particle.id()); // if no possible branching return if(_bbranchings.find(index) == _bbranchings.end()) return Branching(ShoKinPtr(), IdList(),SudakovPtr(),ShowerPartnerType::Undefined); // otherwise select branching for(BranchingList::const_iterator cit = _bbranchings.lower_bound(index); cit != _bbranchings.upper_bound(index); ++cit ) { // check either right interaction or doing both if(!checkInteraction(type,cit->second.sudakov->interactionType())) continue; // setup the PDF cit->second.sudakov->setPDF(pdf,freeze); //calc rho as needed if(!rhoCalc) { rho = particle.extractRhoMatrix(false); rhoCalc = true; } // whether or not this interaction should be angular ordered bool angularOrdered = cit->second.sudakov->splittingFn()->angularOrdered(); ShoKinPtr newKin; IdList particles = particle.id()!=cit->first ? cit->second.conjugateParticles : cit->second.particles; ShowerPartnerType type; if(cit->second.sudakov->interactionType()==ShowerInteraction::QED) { type = ShowerPartnerType::QED; Energy startingScale = angularOrdered ? particle.scales().QED : particle.scales().QED_noAO; newKin=cit->second.sudakov-> generateNextSpaceBranching(startingScale,particles,particle.x(),rho,enhance,beam,_deTuning); } else if(cit->second.sudakov->interactionType()==ShowerInteraction::QCD) { // special for octets if(particle.dataPtr()->iColour()==PDT::Colour8) { // octet -> octet octet if(cit->second.sudakov->splittingFn()->colourStructure()==OctetOctetOctet) { type = ShowerPartnerType::QCDColourLine; Energy startingScale = angularOrdered ? particle.scales().QCD_c : particle.scales().QCD_c_noAO; newKin = cit->second.sudakov-> generateNextSpaceBranching(startingScale,particles, particle.x(),rho,0.5*enhance,beam,_deTuning); startingScale = angularOrdered ? particle.scales().QCD_ac : particle.scales().QCD_ac_noAO; ShoKinPtr newKin2 = cit->second.sudakov-> generateNextSpaceBranching(startingScale,particles, particle.x(),rho,0.5*enhance,beam,_deTuning); // pick the one with the highest scale if( (newKin&&newKin2&&newKin2->scale()>newKin->scale()) || (!newKin&&newKin2) ) { newKin = newKin2; type = ShowerPartnerType::QCDAntiColourLine; } } else { Energy startingScale = angularOrdered ? max(particle.scales().QCD_c , particle.scales().QCD_ac ) : max(particle.scales().QCD_c_noAO, particle.scales().QCD_ac_noAO); type = UseRandom::rndbool() ? ShowerPartnerType::QCDColourLine : ShowerPartnerType::QCDAntiColourLine; newKin=cit->second.sudakov-> generateNextSpaceBranching(startingScale,particles, particle.x(),rho,enhance,beam,_deTuning); } } // everything else else { Energy startingScale; if(particle.hasColour()) { type = ShowerPartnerType::QCDColourLine; startingScale = angularOrdered ? particle.scales().QCD_c : particle.scales().QCD_c_noAO; } else { type = ShowerPartnerType::QCDAntiColourLine; startingScale = angularOrdered ? particle.scales().QCD_ac : particle.scales().QCD_ac_noAO; } newKin=cit->second.sudakov-> generateNextSpaceBranching(startingScale,particles, particle.x(),rho,enhance,beam,_deTuning); } } // shouldn't be anything else else assert(false); // if no kinematics contine if(!newKin) continue; // select highest scale if(newKin->scale() > newQ) { newQ = newKin->scale(); kinematics=newKin; ids = particles; sudakov=cit->second.sudakov; partnerType = type; } } // return empty branching if nothing happened - if(!kinematics) return Branching(ShoKinPtr(), IdList(),SudakovPtr(), - ShowerPartnerType::Undefined); + if(!kinematics) { + if ( particle.spinInfo() ) particle.spinInfo()->undecay(); + return Branching(ShoKinPtr(), IdList(),SudakovPtr(), + ShowerPartnerType::Undefined); + } // initialize the ShowerKinematics // and generate phi kinematics->phi(sudakov->generatePhiBackward(particle,ids,kinematics,rho)); // return the answer return Branching(kinematics, ids,sudakov,partnerType); } void SplittingGenerator::rebind(const TranslationMap & trans) { BranchingList::iterator cit; for(cit=_fbranchings.begin();cit!=_fbranchings.end();++cit) { (cit->second).sudakov=trans.translate((cit->second).sudakov); for(unsigned int ix=0;ix<(cit->second).particles.size();++ix) { (cit->second).particles[ix]=trans.translate((cit->second).particles[ix]); } for(unsigned int ix=0;ix<(cit->second).conjugateParticles.size();++ix) { (cit->second).conjugateParticles[ix]=trans.translate((cit->second).conjugateParticles[ix]); } } for(cit=_bbranchings.begin();cit!=_bbranchings.end();++cit) { (cit->second).sudakov=trans.translate((cit->second).sudakov); for(unsigned int ix=0;ix<(cit->second).particles.size();++ix) { (cit->second).particles[ix]=trans.translate((cit->second).particles[ix]); } for(unsigned int ix=0;ix<(cit->second).conjugateParticles.size();++ix) { (cit->second).conjugateParticles[ix]=trans.translate((cit->second).conjugateParticles[ix]); } } Interfaced::rebind(trans); } IVector SplittingGenerator::getReferences() { IVector ret = Interfaced::getReferences(); BranchingList::iterator cit; for(cit=_fbranchings.begin();cit!=_fbranchings.end();++cit) { ret.push_back((cit->second).sudakov); for(unsigned int ix=0;ix<(cit->second).particles.size();++ix) ret.push_back(const_ptr_cast((cit->second).particles[ix])); for(unsigned int ix=0;ix<(cit->second).conjugateParticles.size();++ix) ret.push_back(const_ptr_cast((cit->second).conjugateParticles[ix])); } for(cit=_bbranchings.begin();cit!=_bbranchings.end();++cit) { ret.push_back((cit->second).sudakov); for(unsigned int ix=0;ix<(cit->second).particles.size();++ix) ret.push_back(const_ptr_cast((cit->second).particles[ix])); for(unsigned int ix=0;ix<(cit->second).conjugateParticles.size();++ix) ret.push_back(const_ptr_cast((cit->second).conjugateParticles[ix])); } return ret; } diff --git a/Shower/QTilde/SplittingFunctions/SudakovFormFactor.cc b/Shower/QTilde/SplittingFunctions/SudakovFormFactor.cc --- a/Shower/QTilde/SplittingFunctions/SudakovFormFactor.cc +++ b/Shower/QTilde/SplittingFunctions/SudakovFormFactor.cc @@ -1,1228 +1,1236 @@ // -*- C++ -*- // // SudakovFormFactor.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 SudakovFormFactor class. // #include "SudakovFormFactor.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "Herwig/Shower/QTilde/Kinematics/ShowerKinematics.h" #include "Herwig/Shower/QTilde/Base/ShowerParticle.h" #include "ThePEG/Utilities/DescribeClass.h" #include "Herwig/Shower/QTilde/QTildeShowerHandler.h" #include "Herwig/Shower/QTilde/Kinematics/FS_QTildeShowerKinematics1to2.h" #include "Herwig/Shower/QTilde/Kinematics/IS_QTildeShowerKinematics1to2.h" #include "Herwig/Shower/QTilde/Kinematics/Decay_QTildeShowerKinematics1to2.h" #include "Herwig/Shower/QTilde/Kinematics/KinematicHelpers.h" #include "SudakovCutOff.h" #include using std::array; using namespace Herwig; DescribeClass describeSudakovFormFactor ("Herwig::SudakovFormFactor",""); void SudakovFormFactor::persistentOutput(PersistentOStream & os) const { os << splittingFn_ << alpha_ << pdfmax_ << particles_ << pdffactor_ << cutoff_; } void SudakovFormFactor::persistentInput(PersistentIStream & is, int) { is >> splittingFn_ >> alpha_ >> pdfmax_ >> particles_ >> pdffactor_ >> cutoff_; } void SudakovFormFactor::Init() { static ClassDocumentation documentation ("The SudakovFormFactor class is the base class for the implementation of Sudakov" " form factors in Herwig"); static Reference interfaceSplittingFunction("SplittingFunction", "A reference to the SplittingFunction object", &Herwig::SudakovFormFactor::splittingFn_, false, false, true, false); static Reference interfaceAlpha("Alpha", "A reference to the Alpha object", &Herwig::SudakovFormFactor::alpha_, false, false, true, false); static Reference interfaceCutoff("Cutoff", "A reference to the SudakovCutOff object", &Herwig::SudakovFormFactor::cutoff_, false, false, true, false); static Parameter interfacePDFmax ("PDFmax", "Maximum value of PDF weight. ", &SudakovFormFactor::pdfmax_, 35.0, 1.0, 1000000.0, false, false, Interface::limited); static Switch interfacePDFFactor ("PDFFactor", "Include additional factors in the overestimate for the PDFs", &SudakovFormFactor::pdffactor_, 0, false, false); static SwitchOption interfacePDFFactorNo (interfacePDFFactor, "No", "Don't include any factors", 0); static SwitchOption interfacePDFFactorOverZ (interfacePDFFactor, "OverZ", "Include an additional factor of 1/z", 1); static SwitchOption interfacePDFFactorOverOneMinusZ (interfacePDFFactor, "OverOneMinusZ", "Include an additional factor of 1/(1-z)", 2); static SwitchOption interfacePDFFactorOverZOneMinusZ (interfacePDFFactor, "OverZOneMinusZ", "Include an additional factor of 1/z/(1-z)", 3); static SwitchOption interfacePDFFactorOverRootZ (interfacePDFFactor, "OverRootZ", "Include an additional factor of 1/sqrt(z)", 4); static SwitchOption interfacePDFFactorRootZ (interfacePDFFactor, "RootZ", "Include an additional factor of sqrt(z)", 5); } bool SudakovFormFactor::alphaSVeto(Energy2 pt2) const { double ratio=alphaSVetoRatio(pt2,1.); return UseRandom::rnd() > ratio; } double SudakovFormFactor::alphaSVetoRatio(Energy2 pt2, double factor) const { factor *= ShowerHandler::currentHandler()->renormalizationScaleFactor(); return alpha_->ratio(pt2, factor); } bool SudakovFormFactor::PDFVeto(const Energy2 t, const double x, const tcPDPtr parton0, const tcPDPtr parton1, Ptr::transient_const_pointer beam) const { double ratio=PDFVetoRatio(t,x,parton0,parton1,beam,1.); return UseRandom::rnd() > ratio; } double SudakovFormFactor::PDFVetoRatio(const Energy2 t, const double x, const tcPDPtr parton0, const tcPDPtr parton1, Ptr::transient_const_pointer beam,double factor) const { assert(pdf_); Energy2 theScale = t * sqr(ShowerHandler::currentHandler()->factorizationScaleFactor()*factor); if (theScale < sqr(freeze_)) theScale = sqr(freeze_); const double newpdf=pdf_->xfx(beam,parton0,theScale,x/z()); if(newpdf<=0.) return 0.; const double oldpdf=pdf_->xfx(beam,parton1,theScale,x); if(oldpdf<=0.) return 1.; const double ratio = newpdf/oldpdf; double maxpdf = pdfmax_; switch (pdffactor_) { case 0: break; case 1: maxpdf /= z(); break; case 2: maxpdf /= 1.-z(); break; case 3: maxpdf /= (z()*(1.-z())); break; case 4: maxpdf /= sqrt(z()); break; case 5: maxpdf *= sqrt(z()); break; default : throw Exception() << "SudakovFormFactor::PDFVetoRatio invalid PDFfactor = " << pdffactor_ << Exception::runerror; } if (ratio > maxpdf) { generator()->log() << "PDFVeto warning: Ratio > " << name() << ":PDFmax (by a factor of " << ratio/maxpdf <<") for " << parton0->PDGName() << " to " << parton1->PDGName() << "\n"; } return ratio/maxpdf ; } void SudakovFormFactor::addSplitting(const IdList & in) { bool add=true; for(unsigned int ix=0;ix::iterator it=particles_.begin(); it!=particles_.end();++it) { if(it->size()==in.size()) { bool match=true; for(unsigned int iy=0;iy::iterator itemp=it; --itemp; particles_.erase(it); it = itemp; } } } } Energy2 SudakovFormFactor::guesst(Energy2 t1,unsigned int iopt, const IdList &ids, double enhance,bool ident, double detune) const { unsigned int pdfopt = iopt!=1 ? 0 : pdffactor_; double c = 1./((splittingFn_->integOverP(zlimits_.second,ids,pdfopt) - splittingFn_->integOverP(zlimits_.first ,ids,pdfopt))* alpha_->overestimateValue()/Constants::twopi*enhance*detune); assert(iopt<=2); if(iopt==1) { c/=pdfmax_; //symmetry of FS gluon splitting if(ident) c*=0.5; } else if(iopt==2) c*=-1.; double r = UseRandom::rnd(); if(iopt!=2 || c*log(r)integOverP(zlimits_.first,ids,pdfopt); return splittingFn_->invIntegOverP (lower + UseRandom::rnd()*(splittingFn_->integOverP(zlimits_.second,ids,pdfopt) - lower),ids,pdfopt); } bool SudakovFormFactor::guessTimeLike(Energy2 &t,Energy2 tmin,double enhance, double detune) { Energy2 told = t; // calculate limits on z and if lower>upper return if(!computeTimeLikeLimits(t)) return false; // guess values of t and z t = guesst(told,0,ids_,enhance,ids_[1]==ids_[2],detune); z_ = guessz(0,ids_); // actual values for z-limits if(!computeTimeLikeLimits(t)) return false; if(tupper return if(!computeSpaceLikeLimits(t,x)) return false; // guess values of t and z t = guesst(told,1,ids_,enhance,ids_[1]==ids_[2],detune); z_ = guessz(1,ids_); // actual values for z-limits if(!computeSpaceLikeLimits(t,x)) return false; if(t zlimits_.second) return true; Energy2 m02 = (ids_[0]->id()!=ParticleID::g && ids_[0]->id()!=ParticleID::gamma) ? masssquared_[0] : Energy2(); Energy2 pt2 = QTildeKinematics::pT2_FSR(t,z(),m02,masssquared_[1],masssquared_[2]); // if pt2<0 veto if (pt2pT2min()) return true; // otherwise calculate pt and return pT_ = sqrt(pt2); return false; } ShoKinPtr SudakovFormFactor::generateNextTimeBranching(const Energy startingScale, const IdList &ids, const RhoDMatrix & rho, double enhance, double detuning) { // First reset the internal kinematics variables that can // have been eventually set in the previous call to the method. q_ = ZERO; z_ = 0.; phi_ = 0.; // perform initialization Energy2 tmax(sqr(startingScale)),tmin; initialize(ids,tmin); // check max > min if(tmax<=tmin) return ShoKinPtr(); // calculate next value of t using veto algorithm Energy2 t(tmax); // no shower variations to calculate if(ShowerHandler::currentHandler()->showerVariations().empty()){ // Without variations do the usual Veto algorithm // No need for more if-statements in this loop. do { if(!guessTimeLike(t,tmin,enhance,detuning)) break; } while(PSVeto(t) || SplittingFnVeto(z()*(1.-z())*t,ids,true,rho,detuning) || alphaSVeto(splittingFn()->pTScale() ? sqr(z()*(1.-z()))*t : z()*(1.-z())*t)); } else { bool alphaRew(true),PSRew(true),SplitRew(true); do { if(!guessTimeLike(t,tmin,enhance,detuning)) break; PSRew=PSVeto(t); if (PSRew) continue; SplitRew=SplittingFnVeto(z()*(1.-z())*t,ids,true,rho,detuning); alphaRew=alphaSVeto(splittingFn()->pTScale() ? sqr(z()*(1.-z()))*t : z()*(1.-z())*t); double factor=alphaSVetoRatio(splittingFn()->pTScale() ? sqr(z()*(1.-z()))*t : z()*(1.-z())*t,1.)* SplittingFnVetoRatio(z()*(1.-z())*t,ids,true,rho,detuning); tShowerHandlerPtr ch = ShowerHandler::currentHandler(); if( !(SplitRew || alphaRew) ) { //Emission q_ = t > ZERO ? Energy(sqrt(t)) : -1.*MeV; if (q_ <= ZERO) break; } for ( map::const_iterator var = ch->showerVariations().begin(); var != ch->showerVariations().end(); ++var ) { if ( ( ch->firstInteraction() && var->second.firstInteraction ) || ( !ch->firstInteraction() && var->second.secondaryInteractions ) ) { double newfactor = alphaSVetoRatio(splittingFn()->pTScale() ? sqr(z()*(1.-z()))*t : z()*(1.-z())*t,var->second.renormalizationScaleFactor) * SplittingFnVetoRatio(z()*(1.-z())*t,ids,true,rho,detuning); double varied; if ( SplitRew || alphaRew ) { // No Emission varied = (1. - newfactor) / (1. - factor); } else { // Emission varied = newfactor / factor; } map::iterator wi = ch->currentWeights().find(var->first); if ( wi != ch->currentWeights().end() ) wi->second *= varied; else { assert(false); //ch->currentWeights()[var->first] = varied; } } } } while(PSRew || SplitRew || alphaRew); } q_ = t > ZERO ? Energy(sqrt(t)) : -1.*MeV; if(q_ < ZERO) return ShoKinPtr(); // return the ShowerKinematics object return new_ptr(FS_QTildeShowerKinematics1to2(q_,z(),phi(),pT(),this)); } ShoKinPtr SudakovFormFactor:: generateNextSpaceBranching(const Energy startingQ, const IdList &ids, double x, const RhoDMatrix & rho, double enhance, Ptr::transient_const_pointer beam, double detuning) { // First reset the internal kinematics variables that can // have been eventually set in the previous call to the method. q_ = ZERO; z_ = 0.; phi_ = 0.; // perform the initialization Energy2 tmax(sqr(startingQ)),tmin; initialize(ids,tmin); // check max > min if(tmax<=tmin) return ShoKinPtr(); // calculate next value of t using veto algorithm Energy2 t(tmax),pt2(ZERO); // no shower variations if(ShowerHandler::currentHandler()->showerVariations().empty()){ // Without variations do the usual Veto algorithm // No need for more if-statements in this loop. do { if(!guessSpaceLike(t,tmin,x,enhance,detuning)) break; pt2 = QTildeKinematics::pT2_ISR(t,z(),masssquared_[2]); } while(pt2 < cutoff_->pT2min()|| z() > zlimits_.second|| SplittingFnVeto((1.-z())*t/z(),ids,false,rho,detuning)|| alphaSVeto(splittingFn()->pTScale() ? sqr(1.-z())*t : (1.-z())*t)|| PDFVeto(t,x,ids[0],ids[1],beam)); } // shower variations else { bool alphaRew(true),PDFRew(true),ptRew(true),zRew(true),SplitRew(true); do { if(!guessSpaceLike(t,tmin,x,enhance,detuning)) break; pt2 = QTildeKinematics::pT2_ISR(t,z(),masssquared_[2]); ptRew=pt2 < cutoff_->pT2min(); zRew=z() > zlimits_.second; if (ptRew||zRew) continue; SplitRew=SplittingFnVeto((1.-z())*t/z(),ids,false,rho,detuning); alphaRew=alphaSVeto(splittingFn()->pTScale() ? sqr(1.-z())*t : (1.-z())*t); PDFRew=PDFVeto(t,x,ids[0],ids[1],beam); double factor=PDFVetoRatio(t,x,ids[0],ids[1],beam,1.)* alphaSVetoRatio(splittingFn()->pTScale() ? sqr(1.-z())*t : (1.-z())*t,1.)* SplittingFnVetoRatio((1.-z())*t/z(),ids,false,rho,detuning); tShowerHandlerPtr ch = ShowerHandler::currentHandler(); if( !(PDFRew || SplitRew || alphaRew) ) { //Emission q_ = t > ZERO ? Energy(sqrt(t)) : -1.*MeV; if (q_ <= ZERO) break; } for ( map::const_iterator var = ch->showerVariations().begin(); var != ch->showerVariations().end(); ++var ) { if ( ( ch->firstInteraction() && var->second.firstInteraction ) || ( !ch->firstInteraction() && var->second.secondaryInteractions ) ) { double newfactor = PDFVetoRatio(t,x,ids[0],ids[1],beam,var->second.factorizationScaleFactor)* alphaSVetoRatio(splittingFn()->pTScale() ? sqr(1.-z())*t : (1.-z())*t,var->second.renormalizationScaleFactor) *SplittingFnVetoRatio((1.-z())*t/z(),ids,false,rho,detuning); double varied; if( PDFRew || SplitRew || alphaRew) { // No Emission varied = (1. - newfactor) / (1. - factor); } else { // Emission varied = newfactor / factor; } map::iterator wi = ch->currentWeights().find(var->first); if ( wi != ch->currentWeights().end() ) wi->second *= varied; else { assert(false); //ch->currentWeights()[var->first] = varied; } } } } while( PDFRew || SplitRew || alphaRew); } if(t > ZERO && zlimits_.first < zlimits_.second) q_ = sqrt(t); else return ShoKinPtr(); pT_ = sqrt(pt2); // create the ShowerKinematics and return it return new_ptr(IS_QTildeShowerKinematics1to2(q_,z(),phi(),pT(),this)); } void SudakovFormFactor::initialize(const IdList & ids, Energy2 & tmin) { ids_=ids; tmin = 4.*cutoff_->pT2min(); masses_ = cutoff_->virtualMasses(ids); masssquared_.clear(); for(unsigned int ix=0;ix0) tmin=max(masssquared_[ix],tmin); } } ShoKinPtr SudakovFormFactor::generateNextDecayBranching(const Energy startingScale, const Energy stoppingScale, const Energy minmass, const IdList &ids, const RhoDMatrix & rho, double enhance, double detuning) { // First reset the internal kinematics variables that can // have been eventually set in the previous call to this method. q_ = Constants::MaxEnergy; z_ = 0.; phi_ = 0.; // perform initialisation Energy2 tmax(sqr(stoppingScale)),tmin; initialize(ids,tmin); tmin=sqr(startingScale); // check some branching possible if(tmax<=tmin) return ShoKinPtr(); // perform the evolution Energy2 t(tmin),pt2(-MeV2); do { if(!guessDecay(t,tmax,minmass,enhance,detuning)) break; pt2 = QTildeKinematics::pT2_Decay(t,z(),masssquared_[0],masssquared_[2]); } while(SplittingFnVeto((1.-z())*t/z(),ids,true,rho,detuning)|| alphaSVeto(splittingFn()->pTScale() ? sqr(1.-z())*t : (1.-z())*t ) || pt2pT2min() || t*(1.-z())>masssquared_[0]-sqr(minmass)); if(t > ZERO) { q_ = sqrt(t); pT_ = sqrt(pt2); } else return ShoKinPtr(); phi_ = 0.; // create the ShowerKinematics object return new_ptr(Decay_QTildeShowerKinematics1to2(q_,z(),phi(),pT(),this)); } bool SudakovFormFactor::guessDecay(Energy2 &t,Energy2 tmax, Energy minmass, double enhance, double detune) { // previous scale Energy2 told = t; // overestimated limits on z if(tmaxpT2min()+ 0.25*sqr(masssquared_[2])/tm2)/tm +0.5*masssquared_[2]/tm2); if(zlimits_.secondpT2min()+ 0.25*sqr(masssquared_[2])/tm2)/tm +0.5*masssquared_[2]/tm2); if(t>tmax||zlimits_.secondpT2min(); // special case for gluon radiating if(ids_[0]->id()==ParticleID::g||ids_[0]->id()==ParticleID::gamma) { // no emission possible if(t<16.*(masssquared_[1]+pT2min)) { t=-1.*GeV2; return false; } // overestimate of the limits zlimits_.first = 0.5*(1.-sqrt(1.-4.*sqrt((masssquared_[1]+pT2min)/t))); zlimits_.second = 1.-zlimits_.first; } // special case for radiated particle is gluon else if(ids_[2]->id()==ParticleID::g||ids_[2]->id()==ParticleID::gamma) { zlimits_.first = sqrt((masssquared_[1]+pT2min)/t); zlimits_.second = 1.-sqrt((masssquared_[2]+pT2min)/t); } else if(ids_[1]->id()==ParticleID::g||ids_[1]->id()==ParticleID::gamma) { zlimits_.second = sqrt((masssquared_[2]+pT2min)/t); zlimits_.first = 1.-sqrt((masssquared_[1]+pT2min)/t); } else { zlimits_.first = (masssquared_[1]+pT2min)/t; zlimits_.second = 1.-(masssquared_[2]+pT2min)/t; } if(zlimits_.first>=zlimits_.second) { t=-1.*GeV2; return false; } return true; } bool SudakovFormFactor::computeSpaceLikeLimits(Energy2 & t, double x) { if (t < 1e-20 * GeV2) { t=-1.*GeV2; return false; } // compute the limits zlimits_.first = x; double yy = 1.+0.5*masssquared_[2]/t; zlimits_.second = yy - sqrt(sqr(yy)-1.+cutoff_->pT2min()/t); // return false if lower>upper if(zlimits_.second(particle.parents()[0]) : tShowerParticlePtr(); } else { mother = particle.children().size()==2 ? dynamic_ptr_cast(&particle) : tShowerParticlePtr(); } tShowerParticlePtr partner; while(mother) { tPPtr otherChild; if(forward) { for (unsigned int ix=0;ixchildren().size();++ix) { if(mother->children()[ix]!=child) { otherChild = mother->children()[ix]; break; } } } else { otherChild = mother->children()[1]; } tShowerParticlePtr other = dynamic_ptr_cast(otherChild); if((inter==ShowerInteraction::QCD && otherChild->dataPtr()->coloured()) || (inter==ShowerInteraction::QED && otherChild->dataPtr()->charged())) { partner = other; break; } if(forward && !other->isFinalState()) { partner = dynamic_ptr_cast(mother); break; } child = mother; if(forward) { mother = ! mother->parents().empty() ? dynamic_ptr_cast(mother->parents()[0]) : tShowerParticlePtr(); } else { if(mother->children()[0]->children().size()!=2) break; tShowerParticlePtr mtemp = dynamic_ptr_cast(mother->children()[0]); if(!mtemp) break; else mother=mtemp; } } if(!partner) { if(forward) { partner = dynamic_ptr_cast( child)->partner(); } else { if(mother) { tShowerParticlePtr parent; if(!mother->children().empty()) { parent = dynamic_ptr_cast(mother->children()[0]); } if(!parent) { parent = dynamic_ptr_cast(mother); } partner = parent->partner(); } else { partner = dynamic_ptr_cast(&particle)->partner(); } } } return partner; } pair softPhiMin(double phi0, double phi1, double A, double B, double C, double D) { double c01 = cos(phi0 - phi1); double s01 = sin(phi0 - phi1); double s012(sqr(s01)), c012(sqr(c01)); double A2(A*A), B2(B*B), C2(C*C), D2(D*D); if(abs(B/A)<1e-10 && abs(D/C)<1e-10) return make_pair(phi0,phi0+Constants::pi); double root = sqr(B2)*C2*D2*sqr(s012) + 2.*A*B2*B*C2*C*D*c01*s012 + 2.*A*B2*B*C*D2*D*c01*s012 + 4.*A2*B2*C2*D2*c012 - A2*B2*C2*D2*s012 - A2*B2*sqr(D2)*s012 - sqr(B2)*sqr(C2)*s012 - sqr(B2)*C2*D2*s012 - 4.*A2*A*B*C*D2*D*c01 - 4.*A*B2*B*C2*C*D*c01 + sqr(A2)*sqr(D2) + 2.*A2*B2*C2*D2 + sqr(B2)*sqr(C2); if(root<0.) return make_pair(phi0,phi0+Constants::pi); root = sqrt(root); double denom = (-2.*A*B*C*D*c01 + A2*D2 + B2*C2); double denom2 = (-B*C*c01 + A*D); - if(denom==ZERO || denom2==0) - return make_pair(phi0,phi0+Constants::pi); + double num = B2*C*D*s012; - return make_pair(atan2(B*s01*(-C*(num + root) / denom + D) / denom2, -(num + root ) / denom) + phi0, - atan2(B*s01*(-C*(num - root) / denom + D) / denom2, -(num - root ) / denom) + phi0); + double y1 = B*s01*(-C*(num + root) + D*denom) / denom2; + double y2 = B*s01*(-C*(num - root) + D*denom) / denom2; + double x1 = -(num + root ); + double x2 = -(num - root ); + if(denom<0.) { + y1*=-1.; + y2*=-1.; + x1*=-1.; + x2*=-1.; + } + return make_pair(atan2(y1,x1) + phi0,atan2(y2,x2) + phi0); } } double SudakovFormFactor::generatePhiForward(ShowerParticle & particle, const IdList & ids, ShoKinPtr kinematics, const RhoDMatrix & rho) { // no correlations, return flat phi if(! dynamic_ptr_cast(ShowerHandler::currentHandler())->correlations()) return Constants::twopi*UseRandom::rnd(); // get the kinematic variables double z = kinematics->z(); Energy2 t = z*(1.-z)*sqr(kinematics->scale()); Energy pT = kinematics->pT(); // if soft correlations Energy2 pipj,pik; bool canBeSoft[2] = {ids[1]->id()==ParticleID::g || ids[1]->id()==ParticleID::gamma, ids[2]->id()==ParticleID::g || ids[2]->id()==ParticleID::gamma }; array pjk; array Ek; Energy Ei,Ej; Energy2 m12(ZERO),m22(ZERO); InvEnergy2 aziMax(ZERO); bool softAllowed = dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()&& (canBeSoft[0] || canBeSoft[1]); if(softAllowed) { // find the partner for the soft correlations tShowerParticlePtr partner=findCorrelationPartner(particle,true,splittingFn()->interactionType()); // remember we want the softer gluon bool swapOrder = !canBeSoft[1] || (canBeSoft[0] && canBeSoft[1] && z < 0.5); double zFact = !swapOrder ? (1.-z) : z; // compute the transforms to the shower reference frame // first the boost Lorentz5Momentum pVect = particle.showerBasis()->pVector(); Lorentz5Momentum nVect = particle.showerBasis()->nVector(); Boost beta_bb; if(particle.showerBasis()->frame()==ShowerBasis::BackToBack) { beta_bb = -(pVect + nVect).boostVector(); } else if(particle.showerBasis()->frame()==ShowerBasis::Rest) { beta_bb = -pVect.boostVector(); } else assert(false); pVect.boost(beta_bb); nVect.boost(beta_bb); Axis axis; if(particle.showerBasis()->frame()==ShowerBasis::BackToBack) { axis = pVect.vect().unit(); } else if(particle.showerBasis()->frame()==ShowerBasis::Rest) { axis = nVect.vect().unit(); } else assert(false); // and then the rotation LorentzRotation rot; if(axis.perp2()>0.) { double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); rot.rotate(acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); } else if(axis.z()<0.) { rot.rotate(Constants::pi,Axis(1.,0.,0.)); } rot.invert(); pVect *= rot; nVect *= rot; // shower parameters Energy2 pn = pVect*nVect, m2 = pVect.m2(); double alpha0 = particle.showerParameters().alpha; double beta0 = 0.5/alpha0/pn* (sqr(particle.dataPtr()->mass())-sqr(alpha0)*m2+sqr(particle.showerParameters().pt)); Lorentz5Momentum qperp0(particle.showerParameters().ptx, particle.showerParameters().pty,ZERO,ZERO); assert(partner); Lorentz5Momentum pj = partner->momentum(); pj.boost(beta_bb); pj *= rot; // compute the two phi independent dot products pik = 0.5*zFact*(sqr(alpha0)*m2 - sqr(particle.showerParameters().pt) + 2.*alpha0*beta0*pn ) +0.5*sqr(pT)/zFact; Energy2 dot1 = pj*pVect; Energy2 dot2 = pj*nVect; Energy2 dot3 = pj*qperp0; pipj = alpha0*dot1+beta0*dot2+dot3; // compute the constants for the phi dependent dot product pjk[0] = zFact*(alpha0*dot1+dot3-0.5*dot2/pn*(alpha0*m2-sqr(particle.showerParameters().pt)/alpha0)) +0.5*sqr(pT)*dot2/pn/zFact/alpha0; pjk[1] = (pj.x() - dot2/alpha0/pn*qperp0.x())*pT; pjk[2] = (pj.y() - dot2/alpha0/pn*qperp0.y())*pT; m12 = sqr(particle.dataPtr()->mass()); m22 = sqr(partner->dataPtr()->mass()); if(swapOrder) { pjk[1] *= -1.; pjk[2] *= -1.; } Ek[0] = zFact*(alpha0*pVect.t()-0.5*nVect.t()/pn*(alpha0*m2-sqr(particle.showerParameters().pt)/alpha0)) +0.5*sqr(pT)*nVect.t()/pn/zFact/alpha0; Ek[1] = -nVect.t()/alpha0/pn*qperp0.x()*pT; Ek[2] = -nVect.t()/alpha0/pn*qperp0.y()*pT; if(swapOrder) { Ek[1] *= -1.; Ek[2] *= -1.; } Energy mag2=sqrt(sqr(Ek[1])+sqr(Ek[2])); Ei = alpha0*pVect.t()+beta0*nVect.t(); Ej = pj.t(); double phi0 = atan2(-pjk[2],-pjk[1]); if(phi0<0.) phi0 += Constants::twopi; double phi1 = atan2(-Ek[2],-Ek[1]); if(phi1<0.) phi1 += Constants::twopi; double xi_min = pik/Ei/(Ek[0]+mag2), xi_max = pik/Ei/(Ek[0]-mag2), xi_ij = pipj/Ei/Ej; if(xi_min>xi_max) swap(xi_min,xi_max); if(xi_min>xi_ij) softAllowed = false; Energy2 mag = sqrt(sqr(pjk[1])+sqr(pjk[2])); if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==1) { aziMax = -m12/sqr(pik) -m22/sqr(pjk[0]+mag) +2.*pipj/pik/(pjk[0]-mag); } else if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==2) { double A = (pipj*Ek[0]- Ej*pik)/Ej/sqr(Ej); double B = -sqrt(sqr(pipj)*(sqr(Ek[1])+sqr(Ek[2])))/Ej/sqr(Ej); double C = pjk[0]/sqr(Ej); double D = -sqrt(sqr(pjk[1])+sqr(pjk[2]))/sqr(Ej); pair minima = softPhiMin(phi0,phi1,A,B,C,D); aziMax = 0.5/pik/(Ek[0]-mag2)*(Ei-m12*(Ek[0]-mag2)/pik + max(Ej*(A+B*cos(minima.first -phi1))/(C+D*cos(minima.first -phi0)), Ej*(A+B*cos(minima.second-phi1))/(C+D*cos(minima.second-phi0)))); } else assert(false); } // if spin correlations vector > wgts; if(dynamic_ptr_cast(ShowerHandler::currentHandler())->spinCorrelations()) { // calculate the weights wgts = splittingFn()->generatePhiForward(z,t,ids,rho); } else { - wgts = vector >(1,make_pair(0,1.)); + wgts = {{ {0, 1.} }}; } // generate the azimuthal angle double phi,wgt; static const Complex ii(0.,1.); unsigned int ntry(0); double phiMax(0.),wgtMax(0.); do { phi = Constants::twopi*UseRandom::rnd(); // first the spin correlations bit (gives 1 if correlations off) Complex spinWgt = 0.; for(unsigned int ix=0;ix1e-10) { generator()->log() << "Forward spin weight problem " << wgt << " " << wgt-1. << " " << ids[0]->id() << " " << ids[1]->id() << " " << ids[2]->id() << " " << " " << phi << "\n"; generator()->log() << "Weights \n"; for(unsigned int ix=0;ixlog() << wgts[ix].first << " " << wgts[ix].second << "\n"; } // soft correlations bit double aziWgt = 1.; if(softAllowed) { Energy2 dot = pjk[0]+pjk[1]*cos(phi)+pjk[2]*sin(phi); Energy Eg = Ek[0]+Ek[1]*cos(phi)+Ek[2]*sin(phi); if(pipj*Eg>pik*Ej) { if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==1) { aziWgt = (-m12/sqr(pik) -m22/sqr(dot) +2.*pipj/pik/dot)/aziMax; } else if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==2) { aziWgt = max(ZERO,0.5/pik/Eg*(Ei-m12*Eg/pik + (pipj*Eg - Ej*pik)/dot)/aziMax); } if(aziWgt-1.>1e-10||aziWgt<-1e-10) { generator()->log() << "Forward soft weight problem " << aziWgt << " " << aziWgt-1. << " " << ids[0]->id() << " " << ids[1]->id() << " " << ids[2]->id() << " " << " " << phi << "\n"; } } else { aziWgt = 0.; } } wgt *= aziWgt; if(wgt>wgtMax) { phiMax = phi; wgtMax = wgt; } ++ntry; } while(wgtlog() << "Too many tries to generate phi in forward evolution\n"; phi = phiMax; } // return the azimuthal angle return phi; } double SudakovFormFactor::generatePhiBackward(ShowerParticle & particle, const IdList & ids, ShoKinPtr kinematics, const RhoDMatrix & rho) { // no correlations, return flat phi if(! dynamic_ptr_cast(ShowerHandler::currentHandler())->correlations()) return Constants::twopi*UseRandom::rnd(); // get the kinematic variables double z = kinematics->z(); Energy2 t = (1.-z)*sqr(kinematics->scale())/z; Energy pT = kinematics->pT(); // if soft correlations bool softAllowed = dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations() && (ids[2]->id()==ParticleID::g || ids[2]->id()==ParticleID::gamma); Energy2 pipj,pik,m12(ZERO),m22(ZERO); array pjk; Energy Ei,Ej,Ek; InvEnergy2 aziMax(ZERO); if(softAllowed) { // find the partner for the soft correlations tShowerParticlePtr partner=findCorrelationPartner(particle,false,splittingFn()->interactionType()); double zFact = (1.-z); // compute the transforms to the shower reference frame // first the boost Lorentz5Momentum pVect = particle.showerBasis()->pVector(); Lorentz5Momentum nVect = particle.showerBasis()->nVector(); assert(particle.showerBasis()->frame()==ShowerBasis::BackToBack); Boost beta_bb = -(pVect + nVect).boostVector(); pVect.boost(beta_bb); nVect.boost(beta_bb); Axis axis = pVect.vect().unit(); // and then the rotation LorentzRotation rot; if(axis.perp2()>0.) { double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); rot.rotate(acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); } else if(axis.z()<0.) { rot.rotate(Constants::pi,Axis(1.,0.,0.)); } rot.invert(); pVect *= rot; nVect *= rot; // shower parameters Energy2 pn = pVect*nVect; Energy2 m2 = pVect.m2(); double alpha0 = particle.x(); double beta0 = -0.5/alpha0/pn*sqr(alpha0)*m2; Lorentz5Momentum pj = partner->momentum(); pj.boost(beta_bb); pj *= rot; double beta2 = 0.5*(1.-zFact)*(sqr(alpha0*zFact/(1.-zFact))*m2+sqr(pT))/alpha0/zFact/pn; // compute the two phi independent dot products Energy2 dot1 = pj*pVect; Energy2 dot2 = pj*nVect; pipj = alpha0*dot1+beta0*dot2; pik = alpha0*(alpha0*zFact/(1.-zFact)*m2+pn*(beta2+zFact/(1.-zFact)*beta0)); // compute the constants for the phi dependent dot product pjk[0] = alpha0*zFact/(1.-zFact)*dot1+beta2*dot2; pjk[1] = pj.x()*pT; pjk[2] = pj.y()*pT; m12 = ZERO; m22 = sqr(partner->dataPtr()->mass()); Energy2 mag = sqrt(sqr(pjk[1])+sqr(pjk[2])); if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==1) { aziMax = -m12/sqr(pik) -m22/sqr(pjk[0]+mag) +2.*pipj/pik/(pjk[0]-mag); } else if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==2) { Ek = alpha0*zFact/(1.-zFact)*pVect.t()+beta2*nVect.t(); Ei = alpha0*pVect.t()+beta0*nVect.t(); Ej = pj.t(); if(pipj*Ek> Ej*pik) { aziMax = 0.5/pik/Ek*(Ei-m12*Ek/pik + (pipj*Ek- Ej*pik)/(pjk[0]-mag)); } else { aziMax = 0.5/pik/Ek*(Ei-m12*Ek/pik); } } else { assert(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==0); } } // if spin correlations vector > wgts; if(dynamic_ptr_cast(ShowerHandler::currentHandler())->spinCorrelations()) { // get the weights wgts = splittingFn()->generatePhiBackward(z,t,ids,rho); } else { - wgts = vector >(1,make_pair(0,1.)); + wgts = {{ {0, 1.} }}; } // generate the azimuthal angle double phi,wgt; static const Complex ii(0.,1.); unsigned int ntry(0); double phiMax(0.),wgtMax(0.); do { phi = Constants::twopi*UseRandom::rnd(); Complex spinWgt = 0.; for(unsigned int ix=0;ix1e-10) { generator()->log() << "Backward weight problem " << wgt << " " << wgt-1. << " " << ids[0]->id() << " " << ids[1]->id() << " " << ids[2]->id() << " " << " " << z << " " << phi << "\n"; generator()->log() << "Weights \n"; for(unsigned int ix=0;ixlog() << wgts[ix].first << " " << wgts[ix].second << "\n"; } // soft correlations bit double aziWgt = 1.; if(softAllowed) { Energy2 dot = pjk[0]+pjk[1]*cos(phi)+pjk[2]*sin(phi); if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==1) { aziWgt = (-m12/sqr(pik) -m22/sqr(dot) +2.*pipj/pik/dot)/aziMax; } else if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==2) { aziWgt = max(ZERO,0.5/pik/Ek*(Ei-m12*Ek/pik + pipj*Ek/dot - Ej*pik/dot)/aziMax); } if(aziWgt-1.>1e-10||aziWgt<-1e-10) { generator()->log() << "Backward soft weight problem " << aziWgt << " " << aziWgt-1. << " " << ids[0]->id() << " " << ids[1]->id() << " " << ids[2]->id() << " " << " " << phi << "\n"; } } wgt *= aziWgt; if(wgt>wgtMax) { phiMax = phi; wgtMax = wgt; } ++ntry; } while(wgtlog() << "Too many tries to generate phi in backward evolution\n"; phi = phiMax; } // return the azimuthal angle return phi; } double SudakovFormFactor::generatePhiDecay(ShowerParticle & particle, const IdList & ids, ShoKinPtr kinematics, const RhoDMatrix &) { // only soft correlations in this case // no correlations, return flat phi if( !(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations() && (ids[2]->id()==ParticleID::g || ids[2]->id()==ParticleID::gamma ))) return Constants::twopi*UseRandom::rnd(); // get the kinematic variables double z = kinematics->z(); Energy pT = kinematics->pT(); // if soft correlations // find the partner for the soft correlations tShowerParticlePtr partner = findCorrelationPartner(particle,true,splittingFn()->interactionType()); double zFact(1.-z); // compute the transforms to the shower reference frame // first the boost Lorentz5Momentum pVect = particle.showerBasis()->pVector(); Lorentz5Momentum nVect = particle.showerBasis()->nVector(); assert(particle.showerBasis()->frame()==ShowerBasis::Rest); Boost beta_bb = -pVect.boostVector(); pVect.boost(beta_bb); nVect.boost(beta_bb); Axis axis = nVect.vect().unit(); // and then the rotation LorentzRotation rot; if(axis.perp2()>0.) { double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); rot.rotate(acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); } else if(axis.z()<0.) { rot.rotate(Constants::pi,Axis(1.,0.,0.)); } rot.invert(); pVect *= rot; nVect *= rot; // shower parameters Energy2 pn = pVect*nVect; Energy2 m2 = pVect.m2(); double alpha0 = particle.showerParameters().alpha; double beta0 = 0.5/alpha0/pn* (sqr(particle.dataPtr()->mass())-sqr(alpha0)*m2+sqr(particle.showerParameters().pt)); Lorentz5Momentum qperp0(particle.showerParameters().ptx, particle.showerParameters().pty,ZERO,ZERO); Lorentz5Momentum pj = partner->momentum(); pj.boost(beta_bb); pj *= rot; // compute the two phi independent dot products Energy2 pik = 0.5*zFact*(sqr(alpha0)*m2 - sqr(particle.showerParameters().pt) + 2.*alpha0*beta0*pn ) +0.5*sqr(pT)/zFact; Energy2 dot1 = pj*pVect; Energy2 dot2 = pj*nVect; Energy2 dot3 = pj*qperp0; Energy2 pipj = alpha0*dot1+beta0*dot2+dot3; // compute the constants for the phi dependent dot product array pjk; pjk[0] = zFact*(alpha0*dot1+dot3-0.5*dot2/pn*(alpha0*m2-sqr(particle.showerParameters().pt)/alpha0)) +0.5*sqr(pT)*dot2/pn/zFact/alpha0; pjk[1] = (pj.x() - dot2/alpha0/pn*qperp0.x())*pT; pjk[2] = (pj.y() - dot2/alpha0/pn*qperp0.y())*pT; Energy2 m12 = sqr(particle.dataPtr()->mass()); Energy2 m22 = sqr(partner->dataPtr()->mass()); Energy2 mag = sqrt(sqr(pjk[1])+sqr(pjk[2])); InvEnergy2 aziMax; array Ek; Energy Ei,Ej; if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==1) { aziMax = -m12/sqr(pik) -m22/sqr(pjk[0]+mag) +2.*pipj/pik/(pjk[0]-mag); } else if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==2) { Ek[0] = zFact*(alpha0*pVect.t()+-0.5*nVect.t()/pn*(alpha0*m2-sqr(particle.showerParameters().pt)/alpha0)) +0.5*sqr(pT)*nVect.t()/pn/zFact/alpha0; Ek[1] = -nVect.t()/alpha0/pn*qperp0.x()*pT; Ek[2] = -nVect.t()/alpha0/pn*qperp0.y()*pT; Energy mag2=sqrt(sqr(Ek[1])+sqr(Ek[2])); Ei = alpha0*pVect.t()+beta0*nVect.t(); Ej = pj.t(); aziMax = 0.5/pik/(Ek[0]-mag2)*(Ei-m12*(Ek[0]-mag2)/pik + pipj*(Ek[0]+mag2)/(pjk[0]-mag) - Ej*pik/(pjk[0]-mag) ); } else assert(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==0); // generate the azimuthal angle double phi,wgt(0.); unsigned int ntry(0); double phiMax(0.),wgtMax(0.); do { phi = Constants::twopi*UseRandom::rnd(); Energy2 dot = pjk[0]+pjk[1]*cos(phi)+pjk[2]*sin(phi); if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==1) { wgt = (-m12/sqr(pik) -m22/sqr(dot) +2.*pipj/pik/dot)/aziMax; } else if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==2) { if(qperp0.m2()==ZERO) { wgt = 1.; } else { Energy Eg = Ek[0]+Ek[1]*cos(phi)+Ek[2]*sin(phi); wgt = max(ZERO,0.5/pik/Eg*(Ei-m12*Eg/pik + (pipj*Eg - Ej*pik)/dot)/aziMax); } } if(wgt-1.>1e-10||wgt<-1e-10) { generator()->log() << "Decay soft weight problem " << wgt << " " << wgt-1. << " " << ids[0]->id() << " " << ids[1]->id() << " " << ids[2]->id() << " " << " " << phi << "\n"; } if(wgt>wgtMax) { phiMax = phi; wgtMax = wgt; } ++ntry; } while(wgtlog() << "Too many tries to generate phi\n"; } // return the azimuthal angle return phi; } Energy SudakovFormFactor::calculateScale(double zin, Energy pt, IdList ids, unsigned int iopt) { Energy2 tmin; initialize(ids,tmin); // final-state branching if(iopt==0) { Energy2 scale=(sqr(pt)+masssquared_[1]*(1.-zin)+masssquared_[2]*zin); if(ids[0]->id()!=ParticleID::g) scale -= zin*(1.-zin)*masssquared_[0]; scale /= sqr(zin*(1-zin)); return scale<=ZERO ? sqrt(tmin) : sqrt(scale); } else if(iopt==1) { Energy2 scale=(sqr(pt)+zin*masssquared_[2])/sqr(1.-zin); return scale<=ZERO ? sqrt(tmin) : sqrt(scale); } else if(iopt==2) { Energy2 scale = (sqr(pt)+zin*masssquared_[2])/sqr(1.-zin)+masssquared_[0]; return scale<=ZERO ? sqrt(tmin) : sqrt(scale); } else { throw Exception() << "Unknown option in SudakovFormFactor::calculateScale() " << "iopt = " << iopt << Exception::runerror; } } diff --git a/Shower/QTilde/SplittingFunctions/ZeroZeroOneSplitFn.cc b/Shower/QTilde/SplittingFunctions/ZeroZeroOneSplitFn.cc --- a/Shower/QTilde/SplittingFunctions/ZeroZeroOneSplitFn.cc +++ b/Shower/QTilde/SplittingFunctions/ZeroZeroOneSplitFn.cc @@ -1,118 +1,118 @@ // -*- C++ -*- // // PhitoPhiGSplitFn.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 ZeroZeroOneSplitFn class. // #include "ZeroZeroOneSplitFn.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "Herwig/Decay/TwoBodyDecayMatrixElement.h" using namespace Herwig; DescribeNoPIOClass describeZeroZeroOneSplitFn ("Herwig::ZeroZeroOneSplitFn","HwShower.so"); void ZeroZeroOneSplitFn::Init() { static ClassDocumentation documentation ("The ZeroZeroOneSplitFn class implements the splitting function for the " "radiation of a gluon by a scalar coloured particle"); } double ZeroZeroOneSplitFn::P(const double z, const Energy2 t, const IdList &ids, const bool mass, const RhoDMatrix &) const { double val = z/(1.-z); if(mass) { Energy m = ids[0]->mass(); val-= sqr(m)/t; } return 2.*colourFactor(ids)*val; } double ZeroZeroOneSplitFn::overestimateP(const double z, const IdList &ids) const { return 2.*colourFactor(ids)/(1.-z); } double ZeroZeroOneSplitFn::ratioP(const double z, const Energy2 t, const IdList &ids,const bool mass, const RhoDMatrix &) const { double val = z; if(mass) { Energy m = ids[0]->mass(); val-=sqr(m)*(1.-z)/t; } return val; } double ZeroZeroOneSplitFn::integOverP(const double z, const IdList & ids, unsigned int PDFfactor) const { switch(PDFfactor) { case 0: return -2.*colourFactor(ids)*log(1.-z); case 1: case 2: case 3: default: throw Exception() << "ZeroZeroOneSplitFn::integOverP() invalid PDFfactor = " << PDFfactor << Exception::runerror; } } double ZeroZeroOneSplitFn::invIntegOverP(const double r, const IdList & ids, unsigned int PDFfactor) const { switch(PDFfactor) { case 0: return 1. - exp(- 0.5*r/colourFactor(ids)); case 1: case 2: case 3: default: throw Exception() << "ZeroZeroOneSplitFn::integOverP() invalid PDFfactor = " << PDFfactor << Exception::runerror; } } bool ZeroZeroOneSplitFn::accept(const IdList &ids) const { if(ids.size()!=3) return false; if(ids[0]!=ids[1]) return false; if(ids[0]->iSpin()!=PDT::Spin0 || ids[2]->iSpin()!=PDT::Spin1) return false; return checkColours(ids); } vector > ZeroZeroOneSplitFn::generatePhiForward(const double, const Energy2, const IdList &, const RhoDMatrix &) { // scalar so no dependence - return vector >(1,make_pair(0,1.)); + return {{ {0, 1.} }}; } vector > ZeroZeroOneSplitFn::generatePhiBackward(const double, const Energy2, const IdList &, const RhoDMatrix &) { // scalar so no dependence assert(false); - return vector >(1,make_pair(0,1.)); + return {{ {0, 1.} }}; } DecayMEPtr ZeroZeroOneSplitFn::matrixElement(const double z, const Energy2 t, const IdList & ids, const double phi, bool timeLike) { // calculate the kernal DecayMEPtr kernal(new_ptr(TwoBodyDecayMatrixElement(PDT::Spin0,PDT::Spin0,PDT::Spin1))); Energy m = timeLike ? ids[0]->mass() : ZERO; (*kernal)(0,0,0) = -exp(Complex(0.,1.)*phi)*sqrt(1.-(1.-z)*sqr(m)/z/t)*sqrt(z/(1.-z)); (*kernal)(0,0,2) = -conj((*kernal)(0,0,0)); return kernal; } diff --git a/Shower/ShowerHandler.h b/Shower/ShowerHandler.h --- a/Shower/ShowerHandler.h +++ b/Shower/ShowerHandler.h @@ -1,839 +1,847 @@ // -*- C++ -*- // // ShowerHandler.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_ShowerHandler_H #define HERWIG_ShowerHandler_H // // This is the declaration of the ShowerHandler class. // #include "ThePEG/Handlers/EventHandler.h" #include "ThePEG/Handlers/CascadeHandler.h" #include "ShowerVariation.h" #include "Herwig/PDF/HwRemDecayer.fh" #include "ThePEG/EventRecord/RemnantParticle.fh" #include "UEBase.h" #include "PerturbativeProcess.h" #include "Herwig/MatrixElement/Matchbox/Matching/HardScaleProfile.h" #include "ShowerHandler.fh" namespace Herwig { using namespace ThePEG; /** \ingroup Shower * * This class is the main driver of the shower: it is responsible for * the proper handling of all other specific collaborating classes * and for the storing of the produced particles in the event record. * * @see \ref ShowerHandlerInterfaces "The interfaces" * * @see ThePEG::CascadeHandler * @see MPIHandler * @see HwRemDecayer */ class ShowerHandler: public CascadeHandler { public: /** * Typedef for a pair of ThePEG::RemnantParticle pointers. */ typedef pair RemPair; public: /** * Default constructor */ ShowerHandler(); /** * Destructor */ virtual ~ShowerHandler(); public: /** * The main method which manages the multiple interactions and starts * the shower by calling cascade(sub, lastXC). */ virtual void cascade(); /** * pointer to "this", the current ShowerHandler. */ static const tShowerHandlerPtr currentHandler() { assert(currentHandler_); return currentHandler_; } public: /** * Hook to allow vetoing of event after showering hard sub-process * as in e.g. MLM merging. */ virtual bool showerHardProcessVeto() const { return false; } /** * Return true, if this cascade handler will perform reshuffling from hard * process masses. */ virtual bool isReshuffling() const { return true; } /** * Return true, if the shower handler can generate a truncated * shower for POWHEG style events generated using Matchbox */ virtual bool canHandleMatchboxTrunc() const { return false; } /** * Get the PDF freezing scale */ Energy pdfFreezingScale() const { return pdfFreezingScale_; } /** * Get the local PDFs. */ PDFPtr getPDFA() const {return PDFA_;} /** * Get the local PDFs. */ PDFPtr getPDFB() const {return PDFB_;} /** * Return true if currently the primary subprocess is showered. */ bool firstInteraction() const { if (!eventHandler()->currentCollision())return true; return ( subProcess_ == eventHandler()->currentCollision()->primarySubProcess() ); } /** * Return the remnant decayer. */ tHwRemDecPtr remnantDecayer() const { return remDec_; } /** * Split the hard process into production and decays * @param tagged The tagged particles from the StepHandler * @param hard The hard perturbative process * @param decay The decay particles */ void splitHardProcess(tPVector tagged, PerturbativeProcessPtr & hard, DecayProcessMap & decay) const; /** * Information if the Showerhandler splits the hard process. */ bool doesSplitHardProcess()const {return splitHardProcess_;} /** * Decay a particle. * radPhotons switches the generation of photon * radiation on/off. * Required for Dipole Shower but not QTilde Shower. */ tDMPtr decay(PerturbativeProcessPtr, DecayProcessMap & decay, bool radPhotons = false) const; /** * Cached lookup of decay modes. * Generator::findDecayMode() is not efficient. */ tDMPtr findDecayMode(const string & tag) const; /** * A struct to order the particles in the same way as in the DecayMode's */ struct ParticleOrdering { bool operator() (tcPDPtr p1, tcPDPtr p2); }; /** * A container for ordered particles required * for constructing tags for decay mode lookup. */ typedef multiset OrderedParticles; public: /** * @name Switches for initial- and final-state radiation */ //@{ /** * Switch for any radiation */ bool doRadiation() const {return doFSR_ || doISR_;} /** * Switch on or off final state radiation. */ bool doFSR() const { return doFSR_;} /** * Switch on or off initial state radiation. */ bool doISR() const { return doISR_;} //@} public: /** * @name Switches for scales */ //@{ /** * Return true if maximum pt should be deduced from the factorization scale */ bool hardScaleIsMuF() const { return maxPtIsMuF_; } /** * The factorization scale factor. */ double factorizationScaleFactor() const { return factorizationScaleFactor_; } /** * The renormalization scale factor. */ double renFac() const { return renormalizationScaleFactor_; } /** * The factorization scale factor. */ double facFac() const { return factorizationScaleFactor_; } /** * The renormalization scale factor. */ double renormalizationScaleFactor() const { return renormalizationScaleFactor_; } /** * The scale factor for the hard scale */ double hardScaleFactor() const { return hardScaleFactor_; } /** * Return true, if the phase space restrictions of the dipole shower should * be applied. */ bool restrictPhasespace() const { return restrictPhasespace_; } /** * Return profile scales */ Ptr::tptr profileScales() const { return hardScaleProfile_; } /** * Return the relevant hard scale to be used in the profile scales */ virtual Energy hardScale() const; + + /** + * Return information about shower phase space choices + */ + virtual int showerPhaseSpaceOption() const { + assert(false && "not implemented in general"); + return -1; + } //@} public: /** * Access the shower variations */ map& showerVariations() { return showerVariations_; } /** * Return the shower variations */ const map& showerVariations() const { return showerVariations_; } /** * Access the current Weights */ map& currentWeights() { return currentWeights_; } /** * Return the current Weights */ const map& currentWeights() const { return currentWeights_; } /** * Change the current reweighting factor */ void reweight(double w) { reweight_ = w; } /** * Return the current reweighting factor */ double reweight() const { return reweight_; } public: /** * struct that is used to catch exceptions which are thrown * due to energy conservation issues of additional scatters */ struct ExtraScatterVeto {}; /** * struct that is used to catch exceptions which are thrown * due to fact that the Shower has been invoked more than * a defined threshold on a certain configuration */ struct ShowerTriesVeto { /** variable to store the number of attempts */ const int tries; /** constructor */ ShowerTriesVeto(int t) : tries(t) {} }; 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 Functions to perform the cascade */ //@{ /** * The main method which manages the showering of a subprocess. */ virtual tPPair cascade(tSubProPtr sub, XCPtr xcomb); /** * Set up for the cascade */ void prepareCascade(tSubProPtr sub) { current_ = currentStep(); subProcess_ = sub; } /** * Boost all the particles in the collision so that the collision always occurs * in the rest frame with the incoming particles along the z axis */ void boostCollision(bool boost); //@} protected: /** * Set/unset the current shower handler */ //@{ /** * Set the current handler */ void setCurrentHandler() { currentHandler_ = tShowerHandlerPtr(this); } /** * Unset the current handler */ void unSetCurrentHandler() { currentHandler_ = tShowerHandlerPtr(); } //@} protected: /** * @name Members relating to the underlying event and MPI */ //@{ /** * Return true if multiple parton interactions are switched on * and can be used for this beam setup. */ bool isMPIOn() const { return MPIHandler_ && MPIHandler_->beamOK(); } /** * Access function for the MPIHandler, it should only be called after * checking with isMPIOn. */ tUEBasePtr getMPIHandler() const { assert(MPIHandler_); return MPIHandler_; } /** * Is a beam particle where hadronic structure is resolved */ bool isResolvedHadron(tPPtr); /** * Get the remnants from the ThePEG::PartonBinInstance es and * do some checks. */ RemPair getRemnants(PBIPair incbins); /** * Reset the PDF's after the hard collision has been showered */ void setMPIPDFs(); //@} public: /** * Check if a particle decays in the shower * @param id The PDG code for the particle */ bool decaysInShower(long id) const { return ( particlesDecayInShower_.find( abs(id) ) != particlesDecayInShower_.end() ); } protected: /** * Members to handle splitting up of hard process and decays */ //@{ /** * Find decay products from the hard process and create decay processes * @param parent The parent particle * @param hard The hard process * @param decay The decay processes */ void findDecayProducts(PPtr parent, PerturbativeProcessPtr hard, DecayProcessMap & decay) const; /** * Find decay products from the hard process and create decay processes * @param parent The parent particle * @param hard The parent hard process * @param decay The decay processes */ void createDecayProcess(PPtr parent,PerturbativeProcessPtr hard, DecayProcessMap & decay) const; //@} /** * @name Functions to return information relevant to the process being showered */ //@{ /** * Return the currently used SubProcess. */ tSubProPtr currentSubProcess() const { assert(subProcess_); return subProcess_; } /** * Access to the incoming beam particles */ tPPair incomingBeams() const { return incoming_; } //@} protected: /** * Weight handling for shower variations */ //@ /** * Combine the variation weights which have been encountered */ void combineWeights(); /** * Initialise the weights in currentEvent() */ void initializeWeights(); /** * Reset the current weights */ void resetWeights(); //@} protected: /** * Return the maximum number of attempts for showering * a given subprocess. */ unsigned int maxtry() const { return maxtry_; } protected: /** * Parameters for the space-time model */ //@{ /** * Whether or not to include spa-cetime distances in the shower */ bool includeSpaceTime() const {return includeSpaceTime_;} /** * The minimum virtuality for the space-time model */ Energy2 vMin() const {return vMin_;} //@} 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(); /** * 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(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ ShowerHandler & operator=(const ShowerHandler &); private: /** * pointer to "this", the current ShowerHandler. */ static tShowerHandlerPtr currentHandler_; /** * a MPIHandler to administer the creation of several (semihard) * partonic interactions. */ UEBasePtr MPIHandler_; /** * Pointer to the HwRemDecayer */ HwRemDecPtr remDec_; private: /** * Maximum tries for various stages of the showering process */ //@{ /** * Maximum number of attempts for the * main showering loop */ unsigned int maxtry_; /** * Maximum number of attempts for the regeneration of an additional * scattering, before the number of scatters is reduced. */ unsigned int maxtryMPI_; /** * Maximum number of attempts for the regeneration of an additional * hard scattering, before this event is vetoed. */ unsigned int maxtryDP_; /** * Maximum number of attempts to generate a decay */ unsigned int maxtryDecay_; //@} private: /** * Factors for the various scales */ //@{ /** * The factorization scale factor. */ double factorizationScaleFactor_; /** * The renormalization scale factor. */ double renormalizationScaleFactor_; /** * The scale factor for the hard scale */ double hardScaleFactor_; /** * True, if the phase space restrictions of the dipole shower should * be applied. */ bool restrictPhasespace_; /** * True if maximum pt should be deduced from the factorization scale */ bool maxPtIsMuF_; /** * The profile scales */ Ptr::ptr hardScaleProfile_; //@} private: /** * Storage of information about the current event */ //@{ /** * The incoming beam particles for the current collision */ tPPair incoming_; /** * Boost to get back to the lab */ LorentzRotation boost_; /** * Const pointer to the currently handeled ThePEG::SubProcess */ tSubProPtr subProcess_; /** * Const pointer to the current step */ tcStepPtr current_; //@} private: /** * PDFs to be used for the various stages and related parameters */ //@{ /** * The PDF freezing scale */ Energy pdfFreezingScale_; /** * PDFs to be used for the various stages and related parameters */ //@{ /** * The PDF for beam particle A. Overrides the particle's own PDF setting. */ PDFPtr PDFA_; /** * The PDF for beam particle B. Overrides the particle's own PDF setting. */ PDFPtr PDFB_; /** * The PDF for beam particle A for remnant splitting. Overrides the particle's own PDF setting. */ PDFPtr PDFARemnant_; /** * The PDF for beam particle B for remnant splitting. Overrides the particle's own PDF setting. */ PDFPtr PDFBRemnant_; /** * The MPI PDF's to be used for secondary scatters. */ pair mpipdfs_; /** * The MPI PDF's to be used for secondary scatters. */ pair rempdfs_; /** * The MPI PDF's to be used for secondary scatters. */ pair remmpipdfs_; //@} private: /** * @name Parameters for initial- and final-state radiation */ //@{ /** * Switch on or off final state radiation. */ bool doFSR_; /** * Switch on or off initial state radiation. */ bool doISR_; //@} private: /** * @name Parameters for particle decays */ //@{ /** * Whether or not to split into hard and decay trees */ bool splitHardProcess_; /** * PDG codes of the particles which decay during showering * this is fast storage for use during running */ set particlesDecayInShower_; /** * PDG codes of the particles which decay during showering * this is a vector that is interfaced so they can be changed */ vector inputparticlesDecayInShower_; //@} private: /** * Parameters for the space-time model */ //@{ /** * Whether or not to include spa-cetime distances in the shower */ bool includeSpaceTime_; /** * The minimum virtuality for the space-time model */ Energy2 vMin_; //@} private: /** * Parameters relevant for reweight and variations */ //@{ /** * The shower variations */ map showerVariations_; /** * Command to add a shower variation */ string doAddVariation(string); /** * A reweighting factor applied by the showering */ double reweight_; /** * The shower variation weights */ map currentWeights_; //@} }; } #endif /* HERWIG_ShowerHandler_H */ diff --git a/Tests/Makefile.am b/Tests/Makefile.am --- a/Tests/Makefile.am +++ b/Tests/Makefile.am @@ -1,400 +1,400 @@ AM_LDFLAGS += -module -avoid-version -rpath /dummy/path/not/used EXTRA_DIST = Inputs python Rivet EXTRA_LTLIBRARIES = LeptonTest.la GammaTest.la HadronTest.la DISTest.la if WANT_LIBFASTJET EXTRA_LTLIBRARIES += HadronJetTest.la LeptonJetTest.la HadronJetTest_la_SOURCES = \ Hadron/VHTest.h Hadron/VHTest.cc\ Hadron/VTest.h Hadron/VTest.cc\ Hadron/HTest.h Hadron/HTest.cc HadronJetTest_la_CPPFLAGS = $(AM_CPPFLAGS) $(FASTJETINCLUDE) \ -I$(FASTJETPATH) HadronJetTest_la_LIBADD = $(FASTJETLIBS) LeptonJetTest_la_SOURCES = \ Lepton/TopDecay.h Lepton/TopDecay.cc LeptonJetTest_la_CPPFLAGS = $(AM_CPPFLAGS) $(FASTJETINCLUDE) \ -I$(FASTJETPATH) LeptonJetTest_la_LIBADD = $(FASTJETLIBS) endif LeptonTest_la_SOURCES = \ Lepton/VVTest.h Lepton/VVTest.cc \ Lepton/VBFTest.h Lepton/VBFTest.cc \ Lepton/VHTest.h Lepton/VHTest.cc \ Lepton/FermionTest.h Lepton/FermionTest.cc GammaTest_la_SOURCES = \ Gamma/GammaMETest.h Gamma/GammaMETest.cc \ Gamma/GammaPMETest.h Gamma/GammaPMETest.cc DISTest_la_SOURCES = \ DIS/DISTest.h DIS/DISTest.cc HadronTest_la_SOURCES = \ Hadron/HadronVVTest.h Hadron/HadronVVTest.cc\ Hadron/HadronVBFTest.h Hadron/HadronVBFTest.cc\ Hadron/WHTest.h Hadron/WHTest.cc\ Hadron/ZHTest.h Hadron/ZHTest.cc\ Hadron/VGammaTest.h Hadron/VGammaTest.cc\ Hadron/ZJetTest.h Hadron/ZJetTest.cc\ Hadron/WJetTest.h Hadron/WJetTest.cc\ Hadron/QQHTest.h Hadron/QQHTest.cc REPO = $(top_builddir)/src/HerwigDefaults.rpo HERWIG = $(top_builddir)/src/Herwig HWREAD = $(HERWIG) read --repo $(REPO) -L $(builddir)/.libs -i $(top_builddir)/src HWBUILD = $(HERWIG) build --repo $(REPO) -L $(builddir)/.libs -i $(top_builddir)/src HWINTEGRATE = $(HERWIG) integrate HWRUN = $(HERWIG) run -N $${NUMEVENTS:-10000} tests : tests-LEP tests-DIS tests-LHC tests-Gamma LEPDEPS = \ test-LEP-VV \ test-LEP-VH \ test-LEP-VBF \ test-LEP-BB \ test-LEP-Quarks \ test-LEP-Leptons if WANT_LIBFASTJET LEPDEPS += test-LEP-TopDecay endif tests-LEP : $(LEPDEPS) tests-DIS : test-DIS-Charged test-DIS-Neutral LHCDEPS = \ test-LHC-WW test-LHC-WZ test-LHC-ZZ \ test-LHC-ZGamma test-LHC-WGamma \ test-LHC-ZH test-LHC-WH \ test-LHC-ZJet test-LHC-WJet \ test-LHC-Z test-LHC-W \ test-LHC-ZZVBF test-LHC-VBF \ test-LHC-WWVBF \ test-LHC-bbH test-LHC-ttH \ test-LHC-GammaGamma test-LHC-GammaJet \ test-LHC-Higgs test-LHC-HiggsJet \ test-LHC-QCDFast test-LHC-QCD \ test-LHC-Top if WANT_LIBFASTJET LHCDEPS += \ test-LHC-Bottom \ test-LHC-WHJet test-LHC-ZHJet test-LHC-HJet \ test-LHC-ZShower test-LHC-WShower \ test-LHC-WHJet-Powheg test-LHC-ZHJet-Powheg test-LHC-HJet-Powheg \ test-LHC-ZShower-Powheg test-LHC-WShower-Powheg endif tests-LHC : $(LHCDEPS) tests-Gamma : test-Gamma-FF test-Gamma-WW test-Gamma-P LEPLIBS = LeptonTest.la HADLIBS = HadronTest.la if WANT_LIBFASTJET LEPLIBS += LeptonJetTest.la HADLIBS += HadronJetTest.la endif test-LEP-% : Inputs/LEP-%.in $(LEPLIBS) $(HWREAD) $< $(HWRUN) $(notdir $(subst .in,.run,$<)) test-Gamma-% : Inputs/Gamma-%.in GammaTest.la $(HWREAD) $< $(HWRUN) $(notdir $(subst .in,.run,$<)) test-DIS-% : Inputs/DIS-%.in DISTest.la $(HWREAD) $< $(HWRUN) $(notdir $(subst .in,.run,$<)) test-LHC-% : Inputs/LHC-%.in GammaTest.la $(HADLIBS) $(HWREAD) $< $(HWRUN) $(notdir $(subst .in,.run,$<)) tests-Rivet : Rivet-LEP Rivet-BFactory Rivet-DIS Rivet-Star Rivet-SppS \ Rivet-TVT-WZ Rivet-TVT-Photon Rivet-TVT-Jets \ Rivet-LHC-Jets Rivet-LHC-EW Rivet-LHC-Photon Rivet-LHC-Higgs Rivet-%.run : Rivet/%.in $(HWBUILD) -c .cache/$(subst .run,,$@) $< Rivet-Matchbox-%.yoda : Rivet-Matchbox-%.run $(HWINTEGRATE) -c .cache/$(subst .run,,$<) $< $(HWRUN) -c .cache/$(subst .run,,$<) $< Rivet-%.yoda : Rivet-%.run $(HWRUN) $< Rivet/%.in : python/make_input_files.py $(notdir $(subst .in,,$@)) Rivet-inputfiles: $(shell echo Rivet/LEP{,-Powheg,-Matchbox,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Matchbox-Powheg,-Merging}-{9.4,12,13,17,27.6,29,30.2,30.7,30.75,30,31.3,34.8,43.6,50,52,55,56,57,60.8,60,61.4,10,12.8,22,26.8,35,44,48.0,91,93.0,130,133,136,161,172,177,183,189,192,196,197,200,202,206,91-nopi}.in) \ $(shell echo Rivet/LEP{,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Powheg,-Matchbox-Powheg}-14.in) \ $(shell echo Rivet/LEP{,-Dipole}-{10.5,11.96,12.8,13.96,16.86,21.84,26.8,28.48,35.44,48.0,97.0}-gg.in) \ $(shell echo Rivet/BFactory{,-Powheg,-Matchbox,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Matchbox-Powheg}-{10.52,10.52-sym,10.54,10.45}.in) \ $(shell echo Rivet/BFactory{,-Dipole}-{Upsilon,Upsilon2,Upsilon4,Tau,10.58-res}.in) \ $(shell echo Rivet/DIS{,-NoME,-Powheg,-Matchbox,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Matchbox-Powheg,-Merging}-{e--LowQ2,e+-LowQ2,e+-HighQ2}.in) \ $(shell echo Rivet/TVT{,-Powheg,-Matchbox,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Matchbox-Powheg,-Merging}-{Run-I-Z,Run-I-W,Run-I-WZ,Run-II-Z-e,Run-II-Z-{,LowMass-,HighMass-}mu,Run-II-W}.in) \ $(shell echo Rivet/TVT{,-Dipole}-Run-II-{DiPhoton-GammaGamma,DiPhoton-GammaJet,PromptPhoton}.in) \ $(shell echo Rivet/TVT-Powheg-Run-II-{DiPhoton-GammaGamma,DiPhoton-GammaJet}.in) \ $(shell echo Rivet/TVT{,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Matchbox,-Matchbox-Powheg,-Merging}-{Run-II-Jets-{0..11},Run-I-Jets-{1..8}}.in ) \ $(shell echo Rivet/TVT{,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Matchbox,-Matchbox-Powheg,-Merging}-{630-Jets-{1..3},300-Jets-1,900-Jets-1}.in ) \ $(shell echo Rivet/TVT{,-Dipole}-{Run-I,Run-II,300,630,900}-UE.in) \ $(shell echo Rivet/LHC{,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Matchbox,-Matchbox-Powheg,-Merging}-7-DiJets-{1..7}-{A,B,C}.in ) \ $(shell echo Rivet/LHC{,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Matchbox,-Matchbox-Powheg,-Merging}-{7,8,13}-Jets-{0..10}.in ) \ $(shell echo Rivet/LHC{,-Dipole}-{900,2360,2760,7,8,13}-UE.in ) \ $(shell echo Rivet/LHC{,-Dipole}-{900,7,13}-UE-Long.in ) \ $(shell echo Rivet/LHC{,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Matchbox,-Matchbox-Powheg,-Merging}-7-Charm-{1..5}.in) \ $(shell echo Rivet/LHC{,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Matchbox,-Matchbox-Powheg,-Merging}-7-Bottom-{0..8}.in) \ - $(shell echo Rivet/LHC{,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Matchbox,-Matchbox-Powheg,-Merging}-7-Top-{L,SL}.in) \ - $(shell echo Rivet/LHC{,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Matchbox,-Matchbox-Powheg,-Merging}-{7,8,13}-Top-All.in) \ + $(shell echo Rivet/LHC{,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Matchbox,-Matchbox-Powheg,-Merging}-{7,8,13}-Top-{L,SL}.in) \ + $(shell echo Rivet/LHC{,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Matchbox,-Matchbox-Powheg,-Merging}-{7,8}-Top.in) \ $(shell echo Rivet/Star{,-Dipole}-{UE,Jets-{1..4}}.in ) \ $(shell echo Rivet/SppS{,-Dipole}-{200,500,900,546}-UE.in ) \ - $(shell echo Rivet/LHC{,-Matchbox,-Matchbox-Powheg,-Powheg,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Merging}-{W-{e,mu},13-Z-{e,mu},Z-HighMass{1,2}-e,8-Z-Mass{1..4}-{e,mu},Z-{e,mu,mu-SOPHTY},Z-LowMass-{e,mu},Z-MedMass-e,WZ,WW-{emu,ll},ZZ-{ll,lv},8-ZZ-lv,8-WW-ll,W-Z-{e,mu}}.in) \ + $(shell echo Rivet/LHC{,-Matchbox,-Matchbox-Powheg,-Powheg,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Merging}-{W-{e,mu},13-Z-{e,mu},Z-HighMass{1,2}-e,{8,13}-W-mu,8-Z-Mass{1..4}-{e,mu},Z-{e,mu,mu-SOPHTY},Z-LowMass-{e,mu},Z-MedMass-e,WZ,WW-{emu,ll},ZZ-{ll,lv},{8,13}-WZ,8-ZZ-lv,8-WW-ll,W-Z-{e,mu}}.in) \ $(shell echo Rivet/LHC{,-Dipole}-7-{W,Z}Gamma-{e,mu}.in) \ $(shell echo Rivet/LHC{,-Matchbox,-Matchbox-Powheg,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Merging}-{7-W-Jet-{1..3}-e,7-Z-Jet-{0..3}-e,7-Z-Jet-0-mu}.in) \ $(shell echo Rivet/LHC{-Matchbox,-Matchbox-Powheg,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Merging}-{Z-b,Z-bb,W-b,8-Z-jj}.in) \ $(shell echo Rivet/LHC{,-Dipole}-{7,8}-PromptPhoton-{1..4}.in) Rivet/LHC-GammaGamma-7.in \ $(shell echo Rivet/LHC{,-Powheg}-{7,8}-{DiPhoton-GammaGamma,DiPhoton-GammaJet}.in) \ $(shell echo Rivet/LHC{,-Powheg,-Matchbox,-Matchbox-Powheg,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Merging}-{ggH,VBF,WH,ZH}.in) \ $(shell echo Rivet/LHC{,-Powheg,-Matchbox,-Matchbox-Powheg,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Merging}-8-{{ggH,VBF,WH,ZH}{,-GammaGamma},ggH-WW}.in) \ $(shell echo Rivet/LHC{,-Matchbox,-Matchbox-Powheg,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Merging}-ggHJet.in) # $(shell echo Rivet/ISR-{30,44,53,62}-UE.in ) $(shell echo Rivet/SppS-{53,63}-UE.in ) Rivet-LEP : Rivet-LEP/done touch $@ Rivet-LEP/done : $(shell echo Rivet{,-Powheg,-Matchbox,-Dipole}-LEP-{9.4,12,13,17,27.6,29,30.2,30.7,30.75,30,31.3,34.8,43.6,50,52,55,56,57,60.8,60,61.4,10,12.8,22,26.8,35,44,48.0,91,93.0,130,133,136,161,172,177,183,189,192,196,197,200,202,206,91-nopi}.yoda) \ $(shell echo Rivet-LEP-{10.5,11.96,12.8,13.96,16.86,21.84,26.8,28.48,35.44,48.0,97.0}-gg.yoda) \ $(shell echo Rivet{,-Powheg,-Matchbox,-Matchbox-Powheg,-Dipole}-LEP-14.yoda) rm -rf Rivet-LEP python/merge-LEP --with-gg LEP python/merge-LEP Powheg-LEP python/merge-LEP Matchbox-LEP python/merge-LEP Dipole-LEP rivet-mkhtml -o Rivet-LEP LEP.yoda:Hw Powheg-LEP.yoda:Hw-Powheg Matchbox-LEP.yoda:Hw-Matchbox Dipole-LEP.yoda:Hw-Dipole touch $@ Rivet-BFactory : Rivet-BFactory/done touch $@ Rivet-BFactory/done: $(shell echo Rivet{,-Powheg,-Matchbox,-Dipole}-BFactory-{10.52,10.52-sym,10.54,10.45}.yoda) \ $(shell echo Rivet-BFactory-{Upsilon,Upsilon2,Upsilon4,Tau,10.58-res,10.58}.yoda) rm -rf Rivet-BFactory python/merge-BFactory BFactory python/merge-BFactory Powheg-BFactory python/merge-BFactory Matchbox-BFactory python/merge-BFactory Dipole-BFactory rivet-mkhtml -o Rivet-BFactory BFactory.yoda:Hw Powheg-BFactory.yoda:Hw-Powheg Matchbox-BFactory.yoda:Hw-Matchbox Dipole-BFactory.yoda:Hw-Dipole touch $@ Rivet-DIS : Rivet-DIS/done touch $@ Rivet-DIS/done: $(shell echo Rivet{-DIS,-DIS-NoME,-Powheg-DIS,-Matchbox-DIS,-Dipole-DIS}-{e--LowQ2,e+-LowQ2,e+-HighQ2}.yoda) rm -rf Rivet-DIS python/merge-DIS DIS python/merge-DIS Powheg-DIS python/merge-DIS DIS-NoME python/merge-DIS Matchbox-DIS python/merge-DIS Dipole-DIS rivet-mkhtml -o Rivet-DIS DIS.yoda:Hw Powheg-DIS.yoda:Hw-Powheg DIS-NoME.yoda:Hw-NoME Matchbox-DIS.yoda:Hw-Matchbox Dipole-DIS.yoda:Hw-Dipole touch $@ Rivet-TVT-WZ : Rivet-TVT-WZ/done touch $@ Rivet-TVT-WZ/done: $(shell echo Rivet{,-Powheg,-Matchbox,-Dipole}-TVT-{Run-I-Z,Run-I-W,Run-I-WZ,Run-II-Z-{e,{,LowMass-,HighMass-}mu},Run-II-W}.yoda) rm -rf Rivet-TVT-WZ python/merge-TVT-EW Rivet-TVT-Run-II-W.yoda Rivet-TVT-Run-II-Z-{e,{,LowMass-,HighMass-}mu}.yoda\ Rivet-TVT-Run-I-{W,Z,WZ}.yoda -o TVT-WZ.yoda python/merge-TVT-EW Rivet-TVT-Powheg-Run-II-W.yoda Rivet-TVT-Powheg-Run-II-Z-{e,{,LowMass-,HighMass-}mu}.yoda\ Rivet-TVT-Powheg-Run-I-{W,Z,WZ}.yoda -o TVT-Powheg-WZ.yoda python/merge-TVT-EW Rivet-TVT-Matchbox-Run-II-W.yoda Rivet-TVT-Matchbox-Run-II-Z-{e,{,LowMass-,HighMass-}mu}.yoda\ Rivet-TVT-Matchbox-Run-I-{W,Z,WZ}.yoda -o TVT-Matchbox-WZ.yoda python/merge-TVT-EW Rivet-TVT-Dipole-Run-II-W.yoda Rivet-TVT-Dipole-Run-II-Z-{e,{,LowMass-,HighMass-}mu}.yoda\ Rivet-TVT-Dipole-Run-I-{W,Z,WZ}.yoda -o TVT-Dipole-WZ.yoda rivet-mkhtml -o Rivet-TVT-WZ TVT-WZ.yoda:Hw TVT-Powheg-WZ.yoda:Hw-Powheg TVT-Matchbox-WZ.yoda:Hw-Matchbox TVT-Dipole-WZ.yoda:Hw-Dipole touch $@ Rivet-TVT-Photon : Rivet-TVT-Photon/done touch $@ Rivet-TVT-Photon/done: $(shell echo Rivet-TVT-Run-II-{DiPhoton-GammaGamma,DiPhoton-GammaJet,PromptPhoton}.yoda) \ $(shell echo Rivet-Powheg-TVT-Run-II-{DiPhoton-GammaGamma,DiPhoton-GammaJet}.yoda) rm -rf Rivet-TVT-Photon python/merge-TVT-Photon TVT -o TVT-Photon.yoda python/merge-TVT-Photon TVT-Powheg -o TVT-Powheg-Photon.yoda rivet-mkhtml -o Rivet-TVT-Photon TVT-Photon.yoda:Hw TVT-Powheg-Photon.yoda:Hw-Powheg touch $@ Rivet-TVT-Jets : Rivet-TVT-Jets/done touch $@ Rivet-TVT-Jets/done: $(shell echo Rivet-TVT-{Run-II-Jets-{0..11},Run-I-Jets-{1..8}}.yoda ) \ $(shell echo Rivet-TVT-{630-Jets-{1..3},300-Jets-1,900-Jets-1}.yoda ) \ $(shell echo Rivet-TVT-{Run-I,Run-II,300,630,900}-UE.yoda) rm -rf Rivet-TVT-Jets python/merge-TVT-Jets TVT rivet-mkhtml -o Rivet-TVT-Jets TVT-Jets.yoda:Hw touch $@ #python/merge-TVT-Energy TVT #rivet-merge-CDF_2012_NOTE10874 TVT-300-Energy.yoda TVT-900-Energy.yoda TVT-1960-Energy.yoda #flat2yoda RatioPlots.dat -o TVT-RatioPlots.yoda Rivet-Star : Rivet-Star/done touch $@ Rivet-Star/done : $(shell echo Rivet-Star-{UE,Jets-{1..4}}.yoda ) rm -rf Rivet-Star python/merge-Star Star ## broken DVI? ## rivet-mkhtml -v -o Rivet-Star Star.yoda mkdir -p Rivet-Star # remove when fixed touch $@ Rivet-SppS : Rivet-SppS/done touch $@ ## $(shell echo Rivet-ISR-{30,44,53,62}-UE.yoda ) \ ## {53,63,200,500,900,546} Rivet-SppS/done : $(shell echo Rivet-SppS-{200,500,900,546}-UE.yoda ) rm -rf Rivet-SppS python/merge-SppS SppS rivet-mkhtml -o Rivet-SppS SppS.yoda touch $@ Rivet-LHC-Jets : Rivet-LHC-Jets/done touch $@ Rivet-LHC-Jets/done : \ $(shell echo Rivet-LHC-7-DiJets-{1..7}-{A,B,C}.yoda ) \ $(shell echo Rivet-LHC-{7,8,13}-Jets-{0..10}.yoda ) \ $(shell echo Rivet-LHC-{900,2360,2760,7,8,13}-UE.yoda ) \ $(shell echo Rivet-LHC-{900,7,13}-UE-Long.yoda ) \ - $(shell echo Rivet-LHC-7-Charm-{1..5}.yoda ) \ - $(shell echo Rivet-LHC-7-Bottom-{0..8}.yoda ) \ - $(shell echo Rivet-LHC-7-Top-{L,SL}.yoda ) \ - $(shell echo Rivet-LHC-{7,8,13}-Top-All.yoda ) + $(shell echo Rivet-LHC-7-Charm-{1..5}.yoda ) \ + $(shell echo Rivet-LHC-7-Bottom-{0..8}.yoda ) \ + $(shell echo Rivet-LHC-{7,8,13}-Top-{L,SL}.yoda ) \ + $(shell echo Rivet-LHC-{7,8}-Top-All.yoda ) rm -rf Rivet-LHC-Jets python/merge-LHC-Jets LHC rivet-mkhtml -o Rivet-LHC-Jets LHC-Jets.yoda:Hw touch $@ Rivet-LHC-EW : Rivet-LHC-EW/done touch $@ Rivet-LHC-EW/done: \ - $(shell echo Rivet{,-Matchbox,-Powheg,-Dipole}-LHC-{13-Z-{e,mu},Z-HighMass{1,2}-e,8-Z-Mass{1..4}-{e,mu},W-{e,mu},Z-{e,mu,mu-SOPHTY},Z-LowMass-{e,mu},Z-MedMass-e,WZ,WW-{emu,ll},ZZ-{ll,lv},8-ZZ-lv,8-WW-ll,W-Z-{e,mu}}.yoda) \ + $(shell echo Rivet{,-Matchbox,-Powheg,-Dipole}-LHC-{13-Z-{e,mu},{8,13}-W-mu,Z-HighMass{1,2}-e,8-Z-Mass{1..4}-{e,mu},W-{e,mu},Z-{e,mu,mu-SOPHTY},Z-LowMass-{e,mu},Z-MedMass-e,WZ,WW-{emu,ll},ZZ-{ll,lv},{8,13}-WZ,8-ZZ-lv,8-WW-ll,W-Z-{e,mu}}.yoda) \ $(shell echo Rivet{,-Matchbox,-Dipole}-LHC-{7-W-Jet-{1..3}-e,7-Z-Jet-{0..3}-e,7-Z-Jet-0-mu}.yoda) \ $(shell echo Rivet{-Matchbox,-Dipole}-LHC-{Z-b,Z-bb,W-b,8-Z-jj}.yoda) \ $(shell echo Rivet-LHC-7-{W,Z}Gamma-{e,mu}.yoda) rm -rf Rivet-LHC-EW; - python/merge-LHC-EW Rivet-LHC-{13-Z-{e,mu},Z-HighMass{1,2}-e,8-Z-Mass{1..4}-{e,mu},W-{e,mu},Z-{e,mu,mu-Short},Z-LowMass-{e,mu},Z-MedMass-e,W-Z-{e,mu},WW-{emu,ll},WZ,ZZ-{ll,lv},8-ZZ-lv,8-WW-ll}.yoda Rivet-LHC-7-{W,Z}-Jet-{1,2,3}-e.yoda Rivet-LHC-7-{W,Z}Gamma-{e,mu}.yoda -o LHC-EW.yoda; - python/merge-LHC-EW Rivet-Matchbox-LHC-{13-Z-{e,mu},Z-HighMass{1,2}-e,8-Z-Mass{1..4}-{e,mu},W-{e,mu},Z-{e,mu,mu-Short},Z-LowMass-{e,mu},Z-MedMass-e,W-Z-{e,mu},WW-{emu,ll},WZ,ZZ-{ll,lv},8-ZZ-lv,8-WW-ll}.yoda Rivet-LHC-Matchbox-7-{W,Z}-Jet-{1,2,3}-e.yoda -o LHC-Matchbox-EW.yoda; - python/merge-LHC-EW Rivet-Dipole-LHC-{13-Z-{e,mu},Z-HighMass{1,2}-e,8-Z-Mass{1..4}-{e,mu},W-{e,mu},Z-{e,mu,mu-Short},Z-LowMass-{e,mu},Z-MedMass-e,W-Z-{e,mu},WW-{emu,ll},WZ,ZZ-{ll,lv},8-ZZ-lv,8-WW-ll}.yoda Rivet-LHC-Dipole-7-{W,Z}-Jet-{1,2,3}-e.yoda -o LHC-Dipole-EW.yoda; - python/merge-LHC-EW Rivet-Powheg-LHC-{W-{e,mu},Z-{e,mu},Z-LowMass-{e,mu},Z-MedMass-e,W-Z-{e,mu},WW-{emu,ll},WZ,ZZ-{ll,lv},8-ZZ-lv,8-WW-ll}.yoda -o LHC-Powheg-EW.yoda; + python/merge-LHC-EW Rivet-LHC-{13-Z-{e,mu},Z-HighMass{1,2}-e,8-Z-Mass{1..4}-{e,mu},W-{e,mu},Z-{e,mu,mu-Short},Z-LowMass-{e,mu},Z-MedMass-e,W-Z-{e,mu},WW-{emu,ll},WZ,ZZ-{ll,lv},{8,13}-WZ,8-ZZ-lv,8-WW-ll}.yoda Rivet-LHC-7-{W,Z}-Jet-{1,2,3}-e.yoda Rivet-LHC-7-{W,Z}Gamma-{e,mu}.yoda -o LHC-EW.yoda; + python/merge-LHC-EW Rivet-Matchbox-LHC-{13-Z-{e,mu},Z-HighMass{1,2}-e,8-Z-Mass{1..4}-{e,mu},W-{e,mu},Z-{e,mu,mu-Short},Z-LowMass-{e,mu},Z-MedMass-e,W-Z-{e,mu},WW-{emu,ll},WZ,ZZ-{ll,lv},{8,13}-WZ,{8,13}-WZ,8-ZZ-lv,8-WW-ll}.yoda Rivet-LHC-Matchbox-7-{W,Z}-Jet-{1,2,3}-e.yoda -o LHC-Matchbox-EW.yoda; + python/merge-LHC-EW Rivet-Dipole-LHC-{13-Z-{e,mu},Z-HighMass{1,2}-e,8-Z-Mass{1..4}-{e,mu},W-{e,mu},Z-{e,mu,mu-Short},Z-LowMass-{e,mu},Z-MedMass-e,W-Z-{e,mu},WW-{emu,ll},WZ,ZZ-{ll,lv},{8,13}-WZ,8-ZZ-lv,8-WW-ll}.yoda Rivet-LHC-Dipole-7-{W,Z}-Jet-{1,2,3}-e.yoda -o LHC-Dipole-EW.yoda; + python/merge-LHC-EW Rivet-Powheg-LHC-{W-{e,mu},Z-{e,mu},Z-LowMass-{e,mu},Z-MedMass-e,W-Z-{e,mu},WW-{emu,ll},WZ,ZZ-{ll,lv},{8,13}-WZ,8-ZZ-lv,8-WW-ll}.yoda -o LHC-Powheg-EW.yoda; rivet-mkhtml -o Rivet-LHC-EW LHC-EW.yoda:Hw LHC-Powheg-EW.yoda:Hw-Powheg LHC-Matchbox-EW.yoda:Hw-Matchbox LHC-Matchbox-Z-b.yoda:Hw-Matchbox-Zb \ LHC-Matchbox-Z-bb.yoda:Hw-Matchbox-Zbb LHC-Matchbox-W-b.yoda:Hw-Matchbox-W-bb LHC-Dipole-EW.yoda:Hw-Dipole \ LHC-Dipole-Z-b.yoda:Hw-Dipole-Zb LHC-Dipole-Z-bb.yoda:Hw-Dipole-Zbb LHC-Dipole-W-b.yoda:Hw-Dipole-W-bb \ LHC-Z-mu-SOPHTY.yoda:Hw LHC-Powheg-Z-mu-SOPHTY.yoda:Hw-Powheg LHC-Matchbox-Z-mu-SOPHTY.yoda:Hw-Matchbox touch $@ Rivet-LHC-Photon : Rivet-LHC-Photon/done touch $@ Rivet-LHC-Photon/done: \ $(shell echo Rivet-LHC-{7,8}-PromptPhoton-{1..4}.yoda) \ Rivet-LHC-GammaGamma-7.yoda \ $(shell echo Rivet{,-Powheg}-LHC-{7,8}-{DiPhoton-GammaGamma,DiPhoton-GammaJet}.yoda) rm -rf Rivet-LHC-Photon python/merge-LHC-Photon LHC -o LHC-Photon.yoda python/merge-LHC-Photon LHC-Powheg -o LHC-Powheg-Photon.yoda rivet-mkhtml -o Rivet-LHC-Photon LHC-Photon.yoda:Hw LHC-Powheg-Photon.yoda:Hw-Powheg touch $@ Rivet-LHC-Higgs : Rivet-LHC-Higgs/done touch $@ Rivet-LHC-Higgs/done: \ $(shell echo Rivet{,-Powheg}-LHC-{ggH,VBF,WH,ZH}.yoda) \ $(shell echo Rivet{,-Powheg}-LHC-8-{{ggH,VBF,WH,ZH}{,-GammaGamma},ggH-WW}.yoda) \ Rivet-LHC-ggHJet.yoda rm -rf Rivet-LHC-Higgs rivet-mkhtml -o Rivet-LHC-Higgs LHC-Powheg-ggH.yoda:gg-Powheg LHC-ggH.yoda:gg LHC-ggHJet.yoda:HJet \ LHC-Powheg-VBF.yoda:VBF-Powheg LHC-VBF.yoda:VBF LHC-WH.yoda:WH LHC-ZH.yoda:ZH \ LHC-Powheg-WH.yoda:WH-Powheg LHC-Powheg-ZH.yoda:ZH-Powheg touch $@ clean-local: rm -f *.out *.log *.tex *.top *.run *.dump *.mult *.Bmult *.yoda Rivet/*.in rm -rf Rivet-* distclean-local: rm -rf .cache diff --git a/Tests/Rivet/LHC/LHC-13-Top-All.in b/Tests/Rivet/LHC/LHC-13-Top-All.in --- a/Tests/Rivet/LHC/LHC-13-Top-All.in +++ b/Tests/Rivet/LHC/LHC-13-Top-All.in @@ -1,5 +1,3 @@ ################################################## # select the analyses -################################################## -# ATLAS top -insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1468168 +################################################## \ No newline at end of file diff --git a/Tests/Rivet/LHC/LHC-13-Top-L.in b/Tests/Rivet/LHC/LHC-13-Top-L.in new file mode 100644 --- /dev/null +++ b/Tests/Rivet/LHC/LHC-13-Top-L.in @@ -0,0 +1,6 @@ +################################################## +# select the analyses +################################################## +# ATLAS top +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1468168 +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2017_I1495243 \ No newline at end of file diff --git a/Tests/Rivet/LHC/LHC-13-Top-SL.in b/Tests/Rivet/LHC/LHC-13-Top-SL.in new file mode 100644 --- /dev/null +++ b/Tests/Rivet/LHC/LHC-13-Top-SL.in @@ -0,0 +1,4 @@ +################################################## +# select the analyses +################################################## +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2016_I1491950 \ No newline at end of file diff --git a/Tests/Rivet/LHC/LHC-13-W-mu.in b/Tests/Rivet/LHC/LHC-13-W-mu.in new file mode 100644 --- /dev/null +++ b/Tests/Rivet/LHC/LHC-13-W-mu.in @@ -0,0 +1,5 @@ +################################################## +# select the analyses +################################################## +# CMS W+jets +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2017_I1610623 diff --git a/Tests/Rivet/LHC/LHC-WZ.in b/Tests/Rivet/LHC/LHC-13-WZ.in copy from Tests/Rivet/LHC/LHC-WZ.in copy to Tests/Rivet/LHC/LHC-13-WZ.in --- a/Tests/Rivet/LHC/LHC-WZ.in +++ b/Tests/Rivet/LHC/LHC-13-WZ.in @@ -1,5 +1,5 @@ ################################################## # select the analyses ################################################## # general analysis -insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_I954993 +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1469071 diff --git a/Tests/Rivet/LHC/LHC-13-Z-e.in b/Tests/Rivet/LHC/LHC-13-Z-e.in --- a/Tests/Rivet/LHC/LHC-13-Z-e.in +++ b/Tests/Rivet/LHC/LHC-13-Z-e.in @@ -1,5 +1,6 @@ ################################################## # select the analyses ################################################## # ATLAS Z insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_CONF_2015_041_EL +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2017_I1514251 \ No newline at end of file diff --git a/Tests/Rivet/LHC/LHC-2760-UE.in b/Tests/Rivet/LHC/LHC-2760-UE.in --- a/Tests/Rivet/LHC/LHC-2760-UE.in +++ b/Tests/Rivet/LHC/LHC-2760-UE.in @@ -1,7 +1,9 @@ ################################################## # select the analyses ################################################## # underlying event forward rapidities insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1218372 # underlying event insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2015_I1385107 +# ALICE neutral pion cross section +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ALICE_2017_I1512110 diff --git a/Tests/Rivet/LHC/LHC-7-PromptPhoton-1.in b/Tests/Rivet/LHC/LHC-7-PromptPhoton-1.in --- a/Tests/Rivet/LHC/LHC-7-PromptPhoton-1.in +++ b/Tests/Rivet/LHC/LHC-7-PromptPhoton-1.in @@ -1,13 +1,15 @@ ################################################## # select the analyses ################################################## # ATLAS prompt photon insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8914702 insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1093738 insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_I921594 insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2013_I1263495 insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2013_I1244522 # CMS insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1258128 # MC insert /Herwig/Analysis/RivetAnalysis:Analyses 0 MC_PHOTONJETS +# CMS photon + jets +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2014_I1266056 diff --git a/Tests/Rivet/LHC/LHC-7-PromptPhoton-2.in b/Tests/Rivet/LHC/LHC-7-PromptPhoton-2.in --- a/Tests/Rivet/LHC/LHC-7-PromptPhoton-2.in +++ b/Tests/Rivet/LHC/LHC-7-PromptPhoton-2.in @@ -1,13 +1,15 @@ ################################################## # select the analyses ################################################## # ATLAS prompt photon insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8914702 insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1093738 insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_I921594 insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2013_I1263495 insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2013_I1244522 # CMS insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1258128 # MC insert /Herwig/Analysis/RivetAnalysis:Analyses 0 MC_PHOTONJETS +# CMS photon + jets +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2014_I1266056 diff --git a/Tests/Rivet/LHC/LHC-7-PromptPhoton-3.in b/Tests/Rivet/LHC/LHC-7-PromptPhoton-3.in --- a/Tests/Rivet/LHC/LHC-7-PromptPhoton-3.in +++ b/Tests/Rivet/LHC/LHC-7-PromptPhoton-3.in @@ -1,13 +1,15 @@ ################################################## # select the analyses ################################################## # ATLAS prompt photon insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8914702 insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1093738 insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_I921594 insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2013_I1263495 insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2013_I1244522 # CMS insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1258128 # MC insert /Herwig/Analysis/RivetAnalysis:Analyses 0 MC_PHOTONJETS +# CMS photon + jets +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2014_I1266056 diff --git a/Tests/Rivet/LHC/LHC-7-PromptPhoton-4.in b/Tests/Rivet/LHC/LHC-7-PromptPhoton-4.in --- a/Tests/Rivet/LHC/LHC-7-PromptPhoton-4.in +++ b/Tests/Rivet/LHC/LHC-7-PromptPhoton-4.in @@ -1,14 +1,16 @@ ################################################## # select the analyses ################################################## # ATLAS prompt photon insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8914702 insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1093738 insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_I921594 insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2013_I1263495 insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2013_I1244522 # CMS insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1258128 # MC insert /Herwig/Analysis/RivetAnalysis:Analyses 0 MC_PHOTONJETS +# CMS photon + jets +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2014_I1266056 diff --git a/Tests/Rivet/LHC/LHC-7-UE.in b/Tests/Rivet/LHC/LHC-7-UE.in --- a/Tests/Rivet/LHC/LHC-7-UE.in +++ b/Tests/Rivet/LHC/LHC-7-UE.in @@ -1,90 +1,90 @@ ################################################## # select the analyses ################################################## # ATLAS jet shapes insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_S8924791 # ATLAS jets insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8817804 insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1082936 # ATLAS UE insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_S8994773 # ATLAS UE insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8894728 # ATLAS fragmentation function insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_CONF_2010_049 # ATLAS UE insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8918562 # ALICE charged particles insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ALICE_2010_S8625980 # CMS particle spectra insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S8978280 # CMS charged particle multiplicity insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S8884919 # CMS charged particle pT and rapidity insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2010_S8656010 # CMS UE insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S9120041 # ATLAS track jet insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_I919017 # LHCB phi production insert /Herwig/Analysis/RivetAnalysis:Analyses 0 LHCB_2011_I919315 # ATLAS phi production insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1282441 # LHCB promt hadron productiom insert /Herwig/Analysis/RivetAnalysis:Analyses 0 LHCB_2012_I1119400 # ATLAS rap gap insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1084540 # CMS forward energy flow insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S9215166 # LHC K0s/Lambda insert /Herwig/Analysis/RivetAnalysis:Analyses 0 LHCB_2011_I917009 # TOTEM at large rapidity insert /Herwig/Analysis/RivetAnalysis:Analyses 0 TOTEM_2012_I1115294 # ATLAS Azimuthal ordering of charged hadrons insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1091481 # ALICE single/double diffractive and inelastic sigma insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ALICE_2012_I1181770 # ATLAS inelastic cross section insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_I894867 # CMS inelastic cross section insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I1193338 # total transverse energy insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1183818 # underlying event forward rapidities insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1218372 # strange particles in underlying event insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_PAS_QCD_11_010 # CMS central and forward jets insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I1087342 # CMS dijet insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I1184941 # ATLAS charged particle in min bias insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1125575 # ATLAS two particle correlation #insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1094061 # ATLAS correlations insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1093734 # LHCB energy flow insert /Herwig/Analysis/RivetAnalysis:Analyses 0 LHCB_2013_I1208105 # ATLAS charged particle event shapes insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1124167 # CMS Jet/UE properties insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1261026 # ATLAS leading jet UE insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1298811 # LHCB charged particles in min bias insert /Herwig/Analysis/RivetAnalysis:Analyses 0 LHCB_2014_I1281685 # ALICE identified particle spectra insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ALICE_2015_I1357424 insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ALICE_2014_I1300380 # LHCB min bias insert /Herwig/Analysis/RivetAnalysis:Analyses 0 LHCB_2015_I1333223 # ALICE pion and eta pT insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ALICE_2012_I1116147 -insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_PAS_FSQ_12_020 +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_PAS_FSQ_12_020 # CMS charged particle rapidity -insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2010_PAS_QCD_10_024 +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_QCD_10_024 # diffractive analyses insert /Herwig/Analysis/RivetAnalysis:Analyses 0 LHCF_2012_I1115479 insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2015_I1356998 insert /Herwig/Analysis/RivetAnalysis:Analyses 0 TOTEM_2012_I1220862 \ No newline at end of file diff --git a/Tests/Rivet/LHC/LHC-8-Jets-1.in b/Tests/Rivet/LHC/LHC-8-Jets-1.in --- a/Tests/Rivet/LHC/LHC-8-Jets-1.in +++ b/Tests/Rivet/LHC/LHC-8-Jets-1.in @@ -1,4 +1,11 @@ # ATLAS tracks in jets insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1419070 # ATLAS jet charge insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1393758 +# ATLAS transverse energy correlations +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2017_I1609253 +# CMS jets +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2016_I1487277 +# CMS di-jet decorrelation +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2016_I1421646 + diff --git a/Tests/Rivet/LHC/LHC-8-Jets-10.in b/Tests/Rivet/LHC/LHC-8-Jets-10.in --- a/Tests/Rivet/LHC/LHC-8-Jets-10.in +++ b/Tests/Rivet/LHC/LHC-8-Jets-10.in @@ -1,6 +1,12 @@ # ATLAS tracks in jets insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1419070 # ATLAS multijet insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1394679 # ATLAS jet charge insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1393758 +# ATLAS transverse energy correlations +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2017_I1609253 +# CMS jets +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2016_I1487277 +# CMS di-jet decorrelation +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2016_I1421646 diff --git a/Tests/Rivet/LHC/LHC-8-Jets-2.in b/Tests/Rivet/LHC/LHC-8-Jets-2.in --- a/Tests/Rivet/LHC/LHC-8-Jets-2.in +++ b/Tests/Rivet/LHC/LHC-8-Jets-2.in @@ -1,4 +1,12 @@ # ATLAS tracks in jets insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1419070 # ATLAS jet charge insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1393758 +# ATLAS transverse energy correlations +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2017_I1609253 +# CMS jets +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2016_I1487277 +# CMS di-jet decorrelation +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2016_I1421646 + + diff --git a/Tests/Rivet/LHC/LHC-8-Jets-3.in b/Tests/Rivet/LHC/LHC-8-Jets-3.in --- a/Tests/Rivet/LHC/LHC-8-Jets-3.in +++ b/Tests/Rivet/LHC/LHC-8-Jets-3.in @@ -1,6 +1,12 @@ # ATLAS tracks in jets insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1419070 # ATLAS multijet insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1394679 # ATLAS jet charge insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1393758 +# ATLAS transverse energy correlations +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2017_I1609253 +# CMS jets +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2016_I1487277 +# CMS di-jet decorrelation +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2016_I1421646 diff --git a/Tests/Rivet/LHC/LHC-8-Jets-4.in b/Tests/Rivet/LHC/LHC-8-Jets-4.in --- a/Tests/Rivet/LHC/LHC-8-Jets-4.in +++ b/Tests/Rivet/LHC/LHC-8-Jets-4.in @@ -1,6 +1,14 @@ # ATLAS tracks in jets insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1419070 # ATLAS multijet insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1394679 # ATLAS jet charge insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1393758 +# ATLAS transverse energy correlations +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2017_I1609253 +# CMS jets +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2016_I1487277 +# CMS di-jet decorrelation +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2016_I1421646 + + diff --git a/Tests/Rivet/LHC/LHC-8-Jets-5.in b/Tests/Rivet/LHC/LHC-8-Jets-5.in --- a/Tests/Rivet/LHC/LHC-8-Jets-5.in +++ b/Tests/Rivet/LHC/LHC-8-Jets-5.in @@ -1,6 +1,14 @@ # ATLAS tracks in jets insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1419070 # ATLAS multijet insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1394679 # ATLAS jet charge insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1393758 +# ATLAS transverse energy correlations +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2017_I1609253 +# CMS jets +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2016_I1487277 +# CMS di-jet decorrelation +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2016_I1421646 + + diff --git a/Tests/Rivet/LHC/LHC-8-Jets-6.in b/Tests/Rivet/LHC/LHC-8-Jets-6.in --- a/Tests/Rivet/LHC/LHC-8-Jets-6.in +++ b/Tests/Rivet/LHC/LHC-8-Jets-6.in @@ -1,6 +1,14 @@ # ATLAS tracks in jets insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1419070 # ATLAS multijet insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1394679 # ATLAS jet charge insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1393758 +# ATLAS transverse energy correlations +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2017_I1609253 +# CMS jets +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2016_I1487277 +# CMS di-jet decorrelation +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2016_I1421646 + + diff --git a/Tests/Rivet/LHC/LHC-8-Jets-7.in b/Tests/Rivet/LHC/LHC-8-Jets-7.in --- a/Tests/Rivet/LHC/LHC-8-Jets-7.in +++ b/Tests/Rivet/LHC/LHC-8-Jets-7.in @@ -1,6 +1,14 @@ # ATLAS tracks in jets insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1419070 # ATLAS multijet insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1394679 # ATLAS jet charge insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1393758 +# ATLAS transverse energy correlations +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2017_I1609253 +# CMS jets +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2016_I1487277 +# CMS di-jet decorrelation +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2016_I1421646 + + diff --git a/Tests/Rivet/LHC/LHC-8-Jets-8.in b/Tests/Rivet/LHC/LHC-8-Jets-8.in --- a/Tests/Rivet/LHC/LHC-8-Jets-8.in +++ b/Tests/Rivet/LHC/LHC-8-Jets-8.in @@ -1,6 +1,12 @@ # ATLAS tracks in jets insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1419070 # ATLAS multijet insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1394679 # ATLAS jet charge insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1393758 +# ATLAS transverse energy correlations +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2017_I1609253 +# CMS jets +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2016_I1487277 +# CMS di-jet decorrelation +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2016_I1421646 diff --git a/Tests/Rivet/LHC/LHC-8-Jets-9.in b/Tests/Rivet/LHC/LHC-8-Jets-9.in --- a/Tests/Rivet/LHC/LHC-8-Jets-9.in +++ b/Tests/Rivet/LHC/LHC-8-Jets-9.in @@ -1,6 +1,14 @@ # ATLAS tracks in jets insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1419070 # ATLAS multijet insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1394679 # ATLAS jet charge insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1393758 +# ATLAS transverse energy correlations +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2017_I1609253 +# CMS jets +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2016_I1487277 +# CMS di-jet decorrelation +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2016_I1421646 + + diff --git a/Tests/Rivet/LHC/LHC-8-PromptPhoton-1.in b/Tests/Rivet/LHC/LHC-8-PromptPhoton-1.in --- a/Tests/Rivet/LHC/LHC-8-PromptPhoton-1.in +++ b/Tests/Rivet/LHC/LHC-8-PromptPhoton-1.in @@ -1,5 +1,7 @@ ################################################## # select the analyses ################################################## # ATLAS prompt photon insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1457605 +# ATLAS prompt photon + heavy flavour +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2017_I1632756 diff --git a/Tests/Rivet/LHC/LHC-8-PromptPhoton-2.in b/Tests/Rivet/LHC/LHC-8-PromptPhoton-2.in --- a/Tests/Rivet/LHC/LHC-8-PromptPhoton-2.in +++ b/Tests/Rivet/LHC/LHC-8-PromptPhoton-2.in @@ -1,5 +1,7 @@ ################################################## # select the analyses ################################################## # ATLAS prompt photon insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1457605 +# ATLAS prompt photon + heavy flavour +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2017_I1632756 diff --git a/Tests/Rivet/LHC/LHC-8-PromptPhoton-3.in b/Tests/Rivet/LHC/LHC-8-PromptPhoton-3.in --- a/Tests/Rivet/LHC/LHC-8-PromptPhoton-3.in +++ b/Tests/Rivet/LHC/LHC-8-PromptPhoton-3.in @@ -1,5 +1,7 @@ ################################################## # select the analyses ################################################## # ATLAS prompt photon insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1457605 +# ATLAS prompt photon + heavy flavour +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2017_I1632756 diff --git a/Tests/Rivet/LHC/LHC-8-PromptPhoton-4.in b/Tests/Rivet/LHC/LHC-8-PromptPhoton-4.in --- a/Tests/Rivet/LHC/LHC-8-PromptPhoton-4.in +++ b/Tests/Rivet/LHC/LHC-8-PromptPhoton-4.in @@ -1,5 +1,7 @@ ################################################## # select the analyses ################################################## # ATLAS prompt photon insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1457605 +# ATLAS prompt photon + heavy flavour +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2017_I1632756 diff --git a/Tests/Rivet/LHC/LHC-8-Top-All.in b/Tests/Rivet/LHC/LHC-8-Top-All.in --- a/Tests/Rivet/LHC/LHC-8-Top-All.in +++ b/Tests/Rivet/LHC/LHC-8-Top-All.in @@ -1,21 +1,5 @@ ################################################## # select the analyses ################################################## -# ATLAS pull in top events -insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1376945 # CMS top insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2015_I1370682 -# ATLAS top + b jet -insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1390114 -# ATLAS boosted t tbar -insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1397637 -# CMS -insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2016_I1473674 -insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2015_I1397174 -# ATLAS l +jets -insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1397635 -insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1404878 -# ATLAS charge asymmetry -insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1449082 -# cms boosted top -insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2016_I1454211 \ No newline at end of file diff --git a/Tests/Rivet/LHC/LHC-8-Top-L.in b/Tests/Rivet/LHC/LHC-8-Top-L.in new file mode 100644 --- /dev/null +++ b/Tests/Rivet/LHC/LHC-8-Top-L.in @@ -0,0 +1,16 @@ +################################################## +# select the analyses +################################################## +# ATLAS top + b jet +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1390114 +# CMS +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2015_I1397174 +# ATLAS l +jets +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1397635 +# ATLAS charge asymmetry +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1449082 +# CMS diplepton charge asym +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2016_I1430892 +# CMS spin correlations +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2016_I1413748 +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1404878 diff --git a/Tests/Rivet/LHC/LHC-8-Top-SL.in b/Tests/Rivet/LHC/LHC-8-Top-SL.in new file mode 100644 --- /dev/null +++ b/Tests/Rivet/LHC/LHC-8-Top-SL.in @@ -0,0 +1,15 @@ +################################################## +# select the analyses +################################################## +# ATLAS pull in top events +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1376945 +# ATLAS top + b jet +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1390114 +# ATLAS boosted t tbar +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1397637 +# cms boosted top +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2016_I1454211 +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2017_I1518399 +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2016_PAS_TOP_15_006 +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1404878 +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2016_I1473674 \ No newline at end of file diff --git a/Tests/Rivet/LHC/LHC-8-ggH-WW.in b/Tests/Rivet/LHC/LHC-8-VBF-WW.in copy from Tests/Rivet/LHC/LHC-8-ggH-WW.in copy to Tests/Rivet/LHC/LHC-8-VBF-WW.in --- a/Tests/Rivet/LHC/LHC-8-ggH-WW.in +++ b/Tests/Rivet/LHC/LHC-8-VBF-WW.in @@ -1,7 +1,9 @@ ################################################## # select the analyses ################################################## -# General analysis +# ATLAS gg -> H -> WW insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1444991 +# CMS H -> WW +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2017_I1467451 do /Herwig/Particles/h0:SelectDecayModes h0->W+,W-; diff --git a/Tests/Rivet/LHC/LHC-8-ggH-WW.in b/Tests/Rivet/LHC/LHC-8-VBF-ZZ.in copy from Tests/Rivet/LHC/LHC-8-ggH-WW.in copy to Tests/Rivet/LHC/LHC-8-VBF-ZZ.in --- a/Tests/Rivet/LHC/LHC-8-ggH-WW.in +++ b/Tests/Rivet/LHC/LHC-8-VBF-ZZ.in @@ -1,7 +1,7 @@ ################################################## # select the analyses ################################################## -# General analysis -insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1444991 +# ATLAS gg -> H -> ZZ +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1310835 -do /Herwig/Particles/h0:SelectDecayModes h0->W+,W-; +do /Herwig/Particles/h0:SelectDecayModes h0->Z0,Z0; diff --git a/Tests/Rivet/LHC/LHC-8-W-mu.in b/Tests/Rivet/LHC/LHC-8-W-mu.in new file mode 100644 --- /dev/null +++ b/Tests/Rivet/LHC/LHC-8-W-mu.in @@ -0,0 +1,5 @@ +################################################## +# select the analyses +################################################## +# CMS W+jets +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2016_I1491953 diff --git a/Tests/Rivet/LHC/LHC-8-ggH-WW.in b/Tests/Rivet/LHC/LHC-8-WH-WW.in copy from Tests/Rivet/LHC/LHC-8-ggH-WW.in copy to Tests/Rivet/LHC/LHC-8-WH-WW.in --- a/Tests/Rivet/LHC/LHC-8-ggH-WW.in +++ b/Tests/Rivet/LHC/LHC-8-WH-WW.in @@ -1,7 +1,9 @@ ################################################## # select the analyses ################################################## -# General analysis +# ATLAS gg -> H -> WW insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1444991 +# CMS H -> WW +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2017_I1467451 do /Herwig/Particles/h0:SelectDecayModes h0->W+,W-; diff --git a/Tests/Rivet/LHC/LHC-8-ggH-WW.in b/Tests/Rivet/LHC/LHC-8-WH-ZZ.in copy from Tests/Rivet/LHC/LHC-8-ggH-WW.in copy to Tests/Rivet/LHC/LHC-8-WH-ZZ.in --- a/Tests/Rivet/LHC/LHC-8-ggH-WW.in +++ b/Tests/Rivet/LHC/LHC-8-WH-ZZ.in @@ -1,7 +1,7 @@ ################################################## # select the analyses ################################################## -# General analysis -insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1444991 +# ATLAS gg -> H -> ZZ +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1310835 -do /Herwig/Particles/h0:SelectDecayModes h0->W+,W-; +do /Herwig/Particles/h0:SelectDecayModes h0->Z0,Z0; diff --git a/Tests/Rivet/LHC/LHC-WZ.in b/Tests/Rivet/LHC/LHC-8-WZ.in copy from Tests/Rivet/LHC/LHC-WZ.in copy to Tests/Rivet/LHC/LHC-8-WZ.in --- a/Tests/Rivet/LHC/LHC-WZ.in +++ b/Tests/Rivet/LHC/LHC-8-WZ.in @@ -1,5 +1,5 @@ ################################################## # select the analyses ################################################## # general analysis -insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_I954993 +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1426523 diff --git a/Tests/Rivet/LHC/LHC-8-ggH-WW.in b/Tests/Rivet/LHC/LHC-8-ZH-WW.in copy from Tests/Rivet/LHC/LHC-8-ggH-WW.in copy to Tests/Rivet/LHC/LHC-8-ZH-WW.in --- a/Tests/Rivet/LHC/LHC-8-ggH-WW.in +++ b/Tests/Rivet/LHC/LHC-8-ZH-WW.in @@ -1,7 +1,9 @@ ################################################## # select the analyses ################################################## -# General analysis +# ATLAS gg -> H -> WW insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1444991 +# CMS H -> WW +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2017_I1467451 do /Herwig/Particles/h0:SelectDecayModes h0->W+,W-; diff --git a/Tests/Rivet/LHC/LHC-8-ggH-WW.in b/Tests/Rivet/LHC/LHC-8-ZH-ZZ.in copy from Tests/Rivet/LHC/LHC-8-ggH-WW.in copy to Tests/Rivet/LHC/LHC-8-ZH-ZZ.in --- a/Tests/Rivet/LHC/LHC-8-ggH-WW.in +++ b/Tests/Rivet/LHC/LHC-8-ZH-ZZ.in @@ -1,7 +1,7 @@ ################################################## # select the analyses ################################################## -# General analysis -insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1444991 +# ATLAS gg -> H -> ZZ +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1310835 -do /Herwig/Particles/h0:SelectDecayModes h0->W+,W-; +do /Herwig/Particles/h0:SelectDecayModes h0->Z0,Z0; diff --git a/Tests/Rivet/LHC/LHC-8-ggH-WW.in b/Tests/Rivet/LHC/LHC-8-ggH-WW.in --- a/Tests/Rivet/LHC/LHC-8-ggH-WW.in +++ b/Tests/Rivet/LHC/LHC-8-ggH-WW.in @@ -1,7 +1,9 @@ ################################################## # select the analyses ################################################## -# General analysis +# ATLAS gg -> H -> WW insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1444991 +# CMS H -> WW +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2017_I1467451 do /Herwig/Particles/h0:SelectDecayModes h0->W+,W-; diff --git a/Tests/Rivet/LHC/LHC-8-ggH-WW.in b/Tests/Rivet/LHC/LHC-8-ggH-ZZ.in copy from Tests/Rivet/LHC/LHC-8-ggH-WW.in copy to Tests/Rivet/LHC/LHC-8-ggH-ZZ.in --- a/Tests/Rivet/LHC/LHC-8-ggH-WW.in +++ b/Tests/Rivet/LHC/LHC-8-ggH-ZZ.in @@ -1,7 +1,7 @@ ################################################## # select the analyses ################################################## -# General analysis -insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1444991 +# ATLAS gg -> H -> ZZ +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1310835 -do /Herwig/Particles/h0:SelectDecayModes h0->W+,W-; +do /Herwig/Particles/h0:SelectDecayModes h0->Z0,Z0; diff --git a/Tests/Rivet/LHC/LHC-900-UE.in b/Tests/Rivet/LHC/LHC-900-UE.in --- a/Tests/Rivet/LHC/LHC-900-UE.in +++ b/Tests/Rivet/LHC/LHC-900-UE.in @@ -1,53 +1,53 @@ ################################################## # select the analyses ################################################## # ATLAS UE insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_S8994773 # ATLAS UE insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8918562 # ATLAS UE insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8894728 # ATLAS charged particles insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8591806 # ALICE charged particles insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ALICE_2010_S8706239 # ALICE charged particles insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ALICE_2010_S8625980 # ALICE charged particles insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ALICE_2010_S8624100 # ALICE particle spectra insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ALICE_2011_S8945144 # ALICE strange particle production insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ALICE_2011_S8909580 # CMS particle spectra insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S8978280 # CMS charged particle multiplicity insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S8884919 # CMS charged particle pT and rapidity insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2010_S8547297 # CMS UE insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S9120041 # LHCB k_s0 insert /Herwig/Analysis/RivetAnalysis:Analyses 0 LHCB_2010_S8758301 # LHCB promt hadron production insert /Herwig/Analysis/RivetAnalysis:Analyses 0 LHCB_2012_I1119400 # CMS forward energy flow insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S9215166 # LHC K0s/Lambda insert /Herwig/Analysis/RivetAnalysis:Analyses 0 LHCB_2011_I917009 # ATLAS Azimuthal ordering of charged hadrons insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1091481 # ALICE single/double diffractive and inelastic sigma insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ALICE_2012_I1181770 # ATLAS inelastic cross section insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_I894867 # underlying event forward rapidities insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1218372 # ATLAS two particle correlation #insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1094061 # ATLAS correlations insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1093734 # ALICE pion and eta pT insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ALICE_2012_I1116147 # CMS charged particle rapidity -insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2010_PAS_QCD_10_024 +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_QCD_10_024 diff --git a/Tests/Rivet/LHC/LHC-W-e.in b/Tests/Rivet/LHC/LHC-W-e.in --- a/Tests/Rivet/LHC/LHC-W-e.in +++ b/Tests/Rivet/LHC/LHC-W-e.in @@ -1,23 +1,25 @@ ################################################## # select the analyses ################################################## # general analysis insert /Herwig/Analysis/RivetAnalysis:Analyses 0 MC_WJETS insert /Herwig/Analysis/RivetAnalysis:Analyses 0 MC_WPOL # ATLAS W+jets insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8919674 # ATLAS W pT insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_I925932 # ATLAS W kT scales insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2013_I1217867 # W DPI insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2013_I1216670 # W +b insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2013_I1219109_EL # ATLAS W insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_I928289_W # ATLAS W+jets insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1319490 insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1319490_EL # ATLAS W+charm -insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1282447 \ No newline at end of file +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1282447 +# ATLAS W inclusive cross section +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1502620_W_EL \ No newline at end of file diff --git a/Tests/Rivet/LHC/LHC-W-mu.in b/Tests/Rivet/LHC/LHC-W-mu.in --- a/Tests/Rivet/LHC/LHC-W-mu.in +++ b/Tests/Rivet/LHC/LHC-W-mu.in @@ -1,27 +1,29 @@ ################################################## # select the analyses ################################################## # ATLAS W asymetry insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_S9002537 # ATLAS W+jets insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8919674 # ATLAS W pT insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_I925932 # ATLAS W+jets insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1083318 # ATLAS W kT scales insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2013_I1217867 # CMS double parton scattering insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1272853 # W DPI insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2013_I1216670 # CMS W+ jets insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2014_I1303894 # ATLAS W insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_I928289_W # ATLAS W+jets insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1319490_MU # W +b insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2013_I1219109_MU # ATLAS W+charm insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1282447 +# ATLAS W inclusive cross section +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1502620_W_MU diff --git a/Tests/Rivet/LHC/LHC-Z-e.in b/Tests/Rivet/LHC/LHC-Z-e.in --- a/Tests/Rivet/LHC/LHC-Z-e.in +++ b/Tests/Rivet/LHC/LHC-Z-e.in @@ -1,32 +1,34 @@ ################################################## # select the analyses ################################################## # General analysis insert /Herwig/Analysis/RivetAnalysis:Analyses 0 MC_ZINC insert /Herwig/Analysis/RivetAnalysis:Analyses 0 MC_ZJETS # ATLAS pT insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_S9131140 insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1300647 # ATLAS Z+jets insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_I945498 insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2013_I1230812 # ATLAS phi* insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1204784 # CMS Z + b-hadron insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1256943 # CMS Z pt and y insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I941555 # ATLAS Z + bjets insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1306294 # ATLAS Z insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_I928289_Z # CMS Z AFB insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1122847 # CMS Z+jets insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2015_I1310737 # ATLAS event shapes in Z events insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1424838 # ATLAS forwrd backward insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1351916_EL # ATLAS forward backward -insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2013_I1234228 \ No newline at end of file +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2013_I1234228 +# ATLAS Z inclusive cross section +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1502620_Z_EL \ No newline at end of file diff --git a/Tests/Rivet/LHC/LHC-Z-mu.in b/Tests/Rivet/LHC/LHC-Z-mu.in --- a/Tests/Rivet/LHC/LHC-Z-mu.in +++ b/Tests/Rivet/LHC/LHC-Z-mu.in @@ -1,33 +1,35 @@ ################################################## # select the analyses ################################################## # ATLAS Z pt insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_S9131140 insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1300647 # ATLAS Z+jets insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_I945498 # ATLAS phi* insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1204784 # Z and real photon + jet insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1258128 # CMS Z + b-hadron insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1256943 # CMS Z pt and y insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I941555 # ATLAS MPI in Z events insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1315949 # ATLAS Z insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_I928289_Z # CMS Z AFB insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1122847 # CMS Z+jets insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2015_I1310737 # ATLAS event shapes in Z events insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1424838 # CMS photon radiation in Z decays insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2015_I1346843 # ATLAS forwrd backward insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1351916_MU # LHCB forward Z+jet insert /Herwig/Analysis/RivetAnalysis:Analyses 0 LHCB_2014_I1262703 +# ATLAS Z inclusive cross section +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1502620_Z_MU diff --git a/Tests/Rivet/TVT/TVT-Run-I-Jets-1.in b/Tests/Rivet/TVT/TVT-Run-I-Jets-1.in --- a/Tests/Rivet/TVT/TVT-Run-I-Jets-1.in +++ b/Tests/Rivet/TVT/TVT-Run-I-Jets-1.in @@ -1,11 +1,13 @@ ################################################## # select the analyses ################################################## # run I CDF di jet insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CDF_2001_S4517016 # run I CDF inclusive jet insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CDF_2001_S4563131 # run I CDF UE insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CDF_2004_S5839831 # run I CDF UE insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CDF_2001_S4751469 +# run I D0 jet shape +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 D0_1995_I398175 \ No newline at end of file diff --git a/Tests/Rivet/TVT/TVT-Run-I-Jets-2.in b/Tests/Rivet/TVT/TVT-Run-I-Jets-2.in --- a/Tests/Rivet/TVT/TVT-Run-I-Jets-2.in +++ b/Tests/Rivet/TVT/TVT-Run-I-Jets-2.in @@ -1,11 +1,13 @@ ################################################## # select the analyses ################################################## # run I CDF di jet insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CDF_2001_S4517016 # run I CDF inclusive jet insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CDF_2001_S4563131 # run I CDF UE insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CDF_2004_S5839831 # run I D0 dijet decorrelation insert /Herwig/Analysis/RivetAnalysis:Analyses 0 D0_1996_S3324664 +# run I D0 jet shape +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 D0_1995_I398175 diff --git a/Tests/Rivet/TVT/TVT-Run-I-Jets-3.in b/Tests/Rivet/TVT/TVT-Run-I-Jets-3.in --- a/Tests/Rivet/TVT/TVT-Run-I-Jets-3.in +++ b/Tests/Rivet/TVT/TVT-Run-I-Jets-3.in @@ -1,9 +1,11 @@ ################################################## # select the analyses ################################################## # run I CDF di jet insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CDF_2001_S4517016 # run I CDF inclusive jet insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CDF_2001_S4563131 # run I CDF UE insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CDF_2004_S5839831 +# run I D0 jet shape +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 D0_1995_I398175 diff --git a/Tests/Rivet/TVT/TVT-Run-I-Jets-4.in b/Tests/Rivet/TVT/TVT-Run-I-Jets-4.in --- a/Tests/Rivet/TVT/TVT-Run-I-Jets-4.in +++ b/Tests/Rivet/TVT/TVT-Run-I-Jets-4.in @@ -1,15 +1,17 @@ ################################################## # select the analyses ################################################## # run I CDF large total ET insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CDF_1998_S3618439 # run I CDF di jet insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CDF_2001_S4517016 # run I CDF inclusive jet insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CDF_2001_S4563131 # run I CDF UE insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CDF_2004_S5839831 # run I coherence insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CDF_1994_S2952106 # run I D0 3 and 4 jets insert /Herwig/Analysis/RivetAnalysis:Analyses 0 D0_1996_S3214044 +# run I D0 jet shape +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 D0_1995_I398175 diff --git a/Tests/Rivet/TVT/TVT-Run-I-Jets-5.in b/Tests/Rivet/TVT/TVT-Run-I-Jets-5.in --- a/Tests/Rivet/TVT/TVT-Run-I-Jets-5.in +++ b/Tests/Rivet/TVT/TVT-Run-I-Jets-5.in @@ -1,17 +1,19 @@ ################################################## # select the analyses ################################################## # run I CDF multijet insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CDF_1996_S3108457 # run I CDF multijet insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CDF_1996_S3349578 # run I CDF 6 jets insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CDF_1997_S3541940 # run I CDF large total ET insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CDF_1998_S3618439 # run I CDF di jet insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CDF_2001_S4517016 # run I CDF inclusive jet insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CDF_2001_S4563131 # run I CDF UE insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CDF_2004_S5839831 +# run I D0 jet shape +insert /Herwig/Analysis/RivetAnalysis:Analyses 0 D0_1995_I398175 diff --git a/Tests/python/make_input_files.py b/Tests/python/make_input_files.py --- a/Tests/python/make_input_files.py +++ b/Tests/python/make_input_files.py @@ -1,1790 +1,1801 @@ #! /usr/bin/env python import logging,sys,os from string import strip, Template import sys if sys.version_info[:3] < (2,4,0): print "rivet scripts require Python version >= 2.4.0... exiting" sys.exit(1) if __name__ == "__main__": import logging from optparse import OptionParser, OptionGroup parser = OptionParser(usage="%prog name [...]") simulation="" numberOfAddedProcesses=0 def addProcess(thefactory,theProcess,Oas,Oew,scale,mergedlegs,NLOprocesses): global numberOfAddedProcesses global simulation numberOfAddedProcesses+=1 res ="set "+thefactory+":OrderInAlphaS "+Oas+"\n" res+="set "+thefactory+":OrderInAlphaEW "+Oew+"\n" res+="do "+thefactory+":Process "+theProcess+" " if ( mergedlegs != 0 ): if simulation!="Merging": print "simulation is not Merging, trying to add merged legs." sys.exit(1) res+="[" for j in range(mergedlegs): res+=" j " res+="]" res+="\n" if (NLOprocesses!=0): if simulation!="Merging": print "simulation is not Merging, trying to add NLOProcesses." sys.exit(1) res+="set MergingFactory:NLOProcesses %s \n" % NLOprocesses if ( scale != "" ): res+="set "+thefactory+":ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/"+scale+"\n" return res def addLeptonPairCut(minmass,maxmass): return "set /Herwig/Cuts/LeptonPairMassCut:MinMass "+minmass+"*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass "+maxmass+"*GeV\n" didaddfirstjet=False def addFirstJet(ptcut): global didaddfirstjet if(didaddfirstjet): logging.error("Can only add jetcut once.") sys.exit(1) res="set /Herwig/Cuts/Cuts:JetFinder /Herwig/Cuts/JetFinder\n" res+="insert /Herwig/Cuts/Cuts:MultiCuts 0 /Herwig/Cuts/JetCuts\n" res+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/FirstJet\n" if(ptcut!=""): res+="set /Herwig/Cuts/FirstJet:PtMin "+ptcut+".*GeV\n" didaddfirstjet=True return res didaddsecondjet=False def addSecondJet(ptcut): global didaddsecondjet if(didaddsecondjet): logging.error("Can only add second jetcut once.") sys.exit(1) res="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n" res+="set /Herwig/Cuts/SecondJet:PtMin "+ptcut+".*GeV\n" didaddsecondjet=True return res didaddjetpair=False def addJetPairCut(minmass): global didaddjetpair if(didaddjetpair): logging.error("Can only add second jetcut once.") sys.exit(1) res="""\ create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass set /Herwig/Cuts/JetPairMass:MassMin {mm}.*GeV """.format(mm=minmass) didaddjetpair=True return res addedBRReweighter=False def addBRReweighter(): global addedBRReweighter if(addedBRReweighter): logging.error("Can only add BRReweighter once.") sys.exit(1) res="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n" res+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n" addedBRReweighter=True return res def setHardProcessWidthToZero(list1): res="" for i in list1: res+="set /Herwig/Particles/"+i+":HardProcessWidth 0.\n" return res selecteddecaymode=False def selectDecayMode(particle,decaymodes): global selecteddecaymode res="do /Herwig/Particles/"+particle+":SelectDecayModes" for decay in decaymodes: res+=" /Herwig/Particles/"+particle+"/"+decay res+="\n" selecteddecaymode=True return res def jet_kt_cut(energy): return "set /Herwig/Cuts/JetKtCut:MinKT {E}*GeV\n".format(E=energy) def mhatmin_cut(energy): return "set /Herwig/Cuts/Cuts:MHatMin {E}*GeV\n".format(E=energy) def mhat_minm_maxm(e1,e2,e3): return """\ set /Herwig/Cuts/Cuts:MHatMin {e1}*GeV set /Herwig/Cuts/MassCut:MinM {e2}*GeV set /Herwig/Cuts/MassCut:MaxM {e3}*GeV """.format(**locals()) def collider_lumi(energy): return "set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy {E}*GeV\n".format(E=energy) def insert_ME(me,process=None,ifname='Process'): result = "insert /Herwig/MatrixElements/SubProcess:MatrixElements 0 /Herwig/MatrixElements/{me}\n".format(**locals()) if process is not None: result += "set /Herwig/MatrixElements/{me}:{ifname} {process}".format(**locals()) return result def particlegroup(name,*particles): result = ["do /Herwig/MatrixElements/Matchbox/Factory:StartParticleGroup {n}".format(n=name)] for p in particles: result.append( "insert /Herwig/MatrixElements/Matchbox/Factory:ParticleGroup 0 /Herwig/Particles/{p}".format(p=p) ) result.append("do /Herwig/MatrixElements/Matchbox/Factory:EndParticleGroup") return '\n'.join(result) # settings for four flavour scheme fourFlavour=""" read Matchbox/FourFlavourScheme.in {bjetgroup} set /Herwig/Cuts/MatchboxJetMatcher:Group bjet """.format(bjetgroup=particlegroup('bjet','b','bbar','c', 'cbar', 's','sbar','d','dbar','u','ubar','g')) ME_Upsilon = """\ create Herwig::MEee2VectorMeson /Herwig/MatrixElements/MEUpsilon HwMELepton.so set /Herwig/MatrixElements/MEUpsilon:VectorMeson /Herwig/Particles/Upsilon(4S) set /Herwig/MatrixElements/MEUpsilon:Coupling 0.0004151809 """ + insert_ME("MEUpsilon") (opts, args) = parser.parse_args() ## Check args if len(args) != 1: logging.error("Must specify at least input file") sys.exit(1) name = args[0] print name # select the template to load # collider KNOWN_COLLIDERS = [ "BFactory", "LEP", "DIS", "TVT", "LHC-GammaGamma", "LHC", "ISR", "SppS", "Star", ] collider = "" for cand_collider in KNOWN_COLLIDERS: if cand_collider in name: collider = cand_collider break del cand_collider assert collider have_hadronic_collider = collider in ["TVT","LHC","ISR","SppS","Star"] thefactory="Factory" parameters = { 'shower' : '', 'bscheme' : '', } # istart determines how many name parts need to be skipped istart = 1 # Dipole shower with Matchbox Powheg if "Dipole-Matchbox-Powheg" in name : istart = 4 simulation="Matchbox" parameters["shower"] = "read Matchbox/Powheg-DipoleShower.in\n" # Dipole shower with internal Powheg - Todo: Finish modifying template files. ''' elif "Dipole-Powheg" in name : istart = 3 simulation="Powheg" - parameters["shower"] = "set /Herwig/EventHandlers/EventHandler:CascadeHandler /Herwig/DipoleShower/DipoleShowerHandler\nread Matchbox/MCatNLO-Dipole-HardAlphaSTune.in\n" + parameters["shower"] = "set /Herwig/EventHandlers/EventHandler:CascadeHandler /Herwig/DipoleShower/DipoleShowerHandler\nread snippets/Dipole_AutoTune_prel.in\n" ''' # Dipole shower with MCatNLO elif "Dipole-MCatNLO" in name : istart = 3 simulation="Matchbox" parameters["shower"] = "read Matchbox/MCatNLO-DipoleShower.in\n" # Dipole shower with Matchbox LO elif "Dipole-Matchbox-LO" in name : istart = 4 simulation="Matchbox" parameters["shower"] = "read Matchbox/LO-DipoleShower.in\n" # Dipole shower with internal LO elif "Dipole" in name : istart = 2 simulation="" - parameters["shower"] = "set /Herwig/EventHandlers/EventHandler:CascadeHandler /Herwig/DipoleShower/DipoleShowerHandler\nread Matchbox/MCatNLO-Dipole-HardAlphaSTune.in\n" + parameters["shower"] = "set /Herwig/EventHandlers/EventHandler:CascadeHandler /Herwig/DipoleShower/DipoleShowerHandler\nread snippets/Dipole_AutoTune_prel.in\n" # AO shower with Matchbox Powheg elif "Matchbox-Powheg" in name : istart = 3 simulation="Matchbox" parameters["shower"] = "read Matchbox/Powheg-DefaultShower.in\n" # AO shower with MCatNLO elif "Matchbox" in name : istart = 2 simulation="Matchbox" parameters["shower"] = "read Matchbox/MCatNLO-DefaultShower.in\n" # AO shower with inernal Powheg elif "Powheg" in name : istart = 2 simulation="Powheg" # Dipole shower with merging elif "Merging" in name : istart = 2 simulation="Merging" thefactory="MergingFactory" # Flavour settings for Matchbox if simulation=="Matchbox" : parameters["bscheme"] = "read Matchbox/FiveFlavourScheme.in\n" if "Dipole" in parameters["shower"] : parameters["bscheme"] += "read Matchbox/FiveFlavourNoBMassScheme.in\n" if collider not in ['DIS','LEP'] : parameters["nlo"] = "read Matchbox/MadGraph-OpenLoops.in\n" # Flavour settings for dipole shower with internal ME if simulation=="" and "Dipole" in parameters["shower"] : parameters["bscheme"] = "read snippets/DipoleShowerFiveFlavours.in" # find the template if simulation=="" : if collider=="LHC-GammaGamma" : istart += 1 templateName="Hadron-Gamma.in" elif have_hadronic_collider : templateName="Hadron.in" elif collider != "BFactory" : templateName= "%s.in" % collider else : templateName= "LEP.in" else : if have_hadronic_collider : templateName= "Hadron-%s.in" % simulation elif collider != "BFactory" : templateName= "%s-%s.in" % (collider,simulation) else : templateName= "LEP-%s.in" % simulation # work out the name of the parameter file parameterName="-".join(name.split("-")[istart:]) del istart class StringBuilder(object): """ Avoid expensive string additions until the end by building up a list first. This helper class avoids rewriting all the += lower down to list operations. """ def __init__(self, init = None): self.lines = [] if init is None else [init] def __iadd__(self, line): self.lines.append(line) return self def __str__(self): return '\n'.join(self.lines) # work out the process and parameters process=StringBuilder() # Bfactory if(collider=="BFactory") : if(simulation=="") : if(parameterName=="10.58-res") : process += ME_Upsilon elif(parameterName=="10.58") : process += ME_Upsilon process += "set /Herwig/MatrixElements/MEee2gZ2qq:MaximumFlavour 4\n" else : process+=insert_ME("MEee2gZ2qq") process+= "set /Herwig/MatrixElements/MEee2gZ2qq:MaximumFlavour 4\n" elif(simulation=="Powheg") : process = StringBuilder("set /Herwig/MatrixElements/PowhegMEee2gZ2qq:MaximumFlavour 4\n") elif(simulation=="Matchbox" ) : process = StringBuilder(addProcess(thefactory,"e- e+ -> u ubar","0","2","",0,0)) process+=addProcess(thefactory,"e- e+ -> d dbar","0","2","",0,0) process+=addProcess(thefactory,"e- e+ -> c cbar","0","2","",0,0) process+=addProcess(thefactory,"e- e+ -> s sbar","0","2","",0,0) elif(simulation=="Merging" ) : logging.warning("BFactory not explicitly tested for %s " % simulation) sys.exit(0) # DIS elif(collider=="DIS") : if(simulation=="") : if "NoME" in parameterName : process = StringBuilder("set /Herwig/Shower/ShowerHandler:HardEmission None") parameterName=parameterName.replace("NoME-","") else : process = StringBuilder("") elif(simulation=="Powheg") : process = StringBuilder("") elif(simulation=="Matchbox" ) : if "e-" in parameterName : process = StringBuilder(addProcess(thefactory,"e- p -> e- j","0","2","",0,0)) else : process = StringBuilder(addProcess(thefactory,"e+ p -> e+ j","0","2","",0,0)) elif(simulation=="Merging" ) : if "e-" in parameterName : process = StringBuilder(addProcess(thefactory,"e- p -> e- j","0","2","",2,2)) else : process = StringBuilder(addProcess(thefactory,"e+ p -> e+ j","0","2","",2,2)) # LEP elif(collider=="LEP") : if(simulation=="") : if "gg" in parameterName : process = StringBuilder("create Herwig::MEee2Higgs2SM /Herwig/MatrixElements/MEee2Higgs2SM\n") process+=insert_ME("MEee2Higgs2SM","Gluon","Allowed") else : process = StringBuilder(insert_ME("MEee2gZ2qq")) if(parameterName=="10") : process+="set /Herwig/MatrixElements/MEee2gZ2qq:MaximumFlavour 4" elif(simulation=="Powheg") : process = StringBuilder() if(parameterName=="10") : process = StringBuilder("set /Herwig/MatrixElements/PowhegMEee2gZ2qq:MaximumFlavour 4") elif(simulation=="Matchbox" ) : if(parameterName=="10") : process = StringBuilder(addProcess(thefactory,"e- e+ -> u ubar","0","2","",0,0)) process+=addProcess(thefactory,"e- e+ -> d dbar","0","2","",0,0) process+=addProcess(thefactory,"e- e+ -> c cbar","0","2","",0,0) process+=addProcess(thefactory,"e- e+ -> s sbar","0","2","",0,0) else : process = StringBuilder(addProcess(thefactory,"e- e+ -> j j","0","2","",0,0)) elif(simulation=="Merging" ) : if(parameterName=="10") : process = StringBuilder(addProcess(thefactory,"e- e+ -> j j","0","2","",2,2)) process+="read Matchbox/FourFlavourScheme.in" else : process = StringBuilder(addProcess(thefactory,"e- e+ -> j j","0","2","",2,2)) # TVT elif(collider=="TVT") : process = StringBuilder("set /Herwig/Generators/EventGenerator:EventHandler:BeamB /Herwig/Particles/pbar-\n") if "Run-II" in parameterName : process+=collider_lumi(1960.0) elif "Run-I" in parameterName : process+=collider_lumi(1800.0) elif "900" in parameterName : process+=collider_lumi(900.0) elif "630" in parameterName : process+=collider_lumi(630.0) elif "300" in parameterName : process+=collider_lumi(300.0) if(simulation=="") : if "PromptPhoton" in parameterName : process+=insert_ME("MEGammaJet") process+="set /Herwig/Cuts/PhotonKtCut:MinKT 15.\n" elif "DiPhoton-GammaGamma" in parameterName : process+=insert_ME("MEGammaGamma") process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n" parameterName=parameterName.replace("-GammaGamma","") elif "DiPhoton-GammaJet" in parameterName : process+=insert_ME("MEGammaJet") process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n" parameterName=parameterName.replace("-GammaJet","") elif "UE" in parameterName : if "Dipole" in parameters["shower"]: process+="read snippets/MB-DipoleShower.in\n" else: process+="read snippets/MB.in\n" process+="read snippets/Diffraction.in\n" process += "set /Herwig/Decays/DecayHandler:LifeTimeOption 0\n" process += "set /Herwig/Decays/DecayHandler:MaxLifeTime 10*mm\n" elif "Jets" in parameterName : process+=insert_ME("MEQCD2to2") process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n" if "Run-II-Jets-10" in parameterName : process+=jet_kt_cut( 30.)+mhatmin_cut(500.) elif "Run-II-Jets-11" in parameterName: process+=jet_kt_cut( 30.)+mhatmin_cut(900.) elif "Run-I-Jets-1" in parameterName : process+=jet_kt_cut( 20.) elif "Run-I-Jets-2" in parameterName : process+=jet_kt_cut( 40.) elif "Run-I-Jets-3" in parameterName : process+=jet_kt_cut( 65.) elif "Run-I-Jets-4" in parameterName : process+=jet_kt_cut( 90.) elif "Run-I-Jets-5" in parameterName : process+=jet_kt_cut(160.) elif "Run-I-Jets-6" in parameterName : process+=jet_kt_cut( 30.)+mhatmin_cut(100.) elif "Run-I-Jets-7" in parameterName : process+=jet_kt_cut( 30.)+mhatmin_cut(400.) elif "Run-I-Jets-8" in parameterName : process+=jet_kt_cut( 30.)+mhatmin_cut(700.) elif "Run-II-Jets-0" in parameterName : process+=jet_kt_cut( 15.) elif "Run-II-Jets-1" in parameterName : process+=jet_kt_cut( 25.) elif "Run-II-Jets-2" in parameterName : process+=jet_kt_cut( 40.) elif "Run-II-Jets-3" in parameterName : process+=jet_kt_cut( 60.) elif "Run-II-Jets-4" in parameterName : process+=jet_kt_cut( 85.) elif "Run-II-Jets-5" in parameterName : process+=jet_kt_cut(110.) elif "Run-II-Jets-6" in parameterName : process+=jet_kt_cut(160.) elif "Run-II-Jets-7" in parameterName : process+=jet_kt_cut(250.) elif "Run-II-Jets-8" in parameterName : process+=jet_kt_cut( 30.)+mhatmin_cut(100.) elif "Run-II-Jets-9" in parameterName : process+=jet_kt_cut( 30.)+mhatmin_cut(300.) elif "900-Jets-1" in parameterName : process+=jet_kt_cut( 10.) elif "300-Jets-1" in parameterName : process+=jet_kt_cut( 6.) elif "630-Jets-1" in parameterName : process+=jet_kt_cut( 20.) elif "630-Jets-2" in parameterName : process+=jet_kt_cut( 40.) elif "630-Jets-3" in parameterName : process+=jet_kt_cut( 75.) elif "900-Jets-1" in parameterName : process+=jet_kt_cut( 10.) elif "Run-I-WZ" in parameterName : process+=insert_ME("MEqq2W2ff","Electron") process+=insert_ME("MEqq2gZ2ff","Electron") elif "Run-II-W" in parameterName or "Run-I-W" in parameterName : process+=insert_ME("MEqq2W2ff","Electron") elif "Run-II-Z-e" in parameterName or "Run-I-Z" in parameterName : process +=insert_ME("MEqq2gZ2ff","Electron") elif "Run-II-Z-LowMass-mu" in parameterName : process +=insert_ME("MEqq2gZ2ff","Muon") process+=addLeptonPairCut("25","70") elif "Run-II-Z-HighMass-mu" in parameterName : process +=insert_ME("MEqq2gZ2ff","Muon") process+=addLeptonPairCut("150","600") elif "Run-II-Z-mu" in parameterName : process +=insert_ME("MEqq2gZ2ff","Muon") elif(simulation=="Powheg") : if "Run-I-WZ" in parameterName : process+=insert_ME("PowhegMEqq2W2ff","Electron") process+=insert_ME("PowhegMEqq2gZ2ff","Electron") elif "Run-II-W" in parameterName or "Run-I-W" in parameterName : process+=insert_ME("PowhegMEqq2W2ff","Electron") elif "Run-II-Z-e" in parameterName or "Run-I-Z" in parameterName : process+=insert_ME("PowhegMEqq2gZ2ff","Electron") elif "Run-II-Z-LowMass-mu" in parameterName : process+=insert_ME("PowhegMEqq2gZ2ff","Muon") process+=addLeptonPairCut("25","70") elif "Run-II-Z-HighMass-mu" in parameterName : process+=insert_ME("PowhegMEqq2gZ2ff","Muon") process+=addLeptonPairCut("150","600") elif "Run-II-Z-mu" in parameterName : process+=insert_ME("PowhegMEqq2gZ2ff","Muon") elif "DiPhoton-GammaGamma" in parameterName : process+=insert_ME("MEGammaGammaPowheg","GammaGamma") process+=insert_ME("MEGammaGamma","gg") process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n" process+=jet_kt_cut(5.) parameterName=parameterName.replace("-GammaGamma","") elif "DiPhoton-GammaJet" in parameterName : process+=insert_ME("MEGammaGammaPowheg","VJet") process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n" process+=jet_kt_cut(5.) parameterName=parameterName.replace("-GammaJet","") elif(simulation=="Matchbox" or simulation=="Merging" ) : if "Jets" in parameterName : if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p -> j j","2","0","MaxJetPtScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p p -> j j","2","0","MaxJetPtScale",1,0) process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n" if "Run-II-Jets-10" in parameterName : process+=addFirstJet("30") process+=addSecondJet("25") process+=addJetPairCut("500") elif "Run-II-Jets-11" in parameterName : process+=addFirstJet("30") process+=addSecondJet("25") process+=addJetPairCut("900") elif "Run-II-Jets-12" in parameterName : process+=addFirstJet("30") process+=addSecondJet("25") process+=addJetPairCut("300") elif "Run-I-Jets-1" in parameterName : process+=addFirstJet("20") elif "Run-I-Jets-2" in parameterName : process+=addFirstJet("40") elif "Run-I-Jets-3" in parameterName : process+=addFirstJet("65") elif "Run-I-Jets-4" in parameterName : process+=addFirstJet("90") elif "Run-I-Jets-5" in parameterName : process+=addFirstJet("160") elif "Run-I-Jets-6" in parameterName : process+=addFirstJet("30")+addSecondJet("25")+addJetPairCut("100") elif "Run-I-Jets-7" in parameterName : process+=addFirstJet("30")+addSecondJet("25")+addJetPairCut("400") elif "Run-I-Jets-8" in parameterName : process+=addFirstJet("30")+addSecondJet("25")+addJetPairCut("700") elif "Run-II-Jets-0" in parameterName : process+=addFirstJet("15") elif "Run-II-Jets-1" in parameterName : process+=addFirstJet("25") elif "Run-II-Jets-2" in parameterName : process+=addFirstJet("40") elif "Run-II-Jets-3" in parameterName : process+=addFirstJet("60") elif "Run-II-Jets-4" in parameterName : process+=addFirstJet("85") elif "Run-II-Jets-5" in parameterName : process+=addFirstJet("110") elif "Run-II-Jets-6" in parameterName : process+=addFirstJet("160") elif "Run-II-Jets-7" in parameterName : process+=addFirstJet("250") elif "Run-II-Jets-8" in parameterName : process+=addFirstJet("30")+addSecondJet("25")+addJetPairCut("100") elif "Run-II-Jets-9" in parameterName : process+=addFirstJet("30")+addSecondJet("25")+addJetPairCut("300") elif "900-Jets-1" in parameterName : process+=addFirstJet("10") elif "300-Jets-1" in parameterName : process+=addFirstJet("6") elif "630-Jets-1" in parameterName : process+=addFirstJet("20") elif "630-Jets-2" in parameterName : process+=addFirstJet("40") elif "630-Jets-3" in parameterName : process+=addFirstJet("75") elif "900-Jets-1" in parameterName : process+=addFirstJet("10") else : logging.error("Exit 00007") sys.exit(1) elif "Run-I-WZ" in parameterName : if(simulation=="Matchbox"): process+=addProcess(thefactory,"p pbar e+ e-","0","2","LeptonPairMassScale",0,0) process+=addProcess(thefactory,"p pbar e+ nu","0","2","LeptonPairMassScale",0,0) process+=addProcess(thefactory,"p pbar e- nu","0","2","LeptonPairMassScale",0,0) elif(simulation=="Merging"): process+=particlegroup('epm','e+','e-') process+=particlegroup('epmnu','e+','e-','nu_e','nu_ebar') process+=addProcess(thefactory,"p pbar epm epmnu","0","2","LeptonPairMassScale",2,2) process+=addLeptonPairCut("60","120") elif "Run-II-W" in parameterName or "Run-I-W" in parameterName : if(simulation=="Matchbox"): process+=addProcess(thefactory,"p pbar e+ nu","0","2","LeptonPairMassScale",0,0) process+=addProcess(thefactory,"p pbar e- nu","0","2","LeptonPairMassScale",0,0) elif(simulation=="Merging"): process+=particlegroup('epm','e+','e-') process+=addProcess(thefactory,"p pbar epm nu","0","2","LeptonPairMassScale",2,2) process+=addLeptonPairCut("60","120") elif "Run-II-Z-e" in parameterName or "Run-I-Z" in parameterName : if(simulation=="Matchbox"): process+=addProcess(thefactory,"p pbar e+ e-","0","2","LeptonPairMassScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p pbar e+ e-","0","2","LeptonPairMassScale",2,2) process+=addLeptonPairCut("60","120") elif "Run-II-Z-LowMass-mu" in parameterName : if(simulation=="Matchbox"): process+=addProcess(thefactory,"p pbar mu+ mu-","0","2","LeptonPairMassScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p pbar mu+ mu-","0","2","LeptonPairMassScale",2,2) process+=addLeptonPairCut("25","70") elif "Run-II-Z-HighMass-mu" in parameterName : if(simulation=="Matchbox"): process+=addProcess(thefactory,"p pbar mu+ mu-","0","2","LeptonPairMassScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p pbar mu+ mu-","0","2","LeptonPairMassScale",2,2) process+=addLeptonPairCut("150","600") elif "Run-II-Z-mu" in parameterName : if(simulation=="Matchbox"): process+=addProcess(thefactory,"p pbar mu+ mu-","0","2","LeptonPairMassScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p pbar mu+ mu-","0","2","LeptonPairMassScale",2,2) process+=addLeptonPairCut("60","120") # Star elif(collider=="Star" ) : process = StringBuilder("set /Herwig/Decays/DecayHandler:LifeTimeOption 0\n") process+= "set /Herwig/Decays/DecayHandler:MaxLifeTime 10*mm\n" process+= "set /Herwig/Generators/EventGenerator:EventHandler:BeamB /Herwig/Particles/p+\n" process+= collider_lumi(200.0) process+= "set /Herwig/Cuts/Cuts:X2Min 0.01\n" if(simulation=="") : if "UE" in parameterName : if "Dipole" in parameters["shower"]: process+="read snippets/MB-DipoleShower.in\n" else: process+="read snippets/MB.in\n" process+="read snippets/Diffraction.in\n" else : process+=insert_ME("MEQCD2to2") process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n" if "Jets-1" in parameterName : process+=jet_kt_cut(2.) elif "Jets-2" in parameterName : process+=jet_kt_cut(5.) elif "Jets-3" in parameterName : process+=jet_kt_cut(20.) elif "Jets-4" in parameterName : process+=jet_kt_cut(25.) else : logging.error("Star not supported for %s " % simulation) sys.exit(1) # ISR and SppS elif(collider=="ISR" or collider =="SppS" ) : process = StringBuilder("set /Herwig/Decays/DecayHandler:LifeTimeOption 0\n") process+="set /Herwig/Decays/DecayHandler:MaxLifeTime 10*mm\n" if(collider=="SppS") : process = StringBuilder("set /Herwig/Generators/EventGenerator:EventHandler:BeamB /Herwig/Particles/pbar-\n") if "30" in parameterName : process+=collider_lumi( 30.4) elif "44" in parameterName : process+=collider_lumi( 44.4) elif "53" in parameterName : process+=collider_lumi( 53.0) elif "62" in parameterName : process+=collider_lumi( 62.2) elif "63" in parameterName : process+=collider_lumi( 63.0) elif "200" in parameterName : process+=collider_lumi(200.0) elif "500" in parameterName : process+=collider_lumi(500.0) elif "546" in parameterName : process+=collider_lumi(546.0) elif "900" in parameterName : process+=collider_lumi(900.0) if(simulation=="") : if "Dipole" in parameters["shower"]: process+="read snippets/MB-DipoleShower.in\n" else: process+="read snippets/MB.in\n" process+="read snippets/Diffraction.in\n" else : logging.error(" SppS and ISR not supported for %s " % simulation) sys.exit(1) # LHC elif(collider=="LHC") : if parameterName.startswith("7-") : process = StringBuilder(collider_lumi(7000.0)) elif parameterName.startswith("8-") : process = StringBuilder(collider_lumi(8000.0)) elif parameterName.startswith("13-") : process = StringBuilder(collider_lumi(13000.0)) elif parameterName.startswith("900") : process = StringBuilder(collider_lumi(900.0)) elif parameterName.startswith("2360") : process = StringBuilder(collider_lumi(2360.0)) elif parameterName.startswith("2760") : process = StringBuilder(collider_lumi(2760.0)) else : process = StringBuilder(collider_lumi(7000.0)) if(simulation=="") : if "8-VBF" in parameterName : process+=insert_ME("MEPP2HiggsVBF") elif "VBF" in parameterName : process+=selectDecayMode("h0",["h0->tau-,tau+;"]) process+=addBRReweighter() process+="set /Herwig/Particles/tau-:Stable Stable\n" process+=insert_ME("MEPP2HiggsVBF") elif "ggHJet" in parameterName : process+=selectDecayMode("h0",["h0->tau-,tau+;"]) process+=addBRReweighter() process+="set /Herwig/Particles/tau-:Stable Stable\n" process+=insert_ME("MEHiggsJet") process+=jet_kt_cut(20.) elif "8-ggH" in parameterName : process+=insert_ME("MEHiggs") process+=insert_ME("MEHiggsJet","qqbar") process+=jet_kt_cut(0.0) elif "ggH" in parameterName : process+=selectDecayMode("h0",["h0->tau-,tau+;"]) process+=addBRReweighter() process+="set /Herwig/Particles/tau-:Stable Stable\n" process+=insert_ME("MEHiggs") process+=insert_ME("MEHiggsJet","qqbar") process+=jet_kt_cut(0.0) elif "PromptPhoton" in parameterName : process+=insert_ME("MEGammaJet") if "PromptPhoton-1" in parameterName : process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n" elif "PromptPhoton-2" in parameterName : process+="set /Herwig/Cuts/PhotonKtCut:MinKT 25.\n" elif "PromptPhoton-3" in parameterName : process+="set /Herwig/Cuts/PhotonKtCut:MinKT 80.\n" elif "PromptPhoton-4" in parameterName : process+="set /Herwig/Cuts/PhotonKtCut:MinKT 150.\n" elif "DiPhoton-GammaGamma" in parameterName : process+=insert_ME("MEGammaGamma") process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n" parameterName=parameterName.replace("-GammaGamma","") elif "DiPhoton-GammaJet" in parameterName : process+=insert_ME("MEGammaJet") process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n" parameterName=parameterName.replace("-GammaJet","") elif "8-WH" in parameterName : process+=insert_ME("MEPP2WH") process+=jet_kt_cut(0.0) elif "8-ZH" in parameterName : process+=insert_ME("MEPP2ZH") process+=jet_kt_cut(0.0) elif "WH" in parameterName : process+=selectDecayMode("h0",["h0->b,bbar;"]) process+=selectDecayMode("W+",["W+->nu_e,e+;", "W+->nu_mu,mu+;"]) process+=addBRReweighter() process+=insert_ME("MEPP2WH") process+=jet_kt_cut(0.0) elif "ZH" in parameterName : process+=selectDecayMode("h0",["h0->b,bbar;"]) process+=selectDecayMode("Z0",["Z0->e-,e+;", "Z0->mu-,mu+;"]) process+=addBRReweighter() process+=insert_ME("MEPP2ZH") process+=jet_kt_cut(0.0) elif "UE" in parameterName : if "Dipole" in parameters["shower"]: process+="read snippets/MB-DipoleShower.in\n" else: process+="set /Herwig/Shower/ShowerHandler:IntrinsicPtGaussian 2.2*GeV\n" process+="read snippets/MB.in\n" process+="read snippets/Diffraction.in\n" if "Long" in parameterName : process += "set /Herwig/Decays/DecayHandler:MaxLifeTime 100*mm\n" elif "8-DiJets" in parameterName or "7-DiJets" in parameterName : process+=insert_ME("MEQCD2to2") process+="set MEQCD2to2:MaximumFlavour 5\n" process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n" if "-A" in parameterName : process+=jet_kt_cut(45.) process+="set /Herwig/Cuts/JetKtCut:MinEta -3.\n" process+="set /Herwig/Cuts/JetKtCut:MaxEta 3.\n" elif "-B" in parameterName : process+=jet_kt_cut(20.) process+="set /Herwig/Cuts/JetKtCut:MinEta -2.7\n" process+="set /Herwig/Cuts/JetKtCut:MaxEta 2.7\n" elif "-C" in parameterName : process+=jet_kt_cut(20.) process+="set /Herwig/Cuts/JetKtCut:MinEta -4.8\n" process+="set /Herwig/Cuts/JetKtCut:MaxEta 4.8\n" if "DiJets-1" in parameterName : process+=mhatmin_cut(90.) elif "DiJets-2" in parameterName : process+=mhatmin_cut(200.) elif "DiJets-3" in parameterName : process+=mhatmin_cut(450.) elif "DiJets-4" in parameterName : process+=mhatmin_cut(750.) elif "DiJets-5" in parameterName : process+=mhatmin_cut(950.) elif "DiJets-6" in parameterName : process+=mhatmin_cut(1550.) elif "DiJets-7" in parameterName : process+=mhatmin_cut(2150.) elif "DiJets-8" in parameterName : process+=mhatmin_cut(2750.) elif( "7-Jets" in parameterName or "8-Jets" in parameterName or "13-Jets" in parameterName ) : process+=insert_ME("MEQCD2to2") process+="set MEQCD2to2:MaximumFlavour 5\n" process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n" if "Jets-10" in parameterName : process+=jet_kt_cut(1800.) elif "Jets-0" in parameterName : process+=jet_kt_cut(5.) elif "Jets-1" in parameterName : process+=jet_kt_cut(10.) elif "Jets-2" in parameterName : process+=jet_kt_cut(20.) elif "Jets-3" in parameterName : process+=jet_kt_cut(40.) elif "Jets-4" in parameterName : process+=jet_kt_cut(70.) elif "Jets-5" in parameterName : process+=jet_kt_cut(150.) elif "Jets-6" in parameterName : process+=jet_kt_cut(200.) elif "Jets-7" in parameterName : process+=jet_kt_cut(300.) elif "Jets-8" in parameterName : process+=jet_kt_cut(500.) elif "Jets-9" in parameterName : process+=jet_kt_cut(800.) elif("7-Charm" in parameterName or "7-Bottom" in parameterName) : if "7-Bottom" in parameterName : process+="cp MEHeavyQuark MEBottom\n" process+="set MEBottom:QuarkType Bottom\n" process+=insert_ME("MEBottom") else : process+="cp MEHeavyQuark MECharm\n" process+="set MECharm:QuarkType Charm\n" process+=insert_ME("MECharm") process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n" if "-0" in parameterName : if "7-Bottom" in parameterName : process+="set MEBottom:Process Pair\n" process+=jet_kt_cut(0.) elif "-1" in parameterName : process+=jet_kt_cut(5.) elif "-2" in parameterName : process+=jet_kt_cut(20.) elif "-3" in parameterName : process+=jet_kt_cut(50.) elif "-4" in parameterName : process+=jet_kt_cut(80.) elif "-5" in parameterName : process+=jet_kt_cut(110.) elif "-6" in parameterName : process+=jet_kt_cut(30.)+mhatmin_cut(90.) elif "-7" in parameterName : process+=jet_kt_cut(30.)+mhatmin_cut(340.) elif "-8" in parameterName : process+=jet_kt_cut(30.)+mhatmin_cut(500.) elif "Top-L" in parameterName : process+="set MEHeavyQuark:QuarkType Top\n" process+=insert_ME("MEHeavyQuark") process+=selectDecayMode("t",["t->nu_e,e+,b;", "t->nu_mu,mu+,b;"]) process+=addBRReweighter() elif "Top-SL" in parameterName : process+="set MEHeavyQuark:QuarkType Top\n" process+=insert_ME("MEHeavyQuark") process+="set /Herwig/Particles/t:Synchronized Not_synchronized\n" process+="set /Herwig/Particles/tbar:Synchronized Not_synchronized\n" process+=selectDecayMode("t",["t->nu_e,e+,b;","t->nu_mu,mu+,b;"]) process+=selectDecayMode("tbar",["tbar->b,bbar,cbar;", "tbar->bbar,cbar,d;", "tbar->bbar,cbar,s;", "tbar->bbar,s,ubar;", "tbar->bbar,ubar,d;"]) process+=addBRReweighter() elif "Top-All" in parameterName : process+="set MEHeavyQuark:QuarkType Top\n" process+=insert_ME("MEHeavyQuark") elif "WZ" in parameterName : process+=insert_ME("MEPP2VV","WZ") process+=selectDecayMode("W+",["W+->nu_e,e+;", "W+->nu_mu,mu+;"]) process+=selectDecayMode("W-",["W-->nu_ebar,e-;", "W-->nu_mubar,mu-;"]) process+=selectDecayMode("Z0",["Z0->e-,e+;", "Z0->mu-,mu+;"]) process+=addBRReweighter() elif "WW-emu" in parameterName : process+=insert_ME("MEPP2VV","WW") process+="set /Herwig/Particles/W+:Synchronized 0\n" process+="set /Herwig/Particles/W-:Synchronized 0\n" process+=selectDecayMode("W+",["W+->nu_e,e+;"]) process+=selectDecayMode("W-",["W-->nu_mubar,mu-;"]) process+=addBRReweighter() elif "WW-ll" in parameterName : process+=insert_ME("MEPP2VV","WW") process+=selectDecayMode("W+",["W+->nu_e,e+;","W+->nu_mu,mu+;","W+->nu_tau,tau+;"]) process+=addBRReweighter() elif "ZZ-ll" in parameterName : process+=insert_ME("MEPP2VV","ZZ") process+=selectDecayMode("Z0",["Z0->e-,e+;", "Z0->mu-,mu+;", "Z0->tau-,tau+;"]) process+=addBRReweighter() elif "ZZ-lv" in parameterName : process+=insert_ME("MEPP2VV","ZZ") process+=selectDecayMode("Z0",["Z0->e-,e+;", "Z0->mu-,mu+;", "Z0->tau-,tau+;", "Z0->nu_e,nu_ebar;", "Z0->nu_mu,nu_mubar;", "Z0->nu_tau,nu_taubar;"]) process+=addBRReweighter() elif "W-Z-e" in parameterName : process+=insert_ME("MEqq2gZ2ff","Electron") process+=insert_ME("MEqq2W2ff","Electron") - elif "W-Z-mu" in parameterName : process+=insert_ME("MEqq2gZ2ff","Muon") process+=insert_ME("MEqq2W2ff","Muon") elif "W-e" in parameterName : process+=insert_ME("MEqq2W2ff","Electron") elif "W-mu" in parameterName : process+=insert_ME("MEqq2W2ff","Muon") elif "Z-e" in parameterName : process+=insert_ME("MEqq2gZ2ff","Electron") elif "Z-mu" in parameterName : process+=insert_ME("MEqq2gZ2ff","Muon") elif "Z-LowMass-e" in parameterName : process+=insert_ME("MEqq2gZ2ff","Electron") process+=mhat_minm_maxm(20,20,70) elif "Z-MedMass-e" in parameterName : process+=insert_ME("MEqq2gZ2ff","Electron") process+=mhat_minm_maxm(40,40,130) elif "Z-LowMass-mu" in parameterName : process+=insert_ME("MEqq2gZ2ff","Muon") process+=mhat_minm_maxm(10,10,70) elif "Z-Mass1" in parameterName : process+=mhat_minm_maxm(10,10,35) if "-e" in parameterName : process+=insert_ME("MEqq2gZ2ff","Electron") else : process+=insert_ME("MEqq2gZ2ff","Muon") elif "Z-Mass2" in parameterName : process+=mhat_minm_maxm(25,25,70) if "-e" in parameterName : process+=insert_ME("MEqq2gZ2ff","Electron") else : process+=insert_ME("MEqq2gZ2ff","Muon") elif "Z-Mass3" in parameterName : process+=mhat_minm_maxm(60,60,120) if "-e" in parameterName : process+=insert_ME("MEqq2gZ2ff","Electron") else : process+=insert_ME("MEqq2gZ2ff","Muon") elif "Z-Mass4" in parameterName : process+=mhat_minm_maxm(110,110,8000) if "-e" in parameterName : process+=insert_ME("MEqq2gZ2ff","Electron") else : process+=insert_ME("MEqq2gZ2ff","Muon") elif "Z-HighMass1" in parameterName : process+=mhat_minm_maxm(116,116,400) if "-e" in parameterName : process+=insert_ME("MEqq2gZ2ff","Electron") else : process+=insert_ME("MEqq2gZ2ff","Muon") elif "Z-HighMass2" in parameterName : process+=mhat_minm_maxm(400,400,7000) if "-e" in parameterName : process+=insert_ME("MEqq2gZ2ff","Electron") else : process+=insert_ME("MEqq2gZ2ff","Muon") elif "W-Jet" in parameterName : process+=insert_ME("MEWJet","Electron","WDecay") if "W-Jet-1-e" in parameterName : process+="set /Herwig/Cuts/WBosonKtCut:MinKT 100.0*GeV\n" parameterName=parameterName.replace("W-Jet-1-e","W-Jet-e") elif "W-Jet-2-e" in parameterName : process+="set /Herwig/Cuts/WBosonKtCut:MinKT 190.0*GeV\n" parameterName=parameterName.replace("W-Jet-2-e","W-Jet-e") elif "W-Jet-3-e" in parameterName : process+="set /Herwig/Cuts/WBosonKtCut:MinKT 270.0*GeV\n" parameterName=parameterName.replace("W-Jet-3-e","W-Jet-e") elif "Z-Jet" in parameterName : if "-e" in parameterName : process+=insert_ME("MEZJet","Electron","ZDecay") if "Z-Jet-0-e" in parameterName : process+="set /Herwig/Cuts/ZBosonKtCut:MinKT 35.0*GeV\n" parameterName=parameterName.replace("Z-Jet-0-e","Z-Jet-e") elif "Z-Jet-1-e" in parameterName : process+="set /Herwig/Cuts/ZBosonKtCut:MinKT 100.0*GeV\n" parameterName=parameterName.replace("Z-Jet-1-e","Z-Jet-e") elif "Z-Jet-2-e" in parameterName : process+="set /Herwig/Cuts/ZBosonKtCut:MinKT 190.0*GeV\n" parameterName=parameterName.replace("Z-Jet-2-e","Z-Jet-e") elif "Z-Jet-3-e" in parameterName : process+="set /Herwig/Cuts/ZBosonKtCut:MinKT 270.0*GeV\n" parameterName=parameterName.replace("Z-Jet-3-e","Z-Jet-e") else : process+=insert_ME("MEZJet","Muon","ZDecay") process+="set /Herwig/Cuts/ZBosonKtCut:MinKT 35.0*GeV\n" parameterName=parameterName.replace("Z-Jet-0-mu","Z-Jet-mu") elif "WGamma" in parameterName : process+=insert_ME("MEPP2VGamma","1") process+="set MEPP2VGamma:MassOption 1" process+="set /Herwig/Cuts/PhotonKtCut:MinKT 10.\n" if "-e" in parameterName : process+=selectDecayMode("W+",["W+->nu_e,e+;"]) process+=addBRReweighter() else : process+=selectDecayMode("W+",["W+->nu_mu,mu+;"]) process+=addBRReweighter() elif "ZGamma" in parameterName : process+=insert_ME("MEPP2VGamma","2") process+="set /Herwig/Cuts/PhotonKtCut:MinKT 10.\n" if "-e" in parameterName : process+=selectDecayMode("Z0",["Z0->e-,e+;"]) process+=addBRReweighter() else : process+=selectDecayMode("Z0",["Z0->mu-,mu+;"]) process+=addBRReweighter() else : logging.error(" Process %s not supported for internal matrix elements" % name) sys.exit(1) elif(simulation=="Powheg") : if "8-VBF" in parameterName : process+=insert_ME("PowhegMEPP2HiggsVBF") elif "VBF" in parameterName : process+=selectDecayMode("h0",["h0->tau-,tau+;"]) process+=addBRReweighter() process+="set /Herwig/Particles/tau-:Stable Stable\n" process+=insert_ME("PowhegMEPP2HiggsVBF") elif "ggHJet" in parameterName : logging.error(" Process %s not supported for POWHEG matrix elements" % name) sys.exit(1) elif "8-ggH" in parameterName : process+=insert_ME("PowhegMEHiggs") elif "ggH" in parameterName : process+=selectDecayMode("h0",["h0->tau-,tau+;"]) process+=addBRReweighter() process+="set /Herwig/Particles/tau-:Stable Stable\n" process+=insert_ME("PowhegMEHiggs") elif "8-WH" in parameterName : process+=insert_ME("PowhegMEPP2WH") process+=jet_kt_cut(0.0) elif "8-ZH" in parameterName : process+=insert_ME("PowhegMEPP2ZH") process+=jet_kt_cut(0.0) elif "WH" in parameterName : process+=selectDecayMode("h0",["h0->b,bbar;"]) process+=selectDecayMode("W+",["W+->nu_e,e+;", "W+->nu_mu,mu+;"]) process+=addBRReweighter() process+=insert_ME("PowhegMEPP2WH") process+=jet_kt_cut(0.0) elif "ZH" in parameterName : process+=selectDecayMode("h0",["h0->b,bbar;"]) process+=selectDecayMode("Z0",["Z0->e-,e+;", "Z0->mu-,mu+;"]) process+=addBRReweighter() process+=insert_ME("PowhegMEPP2ZH") process+=jet_kt_cut(0.0) elif "UE" in parameterName : logging.error(" Process %s not supported for powheg matrix elements" % name) sys.exit(1) elif "WZ" in parameterName : process+="create Herwig::HwDecayHandler /Herwig/NewPhysics/DecayHandler\n" process+="set /Herwig/NewPhysics/DecayHandler:NewStep No\n" process+="set /Herwig/Shower/ShowerHandler:SplitHardProcess No\n"; process+="set /Herwig/Decays/ZDecayer:PhotonGenerator NULL\n"; process+="set /Herwig/Decays/ZPowhegDecayer:PhotonGenerator NULL\n"; process+="set /Herwig/Decays/WDecayer:PhotonGenerator NULL\n"; process+="set /Herwig/Decays/WPowhegDecayer:PhotonGenerator NULL\n"; process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 0 /Herwig/Particles/tau-\n" process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 1 /Herwig/Particles/tau+\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PreCascadeHandlers 0 /Herwig/NewPhysics/DecayHandler\n" process+=insert_ME("PowhegMEPP2VV","WZ") process+=selectDecayMode("W+",["W+->nu_e,e+;", "W+->nu_mu,mu+;"]) process+=selectDecayMode("W-",["W-->nu_ebar,e-;", "W-->nu_mubar,mu-;"]) process+=selectDecayMode("Z0",["Z0->e-,e+;", "Z0->mu-,mu+;"]) process+=addBRReweighter() elif "WW-emu" in parameterName : process+="create Herwig::HwDecayHandler /Herwig/NewPhysics/DecayHandler\n" process+="set /Herwig/NewPhysics/DecayHandler:NewStep No\n" process+="set /Herwig/Shower/ShowerHandler:SplitHardProcess No\n"; process+="set /Herwig/Decays/ZDecayer:PhotonGenerator NULL\n"; process+="set /Herwig/Decays/ZPowhegDecayer:PhotonGenerator NULL\n"; process+="set /Herwig/Decays/WDecayer:PhotonGenerator NULL\n"; process+="set /Herwig/Decays/WPowhegDecayer:PhotonGenerator NULL\n"; process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 0 /Herwig/Particles/tau-\n" process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 1 /Herwig/Particles/tau+\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PreCascadeHandlers 0 /Herwig/NewPhysics/DecayHandler\n" process+=insert_ME("PowhegMEPP2VV","WW") process+="set /Herwig/Particles/W+:Synchronized 0\n" process+="set /Herwig/Particles/W-:Synchronized 0\n" process+=selectDecayMode("W+",["W+->nu_e,e+;"]) process+=selectDecayMode("W-",["W-->nu_mubar,mu-;"]) process+=addBRReweighter() elif "WW-ll" in parameterName : process+="create Herwig::HwDecayHandler /Herwig/NewPhysics/DecayHandler\n" process+="set /Herwig/NewPhysics/DecayHandler:NewStep No\n" process+="set /Herwig/Shower/ShowerHandler:SplitHardProcess No\n"; process+="set /Herwig/Decays/ZDecayer:PhotonGenerator NULL\n"; process+="set /Herwig/Decays/ZPowhegDecayer:PhotonGenerator NULL\n"; process+="set /Herwig/Decays/WDecayer:PhotonGenerator NULL\n"; process+="set /Herwig/Decays/WPowhegDecayer:PhotonGenerator NULL\n"; process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 0 /Herwig/Particles/tau-\n" process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 1 /Herwig/Particles/tau+\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PreCascadeHandlers 0 /Herwig/NewPhysics/DecayHandler\n" process+=insert_ME("PowhegMEPP2VV","WW") process+=selectDecayMode("W+",["W+->nu_e,e+;", "W+->nu_mu,mu+;", "W+->nu_tau,tau+;"]) process+=addBRReweighter() elif "ZZ-ll" in parameterName : process+="create Herwig::HwDecayHandler /Herwig/NewPhysics/DecayHandler\n" process+="set /Herwig/NewPhysics/DecayHandler:NewStep No\n" process+="set /Herwig/Shower/ShowerHandler:SplitHardProcess No\n"; process+="set /Herwig/Decays/ZDecayer:PhotonGenerator NULL\n"; process+="set /Herwig/Decays/ZPowhegDecayer:PhotonGenerator NULL\n"; process+="set /Herwig/Decays/WDecayer:PhotonGenerator NULL\n"; process+="set /Herwig/Decays/WPowhegDecayer:PhotonGenerator NULL\n"; process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 0 /Herwig/Particles/tau-\n" process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 1 /Herwig/Particles/tau+\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PreCascadeHandlers 0 /Herwig/NewPhysics/DecayHandler\n" process+=insert_ME("PowhegMEPP2VV","ZZ") process+=selectDecayMode("Z0",["Z0->e-,e+;", "Z0->mu-,mu+;", "Z0->tau-,tau+;"]) process+=addBRReweighter() elif "ZZ-lv" in parameterName : process+="create Herwig::HwDecayHandler /Herwig/NewPhysics/DecayHandler\n" process+="set /Herwig/NewPhysics/DecayHandler:NewStep No\n" process+="set /Herwig/Shower/ShowerHandler:SplitHardProcess No\n"; process+="set /Herwig/Decays/ZDecayer:PhotonGenerator NULL\n"; process+="set /Herwig/Decays/ZPowhegDecayer:PhotonGenerator NULL\n"; process+="set /Herwig/Decays/WDecayer:PhotonGenerator NULL\n"; process+="set /Herwig/Decays/WPowhegDecayer:PhotonGenerator NULL\n"; process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 0 /Herwig/Particles/tau-\n" process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 1 /Herwig/Particles/tau+\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PreCascadeHandlers 0 /Herwig/NewPhysics/DecayHandler\n" process+=insert_ME("PowhegMEPP2VV","ZZ") process+=selectDecayMode("Z0",["Z0->e-,e+;", "Z0->mu-,mu+;", "Z0->tau-,tau+;", "Z0->nu_e,nu_ebar;", "Z0->nu_mu,nu_mubar;", "Z0->nu_tau,nu_taubar;"]) process+=addBRReweighter() elif "W-Z-e" in parameterName : process+=insert_ME("PowhegMEqq2gZ2ff","Electron") process+=insert_ME("PowhegMEqq2W2ff","Electron") elif "W-Z-mu" in parameterName : process+=insert_ME("MEqq2gZ2ff","Muon") process+=insert_ME("MEqq2W2ff","Muon") elif "W-e" in parameterName : process+=insert_ME("PowhegMEqq2W2ff","Electron") elif "W-mu" in parameterName : process+=insert_ME("PowhegMEqq2W2ff","Muon") elif "Z-e" in parameterName : process+=insert_ME("PowhegMEqq2gZ2ff","Electron") elif "Z-mu" in parameterName : process+=insert_ME("PowhegMEqq2gZ2ff","Muon") elif "Z-LowMass-e" in parameterName : process+=insert_ME("PowhegMEqq2gZ2ff","Electron") process+=mhat_minm_maxm(20,20,70) elif "Z-MedMass-e" in parameterName : process+=insert_ME("PowhegMEqq2gZ2ff","Electron") process+=mhat_minm_maxm(40,40,130) elif "Z-LowMass-mu" in parameterName : process+=insert_ME("PowhegMEqq2gZ2ff","Muon") process+=mhat_minm_maxm(10,10,70) elif "Z-Mass1" in parameterName : process+=mhat_minm_maxm(10,10,35) if "-e" in parameterName : process+=insert_ME("PowhegMEqq2gZ2ff","Electron") else : process+=insert_ME("PowhegMEqq2gZ2ff","Muon") elif "Z-Mass2" in parameterName : process+=mhat_minm_maxm(25,25,70) if "-e" in parameterName : process+=insert_ME("PowhegMEqq2gZ2ff","Electron") else : process+=insert_ME("PowhegMEqq2gZ2ff","Muon") elif "Z-Mass3" in parameterName : process+=mhat_minm_maxm(60,60,120) if "-e" in parameterName : process+=insert_ME("PowhegMEqq2gZ2ff","Electron") else : process+=insert_ME("PowhegMEqq2gZ2ff","Muon") elif "Z-Mass4" in parameterName : process+=mhat_minm_maxm(110,110,8000) if "-e" in parameterName : process+=insert_ME("PowhegMEqq2gZ2ff","Electron") else : process+=insert_ME("PowhegMEqq2gZ2ff","Muon") elif "Z-HighMass1" in parameterName : process+=mhat_minm_maxm(116,116,400) if "-e" in parameterName : process+=insert_ME("PowhegMEqq2gZ2ff","Electron") else : process+=insert_ME("PowhegMEqq2gZ2ff","Muon") elif "Z-HighMass2" in parameterName : process+=mhat_minm_maxm(400,400,7000) if "-e" in parameterName : process+=insert_ME("PowhegMEqq2gZ2ff","Electron") else : process+=insert_ME("PowhegMEqq2gZ2ff","Muon") elif "DiPhoton-GammaGamma" in parameterName : process+=insert_ME("MEGammaGammaPowheg","GammaGamma") process+=insert_ME("MEGammaGamma","gg") process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n" process+=jet_kt_cut(5.) parameterName=parameterName.replace("-GammaGamma","") elif "DiPhoton-GammaJet" in parameterName : process+=insert_ME("MEGammaGammaPowheg","VJet") process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n" process+=jet_kt_cut(5.) parameterName=parameterName.replace("-GammaJet","") else : logging.error(" Process %s not supported for internal POWHEG matrix elements" % name) sys.exit(1) elif( simulation=="Matchbox" or simulation=="Merging" ) : if "8-VBF" in parameterName : parameters["nlo"] = "read Matchbox/VBFNLO.in\n" if(simulation=="Merging"): process+="cd /Herwig/Merging/\n" process+="insert "+thefactory+":DiagramGenerator:RestrictLines 0 /Herwig/Particles/Z0\n" process+="insert "+thefactory+":DiagramGenerator:RestrictLines 0 /Herwig/Particles/W+\n" process+="insert "+thefactory+":DiagramGenerator:RestrictLines 0 /Herwig/Particles/W-\n" process+="insert "+thefactory+":DiagramGenerator:RestrictLines 0 /Herwig/Particles/gamma\n" process+="do "+thefactory+":DiagramGenerator:TimeLikeRange 0 0\n" if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p h0 j j","0","3","FixedScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p p h0 j j","0","3","FixedScale",1,1) process+=setHardProcessWidthToZero(["h0"]) process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 125.7\n" if "GammaGamma" in parameterName : process+=selectDecayMode("h0",["h0->gamma,gamma;"]) process+=addBRReweighter() elif "WW" in parameterName : process+=selectDecayMode("h0",["h0->W+,W-;"]) process+=addBRReweighter() + elif "ZZ" in parameterName : + process+=selectDecayMode("h0",["h0->Z0,Z0;"]) + process+=addBRReweighter() elif "VBF" in parameterName : process+=selectDecayMode("h0",["h0->tau-,tau+;"]) process+=addBRReweighter() process+="set /Herwig/Particles/tau-:Stable Stable\n" parameters["nlo"] = "read Matchbox/VBFNLO.in\n" if(simulation=="Merging"): process+="cd /Herwig/Merging/\n" process+="insert "+thefactory+":DiagramGenerator:RestrictLines 0 /Herwig/Particles/Z0\n" process+="insert "+thefactory+":DiagramGenerator:RestrictLines 0 /Herwig/Particles/W+\n" process+="insert "+thefactory+":DiagramGenerator:RestrictLines 0 /Herwig/Particles/W-\n" process+="insert "+thefactory+":DiagramGenerator:RestrictLines 0 /Herwig/Particles/gamma\n" process+="do "+thefactory+":DiagramGenerator:TimeLikeRange 0 0\n" if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p h0 j j","0","3","FixedScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p p h0 j j","0","3","FixedScale",1,1) process+=setHardProcessWidthToZero(["h0"]) process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 125.7\n" elif "ggHJet" in parameterName : if(simulation=="Merging"): logging.warning("ggHJet not explicitly tested for %s " % simulation) sys.exit(0) parameters["nlo"] = "read Matchbox/MadGraph-GoSam.in\nread Matchbox/HiggsEffective.in\n" process+=selectDecayMode("h0",["h0->tau-,tau+;"]) process+=addBRReweighter() process+="set /Herwig/Particles/tau-:Stable Stable\n" process+=setHardProcessWidthToZero(["h0"]) process+=addProcess(thefactory,"p p h0 j","3","1","FixedScale",0,0) process+=addFirstJet("20") process+="set "+thefactory+":ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n" process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 125.7\n" elif "8-ggH" in parameterName : parameters["nlo"] = "read Matchbox/MadGraph-GoSam.in\nread Matchbox/HiggsEffective.in\n" if(simulation=="Merging"): process+= "cd /Herwig/MatrixElements/Matchbox/Amplitudes\nset OpenLoops:HiggsEff On\nset MadGraph:Model heft\n" process+="cd /Herwig/Merging/\n" process+=setHardProcessWidthToZero(["h0"]) if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p h0","2","1","FixedScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p p h0","2","1","FixedScale",2,2) process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 125.7\n" if "GammaGamma" in parameterName : process+=selectDecayMode("h0",["h0->gamma,gamma;"]) process+=addBRReweighter() elif "WW" in parameterName : process+=selectDecayMode("h0",["h0->W+,W-;"]) process+=addBRReweighter() + elif "ZZ" in parameterName : + process+=selectDecayMode("h0",["h0->Z0,Z0;"]) + process+=addBRReweighter() elif "ggH" in parameterName : parameters["nlo"] = "read Matchbox/MadGraph-GoSam.in\nread Matchbox/HiggsEffective.in\n" if(simulation=="Merging"): process+= "cd /Herwig/MatrixElements/Matchbox/Amplitudes\nset OpenLoops:HiggsEff On\nset MadGraph:Model heft\n" process+="cd /Herwig/Merging/\n" process+=selectDecayMode("h0",["h0->tau-,tau+;"]) process+=addBRReweighter() process+="set /Herwig/Particles/tau-:Stable Stable\n" process+=setHardProcessWidthToZero(["h0"]) if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p h0","2","1","FixedScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p p h0","2","1","FixedScale",2,2) process+="set "+thefactory+":ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n" process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 125.7\n" elif "8-WH" in parameterName : if(simulation=="Merging"): logging.warning("8-WH not explicitly tested for %s " % simulation) sys.exit(0) process+=setHardProcessWidthToZero(["h0","W+","W-"]) process+=addProcess(thefactory,"p p W+ h0","0","2","FixedScale",0,0) process+=addProcess(thefactory,"p p W- h0","0","2","FixedScale",0,0) process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 125.7\n" if "GammaGamma" in parameterName : process+=selectDecayMode("h0",["h0->gamma,gamma;"]) process+=addBRReweighter() elif "WW" in parameterName : process+=selectDecayMode("h0",["h0->W+,W-;"]) process+=addBRReweighter() + elif "ZZ" in parameterName : + process+=selectDecayMode("h0",["h0->Z0,Z0;"]) + process+=addBRReweighter() elif "8-ZH" in parameterName : if(simulation=="Merging"): logging.warning("8-ZH not explicitly tested for %s " % simulation) sys.exit(0) process+=setHardProcessWidthToZero(["h0","Z0"]) process+=addProcess(thefactory,"p p Z0 h0","0","2","FixedScale",0,0) process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 125.7\n" if "GammaGamma" in parameterName : process+=selectDecayMode("h0",["h0->gamma,gamma;"]) process+=addBRReweighter() elif "WW" in parameterName : process+=selectDecayMode("h0",["h0->W+,W-;"]) process+=addBRReweighter() + elif "ZZ" in parameterName : + process+=selectDecayMode("h0",["h0->Z0,Z0;"]) + process+=addBRReweighter() elif "WH" in parameterName : if(simulation=="Merging"): logging.warning("WH not explicitly tested for %s " % simulation) sys.exit(0) process+=selectDecayMode("h0",["h0->b,bbar;"]) process+=addBRReweighter() process+=setHardProcessWidthToZero(["h0"]) process+=addProcess(thefactory,"p p e+ nu h0","0","3","LeptonPairMassScale",0,0) process+=addProcess(thefactory,"p p e- nu h0","0","3","LeptonPairMassScale",0,0) process+=addProcess(thefactory,"p p mu+ nu h0","0","3","LeptonPairMassScale",0,0) process+=addProcess(thefactory,"p p mu- nu h0","0","3","LeptonPairMassScale",0,0) process+=addLeptonPairCut("60","120") elif "ZH" in parameterName : if(simulation=="Merging"): logging.warning("ZH not explicitly tested for %s " % simulation) sys.exit(0) process+=selectDecayMode("h0",["h0->b,bbar;"]) process+=addBRReweighter() process+=setHardProcessWidthToZero(["h0"]) process+=addProcess(thefactory,"p p e+ e- h0","0","3","LeptonPairMassScale",0,0) process+=addProcess(thefactory,"p p mu+ mu- h0","0","3","LeptonPairMassScale",0,0) process+=addLeptonPairCut("60","120") elif "UE" in parameterName : logging.error(" Process %s not supported for Matchbox matrix elements" % name) sys.exit(1) elif "8-DiJets" in parameterName or "7-DiJets" in parameterName : if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p j j","2","0","MaxJetPtScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p p j j","2","0","MaxJetPtScale",1,1) process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n" if "-A" in parameterName : process+=addFirstJet("45") process+=addSecondJet("25") process+="set /Herwig/Cuts/FirstJet:YRange -3. 3.\n" process+="set /Herwig/Cuts/SecondJet:YRange -3. 3.\n" elif "-B" in parameterName : process+=addFirstJet("20") process+=addSecondJet("15") process+="set /Herwig/Cuts/FirstJet:YRange -2.7 2.7\n" process+="set /Herwig/Cuts/SecondJet:YRange -2.7 2.7\n" elif "-C" in parameterName : process+=addFirstJet("20") process+=addSecondJet("15") process+="set /Herwig/Cuts/FirstJet:YRange -4.8 4.8\n" process+="set /Herwig/Cuts/SecondJet:YRange -4.8 4.8\n" else : logging.error("Exit 00001") sys.exit(1) if "DiJets-1" in parameterName : process+=addJetPairCut("90") elif "DiJets-2" in parameterName : process+=addJetPairCut("200") elif "DiJets-3" in parameterName : process+=addJetPairCut("450") elif "DiJets-4" in parameterName : process+=addJetPairCut("750") elif "DiJets-5" in parameterName : process+=addJetPairCut("950") elif "DiJets-6" in parameterName : process+=addJetPairCut("1550") elif "DiJets-7" in parameterName : process+=addJetPairCut("2150") elif "DiJets-8" in parameterName : process+=addJetPairCut("2750") else : logging.error("Exit 00002") sys.exit(1) elif( "7-Jets" in parameterName or "8-Jets" in parameterName or "13-Jets" in parameterName ) : if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p j j","2","0","MaxJetPtScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p p j j","2","0","MaxJetPtScale",1,1) process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n" if "Jets-10" in parameterName : process+=addFirstJet("1800") elif "Jets-0" in parameterName : process+=addFirstJet("5") elif "Jets-1" in parameterName : process+=addFirstJet("10") elif "Jets-2" in parameterName : process+=addFirstJet("20") elif "Jets-3" in parameterName : process+=addFirstJet("40") elif "Jets-4" in parameterName : process+=addFirstJet("70") elif "Jets-5" in parameterName : process+=addFirstJet("150") elif "Jets-6" in parameterName : process+=addFirstJet("200") elif "Jets-7" in parameterName : process+=addFirstJet("300") elif "Jets-8" in parameterName : process+=addFirstJet("500") elif "Jets-9" in parameterName : process+=addFirstJet("800") else : logging.error("Exit 00003") sys.exit(1) elif( "7-Charm" in parameterName or "7-Bottom" in parameterName) : parameters["bscheme"]=fourFlavour process+="set /Herwig/Particles/b:HardProcessMass 4.2*GeV\n" process+="set /Herwig/Particles/bbar:HardProcessMass 4.2*GeV\n" if "7-Bottom" in parameterName : if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p b bbar","2","0","MaxJetPtScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p p b bbar","2","0","MaxJetPtScale",1,0) else: if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p c cbar","2","0","MaxJetPtScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p p c cbar","2","0","MaxJetPtScale",1,0) process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n" if "-0" in parameterName : process+=addFirstJet("0") elif "-1" in parameterName : process+=addFirstJet("5") elif "-2" in parameterName : process+=addFirstJet("20") elif "-3" in parameterName : process+=addFirstJet("50") elif "-4" in parameterName : process+=addFirstJet("80") elif "-5" in parameterName : process+=addFirstJet("110") elif "-6" in parameterName : process+=addFirstJet("30") process+=addSecondJet("25") process+=addJetPairCut("90") elif "-7" in parameterName : process+=addFirstJet("30") process+=addSecondJet("25") process+=addJetPairCut("340") elif "-8" in parameterName : process+=addFirstJet("30") process+=addSecondJet("25") process+=addJetPairCut("500") else : logging.error("Exit 00004") sys.exit(1) elif "Top-L" in parameterName : process+=setHardProcessWidthToZero(["t","tbar"]) if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p t tbar","2","0","TopPairMTScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p p t tbar","2","0","TopPairMTScale",2,2) process+=selectDecayMode("t",["t->nu_e,e+,b;", "t->nu_mu,mu+,b;"]) process+=addBRReweighter() elif "Top-SL" in parameterName : process+=setHardProcessWidthToZero(["t","tbar"]) if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p t tbar","2","0","TopPairMTScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p p t tbar","2","0","TopPairMTScale",2,2) process+="set /Herwig/Particles/t:Synchronized Not_synchronized\n" process+="set /Herwig/Particles/tbar:Synchronized Not_synchronized\n" process+=selectDecayMode("t",["t->nu_e,e+,b;", "t->nu_mu,mu+,b;"]) process+=selectDecayMode("tbar",["tbar->b,bbar,cbar;", "tbar->bbar,cbar,d;", "tbar->bbar,cbar,s;", "tbar->bbar,s,ubar;", "tbar->bbar,ubar,d;"]) process+=addBRReweighter() elif "Top-All" in parameterName : process+=setHardProcessWidthToZero(["t","tbar"]) if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p t tbar","2","0","TopPairMTScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p p t tbar","2","0","TopPairMTScale",2,2) elif "WZ" in parameterName : if(simulation=="Merging"): logging.warning("WZ not explicitly tested for %s " % simulation) sys.exit(0) process+=setHardProcessWidthToZero(["W+","W-","Z0"]) process+=addProcess(thefactory,"p p W+ Z0","0","2","FixedScale",0,0) process+=addProcess(thefactory,"p p W- Z0","0","2","FixedScale",0,0) process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 171.6*GeV\n\n" process+=selectDecayMode("W+",["W+->nu_e,e+;", "W+->nu_mu,mu+;"]) process+=selectDecayMode("W-",["W-->nu_ebar,e-;", "W-->nu_mubar,mu-;"]) process+=selectDecayMode("Z0",["Z0->e-,e+;", "Z0->mu-,mu+;"]) process+=addBRReweighter() process+=addLeptonPairCut("60","120") elif "WW-emu" in parameterName : if(simulation=="Merging"): logging.warning("WW-emu not explicitly tested for %s " % simulation) sys.exit(0) process+=setHardProcessWidthToZero(["W+","W-","Z0"]) process+=addProcess(thefactory,"p p W+ W-","0","2","FixedScale",0,0) process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 160.8*GeV\n" process+="set /Herwig/Particles/W+:Synchronized 0\n" process+="set /Herwig/Particles/W-:Synchronized 0\n" process+=selectDecayMode("W+",["W+->nu_e,e+;"]) process+=selectDecayMode("W-",["W-->nu_mubar,mu-;"]) process+=addBRReweighter() parameters["bscheme"] = "read Matchbox/FourFlavourScheme.in\n" process+=addLeptonPairCut("60","120") elif "WW-ll" in parameterName : if(simulation=="Merging"): logging.warning("WW-ll not explicitly tested for %s " % simulation) sys.exit(0) process+=setHardProcessWidthToZero(["W+","W-","Z0"]) process+=addProcess(thefactory,"p p W+ W-","0","2","FixedScale",0,0) process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 160.8*GeV\n" process+=selectDecayMode("W+",["W+->nu_e,e+;", "W+->nu_mu,mu+;", "W+->nu_tau,tau+;"]) process+=addBRReweighter() process+=addLeptonPairCut("60","120") parameters["bscheme"] = "read Matchbox/FourFlavourScheme.in\n" elif "ZZ-ll" in parameterName : if(simulation=="Merging"): logging.warning("ZZ-ll not explicitly tested for %s " % simulation) sys.exit(0) process+=setHardProcessWidthToZero(["W+","W-","Z0"]) process+=addProcess(thefactory,"p p Z0 Z0","0","2","FixedScale",0,0) process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 182.2*GeV\n" process+=selectDecayMode("Z0",["Z0->e-,e+;", "Z0->mu-,mu+;", "Z0->tau-,tau+;"]) process+=addBRReweighter() process+=addLeptonPairCut("60","120") elif "ZZ-lv" in parameterName : if(simulation=="Merging"): logging.warning("ZZ-lv not explicitly tested for %s " % simulation) sys.exit(0) process+=setHardProcessWidthToZero(["W+","W-","Z0"]) process+=addProcess(thefactory,"p p Z0 Z0","0","2","FixedScale",0,0) process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 182.2*GeV\n" process+=selectDecayMode("Z0",["Z0->e-,e+;", "Z0->mu-,mu+;", "Z0->tau-,tau+;", "Z0->nu_e,nu_ebar;", "Z0->nu_mu,nu_mubar;", "Z0->nu_tau,nu_taubar;"]) process+=addBRReweighter() process+=addLeptonPairCut("60","120") elif "W-Z-e" in parameterName : if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p e+ e-","0","2","LeptonPairMassScale",0,0) process+=addProcess(thefactory,"p p e+ nu","0","2","LeptonPairMassScale",0,0) process+=addProcess(thefactory,"p p e- nu","0","2","LeptonPairMassScale",0,0) elif(simulation=="Merging"): process+=particlegroup('epm','e+','e-') process+=particlegroup('epmnu','e+','e-','nu_e','nu_ebar') process+=addProcess(thefactory,"p p epm epmnu","0","2","LeptonPairMassScale",2,2) process+=addLeptonPairCut("60","120") elif "W-Z-mu" in parameterName : if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p mu+ mu-","0","2","LeptonPairMassScale",0,0) process+=addProcess(thefactory,"p p mu+ nu","0","2","LeptonPairMassScale",0,0) process+=addProcess(thefactory,"p p mu- nu","0","2","LeptonPairMassScale",0,0) elif(simulation=="Merging"): process+=particlegroup('mupm','mu+','mu-') process+=particlegroup('mupmnu','mu+','mu-','nu_mu','nu_mubar') process+=addProcess(thefactory,"p p mupm mupmnu","0","2","LeptonPairMassScale",2,2) process+=addLeptonPairCut("60","120") elif "W-e" in parameterName : if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p e+ nu","0","2","LeptonPairMassScale",0,0) process+=addProcess(thefactory,"p p e- nu","0","2","LeptonPairMassScale",0,0) elif(simulation=="Merging"): process+=particlegroup('epm','e+','e-') process+=addProcess(thefactory,"p p epm nu","0","2","LeptonPairMassScale",2,2) process+=addLeptonPairCut("60","120") elif "W-mu" in parameterName : if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p mu+ nu","0","2","LeptonPairMassScale",0,0) process+=addProcess(thefactory,"p p mu- nu","0","2","LeptonPairMassScale",0,0) elif(simulation=="Merging"): process+=particlegroup('mupm','mu+','mu-') process+=addProcess(thefactory,"p p mupm nu","0","2","LeptonPairMassScale",2,2) process+=addLeptonPairCut("60","120") elif "Z-e" in parameterName : if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p e+ e-","0","2","LeptonPairMassScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p p e+ e-","0","2","LeptonPairMassScale",2,2) process+=addLeptonPairCut("60","120") elif "Z-mu" in parameterName : if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p mu+ mu-","0","2","LeptonPairMassScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p p mu+ mu-","0","2","LeptonPairMassScale",2,2) process+=addLeptonPairCut("60","120") elif "Z-jj" in parameterName : if(simulation=="Merging"): logging.warning("Z-jj not explicitly tested for %s " % simulation) sys.exit(0) process+=addProcess(thefactory,"p p e+ e- j j","2","2","LeptonPairMassScale",0,0) process+=addFirstJet("40") process+=addSecondJet("30") process+=addLeptonPairCut("60","120") elif "Z-LowMass-e" in parameterName : if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p e+ e-","0","2","LeptonPairMassScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p p e+ e-","0","2","LeptonPairMassScale",2,2) process+=addLeptonPairCut("20","70") elif "Z-MedMass-e" in parameterName : if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p e+ e-","0","2","LeptonPairMassScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p p e+ e-","0","2","LeptonPairMassScale",2,2) process+=addLeptonPairCut("40","130") elif "Z-LowMass-mu" in parameterName : if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p mu+ mu-","0","2","LeptonPairMassScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p p mu+ mu-","0","2","LeptonPairMassScale",2,2) process+=addLeptonPairCut("10","70") elif "Z-Mass1" in parameterName : process+=addLeptonPairCut("10","35") if "-e" in parameterName : if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p e+ e-","0","2","LeptonPairMassScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p p e+ e-","0","2","LeptonPairMassScale",2,2) else : if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p mu+ mu-","0","2","LeptonPairMassScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p p mu+ mu-","0","2","LeptonPairMassScale",2,2) elif "Z-Mass2" in parameterName : process+=addLeptonPairCut("25","70") if "-e" in parameterName : if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p e+ e-","0","2","LeptonPairMassScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p p e+ e-","0","2","LeptonPairMassScale",2,2) else : if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p mu+ mu-","0","2","LeptonPairMassScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p p mu+ mu-","0","2","LeptonPairMassScale",2,2) elif "Z-Mass3" in parameterName : process+=addLeptonPairCut("60","120") if "-e" in parameterName : if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p e+ e-","0","2","LeptonPairMassScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p p e+ e-","0","2","LeptonPairMassScale",2,2) else : if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p mu+ mu-","0","2","LeptonPairMassScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p p mu+ mu-","0","2","LeptonPairMassScale",2,2) elif "Z-Mass4" in parameterName : process+=addLeptonPairCut("115","8000") if "-e" in parameterName : if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p e+ e-","0","2","LeptonPairMassScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p p e+ e-","0","2","LeptonPairMassScale",2,2) else : if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p mu+ mu-","0","2","LeptonPairMassScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p p mu+ mu-","0","2","LeptonPairMassScale",2,2) elif "Z-HighMass1" in parameterName : process+=addLeptonPairCut("116","400") if "-e" in parameterName : if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p e+ e-","0","2","LeptonPairMassScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p p e+ e-","0","2","LeptonPairMassScale",2,2) else : if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p mu+ mu-","0","2","LeptonPairMassScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p p mu+ mu-","0","2","LeptonPairMassScale",2,2) elif "Z-HighMass2" in parameterName : process+=addLeptonPairCut("400","7000") if "-e" in parameterName : if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p e+ e-","0","2","LeptonPairMassScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p p e+ e-","0","2","LeptonPairMassScale",2,2) else : if(simulation=="Matchbox"): process+=addProcess(thefactory,"p p mu+ mu-","0","2","LeptonPairMassScale",0,0) elif(simulation=="Merging"): process+=addProcess(thefactory,"p p mu+ mu-","0","2","LeptonPairMassScale",2,2) elif "W-Jet" in parameterName : if(simulation=="Merging"): logging.warning("W-Jet not explicitly tested for %s " % simulation) sys.exit(0) process+=addProcess(thefactory,"p p e+ nu j","1","2","HTScale",0,0) process+=addProcess(thefactory,"p p e- nu j","1","2","HTScale",0,0) process+=addLeptonPairCut("60","120") if "W-Jet-1-e" in parameterName : process+=addFirstJet("100") parameterName=parameterName.replace("W-Jet-1-e","W-Jet-e") elif "W-Jet-2-e" in parameterName : process+=addFirstJet("190") parameterName=parameterName.replace("W-Jet-2-e","W-Jet-e") elif "W-Jet-3-e" in parameterName : process+=addFirstJet("270") parameterName=parameterName.replace("W-Jet-3-e","W-Jet-e") else : logging.error("Exit 00005") sys.exit(1) elif "Z-Jet" in parameterName : if(simulation=="Merging"): logging.warning("Z-Jet not explicitly tested for %s " % simulation) sys.exit(0) if "-e" in parameterName : process+=addProcess(thefactory,"p p e+ e- j","1","2","HTScale",0,0) if "Z-Jet-0-e" in parameterName : process+=addFirstJet("35") parameterName=parameterName.replace("Z-Jet-0-e","Z-Jet-e") elif "Z-Jet-1-e" in parameterName : process+=addFirstJet("100") parameterName=parameterName.replace("Z-Jet-1-e","Z-Jet-e") elif "Z-Jet-2-e" in parameterName : process+=addFirstJet("190") parameterName=parameterName.replace("Z-Jet-2-e","Z-Jet-e") elif "Z-Jet-3-e" in parameterName : process+=addFirstJet("270") parameterName=parameterName.replace("Z-Jet-3-e","Z-Jet-e") else : logging.error("Exit 00006") sys.exit(1) else : process+=addProcess(thefactory,"p p mu+ mu- j","1","2","HTScale",0,0) process+=addFirstJet("35") parameterName=parameterName.replace("Z-Jet-0-mu","Z-Jet-mu") process+=addLeptonPairCut("60","120") elif "Z-bb" in parameterName : if(simulation=="Merging"): logging.warning("Z-bb not explicitly tested for %s " % simulation) sys.exit(0) parameters["bscheme"]=fourFlavour process+="set /Herwig/Particles/b:HardProcessMass 4.2*GeV\nset /Herwig/Particles/bbar:HardProcessMass 4.2*GeV\n" process+=addProcess(thefactory,"p p e+ e- b bbar","2","2","FixedScale",0,0) process+=addLeptonPairCut("66","116") process+=addFirstJet("18") process+=addSecondJet("15") process+=addLeptonPairCut("60","120") elif "Z-b" in parameterName : if(simulation=="Merging"): logging.warning("Z-b not explicitly tested for %s " % simulation) sys.exit(0) process+=particlegroup('bjet','b','bbar') process+=addProcess(thefactory,"p p e+ e- bjet","1","2","FixedScale",0,0) process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 91.2*GeV\n" process+=addLeptonPairCut("60","120") process+=addFirstJet("15") elif "W-b" in parameterName : if(simulation=="Merging"): logging.warning("W-b not explicitly tested for %s " % simulation) sys.exit(0) parameters["bscheme"]=fourFlavour process += "set /Herwig/Particles/b:HardProcessMass 4.2*GeV\nset /Herwig/Particles/bbar:HardProcessMass 4.2*GeV\n" process+=addProcess(thefactory,"p p e- nu b bbar","2","2","FixedScale",0,0) process+=addProcess(thefactory,"p p mu+ nu b bbar","2","2","FixedScale",0,0) process += "set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 80.4*GeV\n" process+=addFirstJet("30") process+=addLeptonPairCut("60","120") else : logging.error(" Process %s not supported for Matchbox matrix elements" % name) sys.exit(1) # LHC-GammaGamma elif(collider=="LHC-GammaGamma" ) : if "-7-" in parameterName : process = StringBuilder(collider_lumi(7000.0)) elif "-8-" in parameterName : process = StringBuilder(collider_lumi(8000.0)) else : process = StringBuilder(collider_lumi(7000.0)) if(simulation=="") : if "7" in parameterName : process += insert_ME("MEgg2ff","Muon") else : logging.error(" Process %s not supported for default matrix elements" % name) sys.exit(1) else : logging.error("LHC-GammaGamma not supported for %s " % simulation) sys.exit(1) parameters['parameterFile'] = os.path.join(collider,"{c}-{pn}.in".format(c=collider, pn=parameterName)) parameters['runname'] = 'Rivet-%s' % name parameters['process'] = str(process) #check if selecteddecaymode and addedBRReweighter is consistent if selecteddecaymode and not addedBRReweighter: logging.error("Decaymode was selected but no BRReweighter was added.") sys.exit(1) if addedBRReweighter and not selecteddecaymode: logging.error("BRReweighter was added but no Decaymode was selected.") sys.exit(1) # check that we only add one process if in merging mode: if numberOfAddedProcesses > 1 and simulation =="Merging": logging.error("In Merging only one process is allowed at the moment. See ticket #403.") sys.exit(1) # Check if a process was added for Merging or Matchbox: if numberOfAddedProcesses == 0 and (simulation =="Merging" or simulation =="Matchbox"): logging.error("No process was selected.") sys.exit(1) # get template and write the file with open(os.path.join("Rivet/Templates",templateName), 'r') as f: templateText = f.read() template = Template( templateText ) with open(os.path.join("Rivet",name+".in"), 'w') as f: f.write( template.substitute(parameters) ) diff --git a/Tests/python/merge-LHC-Jets b/Tests/python/merge-LHC-Jets --- a/Tests/python/merge-LHC-Jets +++ b/Tests/python/merge-LHC-Jets @@ -1,1427 +1,1462 @@ #! /usr/bin/env python import logging import sys import math if sys.version_info[:3] < (2,4,0): print "rivet scripts require Python version >= 2.4.0... exiting" sys.exit(1) import os, yoda # ############################################# def fillAbove(scale,desthisto, sourcehistosbyptmin) : pthigh= 1e100 ptlow =-1e100 for pt, h in sorted(sourcehistosbyptmin.iteritems(),reverse=True): ptlow=pt if(type(desthisto)==yoda.core.Scatter2D) : for i in range(0,h.numPoints) : xMin = h.points[i].x-h.points[i].xErrs.minus if( xMin*scale >= ptlow and xMin*scale < pthigh ) : desthisto.addPoint(h.points[i]) elif(type(desthisto)==yoda.core.Profile1D) : for i in range(0,h.numBins) : if(h.bins[i].xMin*scale >= ptlow and h.bins[i].xMin*scale < pthigh ) : desthisto.bins[i] += h.bins[i] elif(type(desthisto)==yoda.core.Histo1D) : for i in range(0,h.numBins) : if(h.bins[i].xMin*scale >= ptlow and h.bins[i].xMin*scale < pthigh ) : desthisto.bins[i] += h.bins[i] elif(type(desthisto)==yoda.core.Counter) : desthisto += h else : logging.error("Can't merge %s, unknown type" % desthisto.path) sys.exit(1) pthigh=pt def mergeByPt(hpath, sqrts, scale=1.) : global inhistos_pt global outhistos try: fillAbove(scale,outhistos[hpath], inhistos_pt[hpath][float(sqrts)]) except: pass def mergeByMass(hpath, sqrts, scale=1.): global inhistos_mass global outhistos try: fillAbove(scale,outhistos[hpath], inhistos_mass[hpath][float(sqrts)]) except: pass def useOnePt(hpath, sqrts, ptmin): global inhistos_pt global outhistos try: ## Find best pT_min match ptmins = inhistos_pt[hpath][float(sqrts)].keys() closest_ptmin = None for ptm in ptmins: if closest_ptmin is None or \ abs(ptm-float(ptmin)) < abs(closest_ptmin-float(ptmin)): closest_ptmin = ptm if closest_ptmin != float(ptmin): logging.warning("Inexact match for requested pTmin=%s: " % ptmin + \ "using pTmin=%e instead" % closest_ptmin) outhistos[hpath] = inhistos_pt[hpath][float(sqrts)][closest_ptmin] except: pass def useOneMass(hpath, sqrts, ptmin): global inhistos_pt global outhistos try: ## Find best pT_min match ptmins = inhistos_mass[hpath][float(sqrts)].keys() closest_ptmin = None for ptm in ptmins: if closest_ptmin is None or \ abs(ptm-float(ptmin)) < abs(closest_ptmin-float(ptmin)): closest_ptmin = ptm if closest_ptmin != float(ptmin): logging.warning("Inexact match for requested mass=%s: " % ptmin + \ "using mass=%e instead" % closest_ptmin) outhistos[hpath] = inhistos_mass[hpath][float(sqrts)][closest_ptmin] except: pass # ####################################### if __name__ == "__main__": import logging from optparse import OptionParser, OptionGroup parser = OptionParser(usage="%prog name") verbgroup = OptionGroup(parser, "Verbosity control") parser.add_option("--with-ue", action='store_true' , dest="ue", default=True, help="Include UE analyses") parser.add_option("--without-ue", action='store_false', dest="ue", default=True, help="Don\'t include UE analyses") verbgroup.add_option("-v", "--verbose", action="store_const", const=logging.DEBUG, dest="LOGLEVEL", default=logging.INFO, help="print debug (very verbose) messages") verbgroup.add_option("-q", "--quiet", action="store_const", const=logging.WARNING, dest="LOGLEVEL", default=logging.INFO, help="be very quiet") parser.add_option_group(verbgroup) (opts, args) = parser.parse_args() logging.basicConfig(level=opts.LOGLEVEL, format="%(message)s") (opts, args) = parser.parse_args() ## Check args if len(args) < 1: logging.error("Must specify at least the name of the files") sys.exit(1) yodafiles=["-7-Bottom-0.yoda","-7-Bottom-1.yoda","-7-Bottom-2.yoda", "-7-Bottom-3.yoda","-7-Bottom-4.yoda","-7-Bottom-5.yoda", "-7-Charm-1.yoda","-7-Charm-2.yoda", "-7-Charm-3.yoda","-7-Charm-4.yoda","-7-Charm-5.yoda", "-7-Top-SL.yoda","-7-Top-L.yoda","-7-Top-All.yoda", - "-8-Top-All.yoda","-13-Top-All.yoda"] + "-8-Top-SL.yoda","-8-Top-L.yoda","-8-Top-All.yoda", + "-13-Top-L.yoda","-13-Top-SL.yoda"] -for i in range(1,10) : +for i in range(1,11) : for j in [7,8,13] : yodafiles.append("-%1.1i-Jets-%1.1i.yoda" % (j,i)) if(opts.ue) : - yodafiles += ["-7-Jets-0.yoda" ,"-8-Jets-0.yoda" ,"-7-Jets-10.yoda", - "-8-Jets-10.yoda" ,"-900-UE.yoda" ,"-2360-UE.yoda" , + yodafiles += ["-7-Jets-0.yoda" ,"-8-Jets-0.yoda" , + "-900-UE.yoda" ,"-2360-UE.yoda" , "-2760-UE.yoda" ,"-7-UE.yoda" ,"-900-UE-Long.yoda", "-900-UE-Short.yoda","-8-UE.yoda" , "-7-UE-Long.yoda","-13-UE.yoda","-13-UE-Long.yoda"] ## Get histos inhistos_pt = {} inhistos_mass = {} outhistos={} weights = {} for f in yodafiles: file='Rivet-'+args[0]+f ptmin=0. sqrts=7000 # CMS energy if(file.find("-900-")>0) : sqrts=900 elif(file.find("-2360-")>0) : sqrts=2360 elif(file.find("-2760-")>0) : sqrts=2760 elif(file.find("-7-")>=0) : sqrts=7000 elif(file.find("-8-")>=0) : sqrts=8000 elif(file.find("-13-")>0) : sqrts=13000 # pT min if(file.find("UE")>0) : ptmin=0. elif(file.find("Jets-0")>0) : ptmin=4. elif(file.find("Jets-10")>0) : ptmin=1900. elif(file.find("Jets-1")>0) : if( not opts.ue) : ptmin = 10. else : ptmin = 20. elif(file.find("Jets-2")>0) : ptmin=40. elif(file.find("Jets-3")>0) : ptmin=80. elif(file.find("Jets-4")>0) : ptmin=110. elif(file.find("Jets-5")>0) : ptmin=210. elif(file.find("Jets-6")>0) : ptmin=260. elif(file.find("Jets-7")>0) : ptmin=400. elif(file.find("Jets-8")>0) : ptmin=600. elif(file.find("Jets-9")>0) : ptmin=900. elif(file.find("Bottom-0")>0) : ptmin=0. elif(file.find("Bottom-1")>0 or file.find("Charm-1")>0) : ptmin=10. elif(file.find("Bottom-2")>0 or file.find("Charm-2")>0) : ptmin=30. elif(file.find("Bottom-3")>0 or file.find("Charm-3")>0) : ptmin=70. elif(file.find("Bottom-4")>0 or file.find("Charm-4")>0) : ptmin=100. elif(file.find("Bottom-5")>0 or file.find("Charm-5")>0) : ptmin=130. elif(file.find("Top-SL.yoda")>0 or file.find("Top-L.yoda")>0 or \ file.find("Top-All.yoda")>0): ptmin=0. if not os.access(file, os.R_OK): logging.error("%s can not be read" % file) continue try: aos = yoda.read(file) except: logging.error("%s can not be parsed as YODA" % file) continue ## Get histos from this YODA file for aopath, ao in aos.iteritems() : if(aopath.find("S8924791")>0 or aopath.find("S8971293")>0 or aopath.find("S8817804")>0 or aopath.find("I1082936")>0 or aopath.find("S8994773")>0 or aopath.find("S8918562")>0 or aopath.find("S8624100")>0 or aopath.find("S8625980")>0 or aopath.find("S8894728")>0 or aopath.find("S8957746")>0 or aopath.find("S9126244")>0 or aopath.find("S9120041")>0 or aopath.find("S8950903")>0 or aopath.find("S9086218")>0 or aopath.find("S9088458")>0 or aopath.find("I919017" )>0 or aopath.find("I926145" )>0 or aopath.find("S8941262")>0 or aopath.find("S8973270")>0 or aopath.find("I1118269")>0 or aopath.find("I1188891")>0 or aopath.find("I1082009")>0 or aopath.find("I1087342")>0 or aopath.find("S9035664")>0 or aopath.find("I1125575")>0 or aopath.find("I1094564")>0 or aopath.find("I930220" )>0 or aopath.find("I1224539")>0 or aopath.find("I1273574")>0 or aopath.find("I1261026")>0 or aopath.find("I1307243")>0 or aopath.find("I1325553")>0 or aopath.find("I1298810")>0 or aopath.find("I1298811")>0 or aopath.find("I1208923")>0 or aopath.find("I1305624")>0 or aopath.find("I1419070")>0 or aopath.find("I1394679")>0 or aopath.find("I929691" )>0 or aopath.find("I1393758")>0 or - aopath.find("I1459051")>0 or aopath.find("ATLAS_2016_CONF_2016_092")>0 or + aopath.find("I1459051")>0 or aopath.find("I1487277")>0 or + aopath.find("I1421646")>0 or + aopath.find("ATLAS_2016_CONF_2016_092")>0 or aopath.find("CMS_2012_PAS_QCD_11_010")>0) : if not inhistos_pt.has_key(aopath): inhistos_pt[aopath] = {} tmpE = inhistos_pt[aopath] if not tmpE.has_key(sqrts): tmpE[sqrts] = {} if not tmpE[sqrts].has_key(ptmin): tmpE[sqrts][ptmin] = ao else: tmpE[sqrts][ptmin] += ao #raise Exception("A set with ptmin = %s already exists" % ( ptmin)) else : if(aopath.find("I1243871")>0) : if(aopath.find("x01")>0 and file.find("-7-Top-L.yoda")>0 ) : outhistos[aopath] = ao elif(aopath.find("x02")>0 and file.find("-7-Top-SL.yoda")>0 ) : outhistos[aopath] = ao elif(aopath.find("1467230")>0 or aopath.find("1419652")>0) : if(aopath.find("y01")>0 and file.find("Long")>0 ) : outhistos[aopath] = ao elif(aopath.find("y02")>0 and file.find("Long")<0 ) : outhistos[aopath] = ao else : outhistos[aopath] = ao yodafiles=["-7-Bottom-6.yoda","-7-Bottom-7.yoda","-7-Bottom-8.yoda"] for i in range(1,8) : yodafiles.append("-7-DiJets-%1.1i-A.yoda" % i) yodafiles.append("-7-DiJets-%1.1i-B.yoda" % i) yodafiles.append("-7-DiJets-%1.1i-C.yoda" % i) for f in yodafiles: - print file file='Rivet-'+args[0]+f if(file.find("-7-Jets-1")>0) : sqrts=7000 mass=0 if(file.find("-7-DiJets-1")>0) : sqrts=7000 mass=100 elif(file.find("-7-DiJets-2")>0) : sqrts=7000 mass=250 elif(file.find("-7-DiJets-3")>0) : sqrts=7000 mass=500 elif(file.find("-7-DiJets-4")>0) : sqrts=7000 mass=800 elif(file.find("-7-DiJets-5")>0) : sqrts=7000 mass=1000 elif(file.find("-7-DiJets-6")>0) : sqrts=7000 mass=1600 elif(file.find("-7-DiJets-7")>0) : sqrts=7000 mass=2200 elif(file.find("-7-DiJets-8")>0) : sqrts=7000 mass=2800 elif(file.find("-7-Bottom-6")>0) : sqrts=7000 mass=110 elif(file.find("-7-Bottom-7")>0) : sqrts=7000 mass=370 elif(file.find("-7-Bottom-8")>0) : sqrts=7000 mass=550 if not os.access(file, os.R_OK): logging.error("%s can not be read" % file) continue try: aos = yoda.read(file) except: logging.error("%s can not be parsed as YODA" % file) continue ## Get histos from this YODA file for aopath, ao in aos.iteritems() : if(aopath.find("8817804")>0 or aopath.find("8968497")>0 or aopath.find("1082936")>0 or aopath.find("I930220")>0 or aopath.find("1261026")>0 or aopath.find("1090423")>0 or aopath.find("1268975")>0 or aopath.find("CMS_2013_I1208923")>0) : if not inhistos_mass.has_key(aopath): inhistos_mass[aopath] = {} tmpE = inhistos_mass[aopath] if not tmpE.has_key(sqrts): tmpE[sqrts] = {} tmpP = tmpE[sqrts] if not tmpP.has_key(mass): tmpP[mass] = ao else: print aopath raise Exception("A set with mass = %s already exists" % ( mass)) ## Make empty output histos if needed for hpath,hsets in inhistos_pt.iteritems(): if( hpath.find("8924791")>0 or hpath.find("8971293")>0 or hpath.find("8817804")>0 or hpath.find("8968497")>0 or (hpath.find("9120041")>0 and (hpath.find("d01")>0 or hpath.find("d02")>0)) or hpath.find("9126244")>0 or hpath.find("926145") >0 or hpath.find("9086218")>0 or hpath.find("1082936")>0 or hpath.find("8941262")>0 or hpath.find("1118269")>0 or hpath.find("1087342")>0 or hpath.find("1188891")>0 or hpath.find("919017")>0 or hpath.find("9035664")>0 or hpath.find("1125575")>0 or hpath.find("1094564")>0 or hpath.find("I930220")>0 or hpath.find("S9088458")>0 or hpath.find("I1273574")>0 or hpath.find("I1261026")>0 or hpath.find("I1090423")>0 or hpath.find("QCD_11_010")>0 or hpath.find("1298811" )>0 or hpath.find("I1325553" )>0 or hpath.find("I1298810" )>0 or hpath.find("1307243" )>0 or hpath.find("I1419070")>0 or hpath.find("I1394679")>0 or + hpath.find("I1487277")>0 or hpath.find("CMS_2013_I1208923")>0 or hpath.find("1393758")>0 or hpath.find("ATLAS_2016_CONF_2016_092")>0 or hpath.find("1459051")>0) : if(type(hsets.values()[0].values()[0])==yoda.core.Counter) : outhistos[hpath] = yoda.core.Counter(hsets.values()[0].values()[0].path, hsets.values()[0].values()[0].title) elif(type(hsets.values()[0].values()[0])==yoda.core.Scatter2D) : outhistos[hpath] = yoda.core.Scatter2D(hsets.values()[0].values()[0].path, hsets.values()[0].values()[0].title) elif(type(hsets.values()[0].values()[0])==yoda.core.Profile1D) : outhistos[hpath] = yoda.core.Profile1D(hsets.values()[0].values()[0].path, hsets.values()[0].values()[0].title) for i in range(0,hsets.values()[0].values()[0].numBins) : outhistos[hpath].addBin(hsets.values()[0].values()[0].bins[i].xMin, hsets.values()[0].values()[0].bins[i].xMax) elif(type(hsets.values()[0].values()[0])==yoda.core.Histo1D) : outhistos[hpath] = yoda.core.Histo1D(hsets.values()[0].values()[0].path, hsets.values()[0].values()[0].title) for i in range(0,hsets.values()[0].values()[0].numBins) : outhistos[hpath].addBin(hsets.values()[0].values()[0].bins[i].xMin, hsets.values()[0].values()[0].bins[i].xMax) else : logging.error("Histogram %s is of unknown type" % hpath) sys.exit(1) ## Make empty output histos if needed for hpath,hsets in inhistos_mass.iteritems(): if(hpath.find("1268975")>0) : if(type(hsets.values()[0].values()[0])==yoda.core.Counter) : outhistos[hpath] = yoda.core.Counter(hsets.values()[0].values()[0].path, hsets.values()[0].values()[0].title) elif(type(hsets.values()[0].values()[0])==yoda.core.Scatter2D) : outhistos[hpath] = yoda.core.Scatter2D(hsets.values()[0].values()[0].path, hsets.values()[0].values()[0].title) elif(type(hsets.values()[0].values()[0])==yoda.core.Profile1D) : outhistos[hpath] = yoda.core.Profile1D(hsets.values()[0].values()[0].path, hsets.values()[0].values()[0].title) for i in range(0,hsets.values()[0].values()[0].numBins) : outhistos[hpath].addBin(hsets.values()[0].values()[0].bins[i].xMin, hsets.values()[0].values()[0].bins[i].xMax) elif(type(hsets.values()[0].values()[0])==yoda.core.Histo1D) : outhistos[hpath] = yoda.core.Histo1D(hsets.values()[0].values()[0].path, hsets.values()[0].values()[0].title) for i in range(0,hsets.values()[0].values()[0].numBins) : outhistos[hpath].addBin(hsets.values()[0].values()[0].bins[i].xMin, hsets.values()[0].values()[0].bins[i].xMax) else : logging.error("Histogram %s is of unknown type" % hpath) sys.exit(1) logging.info("Processing CMS_2011_S8957746") useOnePt("/CMS_2011_S8957746/d01-x01-y01", "7000", "80" ) useOnePt("/CMS_2011_S8957746/d02-x01-y01", "7000", "80" ) useOnePt("/CMS_2011_S8957746/d03-x01-y01", "7000", "110" ) useOnePt("/CMS_2011_S8957746/d04-x01-y01", "7000", "110" ) useOnePt("/CMS_2011_S8957746/d05-x01-y01", "7000", "210" ) useOnePt("/CMS_2011_S8957746/d06-x01-y01", "7000", "210" ) logging.info("Processing ATLAS_2010_S8894728") useOnePt("/ATLAS_2010_S8894728/d01-x01-y01", "900", "0" ) useOnePt("/ATLAS_2010_S8894728/d01-x01-y02", "900", "0" ) useOnePt("/ATLAS_2010_S8894728/d01-x01-y03", "900", "0" ) useOnePt("/ATLAS_2010_S8894728/d02-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2010_S8894728/d02-x01-y02", "7000", "0" ) useOnePt("/ATLAS_2010_S8894728/d02-x01-y03", "7000", "0" ) useOnePt("/ATLAS_2010_S8894728/d03-x01-y01", "900", "0" ) useOnePt("/ATLAS_2010_S8894728/d03-x01-y02", "900", "0" ) useOnePt("/ATLAS_2010_S8894728/d03-x01-y03", "900", "0" ) useOnePt("/ATLAS_2010_S8894728/d04-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2010_S8894728/d04-x01-y02", "7000", "0" ) useOnePt("/ATLAS_2010_S8894728/d04-x01-y03", "7000", "0" ) useOnePt("/ATLAS_2010_S8894728/d05-x01-y01", "900", "0" ) useOnePt("/ATLAS_2010_S8894728/d06-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2010_S8894728/d07-x01-y01", "900", "0" ) useOnePt("/ATLAS_2010_S8894728/d08-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2010_S8894728/d09-x01-y01", "900", "0" ) useOnePt("/ATLAS_2010_S8894728/d09-x01-y02", "900", "0" ) useOnePt("/ATLAS_2010_S8894728/d09-x01-y03", "900", "0" ) useOnePt("/ATLAS_2010_S8894728/d10-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2010_S8894728/d10-x01-y02", "7000", "0" ) useOnePt("/ATLAS_2010_S8894728/d10-x01-y03", "7000", "0" ) useOnePt("/ATLAS_2010_S8894728/d11-x01-y01", "900", "0" ) useOnePt("/ATLAS_2010_S8894728/d11-x01-y02", "900", "0" ) useOnePt("/ATLAS_2010_S8894728/d11-x01-y03", "900", "0" ) useOnePt("/ATLAS_2010_S8894728/d12-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2010_S8894728/d12-x01-y02", "7000", "0" ) useOnePt("/ATLAS_2010_S8894728/d12-x01-y03", "7000", "0" ) useOnePt("/ATLAS_2010_S8894728/d13-x01-y01", "900", "0" ) useOnePt("/ATLAS_2010_S8894728/d13-x01-y02", "900", "0" ) useOnePt("/ATLAS_2010_S8894728/d13-x01-y03", "900", "0" ) useOnePt("/ATLAS_2010_S8894728/d13-x01-y04", "900", "0" ) useOnePt("/ATLAS_2010_S8894728/d14-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2010_S8894728/d14-x01-y02", "7000", "0" ) useOnePt("/ATLAS_2010_S8894728/d14-x01-y03", "7000", "0" ) useOnePt("/ATLAS_2010_S8894728/d14-x01-y04", "7000", "0" ) useOnePt("/ATLAS_2010_S8894728/d15-x01-y01", "900", "0" ) useOnePt("/ATLAS_2010_S8894728/d15-x01-y02", "900", "0" ) useOnePt("/ATLAS_2010_S8894728/d15-x01-y03", "900", "0" ) useOnePt("/ATLAS_2010_S8894728/d15-x01-y04", "900", "0" ) useOnePt("/ATLAS_2010_S8894728/d16-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2010_S8894728/d16-x01-y02", "7000", "0" ) useOnePt("/ATLAS_2010_S8894728/d16-x01-y03", "7000", "0" ) useOnePt("/ATLAS_2010_S8894728/d16-x01-y04", "7000", "0" ) useOnePt("/ATLAS_2010_S8894728/d17-x01-y01", "900", "0" ) useOnePt("/ATLAS_2010_S8894728/d17-x01-y02", "900", "0" ) useOnePt("/ATLAS_2010_S8894728/d17-x01-y03", "900", "0" ) useOnePt("/ATLAS_2010_S8894728/d18-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2010_S8894728/d18-x01-y02", "7000", "0" ) useOnePt("/ATLAS_2010_S8894728/d18-x01-y03", "7000", "0" ) useOnePt("/ATLAS_2010_S8894728/d19-x01-y01", "900", "0" ) useOnePt("/ATLAS_2010_S8894728/d19-x01-y02", "900", "0" ) useOnePt("/ATLAS_2010_S8894728/d19-x01-y03", "900", "0" ) useOnePt("/ATLAS_2010_S8894728/d20-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2010_S8894728/d20-x01-y02", "7000", "0" ) useOnePt("/ATLAS_2010_S8894728/d20-x01-y03", "7000", "0" ) useOnePt("/ATLAS_2010_S8894728/d21-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2010_S8894728/d22-x01-y01", "7000", "0" ) logging.info("Processing ATLAS_2011_S8994773") useOnePt("/ATLAS_2011_S8994773/d01-x01-y01", "900", "0" ) useOnePt("/ATLAS_2011_S8994773/d02-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2011_S8994773/d03-x01-y01", "900", "0" ) useOnePt("/ATLAS_2011_S8994773/d04-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2011_S8994773/d13-x01-y01", "900", "0" ) useOnePt("/ATLAS_2011_S8994773/d13-x01-y02", "900", "0" ) useOnePt("/ATLAS_2011_S8994773/d13-x01-y03", "900", "0" ) useOnePt("/ATLAS_2011_S8994773/d14-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2011_S8994773/d14-x01-y02", "7000", "0" ) useOnePt("/ATLAS_2011_S8994773/d14-x01-y03", "7000", "0" ) logging.info("Processing ALICE_2010_S8624100") useOnePt("/ALICE_2010_S8624100/d11-x01-y01", "900", "0" ) useOnePt("/ALICE_2010_S8624100/d12-x01-y01", "900", "0" ) useOnePt("/ALICE_2010_S8624100/d13-x01-y01", "900", "0" ) useOnePt("/ALICE_2010_S8624100/d17-x01-y01","2360", "0" ) useOnePt("/ALICE_2010_S8624100/d18-x01-y01","2360", "0" ) useOnePt("/ALICE_2010_S8624100/d19-x01-y01","2360", "0" ) logging.info("Processing ALICE_2010_S8625980") useOnePt("/ALICE_2010_S8625980/d03-x01-y01", "7000", "0" ) useOnePt("/ALICE_2010_S8625980/d04-x01-y01", "900", "0" ) useOnePt("/ALICE_2010_S8625980/d05-x01-y01", "2360", "0" ) useOnePt("/ALICE_2010_S8625980/d06-x01-y01", "7000", "0" ) logging.info("Processing ATLAS_2010_S8918562") useOnePt("/ATLAS_2010_S8918562/d01-x01-y01", "900", "0" ) useOnePt("/ATLAS_2010_S8918562/d02-x01-y01", "2360", "0" ) useOnePt("/ATLAS_2010_S8918562/d03-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2010_S8918562/d04-x01-y01", "900", "0" ) useOnePt("/ATLAS_2010_S8918562/d05-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2010_S8918562/d06-x01-y01", "900", "0" ) useOnePt("/ATLAS_2010_S8918562/d07-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2010_S8918562/d08-x01-y01", "900", "0" ) useOnePt("/ATLAS_2010_S8918562/d09-x01-y01", "2360", "0" ) useOnePt("/ATLAS_2010_S8918562/d10-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2010_S8918562/d11-x01-y01", "900", "0" ) useOnePt("/ATLAS_2010_S8918562/d12-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2010_S8918562/d13-x01-y01", "900", "0" ) useOnePt("/ATLAS_2010_S8918562/d14-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2010_S8918562/d15-x01-y01", "900", "0" ) useOnePt("/ATLAS_2010_S8918562/d16-x01-y01", "2360", "0" ) useOnePt("/ATLAS_2010_S8918562/d17-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2010_S8918562/d18-x01-y01", "900", "0" ) useOnePt("/ATLAS_2010_S8918562/d19-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2010_S8918562/d20-x01-y01", "900", "0" ) useOnePt("/ATLAS_2010_S8918562/d21-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2010_S8918562/d22-x01-y01", "900", "0" ) useOnePt("/ATLAS_2010_S8918562/d23-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2010_S8918562/d24-x01-y01", "900", "0" ) useOnePt("/ATLAS_2010_S8918562/d25-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2010_S8918562/d26-x01-y01", "900", "0" ) useOnePt("/ATLAS_2010_S8918562/d27-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2010_S8918562/d28-x01-y01", "900", "0" ) useOnePt("/ATLAS_2010_S8918562/d29-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2010_S8918562/d30-x01-y01", "900", "0" ) useOnePt("/ATLAS_2010_S8918562/d31-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2010_S8918562/d32-x01-y01", "900", "0" ) useOnePt("/ATLAS_2010_S8918562/d33-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2010_S8918562/d34-x01-y01", "900", "0" ) useOnePt("/ATLAS_2010_S8918562/d35-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2010_S8918562/d36-x01-y01", "900", "0" ) useOnePt("/ATLAS_2010_S8918562/d37-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2010_S8918562/d38-x01-y01", "900", "0" ) useOnePt("/ATLAS_2010_S8918562/d39-x01-y01", "7000", "0" ) logging.info("Processing ATLAS_2011_S8971293") useOnePt("/ATLAS_2011_S8971293/d01-x01-y01", "7000", "110" ) useOnePt("/ATLAS_2011_S8971293/d01-x01-y02", "7000", "110" ) useOnePt("/ATLAS_2011_S8971293/d01-x01-y03", "7000", "210" ) useOnePt("/ATLAS_2011_S8971293/d01-x01-y04", "7000", "260" ) useOnePt("/ATLAS_2011_S8971293/d01-x01-y05", "7000", "260" ) useOnePt("/ATLAS_2011_S8971293/d01-x01-y06", "7000", "400" ) useOnePt("/ATLAS_2011_S8971293/d01-x01-y07", "7000", "400" ) useOnePt("/ATLAS_2011_S8971293/d01-x01-y08", "7000", "600" ) useOnePt("/ATLAS_2011_S8971293/d01-x01-y09", "7000", "600" ) logging.info("Processing ATLAS_2011_S8924791") if( not opts.ue) : useOnePt("/ATLAS_2011_S8924791/d01-x01-y01", "7000", "10" ) useOnePt("/ATLAS_2011_S8924791/d01-x01-y02", "7000", "10" ) useOnePt("/ATLAS_2011_S8924791/d01-x02-y01", "7000", "10" ) useOnePt("/ATLAS_2011_S8924791/d01-x02-y02", "7000", "10" ) useOnePt("/ATLAS_2011_S8924791/d01-x03-y01", "7000", "10" ) useOnePt("/ATLAS_2011_S8924791/d01-x03-y02", "7000", "10" ) useOnePt("/ATLAS_2011_S8924791/d01-x04-y01", "7000", "10" ) useOnePt("/ATLAS_2011_S8924791/d01-x04-y02", "7000", "10" ) useOnePt("/ATLAS_2011_S8924791/d01-x05-y01", "7000", "10" ) useOnePt("/ATLAS_2011_S8924791/d01-x05-y02", "7000", "10" ) useOnePt("/ATLAS_2011_S8924791/d01-x06-y01", "7000", "10" ) useOnePt("/ATLAS_2011_S8924791/d01-x06-y02", "7000", "10" ) else : useOnePt("/ATLAS_2011_S8924791/d01-x01-y01", "7000", "20" ) useOnePt("/ATLAS_2011_S8924791/d01-x01-y02", "7000", "20" ) useOnePt("/ATLAS_2011_S8924791/d01-x02-y01", "7000", "20" ) useOnePt("/ATLAS_2011_S8924791/d01-x02-y02", "7000", "20" ) useOnePt("/ATLAS_2011_S8924791/d01-x03-y01", "7000", "20" ) useOnePt("/ATLAS_2011_S8924791/d01-x03-y02", "7000", "20" ) useOnePt("/ATLAS_2011_S8924791/d01-x04-y01", "7000", "20" ) useOnePt("/ATLAS_2011_S8924791/d01-x04-y02", "7000", "20" ) useOnePt("/ATLAS_2011_S8924791/d01-x05-y01", "7000", "20" ) useOnePt("/ATLAS_2011_S8924791/d01-x05-y02", "7000", "20" ) useOnePt("/ATLAS_2011_S8924791/d01-x06-y01", "7000", "20" ) useOnePt("/ATLAS_2011_S8924791/d01-x06-y02", "7000", "20" ) useOnePt("/ATLAS_2011_S8924791/d02-x01-y01", "7000", "40" ) useOnePt("/ATLAS_2011_S8924791/d02-x01-y02", "7000", "40" ) useOnePt("/ATLAS_2011_S8924791/d02-x02-y01", "7000", "40" ) useOnePt("/ATLAS_2011_S8924791/d02-x02-y02", "7000", "40" ) useOnePt("/ATLAS_2011_S8924791/d02-x03-y01", "7000", "40" ) useOnePt("/ATLAS_2011_S8924791/d02-x03-y02", "7000", "40" ) useOnePt("/ATLAS_2011_S8924791/d02-x04-y01", "7000", "40" ) useOnePt("/ATLAS_2011_S8924791/d02-x04-y02", "7000", "40" ) useOnePt("/ATLAS_2011_S8924791/d02-x05-y01", "7000", "40" ) useOnePt("/ATLAS_2011_S8924791/d02-x05-y02", "7000", "40" ) useOnePt("/ATLAS_2011_S8924791/d02-x06-y01", "7000", "40" ) useOnePt("/ATLAS_2011_S8924791/d02-x06-y02", "7000", "40" ) useOnePt("/ATLAS_2011_S8924791/d03-x01-y01", "7000", "40" ) useOnePt("/ATLAS_2011_S8924791/d03-x01-y02", "7000", "40" ) useOnePt("/ATLAS_2011_S8924791/d03-x02-y01", "7000", "40" ) useOnePt("/ATLAS_2011_S8924791/d03-x02-y02", "7000", "40" ) useOnePt("/ATLAS_2011_S8924791/d03-x03-y01", "7000", "40" ) useOnePt("/ATLAS_2011_S8924791/d03-x03-y02", "7000", "40" ) useOnePt("/ATLAS_2011_S8924791/d03-x04-y01", "7000", "40" ) useOnePt("/ATLAS_2011_S8924791/d03-x04-y02", "7000", "40" ) useOnePt("/ATLAS_2011_S8924791/d03-x05-y01", "7000", "40" ) useOnePt("/ATLAS_2011_S8924791/d03-x05-y02", "7000", "40" ) useOnePt("/ATLAS_2011_S8924791/d03-x06-y01", "7000", "40" ) useOnePt("/ATLAS_2011_S8924791/d03-x06-y02", "7000", "40" ) useOnePt("/ATLAS_2011_S8924791/d04-x01-y01", "7000", "80" ) useOnePt("/ATLAS_2011_S8924791/d04-x01-y02", "7000", "80" ) useOnePt("/ATLAS_2011_S8924791/d04-x02-y01", "7000", "80" ) useOnePt("/ATLAS_2011_S8924791/d04-x02-y02", "7000", "80" ) useOnePt("/ATLAS_2011_S8924791/d04-x03-y01", "7000", "80" ) useOnePt("/ATLAS_2011_S8924791/d04-x03-y02", "7000", "80" ) useOnePt("/ATLAS_2011_S8924791/d04-x04-y01", "7000", "80" ) useOnePt("/ATLAS_2011_S8924791/d04-x04-y02", "7000", "80" ) useOnePt("/ATLAS_2011_S8924791/d04-x05-y01", "7000", "80" ) useOnePt("/ATLAS_2011_S8924791/d04-x05-y02", "7000", "80" ) useOnePt("/ATLAS_2011_S8924791/d04-x06-y01", "7000", "80" ) useOnePt("/ATLAS_2011_S8924791/d04-x06-y02", "7000", "80" ) useOnePt("/ATLAS_2011_S8924791/d05-x01-y01", "7000", "110" ) useOnePt("/ATLAS_2011_S8924791/d05-x01-y02", "7000", "110" ) useOnePt("/ATLAS_2011_S8924791/d05-x02-y01", "7000", "110" ) useOnePt("/ATLAS_2011_S8924791/d05-x02-y02", "7000", "110" ) useOnePt("/ATLAS_2011_S8924791/d05-x03-y01", "7000", "110" ) useOnePt("/ATLAS_2011_S8924791/d05-x03-y02", "7000", "110" ) useOnePt("/ATLAS_2011_S8924791/d05-x04-y01", "7000", "110" ) useOnePt("/ATLAS_2011_S8924791/d05-x04-y02", "7000", "110" ) useOnePt("/ATLAS_2011_S8924791/d05-x05-y01", "7000", "110" ) useOnePt("/ATLAS_2011_S8924791/d05-x05-y02", "7000", "110" ) useOnePt("/ATLAS_2011_S8924791/d05-x06-y01", "7000", "110" ) useOnePt("/ATLAS_2011_S8924791/d05-x06-y02", "7000", "110" ) useOnePt("/ATLAS_2011_S8924791/d06-x01-y01", "7000", "110" ) useOnePt("/ATLAS_2011_S8924791/d06-x01-y02", "7000", "110" ) useOnePt("/ATLAS_2011_S8924791/d06-x02-y01", "7000", "110" ) useOnePt("/ATLAS_2011_S8924791/d06-x02-y02", "7000", "110" ) useOnePt("/ATLAS_2011_S8924791/d06-x03-y01", "7000", "110" ) useOnePt("/ATLAS_2011_S8924791/d06-x03-y02", "7000", "110" ) useOnePt("/ATLAS_2011_S8924791/d06-x04-y01", "7000", "110" ) useOnePt("/ATLAS_2011_S8924791/d06-x04-y02", "7000", "110" ) useOnePt("/ATLAS_2011_S8924791/d06-x05-y01", "7000", "110" ) useOnePt("/ATLAS_2011_S8924791/d06-x05-y02", "7000", "110" ) useOnePt("/ATLAS_2011_S8924791/d06-x06-y01", "7000", "110" ) useOnePt("/ATLAS_2011_S8924791/d06-x06-y02", "7000", "110" ) useOnePt("/ATLAS_2011_S8924791/d07-x01-y01", "7000", "210" ) useOnePt("/ATLAS_2011_S8924791/d07-x01-y02", "7000", "210" ) useOnePt("/ATLAS_2011_S8924791/d07-x02-y01", "7000", "210" ) useOnePt("/ATLAS_2011_S8924791/d07-x02-y02", "7000", "210" ) useOnePt("/ATLAS_2011_S8924791/d07-x03-y01", "7000", "210" ) useOnePt("/ATLAS_2011_S8924791/d07-x03-y02", "7000", "210" ) useOnePt("/ATLAS_2011_S8924791/d07-x04-y01", "7000", "210" ) useOnePt("/ATLAS_2011_S8924791/d07-x04-y02", "7000", "210" ) useOnePt("/ATLAS_2011_S8924791/d07-x05-y01", "7000", "210" ) useOnePt("/ATLAS_2011_S8924791/d07-x05-y02", "7000", "210" ) useOnePt("/ATLAS_2011_S8924791/d07-x06-y01", "7000", "210" ) useOnePt("/ATLAS_2011_S8924791/d07-x06-y02", "7000", "210" ) useOnePt("/ATLAS_2011_S8924791/d08-x01-y01", "7000", "260" ) useOnePt("/ATLAS_2011_S8924791/d08-x01-y02", "7000", "260" ) useOnePt("/ATLAS_2011_S8924791/d08-x02-y01", "7000", "260" ) useOnePt("/ATLAS_2011_S8924791/d08-x02-y02", "7000", "260" ) useOnePt("/ATLAS_2011_S8924791/d08-x03-y01", "7000", "260" ) useOnePt("/ATLAS_2011_S8924791/d08-x03-y02", "7000", "260" ) useOnePt("/ATLAS_2011_S8924791/d08-x04-y01", "7000", "260" ) useOnePt("/ATLAS_2011_S8924791/d08-x04-y02", "7000", "260" ) useOnePt("/ATLAS_2011_S8924791/d08-x05-y01", "7000", "260" ) useOnePt("/ATLAS_2011_S8924791/d08-x05-y02", "7000", "260" ) useOnePt("/ATLAS_2011_S8924791/d08-x06-y01", "7000", "260" ) useOnePt("/ATLAS_2011_S8924791/d08-x06-y02", "7000", "260" ) useOnePt("/ATLAS_2011_S8924791/d09-x01-y01", "7000", "260" ) useOnePt("/ATLAS_2011_S8924791/d09-x01-y02", "7000", "260" ) useOnePt("/ATLAS_2011_S8924791/d09-x02-y01", "7000", "260" ) useOnePt("/ATLAS_2011_S8924791/d09-x02-y02", "7000", "260" ) useOnePt("/ATLAS_2011_S8924791/d09-x03-y01", "7000", "260" ) useOnePt("/ATLAS_2011_S8924791/d09-x03-y02", "7000", "260" ) useOnePt("/ATLAS_2011_S8924791/d09-x04-y01", "7000", "260" ) useOnePt("/ATLAS_2011_S8924791/d09-x04-y02", "7000", "260" ) useOnePt("/ATLAS_2011_S8924791/d09-x05-y01", "7000", "260" ) useOnePt("/ATLAS_2011_S8924791/d09-x05-y02", "7000", "260" ) useOnePt("/ATLAS_2011_S8924791/d09-x06-y01", "7000", "260" ) useOnePt("/ATLAS_2011_S8924791/d09-x06-y02", "7000", "260" ) useOnePt("/ATLAS_2011_S8924791/d10-x01-y01", "7000", "400" ) useOnePt("/ATLAS_2011_S8924791/d10-x01-y02", "7000", "400" ) useOnePt("/ATLAS_2011_S8924791/d10-x02-y01", "7000", "400" ) useOnePt("/ATLAS_2011_S8924791/d10-x02-y02", "7000", "400" ) useOnePt("/ATLAS_2011_S8924791/d10-x03-y01", "7000", "400" ) useOnePt("/ATLAS_2011_S8924791/d10-x03-y02", "7000", "400" ) useOnePt("/ATLAS_2011_S8924791/d10-x04-y01", "7000", "400" ) useOnePt("/ATLAS_2011_S8924791/d10-x04-y02", "7000", "400" ) useOnePt("/ATLAS_2011_S8924791/d10-x05-y01", "7000", "400" ) useOnePt("/ATLAS_2011_S8924791/d10-x05-y02", "7000", "400" ) useOnePt("/ATLAS_2011_S8924791/d10-x06-y01", "7000", "400" ) useOnePt("/ATLAS_2011_S8924791/d10-x06-y02", "7000", "400" ) useOnePt("/ATLAS_2011_S8924791/d11-x01-y01", "7000", "400" ) useOnePt("/ATLAS_2011_S8924791/d11-x01-y02", "7000", "400" ) useOnePt("/ATLAS_2011_S8924791/d11-x02-y01", "7000", "400" ) useOnePt("/ATLAS_2011_S8924791/d11-x02-y02", "7000", "400" ) useOnePt("/ATLAS_2011_S8924791/d11-x03-y01", "7000", "400" ) useOnePt("/ATLAS_2011_S8924791/d11-x03-y02", "7000", "400" ) useOnePt("/ATLAS_2011_S8924791/d11-x04-y01", "7000", "400" ) useOnePt("/ATLAS_2011_S8924791/d11-x04-y02", "7000", "400" ) useOnePt("/ATLAS_2011_S8924791/d11-x05-y01", "7000", "400" ) useOnePt("/ATLAS_2011_S8924791/d11-x05-y02", "7000", "400" ) useOnePt("/ATLAS_2011_S8924791/d11-x06-y01", "7000", "400" ) useOnePt("/ATLAS_2011_S8924791/d11-x06-y02", "7000", "400" ) logging.info("Processing ATLAS_2010_S8817804") mergeByPt("/ATLAS_2010_S8817804/d01-x01-y01", "7000") mergeByPt("/ATLAS_2010_S8817804/d02-x01-y01", "7000") mergeByPt("/ATLAS_2010_S8817804/d03-x01-y01", "7000") mergeByPt("/ATLAS_2010_S8817804/d04-x01-y01", "7000") mergeByPt("/ATLAS_2010_S8817804/d05-x01-y01", "7000") mergeByPt("/ATLAS_2010_S8817804/d06-x01-y01", "7000") mergeByPt("/ATLAS_2010_S8817804/d07-x01-y01", "7000") mergeByPt("/ATLAS_2010_S8817804/d08-x01-y01", "7000") mergeByPt("/ATLAS_2010_S8817804/d09-x01-y01", "7000") mergeByPt("/ATLAS_2010_S8817804/d10-x01-y01", "7000") mergeByMass("/ATLAS_2010_S8817804/d11-x01-y01", "7000") mergeByMass("/ATLAS_2010_S8817804/d12-x01-y01", "7000") mergeByMass("/ATLAS_2010_S8817804/d13-x01-y01", "7000") mergeByMass("/ATLAS_2010_S8817804/d14-x01-y01", "7000") mergeByMass("/ATLAS_2010_S8817804/d15-x01-y01", "7000") mergeByMass("/ATLAS_2010_S8817804/d16-x01-y01", "7000") mergeByMass("/ATLAS_2010_S8817804/d17-x01-y01", "7000") mergeByMass("/ATLAS_2010_S8817804/d18-x01-y01", "7000") mergeByMass("/ATLAS_2010_S8817804/d19-x01-y01", "7000") mergeByMass("/ATLAS_2010_S8817804/d20-x01-y01", "7000") useOneMass("/ATLAS_2010_S8817804/d21-x01-y01", "7000", "250" ) useOneMass("/ATLAS_2010_S8817804/d22-x01-y01", "7000", "250" ) useOneMass("/ATLAS_2010_S8817804/d23-x01-y01", "7000", "650" ) useOneMass("/ATLAS_2010_S8817804/d24-x01-y01", "7000", "250" ) useOneMass("/ATLAS_2010_S8817804/d25-x01-y01", "7000", "250" ) useOneMass("/ATLAS_2010_S8817804/d26-x01-y01", "7000", "650" ) logging.info("Processing ATLAS_2011_I930220") mergeByPt("/ATLAS_2011_I930220/d01-x01-y01", "7000" ) mergeByPt("/ATLAS_2011_I930220/d02-x01-y01", "7000" ) mergeByPt("/ATLAS_2011_I930220/d03-x01-y01", "7000" ) mergeByPt("/ATLAS_2011_I930220/d04-x01-y01", "7000" ) mergeByPt("/ATLAS_2011_I930220/d05-x01-y01", "7000" ) mergeByPt("/ATLAS_2011_I930220/d06-x01-y01", "7000" ) mergeByMass("/ATLAS_2011_I930220/d07-x01-y01", "7000") useOneMass("/ATLAS_2011_I930220/d08-x01-y01", "7000", "110" ) useOneMass("/ATLAS_2011_I930220/d09-x01-y01", "7000", "110" ) useOneMass("/ATLAS_2011_I930220/d10-x01-y01", "7000", "370" ) logging.info("Processing ATLAS_2012_I1082936") mergeByPt("/ATLAS_2012_I1082936/d01-x01-y01", "7000") mergeByPt("/ATLAS_2012_I1082936/d01-x01-y02", "7000") mergeByPt("/ATLAS_2012_I1082936/d01-x01-y03", "7000") mergeByPt("/ATLAS_2012_I1082936/d01-x01-y04", "7000") mergeByPt("/ATLAS_2012_I1082936/d01-x01-y05", "7000") mergeByPt("/ATLAS_2012_I1082936/d01-x01-y06", "7000") mergeByPt("/ATLAS_2012_I1082936/d01-x01-y07", "7000") mergeByPt("/ATLAS_2012_I1082936/d02-x01-y01", "7000") mergeByPt("/ATLAS_2012_I1082936/d02-x01-y02", "7000") mergeByPt("/ATLAS_2012_I1082936/d02-x01-y03", "7000") mergeByPt("/ATLAS_2012_I1082936/d02-x01-y04", "7000") mergeByPt("/ATLAS_2012_I1082936/d02-x01-y05", "7000") mergeByPt("/ATLAS_2012_I1082936/d02-x01-y06", "7000") mergeByPt("/ATLAS_2012_I1082936/d02-x01-y07", "7000") mergeByMass("/ATLAS_2012_I1082936/d03-x01-y01", "7000", 1000.) mergeByMass("/ATLAS_2012_I1082936/d03-x01-y02", "7000", 1000.) mergeByMass("/ATLAS_2012_I1082936/d03-x01-y03", "7000", 1000.) mergeByMass("/ATLAS_2012_I1082936/d03-x01-y04", "7000", 1000.) mergeByMass("/ATLAS_2012_I1082936/d03-x01-y05", "7000", 1000.) mergeByMass("/ATLAS_2012_I1082936/d03-x01-y06", "7000", 1000.) mergeByMass("/ATLAS_2012_I1082936/d03-x01-y07", "7000", 1000.) mergeByMass("/ATLAS_2012_I1082936/d03-x01-y08", "7000", 1000.) mergeByMass("/ATLAS_2012_I1082936/d03-x01-y09", "7000", 1000.) mergeByMass("/ATLAS_2012_I1082936/d04-x01-y01", "7000", 1000.) mergeByMass("/ATLAS_2012_I1082936/d04-x01-y02", "7000", 1000.) mergeByMass("/ATLAS_2012_I1082936/d04-x01-y03", "7000", 1000.) mergeByMass("/ATLAS_2012_I1082936/d04-x01-y04", "7000", 1000.) mergeByMass("/ATLAS_2012_I1082936/d04-x01-y05", "7000", 1000.) mergeByMass("/ATLAS_2012_I1082936/d04-x01-y06", "7000", 1000.) mergeByMass("/ATLAS_2012_I1082936/d04-x01-y07", "7000", 1000.) mergeByMass("/ATLAS_2012_I1082936/d04-x01-y08", "7000", 1000.) mergeByMass("/ATLAS_2012_I1082936/d04-x01-y09", "7000", 1000.) logging.info("Processing CMS_2011_S8968497") useOneMass("/CMS_2011_S8968497/d01-x01-y01", "7000", "1700" ) useOneMass("/CMS_2011_S8968497/d02-x01-y01", "7000", "1700" ) useOneMass("/CMS_2011_S8968497/d03-x01-y01", "7000", "1100" ) useOneMass("/CMS_2011_S8968497/d04-x01-y01", "7000", "1100" ) useOneMass("/CMS_2011_S8968497/d05-x01-y01", "7000", "650" ) useOneMass("/CMS_2011_S8968497/d06-x01-y01", "7000", "650" ) useOneMass("/CMS_2011_S8968497/d07-x01-y01", "7000", "250" ) useOneMass("/CMS_2011_S8968497/d08-x01-y01", "7000", "250" ) useOneMass("/CMS_2011_S8968497/d09-x01-y01", "7000", "250" ) logging.info("Processing ATLAS_2011_S9126244") mergeByPt("/ATLAS_2011_S9126244/d01-x01-y01", "7000") mergeByPt("/ATLAS_2011_S9126244/d01-x01-y02", "7000") mergeByPt("/ATLAS_2011_S9126244/d02-x01-y01", "7000") mergeByPt("/ATLAS_2011_S9126244/d02-x01-y02", "7000") mergeByPt("/ATLAS_2011_S9126244/d03-x01-y01", "7000") mergeByPt("/ATLAS_2011_S9126244/d03-x01-y02", "7000") mergeByPt("/ATLAS_2011_S9126244/d04-x01-y01", "7000") mergeByPt("/ATLAS_2011_S9126244/d04-x01-y02", "7000") mergeByPt("/ATLAS_2011_S9126244/d05-x01-y01", "7000") mergeByPt("/ATLAS_2011_S9126244/d05-x01-y02", "7000") useOnePt("/ATLAS_2011_S9126244/d06-x01-y01", "7000", "40" ) useOnePt("/ATLAS_2011_S9126244/d06-x01-y02", "7000", "40" ) useOnePt("/ATLAS_2011_S9126244/d07-x01-y01", "7000", "80" ) useOnePt("/ATLAS_2011_S9126244/d07-x01-y02", "7000", "80" ) useOnePt("/ATLAS_2011_S9126244/d08-x01-y01", "7000", "80" ) useOnePt("/ATLAS_2011_S9126244/d08-x01-y02", "7000", "80" ) useOnePt("/ATLAS_2011_S9126244/d09-x01-y01", "7000", "110" ) useOnePt("/ATLAS_2011_S9126244/d09-x01-y02", "7000", "110" ) useOnePt("/ATLAS_2011_S9126244/d10-x01-y01", "7000", "110" ) useOnePt("/ATLAS_2011_S9126244/d10-x01-y02", "7000", "110" ) useOnePt("/ATLAS_2011_S9126244/d11-x01-y01", "7000", "210" ) useOnePt("/ATLAS_2011_S9126244/d11-x01-y02", "7000", "210" ) useOnePt("/ATLAS_2011_S9126244/d12-x01-y01", "7000", "210" ) useOnePt("/ATLAS_2011_S9126244/d12-x01-y02", "7000", "210" ) useOnePt("/ATLAS_2011_S9126244/d13-x01-y01", "7000", "40" ) useOnePt("/ATLAS_2011_S9126244/d13-x01-y02", "7000", "40" ) useOnePt("/ATLAS_2011_S9126244/d14-x01-y01", "7000", "40" ) useOnePt("/ATLAS_2011_S9126244/d14-x01-y02", "7000", "40" ) useOnePt("/ATLAS_2011_S9126244/d15-x01-y01", "7000", "110" ) useOnePt("/ATLAS_2011_S9126244/d15-x01-y02", "7000", "110" ) useOnePt("/ATLAS_2011_S9126244/d16-x01-y01", "7000", "110" ) useOnePt("/ATLAS_2011_S9126244/d16-x01-y02", "7000", "110" ) useOnePt("/ATLAS_2011_S9126244/d17-x01-y01", "7000", "210" ) useOnePt("/ATLAS_2011_S9126244/d17-x01-y02", "7000", "210" ) useOnePt("/ATLAS_2011_S9126244/d18-x01-y01", "7000", "210" ) useOnePt("/ATLAS_2011_S9126244/d18-x01-y02", "7000", "210" ) useOnePt("/ATLAS_2011_S9126244/d19-x01-y01", "7000", "40" ) useOnePt("/ATLAS_2011_S9126244/d20-x01-y01", "7000", "80" ) useOnePt("/ATLAS_2011_S9126244/d21-x01-y01", "7000", "110" ) useOnePt("/ATLAS_2011_S9126244/d22-x01-y01", "7000", "110" ) useOnePt("/ATLAS_2011_S9126244/d23-x01-y01", "7000", "110" ) useOnePt("/ATLAS_2011_S9126244/d24-x01-y01", "7000", "210" ) useOnePt("/ATLAS_2011_S9126244/d25-x01-y01", "7000", "210" ) mergeByPt("/ATLAS_2011_S9126244/d26-x01-y01", "7000") mergeByPt("/ATLAS_2011_S9126244/d26-x01-y02", "7000") mergeByPt("/ATLAS_2011_S9126244/d27-x01-y01", "7000") mergeByPt("/ATLAS_2011_S9126244/d27-x01-y02", "7000") mergeByPt("/ATLAS_2011_S9126244/d28-x01-y01", "7000") mergeByPt("/ATLAS_2011_S9126244/d28-x01-y02", "7000") mergeByPt("/ATLAS_2011_S9126244/d29-x01-y01", "7000") mergeByPt("/ATLAS_2011_S9126244/d29-x01-y02", "7000") useOnePt("/ATLAS_2011_S9126244/d30-x01-y01", "7000", "40" ) useOnePt("/ATLAS_2011_S9126244/d31-x01-y01", "7000", "80" ) useOnePt("/ATLAS_2011_S9126244/d32-x01-y01", "7000", "110" ) useOnePt("/ATLAS_2011_S9126244/d33-x01-y01", "7000", "110" ) useOnePt("/ATLAS_2011_S9126244/d34-x01-y01", "7000", "110" ) useOnePt("/ATLAS_2011_S9126244/d35-x01-y01", "7000", "210" ) useOnePt("/ATLAS_2011_S9126244/d36-x01-y01", "7000", "210" ) useOnePt("/ATLAS_2011_S9126244/d37-x01-y01", "7000", "40" ) useOnePt("/ATLAS_2011_S9126244/d37-x01-y02", "7000", "40" ) useOnePt("/ATLAS_2011_S9126244/d38-x01-y01", "7000", "80" ) useOnePt("/ATLAS_2011_S9126244/d38-x01-y02", "7000", "80" ) useOnePt("/ATLAS_2011_S9126244/d39-x01-y01", "7000", "110" ) useOnePt("/ATLAS_2011_S9126244/d39-x01-y02", "7000", "110" ) useOnePt("/ATLAS_2011_S9126244/d40-x01-y01", "7000", "110" ) useOnePt("/ATLAS_2011_S9126244/d40-x01-y02", "7000", "110" ) useOnePt("/ATLAS_2011_S9126244/d41-x01-y01", "7000", "110" ) useOnePt("/ATLAS_2011_S9126244/d41-x01-y02", "7000", "110" ) useOnePt("/ATLAS_2011_S9126244/d42-x01-y01", "7000", "210" ) useOnePt("/ATLAS_2011_S9126244/d42-x01-y02", "7000", "210" ) useOnePt("/ATLAS_2011_S9126244/d43-x01-y01", "7000", "210" ) useOnePt("/ATLAS_2011_S9126244/d43-x01-y02", "7000", "210" ) # CMS_2011_S9120041 UE analysis logging.info("Processing CMS_2011_S9120041") mergeByPt("/CMS_2011_S9120041/d01-x01-y01", "7000") mergeByPt("/CMS_2011_S9120041/d02-x01-y01", "7000") if(opts.ue) : useOnePt("/CMS_2011_S9120041/d03-x01-y01", "900", "0" ) useOnePt("/CMS_2011_S9120041/d04-x01-y01", "900", "0" ) useOnePt("/CMS_2011_S9120041/d05-x01-y01", "7000", "0" ) useOnePt("/CMS_2011_S9120041/d06-x01-y01", "7000", "0" ) useOnePt("/CMS_2011_S9120041/d07-x01-y01", "7000", "0" ) useOnePt("/CMS_2011_S9120041/d11-x01-y01", "900", "0" ) useOnePt("/CMS_2011_S9120041/d12-x01-y01", "900", "0" ) useOnePt("/CMS_2011_S9120041/d13-x01-y01", "900", "0" ) useOnePt("/CMS_2011_S9120041/d08-x01-y01", "7000", "20" ) useOnePt("/CMS_2011_S9120041/d09-x01-y01", "7000", "20" ) useOnePt("/CMS_2011_S9120041/d10-x01-y01", "7000", "20" ) else : useOnePt("/CMS_2011_S9120041/d08-x01-y01", "7000", "10" ) useOnePt("/CMS_2011_S9120041/d09-x01-y01", "7000", "10" ) useOnePt("/CMS_2011_S9120041/d10-x01-y01", "7000", "10" ) # CMS dijet decorrelation logging.info("Processing CMS_2011_S8950903") useOnePt("/CMS_2011_S8950903/d01-x01-y01", "7000", "80" ) useOnePt("/CMS_2011_S8950903/d02-x01-y01", "7000", "110" ) useOnePt("/CMS_2011_S8950903/d03-x01-y01", "7000", "110" ) useOnePt("/CMS_2011_S8950903/d04-x01-y01", "7000", "210" ) useOnePt("/CMS_2011_S8950903/d05-x01-y01", "7000", "260" ) # CMS jet cross section logging.info("Processing CMS_2011_S9086218") mergeByPt("/CMS_2011_S9086218/d01-x01-y01", "7000") mergeByPt("/CMS_2011_S9086218/d02-x01-y01", "7000") mergeByPt("/CMS_2011_S9086218/d03-x01-y01", "7000") mergeByPt("/CMS_2011_S9086218/d04-x01-y01", "7000") mergeByPt("/CMS_2011_S9086218/d05-x01-y01", "7000") mergeByPt("/CMS_2011_S9086218/d06-x01-y01", "7000") # CMS 2/3 jet cross section ratio logging.info("Processing CMS_2011_S9086218") mergeByPt("/CMS_2011_S9088458/d01-x01-y01", "7000",500.) # ATLAS track jet logging.info("Processing ATLAS_2011_I919017") for d in range(1,3) : for y in range(1,5) : mergeByPt("/ATLAS_2011_I919017/d0%s-x01-y0%s" % (d,y), "7000") if( opts.ue) : for x in range(2,6) : for y in ["01","02","06","07","11","12","16","17","21","22"] : useOnePt("/ATLAS_2011_I919017/d0%s-x0%s-y%s" % (d,x,y), "7000", "0" ) for y in ["03","04","08","09","13","14","18","19","23","24"] : useOnePt("/ATLAS_2011_I919017/d0%s-x0%s-y%s" % (d,x,y), "7000", "4" ) for y in range(5,30,5) : useOnePt("/ATLAS_2011_I919017/d0%s-x%02d-y%02d" % (d,x,y) , "7000", "20" ) else : for x in range(2,6) : for y in range(5,30,5) : useOnePt("/ATLAS_2011_I919017/d0%s-x%02d-y%02d" % (d,x,y) , "7000", "10" ) logging.info("Processing ATLAS_2011_I926145") mergeByPt("/ATLAS_2011_I926145/d01-x01-y01", "7000",1.5) mergeByPt("/ATLAS_2011_I926145/d02-x01-y01", "7000",1.5) mergeByPt("/ATLAS_2011_I926145/d03-x01-y01", "7000",1.5) logging.info("Processing CMS_2011_S8941262") useOnePt("/CMS_2011_S8941262/d01-x01-y01", "7000", "10" ) useOnePt("/CMS_2011_S8941262/d03-x01-y01", "7000", "10" ) mergeByPt("/CMS_2011_S8941262/d02-x01-y01", "7000",1.5) logging.info("Processing CMS_2011_S8973270") useOnePt("/CMS_2011_S8973270/d01-x01-y01", "7000", "70" ) useOnePt("/CMS_2011_S8973270/d02-x01-y01", "7000", "100" ) useOnePt("/CMS_2011_S8973270/d03-x01-y01", "7000", "130" ) useOnePt("/CMS_2011_S8973270/d04-x01-y01", "7000", "70" ) useOnePt("/CMS_2011_S8973270/d05-x01-y01", "7000", "100" ) useOnePt("/CMS_2011_S8973270/d06-x01-y01", "7000", "130" ) logging.info("Processing ATLAS_2012_I1082009") useOnePt("/ATLAS_2012_I1082009/d08-x01-y01", "7000", "40" ) useOnePt("/ATLAS_2012_I1082009/d09-x01-y01", "7000", "40" ) useOnePt("/ATLAS_2012_I1082009/d10-x01-y01", "7000", "40" ) useOnePt("/ATLAS_2012_I1082009/d11-x01-y01", "7000", "80" ) useOnePt("/ATLAS_2012_I1082009/d12-x01-y01", "7000", "80" ) useOnePt("/ATLAS_2012_I1082009/d13-x01-y01", "7000", "40" ) logging.info("Processing ATLAS_2012_I1118269") mergeByPt("/ATLAS_2012_I1118269/d01-x01-y01", "7000") useOnePt("/ATLAS_2012_I1118269/d02-x01-y01", "7000", "10" ) logging.info("Processing ATLAS_2012_I1188891") mergeByPt("/ATLAS_2012_I1188891/d01-x01-y01", "7000") mergeByPt("/ATLAS_2012_I1188891/d02-x01-y01", "7000") mergeByPt("/ATLAS_2012_I1188891/d03-x01-y01", "7000") mergeByPt("/ATLAS_2012_I1188891/d04-x01-y01", "7000") mergeByPt("/ATLAS_2012_I1188891/d05-x01-y01", "7000") mergeByPt("/ATLAS_2012_I1188891/d06-x01-y01", "7000") logging.info("Processing CMS_2012_I1087342") mergeByPt("/CMS_2012_I1087342/d01-x01-y01", "7000") mergeByPt("/CMS_2012_I1087342/d02-x01-y01", "7000") mergeByPt("/CMS_2012_I1087342/d03-x01-y01", "7000") logging.info("Processing CMS_2012_PAS_QCD_11_010") mergeByPt("/CMS_2012_PAS_QCD_11_010/d01-x01-y01", "7000") mergeByPt("/CMS_2012_PAS_QCD_11_010/d02-x01-y01", "7000") mergeByPt("/CMS_2012_PAS_QCD_11_010/d03-x01-y01", "7000") mergeByPt("/CMS_2012_PAS_QCD_11_010/d04-x01-y01", "7000") logging.info("Processing ATLAS_2011_S9035664") mergeByPt("/ATLAS_2011_S9035664/d11-x01-y01", "7000") mergeByPt("/ATLAS_2011_S9035664/d12-x01-y01", "7000") mergeByPt("/ATLAS_2011_S9035664/d13-x01-y01", "7000") mergeByPt("/ATLAS_2011_S9035664/d14-x01-y01", "7000") mergeByPt("/ATLAS_2011_S9035664/d15-x01-y01", "7000") mergeByPt("/ATLAS_2011_S9035664/d16-x01-y01", "7000") mergeByPt("/ATLAS_2011_S9035664/d17-x01-y01", "7000") mergeByPt("/ATLAS_2011_S9035664/d18-x01-y01", "7000") mergeByPt("/ATLAS_2011_S9035664/d20-x01-y01", "7000") mergeByPt("/ATLAS_2011_S9035664/d21-x01-y01", "7000") mergeByPt("/ATLAS_2011_S9035664/d22-x01-y01", "7000") mergeByPt("/ATLAS_2011_S9035664/d23-x01-y01", "7000") logging.info("Processing ATLAS_2012_I1125575") mergeByPt("/ATLAS_2012_I1125575/d01-x01-y01", "7000") mergeByPt("/ATLAS_2012_I1125575/d01-x01-y02", "7000") mergeByPt("/ATLAS_2012_I1125575/d01-x02-y01", "7000") mergeByPt("/ATLAS_2012_I1125575/d01-x02-y02", "7000") mergeByPt("/ATLAS_2012_I1125575/d01-x03-y01", "7000") mergeByPt("/ATLAS_2012_I1125575/d01-x03-y02", "7000") mergeByPt("/ATLAS_2012_I1125575/d01-x04-y01", "7000") mergeByPt("/ATLAS_2012_I1125575/d01-x04-y02", "7000") mergeByPt("/ATLAS_2012_I1125575/d01-x05-y01", "7000") mergeByPt("/ATLAS_2012_I1125575/d01-x05-y02", "7000") mergeByPt("/ATLAS_2012_I1125575/d02-x01-y01", "7000") mergeByPt("/ATLAS_2012_I1125575/d02-x01-y02", "7000") mergeByPt("/ATLAS_2012_I1125575/d02-x02-y01", "7000") mergeByPt("/ATLAS_2012_I1125575/d02-x02-y02", "7000") mergeByPt("/ATLAS_2012_I1125575/d02-x03-y01", "7000") mergeByPt("/ATLAS_2012_I1125575/d02-x03-y02", "7000") mergeByPt("/ATLAS_2012_I1125575/d02-x04-y01", "7000") mergeByPt("/ATLAS_2012_I1125575/d02-x04-y02", "7000") mergeByPt("/ATLAS_2012_I1125575/d02-x05-y01", "7000") mergeByPt("/ATLAS_2012_I1125575/d02-x05-y02", "7000") mergeByPt("/ATLAS_2012_I1125575/d03-x01-y01", "7000") mergeByPt("/ATLAS_2012_I1125575/d03-x01-y02", "7000") mergeByPt("/ATLAS_2012_I1125575/d03-x02-y01", "7000") mergeByPt("/ATLAS_2012_I1125575/d03-x02-y02", "7000") mergeByPt("/ATLAS_2012_I1125575/d03-x03-y01", "7000") mergeByPt("/ATLAS_2012_I1125575/d03-x03-y02", "7000") mergeByPt("/ATLAS_2012_I1125575/d03-x04-y01", "7000") mergeByPt("/ATLAS_2012_I1125575/d03-x04-y02", "7000") mergeByPt("/ATLAS_2012_I1125575/d03-x05-y01", "7000") mergeByPt("/ATLAS_2012_I1125575/d03-x05-y02", "7000") for d in range(4,7) : for x in range(1,6) : if(opts.ue) : for y in range(1,9) : useOnePt("/ATLAS_2012_I1125575/d0%s-x0%s-y0%s" % (d,x,y), "7000", "0" ) for y in ["09","10","11","12","13","14","15","16"] : useOnePt("/ATLAS_2012_I1125575/d0%s-x0%s-y%s" % (d,x,y), "7000", "0" ) for y in range(17,19) : useOnePt("/ATLAS_2012_I1125575/d0%s-x0%s-y%s" % (d,x,y), "7000", "20" ) else : for y in range(17,19) : useOnePt("/ATLAS_2012_I1125575/d0%s-x0%s-y%s" % (d,x,y), "7000", "10" ) for y in range(19,21) : useOnePt("/ATLAS_2012_I1125575/d0%s-x0%s-y%s" % (d,x,y), "7000", "40" ) # ATLAS_2012_I1094564 useOnePt("/ATLAS_2012_I1094564/d01-x01-y01", "7000", "210" ) useOnePt("/ATLAS_2012_I1094564/d02-x01-y01", "7000", "260" ) useOnePt("/ATLAS_2012_I1094564/d03-x01-y01", "7000", "400" ) useOnePt("/ATLAS_2012_I1094564/d04-x01-y01", "7000", "400" ) useOnePt("/ATLAS_2012_I1094564/d05-x01-y01", "7000", "210" ) useOnePt("/ATLAS_2012_I1094564/d06-x01-y01", "7000", "260" ) useOnePt("/ATLAS_2012_I1094564/d07-x01-y01", "7000", "400" ) useOnePt("/ATLAS_2012_I1094564/d08-x01-y01", "7000", "400" ) useOnePt("/ATLAS_2012_I1094564/d09-x01-y01", "7000", "210" ) useOnePt("/ATLAS_2012_I1094564/d10-x01-y01", "7000", "260" ) useOnePt("/ATLAS_2012_I1094564/d11-x01-y01", "7000", "400" ) useOnePt("/ATLAS_2012_I1094564/d12-x01-y01", "7000", "400" ) useOnePt("/ATLAS_2012_I1094564/d13-x01-y01", "7000", "210" ) useOnePt("/ATLAS_2012_I1094564/d14-x01-y01", "7000", "260" ) useOnePt("/ATLAS_2012_I1094564/d15-x01-y01", "7000", "400" ) useOnePt("/ATLAS_2012_I1094564/d16-x01-y01", "7000", "400" ) useOnePt("/ATLAS_2012_I1094564/d17-x01-y01", "7000", "210" ) useOnePt("/ATLAS_2012_I1094564/d18-x01-y01", "7000", "260" ) useOnePt("/ATLAS_2012_I1094564/d19-x01-y01", "7000", "400" ) useOnePt("/ATLAS_2012_I1094564/d20-x01-y01", "7000", "400" ) useOnePt("/ATLAS_2012_I1094564/d21-x01-y01", "7000", "210" ) useOnePt("/ATLAS_2012_I1094564/d22-x01-y01", "7000", "260" ) useOnePt("/ATLAS_2012_I1094564/d23-x01-y01", "7000", "400" ) useOnePt("/ATLAS_2012_I1094564/d24-x01-y01", "7000", "400" ) useOnePt("/ATLAS_2012_I1094564/d25-x01-y01", "7000", "210" ) useOnePt("/ATLAS_2012_I1094564/d26-x01-y01", "7000", "260" ) useOnePt("/ATLAS_2012_I1094564/d27-x01-y01", "7000", "400" ) useOnePt("/ATLAS_2012_I1094564/d28-x01-y01", "7000", "400" ) useOnePt("/ATLAS_2012_I1094564/d29-x01-y01", "7000", "210" ) useOnePt("/ATLAS_2012_I1094564/d30-x01-y01", "7000", "260" ) useOnePt("/ATLAS_2012_I1094564/d31-x01-y01", "7000", "400" ) useOnePt("/ATLAS_2012_I1094564/d32-x01-y01", "7000", "400" ) useOnePt("/ATLAS_2012_I1094564/d33-x01-y01", "7000", "210" ) useOnePt("/ATLAS_2012_I1094564/d34-x01-y01", "7000", "260" ) useOnePt("/ATLAS_2012_I1094564/d35-x01-y01", "7000", "400" ) useOnePt("/ATLAS_2012_I1094564/d36-x01-y01", "7000", "400" ) logging.info("Processing CMS_2013_I1224539_DIJET") useOnePt("/CMS_2013_I1224539_DIJET/d01-x01-y01", "7000", "210" ) useOnePt("/CMS_2013_I1224539_DIJET/d02-x01-y01", "7000", "260" ) useOnePt("/CMS_2013_I1224539_DIJET/d03-x01-y01", "7000", "400" ) useOnePt("/CMS_2013_I1224539_DIJET/d04-x01-y01", "7000", "400" ) useOnePt("/CMS_2013_I1224539_DIJET/d05-x01-y01", "7000", "600" ) useOnePt("/CMS_2013_I1224539_DIJET/d06-x01-y01", "7000", "600" ) useOnePt("/CMS_2013_I1224539_DIJET/d07-x01-y01", "7000", "600" ) useOnePt("/CMS_2013_I1224539_DIJET/d08-x01-y01", "7000", "210" ) useOnePt("/CMS_2013_I1224539_DIJET/d09-x01-y01", "7000", "260" ) useOnePt("/CMS_2013_I1224539_DIJET/d10-x01-y01", "7000", "400" ) useOnePt("/CMS_2013_I1224539_DIJET/d11-x01-y01", "7000", "400" ) useOnePt("/CMS_2013_I1224539_DIJET/d12-x01-y01", "7000", "600" ) useOnePt("/CMS_2013_I1224539_DIJET/d13-x01-y01", "7000", "600" ) useOnePt("/CMS_2013_I1224539_DIJET/d14-x01-y01", "7000", "600" ) useOnePt("/CMS_2013_I1224539_DIJET/d15-x01-y01", "7000", "210" ) useOnePt("/CMS_2013_I1224539_DIJET/d16-x01-y01", "7000", "260" ) useOnePt("/CMS_2013_I1224539_DIJET/d17-x01-y01", "7000", "400" ) useOnePt("/CMS_2013_I1224539_DIJET/d18-x01-y01", "7000", "400" ) useOnePt("/CMS_2013_I1224539_DIJET/d19-x01-y01", "7000", "600" ) useOnePt("/CMS_2013_I1224539_DIJET/d20-x01-y01", "7000", "600" ) useOnePt("/CMS_2013_I1224539_DIJET/d21-x01-y01", "7000", "600" ) useOnePt("/CMS_2013_I1224539_DIJET/d22-x01-y01", "7000", "210" ) useOnePt("/CMS_2013_I1224539_DIJET/d23-x01-y01", "7000", "260" ) useOnePt("/CMS_2013_I1224539_DIJET/d24-x01-y01", "7000", "400" ) useOnePt("/CMS_2013_I1224539_DIJET/d25-x01-y01", "7000", "600" ) useOnePt("/CMS_2013_I1224539_DIJET/d26-x01-y01", "7000", "600" ) useOnePt("/CMS_2013_I1224539_DIJET/d27-x01-y01", "7000", "600" ) useOnePt("/CMS_2013_I1224539_DIJET/d28-x01-y01", "7000", "600" ) useOnePt("/CMS_2013_I1273574/d01-x01-y01", "7000", "80" ) mergeByPt("/CMS_2013_I1273574/d02-x01-y01", "7000",1.) useOnePt("/CMS_2013_I1273574/d03-x01-y01", "7000", "80" ) useOnePt("/CMS_2013_I1273574/d04-x01-y01", "7000", "80" ) useOnePt("/CMS_2013_I1273574/d05-x01-y01", "7000", "80" ) useOnePt("/CMS_2013_I1273574/d06-x01-y01", "7000", "80" ) mergeByPt("/CMS_2013_I1273574/d07-x01-y01", "7000",1.) useOnePt("/CMS_2013_I1273574/d08-x01-y01", "7000", "80" ) mergeByPt("/CMS_2013_I1273574/d09-x01-y01", "7000",1.) useOnePt("/CMS_2013_I1273574/d10-x01-y01", "7000", "80" ) mergeByPt("/CMS_2013_I1273574/d11-x01-y01", "7000",1.) useOnePt("/CMS_2013_I1261026/d01-x01-y01", "7000", "0" ) useOnePt("/CMS_2013_I1261026/d02-x01-y01", "7000", "0" ) useOnePt("/CMS_2013_I1261026/d03-x01-y01", "7000", "0" ) useOnePt("/CMS_2013_I1261026/d04-x01-y01", "7000", "0" ) useOnePt("/CMS_2013_I1261026/d05-x01-y01", "7000", "0" ) useOnePt("/CMS_2013_I1261026/d06-x01-y01", "7000", "0" ) useOnePt("/CMS_2013_I1261026/d07-x01-y01", "7000", "0" ) useOnePt("/CMS_2013_I1261026/d08-x01-y01", "7000", "0" ) useOnePt("/CMS_2013_I1261026/d09-x01-y01", "7000", "0" ) useOnePt("/CMS_2013_I1261026/d10-x01-y01", "7000", "0" ) useOnePt("/CMS_2013_I1261026/d11-x01-y01", "7000", "0" ) useOnePt("/CMS_2013_I1261026/d12-x01-y01", "7000", "0" ) useOnePt("/CMS_2013_I1261026/d13-x01-y01", "7000", "0" ) useOnePt("/CMS_2013_I1261026/d14-x01-y01", "7000", "0" ) useOnePt("/CMS_2013_I1261026/d15-x01-y01", "7000", "0" ) useOnePt("/CMS_2013_I1261026/d16-x01-y01", "7000", "0" ) useOnePt("/CMS_2013_I1261026/d17-x01-y01", "7000", "0" ) logging.info("Processing CMS_2012_I1090423") useOneMass("/CMS_2012_I1090423/d01-x01-y01", "7000", "2900" ) useOneMass("/CMS_2012_I1090423/d02-x01-y01", "7000", "2300" ) useOneMass("/CMS_2012_I1090423/d03-x01-y01", "7000", "1700" ) useOneMass("/CMS_2012_I1090423/d04-x01-y01", "7000", "1100" ) useOneMass("/CMS_2012_I1090423/d05-x01-y01", "7000", "1100" ) useOneMass("/CMS_2012_I1090423/d06-x01-y01", "7000", "650" ) useOneMass("/CMS_2012_I1090423/d07-x01-y01", "7000", "650" ) useOneMass("/CMS_2012_I1090423/d08-x01-y01", "7000", "250" ) useOneMass("/CMS_2012_I1090423/d09-x01-y01", "7000", "250" ) logging.info("Processing ATLAS_2014_I1298811") mergeByPt("/ATLAS_2014_I1298811/d01-x01-y01", "7000") mergeByPt("/ATLAS_2014_I1298811/d01-x01-y02", "7000") mergeByPt("/ATLAS_2014_I1298811/d02-x01-y01", "7000") mergeByPt("/ATLAS_2014_I1298811/d02-x01-y02", "7000") mergeByPt("/ATLAS_2014_I1298811/d03-x01-y01", "7000") mergeByPt("/ATLAS_2014_I1298811/d03-x01-y02", "7000") mergeByPt("/ATLAS_2014_I1298811/d04-x01-y01", "7000") mergeByPt("/ATLAS_2014_I1298811/d04-x01-y02", "7000") mergeByPt("/ATLAS_2014_I1298811/d05-x01-y01", "7000") mergeByPt("/ATLAS_2014_I1298811/d05-x01-y02", "7000") mergeByPt("/ATLAS_2014_I1298811/d06-x01-y01", "7000") mergeByPt("/ATLAS_2014_I1298811/d06-x01-y02", "7000") mergeByPt("/ATLAS_2014_I1298811/d07-x01-y01", "7000") mergeByPt("/ATLAS_2014_I1298811/d07-x01-y02", "7000") mergeByPt("/ATLAS_2014_I1298811/d08-x01-y01", "7000") mergeByPt("/ATLAS_2014_I1298811/d08-x01-y02", "7000") mergeByPt("/ATLAS_2014_I1298811/d09-x01-y01", "7000") mergeByPt("/ATLAS_2014_I1298811/d09-x01-y02", "7000") mergeByPt("/ATLAS_2014_I1298811/d10-x01-y01", "7000") mergeByPt("/ATLAS_2014_I1298811/d10-x01-y02", "7000") useOnePt("/ATLAS_2014_I1298811/d11-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2014_I1298811/d12-x01-y01", "7000", "0" ) useOnePt("/ATLAS_2014_I1298811/d13-x01-y01", "7000", "4" ) useOnePt("/ATLAS_2014_I1298811/d13-x01-y02", "7000", "4" ) useOnePt("/ATLAS_2014_I1298811/d14-x01-y01", "7000", "4" ) useOnePt("/ATLAS_2014_I1298811/d14-x01-y02", "7000", "4" ) useOnePt("/ATLAS_2014_I1298811/d15-x01-y01", "7000", "4" ) useOnePt("/ATLAS_2014_I1298811/d15-x01-y02", "7000", "4" ) useOnePt("/ATLAS_2014_I1298811/d25-x01-y01", "7000", "4" ) useOnePt("/ATLAS_2014_I1298811/d25-x01-y02", "7000", "4" ) useOnePt("/ATLAS_2014_I1298811/d26-x01-y01", "7000", "4" ) useOnePt("/ATLAS_2014_I1298811/d26-x01-y02", "7000", "4" ) useOnePt("/ATLAS_2014_I1298811/d27-x01-y01", "7000", "4" ) useOnePt("/ATLAS_2014_I1298811/d27-x01-y02", "7000", "4" ) useOnePt("/ATLAS_2014_I1298811/d16-x01-y01", "7000", "4" ) useOnePt("/ATLAS_2014_I1298811/d16-x01-y02", "7000", "4" ) useOnePt("/ATLAS_2014_I1298811/d17-x01-y01", "7000", "4" ) useOnePt("/ATLAS_2014_I1298811/d17-x01-y02", "7000", "4" ) useOnePt("/ATLAS_2014_I1298811/d18-x01-y01", "7000", "4" ) useOnePt("/ATLAS_2014_I1298811/d18-x01-y02", "7000", "4" ) useOnePt("/ATLAS_2014_I1298811/d28-x01-y01", "7000", "4" ) useOnePt("/ATLAS_2014_I1298811/d28-x01-y02", "7000", "4" ) useOnePt("/ATLAS_2014_I1298811/d29-x01-y01", "7000", "4" ) useOnePt("/ATLAS_2014_I1298811/d29-x01-y02", "7000", "4" ) useOnePt("/ATLAS_2014_I1298811/d30-x01-y01", "7000", "4" ) useOnePt("/ATLAS_2014_I1298811/d30-x01-y02", "7000", "4" ) useOnePt("/ATLAS_2014_I1298811/d19-x01-y01", "7000", "40" ) useOnePt("/ATLAS_2014_I1298811/d19-x01-y02", "7000", "40" ) useOnePt("/ATLAS_2014_I1298811/d20-x01-y01", "7000", "40" ) useOnePt("/ATLAS_2014_I1298811/d20-x01-y02", "7000", "40" ) useOnePt("/ATLAS_2014_I1298811/d21-x01-y01", "7000", "40" ) useOnePt("/ATLAS_2014_I1298811/d21-x01-y02", "7000", "40" ) useOnePt("/ATLAS_2014_I1298811/d31-x01-y01", "7000", "40" ) useOnePt("/ATLAS_2014_I1298811/d31-x01-y02", "7000", "40" ) useOnePt("/ATLAS_2014_I1298811/d32-x01-y01", "7000", "40" ) useOnePt("/ATLAS_2014_I1298811/d32-x01-y02", "7000", "40" ) useOnePt("/ATLAS_2014_I1298811/d33-x01-y01", "7000", "40" ) useOnePt("/ATLAS_2014_I1298811/d33-x01-y02", "7000", "40" ) useOnePt("/ATLAS_2014_I1298811/d22-x01-y01", "7000", "210" ) useOnePt("/ATLAS_2014_I1298811/d22-x01-y02", "7000", "210" ) useOnePt("/ATLAS_2014_I1298811/d23-x01-y01", "7000", "210" ) useOnePt("/ATLAS_2014_I1298811/d23-x01-y02", "7000", "210" ) useOnePt("/ATLAS_2014_I1298811/d24-x01-y01", "7000", "210" ) useOnePt("/ATLAS_2014_I1298811/d24-x01-y02", "7000", "210" ) useOnePt("/ATLAS_2014_I1298811/d34-x01-y01", "7000", "210" ) useOnePt("/ATLAS_2014_I1298811/d34-x01-y02", "7000", "210" ) useOnePt("/ATLAS_2014_I1298811/d35-x01-y01", "7000", "210" ) useOnePt("/ATLAS_2014_I1298811/d35-x01-y02", "7000", "210" ) useOnePt("/ATLAS_2014_I1298811/d36-x01-y01", "7000", "210" ) useOnePt("/ATLAS_2014_I1298811/d36-x01-y02", "7000", "210" ) logging.info("Processing ATLAS_2014_I1268975") mergeByMass("/ATLAS_2014_I1268975/d01-x01-y01", "7000", 1000.) mergeByMass("/ATLAS_2014_I1268975/d01-x01-y02", "7000", 1000.) mergeByMass("/ATLAS_2014_I1268975/d01-x01-y03", "7000", 1000.) mergeByMass("/ATLAS_2014_I1268975/d01-x01-y04", "7000", 1000.) mergeByMass("/ATLAS_2014_I1268975/d01-x01-y05", "7000", 1000.) mergeByMass("/ATLAS_2014_I1268975/d01-x01-y06", "7000", 1000.) mergeByMass("/ATLAS_2014_I1268975/d02-x01-y01", "7000", 1000.) mergeByMass("/ATLAS_2014_I1268975/d02-x01-y02", "7000", 1000.) mergeByMass("/ATLAS_2014_I1268975/d02-x01-y03", "7000", 1000.) mergeByMass("/ATLAS_2014_I1268975/d02-x01-y04", "7000", 1000.) mergeByMass("/ATLAS_2014_I1268975/d02-x01-y05", "7000", 1000.) mergeByMass("/ATLAS_2014_I1268975/d02-x01-y06", "7000", 1000.) logging.info("Processing ATLAS_2014_I1307243") useOnePt( "/ATLAS_2014_I1307243/d01-x01-y01", "7000", "80" ) mergeByPt("/ATLAS_2014_I1307243/d02-x01-y01", "7000") useOnePt( "/ATLAS_2014_I1307243/d03-x01-y01", "7000", "80" ) mergeByPt("/ATLAS_2014_I1307243/d04-x01-y01", "7000") useOnePt( "/ATLAS_2014_I1307243/d05-x01-y01", "7000", "80" ) mergeByPt("/ATLAS_2014_I1307243/d06-x01-y01", "7000") useOnePt( "/ATLAS_2014_I1307243/d07-x01-y01", "7000", "80" ) mergeByPt("/ATLAS_2014_I1307243/d08-x01-y01", "7000") useOnePt( "/ATLAS_2014_I1307243/d09-x01-y01", "7000", "80" ) mergeByPt("/ATLAS_2014_I1307243/d10-x01-y01", "7000") useOnePt( "/ATLAS_2014_I1307243/d11-x01-y01", "7000", "80" ) mergeByPt("/ATLAS_2014_I1307243/d12-x01-y01", "7000") useOnePt( "/ATLAS_2014_I1307243/d13-x01-y01", "7000", "80" ) useOnePt( "/ATLAS_2014_I1307243/d14-x01-y01", "7000", "80" ) useOnePt( "/ATLAS_2014_I1307243/d15-x01-y01", "7000", "80" ) useOnePt( "/ATLAS_2014_I1307243/d16-x01-y01", "7000", "80" ) useOnePt( "/ATLAS_2014_I1307243/d17-x01-y01", "7000", "80" ) useOnePt( "/ATLAS_2014_I1307243/d18-x01-y01", "7000", "80" ) useOnePt( "/ATLAS_2014_I1307243/d19-x01-y01", "7000", "80" ) useOnePt( "/ATLAS_2014_I1307243/d20-x01-y01", "7000", "80" ) useOnePt( "/ATLAS_2014_I1307243/d21-x01-y01", "7000", "80" ) useOnePt( "/ATLAS_2014_I1307243/d22-x01-y01", "7000", "80" ) useOnePt( "/ATLAS_2014_I1307243/d23-x01-y01", "7000", "80" ) useOnePt( "/ATLAS_2014_I1307243/d24-x01-y01", "7000", "80" ) useOnePt( "/ATLAS_2014_I1307243/d25-x01-y01", "7000", "80" ) useOnePt( "/ATLAS_2014_I1307243/d26-x01-y01", "7000", "80" ) useOnePt( "/ATLAS_2014_I1307243/d27-x01-y01", "7000", "80" ) useOnePt( "/ATLAS_2014_I1307243/d28-x01-y01", "7000", "80" ) useOnePt( "/ATLAS_2014_I1307243/d29-x01-y01", "7000", "80" ) useOnePt( "/ATLAS_2014_I1307243/d30-x01-y01", "7000", "80" ) useOnePt( "/ATLAS_2014_I1307243/d31-x01-y01", "7000", "80" ) useOnePt( "/ATLAS_2014_I1307243/d32-x01-y01", "7000", "80" ) useOnePt( "/ATLAS_2014_I1307243/d33-x01-y01", "7000", "80" ) useOnePt( "/ATLAS_2014_I1307243/d34-x01-y01", "7000", "80" ) useOnePt( "/ATLAS_2014_I1307243/d35-x01-y01", "7000", "80" ) useOnePt( "/ATLAS_2014_I1307243/d36-x01-y01", "7000", "80" ) useOnePt( "/ATLAS_2014_I1307243/d37-x01-y01", "7000", "80" ) mergeByPt("/ATLAS_2014_I1307243/d38-x01-y01", "7000") useOnePt( "/ATLAS_2014_I1307243/d39-x01-y01", "7000", "80" ) mergeByPt("/ATLAS_2014_I1307243/d40-x01-y01", "7000") logging.info("Processing ATLAS_2014_I1325553") mergeByPt("/ATLAS_2014_I1325553/d01-x01-y01", "7000") mergeByPt("/ATLAS_2014_I1325553/d01-x01-y02", "7000") mergeByPt("/ATLAS_2014_I1325553/d01-x01-y03", "7000") mergeByPt("/ATLAS_2014_I1325553/d01-x01-y04", "7000") mergeByPt("/ATLAS_2014_I1325553/d01-x01-y05", "7000") mergeByPt("/ATLAS_2014_I1325553/d01-x01-y06", "7000") mergeByPt("/ATLAS_2014_I1325553/d02-x01-y01", "7000") mergeByPt("/ATLAS_2014_I1325553/d02-x01-y02", "7000") mergeByPt("/ATLAS_2014_I1325553/d02-x01-y03", "7000") mergeByPt("/ATLAS_2014_I1325553/d02-x01-y04", "7000") mergeByPt("/ATLAS_2014_I1325553/d02-x01-y05", "7000") mergeByPt("/ATLAS_2014_I1325553/d02-x01-y06", "7000") logging.info("Processing ATLAS_2016_I1419070") for i in range(1,13) : if(i<10) : mergeByPt("/ATLAS_2016_I1419070/d0%s-x01-y01" % i, "8000") else : mergeByPt("/ATLAS_2016_I1419070/d%s-x01-y01" % i, "8000") # remake differences and sums for ihist in range(1,4) : if not ("/ATLAS_2016_I1419070/d0%s-x01-y01" % ihist) in outhistos : continue h1 = outhistos["/ATLAS_2016_I1419070/d0%s-x01-y01" % ihist ] h2 = outhistos["/ATLAS_2016_I1419070/d0%s-x01-y01" % (ihist+3)] sstring = "/ATLAS_2016_I1419070/d%s-x01-y01" % (9+ihist) dstring = "/ATLAS_2016_I1419070/d0%s-x01-y01" % (6+ihist) hdiff = yoda.Scatter2D(dstring,dstring) hsum = yoda.Scatter2D(sstring,sstring) outhistos[dstring]= hdiff outhistos[sstring]= hsum for nbin in range(0,h2.numBins) : bsum = h1.bins[nbin]+h2.bins[nbin] try: ydiff = h2.bins[nbin].mean-h1.bins[nbin].mean except: ydiff = 0 try: ysum = bsum.mean bstderr = bsum.stdErr except: ysum = 0 bstderr = 0 try: yerr = math.sqrt(h1.bins[nbin].stdErr**2+h2.bins[nbin].stdErr**2) except: yerr = 0 x = h1.bins[nbin].xMid xerr = 0.5*h1.bins[nbin].xWidth hdiff.addPoint(x,ydiff,xerr,yerr) hsum.addPoint(x,ysum ,xerr,bstderr) logging.info("ATLAS_2015_I1394679") for i in range(1,5) : mergeByPt("/ATLAS_2015_I1394679/d0%s-x01-y01" % i, "8000") for i in range(5,11) : if(i<10) : useOnePt( "/ATLAS_2015_I1394679/d0%s-x01-y01" % i, "8000", "110" ) else : useOnePt( "/ATLAS_2015_I1394679/d%s-x01-y01" % i, "8000", "110" ) for i in range(0,4) : useOnePt( "/ATLAS_2015_I1394679/d%s-x01-y01" % (11+4*i), "8000", "110" ) useOnePt( "/ATLAS_2015_I1394679/d%s-x01-y01" % (12+4*i), "8000", "260" ) useOnePt( "/ATLAS_2015_I1394679/d%s-x01-y01" % (13+4*i), "8000", "600" ) useOnePt( "/ATLAS_2015_I1394679/d%s-x01-y01" % (14+4*i), "8000", "900" ) for i in range(0,5) : useOnePt( "/ATLAS_2015_I1394679/d%s-x01-y01" % (27+4*i), "8000", "110" ) useOnePt( "/ATLAS_2015_I1394679/d%s-x01-y01" % (28+4*i), "8000", "260" ) useOnePt( "/ATLAS_2015_I1394679/d%s-x01-y01" % (29+4*i), "8000", "400" ) useOnePt( "/ATLAS_2015_I1394679/d%s-x01-y01" % (30+4*i), "8000", "400" ) logging.info("Processing CMS_2013_I1208923") for i in range(1,6) : mergeByPt ("/CMS_2013_I1208923/d01-x01-y0%s" % i, "7000") mergeByMass("/CMS_2013_I1208923/d02-x01-y0%s" % i, "7000", 1.) logging.info("Processing CMS_2014_I1298810") for i in range(1,19) : if(i<10) : mergeByPt("/CMS_2014_I1298810/d0"+str(i)+"-x01-y01", "7000") else : mergeByPt("/CMS_2014_I1298810/d"+str(i)+"-x01-y01", "7000") logging.info("Processing CMS_2014_I1305624") for x in range(1,6) : useOnePt( "/CMS_2014_I1305624/d01-x%02d-y01" % x, "7000", "110" ) useOnePt( "/CMS_2014_I1305624/d01-x%02d-y02" % x, "7000", "110" ) useOnePt( "/CMS_2014_I1305624/d01-x%02d-y03" % x, "7000", "260" ) useOnePt( "/CMS_2014_I1305624/d01-x%02d-y04" % x, "7000", "260" ) useOnePt( "/CMS_2014_I1305624/d01-x%02d-y05" % x, "7000", "400" ) logging.info("Processing ATLAS_2011_I929691") for x in range(0,3) : useOnePt( "/ATLAS_2011_I929691/d%02d-x01-y01" % (10*x+ 1), "7000", "20" ) useOnePt( "/ATLAS_2011_I929691/d%02d-x01-y01" % (10*x+ 2), "7000", "40" ) useOnePt( "/ATLAS_2011_I929691/d%02d-x01-y01" % (10*x+ 3), "7000", "40" ) useOnePt( "/ATLAS_2011_I929691/d%02d-x01-y01" % (10*x+ 4), "7000", "80" ) useOnePt( "/ATLAS_2011_I929691/d%02d-x01-y01" % (10*x+ 5), "7000", "110" ) useOnePt( "/ATLAS_2011_I929691/d%02d-x01-y01" % (10*x+ 6), "7000", "110" ) useOnePt( "/ATLAS_2011_I929691/d%02d-x01-y01" % (10*x+ 7), "7000", "210" ) useOnePt( "/ATLAS_2011_I929691/d%02d-x01-y01" % (10*x+ 8), "7000", "260" ) useOnePt( "/ATLAS_2011_I929691/d%02d-x01-y01" % (10*x+ 9), "7000", "260" ) useOnePt( "/ATLAS_2011_I929691/d%02d-x01-y01" % (10*x+10), "7000", "400" ) logging.info("Processing ATLAS_2015_I1393758") for i in range(1,13) : mergeByPt("/ATLAS_2015_I1393758/d%02d-x01-y01" % i, "8000") logging.info("Processing CMS_2016_I1459051") for i in range(1,15) : mergeByPt("/CMS_2016_I1459051/d%02d-x01-y01" % i, "13000") logging.info("Processing ATLAS_2016_CONF_2016_092") for i in range(1,7) : mergeByPt("/ATLAS_2016_CONF_2016_092/d%02d-x01-y01" % i, "13000") -aopath.find("")>0 + +logging.info("Processing ATLAS_2017_I1609253") +useOnePt( "/ATLAS_2017_I1609253/d01-x01-y01", "8000", "260" ) +useOnePt( "/ATLAS_2017_I1609253/d02-x01-y01", "8000", "260" ) +useOnePt( "/ATLAS_2017_I1609253/d03-x01-y01", "8000", "260" ) +useOnePt( "/ATLAS_2017_I1609253/d04-x01-y01", "8000", "260" ) +useOnePt( "/ATLAS_2017_I1609253/d05-x01-y01", "8000", "400" ) +useOnePt( "/ATLAS_2017_I1609253/d06-x01-y01", "8000", "400" ) +useOnePt( "/ATLAS_2017_I1609253/d07-x01-y01", "8000", "400" ) +useOnePt( "/ATLAS_2017_I1609253/d08-x01-y01", "8000", "400" ) +useOnePt( "/ATLAS_2017_I1609253/d09-x01-y01", "8000", "400" ) +useOnePt( "/ATLAS_2017_I1609253/d10-x01-y01", "8000", "400" ) +useOnePt( "/ATLAS_2017_I1609253/d11-x01-y01", "8000", "600" ) +useOnePt( "/ATLAS_2017_I1609253/d12-x01-y01", "8000", "600" ) + +logging.info("Processing CMS_2016_I1487277") +mergeByPt("/CMS_2016_I1487277/d01-x01-y01", "8000") +mergeByPt("/CMS_2016_I1487277/d02-x01-y01", "8000") +mergeByPt("/CMS_2016_I1487277/d03-x01-y01", "8000") +mergeByPt("/CMS_2016_I1487277/d04-x01-y01", "8000") +mergeByPt("/CMS_2016_I1487277/d05-x01-y01", "8000") +mergeByPt("/CMS_2016_I1487277/d06-x01-y01", "8000") +mergeByPt("/CMS_2016_I1487277/d07-x01-y01", "8000") + +logging.info("Processing CMS_2016_I1421646") +useOnePt( "/CMS_2016_I1421646/d01-x01-y01", "8000", "210" ) +useOnePt( "/CMS_2016_I1421646/d02-x01-y01", "8000", "260" ) +useOnePt( "/CMS_2016_I1421646/d03-x01-y01", "8000", "400" ) +useOnePt( "/CMS_2016_I1421646/d04-x01-y01", "8000", "400" ) +useOnePt( "/CMS_2016_I1421646/d05-x01-y01", "8000", "600" ) +useOnePt( "/CMS_2016_I1421646/d06-x01-y01", "8000", "900" ) +useOnePt( "/CMS_2016_I1421646/d07-x01-y01", "8000", "900" ) + # Choose output file name = args[0]+"-Jets.yoda" yoda.writeYODA(outhistos,name) sys.exit(0) diff --git a/Tests/python/merge-LHC-Photon b/Tests/python/merge-LHC-Photon --- a/Tests/python/merge-LHC-Photon +++ b/Tests/python/merge-LHC-Photon @@ -1,275 +1,288 @@ #! /usr/bin/env python import logging import sys import os, yoda """%prog Script for merging aida files """ def fillAbove(scale,desthisto, sourcehistosbyptmin): pthigh= 1e100 ptlow =-1e100 for pt, h in sorted(sourcehistosbyptmin.iteritems(),reverse=True): ptlow=pt if(type(desthisto)==yoda.core.Scatter2D) : for i in range(0,h.numPoints) : xMin = h.points[i].x-h.points[i].xErrs.minus if( xMin*scale >= ptlow and xMin*scale < pthigh ) : desthisto.addPoint(h.points[i]) elif(type(desthisto)==yoda.core.Profile1D) : for i in range(0,h.numBins) : if(h.bins[i].xMin*scale >= ptlow and h.bins[i].xMin*scale < pthigh ) : desthisto.bins[i] += h.bins[i] elif(type(desthisto)==yoda.core.Histo1D) : for i in range(0,h.numBins) : if(h.bins[i].xMin*scale >= ptlow and h.bins[i].xMin*scale < pthigh ) : desthisto.bins[i] += h.bins[i] else : logging.error("Can't merge %s, unknown type" % desthisto.path) sys.exit(1) pthigh=pt def mergeByPt(hpath, scale=1.): global inhistos global outhistos try: fillAbove(scale,outhistos[hpath], inhistos[hpath]) except: pass def useOnePt(hpath, ptmin): global inhistos global outhistos try: ## Find best pT_min match ptmins = inhistos[hpath].keys() closest_ptmin = None for ptm in ptmins: if closest_ptmin is None or \ abs(ptm-float(ptmin)) < abs(closest_ptmin-float(ptmin)): closest_ptmin = ptm if closest_ptmin != float(ptmin): logging.warning("Inexact match for requested pTmin=%s: " % ptmin + \ "using pTmin=%e instead" % closest_ptmin) outhistos[hpath] = inhistos[hpath][closest_ptmin] except: pass if sys.version_info[:3] < (2,4,0): print "rivet scripts require Python version >= 2.4.0... exiting" sys.exit(1) if __name__ == "__main__": import logging from optparse import OptionParser, OptionGroup parser = OptionParser(usage="%prog aidafile aidafile2 [...]") parser.add_option("-o", "--out", dest="OUTFILE", default="-") verbgroup = OptionGroup(parser, "Verbosity control") verbgroup.add_option("-v", "--verbose", action="store_const", const=logging.DEBUG, dest="LOGLEVEL", default=logging.INFO, help="print debug (very verbose) messages") verbgroup.add_option("-q", "--quiet", action="store_const", const=logging.WARNING, dest="LOGLEVEL", default=logging.INFO, help="be very quiet") parser.add_option_group(verbgroup) (opts, args) = parser.parse_args() logging.basicConfig(level=opts.LOGLEVEL, format="%(message)s") ## Check args if len(args) < 1: logging.error("Must specify at least the name of the files") sys.exit(1) files=["-7-PromptPhoton-1.yoda","-7-PromptPhoton-2.yoda", "-7-PromptPhoton-3.yoda","-7-PromptPhoton-4.yoda", "-8-PromptPhoton-1.yoda","-8-PromptPhoton-2.yoda", "-8-PromptPhoton-3.yoda","-8-PromptPhoton-4.yoda", "-7-DiPhoton-GammaGamma.yoda","-7-DiPhoton-GammaJet.yoda","-GammaGamma-7.yoda", "-8-DiPhoton-GammaGamma.yoda","-8-DiPhoton-GammaJet.yoda","-GammaGamma-8.yoda"] ## Get histos inhistos = {} outhistos={} for f in files: file='Rivet-'+args[0]+f if not os.access(file, os.R_OK): logging.error("%s can not be read" % file) continue try: aos = yoda.read(file) except: logging.error("%s can not be parsed as XML" % file) break if(file.find("PromptPhoton")>=0) : if(file.find("PromptPhoton-1")>0) : ptmin=0. elif(file.find("PromptPhoton-2")>0) : ptmin=35. elif(file.find("PromptPhoton-3")>0) : ptmin=90. elif(file.find("PromptPhoton-4")>0) : ptmin=170. ## Get histos from this YODA file for aopath, ao in aos.iteritems() : if not inhistos.has_key(aopath): inhistos[aopath] = {} if (aopath.find("CMS_2013_I1258128")>0) : if(aopath.find("d05")>0 or aopath.find("d06")>0 or aopath.find("d07")>0 or aopath.find("d08")>0) : inhistos[aopath][ptmin] = ao else : inhistos[aopath][ptmin] = ao else : ## Get histos from this YODA file for aopath, ao in aos.iteritems() : if(aopath.find("XSEC")>=0 or aopath.find("EVTCOUNT")>=0) : continue - print aopath if ( aopath in outhistos ) : aotype = type(ao) if aotype in (yoda.Counter, yoda.Histo1D, yoda.Histo2D, yoda.Profile1D, yoda.Profile2D): outhistos[aopath] += ao else : quit() else: outhistos[aopath] = ao for hpath,hsets in inhistos.iteritems(): - if( hpath.find("1263495")>0 or - hpath.find("1093738")>0 or - hpath.find("921594")>0 or - hpath.find("8914702")>0 or - hpath.find("1244522")>0 or - hpath.find("1457605")>0 ) : + if( hpath.find("1263495")>0 or hpath.find("1093738")>0 or + hpath.find("921594" )>0 or hpath.find("8914702")>0 or + hpath.find("1244522")>0 or hpath.find("1457605")>0 or + hpath.find("1632756")>0 or hpath.find("1266056")>0 ) : if(type(hsets.values()[0])==yoda.core.Scatter2D) : outhistos[hpath] = yoda.core.Scatter2D(hsets.values()[0].path, hsets.values()[0].title) elif(type(hsets.values()[0])==yoda.core.Profile1D) : outhistos[hpath] = yoda.core.Profile1D(hsets.values()[0].path, hsets.values()[0].title) for i in range(0,hsets.values()[0].numBins) : outhistos[hpath].addBin(hsets.values()[0].bins[i].xMin, hsets.values()[0].bins[i].xMax) elif(type(hsets.values()[0])==yoda.core.Histo1D) : outhistos[hpath] = yoda.core.Histo1D(hsets.values()[0].path, hsets.values()[0].title) for i in range(0,hsets.values()[0].numBins) : outhistos[hpath].addBin(hsets.values()[0].bins[i].xMin, hsets.values()[0].bins[i].xMax) else : logging.error("Histogram %s is of unknown type" % hpath) print hpath,type(hsets.values()[0]) sys.exit(1) logging.info("Processing ATLAS_2013_I1263495") mergeByPt("/ATLAS_2013_I1263495/d01-x01-y01") mergeByPt("/ATLAS_2013_I1263495/d01-x01-y03") useOnePt("/ATLAS_2013_I1263495/d01-x02-y01", "90" ) logging.info("Processing ATLAS_2012_I1093738") mergeByPt("/ATLAS_2012_I1093738/d01-x01-y01") mergeByPt("/ATLAS_2012_I1093738/d02-x01-y01") mergeByPt("/ATLAS_2012_I1093738/d03-x01-y01") mergeByPt("/ATLAS_2012_I1093738/d04-x01-y01") mergeByPt("/ATLAS_2012_I1093738/d05-x01-y01") mergeByPt("/ATLAS_2012_I1093738/d06-x01-y01") logging.info("Processing ATLAS_2011_I921594") mergeByPt("/ATLAS_2011_I921594/d01-x01-y01") mergeByPt("/ATLAS_2011_I921594/d01-x01-y02") mergeByPt("/ATLAS_2011_I921594/d01-x01-y04") mergeByPt("/ATLAS_2011_I921594/d01-x01-y05") logging.info("Processing ATLAS_2010_S8914702") mergeByPt("/ATLAS_2010_S8914702/d01-x01-y01") mergeByPt("/ATLAS_2010_S8914702/d01-x01-y02") mergeByPt("/ATLAS_2010_S8914702/d01-x01-y03") logging.info("Processing CMS_2013_I1258128") useOnePt("/CMS_2013_I1258128/d05-x01-y01", "35" ) useOnePt("/CMS_2013_I1258128/d06-x01-y01", "35" ) useOnePt("/CMS_2013_I1258128/d07-x01-y01", "35" ) useOnePt("/CMS_2013_I1258128/d08-x01-y01", "35" ) logging.info("Processing ATLAS_2013_I1244522") mergeByPt("/ATLAS_2013_I1244522/d01-x01-y01") mergeByPt("/ATLAS_2013_I1244522/d02-x01-y01") useOnePt("/ATLAS_2013_I1244522/d03-x01-y01", "35" ) useOnePt("/ATLAS_2013_I1244522/d04-x01-y01", "35" ) useOnePt("/ATLAS_2013_I1244522/d05-x01-y01", "35" ) useOnePt("/ATLAS_2013_I1244522/d06-x01-y01", "35" ) useOnePt("/ATLAS_2013_I1244522/d07-x01-y01", "35" ) logging.info("Processing ATLAS_2016_I1457605") mergeByPt("/ATLAS_2016_I1457605/d01-x01-y01") mergeByPt("/ATLAS_2016_I1457605/d02-x01-y01") mergeByPt("/ATLAS_2016_I1457605/d03-x01-y01") mergeByPt("/ATLAS_2016_I1457605/d04-x01-y01") +logging.info("Processing ATLAS_2017_I1632756") +mergeByPt("/ATLAS_2017_I1632756/d02-x01-y01") +mergeByPt("/ATLAS_2017_I1632756/d03-x01-y01") +mergeByPt("/ATLAS_2017_I1632756/d04-x01-y01") +mergeByPt("/ATLAS_2017_I1632756/d05-x01-y01") + +logging.info("Processing CMS_2014_I1266056") +mergeByPt("/CMS_2014_I1266056/d01-x01-y01") +mergeByPt("/CMS_2014_I1266056/d01-x01-y02") +mergeByPt("/CMS_2014_I1266056/d02-x01-y01") +mergeByPt("/CMS_2014_I1266056/d02-x01-y02") +mergeByPt("/CMS_2014_I1266056/d03-x01-y01") +mergeByPt("/CMS_2014_I1266056/d03-x01-y02") +mergeByPt("/CMS_2014_I1266056/d04-x01-y01") +mergeByPt("/CMS_2014_I1266056/d04-x01-y02") + logging.info("Processing /MC_PHOTONJETS") useOnePt("/MC_PHOTONJETS/jet_HT","0") useOnePt("/MC_PHOTONJETS/jet_eta_1","0") useOnePt("/MC_PHOTONJETS/jet_eta_2","0") useOnePt("/MC_PHOTONJETS/jet_eta_3","0") useOnePt("/MC_PHOTONJETS/jet_eta_4","0") useOnePt("/MC_PHOTONJETS/jet_eta_pmratio_1","0") useOnePt("/MC_PHOTONJETS/jet_eta_pmratio_2","0") useOnePt("/MC_PHOTONJETS/jet_eta_pmratio_3","0") useOnePt("/MC_PHOTONJETS/jet_eta_pmratio_4","0") useOnePt("/MC_PHOTONJETS/jet_mass_1","0") useOnePt("/MC_PHOTONJETS/jet_mass_2","0") useOnePt("/MC_PHOTONJETS/jet_mass_3","0") useOnePt("/MC_PHOTONJETS/jet_mass_4","0") useOnePt("/MC_PHOTONJETS/jet_multi_exclusive","0") useOnePt("/MC_PHOTONJETS/jet_multi_inclusive","0") useOnePt("/MC_PHOTONJETS/jet_multi_ratio","0") useOnePt("/MC_PHOTONJETS/jet_pT_1","0") useOnePt("/MC_PHOTONJETS/jet_pT_2","0") useOnePt("/MC_PHOTONJETS/jet_pT_3","0") useOnePt("/MC_PHOTONJETS/jet_pT_4","0") useOnePt("/MC_PHOTONJETS/jet_y_1","0") useOnePt("/MC_PHOTONJETS/jet_y_2","0") useOnePt("/MC_PHOTONJETS/jet_y_3","0") useOnePt("/MC_PHOTONJETS/jet_y_4","0") useOnePt("/MC_PHOTONJETS/jet_y_pmratio_1","0") useOnePt("/MC_PHOTONJETS/jet_y_pmratio_2","0") useOnePt("/MC_PHOTONJETS/jet_y_pmratio_3","0") useOnePt("/MC_PHOTONJETS/jet_y_pmratio_4","0") useOnePt("/MC_PHOTONJETS/jets_dR_12","0") useOnePt("/MC_PHOTONJETS/jets_dR_13","0") useOnePt("/MC_PHOTONJETS/jets_dR_23","0") useOnePt("/MC_PHOTONJETS/jets_deta_12","0") useOnePt("/MC_PHOTONJETS/jets_deta_13","0") useOnePt("/MC_PHOTONJETS/jets_deta_23","0") useOnePt("/MC_PHOTONJETS/jets_dphi_12","0") useOnePt("/MC_PHOTONJETS/jets_dphi_13","0") useOnePt("/MC_PHOTONJETS/jets_dphi_23","0") useOnePt("/MC_PHOTONJETS/photon_jet1_dR","0") useOnePt("/MC_PHOTONJETS/photon_jet1_deta","0") useOnePt("/MC_PHOTONJETS/photon_jet1_dphi","0") useOnePt("/MC_PHOTONJETUE/gammajet-dR","0") useOnePt("/MC_PHOTONJETUE/gammajet-dphi","0") useOnePt("/MC_PHOTONJETUE/trans-maxnchg-gamma","0") useOnePt("/MC_PHOTONJETUE/trans-maxnchg-jet","0") useOnePt("/MC_PHOTONJETUE/trans-maxptsum-gamma","0") useOnePt("/MC_PHOTONJETUE/trans-maxptsum-jet","0") useOnePt("/MC_PHOTONJETUE/trans-minnchg-gamma","0") useOnePt("/MC_PHOTONJETUE/trans-minnchg-jet","0") useOnePt("/MC_PHOTONJETUE/trans-minptsum-gamma","0") useOnePt("/MC_PHOTONJETUE/trans-minptsum-jet","0") useOnePt("/MC_PHOTONJETUE/trans-nchg-gamma","0") useOnePt("/MC_PHOTONJETUE/trans-nchg-jet","0") useOnePt("/MC_PHOTONJETUE/trans-ptavg-gamma","0") useOnePt("/MC_PHOTONJETUE/trans-ptavg-jet","0") useOnePt("/MC_PHOTONJETUE/trans-ptsum-gamma","0") useOnePt("/MC_PHOTONJETUE/trans-ptsum-jet","0") # Choose output file yoda.writeYODA(outhistos,opts.OUTFILE) sys.exit(0) diff --git a/Tests/python/merge-TVT-Jets b/Tests/python/merge-TVT-Jets --- a/Tests/python/merge-TVT-Jets +++ b/Tests/python/merge-TVT-Jets @@ -1,547 +1,557 @@ #! /usr/bin/env python import logging import sys if sys.version_info[:3] < (2,4,0): print "rivet scripts require Python version >= 2.4.0... exiting" sys.exit(1) import os, yoda # ############################################# def fillAbove(desthisto, sourcehistosbyptmin): pthigh= 1e100 ptlow =-1e100 for pt, h in sorted(sourcehistosbyptmin.iteritems(),reverse=True): ptlow=pt if(type(desthisto)==yoda.core.Scatter2D) : for i in range(0,h.numPoints) : xMin = h.points[i].x-h.points[i].xErrs.minus if( xMin >= ptlow and xMin < pthigh ) : desthisto.addPoint(h.points[i]) elif(type(desthisto)==yoda.core.Profile1D) : for i in range(0,h.numBins) : if(h.bins[i].xMin >= ptlow and h.bins[i].xMin < pthigh ) : desthisto.bins[i] += h.bins[i] elif(type(desthisto)==yoda.core.Histo1D) : for i in range(0,h.numBins) : if(h.bins[i].xMin >= ptlow and h.bins[i].xMin < pthigh ) : desthisto.bins[i] += h.bins[i] elif(type(desthisto)==yoda.core.Counter) : desthisto += h else : logging.error("Can't merge %s, unknown type" % desthisto.path) sys.exit(1) pthigh=pt def mergeByPt(hpath, sqrts): global inhistos global outhistos try: fillAbove(outhistos[hpath], inhistos[hpath][float(sqrts)]) except: pass def useOnePt(hpath, sqrts, ptmin): global inhistos global outhistos try: ## Find best pT_min match ptmins = inhistos[hpath][float(sqrts)].keys() closest_ptmin = None for ptm in ptmins: if closest_ptmin is None or \ abs(ptm-float(ptmin)) < abs(closest_ptmin-float(ptmin)): closest_ptmin = ptm if closest_ptmin != float(ptmin): logging.warning("Inexact match for requested pTmin=%s: " % ptmin + \ "using pTmin=%e instead" % closest_ptmin) outhistos[hpath] = inhistos[hpath][float(sqrts)][closest_ptmin] except: pass # ####################################### if __name__ == "__main__": import logging from optparse import OptionParser, OptionGroup parser = OptionParser(usage="%prog name") verbgroup = OptionGroup(parser, "Verbosity control") verbgroup.add_option("-v", "--verbose", action="store_const", const=logging.DEBUG, dest="LOGLEVEL", default=logging.INFO, help="print debug (very verbose) messages") verbgroup.add_option("-q", "--quiet", action="store_const", const=logging.WARNING, dest="LOGLEVEL", default=logging.INFO, help="be very quiet") parser.add_option("--with-ue", action='store_true' , dest="ue", default=True, help="Include UE analyses") parser.add_option("--without-ue", action='store_false', dest="ue", default=True, help="Don\'t include UE analyses") parser.add_option_group(verbgroup) (opts, args) = parser.parse_args() logging.basicConfig(level=opts.LOGLEVEL, format="%(message)s") ## Check args if len(args) < 1: logging.error("Must specify at least the name of the files") sys.exit(1) yodafiles=["-Run-II-Jets-0.yoda","-Run-II-Jets-1.yoda",\ "-Run-II-Jets-2.yoda",\ "-Run-II-Jets-3.yoda","-Run-II-Jets-4.yoda","-Run-II-Jets-5.yoda",\ "-Run-II-Jets-6.yoda","-Run-II-Jets-7.yoda",\ "-Run-I-Jets-1.yoda","-Run-I-Jets-2.yoda",\ "-Run-I-Jets-3.yoda","-Run-I-Jets-4.yoda","-Run-I-Jets-5.yoda",\ "-630-Jets-1.yoda" ,"-630-Jets-2.yoda" ,\ "-630-Jets-3.yoda", "-300-UE.yoda", "-900-UE.yoda" # "-RatioPlots.yoda" ] if(opts.ue) : yodafiles += ["-Run-II-UE.yoda" ,"-Run-I-UE.yoda" ,"-630-UE.yoda" ,] ## Get histos inhistos = {} outhistos={} for f in yodafiles: file='Rivet-'+args[0]+f if(file.find("Run-II-UE")>0) : sqrts=1960 ptmin=0. elif(file.find("Run-II-Jets-0")>0) : sqrts=1960 ptmin=20. elif(file.find("Run-II-Jets-1")>0) : sqrts=1960 ptmin=36. elif(file.find("Run-II-Jets-2")>0) : sqrts=1960 ptmin=55. elif(file.find("Run-II-Jets-3")>0) : sqrts=1960 ptmin=75. elif(file.find("Run-II-Jets-4")>0) : sqrts=1960 ptmin=100. elif(file.find("Run-II-Jets-5")>0) : sqrts=1960 ptmin=125. elif(file.find("Run-II-Jets-6")>0) : ptmin=175. sqrts=1960 elif(file.find("Run-II-Jets-7")>0) : sqrts=1960 ptmin=265. elif(file.find("300-UE")>0) : sqrts=300 ptmin=0. elif(file.find("900-UE")>0) : sqrts=900 ptmin=0. elif(file.find("630-UE")>0) : sqrts=630 ptmin=0. elif(file.find("630-Jets-1")>0) : sqrts=630 ptmin=30. elif(file.find("630-Jets-2")>0) : sqrts=630 ptmin=55. elif(file.find("630-Jets-3")>0) : sqrts=630 ptmin=90. elif(file.find("Run-I-UE")>0) : sqrts=1800 ptmin=0. elif(file.find("Run-I-Jets-1")>0) : sqrts=1800 ptmin=30. elif(file.find("Run-I-Jets-2")>0) : sqrts=1800 ptmin=55. elif(file.find("Run-I-Jets-3")>0) : sqrts=1800 ptmin=80. elif(file.find("Run-I-Jets-4")>0) : sqrts=1800 ptmin=105. elif(file.find("Run-I-Jets-5")>0) : sqrts=1800 ptmin=175. if not os.access(file, os.R_OK): logging.error("%s can not be read" % file) continue try: aos = yoda.read(file) except: logging.error("%s can not be parsed as YODA" % file) continue ## Get histos from this YODA file for aopath, ao in aos.iteritems() : # di-jet decorrelations # jet shapes if(aopath.find("5992206")>0 or aopath.find("6217184")>0 or aopath.find("LEADINGJETS")>0 or aopath.find("7662670")>0 or aopath.find("7057202")>0 or aopath.find("6450792")>0 or aopath.find("7828950")>0 or aopath.find("4751469")>0 or aopath.find("5839831")>0 or aopath.find("4563131")>0 or aopath.find("4517016")>0 or aopath.find("3618439")>0 or - aopath.find("8591881")>0 or aopath.find("1388868")>0) : + aopath.find("8591881")>0 or aopath.find("1388868")>0 or + aopath.find("398175")>0) : if not inhistos.has_key(aopath): inhistos[aopath] = {} tmpE = inhistos[aopath] if not tmpE.has_key(sqrts): tmpE[sqrts] = {} tmpP = tmpE[sqrts] if not tmpP.has_key(ptmin): tmpP[ptmin] = ao else: raise Exception("A set with ptmin = %s already exists" % ( ptmin)) elif(aopath.find("8233977")>0 or aopath.find("NOTE_9936")>0 or aopath.find("3905616")>0 or aopath.find("3324664")>0 or aopath.find("4796047")>0 or aopath.find("1865951")>0 or aopath.find("2089246")>0 or aopath.find("3108457")>0 or aopath.find("3349578")>0 or aopath.find("3541940")>0 or aopath.find("3214044")>0 or aopath.find("2952106")>0 or aopath.find("NOTE10874")>0 or aopath.find("895662")>0 ) : if( opts.ue ) : outhistos[aopath] = ao elif (aopath.find("NOTE10874")<0) : outhistos[aopath] = ao else : if(aopath.find("/_EVTCOUNT")>=0 or aopath.find("/_XSEC" )>=0 ) : continue print aopath quit() yodafiles=["-Run-II-Jets-8.yoda","-Run-II-Jets-9.yoda","-Run-II-Jets-10.yoda","-Run-II-Jets-11.yoda",\ "-Run-I-Jets-6.yoda","-Run-I-Jets-7.yoda","-Run-I-Jets-8.yoda"] for f in yodafiles: file='Rivet-'+args[0]+f if(file.find("Run-II-Jets-8")>0) : sqrts=1960 ptmin=0.150 elif(file.find("Run-II-Jets-9")>0) : sqrts=1960 ptmin=0.400 elif(file.find("Run-II-Jets-10")>0) : sqrts=1960 ptmin=0.600 elif(file.find("Run-II-Jets-11")>0) : sqrts=1960 ptmin=1.000 elif(file.find("Run-I-Jets-6")>0) : sqrts=1800 ptmin=0.150 elif(file.find("Run-I-Jets-7")>0) : sqrts=1800 ptmin=0.5 elif(file.find("Run-I-Jets-8")>0) : sqrts=1800 ptmin=0.8 if not os.access(file, os.R_OK): logging.error("%s can not be read" % file) continue try: aos = yoda.read(file) except: logging.error("%s can not be parsed as YODA" % file) continue ## Get histos from this AIDA file for aopath, ao in aos.iteritems() : if(aopath.find("8566488")>0 or aopath.find("8320160")>0) : if not inhistos.has_key(aopath): inhistos[aopath] = {} tmpE = inhistos[aopath] if not tmpE.has_key(sqrts): tmpE[sqrts] = {} tmpP = tmpE[sqrts] if not tmpP.has_key(ptmin): tmpP[ptmin] = ao else: raise Exception("A set with ptmin = %s already exists" % ( ptmin)) elif(aopath.find("8093652")>0 or aopath.find("3418421")>0 or aopath.find("4266730")>0) : if not inhistos.has_key(aopath): inhistos[aopath] = {} tmpE = inhistos[aopath] if not tmpE.has_key(sqrts): tmpE[sqrts] = {} tmpP = tmpE[sqrts] if not tmpP.has_key(1000.*ptmin): tmpP[1000.*ptmin] = ao else: raise Exception("A set with ptmin = %s already exists" % ( 1000.*ptmin)) ## Make empty output histos if needed for hpath,hsets in inhistos.iteritems(): if( (hpath.find("6217184")>0 and hpath.find("d13-x01-y01")>0 ) or hpath.find("LEADINGJETS")>0 or hpath.find("7662670")>0 or hpath.find("7057202")>0 or hpath.find("6450792")>0 or hpath.find("7828950")>0 or hpath.find("8566488")>0 or hpath.find("8320160")>0 or hpath.find("8093652")>0 or hpath.find("4751469")>0 or hpath.find("5839831")>0 or hpath.find("4563131")>0 or hpath.find("4517016")>0 or hpath.find("3618439")>0 or hpath.find("4266730")>0 or hpath.find("3418421")>0 or hpath.find("8591881")>0 or hpath.find("1388868")>0) : if(type(hsets.values()[0].values()[0])==yoda.core.Counter) : outhistos[hpath] = yoda.core.Counter(hsets.values()[0].values()[0].path, hsets.values()[0].values()[0].title) elif(type(hsets.values()[0].values()[0])==yoda.core.Scatter2D) : outhistos[hpath] = yoda.core.Scatter2D(hsets.values()[0].values()[0].path, hsets.values()[0].values()[0].title) elif(type(hsets.values()[0].values()[0])==yoda.core.Profile1D) : outhistos[hpath] = yoda.core.Profile1D(hsets.values()[0].values()[0].path, hsets.values()[0].values()[0].title) for i in range(0,hsets.values()[0].values()[0].numBins) : outhistos[hpath].addBin(hsets.values()[0].values()[0].bins[i].xMin, hsets.values()[0].values()[0].bins[i].xMax) elif(type(hsets.values()[0].values()[0])==yoda.core.Histo1D) : outhistos[hpath] = yoda.core.Histo1D(hsets.values()[0].values()[0].path, hsets.values()[0].values()[0].title) for i in range(0,hsets.values()[0].values()[0].numBins) : outhistos[hpath].addBin(hsets.values()[0].values()[0].bins[i].xMin, hsets.values()[0].values()[0].bins[i].xMax) else : logging.error("Histogram %s is of unknown type" % hpath) print hpath,type(hsets.values()[0].values()[0]) sys.exit(1) ## Field analysis logging.info("Processing CDF_2001_S4751469") ## Angular distributions in different pT bins if(opts.ue) : useOnePt("/CDF_2001_S4751469/d01-x01-y01", "1800", "0") useOnePt("/CDF_2001_S4751469/d01-x01-y02", "1800", "0") useOnePt("/CDF_2001_S4751469/d02-x01-y01", "1800", "0") useOnePt("/CDF_2001_S4751469/d02-x01-y02", "1800", "0") useOnePt("/CDF_2001_S4751469/d01-x01-y03", "1800", "30") useOnePt("/CDF_2001_S4751469/d02-x01-y03", "1800", "30") ## Number, profile in pT_lead (True?) if(opts.ue) : useOnePt("/CDF_2001_S4751469/d03-x01-y01", "1800", "0") useOnePt("/CDF_2001_S4751469/d03-x01-y02", "1800", "0") useOnePt("/CDF_2001_S4751469/d03-x01-y03", "1800", "0") useOnePt("/CDF_2001_S4751469/d04-x01-y01", "1800", "30") useOnePt("/CDF_2001_S4751469/d04-x01-y02", "1800", "30") useOnePt("/CDF_2001_S4751469/d04-x01-y03", "1800", "30") ## pT sums, profile in pT_lead (True?) if(opts.ue) : useOnePt("/CDF_2001_S4751469/d05-x01-y01", "1800", "0") useOnePt("/CDF_2001_S4751469/d05-x01-y02", "1800", "0") useOnePt("/CDF_2001_S4751469/d05-x01-y03", "1800", "0") useOnePt("/CDF_2001_S4751469/d06-x01-y01", "1800", "30") useOnePt("/CDF_2001_S4751469/d06-x01-y02", "1800", "30") useOnePt("/CDF_2001_S4751469/d06-x01-y03", "1800", "30") ## pT distributions (use a specific pT cut run) if(opts.ue) : useOnePt("/CDF_2001_S4751469/d07-x01-y01", "1800", "0") useOnePt("/CDF_2001_S4751469/d07-x01-y02", "1800", "0") useOnePt("/CDF_2001_S4751469/d07-x01-y03", "1800", "30") ## Acosta analysis logging.info("Processing CDF_2004_S5839831") ## Mean pT, profile in ET_lead mergeByPt("/CDF_2004_S5839831/d01-x01-y01", "1800") mergeByPt("/CDF_2004_S5839831/d01-x01-y02", "1800") ## pT_max,min, profiles in ET_lead mergeByPt("/CDF_2004_S5839831/d02-x01-y01", "1800") mergeByPt("/CDF_2004_S5839831/d02-x01-y02", "1800") mergeByPt("/CDF_2004_S5839831/d02-x01-y03", "1800") ## pT distributions (want to use a specific pT cut run) useOnePt("/CDF_2004_S5839831/d03-x01-y01", "1800", "30") useOnePt("/CDF_2004_S5839831/d03-x01-y02", "1800", "80") useOnePt("/CDF_2004_S5839831/d03-x01-y03", "1800", "105") useOnePt("/CDF_2004_S5839831/d03-x01-y04", "1800", "105") useOnePt("/CDF_2004_S5839831/d03-x01-y05", "1800", "175") ## N_max,min, profiles in ET_lead mergeByPt("/CDF_2004_S5839831/d04-x01-y01", "1800") mergeByPt("/CDF_2004_S5839831/d04-x01-y02", "1800") ## Min bias dbs (want to use min bias pT cut) if(opts.ue) : useOnePt("/CDF_2004_S5839831/d05-x01-y01", "1800", "0") useOnePt("/CDF_2004_S5839831/d06-x01-y01", "1800", "0") ## Swiss Cheese, profile in ET_lead mergeByPt("/CDF_2004_S5839831/d07-x01-y01", "1800") mergeByPt("/CDF_2004_S5839831/d07-x01-y02", "1800") ## pT_max,min, profiles in ET_lead mergeByPt("/CDF_2004_S5839831/d08-x01-y01", "630") mergeByPt("/CDF_2004_S5839831/d08-x01-y02", "630") mergeByPt("/CDF_2004_S5839831/d08-x01-y03", "630") ## Swiss Cheese, profile in ET_lead mergeByPt("/CDF_2004_S5839831/d09-x01-y01", "630") mergeByPt("/CDF_2004_S5839831/d09-x01-y02", "630") ## Min bias dbs (want to use min bias pT cut) if(opts.ue) : useOnePt("/CDF_2004_S5839831/d10-x01-y01", "630", "0") useOnePt("/CDF_2004_S5839831/d11-x01-y01", "630", "0") ## CDF jet shape analysis logging.info("Processing CDF_2005_S6217184") useOnePt("/CDF_2005_S6217184/d01-x01-y01", "1960", "36" ) useOnePt("/CDF_2005_S6217184/d01-x01-y02", "1960", "36" ) useOnePt("/CDF_2005_S6217184/d01-x01-y03", "1960", "55" ) useOnePt("/CDF_2005_S6217184/d02-x01-y01", "1960", "55" ) useOnePt("/CDF_2005_S6217184/d02-x01-y02", "1960", "55" ) useOnePt("/CDF_2005_S6217184/d02-x01-y03", "1960", "75" ) useOnePt("/CDF_2005_S6217184/d03-x01-y01", "1960", "75" ) useOnePt("/CDF_2005_S6217184/d03-x01-y02", "1960", "100") useOnePt("/CDF_2005_S6217184/d03-x01-y03", "1960", "100") useOnePt("/CDF_2005_S6217184/d04-x01-y01", "1960", "125") useOnePt("/CDF_2005_S6217184/d04-x01-y02", "1960", "125") useOnePt("/CDF_2005_S6217184/d04-x01-y03", "1960", "175") useOnePt("/CDF_2005_S6217184/d05-x01-y01", "1960", "175") useOnePt("/CDF_2005_S6217184/d05-x01-y02", "1960", "175") useOnePt("/CDF_2005_S6217184/d05-x01-y03", "1960", "175") useOnePt("/CDF_2005_S6217184/d06-x01-y01", "1960", "265") useOnePt("/CDF_2005_S6217184/d06-x01-y02", "1960", "265") useOnePt("/CDF_2005_S6217184/d06-x01-y03", "1960", "265") useOnePt("/CDF_2005_S6217184/d07-x01-y01", "1960", "36" ) useOnePt("/CDF_2005_S6217184/d07-x01-y02", "1960", "36" ) useOnePt("/CDF_2005_S6217184/d07-x01-y03", "1960", "55" ) useOnePt("/CDF_2005_S6217184/d08-x01-y01", "1960", "55" ) useOnePt("/CDF_2005_S6217184/d08-x01-y02", "1960", "55" ) useOnePt("/CDF_2005_S6217184/d08-x01-y03", "1960", "75" ) useOnePt("/CDF_2005_S6217184/d09-x01-y01", "1960", "75" ) useOnePt("/CDF_2005_S6217184/d09-x01-y02", "1960", "100") useOnePt("/CDF_2005_S6217184/d09-x01-y03", "1960", "100") useOnePt("/CDF_2005_S6217184/d10-x01-y01", "1960", "125") useOnePt("/CDF_2005_S6217184/d10-x01-y02", "1960", "125") useOnePt("/CDF_2005_S6217184/d10-x01-y03", "1960", "175") useOnePt("/CDF_2005_S6217184/d11-x01-y01", "1960", "175") useOnePt("/CDF_2005_S6217184/d11-x01-y02", "1960", "175") useOnePt("/CDF_2005_S6217184/d11-x01-y03", "1960", "175") useOnePt("/CDF_2005_S6217184/d12-x01-y01", "1960", "265") useOnePt("/CDF_2005_S6217184/d12-x01-y02", "1960", "265") useOnePt("/CDF_2005_S6217184/d12-x01-y03", "1960", "265") mergeByPt("/CDF_2005_S6217184/d13-x01-y01", "1960") # ## CDF dijet mass spectrum mergeByPt("/CDF_2008_S8093652/d01-x01-y01", "1960") # ## Rick Field Run-II Leading Jets analysis # logging.info("Processing CDF_2008_LEADINGJETS") # ## charged particle density # mergeByPt("/CDF_2008_LEADINGJETS/d01-x01-y01", "1960") # mergeByPt("/CDF_2008_LEADINGJETS/d02-x01-y01", "1960") # mergeByPt("/CDF_2008_LEADINGJETS/d03-x01-y01", "1960") # mergeByPt("/CDF_2008_LEADINGJETS/d04-x01-y01", "1960") # ## pT sum density # mergeByPt("/CDF_2008_LEADINGJETS/d05-x01-y01", "1960") # mergeByPt("/CDF_2008_LEADINGJETS/d06-x01-y01", "1960") # mergeByPt("/CDF_2008_LEADINGJETS/d07-x01-y01", "1960") # mergeByPt("/CDF_2008_LEADINGJETS/d08-x01-y01", "1960") # ## mean pT # mergeByPt("/CDF_2008_LEADINGJETS/d09-x01-y01", "1960") ## newer version logging.info("Processing CDF_2010_S8591881_QCD") mergeByPt("/CDF_2010_S8591881_QCD/d10-x01-y01", "1960") mergeByPt("/CDF_2010_S8591881_QCD/d10-x01-y02", "1960") mergeByPt("/CDF_2010_S8591881_QCD/d10-x01-y03", "1960") mergeByPt("/CDF_2010_S8591881_QCD/d11-x01-y01", "1960") mergeByPt("/CDF_2010_S8591881_QCD/d11-x01-y02", "1960") mergeByPt("/CDF_2010_S8591881_QCD/d11-x01-y03", "1960") mergeByPt("/CDF_2010_S8591881_QCD/d12-x01-y01", "1960") mergeByPt("/CDF_2010_S8591881_QCD/d12-x01-y02", "1960") mergeByPt("/CDF_2010_S8591881_QCD/d12-x01-y03", "1960") mergeByPt("/CDF_2010_S8591881_QCD/d13-x01-y01", "1960") mergeByPt("/CDF_2010_S8591881_QCD/d13-x01-y02", "1960") mergeByPt("/CDF_2010_S8591881_QCD/d13-x01-y03", "1960") mergeByPt("/CDF_2010_S8591881_QCD/d14-x01-y01", "1960") mergeByPt("/CDF_2010_S8591881_QCD/d15-x01-y01", "1960") ## D0 dijet correlation analysis logging.info("Processing D0_2004_S5992206") useOnePt("/D0_2004_S5992206/d01-x02-y01", "1960", "75") useOnePt("/D0_2004_S5992206/d02-x02-y01", "1960", "100") useOnePt("/D0_2004_S5992206/d03-x02-y01", "1960", "125") useOnePt("/D0_2004_S5992206/d04-x02-y01", "1960", "175") ## D0 incl jet cross-section analysis logging.info("Processing D0_2008_S7662670") mergeByPt("/D0_2008_S7662670/d01-x01-y01", "1960") mergeByPt("/D0_2008_S7662670/d02-x01-y01", "1960") mergeByPt("/D0_2008_S7662670/d03-x01-y01", "1960") mergeByPt("/D0_2008_S7662670/d04-x01-y01", "1960") mergeByPt("/D0_2008_S7662670/d05-x01-y01", "1960") mergeByPt("/D0_2008_S7662670/d06-x01-y01", "1960") mergeByPt("/D0_2010_S8566488/d01-x01-y01", "1960") mergeByPt("/D0_2010_S8566488/d02-x01-y01", "1960") mergeByPt("/D0_2010_S8566488/d03-x01-y01", "1960") mergeByPt("/D0_2010_S8566488/d04-x01-y01", "1960") mergeByPt("/D0_2010_S8566488/d05-x01-y01", "1960") mergeByPt("/D0_2010_S8566488/d06-x01-y01", "1960") # CDF jet cross section mergeByPt("/CDF_2001_S4563131/d01-x01-y01", "1800") mergeByPt("/CDF_2001_S4517016/d01-x01-y01", "1800") mergeByPt("/CDF_2001_S4517016/d02-x01-y01", "1800") mergeByPt("/CDF_2001_S4517016/d03-x01-y01", "1800") mergeByPt("/CDF_2001_S4517016/d04-x01-y01", "1800") useOnePt("/CDF_1998_S3618439/d01-x01-y01", "1800","105") useOnePt("/CDF_1998_S3618439/d01-x01-y02", "1800","105") mergeByPt("/CDF_2008_S7828950/d01-x01-y01", "1960") mergeByPt("/CDF_2008_S7828950/d02-x01-y01", "1960") mergeByPt("/CDF_2008_S7828950/d03-x01-y01", "1960") mergeByPt("/CDF_2008_S7828950/d04-x01-y01", "1960") mergeByPt("/CDF_2008_S7828950/d05-x01-y01", "1960") mergeByPt("/CDF_2007_S7057202/d01-x01-y01", "1960") mergeByPt("/CDF_2007_S7057202/d02-x01-y01", "1960") mergeByPt("/CDF_2007_S7057202/d03-x01-y01", "1960") mergeByPt("/CDF_2007_S7057202/d04-x01-y01", "1960") mergeByPt("/CDF_2007_S7057202/d05-x01-y01", "1960") mergeByPt("/CDF_2007_S7057202/d06-x01-y01", "1960") mergeByPt("/CDF_2007_S7057202/d07-x01-y01", "1960") mergeByPt("/CDF_2006_S6450792/d01-x01-y01", "1960") mergeByPt("/CDF_2000_S4266730/d01-x01-y01", "1800") useOnePt("/CDF_1996_S3418421/d01-x01-y01","1800","150") useOnePt("/CDF_1996_S3418421/d01-x01-y02","1800","150") useOnePt("/CDF_1996_S3418421/d01-x01-y03","1800","150") useOnePt("/CDF_1996_S3418421/d01-x01-y04","1800","500") useOnePt("/CDF_1996_S3418421/d01-x01-y05","1800","500") mergeByPt("/CDF_1996_S3418421/d02-x01-y01","1800") useOnePt("/D0_2009_S8320160/d01-x01-y01", "1960", "0.15" ) useOnePt("/D0_2009_S8320160/d02-x01-y01", "1960", "0.15" ) useOnePt("/D0_2009_S8320160/d03-x01-y01", "1960", "0.4" ) useOnePt("/D0_2009_S8320160/d04-x01-y01", "1960", "0.4" ) useOnePt("/D0_2009_S8320160/d05-x01-y01", "1960", "0.6" ) useOnePt("/D0_2009_S8320160/d06-x01-y01", "1960", "0.6" ) useOnePt("/D0_2009_S8320160/d07-x01-y01", "1960", "0.6" ) useOnePt("/D0_2009_S8320160/d08-x01-y01", "1960", "0.6" ) useOnePt("/D0_2009_S8320160/d09-x01-y01", "1960", "1.0" ) useOnePt("/D0_2009_S8320160/d10-x01-y01", "1960", "1.0" ) logging.info("Processing CDF_2015_I1388868") for d in range(1,4) : if d == 1 : energy="1960" elif d ==2 : energy = "900" elif d==3 : energy = "300" for y in [1,2,3,4,6,7,8,9]: useOnePt("/CDF_2015_I1388868/d0%s-x01-y0%s" % (d,y) , energy, "0" ) +# D0 jet shape +logging.info("Processing D0_1995_I398175") +useOnePt("/D0_1995_I398175/d01-x01-y01", "1800", "30" ) +useOnePt("/D0_1995_I398175/d02-x01-y01", "1800", "55" ) +useOnePt("/D0_1995_I398175/d03-x01-y01", "1800", "105" ) +useOnePt("/D0_1995_I398175/d04-x01-y01", "1800", "105" ) +useOnePt("/D0_1995_I398175/d05-x01-y01", "1800", "30" ) +useOnePt("/D0_1995_I398175/d06-x01-y01", "1800", "55" ) + # Choose output file name = args[0]+"-Jets.yoda" yoda.writeYODA(outhistos,name) sys.exit(0) diff --git a/Utilities/Interpolator.h b/Utilities/Interpolator.h --- a/Utilities/Interpolator.h +++ b/Utilities/Interpolator.h @@ -1,218 +1,249 @@ // -*- C++ -*- // // Interpolator.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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_Interpolator_H #define HERWIG_Interpolator_H // // This is the declaration of the Interpolator class. // #include "ThePEG/Interface/Interfaced.h" #include namespace Herwig { using namespace ThePEG; /** \ingroup Utilities * \author Peter Richardson * * This class implments a polynominal interpolation of a table of values, it is * based on the interpolation code in FORTRAN HERWIG. * */ template class Interpolator: public Interfaced { public: /** * Pointer to an Interpolator */ typedef typename Ptr >::pointer Ptr; /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ Interpolator() : _order(3), _copyx(5),_copyfun(5) {} /** * Constructor with data as vectors. */ Interpolator(const vector & f, - const vector & x, - unsigned int order) + const vector & x, + unsigned int order) : _fun(f.size(),0.0),_xval(x.size(),0.0),_order(order), _funit(TypeTraits::baseunit()), _xunit(TypeTraits::baseunit()), _copyx(order+2),_copyfun(order+2) { assert(_order>0); assert(x.size() == f.size()); for (size_t i = 0; i < f.size(); ++i) { _fun [i] = f[i] / _funit; _xval[i] = x[i] / _xunit; } } + + /** + * Constructor with data as arrays. + */ + template + Interpolator(const array & f, + const array & x, + unsigned int order) + : _fun(N,0.0),_xval(N,0.0),_order(order), + _funit(TypeTraits::baseunit()), + _xunit(TypeTraits::baseunit()), + _copyx(order+2),_copyfun(order+2) { + assert(_order>0); + for (size_t i = 0; i < N; ++i) { + _fun [i] = f[i] / _funit; + _xval[i] = x[i] / _xunit; + } + } //@} /** * Constructor from bare arrays */ Interpolator(size_t size, const double f[], ValT funit, const double x[], ArgT xunit, unsigned int order) : _fun(size,0.0),_xval(size,0.0),_order(order), _funit(funit),_xunit(xunit), _copyx(order+2),_copyfun(order+2) { assert(_order>0); for (size_t i = 0; i < size; ++i) { _fun [i] = f[i]; _xval[i] = x[i]; } } //@} /** * Return the interpolated value */ ValT operator () (ArgT) const; /** Return type for GaussianIntegrator */ typedef ValT ValType; /** Argument type for GaussianIntegrator */ typedef ArgT ArgType; 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 { return new_ptr(*this); } /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const { return new_ptr(*this); } //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ Interpolator & operator=(const Interpolator &); private: /** * the function values. */ vector _fun; /** * The x values. */ vector _xval; /** * the order of interpolation. */ unsigned int _order; /** * The Unit of the function values */ ValT _funit; /** * The Unit of the argument values */ ArgT _xunit; /** * Temporary storage vector */ mutable vector _copyx; /** * Temporary storage vector */ mutable vector _copyfun; }; /** * helper function to create InterpolatorPtr easily - * (analogous to make_pair() ) + * from bare arrays (analogous to make_pair() ) */ template inline typename Interpolator::Ptr make_InterpolatorPtr(size_t size, - const double f[], ValT funit, - const double x[], ArgT xunit, - unsigned int order) + const double f[], ValT funit, + const double x[], ArgT xunit, + unsigned int order) { return new_ptr(Interpolator(size, - f,funit, - x,xunit, - order)); + f,funit, + x,xunit, + order)); } /** * helper function to create InterpolatorPtr easily - * (analogous to make_pair() ) + * from vectors (analogous to make_pair() ) */ template inline typename Interpolator::Ptr make_InterpolatorPtr(const typename std::vector & f, - const typename std::vector & x, - unsigned int order) + const typename std::vector & x, + unsigned int order) +{ + return new_ptr(Interpolator(f,x,order)); +} + +/** + * helper function to create InterpolatorPtr easily + * from arrays (analogous to make_pair() ) + */ +template +inline typename Interpolator::Ptr +make_InterpolatorPtr(const typename std::array & f, + const typename std::array & x, + unsigned int order) { return new_ptr(Interpolator(f,x,order)); } } #ifndef ThePEG_TEMPLATES_IN_CC_FILE #include "Interpolator.tcc" #endif #endif /* HERWIG_Interpolator_H */ diff --git a/configure.ac b/configure.ac --- a/configure.ac +++ b/configure.ac @@ -1,242 +1,244 @@ dnl Process this file with autoconf to produce a configure script. AC_PREREQ([2.63]) AC_INIT([Herwig],[devel],[herwig@projects.hepforge.org],[Herwig]) AC_CONFIG_SRCDIR([Utilities/HerwigStrategy.cc]) AC_CONFIG_AUX_DIR([Config]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_HEADERS([Config/config.h]) dnl AC_PRESERVE_HELP_ORDER AC_CANONICAL_HOST dnl === disable debug symbols by default ===== if test "x$CXXFLAGS" = "x"; then CXXFLAGS=-O2 fi if test "x$CFLAGS" = "x"; then CFLAGS=-O2 fi AC_LANG([C++]) AM_INIT_AUTOMAKE([1.11 subdir-objects gnu dist-bzip2 no-dist-gzip -Wall -Wno-portability]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) dnl Checks for C++ compiler. Handle C++11 flags. AC_PROG_CXX AX_CXX_COMPILE_STDCXX([11],[noext],[mandatory]) dnl check for POSIX AC_CHECK_HEADER([unistd.h],[], [AC_MSG_ERROR([Herwig needs "unistd.h". Non-POSIX systems are not supported.])]) AC_CHECK_HEADER([sys/stat.h],[], [AC_MSG_ERROR([Herwig needs "sys/stat.h". Non-POSIX systems are not supported.])]) dnl Checks for programs. AC_PROG_INSTALL AC_PROG_MAKE_SET AC_PROG_LN_S dnl modified search order AC_PROG_FC([gfortran g95 g77]) dnl xlf95 f95 fort ifort ifc efc pgf95 lf95 ftn xlf90 f90 pgf90 pghpf epcf90 xlf f77 frt pgf77 cf77 fort77 fl32 af77]) AC_LANG_PUSH([Fortran]) AC_MSG_CHECKING([if the Fortran compiler ($FC) works]) AC_COMPILE_IFELSE( AC_LANG_PROGRAM([],[ print *[,]"Hello"]), [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]) AC_MSG_ERROR([A Fortran compiler is required to build Herwig.]) ] ) AC_LANG_POP([Fortran]) +AC_FC_WRAPPERS LT_PREREQ([2.2.6]) LT_INIT([disable-static dlopen pic-only]) dnl #################################### dnl #################################### dnl for Doc/fixinterfaces.pl AC_PATH_PROG(PERL, perl) dnl for Models/Feynrules AM_PATH_PYTHON([2.6],, [:]) AM_CONDITIONAL([HAVE_PYTHON], [test "x$PYTHON" != "x:"]) HERWIG_CHECK_GSL HERWIG_CHECK_THEPEG BOOST_REQUIRE([1.41]) BOOST_FIND_HEADER([boost/numeric/ublas/io.hpp]) dnl Boost 1.64 is missing a required header to make these work dnl we just assume they're there if io.hpp has been found OK above dnl BOOST_FIND_HEADER([boost/numeric/ublas/matrix.hpp]) dnl BOOST_FIND_HEADER([boost/numeric/ublas/matrix_proxy.hpp]) dnl BOOST_FIND_HEADER([boost/numeric/ublas/matrix_sparse.hpp]) dnl BOOST_FIND_HEADER([boost/numeric/ublas/symmetric.hpp]) dnl BOOST_FIND_HEADER([boost/numeric/ublas/vector.hpp]) BOOST_FIND_HEADER([boost/operators.hpp]) BOOST_TEST() HERWIG_CHECK_VBFNLO HERWIG_CHECK_NJET HERWIG_CHECK_GOSAM HERWIG_CHECK_GOSAM_CONTRIB HERWIG_CHECK_OPENLOOPS HERWIG_CHECK_MADGRAPH HERWIG_CHECK_EVTGEN HERWIG_CHECK_PYTHIA HERWIG_COMPILERFLAGS HERWIG_LOOPTOOLS FASTJET_CHECK_FASTJET HERWIG_ENABLE_MODELS SHARED_FLAG=-shared AM_CONDITIONAL(NEED_APPLE_FIXES, [test "xx${host/darwin/foundit}xx" != "xx${host}xx"]) if test "xx${host/darwin/foundit}xx" != "xx${host}xx"; then APPLE_DSO_FLAGS=-Wl,-undefined,dynamic_lookup SHARED_FLAG=-bundle fi AC_SUBST([APPLE_DSO_FLAGS]) AC_SUBST([SHARED_FLAG]) AC_CONFIG_FILES([UnderlyingEvent/Makefile Models/Makefile Models/StandardModel/Makefile Models/RSModel/Makefile Models/General/Makefile Models/Susy/Makefile Models/Susy/NMSSM/Makefile Models/Susy/RPV/Makefile Models/UED/Makefile Models/LH/Makefile Models/LHTP/Makefile Models/Transplanckian/Makefile Models/Leptoquarks/Makefile Models/Zprime/Makefile Models/TTbAsymm/Makefile Models/Feynrules/Makefile Models/Feynrules/python/Makefile-FR Models/ADD/Makefile Models/Sextet/Makefile Decay/Makefile Decay/FormFactors/Makefile Decay/Tau/Makefile Decay/Baryon/Makefile Decay/VectorMeson/Makefile Decay/Perturbative/Makefile Decay/ScalarMeson/Makefile Decay/TensorMeson/Makefile Decay/WeakCurrents/Makefile Decay/Partonic/Makefile Decay/General/Makefile Decay/Radiation/Makefile Decay/EvtGen/Makefile Doc/refman.conf Doc/refman.h PDT/Makefile PDF/Makefile MatrixElement/Makefile MatrixElement/General/Makefile MatrixElement/Lepton/Makefile MatrixElement/Hadron/Makefile MatrixElement/DIS/Makefile MatrixElement/Powheg/Makefile MatrixElement/Gamma/Makefile MatrixElement/Reweighters/Makefile MatrixElement/Matchbox/Makefile MatrixElement/Matchbox/Base/Makefile MatrixElement/Matchbox/Utility/Makefile MatrixElement/Matchbox/Phasespace/Makefile MatrixElement/Matchbox/Dipoles/Makefile MatrixElement/Matchbox/InsertionOperators/Makefile MatrixElement/Matchbox/Matching/Makefile MatrixElement/Matchbox/Cuts/Makefile MatrixElement/Matchbox/Scales/Makefile MatrixElement/Matchbox/ColorFull/Makefile MatrixElement/Matchbox/CVolver/Makefile MatrixElement/Matchbox/Builtin/Makefile MatrixElement/Matchbox/Builtin/Amplitudes/Makefile MatrixElement/Matchbox/Tests/Makefile MatrixElement/Matchbox/External/Makefile MatrixElement/Matchbox/External/BLHAGeneric/Makefile MatrixElement/Matchbox/External/VBFNLO/Makefile MatrixElement/Matchbox/External/NJet/Makefile MatrixElement/Matchbox/External/GoSam/Makefile MatrixElement/Matchbox/External/OpenLoops/Makefile MatrixElement/Matchbox/External/MadGraph/Makefile MatrixElement/Matchbox/External/MadGraph/mg2herwig Sampling/Makefile Sampling/CellGrids/Makefile Shower/Makefile Shower/QTilde/Makefile Shower/QTilde/Matching/Makefile Shower/Dipole/Makefile Shower/Dipole/Base/Makefile Shower/Dipole/Kernels/Makefile Shower/Dipole/Kinematics/Makefile Shower/Dipole/Utility/Makefile Shower/Dipole/AlphaS/Makefile Utilities/Makefile Utilities/XML/Makefile Utilities/Statistics/Makefile Hadronization/Makefile lib/Makefile include/Makefile src/Makefile src/defaults/Makefile src/snippets/Makefile src/Matchbox/Makefile src/herwig-config Doc/Makefile Doc/HerwigDefaults.in Looptools/Makefile Analysis/Makefile API/Makefile src/Makefile-UserModules src/defaults/Analysis.in src/defaults/MatchboxDefaults.in src/defaults/Decays.in src/defaults/decayers.in src/defaults/setup.gosam.in src/Matchbox/LO-DefaultShower.in src/Matchbox/LO-DipoleShower.in src/Matchbox/MCatLO-DefaultShower.in src/Matchbox/MCatLO-DipoleShower.in src/Matchbox/LO-NoShower.in src/Matchbox/MCatNLO-DefaultShower.in src/Matchbox/MCatNLO-DipoleShower.in src/Matchbox/NLO-NoShower.in src/Matchbox/Powheg-DefaultShower.in src/Matchbox/Powheg-DipoleShower.in src/Merging/Makefile Shower/Dipole/Merging/Makefile + Shower/Dipole/Colorea/Makefile src/defaults/MatchboxMergingDefaults.in Contrib/Makefile Contrib/make_makefiles.sh Tests/Makefile Makefile]) AC_CONFIG_LINKS([Doc/BSMlibs.in:Doc/BSMlibs.in]) AC_CONFIG_FILES([Doc/fixinterfaces.pl],[chmod +x Doc/fixinterfaces.pl]) - +AC_CONFIG_HEADERS([PDF/SaSPhotonPDF.cc]) HERWIG_OVERVIEW AC_CONFIG_COMMANDS([summary],[cat config.herwig]) AC_OUTPUT diff --git a/lib/Makefile.am b/lib/Makefile.am --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,49 +1,49 @@ pkglib_LTLIBRARIES = Herwig.la Herwig_la_SOURCES = Herwig_la_LIBTOOLFLAGS = --tag=CXX -Herwig_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 23:0:0 -Herwig_la_LDFLAGS += $(THEPEGLDFLAGS) $(FCLIBS) +Herwig_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 24:0:0 +Herwig_la_LDFLAGS += $(THEPEGLDFLAGS) $(BOOST_SYSTEM_LDFLAGS) $(BOOST_FILESYSTEM_LDFLAGS) $(FCLIBS) Herwig_la_LIBADD = \ $(top_builddir)/Hadronization/libHwHadronization.la \ $(top_builddir)/Models/libHwStandardModel.la \ $(top_builddir)/Decay/libHwDecay.la \ $(top_builddir)/Decay/libHwFormFactor.la \ $(top_builddir)/Decay/libHwDecRad.la \ $(top_builddir)/Utilities/libHwUtils.la \ $(top_builddir)/Models/libHwModelGenerator.la \ $(top_builddir)/Decay/General/libHwGeneralDecay.la \ $(top_builddir)/MatrixElement/General/libHwGeneralME.la \ $(top_builddir)/MatrixElement/libHwME.la \ $(top_builddir)/MatrixElement/Reweighters/libHwReweighters.la \ $(top_builddir)/MatrixElement/Matchbox/libHwMatchbox.la \ $(top_builddir)/Decay/libHwWeakCurrent.la \ $(top_builddir)/Looptools/libHwLooptools.la \ $(top_builddir)/Shower/libHwShower.la \ $(THEPEGLIB) -ldl dist_noinst_SCRIPTS = fix-osx-path POSTPROCESSING = done-all-links if NEED_APPLE_FIXES POSTPROCESSING += apple-fixes endif all-local: $(POSTPROCESSING) done-all-links: Herwig.la find $(top_builddir) \( -name '*.so.*' -or -name '*.so' \) \ -not -name 'lib*' -not -path '$(top_builddir)/lib/*' \ -not -path '$(top_builddir)/.hg/*' -exec $(LN_S) -f \{\} \; $(LN_S) -f .libs/Herwig*so* . echo "stamp" > $@ apple-fixes: fix-osx-path done-all-links ./$< echo "stamp" > $@ clean-local: rm -f *.so *.so.* done-all-links apple-fixes diff --git a/m4/herwig.m4 b/m4/herwig.m4 --- a/m4/herwig.m4 +++ b/m4/herwig.m4 @@ -1,900 +1,900 @@ dnl ##### THEPEG ##### AC_DEFUN([HERWIG_CHECK_THEPEG], [ defaultlocation="${prefix}" test "x$defaultlocation" = xNONE && defaultlocation="${ac_default_prefix}" AC_MSG_CHECKING([for libThePEG in]) AC_ARG_WITH(thepeg, AC_HELP_STRING([--with-thepeg=DIR],[location of ThePEG installation]), [], [with_thepeg="${defaultlocation}"]) AC_MSG_RESULT([$with_thepeg]) if test "x$with_thepeg" = "xno"; then AC_MSG_ERROR([Cannot build Herwig without ThePEG. Please set --with-thepeg.]) fi THEPEGLDFLAGS="-L${with_thepeg}/lib/ThePEG" THEPEGHASLHAPDF="no" if test -e ${with_thepeg}/lib/ThePEG/ThePEGLHAPDF.so ; then THEPEGHASLHAPDF="yes" fi if test "${host_cpu}" == "x86_64" -a -e ${with_thepeg}/lib64/ThePEG/libThePEG.so ; then THEPEGLDFLAGS="-L${with_thepeg}/lib64/ThePEG" if test -e ${with_thepeg}/lib64/ThePEG/ThePEGLHAPDF.so ; then THEPEGHASLHAPDF="yes" fi fi if test "x$THEPEGHASLHAPDF" == "xno" ; then AC_MSG_ERROR([Herwig requires ThePEG to be build with lhapdf.]) fi THEPEGHASFASTJET="no" if test -e ${with_thepeg}/lib/ThePEG/FastJetFinder.so ; then THEPEGHASFASTJET="yes" fi if test "${host_cpu}" == "x86_64" -a -e ${with_thepeg}/lib64/ThePEG/libThePEG.so ; then THEPEGLDFLAGS="-L${with_thepeg}/lib64/ThePEG" if test -e ${with_thepeg}/lib64/ThePEG/FastJetFinder.so ; then THEPEGHASFASTJET="yes" fi fi if test "x$THEPEGHASFASTJET" == "xno" ; then AC_MSG_ERROR([Herwig requires ThePEG to be build with FastJet.]) fi THEPEGPATH="${with_thepeg}" oldldflags="$LDFLAGS" oldlibs="$LIBS" LDFLAGS="$LDFLAGS $THEPEGLDFLAGS" AC_CHECK_LIB([ThePEG],[debugThePEG],[], [AC_MSG_ERROR([No ThePEG libraries in $THEPEGLDFLAGS. Please set --with-thepeg.])]) AC_SUBST([THEPEGLIB],[-lThePEG]) AC_SUBST(THEPEGLDFLAGS) AC_SUBST(THEPEGPATH) AC_SUBST(THEPEGHASLHAPDF) AC_SUBST(THEPEGHASFASTJET) LIBS="$oldlibs" LDFLAGS="$oldldflags" AC_MSG_CHECKING([for ThePEG headers in]) AC_ARG_WITH([thepeg-headers], AC_HELP_STRING([--with-thepeg-headers=DIR],[location of ThePEG include directory]), [], [with_thepeg_headers="${with_thepeg}/include"]) AC_MSG_RESULT([$with_thepeg_headers]) if test "x$with_thepeg_headers" = "xno"; then AC_MSG_ERROR([Cannot build Herwig without ThePEG headers. Please set --with-thepeg-headers.]) fi THEPEGINCLUDE="-I$with_thepeg_headers" oldcppflags="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $THEPEGINCLUDE" AC_CHECK_HEADER([ThePEG/Config/ThePEG.h],[], [AC_MSG_ERROR([No ThePEG headers in $with_thepeg_headers. Please set --with-thepeg-headers.])]) CPPFLAGS="$oldcppflags" AC_SUBST(THEPEGINCLUDE) AC_MSG_CHECKING([for HepMCAnalysis.so in ThePEG]) THEPEGHASHEPMC="no" if test -e ${with_thepeg}/lib/ThePEG/HepMCAnalysis.so ; then THEPEGHASHEPMC="yes" fi if test "${host_cpu}" == "x86_64" -a -e ${with_thepeg}/lib64/ThePEG/libThePEG.so ; then THEPEGLDFLAGS="-L${with_thepeg}/lib64/ThePEG" if test -e ${with_thepeg}/lib64/ThePEG/HepMCAnalysis.so ; then THEPEGHASHEPMC="yes" fi fi if test "x$THEPEGHASHEPMC" == "xno" ; then CREATE_HEPMC="# create" AC_MSG_RESULT([not found]) else CREATE_HEPMC="create" AC_MSG_RESULT([found]) fi AC_SUBST([CREATE_HEPMC]) AC_MSG_CHECKING([for RivetAnalysis.so in ThePEG]) THEPEGHASRIVET="no" if test -e ${with_thepeg}/lib/ThePEG/RivetAnalysis.so ; then THEPEGHASRIVET="yes" fi if test "${host_cpu}" == "x86_64" -a -e ${with_thepeg}/lib64/ThePEG/libThePEG.so ; then THEPEGLDFLAGS="-L${with_thepeg}/lib64/ThePEG" if test -e ${with_thepeg}/lib64/ThePEG/RivetAnalysis.so ; then THEPEGHASRIVET="yes" fi fi if test "x$THEPEGHASRIVET" == "xno" ; then CREATE_RIVET="# create" AC_MSG_RESULT([not found]) else CREATE_RIVET="create" AC_MSG_RESULT([found]) fi AC_SUBST([CREATE_RIVET]) ]) dnl ##### LOOPTOOLS ##### AC_DEFUN([HERWIG_LOOPTOOLS], [ AC_REQUIRE([AC_PROG_FC]) AC_REQUIRE([AC_FC_LIBRARY_LDFLAGS]) AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([HERWIG_COMPILERFLAGS]) AC_MSG_CHECKING([if Looptools build works]) enable_looptools=yes if test "x$GCC" = "xyes"; then case "${host}" in x86_64-*|*-darwin1*) AM_FCFLAGS="$AM_FCFLAGS -fdefault-integer-8" ;; esac AC_LANG_PUSH([Fortran]) oldFCFLAGS="$FCFLAGS" FCFLAGS="$AM_FCFLAGS" AC_COMPILE_IFELSE( AC_LANG_PROGRAM([],[ print *[,]"Hello"]), [], [AC_MSG_RESULT([no]) AC_MSG_ERROR([needs gfortran on 64bit machines])] ) FCFLAGS="$oldFCFLAGS" AC_LANG_POP([Fortran]) fi AC_MSG_RESULT([$enable_looptools]) AC_SUBST([F77],[$FC]) AC_SUBST([FFLAGS],[$FCFLAGS]) AC_SUBST([AM_FFLAGS],[$AM_FCFLAGS]) AC_SUBST([FLIBS],[$FCLIBS]) ]) dnl ##### VBFNLO ##### AC_DEFUN([HERWIG_CHECK_VBFNLO], [ AC_MSG_CHECKING([for VBFNLO]) AC_ARG_WITH([vbfnlo], AS_HELP_STRING([--with-vbfnlo=DIR], [Installation path of VBFNLO]), [], [with_vbfnlo=no] ) AC_MSG_RESULT([$with_vbfnlo]) AS_IF([test "x$with_vbfnlo" != "xno"], [AC_CHECK_FILES( ${with_vbfnlo}/lib/VBFNLO/libVBFNLO.so, [have_vbfnlo=lib], [have_vbfnlo=no])], [have_vbfnlo=no]) AS_IF([test "x$with_vbfnlo" != "xno" -a "x$have_vbfnlo" = "xno" ], [AC_CHECK_FILES( ${with_vbfnlo}/lib64/VBFNLO/libVBFNLO.so, [have_vbfnlo=lib64], [have_vbfnlo=no])]) AS_IF([test "x$with_vbfnlo" != "xno" -a "x$have_vbfnlo" = "xno" ], [AC_CHECK_FILES( ${with_vbfnlo}/lib/VBFNLO/libVBFNLO.dylib, [have_vbfnlo=lib], [have_vbfnlo=no])]) AS_IF([test "x$with_vbfnlo" != "xno" -a "x$have_vbfnlo" = "xno" ], [AC_CHECK_FILES( ${with_vbfnlo}/lib64/VBFNLO/libVBFNLO.dylib, [have_vbfnlo=lib64], [have_vbfnlo=no])]) AS_IF([test "x$have_vbfnlo" = "xlib"], [VBFNLOLIBS=${with_vbfnlo}/lib/VBFNLO AC_SUBST(VBFNLOLIBS) ]) AS_IF([test "x$have_vbfnlo" = "xlib64"], [VBFNLOLIBS=${with_vbfnlo}/lib64/VBFNLO AC_SUBST(VBFNLOLIBS) ]) AS_IF([test "x$with_vbfnlo" != "xno" -a "x$have_vbfnlo" = "xno"], [AC_MSG_ERROR([vbfnlo requested but not found])]) AM_CONDITIONAL(HAVE_VBFNLO,[test "x$have_vbfnlo" = "xlib" -o "x$have_vbfnlo" = "xlib64"]) if test "x$have_vbfnlo" = "xlib" -o "x$have_vbfnlo" = "xlib64" ; then AC_REQUIRE([AC_PROG_SED]) VBFNLOINCLUDE=${with_vbfnlo}/include AC_SUBST(VBFNLOINCLUDE) VBFNLOLIB=$(echo ${with_vbfnlo}/${have_vbfnlo}/VBFNLO | $SED -e 's%/\+%/%g') AC_SUBST(VBFNLOLIB) LOAD_VBFNLO="library" CREATE_VBFNLO="create" INSERT_VBFNLO="insert" SET_VBFNLO="set" DO_VBFNLO="do" MKDIR_VBFNLO="mkdir" else LOAD_VBFNLO="# library" CREATE_VBFNLO="# create" INSERT_VBFNLO="# insert" SET_VBFNLO="# set" DO_VBFNLO="# do" MKDIR_VBFNLO="# mkdir" fi AC_SUBST([LOAD_VBFNLO]) AC_SUBST([CREATE_VBFNLO]) AC_SUBST([INSERT_VBFNLO]) AC_SUBST([SET_VBFNLO]) AC_SUBST([DO_VBFNLO]) AC_SUBST([MKDIR_VBFNLO]) ]) dnl ##### njet ##### AC_DEFUN([HERWIG_CHECK_NJET], [ AC_MSG_CHECKING([for njet]) AC_ARG_WITH([njet], AS_HELP_STRING([--with-njet=DIR], [Installation path of njet]), [], [with_njet=no] ) AC_MSG_RESULT([$with_njet]) AS_IF([test "x$with_njet" != "xno"], [AC_CHECK_FILES( ${with_njet}/lib/libnjet2.so, [have_njet=lib], [have_njet=no])], [have_njet=no]) AS_IF([test "x$with_njet" != "xno" -a "x$have_njet" = "xno" ], [AC_CHECK_FILES( ${with_njet}/lib64/libnjet2.so, [have_njet=lib64], [have_njet=no])]) AS_IF([test "x$with_njet" != "xno" -a "x$have_njet" = "xno" ], [AC_CHECK_FILES( ${with_njet}/lib/libnjet2.dylib, [have_njet=lib], [have_njet=no])]) AS_IF([test "x$have_njet" = "xlib"], [NJETLIBPATH=${with_njet}/lib AC_SUBST(NJETLIBPATH) NJETINCLUDEPATH=${with_njet}/include AC_SUBST(NJETINCLUDEPATH) NJETPREFIX=${with_njet} AC_SUBST(NJETPREFIX) ]) AS_IF([test "x$have_njet" = "xlib64"], [NJETLIBPATH=${with_njet}/lib64 AC_SUBST(NJETLIBPATH) NJETINCLUDEPATH=${with_njet}/include AC_SUBST(NJETINCLUDEPATH) NJETPREFIX=${with_njet} AC_SUBST(NJETPREFIX) ]) AS_IF([test "x$with_njet" != "xno" -a "x$have_njet" = "xno"], [AC_MSG_ERROR([njet requested but not found])]) AM_CONDITIONAL(HAVE_NJET,[test "x$have_njet" = "xlib" -o "x$have_njet" = "xlib64"]) if test "x$have_njet" = "xlib" -o "x$have_njet" = "xlib64" ; then LOAD_NJET="library" CREATE_NJET="create" INSERT_NJET="insert" DO_NJET="do" else LOAD_NJET="# library" CREATE_NJET="# create" INSERT_NJET="# insert" DO_NJET="# do" fi AC_SUBST([LOAD_NJET]) AC_SUBST([CREATE_NJET]) AC_SUBST([INSERT_NJET]) AC_SUBST([DO_NJET]) ]) dnl ##### gosam ##### AC_DEFUN([HERWIG_CHECK_GOSAM], [ AC_MSG_CHECKING([for GoSam]) AC_ARG_WITH([gosam], AS_HELP_STRING([--with-gosam=DIR], [Installation path of GoSam]), [], [with_gosam=no] ) AC_MSG_RESULT([$with_gosam]) AS_IF([test "x$with_gosam" != "xno"], [AC_CHECK_FILES( ${with_gosam}/bin/gosam.py, [have_gosam=lib], [have_gosam=no])], [have_gosam=no]) AS_IF([test "x$have_gosam" = "xlib"], [GOSAMPREFIX=${with_gosam} AC_SUBST(GOSAMPREFIX) ]) AS_IF([test "x$with_gosam" != "xno" -a "x$have_gosam" = "xno"], [AC_MSG_ERROR([GoSam requested but not found])]) AS_IF([test "x$with_gosam" != "xno"], [AC_MSG_CHECKING([for GoSam version >= 2.0.4]) tmp_gosamversion=[$(${with_gosam}/bin/gosam.py --version | grep 'GoSam.*rev' | cut -d' ' -f2)] AX_COMPARE_VERSION([${tmp_gosamversion}],[lt],[2.0.4], [AC_MSG_RESULT([no]) AC_MSG_ERROR([Herwig requires GoSam 2.0.4 or later, found ${tmp_gosamversion}])], [AC_MSG_RESULT([yes])])]) AM_CONDITIONAL(HAVE_GOSAM,[test "x$have_gosam" = "xlib" ]) if test "x$have_gosam" = "xlib" ; then LOAD_GOSAM="library" CREATE_GOSAM="create" INSERT_GOSAM="insert" DO_GOSAM="do" else LOAD_GOSAM="# library" CREATE_GOSAM="# create" INSERT_GOSAM="# insert" DO_GOSAM="# do" fi AC_SUBST([LOAD_GOSAM]) AC_SUBST([CREATE_GOSAM]) AC_SUBST([INSERT_GOSAM]) AC_SUBST([DO_GOSAM]) ]) dnl ##### gosam-contrib ##### AC_DEFUN([HERWIG_CHECK_GOSAM_CONTRIB], [ AC_MSG_CHECKING([for gosam-contrib]) AC_ARG_WITH([gosam-contrib], AS_HELP_STRING([--with-gosam-contrib=DIR], [Installation path of gosam-contrib]), [], [with_gosam_contrib=no] ) AC_MSG_RESULT([$with_gosam_contrib]) AS_IF([test "x$with_gosam_contrib" = "xno" -a "x$with_gosam" != "xno"], [AC_CHECK_FILES( ${with_gosam}/lib/libsamurai.so, [with_gosam_contrib=${with_gosam}], []) ]) AS_IF([test "x$with_gosam_contrib" = "xno" -a "x$with_gosam" != "xno"], [AC_CHECK_FILES( ${with_gosam}/lib64/libsamurai.so, [with_gosam_contrib=${with_gosam}], []) ]) AS_IF([test "x$with_gosam_contrib" = "xno" -a "x$with_gosam" != "xno"], [AC_CHECK_FILES( ${with_gosam}/lib/libsamurai.dylib, [with_gosam_contrib=${with_gosam}], []) ]) AS_IF([test "x$with_gosam_contrib" = "xno" -a "x$with_gosam" != "xno"], [AC_CHECK_FILES( ${with_gosam}/lib64/libsamurai.dylib, [with_gosam_contrib=${with_gosam}], []) ]) AS_IF([test "x$with_gosam_contrib" = "xno" -a "x$with_gosam" != "xno"], [AC_MSG_ERROR([GoSam requested without requesting GoSam-Contrib])]) AS_IF([test "x$with_gosam_contrib" != "xno"], [AC_CHECK_FILES( ${with_gosam_contrib}/lib/libsamurai.so, [have_gosam_contrib=lib], [have_gosam_contrib=no])], [have_gosam_contrib=no]) AS_IF([test "x$with_gosam_contrib" != "xno" -a "x$have_gosam_contrib" = "xno" ], [AC_CHECK_FILES( ${with_gosam_contrib}/lib64/libsamurai.so, [have_gosam_contrib=lib64], [have_gosam_contrib=no])]) AS_IF([test "x$with_gosam_contrib" != "xno" -a "x$have_gosam_contrib" = "xno" ], [AC_CHECK_FILES( ${with_gosam_contrib}/lib/libsamurai.dylib, [have_gosam_contrib=lib], [have_gosam_contrib=no])]) AS_IF([test "x$with_gosam_contrib" != "xno" -a "x$have_gosam_contrib" = "xno" ], [AC_CHECK_FILES( ${with_gosam_contrib}/lib64/libsamurai.dylib, [have_gosam_contrib=lib64], [have_gosam_contrib=no])]) AS_IF([test "x$have_gosam_contrib" != "xno"], [GOSAMCONTRIBPREFIX=${with_gosam_contrib} AC_SUBST(GOSAMCONTRIBPREFIX) ]) AS_IF([test "x$have_gosam_contrib" = "xlib"], [GOSAMCONTRIBLIBS=${with_gosam_contrib}/lib AC_SUBST(GOSAMCONTRIBLIBS) ]) AS_IF([test "x$have_gosam_contrib" = "xlib64"], [GOSAMCONTRIBLIBS=${with_gosam_contrib}/lib64 AC_SUBST(GOSAMCONTRIBLIBS) ]) AS_IF([test "x$with_gosam_contrib" != "xno" -a "x$have_gosam_contrib" = "xno"], [AC_MSG_ERROR([GoSam-Contrib requested but not found])]) AM_CONDITIONAL(HAVE_GOSAM_CONTRIB,[test "x$have_gosam_contrib" = "xlib" -o "x$have_gosam_contrib" = "xlib64"]) if test "x$have_gosam_contrib" = "xlib" -o "x$have_gosam_contrib" = "xlib64" ; then LOAD_GOSAM_CONTRIB="library" CREATE_GOSAM_CONTRIB="create" INSERT_GOSAM_CONTRIB="insert" else LOAD_GOSAM_CONTRIB="# library" CREATE_GOSAM_CONTRIB="# create" INSERT_GOSAM_CONTRIB="# insert" fi AC_SUBST([LOAD_GOSAM_CONTRIB]) AC_SUBST([CREATE_GOSAM_CONTRIB]) AC_SUBST([INSERT_GOSAM_CONTRIB]) ]) dnl ##### OpenLoops ##### AC_DEFUN([HERWIG_CHECK_OPENLOOPS], [ AC_MSG_CHECKING([for OpenLoops]) AC_ARG_WITH([openloops], AS_HELP_STRING([--with-openloops=DIR], [Installation path of OpenLoops]), [], [with_openloops=no] ) AC_MSG_RESULT([$with_openloops]) AS_IF([test "x$with_openloops" != "xno"], [AC_CHECK_FILES( ${with_openloops}/lib/libopenloops.so, [have_openloops=lib], [have_openloops=no])], [have_openloops=no]) AS_IF([test "x$with_openloops" != "xno" -a "x$have_openloops" = "xno" ], [AC_CHECK_FILES( ${with_openloops}/lib/libopenloops.dylib, [have_openloops=lib], [have_openloops=no])]) AS_IF([test "x$with_openloops" != "xno" -a "x$have_openloops" = "xno" ], [AC_CHECK_FILES( ${with_openloops}/lib64/libopenloops.so, [have_openloops=lib64], [have_openloops=no])]) AS_IF([test "x$with_openloops" != "xno" -a "x$have_openloops" = "xno" ], [AC_CHECK_FILES( ${with_openloops}/lib64/libopenloops.dylib, [have_openloops=lib64], [have_openloops=no])]) AS_IF([test "x$have_openloops" = "xlib"], [OPENLOOPSLIBS=${with_openloops}/lib AC_SUBST(OPENLOOPSLIBS) ]) AS_IF([test "x$have_openloops" = "xlib64"], [OPENLOOPSLIBS=${with_openloops}/lib64 AC_SUBST(OPENLOOPSLIBS) ]) AS_IF([test "x$with_openloops" != "xno" -a "x$have_openloops" = "xno"], [AC_MSG_ERROR([OpenLoops requested but not found])]) AM_CONDITIONAL(HAVE_OPENLOOPS,[test "x$have_openloops" = "xlib" -o "x$have_openloops" = "xlib64"]) if test "x$have_openloops" = "xlib" -o "x$have_openloops" = "xlib64" ; then OPENLOOPSPREFIX=${with_openloops} LOAD_OPENLOOPS="library" CREATE_OPENLOOPS="create" INSERT_OPENLOOPS="insert" SET_OPENLOOPS="set" DO_OPENLOOPS="do" MKDIR_OPENLOOPS="mkdir" else LOAD_OPENLOOPS="# library" CREATE_OPENLOOPS="# create" INSERT_OPENLOOPS="# insert" SET_OPENLOOPS="# set" DO_OPENLOOPS="# do" MKDIR_OPENLOOPS="# mkdir" fi AC_SUBST([OPENLOOPSPREFIX]) AC_SUBST([LOAD_OPENLOOPS]) AC_SUBST([CREATE_OPENLOOPS]) AC_SUBST([INSERT_OPENLOOPS]) AC_SUBST([SET_OPENLOOPS]) AC_SUBST([DO_OPENLOOPS]) AC_SUBST([MKDIR_OPENLOOPS]) ]) ######################################### dnl ##### madgraph ##### AC_DEFUN([HERWIG_CHECK_MADGRAPH], [ AC_MSG_CHECKING([for MadGraph]) AC_ARG_WITH([madgraph], AS_HELP_STRING([--with-madgraph=DIR], [Installation path of MadGraph]), [], [with_madgraph=no] ) AC_MSG_RESULT([$with_madgraph]) AS_IF([test "x$with_madgraph" != "xno"], [AC_CHECK_FILES( ${with_madgraph}/bin/mg5_aMC, [have_madgraph=yes], [have_madgraph=no])], [have_madgraph=no]) AS_IF([test "x$have_madgraph" = "xyes"], [MADGRAPHPREFIX=${with_madgraph} AC_SUBST(MADGRAPHPREFIX) ]) AS_IF([test "x$with_madgraph" != "xno" -a "x$have_madgraph" = "xno"], [AC_MSG_ERROR([MadGraph requested but not found])]) AM_CONDITIONAL(HAVE_MADGRAPH,[test "x$have_madgraph" = "xyes" ]) if test "x$have_madgraph" = "xyes" ; then LOAD_MADGRAPH="library" CREATE_MADGRAPH="create" INSERT_MADGRAPH="insert" SET_MADGRAPH="set" DO_MADGRAPH="do" else LOAD_MADGRAPH="# library" CREATE_MADGRAPH="# create" INSERT_MADGRAPH="# insert" SET_MADGRAPH="# set" DO_MADGRAPH="# do" fi AC_SUBST([LOAD_MADGRAPH]) AC_SUBST([CREATE_MADGRAPH]) AC_SUBST([INSERT_MADGRAPH]) AC_SUBST([SET_MADGRAPH]) AC_SUBST([DO_MADGRAPH]) ]) dnl ##### EvtGen ##### AC_DEFUN([HERWIG_CHECK_EVTGEN], [ AC_MSG_CHECKING([for evtgen]) AC_ARG_WITH([evtgen], AS_HELP_STRING([--with-evtgen=DIR], [Installation path of EvtGen]), [], [with_evtgen=no] ) AC_MSG_RESULT([$with_evtgen]) AS_IF([test "x$with_evtgen" != "xno"], [AC_CHECK_FILES( ${with_evtgen}/lib/libEvtGenExternal.so, [have_evtgen=lib], [have_evtgen=no])], [have_evtgen=no]) AS_IF([test "x$with_evtgen" != "xno" -a "x$have_evtgen" = "xno"], [AC_CHECK_FILES( ${with_evtgen}/lib64/libEvtGenExternal.so, [have_evtgen=lib64], [have_evtgen=no])]) AS_IF([test "x$with_evtgen" != "xno" -a "x$have_evtgen" = "xno" ], [AC_CHECK_FILES( ${with_evtgen}/lib/libEvtGenExternal.dylib, [have_evtgen=lib], [have_evtgen=no])]) AS_IF([test "x$have_evtgen" = "xlib" -o "x$have_evtgen" = "xlib64" ], [EVTGENPREFIX=${with_evtgen} AC_SUBST(EVTGENPREFIX) ]) AS_IF([test "x$with_evtgen" != "xno" -a "x$have_evtgen" = "xno"], [AC_MSG_ERROR([EvtGen requested but not found])]) AC_SUBST([EVTGENINCLUDE],[-I$EVTGENPREFIX/include]) -AM_CONDITIONAL(HAVE_EVTGEN,[test "x$have_evtgen" = "xlib" ]) +AM_CONDITIONAL(HAVE_EVTGEN,[test "x$have_evtgen" = "xlib" -o "x$have_evtgen" = "xlib64"]) if test "x$have_evtgen" = "xlib" ; then LOAD_EVTGEN_DECAYS="read EvtGenBDecays.in" LOAD_EVTGEN_DECAYER="read EvtGenDecayer.in" EVTGENLIBS="-L$with_evtgen/lib -lEvtGen -lEvtGenExternal" elif test "x$have_evtgen" = "xlib64" ; then LOAD_EVTGEN_DECAYS="read EvtGenBDecays.in" LOAD_EVTGEN_DECAYER="read EvtGenDecayer.in" EVTGENLIBS="-L$with_evtgen/lib64 -lEvtGen -lEvtGenExternal" else LOAD_EVTGEN_DECAYS="read HerwigBDecays.in" LOAD_EVTGEN_DECAYER="#read EvtGenDecayer.in" EVTGENLIBS="" fi AC_SUBST([LOAD_EVTGEN_DECAYS]) AC_SUBST([LOAD_EVTGEN_DECAYER]) AC_SUBST([EVTGENLIBS]) ]) AC_DEFUN([HERWIG_CHECK_PYTHIA], [ dnl check if a directory is specified for Pythia AC_ARG_WITH(pythia, [AC_HELP_STRING([--with-pythia=dir], [Assume the given directory for Pythia])]) dnl search for the pythia-config script if test "$with_pythia" = ""; then AC_PATH_PROG(pythiaconfig, pythia8-config, no) else AC_PATH_PROG(pythiaconfig, pythia8-config, no, ${with_pythia}/bin) fi if test "${pythiaconfig}" = "no"; then AC_MSG_CHECKING(Pythia) AC_MSG_RESULT(no); # $2 else PYTHIA8DATA=`${pythiaconfig} --datadir`/xmldoc fi AC_SUBST(PYTHIA8DATA) ]) dnl CHECK PYTHIA END dnl ###### GSL ###### AC_DEFUN([HERWIG_CHECK_GSL], [ AC_MSG_CHECKING([for gsl location]) GSLINCLUDE="" GSLLIBS="" AC_ARG_WITH(gsl, AC_HELP_STRING([--with-gsl=DIR],[location of gsl installation @<:@default=system libs@:>@]), [], [with_gsl=system]) if test "x$with_gsl" = "xno"; then AC_MSG_ERROR([libgsl is required. Please install the GNU scientific library and header files.]) fi if test "x$with_gsl" = "xsystem"; then AC_MSG_RESULT([in system libraries]) oldlibs="$LIBS" AC_CHECK_LIB(m,main) AC_CHECK_LIB(gslcblas,main) AC_CHECK_LIB(gsl,main,[], [ AC_MSG_ERROR([Cannot find libgsl. Please install the GNU scientific library and header files or use --with-gsl=.]) ] ) GSLLIBS="$LIBS" GSLPATH="$with_gsl" LIBS=$oldlibs else if test "`uname -m`" = "x86_64" -a -e "$with_gsl/lib64/libgsl.a" -a -d "$with_gsl/include/gsl"; then AC_MSG_RESULT([found in $with_gsl]) GSLLIBS="-L$with_gsl/lib64 -R$with_gsl/lib64 -lgslcblas -lgsl" GSLINCLUDE="-I$with_gsl/include" GSLPATH="$with_gsl" elif test -e "$with_gsl/lib/libgsl.a" -a -d "$with_gsl/include/gsl"; then AC_MSG_RESULT([found in $with_gsl]) GSLLIBS="-L$with_gsl/lib -R$with_gsl/lib -lgslcblas -lgsl" GSLINCLUDE="-I$with_gsl/include" GSLPATH="$with_gsl" else AC_MSG_RESULT([not found]) AC_MSG_ERROR([Can't find $with_gsl/lib/libgsl.a or the headers in $with_gsl/include]) fi fi AC_SUBST(GSLINCLUDE) AC_SUBST(GSLLIBS) AC_SUBST(GSLPATH) ]) dnl ##### COMPILERFLAGS ##### AC_DEFUN([HERWIG_COMPILERFLAGS], [ AC_REQUIRE([HERWIG_CHECK_GSL]) AC_REQUIRE([HERWIG_CHECK_THEPEG]) AC_REQUIRE([BOOST_REQUIRE]) AC_REQUIRE([AX_COMPILER_VENDOR]) AM_CPPFLAGS="-I\$(top_builddir)/include $THEPEGINCLUDE \$(GSLINCLUDE) \$(BOOST_CPPFLAGS)" AC_MSG_CHECKING([for debugging mode]) AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug],[debug mode, use --enable-debug=slow for additional options that slow down the run.]), [], [enable_debug=no] ) AC_MSG_RESULT([$enable_debug]) if test "x$enable_debug" = "xno"; then debugflags="" else debugflags="-g" fi dnl -Wfloat-equal -fvisibility-inlines-hidden -Wctor-dtor-privacy -Weffc++ if test -n "$GCC"; then warnflags="-pedantic -Wall -Wextra -Wno-overloaded-virtual" if test "x$enable_debug" = "xslow"; then debugflags="$debugflags -fno-inline" AM_CPPFLAGS="$AM_CPPFLAGS -D_GLIBCXX_DEBUG" fi fi dnl do an actual capability check on ld instead of this workaround case "${host}" in *-darwin*) ;; *) AM_LDFLAGS="-Wl,--enable-new-dtags" ;; esac case "${ax_cv_cxx_compiler_vendor}" in gnu) AM_CXXFLAGS="-pedantic -Wall -W" ;; clang) AM_CXXFLAGS="-pedantic -Wall -Wno-overloaded-virtual -Wno-unused-function -Wno-unused-parameter" dnl -Wno-unneeded-internal-declaration ;; intel) AM_CXXFLAGS="-strict-ansi -Wall -wd13000,1418,981,444,383,1599,1572,2259,980" ;; esac AC_SUBST(AM_CPPFLAGS) AC_SUBST(AM_CFLAGS, ["$warnflags $debugflags"]) AC_SUBST(AM_CXXFLAGS,["$AM_CXXFLAGS $warnflags $debugflags"]) AC_SUBST(AM_FCFLAGS, ["$debugflags"]) AC_SUBST(AM_LDFLAGS) ]) AC_DEFUN([HERWIG_ENABLE_MODELS], [ AC_MSG_CHECKING([if BSM models should be built]) AC_ARG_ENABLE(models, AC_HELP_STRING([--disable-models],[Turn off compilation of BSM models.]), [], [enable_models=yes] ) AC_MSG_RESULT([$enable_models]) LOAD_BSM="" if test "$enable_models" = "yes"; then LOAD_BSM="read BSMlibs.in" fi AC_SUBST(LOAD_BSM) AM_CONDITIONAL(WANT_BSM,[test "$enable_models" = "yes"]) ]) AC_DEFUN([HERWIG_OVERVIEW], [ FCSTRING=`$FC --version | head -1` CXXSTRING=`$CXX --version | head -1` CCSTRING=`$CC --version | head -1` if test "x$PYTHON" != "x:" then python_was_found="yes, using Python $PYTHON_VERSION" else python_was_found="no, requires Python >= 2.6" fi cat << _HW_EOF_ > config.herwig ***************************************************** *** $PACKAGE_STRING configuration summary *** Please include this information in bug reports! ***-------------------------------------------------- *** Prefix: $prefix *** *** BSM models: $enable_models *** UFO converter: ${python_was_found} *** *** Herwig debug mode: $enable_debug *** *** ThePEG: $with_thepeg *** ThePEG headers: $with_thepeg_headers *** *** GoSam: $with_gosam *** GoSam-Contrib: $with_gosam_contrib *** MadGraph: $with_madgraph *** njet: $with_njet *** OpenLoops: $with_openloops *** VBFNLO: $with_vbfnlo *** *** EvtGen: $with_evtgen *** GSL: $with_gsl *** boost: ${BOOST_CPPFLAGS:-system} *** Fastjet: ${fjconfig} *** *** Host: $host *** CC: $CCSTRING *** CXX: $CXXSTRING *** FC: $FCSTRING *** *** CXXFLAGS: $CXXFLAGS ***************************************************** _HW_EOF_ ]) diff --git a/src/LHC-MB.in b/src/LHC-MB.in --- a/src/LHC-MB.in +++ b/src/LHC-MB.in @@ -1,61 +1,69 @@ # -*- ThePEG-repository -*- ################################################################################ # This file contains our best tune to UE data from ATLAS at 7 TeV. More recent # tunes and tunes for other centre-of-mass energies as well as more usage # instructions can be obtained from this Herwig wiki page: # http://projects.hepforge.org/herwig/trac/wiki/MB_UE_tunes # The model for soft interactions and diffractions is explained in # [S. Gieseke, P. Kirchgaesser, F. Loshaj, arXiv:1612.04701] ################################################################################ read snippets/PPCollider.in ################################################## # Technical parameters for this run ################################################## cd /Herwig/Generators ################################################## # LHC physics parameters (override defaults here) ################################################## set EventGenerator:EventHandler:LuminosityFunction:Energy 7000.0 # Minimum Bias read snippets/MB.in # Read in parameters of the soft model recommended for MB/UE simulations read snippets/SoftTune.in # Diffraction model read snippets/Diffraction.in +# Read in snippet in order to use baryonic reconnection model with modified gluon splitting (uds) +# For more details see [S. Gieseke, P. Kirchgaeßer, S. Plätzer. arXiv:1710.10906]] +############################################################################################## + +# read snippets/BaryonicReconnection.in + + ################################################## # Analyses ################################################## + # cd /Herwig/Analysis # create ThePEG::RivetAnalysis RivetAnalysis RivetAnalysis.so # cd /Herwig/Generators # insert EventGenerator:AnalysisHandlers 0 /Herwig/Analysis/RivetAnalysis # insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_20XX_XXXXXXX #set /Herwig/Analysis/Plot:EventNumber 54 #cd /Herwig/Generators #insert EventGenerator:AnalysisHandlers 0 /Herwig/Analysis/Plot #insert EventGenerator:AnalysisHandlers 0 /Herwig/Analysis/HepMCFile #set /Herwig/Analysis/HepMCFile:PrintEvent 1000000 #set /Herwig/Analysis/HepMCFile:Format GenEvent #set /Herwig/Analysis/HepMCFile:Units GeV_mm #set /Herwig/Analysis/HepMCFile:Filename events.fifo ################################################## # Save run for later usage with 'Herwig run' ################################################## cd /Herwig/Generators saverun LHC-MB EventGenerator diff --git a/src/LHC-ResolvedGammaGamma.in b/src/LHC-ResolvedGammaGamma.in new file mode 100644 --- /dev/null +++ b/src/LHC-ResolvedGammaGamma.in @@ -0,0 +1,73 @@ +# -*- ThePEG-repository -*- + +################################################## +# Example generator based on LEP parameters +# usage: Herwig read LEP.in +################################################## + +read snippets/PPCollider.in + +################################################## +# Technical parameters for this run +################################################## +cd /Herwig/Generators +set EventGenerator:EventHandler:Sampler:Ntry 10000 + +################################################## +# Choice of phase-space generation for PDFs +################################################## +set /Herwig/Partons/PPExtractor:FlatSHatY 0 + +################################################## +# Change the proton PDFs to those for photon radiation +################################################## +set /Herwig/Particles/p+:PDF /Herwig/Partons/BudnevPDF +set /Herwig/Particles/pbar-:PDF /Herwig/Partons/BudnevPDF +set /Herwig/Partons/PPExtractor:FirstPDF /Herwig/Partons/BudnevPDF +set /Herwig/Partons/PPExtractor:SecondPDF /Herwig/Partons/BudnevPDF + +set /Herwig/Shower/ShowerHandler:PDFA /Herwig/Partons/SaSPDF +set /Herwig/Shower/ShowerHandler:PDFB /Herwig/Partons/SaSPDF +set /Herwig/Particles/gamma:PDF /Herwig/Partons/SaSPDF + + +################################################## +# Cuts +################################################## +cd /Herwig/Cuts +set Cuts:ScaleMin 0.0 +set Cuts:X1Min 0 +set Cuts:X2Min 0 +set Cuts:X1Max 1. +set Cuts:X2Max 1. +set Cuts:MHatMin 1.*GeV +erase Cuts:MultiCuts 0 +set LeptonKtCut:MinKT 3*GeV + +################################################## +# Selected the hard process +################################################## +cd /Herwig/MatrixElements + +# fermion-antifermion +insert SubProcess:MatrixElements 0 /Herwig/MatrixElements/MEqq2gZ2ff + +################################################## +# LHC physics parameters (override defaults) +################################################## +cd /Herwig/Generators +set EventGenerator:EventHandler:CascadeHandler:MPIHandler NULL + +################################################## +## prepare for Rivet analysis or HepMC output +## when running with parton shower +################################################## +#read snippets/Rivet.in +#insert /Herwig/Analysis/Rivet:Analyses 0 XXX_2015_ABC123 +#read snippets/HepMC.in +#set /Herwig/Analysis/HepMC:PrintEvent NNN + +################################################### +# Save run for later usage with 'Herwig run' +################################################## +saverun LHC-ResolvedGammaGamma EventGenerator diff --git a/src/Makefile.am b/src/Makefile.am --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,225 +1,226 @@ SUBDIRS = defaults snippets Matchbox Merging defaultsdir = ${pkgdatadir}/defaults bin_PROGRAMS = Herwig Herwig_SOURCES = \ HerwigMain.cc HerwigCLI.cc HerwigCLI.h \ herwigopts.c herwigopts.h BUILT_SOURCES = herwigopts.c herwigopts.h Herwig_LDFLAGS = $(AM_LDFLAGS) -export-dynamic $(THEPEGLDFLAGS) Herwig_LDADD = $(THEPEGLIB) -ldl \ $(top_builddir)/API/libHerwigAPI.la bin_SCRIPTS = herwig-config HELPERFILES = \ CMSSM40.1.1.slha \ NMSSM.spc \ ADD.model \ Leptoquark.model \ LH.model \ LHTP.model \ MSSM.model \ MUED.model \ NMSSM.model \ RPV-Bi.model \ RPV-Tri.model \ RS.model \ Sextet.model \ TTBA.model \ Zprime.model \ RPV-BI.slha \ RPV-TRI.slha \ RPV-UDD.slha INPUTFILES = \ DIS.in \ DIS-Matchbox.in \ GammaGamma.in \ ILC.in \ ILC-MSSM.in \ ILC-MUED.in \ ILC-RS.in \ LEP.in \ LEP-Matchbox.in \ LHC-ADD.in \ LHC-CEX.in \ LHC-GammaGamma.in \ +LHC-ResolvedGammaGamma.in \ LHC.in \ LHC-Matchbox.in \ LHC-LQ.in \ LHC-MSSM.in \ LHC-MUED.in \ LHC-NMSSM.in \ LHC-Powheg.in \ LHC-RPV.in \ LHC-RS.in \ LHC-Sextet.in \ LHC-TRP.in \ LHC-TTBA.in \ LHC-MB.in \ LHC-ZP.in \ TVT.in \ TVT-Powheg.in \ TVT-TTBA.in \ LHC-LH.in \ LHC-LHTP.in \ LHE.in dist_pkgdata_DATA = $(INPUTFILES) $(HELPERFILES) pkgdata_DATA = Makefile-UserModules CLEANFILES = HerwigDefaults.rpo \ *.run *.log *.out *.tex \ multi.test *.output probs.test chisq.value \ LHC-RS-BR.spc LHC-MSSM-BR.spc LHC-RPV-BR.spc clean-local: -rm -rf Herwig ## checking targets ## HerwigDefaults.rpo: Herwig $(srcdir)/defaults/*.in defaults/PDF.in defaults/Analysis.in $(top_builddir)/lib/*.so ./Herwig init -L$(top_builddir)/lib defaults/HerwigDefaults.in -D check_BSM_Full= check_BSM= if WANT_BSM check_BSM += check-LHC-RPV check-LHC-RS check_BSM_Full += \ check-LHC-RPV check-LHC-MSSM check-ILC-MSSM \ check-LHC-NMSSM \ check-LHC-MUED check-ILC-MUED \ check-LHC-RS check-ILC-RS check-LHC-ADD \ check-LHC-LH check-LHC-LHTP \ check-LHC-TRP \ check-LHC-TTBA check-TVT-TTBA \ check-LHC-ZP \ check-LHC-LQ \ check-LHC-Sextet endif check_BSM_Full_valgrind = $(subst check,check-valgrind,$(check_BSM_Full)) check_BSM_valgrind = $(subst check,check-valgrind,$(check_BSM)) check-local: check-LEP check-LHC $(check_BSM) check-DIS check-ILC check-GammaGamma check-LHC-Powheg check-valgrind-local: check-valgrind-LEP check-valgrind-LHC $(check_BSM_valgrind) check-valgrind-DIS check-valgrind-ILC check-valgrind-GammaGamma check-valgrind-LHC-Powheg check-Powheg: check-LHC-Powheg check-TVT-Powheg check-valgrind-Powheg: check-valgrind-LHC-Powheg check-valgrind-TVT-Powheg check-BSM: $(check_BSM_Full) check-valgrind-BSM: $(check_BSM_Full_valgrind) check_Matchbox= \ check-LEP-Matchbox check-DIS-Matchbox check-LHC-Matchbox check_Matchbox_valgrind = $(subst check,check-valgrind,$(check_Matchbox)) check-Matchbox: $(check_Matchbox) check-valgrind-Matchbox: $(check_Matchbox_valgrind) -check-extra: check-LHC-CEX check-LHC-GammaGamma check-LHC-MB check-TVT +check-extra: check-LHC-CEX check-LHC-GammaGamma check-LHC-ResolvedGammaGamma check-LHC-MB check-TVT check-valgrind-extra: check-valgrind-LHC-CEX check-valgrind-LHC-GammaGamma check-valgrind-LHC-MB check-valgrind-TVT check-all: check-local check-Powheg check-BSM check-Matchbox check-extra check-valgrind-all: check-valgrind-local check-valgrind-Powheg check-valgrind-BSM check-valgrind-Matchbox check-valgrind-extra link-helper-files: @for i in $(HELPERFILES); do \ if test -f $(srcdir)/$$i -a ! -e $$i; then \ $(LN_S) -f $(srcdir)/$$i; fi; done ## valgrind targets ## VALGRIND=valgrind --leak-check=full --num-callers=25 --freelist-vol=100000000 --leak-resolution=med --trace-children=yes check-valgrind-%: $(srcdir)/%.in HerwigDefaults.rpo link-helper-files $(VALGRIND) ./Herwig read -d1 -D $< &> valgrind-$(notdir $(subst .in,,$<))-read.log $(VALGRIND) ./Herwig run $(notdir $(subst .in,.run,$<)) -N 500 -d1 -D &> valgrind-$(notdir $(subst .in,,$<))-run.log valgrind: valgrind-init valgrind-read valgrind-run valgrind-init: $(VALGRIND) ./Herwig init -d1 -D -L$(top_builddir)/lib defaults/HerwigDefaults.in \ &> /tmp/valgrind-init.log valgrind-read: $(VALGRIND) ./Herwig read -d1 -D LHC.in &> /tmp/valgrind-read.log valgrind-run: $(VALGRIND) ./Herwig run -d1 -D -N5 LHC.run &> /tmp/valgrind-run.log CHECKCOMMAND = ./Herwig run $(notdir $(subst .in,.run,$<)) -N500 -d1 -D check-%: $(srcdir)/%.in HerwigDefaults.rpo link-helper-files ./Herwig read -i . $< -D @echo $(CHECKCOMMAND) @$(CHECKCOMMAND) && echo "# $@ OK #" \ || (echo "###### $@ BAD ######"; false) SETUPTHEPEG=$(THEPEGPATH)/bin/setupThePEG THEPEGREPO=$(THEPEGLIBPATH)/ThePEGDefaults.rpo install-data-hook: @echo Creating repository @./Herwig init -L$(DESTDIR)$(pkglibdir) -i$(DESTDIR)$(pkgdatadir) -i$(DESTDIR)$(pkgdatadir)/snippets $(DESTDIR)$(defaultsdir)/HerwigDefaults.in --repo=$(DESTDIR)$(pkgdatadir)/HerwigDefaults.rpo @if test -n "$(DESTDIR)"; \ then sed -i.bak -e "s@$(DESTDIR)@@g" $(DESTDIR)$(pkgdatadir)/HerwigDefaults.rpo; \ rm -f $(DESTDIR)$(pkgdatadir)/HerwigDefaults.rpo.bak; \ fi uninstall-hook: rm -f $(DESTDIR)$(pkgdatadir)/HerwigDefaults.rpo register: register-with-thepeg-repo register-with-thepeg-repo: @if test -x "$(SETUPTHEPEG)" -a -w "$(THEPEGREPO)"; \ then echo Registering with ThePEG; \ "$(SETUPTHEPEG)" --init \ $(DESTDIR)$(defaultsdir)/HerwigDefaults.in \ -r "$(THEPEGREPO)" -o "$(THEPEGREPO)" \ -i $(DESTDIR)$(pkgdatadir) \ -l$(DESTDIR)$(pkglibdir) ; \ if test -n "$(DESTDIR)"; \ then sed -i -e "s@$(DESTDIR)@@g" "$(THEPEGREPO)" ; fi ; \ fi unregister : unregister-from-thepeg-repo unregister-from-thepeg-repo: @if test -x "$(SETUPTHEPEG)" -a -w "$(THEPEGREPO)"; \ then echo Unregistering with ThePEG; \ "$(SETUPTHEPEG)" --init defaults/HerwigCleanup.in \ -r "$(THEPEGREPO)" -o "$(THEPEGREPO)" \ -l$(DESTDIR)$(pkglibdir) ; \ fi EXTRA_DIST = herwigopts.ggo nodist_Herwig_SOURCES = hgstamp.inc BUILT_SOURCES += hgstamp.inc CLEANFILES += hgstamp.inc HGVERSION := $(shell hg -R $(top_srcdir) parents --template '"Herwig {node|short} ({branch})"' 2> /dev/null || echo \"$(PACKAGE_STRING)\" || true ) .PHONY: update_hgstamp hgstamp.inc: update_hgstamp @[ -f $@ ] || touch $@ @echo '$(HGVERSION)' | cmp -s $@ - || echo '$(HGVERSION)' > $@ GENGETOPT = gengetopt %opts.h %opts.c : %opts.ggo $(GENGETOPT) < $< diff --git a/src/Matchbox/LO-DipoleShower.in.in b/src/Matchbox/LO-DipoleShower.in.in --- a/src/Matchbox/LO-DipoleShower.in.in +++ b/src/Matchbox/LO-DipoleShower.in.in @@ -1,24 +1,24 @@ # -*- ThePEG-repository -*- read Matchbox/LO.in cd /Herwig/EventHandlers set EventHandler:CascadeHandler /Herwig/DipoleShower/DipoleShowerHandler -read Matchbox/MCatNLO-Dipole-HardAlphaSTune.in +read snippets/Dipole_AutoTune_prel.in cd /Herwig/Analysis @CREATE_RIVET@ ThePEG::RivetAnalysis Rivet RivetAnalysis.so @CREATE_HEPMC@ ThePEG::HepMCFile HepMC HepMCAnalysis.so cd /Herwig/Particles do c:UnsetHardProcessMass do cbar:UnsetHardProcessMass set c:NominalMass 0*GeV set cbar:NominalMass 0*GeV cd /Herwig/UnderlyingEvent set MEQCD2to2Fast:StrictFlavourScheme Yes diff --git a/src/Matchbox/MCatLO-DipoleShower.in.in b/src/Matchbox/MCatLO-DipoleShower.in.in --- a/src/Matchbox/MCatLO-DipoleShower.in.in +++ b/src/Matchbox/MCatLO-DipoleShower.in.in @@ -1,28 +1,28 @@ # -*- ThePEG-repository -*- read Matchbox/LO.in cd /Herwig/EventHandlers set EventHandler:CascadeHandler /Herwig/DipoleShower/DipoleShowerHandler -read Matchbox/MCatNLO-Dipole-HardAlphaSTune.in +read snippets/Dipole_AutoTune_prel.in set /Herwig/DipoleShower/DipoleShowerHandler:RestrictPhasespace Yes set /Herwig/DipoleShower/DipoleShowerHandler:MaxPtIsMuF Yes set /Herwig/DipoleShower/DipoleShowerHandler:HardScaleProfile /Herwig/MatrixElements/Matchbox/HardScaleProfile cd /Herwig/Analysis @CREATE_RIVET@ ThePEG::RivetAnalysis Rivet RivetAnalysis.so @CREATE_HEPMC@ ThePEG::HepMCFile HepMC HepMCAnalysis.so cd /Herwig/Particles do c:UnsetHardProcessMass do cbar:UnsetHardProcessMass set c:NominalMass 0*GeV set cbar:NominalMass 0*GeV cd /Herwig/UnderlyingEvent set MEQCD2to2Fast:StrictFlavourScheme Yes diff --git a/src/Matchbox/MCatNLO-DipoleShower.in.in b/src/Matchbox/MCatNLO-DipoleShower.in.in --- a/src/Matchbox/MCatNLO-DipoleShower.in.in +++ b/src/Matchbox/MCatNLO-DipoleShower.in.in @@ -1,32 +1,32 @@ # -*- ThePEG-repository -*- cd /Herwig/EventHandlers set EventHandler:CascadeHandler /Herwig/DipoleShower/DipoleShowerHandler set /Herwig/DipoleShower/DipoleShowerHandler:RestrictPhasespace Yes set /Herwig/DipoleShower/DipoleShowerHandler:MaxPtIsMuF Yes set /Herwig/DipoleShower/DipoleShowerHandler:HardScaleProfile /Herwig/MatrixElements/Matchbox/HardScaleProfile cd /Herwig/MatrixElements/Matchbox set Factory:ShowerApproximation DipoleMatching # tunes -read Matchbox/MCatNLO-Dipole-HardAlphaSTune.in +read snippets/Dipole_AutoTune_prel.in cd /Herwig/Analysis @CREATE_RIVET@ ThePEG::RivetAnalysis Rivet RivetAnalysis.so @CREATE_HEPMC@ ThePEG::HepMCFile HepMC HepMCAnalysis.so cd /Herwig/Particles do c:UnsetHardProcessMass do cbar:UnsetHardProcessMass set c:NominalMass 0*GeV set cbar:NominalMass 0*GeV cd /Herwig/UnderlyingEvent set MEQCD2to2Fast:StrictFlavourScheme Yes diff --git a/src/Matchbox/Makefile.am b/src/Matchbox/Makefile.am --- a/src/Matchbox/Makefile.am +++ b/src/Matchbox/Makefile.am @@ -1,64 +1,65 @@ BUILT_SOURCES = done-all-links Matchboxdir = ${pkgdatadir}/Matchbox INPUTFILES = \ DefaultEEJets.in \ DefaultEPJets.in \ DefaultPPJets.in \ DiagonalCKM.in \ FiveFlavourNoBMassScheme.in \ FiveFlavourScheme.in \ FourFlavourScheme.in \ GoSam-GoSam.in \ HiggsEffective.in \ HJets.in \ IdentifiedBs.in \ InclusiveDurhamJets.in \ IncreaseVerbosity.in \ KrkNLO-DipoleShower.in \ LO-DefaultShower.in \ LO-DipoleShower.in \ LO.in \ LO-NoShower.in \ MadGraph-GoSam.in \ MadGraph-MadGraph.in \ MadGraph-NJet.in \ MadGraph-OpenLoops.in \ MCatLO-DefaultShower.in \ MCatLO-DipoleShower.in \ MCatNLO-DefaultShower.in \ MCatNLO-Dipole-HardAlphaSTune.in \ MCatNLO-DipoleShower.in \ MMHT2014.in \ MuDown.in \ MuQDown.in \ MuQUp.in \ MuUp.in \ NJet-NJet.in \ NLO-NoShower.in \ NonDiagonalCKM.in \ OnShellHProduction.in \ OnShellTopProduction.in \ OnShellWProduction.in \ OnShellZProduction.in \ OpenLoops-OpenLoops.in \ Powheg-DefaultShower.in \ Powheg-DipoleShower.in \ Powheg.in \ PQCDLevel.in \ StandardModelLike.in \ +ShowerBenchmarks.in \ VBFDiagramsOnly.in \ VBFNLO.in \ VBFNLOPhasespace.in dist_Matchbox_DATA = $(INPUTFILES) CLEANFILES = done-all-links done-all-links: $(INPUTFILES) @echo "Linking input files" @for i in $(INPUTFILES); do \ if test -f $(srcdir)/$$i -a ! -e $$i; then \ $(LN_S) -f $(srcdir)/$$i; fi; done @touch done-all-links diff --git a/src/Matchbox/Powheg-DipoleShower.in.in b/src/Matchbox/Powheg-DipoleShower.in.in --- a/src/Matchbox/Powheg-DipoleShower.in.in +++ b/src/Matchbox/Powheg-DipoleShower.in.in @@ -1,30 +1,30 @@ # -*- ThePEG-repository -*- read Matchbox/Powheg.in set /Herwig/MatrixElements/Matchbox/MEMatching:TruncatedShower No cd /Herwig/EventHandlers set EventHandler:CascadeHandler /Herwig/DipoleShower/DipoleShowerHandler set /Herwig/DipoleShower/DipoleShowerHandler:RestrictPhasespace Yes set /Herwig/DipoleShower/DipoleShowerHandler:MaxPtIsMuF Yes set /Herwig/DipoleShower/DipoleShowerHandler:HardScaleProfile NULL # tunes -read Matchbox/MCatNLO-Dipole-HardAlphaSTune.in +read snippets/Dipole_AutoTune_prel.in cd /Herwig/Analysis @CREATE_RIVET@ ThePEG::RivetAnalysis Rivet RivetAnalysis.so @CREATE_HEPMC@ ThePEG::HepMCFile HepMC HepMCAnalysis.so cd /Herwig/Particles do c:UnsetHardProcessMass do cbar:UnsetHardProcessMass set c:NominalMass 0*GeV set cbar:NominalMass 0*GeV cd /Herwig/UnderlyingEvent set MEQCD2to2Fast:StrictFlavourScheme Yes diff --git a/src/Matchbox/ShowerBenchmarks.in b/src/Matchbox/ShowerBenchmarks.in new file mode 100644 --- /dev/null +++ b/src/Matchbox/ShowerBenchmarks.in @@ -0,0 +1,143 @@ +# -*- ThePEG-repository -*- + +# ############################################################################## +# +# unify alphas running +# +# ############################################################################## + +cd /Herwig/Couplings + +set NLOAlphaS:input_alpha_s 0.118 +set NLOAlphaS:input_scale 91.1876 +set NLOAlphaS:two_largeq_terms No + +clear NLOAlphaS:QuarkMasses +insert NLOAlphaS:QuarkMasses[0] 0.005 +insert NLOAlphaS:QuarkMasses[1] 0.0023 +insert NLOAlphaS:QuarkMasses[2] 0.095 +insert NLOAlphaS:QuarkMasses[3] 1.25 +insert NLOAlphaS:QuarkMasses[4] 4.2 +insert NLOAlphaS:QuarkMasses[5] 174.2 + +cd /Herwig/Shower + +set AlphaQCD:ScaleFactor 1.0 +set AlphaQCD:NPAlphaS 2 +set AlphaQCD:Qmin 0.935 +set AlphaQCD:NumberOfLoops 2 +set AlphaQCD:InputOption 1 + +set AlphaQCD:AlphaMZ 0.118 +set AlphaQCD:InputScale 91.1876 + +clear AlphaQCD:QuarkMasses +insert AlphaQCD:QuarkMasses[0] 0.005 +insert AlphaQCD:QuarkMasses[1] 0.0023 +insert AlphaQCD:QuarkMasses[2] 0.095 +insert AlphaQCD:QuarkMasses[3] 1.25 +insert AlphaQCD:QuarkMasses[4] 4.2 +insert AlphaQCD:QuarkMasses[5] 174.2 + +set /Herwig/Model:QCD/RunningAlphaS /Herwig/Couplings/NLOAlphaS +set /Herwig/DipoleShower/DipoleShowerHandler:GlobalAlphaS /Herwig/Couplings/NLOAlphaS +set /Herwig/Generators/EventGenerator:StandardModelParameters:QCD/RunningAlphaS /Herwig/Couplings/NLOAlphaS + +# ############################################################################## +# +# PDF settings -- same NLO PDF everywhere +# +# ############################################################################## + +read Matchbox/FourFlavourScheme.in + +cd /Herwig/Partons + +set HardNLOPDF:PDFName MMHT2014nlo68cl +set ShowerNLOPDF:PDFName MMHT2014nlo68cl + +set /Herwig/Particles/p+:PDF HardNLOPDF +set /Herwig/Particles/pbar-:PDF HardNLOPDF +set /Herwig/Partons/PPExtractor:FirstPDF HardNLOPDF +set /Herwig/Partons/PPExtractor:SecondPDF HardNLOPDF + +set /Herwig/Shower/ShowerHandler:PDFA ShowerNLOPDF +set /Herwig/Shower/ShowerHandler:PDFB ShowerNLOPDF +set /Herwig/DipoleShower/DipoleShowerHandler:PDFA ShowerNLOPDF +set /Herwig/DipoleShower/DipoleShowerHandler:PDFB ShowerNLOPDF + +# ############################################################################## +# +# Quark kinematic masses are all zero +# +# ############################################################################## + +cd /Herwig/Particles + +do d:UnsetHardProcessMass +do dbar:UnsetHardProcessMass +set d:NominalMass 0*GeV +set dbar:NominalMass 0*GeV + +do u:UnsetHardProcessMass +do ubar:UnsetHardProcessMass +set u:NominalMass 0*GeV +set ubar:NominalMass 0*GeV + +do s:UnsetHardProcessMass +do sbar:UnsetHardProcessMass +set s:NominalMass 0*GeV +set sbar:NominalMass 0*GeV + +do c:UnsetHardProcessMass +do cbar:UnsetHardProcessMass +set c:NominalMass 0*GeV +set cbar:NominalMass 0*GeV + +# ############################################################################## +# +# Shower settings are those appropriate to the uncertainties studies +# +# ############################################################################## + +read Matchbox/PQCDLevel.in + +set /Herwig/Shower/ShowerHandler:MaxPtIsMuF Yes +set /Herwig/Shower/ShowerHandler:HardEmission None +set /Herwig/Shower/ShowerHandler:Interactions QCD +set /Herwig/Shower/ShowerHandler:SpinCorrelations No +set /Herwig/Shower/ShowerHandler:SoftCorrelations No +set /Herwig/Shower/KinematicsReconstructor:ReconstructionOption Colour4 +set /Herwig/Shower/KinematicsReconstructor:InitialStateReconOption SofterFraction +set /Herwig/Shower/PartnerFinder:PartnerMethod 0 +set /Herwig/Shower/PartnerFinder:ScaleChoice 0 +set /Herwig/DipoleShower/DipoleShowerHandler:MaxPtIsMuF Yes + +set /Herwig/Shower/ShowerHandler:IntrinsicPtGaussian 0.0*GeV +set /Herwig/DipoleShower/IntrinsicPtGenerator:ValenceIntrinsicPtScale 0.0*GeV +set /Herwig/DipoleShower/IntrinsicPtGenerator:SeaIntrinsicPtScale 0.0*GeV + +set /Herwig/DipoleShower/DipoleShowerHandler:MPIHandler NULL +set /Herwig/Shower/ShowerHandler:MPIHandler NULL + +set /Herwig/DipoleShower/DipoleShowerHandler:HardScaleProfile /Herwig/MatrixElements/Matchbox/HardScaleProfile +set /Herwig/Shower/ShowerHandler:HardScaleProfile /Herwig/MatrixElements/Matchbox/HardScaleProfile + +set /Herwig/MatrixElements/Matchbox/HardScaleProfile:ProfileType Resummation + +set /Herwig/DipoleShower/Kinematics/FFLightKinematics:IRCutoff 1.0*GeV +set /Herwig/DipoleShower/Kinematics/FILightKinematics:IRCutoff 1.0*GeV +set /Herwig/DipoleShower/Kinematics/IFLightKinematics:IRCutoff 1.0*GeV +set /Herwig/DipoleShower/Kinematics/IILightKinematics:IRCutoff 1.0*GeV + +cd /Herwig/Shower + +set QtoQGSudakov:pTmin 1.0*GeV +set GtoGGSudakov:pTmin 1.0*GeV +set GtoQQbarSudakov:pTmin 1.0*GeV +set GtobbbarSudakov:pTmin 1.0*GeV +set GtoccbarSudakov:pTmin 1.0*GeV +set QtoGQSudakov:pTmin 1.0*GeV +set utoGuSudakov:pTmin 1.0*GeV +set dtoGdSudakov:pTmin 1.0*GeV + diff --git a/src/Merging/LEP-Merging.in b/src/Merging/LEP-Merging.in --- a/src/Merging/LEP-Merging.in +++ b/src/Merging/LEP-Merging.in @@ -1,156 +1,155 @@ # -*- ThePEG-repository -*- ################################################## ## Herwig/Merging example input file ################################################## ################################################## ## Collider type ################################################## read snippets/DipoleMerging.in read snippets/EECollider.in read snippets/MonacoSampler.in ################################################## ## Beam energy sqrt(s) ################################################## cd /Herwig/EventHandlers set EventHandler:LuminosityFunction:Energy 91.2*GeV ################################################## ## Process selection ################################################## ## Note that event generation may fail if no matching matrix element has ## been found. Coupling orders are with respect to the Born process, ## i.e. NLO QCD does not require an additional power of alphas. ## Model assumptions read Matchbox/StandardModelLike.in read Matchbox/DiagonalCKM.in ## Set the order of the couplings cd /Herwig/Merging set MergingFactory:OrderInAlphaS 0 set MergingFactory:OrderInAlphaEW 2 ## Select the process ## You may use identifiers such as p, pbar, j, l, mu+, h0 etc. do MergingFactory:Process e- e+ -> j j [ j j ] set MergingFactory:NLOProcesses 2 set Merger:MergingScale 4.*GeV set Merger:MergingScaleSmearing 0.1 cd /Herwig/MatrixElements/Matchbox/Utility insert DiagramGenerator:ExcludeInternal 0 /Herwig/Particles/gamma ## Special settings required for on-shell production of unstable particles ## enable for on-shell top production # read Matchbox/OnShellTopProduction.in ## enable for on-shell W, Z or h production # read Matchbox/OnShellWProduction.in # read Matchbox/OnShellZProduction.in # read Matchbox/OnShellHProduction.in ################################################## ## Matrix element library selection ################################################## ## Select a generic tree/loop combination or a ## specialized NLO package ## As massive b-quarks are currently not supported by the ## build in ME an external ME-Provider is needed (e.g. MG+OL). # read Matchbox/MadGraph-GoSam.in # read Matchbox/MadGraph-MadGraph.in # read Matchbox/MadGraph-NJet.in read Matchbox/MadGraph-OpenLoops.in ################################################## ## Cut selection ## See the documentation for more options ################################################## ## cuts on additional jets cd /Herwig/Cuts # read Matchbox/DefaultEEJets.in # set NJetsCut:NJetsMin 3 ################################################## ## Scale choice ## See the documentation for more options ################################################## cd /Herwig/MatrixElements/Matchbox/Scales/ set /Herwig/Merging/MergingFactory:ScaleChoice SHatScale ################################################## ## Scale uncertainties ################################################## # read Matchbox/MuDown.in # read Matchbox/MuUp.in ################################################## ## Shower scale uncertainties ################################################## # read Matchbox/MuQDown.in # read Matchbox/MuQUp.in ################################################## ## CMW - Scheme ################################################## - -read Merging/Merging-Dipole-FactorCMWSchemeTune.in +read snippets/Dipole_AutoTune_prel.in ### Use factor in alpha_s argument: alpha_s(q) -> alpha_s(fac*q) ### with fac=exp(-(67-3pi^2-10/3*Nf)/(33-2Nf)) read Merging/FactorCMWScheme.in ### Linear CMW multiplication: ### alpha_s(q) -> alpha_s(q)(1+K_g*alpha_s(q)/2pi ) # read Merging/LinearCMWScheme.in ################################################## ## Analyses ################################################## cd /Herwig/Analysis ## Write HepMC events. Modify the PrintEvent interface for your needs. # insert /Herwig/Generators/EventGenerator:AnalysisHandlers 0 HepMCFile ## Setup the Rivet analysis: #read snippets/Rivet.in #insert Rivet:Analyses 0 XXX_2017_ABC123 ## Here we collected a various Rivet analysis for LEP ## at the Z Mass. (The collection might not be complete.) # read Merging/LEP91-Analysis.in ################################################## ## Do not apply profile scales for LEP as hard ## scale coincides with kinematic limit ################################################## set /Herwig/Shower/ShowerHandler:HardScaleProfile NULL set /Herwig/DipoleShower/DipoleShowerHandler:HardScaleProfile NULL ################################################## ## Save the generator ################################################## do /Herwig/Merging/MergingFactory:ProductionMode cd /Herwig/Generators saverun LEP-Merging EventGenerator diff --git a/src/Merging/LHC-H-Merging.in b/src/Merging/LHC-H-Merging.in --- a/src/Merging/LHC-H-Merging.in +++ b/src/Merging/LHC-H-Merging.in @@ -1,194 +1,194 @@ # -*- ThePEG-repository -*- ################################################## ## Herwig/Merging example input file ################################################## ################################################## ## Collider type ################################################## read snippets/DipoleMerging.in read snippets/PPCollider.in read snippets/MonacoSampler.in ################################################## ## Beam energy sqrt(s) ################################################## cd /Herwig/EventHandlers set EventHandler:LuminosityFunction:Energy 8000*GeV ################################################## ## Process selection ################################################## ## Note that event generation may fail if no matching matrix element has ## been found. Coupling orders are with respect to the Born process, ## i.e. NLO QCD does not require an additional power of alphas. ## Model assumptions read Matchbox/StandardModelLike.in read Matchbox/DiagonalCKM.in ## Set the order of the couplings cd /Herwig/Merging set MergingFactory:OrderInAlphaS 2 set MergingFactory:OrderInAlphaEW 1 ## Select the process ## You may use identifiers such as p, pbar, j, l, mu+, h0 etc. do MergingFactory:Process p p -> h0 [ j j ] set MergingFactory:NLOProcesses 2 # Set the merging scale deviding the parton shower # from the matrix element region in phase space. set Merger:MergingScale 15.*GeV set Merger:MergingScaleSmearing 0.1 # The following line clear a preweighter # that is not working for Higgs as here # pt and HT are 0 before the shower. # See other merging files for more information. clear MergingFactory:Preweighters # The next line can switch of hadronization # and MPI modelling. Use with care!! # read Matchbox/PQCDLevel.in ## Special settings required for on-shell production of unstable particles ## enable for on-shell top production # read Matchbox/OnShellTopProduction.in ## enable for on-shell W, Z or h production # read Matchbox/OnShellWProduction.in # read Matchbox/OnShellZProduction.in read Matchbox/OnShellHProduction.in set /Herwig/Particles/h0:Stable Stable # Special settings for the VBF approximation # read Matchbox/VBFDiagramsOnly.in ################################################## ## Matrix element library selection ################################################## ## Select a generic tree/loop combination or a ## specialized NLO package # read Matchbox/MadGraph-GoSam.in # read Matchbox/MadGraph-MadGraph.in # read Matchbox/MadGraph-NJet.in read Matchbox/MadGraph-OpenLoops.in #read Matchbox/HJets.in # read Matchbox/VBFNLO.in ## Uncomment this to use ggh effective couplings ## currently only supported by MadGraph-GoSam and ## MadGraph-Openloops #read Matchbox/HiggsEffective.in cd /Herwig/MatrixElements/Matchbox/Amplitudes set OpenLoops:HiggsEff Yes set MadGraph:Model heft ################################################## ## Cut selection ## See the documentation for more options ################################################## cd /Herwig/Cuts/ set ChargedLeptonPairMassCut:MinMass 60*GeV set ChargedLeptonPairMassCut:MaxMass 120*GeV cd /Herwig/MatrixElements/Matchbox/Utility insert DiagramGenerator:ExcludeInternal 0 /Herwig/Particles/gamma ## cuts on additional jets cd /Herwig/Cuts/ # read Matchbox/DefaultPPJets.in # insert JetCuts:JetRegions 0 FirstJet # insert JetCuts:JetRegions 1 SecondJet # insert JetCuts:JetRegions 2 ThirdJet # insert JetCuts:JetRegions 3 FourthJet ################################################## ## Scale choice ## See the documentation for more options ################################################## cd /Herwig/MatrixElements/Matchbox/Scales/ set /Herwig/Merging/MergingFactory:ScaleChoice FixedScale set FixedScale:FixedScale 125.*GeV ################################################## ## Scale uncertainties ################################################## # read Matchbox/MuDown.in # read Matchbox/MuUp.in ################################################## ## Shower scale uncertainties ################################################## # read Matchbox/MuQDown.in # read Matchbox/MuQUp.in ################################################## ## CMW - Scheme ################################################## -read Merging/Merging-Dipole-FactorCMWSchemeTune.in +read snippets/Dipole_AutoTune_prel.in ### Use factor in alpha_s argument: alpha_s(q) -> alpha_s(fac*q) ### with fac=exp(-(67-3pi^2-10/3*Nf)/(33-2Nf)) read Merging/FactorCMWScheme.in ### Linear CMW multiplication: ### alpha_s(q) -> alpha_s(q)(1+K_g*alpha_s(q)/2pi ) # read Merging/LinearCMWScheme.in ################################################## ## PDF choice ################################################## read Matchbox/FiveFlavourNoBMassScheme.in read Matchbox/MMHT2014.in ################################################## ## Analyses ################################################## cd /Herwig/Analysis ## Write HepMC events. Modify the PrintEvent interface for your needs. # insert /Herwig/Generators/EventGenerator:AnalysisHandlers 0 HepMCFile ## Setup the Rivet analysis: #read snippets/Rivet.in #insert Rivet:Analyses 0 XXX_2017_ABC123 ## Here we collected a various Rivet analysis for Higgs at LHC ## at the 8 TeV. (The collection might not be complete.) # read Merging/LHC8-H-Analysis.in ################################################## ## Save the generator ################################################## do /Herwig/Merging/MergingFactory:ProductionMode set /Herwig/Generators/EventGenerator:IntermediateOutput Yes cd /Herwig/Generators saverun LHC-H-Merging EventGenerator diff --git a/src/Merging/LHC-J-Merging.in b/src/Merging/LHC-J-Merging.in --- a/src/Merging/LHC-J-Merging.in +++ b/src/Merging/LHC-J-Merging.in @@ -1,191 +1,191 @@ # -*- ThePEG-repository -*- ################################################## ## Herwig/Merging example input file ################################################## ################################################## ## Collider type ################################################## read snippets/DipoleMerging.in read snippets/PPCollider.in read snippets/MonacoSampler.in ################################################## ## Beam energy sqrt(s) ################################################## cd /Herwig/EventHandlers set EventHandler:LuminosityFunction:Energy 7000*GeV ################################################## ## Process selection ################################################## ## Note that event generation may fail if no matching matrix element has ## been found. Coupling orders are with respect to the Born process, ## i.e. NLO QCD does not require an additional power of alphas. ## Model assumptions read Matchbox/StandardModelLike.in read Matchbox/DiagonalCKM.in ## Set the order of the couplings cd /Herwig/Merging set MergingFactory:OrderInAlphaS 2 set MergingFactory:OrderInAlphaEW 0 ## Select the process ## You may use identifiers such as p, pbar, j, l, mu+, h0 etc. do MergingFactory:Process p p -> j j [ j ] set MergingFactory:NLOProcesses 1 # Set the merging scale deviding the parton shower # from the matrix element region in phase space. set Merger:MergingScale 20.*GeV set Merger:MergingScaleSmearing 0.1 # The following lines control a preweighter, # that can be used to force more events in higher # HT or pt regions. The unweighted events are accepted # with a enhanced probability W, that is divided fron the # event weight once the event is accepted. # W = ((HT/scale)^HTPower + (pt_max/scale)^MaxPTPower) # with scale = MZ (can be changed) # Note that the weights will therefore differ from "1" # if the powers are not zero. set MPreWeight:HTPower 0 set MPreWeight:MaxPTPower 0 set MPreWeight:OnlyColoured No # The next line can switch of hadronization # and MPI modelling. Use with care!! # read Matchbox/PQCDLevel.in ## Special settings required for on-shell production of unstable particles ## enable for on-shell top production # read Matchbox/OnShellTopProduction.in ## enable for on-shell W, Z or h production # read Matchbox/OnShellWProduction.in # read Matchbox/OnShellZProduction.in # read Matchbox/OnShellHProduction.in # Special settings for the VBF approximation # read Matchbox/VBFDiagramsOnly.in ################################################## ## Matrix element library selection ################################################## ## Select a generic tree/loop combination or a ## specialized NLO package # read Matchbox/MadGraph-GoSam.in # read Matchbox/MadGraph-MadGraph.in # read Matchbox/MadGraph-NJet.in read Matchbox/MadGraph-OpenLoops.in # read Matchbox/HJets.in # read Matchbox/VBFNLO.in ## Uncomment this to use ggh effective couplings ## currently only supported by MadGraph-GoSam ## and MadGraph-OpenLoops # read Matchbox/HiggsEffective.in ################################################## ## Cut selection ## See the documentation for more options ################################################## cd /Herwig/Cuts/ set ChargedLeptonPairMassCut:MinMass 60*GeV set ChargedLeptonPairMassCut:MaxMass 120*GeV cd /Herwig/MatrixElements/Matchbox/Utility insert DiagramGenerator:ExcludeInternal 0 /Herwig/Particles/gamma ## cuts on additional jets cd /Herwig/Cuts/ read Matchbox/DefaultPPJets.in insert JetCuts:JetRegions 0 FirstJet # insert JetCuts:JetRegions 1 SecondJet # insert JetCuts:JetRegions 2 ThirdJet # insert JetCuts:JetRegions 3 FourthJet ################################################## ## Scale choice ## See the documentation for more options ################################################## cd /Herwig/MatrixElements/Matchbox/Scales/ set /Herwig/Merging/MergingFactory:ScaleChoice MaxJetPtScale ################################################## ## Scale uncertainties ################################################## # read Matchbox/MuDown.in # read Matchbox/MuUp.in ################################################## ## Shower scale uncertainties ################################################## # read Matchbox/MuQDown.in # read Matchbox/MuQUp.in ################################################## ## CMW - Scheme ################################################## -read Merging/Merging-Dipole-FactorCMWSchemeTune.in +read snippets/Dipole_AutoTune_prel.in ### Use factor in alpha_s argument: alpha_s(q) -> alpha_s(fac*q) ### with fac=exp(-(67-3pi^2-10/3*Nf)/(33-2Nf)) read Merging/FactorCMWScheme.in ### Linear CMW multiplication: ### alpha_s(q) -> alpha_s(q)(1+K_g*alpha_s(q)/2pi ) # read Merging/LinearCMWScheme.in ################################################## ## PDF choice ################################################## read Matchbox/FiveFlavourNoBMassScheme.in read Matchbox/MMHT2014.in ################################################## ## Analyses ################################################## cd /Herwig/Analysis ## Write HepMC events. Modify the PrintEvent interface for your needs. # insert /Herwig/Generators/EventGenerator:AnalysisHandlers 0 HepMCFile ## Setup the Rivet analysis: #read snippets/Rivet.in #insert Rivet:Analyses 0 XXX_2017_ABC123 ## Here we collected a various Rivet analysis for Jets at LHC ## at the 7 TeV. (The collection might not be complete.) # read Merging/LHC7-J-Analysis.in ################################################## ## Save the generator ################################################## do /Herwig/Merging/MergingFactory:ProductionMode set /Herwig/Generators/EventGenerator:IntermediateOutput Yes cd /Herwig/Generators saverun LHC-J-Merging EventGenerator diff --git a/src/Merging/LHC-T-Merging.in b/src/Merging/LHC-T-Merging.in --- a/src/Merging/LHC-T-Merging.in +++ b/src/Merging/LHC-T-Merging.in @@ -1,193 +1,193 @@ # -*- ThePEG-repository -*- ################################################## ## Herwig/Merging example input file ################################################## ################################################## ## Collider type ################################################## read snippets/DipoleMerging.in read snippets/PPCollider.in read snippets/MonacoSampler.in ################################################## ## Beam energy sqrt(s) ################################################## cd /Herwig/EventHandlers set EventHandler:LuminosityFunction:Energy 7000*GeV ################################################## ## Process selection ################################################## ## Note that event generation may fail if no matching matrix element has ## been found. Coupling orders are with respect to the Born process, ## i.e. NLO QCD does not require an additional power of alphas. ## Model assumptions read Matchbox/StandardModelLike.in read Matchbox/DiagonalCKM.in ## Set the order of the couplings cd /Herwig/Merging set MergingFactory:OrderInAlphaS 2 set MergingFactory:OrderInAlphaEW 0 ## Select the process ## You may use identifiers such as p, pbar, j, l, mu+, h0 etc. do MergingFactory:Process p p -> t tbar [ j] set MergingFactory:NLOProcesses 1 # Set the merging scale deviding the parton shower # from the matrix element region in phase space. set Merger:MergingScale 20.*GeV set Merger:MergingScaleSmearing 0.1 # The following lines control a preweighter, # that can be used to force more events in higher # HT or pt regions. The unweighted events are accepted # with a enhanced probability W, that is divided fron the # event weight once the event is accepted. # W = ((HT/scale)^HTPower + (pt_max/scale)^MaxPTPower) # with scale = MZ (can be changed) # Note that the weights will therefore differ from "1" # if the powers are not zero. set MPreWeight:HTPower 0 set MPreWeight:MaxPTPower 0 set MPreWeight:OnlyColoured No # The next line can switch of hadronization # and MPI modelling. Use with care!! # read Matchbox/PQCDLevel.in ## Special settings required for on-shell production of unstable particles ## enable for on-shell top production read Matchbox/OnShellTopProduction.in ## enable for on-shell W, Z or h production # read Matchbox/OnShellWProduction.in # read Matchbox/OnShellZProduction.in # read Matchbox/OnShellHProduction.in # Special settings for the VBF approximation # read Matchbox/VBFDiagramsOnly.in ################################################## ## Matrix element library selection ################################################## ## Select a generic tree/loop combination or a ## specialized NLO package # read Matchbox/MadGraph-GoSam.in # read Matchbox/MadGraph-MadGraph.in # read Matchbox/MadGraph-NJet.in read Matchbox/MadGraph-OpenLoops.in # read Matchbox/HJets.in # read Matchbox/VBFNLO.in ## Uncomment this to use ggh effective couplings ## currently only supported by MadGraph-GoSam and ## MadGraph-Openloops # read Matchbox/HiggsEffective.in ################################################## ## Cut selection ## See the documentation for more options ################################################## cd /Herwig/Cuts/ set ChargedLeptonPairMassCut:MinMass 60*GeV set ChargedLeptonPairMassCut:MaxMass 120*GeV cd /Herwig/MatrixElements/Matchbox/Utility insert DiagramGenerator:ExcludeInternal 0 /Herwig/Particles/gamma ## cuts on additional jets cd /Herwig/Cuts/ # read Matchbox/DefaultPPJets.in # insert JetCuts:JetRegions 0 FirstJet # insert JetCuts:JetRegions 1 SecondJet # insert JetCuts:JetRegions 2 ThirdJet # insert JetCuts:JetRegions 3 FourthJet ################################################## ## Scale choice ## See the documentation for more options ################################################## cd /Herwig/MatrixElements/Matchbox/Scales/ set /Herwig/Merging/MergingFactory:ScaleChoice TopPairMassScale ################################################## ## Scale uncertainties ################################################## # read Matchbox/MuDown.in # read Matchbox/MuUp.in ################################################## ## Shower scale uncertainties ################################################## # read Matchbox/MuQDown.in # read Matchbox/MuQUp.in ################################################## ## CMW - Scheme ################################################## -read Merging/Merging-Dipole-FactorCMWSchemeTune.in +read snippets/Dipole_AutoTune_prel.in ### Use factor in alpha_s argument: alpha_s(q) -> alpha_s(fac*q) ### with fac=exp(-(67-3pi^2-10/3*Nf)/(33-2Nf)) read Merging/FactorCMWScheme.in ### Linear CMW multiplication: ### alpha_s(q) -> alpha_s(q)(1+K_g*alpha_s(q)/2pi ) # read Merging/LinearCMWScheme.in ################################################## ## PDF choice ################################################## read Matchbox/FiveFlavourNoBMassScheme.in read Matchbox/MMHT2014.in ################################################## ## Analyses ################################################## cd /Herwig/Analysis ## Write HepMC events. Modify the PrintEvent interface for your needs. # insert /Herwig/Generators/EventGenerator:AnalysisHandlers 0 HepMCFile ## Setup the Rivet analysis: #read snippets/Rivet.in #insert Rivet:Analyses 0 XXX_2017_ABC123 ## Here we collected a various Rivet analysis for Tops at LHC ## at the 7 TeV. (The collection might not be complete.) # read Merging/LHC7-T-Analysis.in ################################################## ## Save the generator ################################################## do /Herwig/Merging/MergingFactory:ProductionMode set /Herwig/Generators/EventGenerator:IntermediateOutput Yes cd /Herwig/Generators saverun LHC-T-Merging EventGenerator diff --git a/src/Merging/LHC-W-Merging.in b/src/Merging/LHC-W-Merging.in --- a/src/Merging/LHC-W-Merging.in +++ b/src/Merging/LHC-W-Merging.in @@ -1,194 +1,194 @@ # -*- ThePEG-repository -*- ################################################## ## Herwig/Merging example input file ################################################## ################################################## ## Collider type ################################################## read snippets/DipoleMerging.in read snippets/PPCollider.in read snippets/MonacoSampler.in ################################################## ## Beam energy sqrt(s) ################################################## cd /Herwig/EventHandlers set EventHandler:LuminosityFunction:Energy 7000*GeV ################################################## ## Process selection ################################################## ## Note that event generation may fail if no matching matrix element has ## been found. Coupling orders are with respect to the Born process, ## i.e. NLO QCD does not require an additional power of alphas. ## Model assumptions read Matchbox/StandardModelLike.in read Matchbox/DiagonalCKM.in ## Set the order of the couplings cd /Herwig/Merging set MergingFactory:OrderInAlphaS 0 set MergingFactory:OrderInAlphaEW 2 ## Select the process ## You may use identifiers such as p, pbar, j, l, mu+, h0 etc. do MergingFactory:Process p p -> l nu [ j j ] set MergingFactory:NLOProcesses 2 # Set the merging scale deviding the parton shower # from the matrix element region in phase space. set Merger:MergingScale 15.*GeV set Merger:MergingScaleSmearing 0.1 # The following lines control a preweighter, # that can be used to force more events in higher # HT or pt regions. The unweighted events are accepted # with a enhanced probability W, that is divided fron the # event weight once the event is accepted. # W = ((HT/scale)^HTPower + (pt_max/scale)^MaxPTPower) # with scale = MZ (can be changed) # Note that the weights will therefore differ from "1" # if the powers are not zero. set MPreWeight:HTPower 0 set MPreWeight:MaxPTPower 0 set MPreWeight:OnlyColoured No # The next line can switch of hadronization # and MPI modelling. Use with care!! # read Matchbox/PQCDLevel.in ## Special settings required for on-shell production of unstable particles ## enable for on-shell top production # read Matchbox/OnShellTopProduction.in ## enable for on-shell W, Z or h production # read Matchbox/OnShellWProduction.in # read Matchbox/OnShellZProduction.in # read Matchbox/OnShellHProduction.in # Special settings for the VBF approximation # read Matchbox/VBFDiagramsOnly.in ################################################## ## Matrix element library selection ################################################## ## Select a generic tree/loop combination or a ## specialized NLO package # read Matchbox/MadGraph-GoSam.in # read Matchbox/MadGraph-MadGraph.in # read Matchbox/MadGraph-NJet.in # read Matchbox/MadGraph-OpenLoops.in # read Matchbox/HJets.in # read Matchbox/VBFNLO.in ## Uncomment this to use ggh effective couplings ## currently only supported by MadGraph-GoSam and ## MadGraph-Openloops # read Matchbox/HiggsEffective.in ################################################## ## Cut selection ## See the documentation for more options ################################################## cd /Herwig/Cuts/ set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV set /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV cd /Herwig/MatrixElements/Matchbox/Utility insert DiagramGenerator:ExcludeInternal 0 /Herwig/Particles/gamma ## cuts on additional jets cd /Herwig/Cuts/ # read Matchbox/DefaultPPJets.in # insert JetCuts:JetRegions 0 FirstJet # insert JetCuts:JetRegions 1 SecondJet # insert JetCuts:JetRegions 2 ThirdJet # insert JetCuts:JetRegions 3 FourthJet ################################################## ## Scale choice ## See the documentation for more options ################################################## cd /Herwig/MatrixElements/Matchbox/Scales/ set /Herwig/Merging/MergingFactory:ScaleChoice LeptonPairMassScale ################################################## ## Scale uncertainties ################################################## # read Matchbox/MuDown.in # read Matchbox/MuUp.in ################################################## ## Shower scale uncertainties ################################################## # read Matchbox/MuQDown.in # read Matchbox/MuQUp.in ################################################## ## CMW - Scheme ################################################## -read Merging/Merging-Dipole-FactorCMWSchemeTune.in +read snippets/Dipole_AutoTune_prel.in ### Use factor in alpha_s argument: alpha_s(q) -> alpha_s(fac*q) ### with fac=exp(-(67-3pi^2-10/3*Nf)/(33-2Nf)) read Merging/FactorCMWScheme.in ### Linear CMW multiplication: ### alpha_s(q) -> alpha_s(q)(1+K_g*alpha_s(q)/2pi ) # read Merging/LinearCMWScheme.in ################################################## ## PDF choice ################################################## read Matchbox/FiveFlavourNoBMassScheme.in read Matchbox/MMHT2014.in ################################################## ## Analyses ################################################## cd /Herwig/Analysis ## Write HepMC events. Modify the PrintEvent interface for your needs. # insert /Herwig/Generators/EventGenerator:AnalysisHandlers 0 HepMCFile ## Setup the Rivet analysis: #read snippets/Rivet.in #insert Rivet:Analyses 0 XXX_2017_ABC123 ## Here we collected a various Rivet analysis for Ws at LHC ## at the 7 TeV. (The collection might not be complete.) # read Merging/LHC7-W-Analysis.in ################################################## ## Save the generator ################################################## do /Herwig/Merging/MergingFactory:ProductionMode set /Herwig/Generators/EventGenerator:IntermediateOutput Yes cd /Herwig/Generators saverun LHC-W-Merging EventGenerator diff --git a/src/Merging/LHC-Z-Merging.in b/src/Merging/LHC-Z-Merging.in --- a/src/Merging/LHC-Z-Merging.in +++ b/src/Merging/LHC-Z-Merging.in @@ -1,194 +1,194 @@ # -*- ThePEG-repository -*- ################################################## ## Herwig/Merging example input file ################################################## ################################################## ## Collider type ################################################## read snippets/DipoleMerging.in read snippets/PPCollider.in read snippets/MonacoSampler.in ################################################## ## Beam energy sqrt(s) ################################################## cd /Herwig/EventHandlers set EventHandler:LuminosityFunction:Energy 7000*GeV ################################################## ## Process selection ################################################## ## Note that event generation may fail if no matching matrix element has ## been found. Coupling orders are with respect to the Born process, ## i.e. NLO QCD does not require an additional power of alphas. ## Model assumptions read Matchbox/StandardModelLike.in read Matchbox/DiagonalCKM.in ## Set the order of the couplings cd /Herwig/Merging set MergingFactory:OrderInAlphaS 0 set MergingFactory:OrderInAlphaEW 2 ## Select the process ## You may use identifiers such as p, pbar, j, l, mu+, h0 etc. do MergingFactory:Process p p -> e+ e- [ j j ] set MergingFactory:NLOProcesses 2 # Set the merging scale deviding the parton shower # from the matrix element region in phase space. set Merger:MergingScale 15.*GeV set Merger:MergingScaleSmearing 0.1 # The following lines control a preweighter, # that can be used to force more events in higher # HT or pt regions. The unweighted events are accepted # with a enhanced probability W, that is divided fron the # event weight once the event is accepted. # W = ((HT/scale)^HTPower + (pt_max/scale)^MaxPTPower) # with scale = MZ (can be changed) # Note that the weights will therefore differ from "1" # if the powers are not zero. set MPreWeight:HTPower 0 set MPreWeight:MaxPTPower 0 set MPreWeight:OnlyColoured No # The next line can switch of hadronization # and MPI modelling. Use with care!! # read Matchbox/PQCDLevel.in ## Special settings required for on-shell production of unstable particles ## enable for on-shell top production # read Matchbox/OnShellTopProduction.in ## enable for on-shell W, Z or h production # read Matchbox/OnShellWProduction.in # read Matchbox/OnShellZProduction.in # read Matchbox/OnShellHProduction.in # Special settings for the VBF approximation # read Matchbox/VBFDiagramsOnly.in ################################################## ## Matrix element library selection ################################################## ## Select a generic tree/loop combination or a ## specialized NLO package # read Matchbox/MadGraph-GoSam.in # read Matchbox/MadGraph-MadGraph.in # read Matchbox/MadGraph-NJet.in # read Matchbox/MadGraph-OpenLoops.in # read Matchbox/HJets.in # read Matchbox/VBFNLO.in ## Uncomment this to use ggh effective couplings ## currently only supported by MadGraph-GoSam and ## MadGraph-Openloops # read Matchbox/HiggsEffective.in ################################################## ## Cut selection ## See the documentation for more options ################################################## cd /Herwig/Cuts/ set ChargedLeptonPairMassCut:MinMass 60*GeV set ChargedLeptonPairMassCut:MaxMass 120*GeV cd /Herwig/MatrixElements/Matchbox/Utility insert DiagramGenerator:ExcludeInternal 0 /Herwig/Particles/gamma ## cuts on additional jets cd /Herwig/Cuts/ # read Matchbox/DefaultPPJets.in # insert JetCuts:JetRegions 0 FirstJet # insert JetCuts:JetRegions 1 SecondJet # insert JetCuts:JetRegions 2 ThirdJet # insert JetCuts:JetRegions 3 FourthJet ################################################## ## Scale choice ## See the documentation for more options ################################################## cd /Herwig/MatrixElements/Matchbox/Scales/ set /Herwig/Merging/MergingFactory:ScaleChoice LeptonPairMassScale ################################################## ## Scale uncertainties ################################################## # read Matchbox/MuDown.in # read Matchbox/MuUp.in ################################################## ## Shower scale uncertainties ################################################## # read Matchbox/MuQDown.in # read Matchbox/MuQUp.in ################################################## ## CMW - Scheme ################################################## -read Merging/Merging-Dipole-FactorCMWSchemeTune.in +read snippets/Dipole_AutoTune_prel.in ### Use factor in alpha_s argument: alpha_s(q) -> alpha_s(fac*q) ### with fac=exp(-(67-3pi^2-10/3*Nf)/(33-2Nf)) read Merging/FactorCMWScheme.in ### Linear CMW multiplication: ### alpha_s(q) -> alpha_s(q)(1+K_g*alpha_s(q)/2pi ) # read Merging/LinearCMWScheme.in ################################################## ## PDF choice ################################################## read Matchbox/FiveFlavourNoBMassScheme.in read Matchbox/MMHT2014.in ################################################## ## Analyses ################################################## cd /Herwig/Analysis ## Write HepMC events. Modify the PrintEvent interface for your needs. # insert /Herwig/Generators/EventGenerator:AnalysisHandlers 0 HepMCFile ## Setup the Rivet analysis: #read snippets/Rivet.in #insert Rivet:Analyses 0 XXX_2017_ABC123 ## Here we collected a various Rivet analysis for Zs at LHC ## at the 8 TeV. (The collection might not be complete.) # read Merging/LHC7-Z-Analysis.in ################################################## ## Save the generator ################################################## do /Herwig/Merging/MergingFactory:ProductionMode set /Herwig/Generators/EventGenerator:IntermediateOutput Yes cd /Herwig/Generators saverun LHC-Z-Merging EventGenerator diff --git a/src/defaults/Cuts.in b/src/defaults/Cuts.in --- a/src/defaults/Cuts.in +++ b/src/defaults/Cuts.in @@ -1,113 +1,118 @@ # -*- ThePEG-repository -*- ########################################################### # Default cuts (applied to the hard subprocess) # # Don't change values here, re-set them in your own input # files using these as examples. ########################################################### mkdir /Herwig/Matchers cd /Herwig/Matchers create ThePEG::Matcher Lepton create ThePEG::Matcher Neutrino create ThePEG::Matcher ChargedLepton create ThePEG::Matcher LightQuark +create ThePEG::Matcher LightParticle create ThePEG::Matcher LightAntiQuark create ThePEG::Matcher StandardQCDParton create ThePEG::Matcher Photon create ThePEG::Matcher Top create ThePEG::Matcher Bottom create ThePEG::Matcher WBoson create ThePEG::Matcher ZBoson create ThePEG::Matcher HiggsBoson mkdir /Herwig/Cuts cd /Herwig/Cuts # cut on jet pt create ThePEG::SimpleKTCut JetKtCut SimpleKTCut.so newdef JetKtCut:Matcher /Herwig/Matchers/StandardQCDParton newdef JetKtCut:MinKT 20.0*GeV # cut on photon create ThePEG::SimpleKTCut PhotonKtCut SimpleKTCut.so newdef PhotonKtCut:Matcher /Herwig/Matchers/Photon newdef PhotonKtCut:MinKT 20.0*GeV newdef PhotonKtCut:MinEta -3. newdef PhotonKtCut:MaxEta 3. # cut on leptons create ThePEG::SimpleKTCut LeptonKtCut SimpleKTCut.so newdef LeptonKtCut:Matcher /Herwig/Matchers/Lepton newdef LeptonKtCut:MinKT 0.0*GeV # cut on charged leptons create ThePEG::SimpleKTCut ChargedLeptonKtCut SimpleKTCut.so newdef ChargedLeptonKtCut:Matcher /Herwig/Matchers/ChargedLepton newdef ChargedLeptonKtCut:MinKT 0.0*GeV # cut on top quarks create ThePEG::KTRapidityCut TopKtCut KTRapidityCut.so newdef TopKtCut:Matcher /Herwig/Matchers/Top newdef TopKtCut:MinKT 0.0*GeV # cut on W bosons create ThePEG::KTRapidityCut WBosonKtCut KTRapidityCut.so newdef WBosonKtCut:Matcher /Herwig/Matchers/WBoson newdef WBosonKtCut:MinKT 0.0*GeV # cut on Z bosons create ThePEG::KTRapidityCut ZBosonKtCut KTRapidityCut.so newdef ZBosonKtCut:Matcher /Herwig/Matchers/ZBoson newdef ZBosonKtCut:MinKT 0.0*GeV # cut on Higgs bosons create ThePEG::KTRapidityCut HiggsBosonKtCut KTRapidityCut.so newdef HiggsBosonKtCut:Matcher /Herwig/Matchers/HiggsBoson newdef HiggsBosonKtCut:MinKT 0.0*GeV +# cut on Higgs bosons +create ThePEG::KTRapidityCut LightParticleKtCut KTRapidityCut.so +newdef LightParticleKtCut:Matcher /Herwig/Matchers/LightParticle +newdef LightParticleKtCut:MinKT 0.0*GeV # create a cut on the invariant mass of lepton pairs create ThePEG::V2LeptonsCut MassCut V2LeptonsCut.so newdef MassCut:Families All newdef MassCut:CComb All newdef MassCut:MinM 20.*GeV newdef MassCut:MaxM 14000.*GeV # create a cut on Q^2 for neutral current DIS create ThePEG::SimpleDISCut NeutralCurrentCut SimpleDISCut.so newdef NeutralCurrentCut:MinQ2 20. newdef NeutralCurrentCut:Current Neutral # create a cut on Q^2 for charged current DIS create ThePEG::SimpleDISCut ChargedCurrentCut SimpleDISCut.so newdef ChargedCurrentCut:MinQ2 20. newdef ChargedCurrentCut:Current Charged # create a cut of Q^2 for charged current DIS # Default Cuts object create ThePEG::Cuts Cuts newdef /Herwig/Generators/EventGenerator:EventHandler:Cuts /Herwig/Cuts/Cuts newdef Cuts:MHatMin 20.*GeV # insert into hadron cuts (by defaults) insert Cuts:OneCuts[0] JetKtCut insert Cuts:OneCuts[1] PhotonKtCut insert Cuts:OneCuts[2] LeptonKtCut insert Cuts:OneCuts[3] TopKtCut insert Cuts:OneCuts[4] WBosonKtCut insert Cuts:OneCuts[5] ZBosonKtCut insert Cuts:OneCuts[6] HiggsBosonKtCut insert Cuts:OneCuts[7] ChargedLeptonKtCut insert Cuts:MultiCuts[0] MassCut # create diffrent cuts object for MinBias to avoid numerical problems create ThePEG::Cuts MinBiasCuts newdef MinBiasCuts:ScaleMin 2.0*GeV2 newdef MinBiasCuts:X1Min 0.055 newdef MinBiasCuts:X2Min 0.055 newdef MinBiasCuts:MHatMin 0.0*GeV diff --git a/src/defaults/PDF.in.in b/src/defaults/PDF.in.in --- a/src/defaults/PDF.in.in +++ b/src/defaults/PDF.in.in @@ -1,73 +1,77 @@ # -*- ThePEG-repository -*- # PDF.in. Generated from PDF.in.in by Makefile.am ##################################### # Default PDF set ##################################### # Handle leptons create ThePEG::LeptonLeptonPDF LeptonPDF LeptonLeptonPDF.so newdef LeptonPDF:RemnantHandler LeptonRemnants newdef /Herwig/Particles/e-:PDF LeptonPDF newdef /Herwig/Particles/e+:PDF LeptonPDF # Handle hadrons # NEW DEFAULT for Hw 7 library ThePEGLHAPDF.so create ThePEG::LHAPDF HardLOPDF newdef HardLOPDF:RemnantHandler HadronRemnants create ThePEG::LHAPDF HardNLOPDF newdef HardNLOPDF:RemnantHandler HadronRemnants create ThePEG::LHAPDF ShowerLOPDF newdef ShowerLOPDF:RemnantHandler HadronRemnants create ThePEG::LHAPDF ShowerNLOPDF newdef ShowerNLOPDF:RemnantHandler HadronRemnants create ThePEG::LHAPDF MPIPDF newdef MPIPDF:RemnantHandler HadronRemnants create ThePEG::LHAPDF RemnantPDF newdef RemnantPDF:RemnantHandler HadronRemnants newdef HardLOPDF:PDFName MMHT2014lo68cl newdef HardNLOPDF:PDFName MMHT2014nlo68cl newdef ShowerLOPDF:PDFName MMHT2014lo68cl newdef ShowerNLOPDF:PDFName MMHT2014nlo68cl newdef MPIPDF:PDFName MMHT2014lo68cl newdef RemnantPDF:PDFName MMHT2014lo68cl # set LO PDFS for hard process and can be changed later newdef /Herwig/Particles/p+:PDF HardLOPDF newdef /Herwig/Particles/pbar-:PDF HardLOPDF # photons from leptons in WW approx create ThePEG::WeizsackerWilliamsPDF WWPDF WeizsackerWilliamsPDF.so create ThePEG::UnResolvedRemnant /Herwig/Partons/LeptonGammaRemnants newdef /Herwig/Partons/WWPDF:RemnantHandler /Herwig/Partons/LeptonGammaRemnants # photons from protons in Budnev approx create ThePEG::BudnevPDF BudnevPDF BudnevPDF.so create ThePEG::UnResolvedRemnant /Herwig/Partons/HadronGammaRemnants newdef /Herwig/Partons/BudnevPDF:RemnantHandler /Herwig/Partons/HadronGammaRemnants +# partons inside photons +create Herwig::SaSPhotonPDF /Herwig/Partons/SaSPDF HwSaSPhotonPDF.so +set /Herwig/Partons/SaSPDF:RemnantHandler /Herwig/Partons/HadronRemnants + # pomerons create Herwig::PomeronFlux PomeronFlux HwPomeronFlux.so newdef PomeronFlux:PDFFit Pomeron2006A newdef PomeronFlux:Q2Max 1. newdef PomeronFlux:Q2Min 1.0e-6 create ThePEG::UnResolvedRemnant /Herwig/Partons/ProtonRemnant UnResolvedRemnant.so newdef /Herwig/Partons/PomeronFlux:RemnantHandler /Herwig/Partons/ProtonRemnant create Herwig::PomeronPDF PomeronPDF HwPomeronPDF.so newdef PomeronPDF:RemnantHandler HadronRemnants newdef PomeronPDF:RootName @HERWIG_PDF_POMERON@ newdef /Herwig/Particles/pomeron:PDF PomeronPDF newdef PomeronPDF:PDFFit 2006A diff --git a/src/snippets/BaryonicReconnection.in b/src/snippets/BaryonicReconnection.in new file mode 100644 --- /dev/null +++ b/src/snippets/BaryonicReconnection.in @@ -0,0 +1,17 @@ +# Set strange quark mass to 0.45 in order to allow alternative gluon splitting +set /Herwig/Particles/s:ConstituentMass 0.45*GeV +set /Herwig/Particles/sbar:ConstituentMass 0.45*GeV + +# Use Baryonic Colour Reconnection Model +set /Herwig/Hadronization/ColourReconnector:Algorithm BaryonicReco + +# Allow alternative gluon splitting +set /Herwig/Hadronization/PartonSplitter:Split uds + +# Parameters for the Baryonic Reconnection Model +set /Herwig/Hadronization/ColourReconnector:ReconnectionProbability 0.772606 +set /Herwig/Hadronization/ColourReconnector:ReconnectionProbabilityBaryonic 0.477612 +set /Herwig/UnderlyingEvent/MPIHandler:pTmin0 3.053252 +set /Herwig/UnderlyingEvent/MPIHandler:InvRadius 1.282032 +set /Herwig/Hadronization/HadronSelector:PwtSquark 0.291717 +set /Herwig/Hadronization/PartonSplitter:SplitPwtSquark 0.824135 diff --git a/src/snippets/DipoleMerging.in b/src/snippets/DipoleMerging.in --- a/src/snippets/DipoleMerging.in +++ b/src/snippets/DipoleMerging.in @@ -1,113 +1,102 @@ # -*- ThePEG-repository -*- cd /Herwig/Cuts # Set up cuts for Merging set Cuts:Fuzzy FuzzyTheta clear Cuts:OneCuts insert Cuts:OneCuts[0] PhotonCut insert Cuts:OneCuts[1] LeptonCut insert Cuts:OneCuts[2] TopQuarkCut insert Cuts:OneCuts[3] BottomQuarkCut insert Cuts:OneCuts[4] WBosonCut insert Cuts:OneCuts[5] ZBosonCut insert Cuts:OneCuts[6] HiggsBosonCut insert Cuts:OneCuts[7] ChargedLeptonCut clear Cuts:TwoCuts insert Cuts:TwoCuts[0] LeptonPairMassCut insert Cuts:TwoCuts[1] ChargedLeptonPairMassCut insert Cuts:TwoCuts[2] LeptonDeltaRCut insert Cuts:TwoCuts[3] ChargedLeptonDeltaRCut clear Cuts:MultiCuts insert Cuts:MultiCuts[0] PhotonIsolationCut insert Cuts:MultiCuts[1] MissingPtCut set Cuts:MHatMin 0.0*GeV set JetKtCut:MinKT 0.0*GeV # Set up the alphas for merging set /Herwig/Model:QCD/RunningAlphaS /Herwig/Couplings/NLOAlphaS set /Herwig/DipoleShower/DipoleShowerHandler:GlobalAlphaS /Herwig/Couplings/NLOAlphaS set /Herwig/Generators/EventGenerator:StandardModelParameters:QCD/RunningAlphaS /Herwig/Couplings/NLOAlphaS cd /Herwig/Merging set MergingFactory:Cuts /Herwig/Cuts/Cuts set MergingFactory:MergingHelper Merger set MergingFactory:CascadeHandler /Herwig/DipoleShower/DipoleShowerHandler cd /Herwig/Generators set EventGenerator:EventHandler:CascadeHandler /Herwig/DipoleShower/DipoleShowerHandler set /Herwig/DipoleShower/DipoleShowerHandler:MaxPtIsMuF Yes cd /Herwig/EventHandlers set EventHandler:Sampler /Herwig/Samplers/Sampler set EventHandler:Weighted No set EventHandler:CollisionCuts No set EventHandler:SubProcessHandlers[0] /Herwig/Merging/MergingFactory cd /Herwig/Particles set d:NominalMass 0*GeV set dbar:NominalMass 0*GeV set u:NominalMass 0*GeV set ubar:NominalMass 0*GeV set s:NominalMass 0*GeV set sbar:NominalMass 0*GeV set c:NominalMass 0*GeV set cbar:NominalMass 0*GeV #set b:HardProcessMass 0*GeV #set bbar:HardProcessMass 0*GeV set e+:HardProcessMass 0*GeV set e-:HardProcessMass 0*GeV set mu+:HardProcessMass 0*GeV set mu-:HardProcessMass 0*GeV set nu_e:HardProcessMass 0*GeV set nu_ebar:HardProcessMass 0*GeV set nu_mu:HardProcessMass 0*GeV set nu_mubar:HardProcessMass 0*GeV set nu_tau:HardProcessMass 0*GeV set nu_taubar:HardProcessMass 0*GeV cd /Herwig/Partons set /Herwig/Particles/p+:PDF HardNLOPDF set /Herwig/Particles/pbar-:PDF HardNLOPDF set /Herwig/Partons/PPExtractor:FirstPDF HardNLOPDF set /Herwig/Partons/PPExtractor:SecondPDF HardNLOPDF set /Herwig/Partons/EPExtractor:SecondPDF HardNLOPDF set /Herwig/Shower/ShowerHandler:PDFA ShowerNLOPDF set /Herwig/Shower/ShowerHandler:PDFB ShowerNLOPDF set /Herwig/DipoleShower/DipoleShowerHandler:PDFA ShowerNLOPDF set /Herwig/DipoleShower/DipoleShowerHandler:PDFB ShowerNLOPDF -### Don't apply restrictions on the z-boundaries while clustering. -set /Herwig/Merging/Merger:OpenZBoundaries DipoleScale - -cd /Herwig/DipoleShower/Kinematics -set IFLightKinematics:OpenZBoundaries Hard -set IILightKinematics:OpenZBoundaries Hard -set FFLightKinematics:OpenZBoundaries Hard -set FILightKinematics:OpenZBoundaries Hard -set FIMassiveKinematics:OpenZBoundaries Hard -set IFMassiveKinematics:OpenZBoundaries Hard -set FFMassiveKinematics:OpenZBoundaries Hard # Switch of the profiles of the Shower set /Herwig/DipoleShower/DipoleShowerHandler:HardScaleProfile NULL cd /Herwig/Merging # Currently we do not splitt the hard process for merged processes. set /Herwig/DipoleShower/DipoleShowerHandler:SplitHardProcess No diff --git a/src/snippets/Dipole_AutoTune_prel.in b/src/snippets/Dipole_AutoTune_prel.in new file mode 100644 --- /dev/null +++ b/src/snippets/Dipole_AutoTune_prel.in @@ -0,0 +1,139 @@ +# This is a preliminary Tune. +# With this version (7.1.3) various changes to the dipole shower are done. +# The dipole shower will be retuned for version 7.1.4. + +# Note: The gluon ConstituentMass is lower than the strange quark +# threshold assumed in the BaryonicReconnection. +# Using both snippets will produce no resonable results. + +set /Herwig/DipoleShower/NLOAlphaS:input_alpha_s 0.118 +set /Herwig/DipoleShower/NLOAlphaS:input_scale 91.18*GeV +set /Herwig/Couplings/NLOAlphaS:input_alpha_s 0.118 +set /Herwig/Couplings/NLOAlphaS:input_scale 91.18*GeV + +set /Herwig/DipoleShower/Kinematics/FFMassiveKinematics:IRCutoff 0.80399886545 +set /Herwig/DipoleShower/Kinematics/FFLightKinematics:IRCutoff 0.80399886545 +set /Herwig/DipoleShower/Kinematics/FIMassiveKinematics:IRCutoff 0.80399886545 +set /Herwig/DipoleShower/Kinematics/FILightKinematics:IRCutoff 0.80399886545 +set /Herwig/DipoleShower/Kinematics/IFMassiveKinematics:IRCutoff 0.80399886545 +set /Herwig/DipoleShower/Kinematics/IFLightKinematics:IRCutoff 0.80399886545 +set /Herwig/DipoleShower/Kinematics/IILightKinematics:IRCutoff 0.80399886545 + +set /Herwig/Particles/g:ConstituentMass 0.762996296601 + +set /Herwig/Hadronization/ClusterDecayer:ClSmrLight 0.342544255421 +set /Herwig/Hadronization/ClusterDecayer:ClSmrCharm 0.237545842862 +set /Herwig/Hadronization/ClusterDecayer:ClSmrBottom 0.0620545338048 + +set /Herwig/Hadronization/ClusterFissioner:ClPowLight 0.950949552153 +set /Herwig/Hadronization/ClusterFissioner:ClPowCharm 0.725163909065 +set /Herwig/Hadronization/ClusterFissioner:ClPowBottom 0.809774254452 + +set /Herwig/Hadronization/ClusterFissioner:ClMaxLight 2.80478186219 +set /Herwig/Hadronization/ClusterFissioner:ClMaxCharm 3.13483791689 +set /Herwig/Hadronization/ClusterFissioner:ClMaxBottom 5.79181302131 + +set /Herwig/Hadronization/ClusterFissioner:PSplitLight 0.995391682928 +set /Herwig/Hadronization/ClusterFissioner:PSplitCharm 0.769749617516 +set /Herwig/Hadronization/ClusterFissioner:PSplitBottom 0.479199412481 + +set /Herwig/Hadronization/HadronSelector:SingleHadronLimitCharm 0.0485533655422 +set /Herwig/Hadronization/HadronSelector:SingleHadronLimitBottom 0.0968582906399 + +set /Herwig/Hadronization/HadronSelector:PwtUquark 0.718641969264 +set /Herwig/Hadronization/HadronSelector:PwtDquark 0.674967529289 +set /Herwig/Hadronization/HadronSelector:PwtSquark 0.542042947191 +set /Herwig/Hadronization/HadronSelector:PwtCquark 0.251544496683 +set /Herwig/Hadronization/HadronSelector:PwtBquark 0.426714635544 +set /Herwig/Hadronization/HadronSelector:PwtDIquark 0.296781084091 +set /Herwig/Hadronization/HadronSelector:SngWt 0.541287379336 +set /Herwig/Hadronization/HadronSelector:DecWt 0.569933528697 + +set /Herwig/Particles/b:NominalMass 5.38329996032 +set /Herwig/Particles/b:ConstituentMass 4.84231667563 + +####### +# CMW scheme: +# Tune was done with CMW for all kernels, as merging currently only is consistent if applied to all. +####### + + +cd /Herwig/DipoleShower/Kernels +set FFgx2ggxDipoleKernel:CMWScheme Factor +set FFqx2qgxDipoleKernel:CMWScheme Factor +set FFgx2ddxDipoleKernel:CMWScheme Factor +set FFgx2uuxDipoleKernel:CMWScheme Factor +set FFgx2ccxDipoleKernel:CMWScheme Factor +set FFgx2ssxDipoleKernel:CMWScheme Factor +set FFgx2bbxDipoleKernel:CMWScheme Factor +set FFMgx2ggxDipoleKernel:CMWScheme Factor +set FFMdx2dgxDipoleKernel:CMWScheme Factor +set FFMux2ugxDipoleKernel:CMWScheme Factor +set FFMcx2cgxDipoleKernel:CMWScheme Factor +set FFMsx2sgxDipoleKernel:CMWScheme Factor +set FFMbx2bgxDipoleKernel:CMWScheme Factor +set FFMtx2tgxDipoleKernel:CMWScheme Factor +set FFMgx2ddxDipoleKernel:CMWScheme Factor +set FFMgx2uuxDipoleKernel:CMWScheme Factor +set FFMgx2ccxDipoleKernel:CMWScheme Factor +set FFMgx2ssxDipoleKernel:CMWScheme Factor +set FFMgx2bbxDipoleKernel:CMWScheme Factor +set FIgx2ggxDipoleKernel:CMWScheme Factor +set FIqx2qgxDipoleKernel:CMWScheme Factor +set FIgx2ddxDipoleKernel:CMWScheme Factor +set FIgx2uuxDipoleKernel:CMWScheme Factor +set FIgx2ccxDipoleKernel:CMWScheme Factor +set FIgx2ssxDipoleKernel:CMWScheme Factor +set FIgx2bbxDipoleKernel:CMWScheme Factor +set FIMdx2dgxDipoleKernel:CMWScheme Factor +set FIMux2ugxDipoleKernel:CMWScheme Factor +set FIMcx2cgxDipoleKernel:CMWScheme Factor +set FIMsx2sgxDipoleKernel:CMWScheme Factor +set FIMbx2bgxDipoleKernel:CMWScheme Factor +set FIMtx2tgxDipoleKernel:CMWScheme Factor +set FIMgx2ddxDipoleKernel:CMWScheme Factor +set FIMgx2uuxDipoleKernel:CMWScheme Factor +set FIMgx2ccxDipoleKernel:CMWScheme Factor +set FIMgx2ssxDipoleKernel:CMWScheme Factor +set FIMgx2bbxDipoleKernel:CMWScheme Factor +#set FIMgx2ttxDipoleKernel:CMWScheme Factor +set IFgx2ggxDipoleKernel:CMWScheme Factor +set IFqx2qgxDipoleKernel:CMWScheme Factor +set IFqx2gqxDipoleKernel:CMWScheme Factor +set IFgx2ddbarxDipoleKernel:CMWScheme Factor +set IFgx2dbardxDipoleKernel:CMWScheme Factor +set IFgx2uubarxDipoleKernel:CMWScheme Factor +set IFgx2ubaruxDipoleKernel:CMWScheme Factor +set IFgx2ccbarxDipoleKernel:CMWScheme Factor +set IFgx2cbarcxDipoleKernel:CMWScheme Factor +set IFgx2ssbarxDipoleKernel:CMWScheme Factor +set IFgx2sbarsxDipoleKernel:CMWScheme Factor +set IFMgx2ggxDipoleKernel:CMWScheme Factor +set IFMqx2qgxDipoleKernel:CMWScheme Factor +set IFMqx2gqxDipoleKernel:CMWScheme Factor +set IFMgx2ddbarxDipoleKernel:CMWScheme Factor +set IFMgx2dbardxDipoleKernel:CMWScheme Factor +set IFMgx2uubarxDipoleKernel:CMWScheme Factor +set IFMgx2ubaruxDipoleKernel:CMWScheme Factor +set IFMgx2ccbarxDipoleKernel:CMWScheme Factor +set IFMgx2cbarcxDipoleKernel:CMWScheme Factor +set IFMgx2ssbarxDipoleKernel:CMWScheme Factor +set IFMgx2sbarsxDipoleKernel:CMWScheme Factor +set IIgx2ggxDipoleKernel:CMWScheme Factor +set IIqx2qgxDipoleKernel:CMWScheme Factor +set IIqx2gqxDipoleKernel:CMWScheme Factor +set IIgx2ddbarxDipoleKernel:CMWScheme Factor +set IIgx2dbardxDipoleKernel:CMWScheme Factor +set IIgx2uubarxDipoleKernel:CMWScheme Factor +set IIgx2ubaruxDipoleKernel:CMWScheme Factor +set IIgx2ccbarxDipoleKernel:CMWScheme Factor +set IIgx2cbarcxDipoleKernel:CMWScheme Factor +set IIgx2ssbarxDipoleKernel:CMWScheme Factor +set IIgx2sbarsxDipoleKernel:CMWScheme Factor +set IFgx2bbbarxDipoleKernel:CMWScheme Factor +set IFgx2bbarbxDipoleKernel:CMWScheme Factor +set IFMgx2bbbarxDipoleKernel:CMWScheme Factor +set IFMgx2bbarbxDipoleKernel:CMWScheme Factor +set IIgx2bbbarxDipoleKernel:CMWScheme Factor +set IIgx2bbarbxDipoleKernel:CMWScheme Factor + diff --git a/src/snippets/Makefile.am b/src/snippets/Makefile.am --- a/src/snippets/Makefile.am +++ b/src/snippets/Makefile.am @@ -1,40 +1,41 @@ BUILT_SOURCES = done-all-links snippetsdir = ${pkgdatadir}/snippets INPUTFILES = \ CellGridSampler.in \ Diffraction.in \ DipoleMerging.in \ DipoleShowerFiveFlavours.in \ DipoleShowerFourFlavours.in \ EECollider.in \ EPCollider.in \ HepMCFixedOrder.in \ HepMC.in \ Matchbox.in \ MB-DipoleShower.in \ MB.in \ MonacoSampler.in \ Particles-SetLonglivedParticlesStable.in \ PDF-CT10.in \ PDF-NNPDF30NLO.in \ PPCollider.in \ RivetFixedOrder.in \ Rivet.in \ SoftModel.in \ SoftTune.in \ +YFS.in \ +BaryonicReconnection.in \ CMWinQtiledShower.in \ -YFS.in - +Dipole_AutoTune_prel.in dist_snippets_DATA = $(INPUTFILES) CLEANFILES = done-all-links done-all-links: $(INPUTFILES) @echo "Linking input files" @for i in $(INPUTFILES); do \ if test -f $(srcdir)/$$i -a ! -e $$i; then \ $(LN_S) -f $(srcdir)/$$i; fi; done @touch done-all-links diff --git a/src/snippets/Matchbox.in b/src/snippets/Matchbox.in --- a/src/snippets/Matchbox.in +++ b/src/snippets/Matchbox.in @@ -1,76 +1,79 @@ # -*- ThePEG-repository -*- cd /Herwig/Cuts set Cuts:Fuzzy FuzzyTheta clear Cuts:OneCuts insert Cuts:OneCuts[0] PhotonCut insert Cuts:OneCuts[1] LeptonCut insert Cuts:OneCuts[2] TopQuarkCut insert Cuts:OneCuts[3] BottomQuarkCut insert Cuts:OneCuts[4] WBosonCut insert Cuts:OneCuts[5] ZBosonCut insert Cuts:OneCuts[6] HiggsBosonCut insert Cuts:OneCuts[7] ChargedLeptonCut clear Cuts:TwoCuts insert Cuts:TwoCuts[0] LeptonPairMassCut insert Cuts:TwoCuts[1] ChargedLeptonPairMassCut insert Cuts:TwoCuts[2] LeptonDeltaRCut insert Cuts:TwoCuts[3] ChargedLeptonDeltaRCut clear Cuts:MultiCuts insert Cuts:MultiCuts[0] PhotonIsolationCut insert Cuts:MultiCuts[1] MissingPtCut set Cuts:MHatMin 0.0*GeV cd /Herwig/MatrixElements/Matchbox set Factory:Cuts /Herwig/Cuts/Cuts cd /Herwig/EventHandlers set EventHandler:Sampler /Herwig/Samplers/Sampler set EventHandler:Weighted No set EventHandler:CollisionCuts No set EventHandler:SubProcessHandlers[0] /Herwig/MatrixElements/Matchbox/Factory cd /Herwig/Particles set d:NominalMass 0*GeV set dbar:NominalMass 0*GeV set u:NominalMass 0*GeV set ubar:NominalMass 0*GeV set s:NominalMass 0*GeV set sbar:NominalMass 0*GeV set c:HardProcessMass 0*GeV set cbar:HardProcessMass 0*GeV set b:HardProcessMass 0*GeV set bbar:HardProcessMass 0*GeV set e+:HardProcessMass 0*GeV set e-:HardProcessMass 0*GeV set mu+:HardProcessMass 0*GeV set mu-:HardProcessMass 0*GeV set nu_e:HardProcessMass 0*GeV set nu_ebar:HardProcessMass 0*GeV set nu_mu:HardProcessMass 0*GeV set nu_mubar:HardProcessMass 0*GeV set nu_tau:HardProcessMass 0*GeV set nu_taubar:HardProcessMass 0*GeV cd /Herwig/Partons set /Herwig/Particles/p+:PDF HardNLOPDF set /Herwig/Particles/pbar-:PDF HardNLOPDF set /Herwig/Partons/PPExtractor:FirstPDF HardNLOPDF set /Herwig/Partons/PPExtractor:SecondPDF HardNLOPDF set /Herwig/Partons/EPExtractor:SecondPDF HardNLOPDF set /Herwig/Shower/ShowerHandler:PDFA ShowerNLOPDF set /Herwig/Shower/ShowerHandler:PDFB ShowerNLOPDF set /Herwig/DipoleShower/DipoleShowerHandler:PDFA ShowerNLOPDF set /Herwig/DipoleShower/DipoleShowerHandler:PDFB ShowerNLOPDF set /Herwig/Generators/EventGenerator:StandardModelParameters:QCD/RunningAlphaS /Herwig/Couplings/NLOAlphaS + +set /Herwig/Shower/ShowerHandler:SplitHardProcess No +set /Herwig/DipoleShower/DipoleShowerHandler:SplitHardProcess No diff --git a/src/snippets/RivetFixedOrder.in b/src/snippets/RivetFixedOrder.in --- a/src/snippets/RivetFixedOrder.in +++ b/src/snippets/RivetFixedOrder.in @@ -1,7 +1,7 @@ ## snippet to set up a rivet analysis hook ## this snippet is for fixed order ie NO shower create ThePEG::NLORivetAnalysis /Herwig/Analysis/RivetFixedOrder RivetAnalysis.so -insert /Herwig/Generators/EventGenerator:AnalysisHandlers 0 /Herwig/Analysis/RivetFixexOrder +insert /Herwig/Generators/EventGenerator:AnalysisHandlers 0 /Herwig/Analysis/RivetFixedOrder