6 #include "Pythia8/HadronScatter.h"
77 const int SigmaPartialWave::LSHIFT = 1000000;
78 const int SigmaPartialWave::ISHIFT = 1000;
81 const double SigmaPartialWave::CONVERT2MB = 0.389380;
84 const double SigmaPartialWave::WCMBIN = 0.005;
85 const double SigmaPartialWave::CTBIN = 0.2;
87 const int SigmaPartialWave::SUBBIN = 2;
88 const int SigmaPartialWave::ITER = 2;
90 const double SigmaPartialWave::MASSSAFETY = 0.001;
91 const double SigmaPartialWave::GRIDSAFETY = 0.05;
98 bool SigmaPartialWave::init(
int processIn,
string xmlPath,
string filename,
99 Info *infoPtrIn, ParticleData *particleDataPtrIn,
103 particleDataPtr = particleDataPtrIn;
107 if (processIn < 0 || processIn > 2) {
108 infoPtr->errorMsg(
"Error in SigmaPartialWave::init: "
119 if (!readFile(xmlPath, filename))
return false;
123 if (Lmax > 0) PlVec[0] = 1.;
127 if (Lmax > 0) PlpVec[0] = 0.;
128 if (Lmax > 1) PlpVec[1] = 1.;
142 bool SigmaPartialWave::readFile(
string xmlPath,
string filename) {
144 string fullPath = xmlPath + filename;
145 ifstream ifs(fullPath.c_str());
147 infoPtr->errorMsg(
"Error in SigmaPartialWave::init: "
148 "could not read data file");
164 vector < int > Lvec, Ivec, Jvec;
171 toLowerRep(line,
false);
172 string::size_type startPos = line.find_first_not_of(
" ");
173 if (startPos != string::npos) line = line.substr(startPos);
175 if (line.length() == 0 || line[0] ==
'#')
continue;
179 vector < string > token;
181 startPos = lineT.find_first_of(
" ");
182 token.push_back(lineT.substr(0, startPos));
183 if (startPos == string::npos)
break;
184 startPos = lineT.find_first_not_of(
" ", startPos + 1);
185 if (startPos == string::npos)
break;
186 lineT = lineT.substr(startPos);
190 if (token[0] ==
"set") {
191 bool badSetting =
false;
194 if (token[1] ==
"etype") {
195 if (token[2] ==
"wcm") eType = 0;
196 else if (token[2] ==
"tlab") eType = 1;
197 else badSetting =
true;
200 }
else if (token[1] ==
"eunit") {
201 if (token[2] ==
"gev") eUnit = 0;
202 else if (token[2] ==
"mev") eUnit = 1;
203 else badSetting =
true;
206 }
else if (token[1] ==
"input") {
207 if (token[2] ==
"eta,delta") input = 0;
208 else if (token[2] ==
"sn,delta") input = 1;
209 else if (token[2] ==
"tr,ti") input = 2;
210 else if (token[2] ==
"mod,phi") input = 3;
211 else badSetting =
true;
214 }
else if (token[1] ==
"dunit") {
215 if (token[2] ==
"deg") dUnit = 0;
216 else if (token[2] ==
"rad") dUnit = 1;
217 else badSetting =
true;
220 }
else if (token[1] ==
"norm") {
221 if (token[2] ==
"0") norm = 0;
222 else if (token[2] ==
"1") norm = 1;
223 else badSetting =
true;
228 infoPtr->errorMsg(
"Error in SigmaPartialWave::init: "
236 if (line.substr(0, 1).find_first_of(
"0123456789.") != 0) {
238 Lvec.clear(); Ivec.clear(); Jvec.clear();
241 bool badHeader =
false;
242 for (
unsigned int i = 1; i < token.size(); i++) {
244 startPos = token[i].find_first_of(
",");
245 if (startPos == string::npos) { badHeader =
true;
break; }
246 string Lstr = token[i].substr(0, startPos);
247 token[i] = token[i].substr(startPos + 1);
250 startPos = token[i].find_first_of(
", ");
251 if (startPos == string::npos) {
255 Istr = token[i].substr(0, startPos);
256 token[i] = token[i].substr(startPos + 1);
260 if (token[i].length() != 0) Jstr = token[i];
264 stringstream Lss(Lstr); Lss >> L;
265 stringstream Iss(Istr); Iss >> I;
266 stringstream Jss(Jstr); Jss >> J;
267 if (Lss.fail() || Iss.fail() || Jss.fail())
268 { badHeader =
true;
break; }
276 infoPtr->errorMsg(
"Error in SigmaPartialWave::init: "
277 "malformed header line");
283 bool badData =
false;
286 if (token.size() != 2 * Lvec.size() + 1) badData =
true;
291 stringstream eSS(token[0]);
293 if (eSS.fail()) badData =
true;
295 if (eUnit == 1) eNow *= 1e-3;
297 if (eType == 1) eNow = sqrt(2. * mB * eNow + pow2(mA + mB));
298 binMax = max(binMax, eNow);
303 for (
unsigned int i = 1; i < token.size(); i += 2) {
305 int LIJidx = (i - 1) / 2;
306 int L = Lvec[LIJidx];
307 int I = Ivec[LIJidx];
308 int J = Jvec[LIJidx];
311 stringstream i1SS(token[i]); i1SS >> i1;
312 stringstream i2SS(token[i + 1]); i2SS >> i2;
313 if (i1SS.fail() || i2SS.fail()) { badData =
true;
break; }
316 if (input == 1) i1 = sqrt(1. - i1);
318 if ((input == 0 || input == 1 || input == 3) &&
319 dUnit == 0) i2 *= M_PI / 180.;
323 if (input == 0 || input == 1) {
324 T = (i1 * exp(2. * complex(0., 1.) * i2) - 1.) /
325 2. / complex(0., 1.);
326 }
else if (input == 2) {
328 }
else if (input == 3) {
329 T = i1 * exp(complex(0., 1.) * i2);
333 pwData[L * LSHIFT + I * ISHIFT + J][eNow] = T;
337 infoPtr->errorMsg(
"Error in SigmaPartialWave::init: "
338 "malformed data line");
345 if (!ifs.eof()) { ifs.close();
return false; }
358 void SigmaPartialWave::setupSubprocesses() {
366 sp2in[0] = pair < int, int > ( 211, 211);
367 sp2in[1] = pair < int, int > ( 211, -211);
368 sp2in[2] = pair < int, int > ( 211, 111);
369 sp2in[3] = pair < int, int > ( 111, 111);
370 sp2in[4] = pair < int, int > (-211, 111);
371 sp2in[5] = pair < int, int > (-211, -211);
373 for (
int i = 0; i < subprocessMax; i++) in2sp[sp2in[i]] = i;
375 isoCoeff[0][0] = 0.; isoCoeff[0][2] = 0.; isoCoeff[0][4] = 1.;
376 isoCoeff[1][0] = 1./3.; isoCoeff[1][2] = 1./2.; isoCoeff[1][4] = 1./6.;
377 isoCoeff[2][0] = 0.; isoCoeff[2][2] = 1./2.; isoCoeff[2][4] = 1./2.;
378 isoCoeff[3][0] = 1./3.; isoCoeff[3][2] = 0.; isoCoeff[3][4] = 2./3.;
379 isoCoeff[4][0] = 0.; isoCoeff[4][2] = 1./2.; isoCoeff[4][4] = 1./2.;
380 isoCoeff[5][0] = 0.; isoCoeff[5][2] = 0.; isoCoeff[5][4] = 1.;
387 if (process == 1) { id1 = 321; id2 = 311; }
388 else { id1 = 2212; id2 = 2112; }
392 sp2in[0] = pair < int, int > ( 211, id1);
393 sp2in[1] = pair < int, int > ( 211, id2);
394 sp2in[2] = pair < int, int > ( 111, id1);
395 sp2in[3] = pair < int, int > ( 111, id2);
396 sp2in[4] = pair < int, int > (-211, id1);
397 sp2in[5] = pair < int, int > (-211, id2);
399 isoCoeff[0][1] = 0.; isoCoeff[0][3] = 1.;
400 isoCoeff[1][1] = 2. / 3.; isoCoeff[1][3] = 1. / 3.;
401 isoCoeff[2][1] = 1. / 3.; isoCoeff[2][3] = 2. / 3.;
402 isoCoeff[3][1] = 1. / 3.; isoCoeff[3][3] = 2. / 3.;
403 isoCoeff[4][1] = 2. / 3.; isoCoeff[4][3] = 1. / 3.;
404 isoCoeff[5][1] = 0.; isoCoeff[5][3] = 1.;
406 for (
int i = 0; i < 6; i++) {
407 id1 = ((sp2in[i].first == 111) ? +1 : -1) * sp2in[i].first;
408 sp2in[i + 6] = pair < int, int > (id1, -sp2in[i].second);
409 isoCoeff[i + 6] = isoCoeff[i];
412 for (
int i = 0; i < subprocessMax; i++) in2sp[sp2in[i]] = i;
425 void SigmaPartialWave::setupGrid() {
430 gridMax.resize(subprocessMax);
431 gridNorm.resize(subprocessMax);
432 for (
int sp = 0; sp < subprocessMax; sp++) {
437 int nBin1 = int( (binMax - mA - mB) / WCMBIN );
438 gridMax[subprocess].resize(nBin1);
439 gridNorm[subprocess].resize(nBin1);
440 for (
int n1 = 0; n1 < nBin1; n1++) {
442 double bl1 = mA + mB + double(n1) * WCMBIN;
443 double bu1 = bl1 + WCMBIN;
446 int nBin2 = int( 2. / CTBIN );
447 gridMax[subprocess][n1].resize(nBin2);
448 for (
int n2 = 0; n2 < nBin2; n2++) {
450 double bl2 = -1. + double(n2) * CTBIN;
451 double bu2 = bl2 + CTBIN;
455 double bl3 = bl1, bu3 = bu1, bl4 = bl2, bu4 = bu2;
456 for (
int iter = 0; iter < ITER; iter++) {
457 int i3Save = -1, i4Save = -1;
458 double step3 = (bu3 - bl3) /
double(SUBBIN);
459 double step4 = (bu4 - bl4) /
double(SUBBIN);
460 for (
int i3 = 0; i3 <= SUBBIN; i3++) {
461 double Wcm = bl3 + double(i3) * step3;
462 for (
int i4 = 0; i4 <= SUBBIN; i4++) {
463 double ct = bl4 + double(i4) * step4;
464 double ds = dSigma(Wcm, ct);
473 if (i3Save == -1 && i4Save == -1)
break;
475 bl3 = bl3 + ((i3Save == 0) ? 0. : i3Save - 1.) * step3;
476 bu3 = bl3 + ((i3Save == SUBBIN) ? 1. : 2.) * step3;
479 bl4 = bl4 + ((i4Save == 0) ? 0. : i4Save - 1.) * step4;
480 bu4 = bl4 + ((i4Save == SUBBIN) ? 1. : 2.) * step4;
485 gridMax[subprocess][n1][n2] = maxSig * (1. + GRIDSAFETY);
486 gridNorm[subprocess][n1] += maxSig * (1. + GRIDSAFETY) * CTBIN;
487 sigElMax = max(sigElMax, maxSig);
501 double SigmaPartialWave::pickCosTheta(
double Wcm) {
503 int WcmBin = int((Wcm - mA - mB) / WCMBIN);
504 if (WcmBin < 0) WcmBin = 0;
505 if (WcmBin >=
int(gridMax[subprocess].size()))
506 WcmBin = int(gridMax[subprocess].size() - 1);
513 double y = rndmPtr->flat() * gridNorm[subprocess][WcmBin];
516 for (ctBin = 0; ctBin < int(2. / CTBIN); ctBin++) {
517 if (sum + CTBIN * gridMax[subprocess][WcmBin][ctBin] > y)
break;
518 sum += CTBIN * gridMax[subprocess][WcmBin][ctBin];
522 double x1 = -1. + CTBIN * double(ctBin);
524 double x2 = x1 + CTBIN;
525 double y2 = sum + CTBIN * gridMax[subprocess][WcmBin][ctBin];
526 ct = (x2 - x1) / (y2 - y1) * (y - y1) + x1;
527 wgt = dSigma(Wcm, ct) / gridMax[subprocess][WcmBin][ctBin];
529 infoPtr->errorMsg(
"Warning in SigmaPartialWave::pickCosTheta: "
530 "weight above unity");
533 }
while (wgt <= rndmPtr->flat());
542 bool SigmaPartialWave::setSubprocess(
int spIn) {
543 if (sp2in.find(spIn) == sp2in.end())
return false;
545 pair < int, int > in = sp2in[spIn];
547 mA = particleDataPtr->m0(idA);
549 mB = particleDataPtr->m0(idB);
553 bool SigmaPartialWave::setSubprocess(
int idAin,
int idBin) {
554 pair < int, int > in = pair < int, int > (idAin, idBin);
555 if (in2sp.find(in) == in2sp.end()) {
557 swap(in.first, in.second);
558 if (in2sp.find(in) == in2sp.end())
return false;
560 subprocess = in2sp[in];
562 mA = particleDataPtr->m0(idA);
564 mB = particleDataPtr->m0(idB);
572 double SigmaPartialWave::sigma(
int mode,
double Wcm,
double cTheta) {
574 if (Wcm < (mA + mB + MASSSAFETY))
return 0.;
577 complex amp[2] = { complex(0., 0.) };
581 double s = pow2(Wcm);
582 double k2 = (s - pow2(mB + mA)) * (s - pow2(mB - mA)) / 4. / s;
587 if (process == 2) sTheta = sqrt(1. - pow2(cTheta));
588 legendreP(cTheta, ((process == 2) ?
true :
false));
592 for (
int L = 0; L < Lmax; L++) {
595 complex ampJ[2] = { complex(0., 0.) };
596 int Jstart = (process != 2) ? 0 : 2 * L - 1;
597 int Jend = (process != 2) ? 1 : 2 * L + 2;
598 int Jstep = (process != 2) ? 1 : 2;
600 for (
int J = Jstart; J < Jend; J += Jstep, Jcount++) {
603 for (
int I = 0; I < Imax; I++) {
604 if (isoCoeff[subprocess][I] == 0.)
continue;
607 int LIJ = L * LSHIFT + I * ISHIFT + J;
608 if (pwData.find(LIJ) == pwData.end())
continue;
611 map < double, complex >::iterator it = pwData[LIJ].upper_bound(Wcm);
612 if (it == pwData[LIJ].begin()) ++it;
614 if (it == pwData[LIJ].end()) {
615 ar = (--it)->second.real();
616 ai = it->second.imag();
618 double eA = it->first;
619 complex ampA = (it--)->second;
620 double eB = it->first;
621 complex ampB = it->second;
623 ar = (ampA.real() - ampB.real()) / (eA - eB) *
624 (Wcm - eB) + ampB.real();
625 ai = (ampA.imag() - ampB.imag()) / (eA - eB) *
626 (Wcm - eB) + ampB.imag();
630 ampJ[Jcount] += isoCoeff[subprocess][I] * complex(ar, ai);
636 if (process == 0 || process == 1) {
637 sig += (2. * L + 1.) * (ampJ[0] * conj(ampJ[0])).real();
638 }
else if (process == 2) {
639 sig += ( (L + 0.) * (ampJ[0] * conj(ampJ[0])).real() +
640 (L + 1.) * (ampJ[1] * conj(ampJ[1])).real() );
644 }
else if (mode == 1) {
645 if (process == 0 || process == 1) {
646 sig += (2. * L + 1.) * ampJ[0].imag();
647 }
else if (process == 2) {
648 sig += ( (L + 0.) * ampJ[0].imag() + (L + 1.) * ampJ[1].imag() );
652 }
else if (mode == 2) {
653 if (process == 0 || process == 1) {
654 amp[0] += (2. * L + 1.) * ampJ[0] * PlVec[L];
655 }
else if (process == 2) {
656 amp[0] += ((L + 0.) * ampJ[0] + double(L + 1.) * ampJ[1]) * PlVec[L];
657 amp[1] += complex(0., 1.) * (ampJ[1] - ampJ[0]) * sTheta * PlpVec[L];
664 if (mode == 0 || mode == 1) {
665 if (norm == 0) sig *= 4. * M_PI / k2 * CONVERT2MB;
666 else if (norm == 1) sig *= 64. * M_PI / s * CONVERT2MB;
668 }
else if (mode == 2) {
669 sig = (amp[0] * conj(amp[0])).real() + (amp[1] * conj(amp[1])).real();
670 if (norm == 0) sig *= 2. * M_PI / k2 * CONVERT2MB;
671 else if (norm == 1) sig *= 32. * M_PI / s * CONVERT2MB;
674 return ((idA == idB) ? 0.5 : 1.) * sig;
682 void SigmaPartialWave::legendreP(
double ct,
bool deriv) {
683 if (Lmax > 1) PlVec[1] = ct;
684 for (
int L = 2; L < Lmax; L++) {
685 PlVec[L] = ( (2. * L - 1.) * ct * PlVec[L - 1] -
686 (L - 1.) * PlVec[L - 2] ) /
double(L);
688 PlpVec[L] = ( (2. * L - 1.) * (PlVec[L - 1] + ct * PlpVec[L - 1]) -
689 (L - 1.) * PlpVec[L - 2] ) /
double(L);
703 bool HadronScatter::init(Info* infoPtrIn, Settings& settings,
704 Rndm *rndmPtrIn, ParticleData *particleDataPtr) {
710 scatterMode = settings.mode(
"HadronScatter:mode");
711 p2max = pow2(settings.parm(
"HadronScatter:pMax"));
712 yDiffMax = settings.parm(
"HadronScatter:yDiffMax");
713 Rmax = settings.parm(
"HadronScatter:Rmax");
714 scatSameString = settings.flag(
"HadronScatter:scatterSameString");
715 scatMultTimes = settings.flag(
"HadronScatter:scatterMultipleTimes");
716 maxProbDS = settings.parm(
"HadronScatter:maxProbDS");
717 neighNear = double(settings.mode(
"HadronScatter:neighbourNear"));
718 neighFar = double(settings.mode(
"HadronScatter:neighbourFar"));
719 minProbSS = settings.parm(
"HadronScatter:minProbSS");
720 maxProbSS = settings.parm(
"HadronScatter:maxProbSS");
723 doOldScatter = (scatterMode == 2);
724 afterDecay = settings.flag(
"HadronScatter:afterDecay");
725 allowDecayProd = settings.flag(
"HadronScatter:allowDecayProd");
726 scatterRepeat = settings.flag(
"HadronScatter:scatterRepeat");
728 hadronSelect = settings.mode(
"HadronScatter:hadronSelect");
729 Npar = settings.parm(
"HadronScatter:N");
730 kPar = settings.parm(
"HadronScatter:k");
731 pPar = settings.parm(
"HadronScatter:p");
733 scatterProb = settings.mode(
"HadronScatter:scatterProb");
734 jPar = settings.parm(
"HadronScatter:j");
735 rMax = settings.parm(
"HadronScatter:rMax");
737 doTile = settings.flag(
"HadronScatter:tile");
740 pTsigma = 2.0 * settings.parm(
"StringPT:sigma");
741 pTsigma2 = pTsigma * pTsigma;
742 double pT0ref = settings.parm(
"MultipartonInteractions:pT0ref");
743 double eCMref = settings.parm(
"MultipartonInteractions:eCMref");
744 double eCMpow = settings.parm(
"MultipartonInteractions:eCMpow");
745 double eCMnow = infoPtr->eCM();
746 pT0MPI = pT0ref * pow(eCMnow / eCMref, eCMpow);
750 double mp2 = particleDataPtr->m0(111) * particleDataPtr->m0(111);
751 double eA = infoPtr->eA();
752 double eB = infoPtr->eB();
753 double pzA = sqrt(eA * eA - mp2);
754 double pzB = -sqrt(eB * eB - mp2);
755 yMax = 0.5 * log((eA + pzA) / (eA - pzA));
756 yMin = 0.5 * log((eB + pzB) / (eB - pzB));
759 ytMax = int((yMax - yMin) / rMax);
760 ytSize = (yMax - yMin) /
double(ytMax);
761 ptMax = int(2. * M_PI / rMax);
762 ptSize = 2. * M_PI / double(ptMax);
765 ytSize = yMax - yMin;
771 for (
int yt = 0; yt < ytMax; yt++) tile[yt].resize(ptMax);
778 const char* PYTHIA8DATA =
"PYTHIA8DATA";
779 char* envPath = getenv(PYTHIA8DATA);
780 if (envPath != 0 && *envPath !=
'\0') {
782 while (*(envPath+i) !=
'\0') xmlPath += *(envPath+(i++));
783 }
else xmlPath =
"../xmldoc";
784 if (xmlPath[ xmlPath.length() - 1 ] !=
'/') xmlPath +=
"/";
787 if ( !sigmaPW[0].init(0, xmlPath,
"pipi-Froggatt.dat",
788 infoPtr, particleDataPtr, rndmPtr) )
return false;
789 if ( !sigmaPW[1].init(1, xmlPath,
"piK-Estabrooks.dat",
790 infoPtr, particleDataPtr, rndmPtr) )
return false;
791 if ( !sigmaPW[2].init(2, xmlPath,
"piN-SAID-WI08.dat",
792 infoPtr, particleDataPtr, rndmPtr) )
return false;
794 sigElMax = max(sigElMax, sigmaPW[0].getSigmaElMax());
795 sigElMax = max(sigElMax, sigmaPW[1].getSigmaElMax());
796 sigElMax = max(sigElMax, sigmaPW[2].getSigmaElMax());
810 void HadronScatter::debugOutput() {
812 cout <<
"Hadron scattering:" << endl
813 <<
" scatter = " << ((doOldScatter) ?
"on" :
"off") << endl
814 <<
" afterDecay = " << ((afterDecay) ?
"on" :
"off") << endl
815 <<
" allowDecayProd = " << ((allowDecayProd) ?
"on" :
"off") << endl
816 <<
" scatterRepeat = " << ((scatterRepeat) ?
"on" :
"off") << endl
817 <<
" tile = " << ((doTile) ?
"on" :
"off") << endl
818 <<
" yMin = " << yMin << endl
819 <<
" yMax = " << yMax << endl
820 <<
" ytMax = " << ytMax << endl
821 <<
" ytSize = " << ytSize << endl
822 <<
" ptMax = " << ptMax << endl
823 <<
" ptSize = " << ptSize << endl
825 <<
" hadronSelect = " << hadronSelect << endl
826 <<
" N = " << Npar << endl
827 <<
" k = " << kPar << endl
828 <<
" p = " << pPar << endl
830 <<
" scatterProb = " << scatterProb << endl
831 <<
" j = " << jPar << endl
832 <<
" rMax = " << rMax << endl
834 <<
" pTsigma = " << pTsigma2 << endl
835 <<
" pT0MPI = " << pT0MPI << endl
837 <<
" sigElMax = " << sigElMax << endl << endl;
849 void HadronScatter::scatter(
Event& event) {
852 vector< pair<int,double> > hadronRapidity;
853 for (
int i = 0; i < int(event.size()); i++) {
854 if (event[i].isFinal() &&
event[i].isHadron())
855 hadronRapidity.push_back( pair<int,double>( i, event[i].y() ) );
858 mergeSortCollFlow(hadronRapidity);
861 vector< pair<int,int> > hadCombis;
862 for (
int i1 = 0; i1 < int(hadronRapidity.size()) - 1; i1++) {
863 int iHad1 = hadronRapidity[i1].first;
865 for (
int i2 = i1 + 1; i2 < int(hadronRapidity.size()); i2++) {
866 int iHad2 = hadronRapidity[i2].first;
868 if (iHad1 == iHad2)
continue;
871 bool sameStr = ( (
event[iHad1].mother1() ==
event[iHad2].mother1()) &&
872 (event[iHad1].mother2() ==
event[iHad2].mother2()) );
874 if (!scatSameString)
continue;
875 int indxDiff = abs(iHad1 - iHad2);
876 if (indxDiff < neighNear)
continue;
877 double probNow = maxProbSS;
878 if (indxDiff < neighFar) {
879 if (neighFar == neighNear) probNow = max(maxProbSS,minProbSS);
881 double grad = (maxProbSS - minProbSS) / (neighFar - neighNear);
882 double yint = maxProbSS - grad * neighFar;
883 probNow = grad * indxDiff + yint;
886 if (rndmPtr->flat() > probNow)
continue;
890 double yDiff = abs( hadronRapidity[i1].second
891 - hadronRapidity[i2].second );
894 if (scatterMode == 0) {
896 if (yDiff > yDiffMax)
break;
898 Vec4 pHad[2] = {
event[iHad1].p(),
event[iHad2].p() };
899 double m2max = pow2( sqrt(pHad[0].m2Calc() + p2max) +
900 sqrt(pHad[1].m2Calc() + p2max) );
901 if ( (pHad[0] + pHad[1]).m2Calc() > m2max )
continue;
904 if (rndmPtr->flat() > maxProbDS * (1.0 - yDiff / yDiffMax) )
continue;
908 else if (scatterMode == 1) {
910 if (yDiff > Rmax)
break;
911 double aDiff = abs( event[iHad1].phi() - event[iHad2].phi() );
912 if (aDiff > M_PI) aDiff = 2. * M_PI - aDiff;
913 double Rdiff = sqrt( pow2(yDiff) + pow2(aDiff) );
916 if (rndmPtr->flat() > maxProbDS * (1.0 - Rdiff / Rmax))
continue;
920 hadCombis.push_back( pair<int,int>(iHad1,iHad2) );
922 if (!scatMultTimes)
break;
927 int nPair = hadCombis.size();
928 for (
int iPair = 0; iPair < nPair; ++iPair) {
929 int iPnow = min(
int( rndmPtr->flat() * (nPair - iPair) ),
931 int iHad[2] = { hadCombis[iPnow].first, hadCombis[iPnow].second };
934 bool hasScat[2] = {!
event[iHad[0]].isFinal(), !
event[iHad[1]].isFinal()};
935 for (
int i = 0; i < 2; i++)
if (hasScat[i]) {
938 iHad[i] =
event[iHad[i]].daughter1();
939 if (event[iHad[i]].isFinal()) found =
true;
944 Vec4 pHad[2] = {
event[iHad[0]].p(),
event[iHad[1]].p() };
945 Vec4 pSumHad = pHad[0] + pHad[1];
946 double thetaRndm = acos( 2. * rndmPtr->flat() - 1.);
947 double phiRndm = 2. * M_PI * rndmPtr->flat();
948 for (
int i = 0; i < 2; i++) {
949 pHad[i].bstback( pSumHad);
950 pHad[i].rot( thetaRndm, phiRndm);
951 pHad[i].bst( pSumHad);
955 for (
int i = 0; i < 2; i++) {
957 int iNew =
event.copy( iHad[i], (hasScat[i] ? 112 : 111));
959 event[iNew].p(pHad[i]);
963 hadCombis[iPnow] = hadCombis.back();
964 hadCombis.pop_back();
975 void HadronScatter::scatterOld(
Event& event) {
977 for (
int yt = 0; yt < ytMax; yt++)
978 for (
int pt = 0; pt < ptMax; pt++)
979 tile[yt][pt].clear();
982 for (
int i = 0; i <
event.size(); i++)
983 if (event[i].isFinal() &&
event[i].isHadron() && canScatter(event, i))
984 tile[yTile(event, i)][pTile(event, i)].insert(HSIndex(i, i));
987 vector < HadronScatterPair > scatterList;
989 for (
int pt1 = 0; pt1 < ptMax; pt1++)
990 for (
int yt1 = 0; yt1 < ytMax; yt1++)
991 for (set < HSIndex >::iterator si1 = tile[yt1][pt1].begin();
992 si1 != tile[yt1][pt1].end(); si1++)
993 tileIntProb(scatterList, event, *si1, yt1, pt1,
false);
995 sort(scatterList.rbegin(), scatterList.rend());
998 if (scatterRepeat) scattered.clear();
1001 while (scatterList.size() > 0) {
1003 HadronScatterPair &hsp = scatterList[0];
1004 if (!event[hsp.i1.second].isFinal() || !
event[hsp.i2.second].isFinal()) {
1005 scatterList.erase(scatterList.begin());
1009 tile[hsp.yt1][hsp.pt1].erase(hsp.i1);
1010 tile[hsp.yt2][hsp.pt2].erase(hsp.i2);
1011 hadronScatter(event, hsp);
1013 HSIndex iNew1 = hsp.i1, iNew2 = hsp.i2;
1016 bool resort =
false;
1017 if (scatterRepeat) {
1019 HSIndex iNew = iNew1;
1020 for (
int i = 0; i < 2; i++) {
1021 if (canScatter(event, iNew.second)) {
1024 if (i == 1) scattered.insert(HSIndex(min(iNew1.first, iNew2.first),
1025 max(iNew1.first, iNew2.first)));
1026 int yt = yTile(event, iNew.second);
1027 int pt = pTile(event, iNew.second);
1028 resort = tileIntProb(scatterList, event, iNew, yt, pt,
true);
1029 tile[yt][pt].insert(iNew);
1037 scatterList.erase(scatterList.begin());
1039 if (resort) sort(scatterList.rbegin(), scatterList.rend());
1052 bool HadronScatter::canScatter(
Event& event,
int i) {
1057 if (scatterProb == 1 || scatterProb == 2)
1058 if (event[i].idAbs() != 111 && event[i].idAbs() != 211 &&
1059 event[i].idAbs() != 321 && event[i].idAbs() != 2212)
1063 switch (hadronSelect) {
1065 double t1 = exp( - event[i].pT2() / 2. / pTsigma2);
1066 double t2 = pow(pT0MPI, pPar) /
1067 pow(pT0MPI * pT0MPI + event[i].pT2(), pPar / 2.);
1068 p = Npar * t1 / ( (1 - kPar) * t1 + kPar * t2 );
1073 if (p > rndmPtr->flat())
return true;
1081 bool HadronScatter::doesScatter(
Event& event,
const HSIndex &i1,
1082 const HSIndex &i2) {
1083 Particle &p1 =
event[i1.second];
1084 Particle &p2 =
event[i2.second];
1087 if (!allowDecayProd && event[i1.first].mother1() ==
1088 event[i2.first].mother1() &&
event[
event[i1.first].mother1()].isHadron())
1092 if (scatterRepeat &&
1093 scattered.find(HSIndex(min(i1.first, i2.first), max(i1.first, i2.first)))
1094 != scattered.end())
return false;
1097 int id1 = min(p1.idAbs(), p2.idAbs());
1098 int id2 = max(p1.idAbs(), p2.idAbs());
1099 if (scatterProb == 1 || scatterProb == 2) {
1100 if ((id1 == 321 || id1 == 2212) && id1 == id2)
return false;
1101 if (id1 == 321 && id2 == 2212)
return false;
1105 double dy = p1.y() - p2.y();
1106 double dp = abs(p1.phi() - p2.phi());
1107 if (dp > M_PI) dp = 2 * M_PI - dp;
1108 double dr2 = dy * dy + dp * dp;
1109 double p = max(0., 1. - dr2 / rMax2);
1112 if (scatterProb == 0 || scatterProb == 1) {
1116 }
else if (scatterProb == 2) {
1118 double Wcm = (p1.p() + p2.p()).mCalc();
1120 if ((id1 == 111 || id1 == 211) && (id2 == 111 || id2 == 211)) pw = 0;
1121 else if ((id1 == 111 || id1 == 211) && id2 == 321) pw = 1;
1122 else if ((id1 == 111 || id1 == 211) && id2 == 2212) pw = 2;
1124 infoPtr->errorMsg(
"Error in HadronScatter::doesScatter:"
1125 "unknown subprocess");
1127 if (!sigmaPW[pw].setSubprocess(p1.id(), p2.id())) {
1128 infoPtr->errorMsg(
"Error in HadronScatter::doesScatter:"
1129 "setSubprocess failed");
1131 p *= 1 - exp(-jPar * sigmaPW[pw].sigmaEl(Wcm));
1136 return (p > rndmPtr->flat());
1144 double HadronScatter::measure(
Event& event,
int idx1,
int idx2) {
1145 Particle &p1 =
event[idx1];
1146 Particle &p2 =
event[idx2];
1147 return abs(p1.pT() / p1.mT() - p2.pT() / p2.mT());
1155 bool HadronScatter::hadronScatter(
Event& event, HadronScatterPair &hsp) {
1156 bool doSwap = (0.5 < rndmPtr->flat()) ?
true :
false;
1157 if (doSwap) swap(hsp.i1, hsp.i2);
1159 Particle &p1 =
event[hsp.i1.second];
1160 Particle &p2 =
event[hsp.i2.second];
1163 double ct = 0., phi = 2 * M_PI * rndmPtr->flat();
1166 if (scatterProb == 0 || scatterProb == 1) {
1167 ct = 2. * rndmPtr->flat() - 1.;
1170 }
else if (scatterProb == 2) {
1172 int id1 = min(p1.idAbs(), p2.idAbs());
1173 int id2 = max(p1.idAbs(), p2.idAbs());
1174 double Wcm = (p1.p() + p2.p()).mCalc();
1176 if ((id1 == 111 || id1 == 211) && (id2 == 111 || id2 == 211)) pw = 0;
1177 else if ((id1 == 111 || id1 == 211) && id2 == 321) pw = 1;
1178 else if ((id1 == 111 || id1 == 211) && id2 == 2212) pw = 2;
1180 infoPtr->errorMsg(
"Error in HadronScatter::hadronScatter:"
1181 "unknown subprocess");
1183 sigmaPW[pw].setSubprocess(p1.id(), p2.id());
1184 ct = sigmaPW[pw].pickCosTheta(Wcm);
1189 sMat.toCMframe(p1.p(), p2.p());
1190 sMat.rot(acos(ct), phi);
1191 sMat.fromCMframe(p1.p(), p2.p());
1192 Vec4 v1 = p1.p(), v2 = p2.p();
1197 int iNew1 =
event.copy(hsp.i1.second, 98);
1199 event[iNew1].e(event[iNew1].eCalc());
1200 event[hsp.i1.second].statusNeg();
1201 int iNew2 =
event.copy(hsp.i2.second, 98);
1203 event[iNew2].e(event[iNew2].eCalc());
1204 event[hsp.i2.second].statusNeg();
1207 hsp.i1.second = iNew1;
1208 hsp.i2.second = iNew2;
1210 if (doSwap) swap(hsp.i1, hsp.i2);
1225 bool HadronScatter::tileIntProb(vector < HadronScatterPair > &hsp,
1226 Event &event,
const HSIndex &i1,
int yt1,
int pt1,
bool doAll) {
1228 bool pairAdded =
false;
1232 set < HSIndex >::iterator si2 = tile[yt1][pt1].find(i1);
1233 while (++si2 != tile[yt1][pt1].end())
1235 if (doesScatter(event, i1, *si2)) {
1236 double m = measure(event, i1.second, si2->second);
1237 hsp.push_back(HadronScatterPair(i1, yt1, pt1, *si2, yt1, pt1, m));
1242 int tileMax = (doAll) ? 9 : 4;
1243 for (
int tileNow = 0; tileNow < tileMax; tileNow++) {
1245 int yt2 = yt1, pt2 = pt1;
1247 case 0: ++pt2;
break;
1248 case 1: ++yt2; ++pt2;
break;
1249 case 2: ++yt2;
break;
1250 case 3: ++yt2; --pt2;
break;
1251 case 4: --pt2;
break;
1252 case 5: --yt2; --pt2;
break;
1253 case 6: --yt2;
break;
1254 case 7: --yt2; ++pt2;
break;
1258 if (yt2 < 0 || yt2 >= ytMax)
continue;
1262 if (pt2 == pt1 || pt2 == pt1 + 1)
continue;
1264 }
else if (pt2 >= ptMax) {
1266 if (pt2 == pt1 || pt2 == pt1 - 1)
continue;
1270 for (set < HSIndex >::iterator si2 = tile[yt2][pt2].begin();
1271 si2 != tile[yt2][pt2].end(); si2++) {
1273 if (doesScatter(event, i1, *si2)) {
1274 double m = measure(event, i1.second, si2->second);
1275 hsp.push_back(HadronScatterPair(i1, yt1, pt1, *si2, yt2, pt2, m));
1288 void HadronScatter::mergeSortCollFlow(vector< pair<int,double> >& sort,
1289 int iStart,
int iEnd) {
1294 iEnd = int(sort.size());
1298 if (iStart < iEnd) {
1300 int iDivide = (iEnd-iStart)/2;
1301 mergeSortCollFlow( sort, iStart, iStart + iDivide);
1302 mergeSortCollFlow( sort, iStart + iDivide + 1, iEnd);
1303 mergeCollFlow( sort, iStart, iDivide, iEnd);
1307 void HadronScatter::mergeCollFlow(vector< pair<int,double> >& sort,
1308 int iStart,
int iDivide,
int iEnd) {
1311 int iStart1 = iStart - 1;
1312 int iEnd1 = iStart + iDivide - 1;
1313 int iStart2 = iStart + iDivide;
1314 int iEnd2 = iEnd - 1;
1316 vector< pair<int,double> > out;
1319 for (
int i = 0; i < iStart - 1; i++) out.push_back( sort[i] );
1322 int iNow1 = iStart1;
1323 int iNow2 = iStart2;
1324 while ( (iNow1 <= iEnd1) && (iNow2 <= iEnd2) ) {
1325 if (sort[iNow1].second < sort[iNow2].second) {
1326 out.push_back(sort[iNow1]);
1329 out.push_back(sort[iNow2]);
1335 if (iNow1 <= iEnd1) {
1336 for (
int i = iNow1; i <= iEnd1; i++) out.push_back( sort[i] );
1337 }
else if (iNow2 <= iEnd2) {
1338 for (
int i = iNow2; i <= iEnd2; i++) out.push_back( sort[i] );
1342 for (
int i = iEnd; i < int(sort.size()); i++) out.push_back( sort[i] );