8 #include "Pythia8/PartonVertex.h"
20 void PartonVertex::init() {
22 doVertex = flag(
"PartonVertex:setVertex");
23 modeVertex = mode(
"PartonVertex:modeVertex");
24 epsPhi = parm(
"PartonVertex:phiAsym");
25 epsRat = sqrt( (1. + epsPhi) / (1. - epsPhi) );
26 rProton = parm(
"PartonVertex:ProtonRadius");
27 rProton2 = rProton * rProton;
28 pTmin = parm(
"PartonVertex:pTmin");
29 widthEmission = parm(
"PartonVertex:EmissionWidth");
37 void PartonVertex::vertexBeam(
int iBeam, vector<int>& iRemn,
38 vector<int>& iInit,
Event& event) {
41 double xBeam = (iBeam == 0) ? bHalf : -bHalf;
42 Vec4 vBeam( xBeam, 0., 0., 0.);
43 event[iBeam + 1].vProd( FM2MM * vBeam );
50 double x, y, r, phi, sthe, xSgn, xWt;
51 pair<double,double> xy;
54 for (
int i = 0; i < int(iRemn.size()); ++i) {
58 r = rProton * pow(rndmPtr->flat(), 1./3.);
59 phi = 2. * M_PI * rndmPtr->flat();
60 sthe = sqrtpos( 1. - pow2(2. * rndmPtr->flat() - 1.) );
61 x = r * sthe * cos(phi);
62 y = r * sthe * sin(phi);
66 xy = rndmPtr->gauss2();
67 x = xy.first * rProton / sqrt(3.);
68 y = xy.second * rProton / sqrt(3.);
72 vNow.push_back( Vec4( x, y, 0., 0.) );
73 vSum +=
event[iRemn[i]].e() * vNow[i];
74 xSgn = (iBeam == 0) ? x : -x;
75 xWt = 1. / ( 1. + (bNow / rProton) * exp(xSgn / rProton) );
76 wtNow.push_back( xWt );
77 wtSum +=
event[iRemn[i]].e() * xWt;
81 for (
int i = 0; i < int(iInit.size()); ++i)
82 vSum += event[iInit[i]].e() * (MM2FM *
event[iInit[i]].vProd() - vBeam);
87 for (
int i = 0; i < int(iRemn.size()); ++i) {
88 vShift = vSum * wtNow[i] / wtSum;
89 if (vShift.pT2() > rProton2) vShift *= rProton / vShift.pT();
90 event[iRemn[i]].vProd( FM2MM * (vNow[i] - vShift + vBeam) );
99 void PartonVertex::vertexMPI(
int iBeg,
int nAdd,
double bNowIn,
103 bNow = bNowIn * rProton;
105 if (modeVertex < 2) {
106 if (bHalf > 0.95 * rProton) {
107 infoPtr->errorMsg(
"Warning in PartonVertex::vertexMPI: large b value");
108 bHalf = 0.95 * rProton;
110 xMax = rProton - bHalf;
111 yMax = sqrt( rProton2 - bHalf * bHalf);
112 zWtMax = yMax * yMax;
118 if (modeVertex < 2) {
121 x = (2. * rndmPtr->flat() - 1.) * xMax;
122 y = (2. * rndmPtr->flat() - 1.) * yMax;
123 double rA2 = pow2(x - bHalf) + y * y;
124 double rB2 = pow2(x + bHalf) + y * y;
125 if ( max( rA2, rB2) < rProton2 ) accept =
true;
126 if (accept && sqrtpos(rProton2 - rA2) * sqrtpos(rProton2 - rB2)
127 < rndmPtr->flat() * zWtMax) accept =
false;
134 pair<double,double> xy = rndmPtr->gauss2();
135 x = xy.first * rProton / sqrt(6.);
136 y = xy.second * rProton / sqrt(6.);
137 if (modeVertex == 2) accept =
true;
139 else if (modeVertex == 3) { x *= epsRat; y /= epsRat; accept =
true;}
141 else if ( 1. + epsPhi * (x*x - y*y)/(x*x + y*y)
142 > rndmPtr->flat() * (1. + abs(epsPhi)) ) accept =
true;
147 for (
int iNow = iBeg; iNow < iBeg + nAdd; ++iNow)
148 event[iNow].vProd( x * FM2MM, y * FM2MM, 0., 0.);
156 void PartonVertex::vertexFSR(
int iNow,
Event& event) {
159 int iMo =
event[iNow].mother1();
160 Vec4 vStart =
event[iNow].hasVertex() ?
event[iNow].vProd()
161 :
event[iMo].vProd();
164 double pT = max( event[iNow].pT(), pTmin);
165 pair<double, double> xy = rndmPtr->gauss2();
166 Vec4 vSmear = (widthEmission / pT) * Vec4( xy.first, xy.second, 0., 0.);
167 event[iNow].vProd( vStart + vSmear * FM2MM);
175 void PartonVertex::vertexISR(
int iNow,
Event& event) {
178 int iMoDa =
event[iNow].mother1();
179 if (iMoDa == 0) iMoDa =
event[iNow].daughter1();
180 Vec4 vStart =
event[iNow].vProd();
181 if (!event[iNow].hasVertex() && iMoDa != 0) vStart =
event[iMoDa].vProd();
184 double pT = max( event[iNow].pT(), pTmin);
185 pair<double, double> xy = rndmPtr->gauss2();
186 Vec4 vSmear = (widthEmission / pT) * Vec4( xy.first, xy.second, 0., 0.);
187 event[iNow].vProd( vStart + vSmear * FM2MM);
196 void PartonVertex::vertexHadrons(
int nBefFrag,
Event& event) {
199 int iFirst =
event[nBefFrag].mother1();
200 int iLast =
event[nBefFrag].mother2();
202 for (
int i = iFirst; i <= iLast; ++i)
203 if (!event[i].isGluon()) iNotG.push_back(i);
204 if ( iNotG.size() == 2 &&
event[iFirst].col() *
event[iLast].col() == 0
205 &&
event[iFirst].acol() *
event[iLast].acol() == 0) {
206 }
else if (iNotG.size() == 0 || iNotG.size() == 3) {
208 infoPtr->errorMsg(
"Error in PartonVertex::vertexHadrons: "
209 "unknown colour topology not handled");
214 if (event[iFirst].daughter2() == event[iFirst].daughter1()) {
215 Vec4 vShift = 0.5 * (
event[iFirst].vProd() +
event[iLast].vProd());
216 event[nBefFrag].vProdAdd( vShift);
223 if (iNotG.size() == 2 || iNotG.size() == 0) {
228 double eBeg =
event[iBeg].e();
229 double eEnd = (iEnd < iLast &&
event[iEnd].isGluon() ? 0.5 : 1.)
231 double ePartonSum = eBeg + eEnd;
232 double eHadronSum = 0.;
235 for (
int i = nBefFrag; i <
event.size(); ++i) {
236 eHadronSum += 0.5 *
event[i].e();
239 while (eHadronSum > ePartonSum && iEnd < iLast) {
240 eHadronSum -= ePartonSum;
244 eEnd = (
event[iEnd].isGluon() ? 0.5 : 1.) *
event[iEnd].e();
245 ePartonSum = eBeg + eEnd;
249 double eFrac = clamp( eHadronSum / ePartonSum, 0., 1.);
250 Vec4 vShift = (1. - eFrac) * event[iBeg].vProd()
251 + eFrac *
event[iEnd].vProd();
252 event[i].vProdAdd( vShift);
253 eHadronSum += 0.5 *
event[i].e();
261 int iOrdSys[3] = {5, 5, 5};
262 for (
int k = 0; k < 3; ++k) {
263 int col = max( event[iNotG[k]].col(), event[iNotG[k]].acol());
264 for (
int i = 0; i <
event.sizeJunction(); ++i)
265 for (
int j = 0; j < 3; ++j)
266 if (event.endColJunction( i, j) == col) {
267 int statusLeg =
event.statusJunction( i, j);
268 if (statusLeg == 85) iOrdSys[0] = k;
269 else if (statusLeg == 86) iOrdSys[1] = k;
275 if (iOrdSys[0] + iOrdSys[1] +iOrdSys[2] == 3) ;
276 else if (iOrdSys[0] == 5 && iOrdSys[1] + iOrdSys[2] < 4)
277 iOrdSys[0] = 3 - iOrdSys[1] - iOrdSys[2];
278 else if (iOrdSys[1] == 5 && iOrdSys[0] + iOrdSys[2] < 4)
279 iOrdSys[1] = 3 - iOrdSys[0] - iOrdSys[2];
280 else if (iOrdSys[2] == 5 && iOrdSys[0] + iOrdSys[1] < 4)
281 iOrdSys[2] = 3 - iOrdSys[0] - iOrdSys[1];
283 infoPtr->errorMsg(
"Warning in PartonVertex::vertexHadrons: "
284 "unidentified junction topology not handled");
289 int nDone = nBefFrag;
290 for (
int leg = 0; leg < 2; ++leg) {
291 int nStop = (iOrdSys[leg] == 0) ? iFirst : iNotG[iOrdSys[leg] - 1] + 1;
292 int iBeg = iNotG[iOrdSys[leg]];
293 int iEnd = max(iBeg - 1, nStop);
294 double eBeg =
event[iBeg].e();
295 double eEnd = (
event[iEnd].isGluon() ? 0.5 : 1.) *
event[iEnd].e();
296 double ePartonSum = eBeg + eEnd;
297 double eHadronSum = 0.;
298 int statusNow = (leg == 0) ? 85 : 86;
301 for (
int i = nDone; i <
event.size(); ++i) {
302 if (event[i].status() != statusNow) {
306 eHadronSum += 0.5 *
event[i].e();
309 while (eHadronSum > ePartonSum && iEnd > nStop) {
310 eHadronSum -= ePartonSum;
314 eEnd = (
event[iEnd].isGluon() ? 0.5 : 1.) *
event[iEnd].e();
315 ePartonSum = eBeg + eEnd;
319 if (eHadronSum > ePartonSum || iBeg == nStop) {
320 event[i].vProdAdd( event[nStop].vProd() );
322 double eFrac = clamp( eHadronSum / ePartonSum, 0., 1.);
323 Vec4 vShift = (1. - eFrac) * event[iBeg].vProd()
324 + eFrac *
event[iEnd].vProd();
325 event[i].vProdAdd( vShift);
327 eHadronSum += 0.5 *
event[i].e();
332 int nStop = (iOrdSys[2] == 0) ? iFirst : iNotG[iOrdSys[2] - 1] + 1;
333 int iBeg = iNotG[iOrdSys[2]];
334 int iEnd = max(iBeg - 1, nStop);
335 double eBeg =
event[iBeg].e();
336 double eEnd = (
event[iEnd].isGluon() ? 0.5 : 1.) *
event[iEnd].e();
337 double ePartonSum = eBeg + eEnd;
338 double eHadronSum = 0.;
341 for (
int i = nDone; i <
event.size(); ++i) {
342 eHadronSum += 0.5 *
event[i].e();
345 while (eHadronSum > ePartonSum && iEnd > nStop) {
346 eHadronSum -= ePartonSum;
350 eEnd = (
event[iEnd].isGluon() ? 0.5 : 1.) *
event[iEnd].e();
351 ePartonSum = eBeg + eEnd;
356 if (eHadronSum > ePartonSum) {
357 event[i].vProdAdd( event[nStop].vProd() );
359 double eFrac = clamp( eHadronSum / ePartonSum, 0., 1.);
360 Vec4 vShift = (1. - eFrac) * event[iBeg].vProd()
361 + eFrac *
event[iEnd].vProd();
362 event[i].vProdAdd( vShift);
364 eHadronSum += 0.5 *
event[i].e();