9 #include "Pythia8/ResonanceDecays.h"
24 const int ResonanceDecays::NTRYCHANNEL = 10;
27 const int ResonanceDecays::NTRYMASSES = 10000;
30 const double ResonanceDecays::MSAFETY = 0.1;
33 const double ResonanceDecays::WIDTHCUT = 5.;
36 const double ResonanceDecays::TINY = 1e-10;
39 const double ResonanceDecays::TINYBWRANGE = 1e-8;
43 const double ResonanceDecays::WTCORRECTION[11] = { 1., 1., 1.,
44 2., 5., 15., 60., 250., 1250., 7000., 50000. };
48 bool ResonanceDecays::next(
Event& process,
int iDecNow) {
54 Particle& decayer = process[iDec];
55 if (decayer.isFinal() && decayer.canDecay() && decayer.mayDecay()
56 && decayer.isResonance() ) {
63 idProd.push_back( id0 );
64 mProd.push_back( m0 );
67 int idIn = process[decayer.mother1()].id();
70 if (!decayer.particleDataEntry().preparePick(id0, m0, idIn)) {
72 osWarn <<
"for id = " << id0;
73 infoPtr->errorMsg(
"Error in ResonanceDecays::next:"
74 " no open decay channel", osWarn.str());
79 bool foundChannel =
false;
80 for (
int iTryChannel = 0; iTryChannel < NTRYCHANNEL; ++iTryChannel) {
83 DecayChannel& channel = decayer.particleDataEntry().pickChannel();
84 mult = channel.multiplicity();
89 for (
int i = 1; i <= mult; ++i) {
90 idNow = channel.product(i - 1);
91 if (id0 < 0 && particleDataPtr->hasAnti(idNow)) idNow = -idNow;
92 idProd.push_back( idNow);
96 if (!pickMasses())
continue;
103 ostringstream osWarn;
104 osWarn <<
"for id = " << id0;
105 infoPtr->errorMsg(
"Error in ResonanceDecays::next:"
106 " failed to find workable decay channel", osWarn.str());
111 if (!pickColours(iDec, process))
return false;
115 pProd.push_back( decayer.p() );
116 if (!pickKinematics())
return false;
119 int iFirst = process.size();
120 for (
int i = 1; i <= mult; ++i) {
121 process.append( idProd[i], 23, iDec, 0, 0, 0, cols[i], acols[i],
122 pProd[i], mProd[i], m0);
124 int iLast = process.size() - 1;
127 if (process[iDec].hasVertex() || process[iDec].tau() > 0.) {
128 Vec4 vDec = process[iDec].vDec();
129 for (
int i = iFirst; i <= iLast; ++i) process[i].vProd( vDec );
133 for (
int i = iFirst; i <= iLast; ++i)
134 process[i].tau( process[i].tau0() * rndmPtr->exp() );
138 decayer.daughters(iFirst, iLast);
142 }
while (iDecNow == 0 && ++iDec < process.size());
153 bool ResonanceDecays::pickMasses() {
157 vector<double> m0BW, mMinBW, mMaxBW, widthBW;
158 double mMother = mProd[0];
159 double m2Mother = mMother * mMother;
160 useBW.push_back(
false );
161 m0BW.push_back( mMother );
162 mMinBW.push_back( mMother );
163 mMaxBW.push_back( mMother );
164 widthBW.push_back( 0. );
168 double m0Now, mMinNow, mMaxNow, widthNow;
169 for (
int i = 1; i <= mult; ++i) {
170 useBWNow = particleDataPtr->useBreitWigner( idProd[i] );
171 m0Now = particleDataPtr->m0( idProd[i] );
172 mMinNow = particleDataPtr->m0Min( idProd[i] );
173 mMaxNow = particleDataPtr->m0Max( idProd[i] );
174 if (useBWNow && mMaxNow < mMinNow) mMaxNow = mMother;
175 widthNow = particleDataPtr->mWidth( idProd[i] );
176 useBW.push_back( useBWNow );
177 m0BW.push_back( m0Now );
178 mMinBW.push_back( mMinNow );
179 mMaxBW.push_back( mMaxNow );
180 widthBW.push_back( widthNow );
181 mProd.push_back( m0Now );
188 for (
int i = 1; i <= mult; ++i) {
190 mSum += max( m0BW[i], mMinBW[i]);
191 mSumMin += mMinBW[i];
195 if (mSumMin + MSAFETY > mMother)
return false;
198 if (mSum + 0.5 * MSAFETY < mMother && nBW == 0)
return true;
201 if (mSum + MSAFETY < mMother) {
202 double wtMax = 2. * sqrtpos(1. - mSum*mSum / m2Mother);
204 for (
int iTryMasses = 0; iTryMasses <= NTRYMASSES; ++ iTryMasses) {
205 if (iTryMasses == NTRYMASSES)
return false;
207 for (
int i = 1; i <= mult; ++i) {
208 if (useBW[i]) mProd[i] = particleDataPtr->mSel( idProd[i] );
211 wt = (mSum + 0.5 * MSAFETY < mMother)
212 ? sqrtpos(1. - mSum*mSum / m2Mother) : 0.;
213 if (wt > rndmPtr->flat() * wtMax)
break;
223 for (
int i = 1; i <= mult; ++i) {
224 if (useBW[i]) iBW.push_back(i);
225 else mSum0 += mProd[i];
227 for (
int i = 1; i < nBW; ++i) {
228 for (
int j = i - 1; j >= 0; --j) {
229 if (widthBW[iBW[j+1]] > widthBW[iBW[j]]) swap (iBW[j+1], iBW[j]);
236 int iMin = (nBW == 1) ? 0 : 2;
237 for (
int i = nBW - 1; i >= iMin; --i) {
241 double mMax = mMother - mSum0 - MSAFETY;
242 if (nBW != 1)
for (
int j = 0; j < i; ++j) mMax -= mMinBW[iBW[j]];
243 mMax = min( mMaxBW[iBWi], mMax );
244 double mMin = min( mMinBW[iBWi], mMax - MSAFETY);
245 if (mMin < 0.)
return false;
248 double m2Nom = pow2( m0BW[iBWi] );
249 double m2Max = mMax * mMax;
250 double m2Min = mMin * mMin;
251 double mmWid = m0BW[iBWi] * widthBW[iBWi];
252 double atanMin = atan( (m2Min - m2Nom) / mmWid );
253 double atanMax = atan( (m2Max - m2Nom) / mmWid );
254 double atanDif = atanMax - atanMin;
257 if (atanDif < TINYBWRANGE)
return false;
260 double mr1 = mSum0*mSum0 / m2Mother;
261 double mr2 = m2Min / m2Mother;
262 double wtMax = sqrtpos( pow2(1. - mr1 - mr2) - 4. * mr1 * mr2 );
264 for (
int iTryMasses = 0; iTryMasses <= NTRYMASSES; ++ iTryMasses) {
265 if (iTryMasses == NTRYMASSES)
return false;
266 m2Now = m2Nom + mmWid * tan(atanMin + rndmPtr->flat() * atanDif);
267 mr2 = m2Now / m2Mother;
268 wt = sqrtpos( pow2(1. - mr1 - mr2) - 4. * mr1 * mr2 );
269 if (wt > rndmPtr->flat() * wtMax)
break;
273 mProd[iBWi] = sqrt(m2Now);
274 mSum0 += mProd[iBWi];
276 if (nBW == 1)
return true;
282 int idMother = abs(idProd[0]);
283 int idDau1 = abs(idProd[iBW1]);
284 int idDau2 = abs(idProd[iBW2]);
288 if ( (idMother == 25 || idMother == 35) && idDau1 < 19
289 && idDau2 == idDau1 ) psMode = 3;
290 if ( (idMother == 25 || idMother == 35 )
291 && (idDau1 == 23 || idDau1 == 24) && idDau2 == idDau1 ) psMode = 5;
293 && (idDau1 == 23 || idDau1 == 24) && idDau2 == idDau1 ) psMode = 6;
296 double mRem = mMother - mSum0 - MSAFETY;
297 double mMax1 = min( mMaxBW[iBW1], mRem - mMinBW[iBW2] );
298 double mMin1 = min( mMinBW[iBW1], mMax1 - MSAFETY);
299 double mMax2 = min( mMaxBW[iBW2], mRem - mMinBW[iBW1] );
300 double mMin2 = min( mMinBW[iBW2], mMax2 - MSAFETY);
303 if (mMin1 + mMin2 > mRem)
return false;
304 double mMid = 0.5 * mRem;
305 bool hasMid1 = (mMin1 < mMid);
306 bool hasMid2 = (mMin2 < mMid);
307 if (!hasMid1 && !hasMid2)
return false;
310 double m2Nom1 = pow2( m0BW[iBW1] );
311 double m2Max1 = mMax1 * mMax1;
312 double m2Min1 = mMin1 * mMin1;
313 double m2Mid1 = min( mMid * mMid, m2Max1);
314 double mmWid1 = m0BW[iBW1] * widthBW[iBW1];
315 double atanMin1 = atan( (m2Min1 - m2Nom1) / mmWid1 );
316 double atanMax1 = atan( (m2Max1 - m2Nom1) / mmWid1 );
317 double atanMid1 = (hasMid1) ? atan( (m2Mid1 - m2Nom1) / mmWid1 ) : 0.;
318 double m2Nom2 = pow2( m0BW[iBW2] );
319 double m2Max2 = mMax2 * mMax2;
320 double m2Min2 = mMin2 * mMin2;
321 double m2Mid2 = min( mMid * mMid, m2Max2);
322 double mmWid2 = m0BW[iBW2] * widthBW[iBW2];
323 double atanMin2 = atan( (m2Min2 - m2Nom2) / mmWid2 );
324 double atanMax2 = atan( (m2Max2 - m2Nom2) / mmWid2 );
325 double atanMid2 = (hasMid2) ? atan( (m2Mid2 - m2Nom2) / mmWid2 ) : 0.;
328 double probLow1 = (hasMid1) ? 1. : 0.;
329 if (hasMid1 && hasMid2) {
330 double intLow1 = (atanMid1 - atanMin1) * (atanMax2 - atanMin2);
331 double intLow2 = (atanMax1 - atanMin1) * (atanMid2 - atanMin2);
332 probLow1 = intLow1 / (intLow1 + intLow2);
336 double m2Rem = mRem * mRem;
337 double mr1 = m2Min1 / m2Rem;
338 double mr2 = m2Min2 / m2Rem;
339 double psMax = sqrtpos( pow2(1. - mr1 - mr2) - 4. * mr1 * mr2 );
341 if (psMode == 1) wtMax = psMax;
342 else if (psMode == 2) wtMax = psMax * psMax;
343 else if (psMode == 3) wtMax = pow3(psMax);
344 else if (psMode == 5) wtMax = psMax
345 * (pow2(1. - mr1 - mr2) + 8. * mr1 * mr2);
346 else if (psMode == 6) wtMax = pow3(psMax);
349 double atanDif1, atanDif2, m2Now1, m2Now2, mNow1, mNow2, ps, wt;
350 for (
int iTryMasses = 0; iTryMasses <= NTRYMASSES; ++ iTryMasses) {
351 if (iTryMasses == NTRYMASSES)
return false;
354 bool pickLow1 =
false;
355 if (rndmPtr->flat() < probLow1) {
356 atanDif1 = atanMid1 - atanMin1;
357 atanDif2 = atanMax2 - atanMin2;
360 atanDif1 = atanMax1 - atanMin1;
361 atanDif2 = atanMid2 - atanMin2;
363 m2Now1 = m2Nom1 + mmWid1 * tan(atanMin1 + rndmPtr->flat() * atanDif1);
364 m2Now2 = m2Nom2 + mmWid2 * tan(atanMin2 + rndmPtr->flat() * atanDif2);
365 mNow1 = sqrt(m2Now1);
366 mNow2 = sqrt(m2Now2);
369 bool rejectRegion = (pickLow1) ? (mNow1 > mNow2) : (mNow2 > mNow1);
370 if (rejectRegion)
continue;
373 mr1 = m2Now1 / m2Rem;
374 mr2 = m2Now2 / m2Rem;
376 if (mNow1 + mNow2 + MSAFETY < mMother) {
377 ps = sqrtpos( pow2(1. - mr1 - mr2) - 4. * mr1 * mr2 );
379 if (psMode == 1) wt = ps;
380 else if (psMode == 2) wt = ps * ps;
381 else if (psMode == 3) wt = pow3(ps);
382 else if (psMode == 5) wt = ps
383 * (pow2(1. - mr1 - mr2) + 8. * mr1 * mr2);
384 else if (psMode == 6) wt = pow3(ps)*mr1*mr2;
386 if (wt > rndmPtr->flat() * wtMax)
break;
400 bool ResonanceDecays::pickColours(
int iDec,
Event& process) {
405 vector<int> iTriplet, iAtriplet, iOctet, iDipCol, iDipAcol;
408 int col0 = process[iDec].col();
409 int acol0 = process[iDec].acol();
410 int colType0 = process[iDec].colType();
411 cols.push_back( col0);
412 acols.push_back(acol0);
416 for (
int i = 1; i <= mult; ++i) {
421 colTypeNow = particleDataPtr->colType( idProd[i] );
422 if (colTypeNow == 0);
423 else if (colTypeNow == 1) iTriplet.push_back(i);
424 else if (colTypeNow == -1) iAtriplet.push_back(i);
425 else if (colTypeNow == 2) iOctet.push_back(i);
427 else if (colTypeNow == 3) {
428 iTriplet.push_back(i);
429 iTriplet.push_back(i);
430 }
else if (colTypeNow == -3) {
431 iAtriplet.push_back(i);
432 iAtriplet.push_back(i);
434 infoPtr->errorMsg(
"Error in ResonanceDecays::pickColours:"
435 " unknown colour type encountered");
441 int nCol = iTriplet.size();
442 if (colType0 == 1 || colType0 == 2) nCol -= 1;
443 else if (colType0 == 3) nCol -= 2;
444 int nAcol = iAtriplet.size();
445 if (colType0 == -1 || colType0 == 2) nAcol -= 1;
446 else if (colType0 == -3) nAcol -= 2;
452 if (nCol - nAcol == 3) {
453 int kindJun = (colType0 == 0 || colType0 == 1 || colType0 == 3) ? 1 : 3;
457 colJun[0] = (kindJun == 1) ? process.nextColTag() : acol0;
458 colJun[1] = process.nextColTag();
459 colJun[2] = process.nextColTag();
460 process.appendJunction( kindJun, colJun[0], colJun[1], colJun[2]);
463 for (
int leg = 0; leg < 3; ++leg) {
464 if (leg == 0 && kindJun != 1) acol0 = 0;
468 int pickT = (iTriplet.size() == 1) ? 0
469 :
int( TINY + rndmPtr->flat() * (iTriplet.size() - TINY) );
470 int iPickT = iTriplet[pickT];
471 cols[iPickT] = colJun[leg];
474 iTriplet[pickT] = iTriplet.back();
476 iDipCol.push_back(iPickT);
477 iDipAcol.push_back(0);
489 if (nAcol - nCol == 3) {
490 int kindJun = (colType0 == 0 || colType0 == -1 || colType0 == -3) ? 2 : 4;
494 acolJun[0] = (kindJun == 2) ? process.nextColTag() : col0;
495 acolJun[1] = process.nextColTag();
496 acolJun[2] = process.nextColTag();
497 process.appendJunction( kindJun, acolJun[0], acolJun[1], acolJun[2]);
500 for (
int leg = 0; leg < 3; ++leg) {
501 if (leg == 0 && kindJun != 2) col0 = 0;
505 int pickA = (iAtriplet.size() == 1) ? 0
506 :
int( TINY + rndmPtr->flat() * (iAtriplet.size() - TINY) );
507 int iPickA = iAtriplet[pickA];
508 acols[iPickA] = acolJun[leg];
511 iAtriplet[pickA] = iAtriplet.back();
512 iAtriplet.pop_back();
513 iDipCol.push_back(0);
514 iDipAcol.push_back(iPickA);
524 infoPtr->errorMsg(
"Error in ResonanceDecays::pickColours:"
525 " inconsistent colour tags");
530 if (col0 > 0 && iTriplet.size() > 0) {
531 int pickT = (iTriplet.size() == 1) ? 0
532 :
int( TINY + rndmPtr->flat() * (iTriplet.size() - TINY) );
533 int iPickT = iTriplet[pickT];
538 iTriplet[pickT] = iTriplet.back();
540 iDipCol.push_back(iPickT);
541 iDipAcol.push_back(0);
545 if (acol0 > 0 && iAtriplet.size() > 0) {
546 int pickA = (iAtriplet.size() == 1) ? 0
547 :
int( TINY + rndmPtr->flat() * (iAtriplet.size() - TINY) );
548 int iPickA = iAtriplet[pickA];
549 acols[iPickA] = acol0;
553 iAtriplet[pickA] = iAtriplet.back();
554 iAtriplet.pop_back();
555 iDipCol.push_back(0);
556 iDipAcol.push_back(iPickA);
560 if (acol0 < 0 && iTriplet.size() > 0) {
561 int pickT = (iTriplet.size() == 1) ? 0
562 :
int( TINY + rndmPtr->flat() * (iTriplet.size() - TINY) );
563 int iPickT = iTriplet[pickT];
564 cols[iPickT] = -acol0;
568 iTriplet[pickT] = iTriplet.back();
570 iDipCol.push_back(iPickT);
571 iDipAcol.push_back(0);
575 if (col0 < 0 && iAtriplet.size() > 0) {
576 int pickA = (iAtriplet.size() == 1) ? 0
577 :
int( TINY + rndmPtr->flat() * (iAtriplet.size() - TINY) );
578 int iPickA = iAtriplet[pickA];
579 acols[iPickA] = -col0;
583 iAtriplet[pickA] = iAtriplet.back();
584 iAtriplet.pop_back();
585 iDipCol.push_back(0);
586 iDipAcol.push_back(iPickA);
590 if ( (iTriplet.size() != iAtriplet.size())
591 || (col0 != 0 && acol0 == 0) || (col0 == 0 && acol0 != 0) ) {
592 infoPtr->errorMsg(
"Error in ResonanceDecays::pickColours:"
593 " inconsistent colour tags");
598 for (
int pickT = 0; pickT < int(iTriplet.size()); ++pickT) {
599 int iPickT = iTriplet[pickT];
600 int pickA = (iAtriplet.size() == 1) ? 0
601 :
int( TINY + rndmPtr->flat() * (iAtriplet.size() - TINY) );
602 int iPickA = iAtriplet[pickA];
605 cols[iPickT] = process.nextColTag();
606 acols[iPickA] = cols[iPickT];
609 iAtriplet[pickT] = iAtriplet.back();
610 iAtriplet.pop_back();
611 iDipCol.push_back(iPickT);
612 iDipAcol.push_back(iPickA);
616 if (col0 == 0 && acol0 == 0 && iOctet.size() == 0)
return true;
620 iDipCol.push_back(0);
621 iDipAcol.push_back(0);
625 for (
int i = 0; i < int(iOctet.size()); ++i) {
626 int iOct = iOctet[i];
629 if (iDipCol.size() == 0) {
630 cols[iOct] = process.nextColTag();
631 acols[iOct] = cols[iOct] ;
632 iDipCol.push_back(iOct);
633 iDipAcol.push_back(iOct);
638 int pickDip = (iDipCol.size() == 1) ? 0
639 :
int( TINY + rndmPtr->flat() * (iDipCol.size() - TINY) );
642 if (iDipCol[pickDip] == 0 && iDipAcol[pickDip] == 0) {
645 iDipAcol[pickDip] = iOct;
646 iDipCol.push_back(iOct);
647 iDipAcol.push_back(0);
650 }
else if (iDipAcol[pickDip] == 0) {
651 int iPickCol = iDipCol[pickDip];
652 cols[iOct] = cols[iPickCol];
653 acols[iOct] = process.nextColTag();
654 cols[iPickCol] = acols[iOct];
655 iDipCol[pickDip] = iOct;
656 iDipCol.push_back(iPickCol);
657 iDipAcol.push_back(iOct);
662 int iPickAcol = iDipAcol[pickDip];
663 acols[iOct] = acols[iPickAcol];
664 cols[iOct] = process.nextColTag();
665 acols[iPickAcol] = cols[iOct];
666 iDipAcol[pickDip] = iOct;
667 iDipCol.push_back(iOct);
668 iDipAcol.push_back(iPickAcol);
674 if (iDipCol.size() < 2) {
675 infoPtr->errorMsg(
"Error in ResonanceDecays::pickColours:"
676 " inconsistent colour tags");
690 bool ResonanceDecays::pickKinematics() {
697 double m1 = mProd[1];
698 double m2 = mProd[2];
701 double e1 = 0.5 * (m0*m0 + m1*m1 - m2*m2) / m0;
702 double e2 = 0.5 * (m0*m0 + m2*m2 - m1*m1) / m0;
703 double pAbs = 0.5 * sqrtpos( (m0 - m1 - m2) * (m0 + m1 + m2)
704 * (m0 + m1 - m2) * (m0 - m1 + m2) ) / m0;
707 double cosTheta = 2. * rndmPtr->flat() - 1.;
708 double sinTheta = sqrt(1. - cosTheta*cosTheta);
709 double phi = 2. * M_PI * rndmPtr->flat();
710 double pX = pAbs * sinTheta * cos(phi);
711 double pY = pAbs * sinTheta * sin(phi);
712 double pZ = pAbs * cosTheta;
715 pProd.push_back( Vec4( pX, pY, pZ, e1) );
716 pProd.push_back( Vec4( -pX, -pY, -pZ, e2) );
717 pProd[1].bst( pProd[0] );
718 pProd[2].bst( pProd[0] );
729 double m1 = mProd[1];
730 double m2 = mProd[2];
731 double m3 = mProd[3];
732 double mDiff = m0 - (m1 + m2 + m3);
735 double m23Min = m2 + m3;
736 double m23Max = m0 - m1;
737 double p1Max = 0.5 * sqrtpos( (m0 - m1 - m23Min) * (m0 + m1 + m23Min)
738 * (m0 + m1 - m23Min) * (m0 - m1 + m23Min) ) / m0;
739 double p23Max = 0.5 * sqrtpos( (m23Max - m2 - m3) * (m23Max + m2 + m3)
740 * (m23Max + m2 - m3) * (m23Max - m2 + m3) ) / m23Max;
741 double wtPSmax = 0.5 * p1Max * p23Max;
744 double wtPS, m23, p1Abs, p23Abs;
746 m23 = m23Min + rndmPtr->flat() * mDiff;
749 p1Abs = 0.5 * sqrtpos( (m0 - m1 - m23) * (m0 + m1 + m23)
750 * (m0 + m1 - m23) * (m0 - m1 + m23) ) / m0;
751 p23Abs = 0.5 * sqrtpos( (m23 - m2 - m3) * (m23 + m2 + m3)
752 * (m23 + m2 - m3) * (m23 - m2 + m3) ) / m23;
753 wtPS = p1Abs * p23Abs;
756 }
while ( wtPS < rndmPtr->flat() * wtPSmax );
759 double cosTheta = 2. * rndmPtr->flat() - 1.;
760 double sinTheta = sqrt(1. - cosTheta*cosTheta);
761 double phi = 2. * M_PI * rndmPtr->flat();
762 double pX = p23Abs * sinTheta * cos(phi);
763 double pY = p23Abs * sinTheta * sin(phi);
764 double pZ = p23Abs * cosTheta;
765 double e2 = sqrt( m2*m2 + p23Abs*p23Abs);
766 double e3 = sqrt( m3*m3 + p23Abs*p23Abs);
767 Vec4 p2( pX, pY, pZ, e2);
768 Vec4 p3( -pX, -pY, -pZ, e3);
771 cosTheta = 2. * rndmPtr->flat() - 1.;
772 sinTheta = sqrt(1. - cosTheta*cosTheta);
773 phi = 2. * M_PI * rndmPtr->flat();
774 pX = p1Abs * sinTheta * cos(phi);
775 pY = p1Abs * sinTheta * sin(phi);
776 pZ = p1Abs * cosTheta;
777 double e1 = sqrt( m1*m1 + p1Abs*p1Abs);
778 double e23 = sqrt( m23*m23 + p1Abs*p1Abs);
779 pProd.push_back( Vec4( pX, pY, pZ, e1) );
782 Vec4 p23( -pX, -pY, -pZ, e23);
785 pProd.push_back( p2 );
786 pProd.push_back( p3 );
787 pProd[1].bst( pProd[0] );
788 pProd[2].bst( pProd[0] );
789 pProd[3].bst( pProd[0] );
799 double mSum = mProd[1];
800 for (
int i = 2; i <= mult; ++i) mSum += mProd[i];
801 double mDiff = m0 - mSum;
805 for (
int i = 0; i <= mult; ++i) mInv.push_back( mProd[i]);
808 double wtPSmax = 1. / WTCORRECTION[mult];
809 double mMax = mDiff + mProd[mult];
811 for (
int i = mult - 1; i > 0; --i) {
814 double mNow = mProd[i];
815 wtPSmax *= 0.5 * sqrtpos( (mMax - mMin - mNow) * (mMax + mMin + mNow)
816 * (mMax + mMin - mNow) * (mMax - mMin + mNow) ) / mMax;
820 vector<double> rndmOrd;
827 rndmOrd.push_back(1.);
828 for (
int i = 1; i < mult - 1; ++i) {
829 double rndm = rndmPtr->flat();
830 rndmOrd.push_back(rndm);
831 for (
int j = i - 1; j > 0; --j) {
832 if (rndm > rndmOrd[j]) swap( rndmOrd[j], rndmOrd[j+1] );
836 rndmOrd.push_back(0.);
839 for (
int i = mult - 1; i > 0; --i) {
840 mInv[i] = mInv[i+1] + mProd[i] + (rndmOrd[i-1] - rndmOrd[i]) * mDiff;
841 wtPS *= 0.5 * sqrtpos( (mInv[i] - mInv[i+1] - mProd[i])
842 * (mInv[i] + mInv[i+1] + mProd[i]) * (mInv[i] + mInv[i+1] - mProd[i])
843 * (mInv[i] - mInv[i+1] + mProd[i]) ) / mInv[i];
847 }
while ( wtPS < rndmPtr->flat() * wtPSmax );
851 pInv.resize(mult + 1);
852 for (
int i = 1; i < mult; ++i) {
853 double pAbs = 0.5 * sqrtpos( (mInv[i] - mInv[i+1] - mProd[i])
854 * (mInv[i] + mInv[i+1] + mProd[i]) * (mInv[i] + mInv[i+1] - mProd[i])
855 * (mInv[i] - mInv[i+1] + mProd[i]) ) / mInv[i];
858 double cosTheta = 2. * rndmPtr->flat() - 1.;
859 double sinTheta = sqrt(1. - cosTheta*cosTheta);
860 double phi = 2. * M_PI * rndmPtr->flat();
861 double pX = pAbs * sinTheta * cos(phi);
862 double pY = pAbs * sinTheta * sin(phi);
863 double pZ = pAbs * cosTheta;
866 double eHad = sqrt( mProd[i]*mProd[i] + pAbs*pAbs);
867 double eInv = sqrt( mInv[i+1]*mInv[i+1] + pAbs*pAbs);
868 pProd.push_back( Vec4( pX, pY, pZ, eHad) );
869 pInv[i+1].p( -pX, -pY, -pZ, eInv);
871 pProd.push_back( pInv[mult] );
875 for (
int iFrame = mult - 1; iFrame > 0; --iFrame)
876 for (
int i = iFrame; i <= mult; ++i) pProd[i].bst(pInv[iFrame]);