9 #include "Pythia8/HeavyIons.h"
32 map<string,Flag> flags = settings.getFlagMap(match);
33 for ( map<string,Flag>::iterator it = flags.begin();
34 it != flags.end(); ++it )
35 settings.addFlag(
"HI" + it->second.name, it->second.valDefault);
36 map<string,Mode> modes = settings.getModeMap(match);
37 for ( map<string,Mode>::iterator it = modes.begin();
38 it != modes.end(); ++it )
39 settings.addMode(
"HI" + it->second.name, it->second.valDefault,
40 it->second.hasMin, it->second.hasMax,
41 it->second.valMin, it->second.valMax, it->second.optOnly);
42 map<string,Parm> parms = settings.getParmMap(match);
43 for ( map<string,Parm>::iterator it = parms.begin();
44 it != parms.end(); ++it )
45 settings.addParm(
"HI" + it->second.name, it->second.valDefault,
46 it->second.hasMin, it->second.hasMax,
47 it->second.valMin, it->second.valMax);
48 map<string,Word> words = settings.getWordMap(match);
49 for ( map<string,Word>::iterator it = words.begin();
50 it != words.end(); ++it )
51 settings.addWord(
"HI" + it->second.name, it->second.valDefault);
52 map<string,FVec> fvecs = settings.getFVecMap(match);
53 for ( map<string, FVec>::iterator it = fvecs.begin();
54 it != fvecs.end(); ++it )
55 settings.addFVec(
"HI" + it->second.name, it->second.valDefault);
56 map<string,MVec> mvecs = settings.getMVecMap(match);
57 for ( map<string,MVec>::iterator it = mvecs.begin();
58 it != mvecs.end(); ++it )
59 settings.addMVec(
"HI" + it->second.name, it->second.valDefault,
60 it->second.hasMin, it->second.hasMax,
61 it->second.valMin, it->second.valMax);
62 map<string,PVec> pvecs = settings.getPVecMap(match);
63 for ( map<string,PVec>::iterator it = pvecs.begin();
64 it != pvecs.end(); ++it )
65 settings.addPVec(
"HI" + it->second.name, it->second.valDefault,
66 it->second.hasMin, it->second.hasMax,
67 it->second.valMin, it->second.valMax);
68 map<string,WVec> wvecs = settings.getWVecMap(match);
69 for ( map<string,WVec>::iterator it = wvecs.begin();
70 it != wvecs.end(); ++it )
71 settings.addWVec(
"HI" + it->second.name, it->second.valDefault);
75 Settings & opts = p.settings;
76 map<string, Flag> flags = opts.getFlagMap(match);
77 for ( map<string, Flag>::iterator it = flags.begin();
78 it != flags.end(); ++it )
79 opts.flag(it->second.name.substr(2), it->second.valNow,
true);
80 map<string, Mode> modes = opts.getModeMap(match);
81 for ( map<string, Mode>::iterator it = modes.begin();
82 it != modes.end(); ++it )
83 opts.mode(it->second.name.substr(2), it->second.valNow,
true);
84 map<string, Parm> parms = opts.getParmMap(match);
85 for ( map<string, Parm>::iterator it = parms.begin();
86 it != parms.end(); ++it )
87 opts.parm(it->second.name.substr(2), it->second.valNow,
true);
88 map<string, Word> words = opts.getWordMap(match);
89 for ( map<string, Word>::iterator it = words.begin();
90 it != words.end(); ++it )
91 opts.word(it->second.name.substr(2), it->second.valNow,
true);
92 map<string, FVec> fvecs = opts.getFVecMap(match);
93 for ( map<string, FVec>::iterator it = fvecs.begin();
94 it != fvecs.end(); ++it )
95 opts.fvec(it->second.name.substr(2), it->second.valNow,
true);
96 map<string, MVec> mvecs = opts.getMVecMap(match);
97 for ( map<string, MVec>::iterator it = mvecs.begin();
98 it != mvecs.end(); ++it )
99 opts.mvec(it->second.name.substr(2), it->second.valNow,
true);
100 map<string, PVec> pvecs = opts.getPVecMap(match);
101 for ( map<string, PVec>::iterator it = pvecs.begin();
102 it != pvecs.end(); ++it )
103 opts.pvec(it->second.name.substr(2), it->second.valNow,
true);
104 map<string, WVec> wvecs = opts.getWVecMap(match);
105 for ( map<string, WVec>::iterator it = wvecs.begin();
106 it != wvecs.end(); ++it )
107 opts.wvec(it->second.name.substr(2), it->second.valNow,
true);
116 for (
auto it : ihi->messages ) in.messages[tag + it.first] += it.second;
125 string path = pyt.settings.word(
"xmlPath");
126 pyt.settings.mode(
"Tune:ee", 0);
127 pyt.settings.mode(
"Tune:pp", 0);
128 pyt.settings.init(path +
"QCDSoftProcesses.xml",
true);
129 pyt.settings.init(path +
"QCDHardProcesses.xml",
true);
130 pyt.settings.init(path +
"ElectroweakProcesses.xml",
true);
131 pyt.settings.init(path +
"OniaProcesses.xml",
true);
132 pyt.settings.init(path +
"TopProcesses.xml",
true);
133 pyt.settings.init(path +
"FourthGenerationProcesses.xml",
true);
134 pyt.settings.init(path +
"HiggsProcesses.xml",
true);
135 pyt.settings.init(path +
"SUSYProcesses.xml",
true);
136 pyt.settings.init(path +
"NewGaugeBosonProcesses.xml",
true);
137 pyt.settings.init(path +
"LeftRightSymmetryProcesses.xml",
true);
138 pyt.settings.init(path +
"LeptoquarkProcesses.xml",
true);
139 pyt.settings.init(path +
"CompositenessProcesses.xml",
true);
140 pyt.settings.init(path +
"HiddenValleyProcesses.xml",
true);
141 pyt.settings.init(path +
"ExtraDimensionalProcesses.xml",
true);
142 pyt.settings.init(path +
"DarkMatterProcesses.xml",
true);
143 pyt.settings.init(path +
"SecondHardProcess.xml",
true);
144 pyt.settings.init(path +
"PhaseSpaceCuts.xml",
true);
154 map<string, int> saveMess = infoPtr->messages;
155 *infoPtr =
hiInfo.primInfo;
156 infoPtr->hiInfo = &
hiInfo;
157 infoPtr->messages = saveMess;
158 infoPtr->weightContainerPtr->setWeightNominal(
hiInfo.
weight());
159 infoPtr->sigmaReset();
160 double norm = 1.0/double(
hiInfo.NSave);
164 for ( map<int,int>::iterator ip =
hiInfo.NPrim.begin();
165 ip !=
hiInfo.NPrim.end(); ++ip ) {
169 double w =
hiInfo.sumPrimW[pc]/millibarn;
170 double w2 =
hiInfo.sumPrimW2[pc]/pow2(millibarn);
171 infoPtr->setSigma(pc,
hiInfo.NamePrim[pc], N, N, N,
172 w*norm, sqrt(w2*norm)/N, w);
177 infoPtr->setSigma(0,
"sum",
hiInfo.NSave, Nall, Nall,
178 wall*norm, sqrt(w2all*norm)/Nall, wall);
185 void HeavyIons::stat() {
186 bool showPrL = flag(
"Stat:showProcessLevel");
188 bool showErr = flag(
"Stat:showErrors");
189 bool reset = flag(
"Stat:reset");
190 Info & in = *infoPtr;
193 cout <<
"\n *----- HeavyIon Event and Cross Section Statistics ------"
194 <<
"-------------------------------------------------------*\n"
197 <<
" | Subprocess Code | "
198 <<
" Number of events | sigma +- delta |\n"
200 <<
"Tried Selected Accepted | (estimated) (mb) |\n"
203 <<
" |------------------------------------------------------------"
204 <<
"-----------------------------------------------------|\n"
208 vector<int> pc = in.codesHard();
209 for (
int i = 0, N = pc.size(); i < N; ++i ) {
210 cout <<
" | " << left << setw(45) << in.nameProc(pc[i])
211 << right << setw(5) << pc[i] <<
" | "
212 << setw(11) << in.nTried(pc[i]) <<
" "
213 << setw(10) << in.nSelected(pc[i]) <<
" "
214 << setw(10) << in.nAccepted(pc[i]) <<
" | "
215 << scientific << setprecision(3)
216 << setw(11) << in.sigmaGen(pc[i])
217 << setw(11) << in.sigmaErr(pc[i]) <<
" |\n";
219 if ( pc.empty() ) in.setSigma(0,
"sum",
hiInfo.NSave, 0, 0, 0.0, 0.0, 0.0);
223 <<
" | " << left << setw(50) <<
"sum" << right <<
" | " << setw(11)
224 << in.nTried(0) <<
" " << setw(10) << in.nSelected(0) <<
" "
225 << setw(10) << in.nAccepted(0) <<
" | " << scientific
226 << setprecision(3) << setw(11)
227 << in.sigmaGen(0) << setw(11) << in.sigmaErr(0) <<
" |\n";
228 cout <<
" | " << left << setw(50) <<
"(Estimated total cross section)"
229 << right <<
" | " << setw(11)
231 << 0 <<
" | " << scientific << setprecision(3) << setw(11)
233 cout <<
" | " << left << setw(50)
234 <<
"(Estimated non-diffractive cross section)"
235 << right <<
" | " << setw(11)
237 << 0 <<
" | " << scientific << setprecision(3) << setw(11)
242 <<
" *----- End HeavyIon Event and Cross Section Statistics -----"
243 <<
"-----------------------------------------------------*" << endl;
245 if ( reset )
hiInfo = HIInfo();
247 for (
int i = 1, np =
pythia.size(); i < np; ++i )
249 in.errorStatistics();
251 if ( reset ) in.errorReset();
260 int idProj = settings.mode(
"Beams:idA");
261 int idTarg = settings.mode(
"Beams:idB");
262 return ( abs(idProj/100000000) == 10 ||abs(idTarg/100000000) == 10 );
274 : HeavyIons(mainPythiaIn), hasSignal(true),
275 bGenPtr(0), projPtr(0), targPtr(0), collPtr(0), recoilerMode(1), bMode(0) {
276 selectMB = make_shared<ProcessSelectorHook>();
277 selectSASD = make_shared<ProcessSelectorHook>();
296 Angantyr::~Angantyr() {
328 ei.
event = pyt.event;
330 ei.
code = pyt.info.code();
335 ei.
projs[coll->proj] = make_pair(1, ei.
event.size());
336 ei.targs[coll->
targ] = make_pair(2, ei.
event.size());
349 bool print = flag(
"HeavyIon:showInit");
351 int idProj = mode(
"Beams:idA");
352 int idTarg = mode(
"Beams:idB");
353 int idProjP = idProj;
355 int idTargP = idTarg;
357 bool isHIProj = ( abs(idProj/100000000) == 10 );
358 bool isHITarg = ( abs(idTarg/100000000) == 10 );
359 bool isHI = isHIProj || isHITarg || mode(
"HeavyIon:mode") > 1;
361 idProjP = idProj > 0? 2212: -2212;
362 idProjN = idProj > 0? 2112: -2112;
364 if ( abs(idTarg/100000000) == 10 ) {
365 idTargP = idTarg > 0? 2212: -2212;
366 idTargN = idTarg > 0? 2112: -2112;
368 if ( mode(
"HeavyIon:mode") == 1 && !isHI ) {
369 infoPtr->errorMsg(
"Angantyr Info: No heavy ions requested"
370 " - reverting to normal Pythia behavior.");
371 settingsPtr->mode(
"HeavyIon:mode", 0);
375 recoilerMode = mode(
"Angantyr:SDRecoil");
376 bMode = mode(
"Angantyr:impactMode");
378 int frame = mode(
"Beams:frameType");
379 bool dohad = flag(
"HadronLevel:all");
381 infoPtr->errorMsg(
"Angantyr warning: Currently only Beams:frameType "
382 "= 1 or 2 is supported. Assuming 2.");
383 double eAbm = parm(
"Beams:eA");
384 double eBbm = parm(
"Beams:eB");
385 if ( frame == 1 ) eAbm = eBbm = parm(
"Beams:eCM")/2.0;
386 settingsPtr->parm(
"Beams:eA", eAbm);
387 settingsPtr->parm(
"Beams:eB", eBbm);
388 settingsPtr->mode(
"Beams:frameType", 2);
390 settingsPtr->mode(
"Next:numberCount", 0);
391 settingsPtr->mode(
"Next:numberShowLHA", 0);
392 settingsPtr->mode(
"Next:numberShowInfo", 0);
393 settingsPtr->mode(
"Next:numberShowProcess", 0);
394 settingsPtr->mode(
"Next:numberShowEvent", 0);
395 settingsPtr->flag(
"HadronLevel:all",
false);
396 settingsPtr->flag(
"SoftQCD:all",
false);
397 settingsPtr->flag(
"SoftQCD:elastic",
false);
398 settingsPtr->flag(
"SoftQCD:nonDiffractive",
false);
399 settingsPtr->flag(
"SoftQCD:singleDiffractive",
false);
400 settingsPtr->flag(
"SoftQCD:doubleDiffractive",
false);
401 settingsPtr->flag(
"SoftQCD:centralDiffractive",
false);
403 for (
int i =
MBIAS; i <
ALL; ++i ) {
404 pythia[i] =
new Pythia(*settingsPtr, *particleDataPtr,
false);
405 pythia[i]->settings.mode(
"HeavyIon:mode", 1);
409 sigtot.calc(2212, 2212, sqrt(4.0*eAbm*eBbm));
413 pythia[
MBIAS]->settings.mode(
"Beams:idA", idProjP);
414 pythia[
MBIAS]->settings.mode(
"Beams:idB", idTargP);
417 Settings & sdabsopts =
pythia[
SASD]->settings;
418 sdabsopts.flag(
"SoftQCD:singleDiffractive",
true);
425 if ( sdabsopts.mode(
"Angantyr:SASDmode") > 0 ) {
426 double pT0Ref = sdabsopts.parm(
"MultipartonInteractions:pT0Ref");
427 double ecmRef = sdabsopts.parm(
"MultipartonInteractions:ecmRef");
428 double ecmPow = sdabsopts.parm(
"MultipartonInteractions:ecmPow");
429 double ecm = sqrt(4.0*eBbm*eAbm);
430 sdabsopts.parm(
"Beams:eCM", ecm);
431 double pT0 = pT0Ref * pow(ecm / ecmRef, ecmPow);
432 sdabsopts.parm(
"MultipartonInteractions:pT0Ref", pT0);
433 sdabsopts.parm(
"MultipartonInteractions:ecmRef", ecm);
434 sdabsopts.parm(
"MultipartonInteractions:ecmPow", 0.0);
435 sdabsopts.word(
"PDF:PomSet",
"11");
436 if ( sdabsopts.mode(
"Angantyr:SASDmode") == 2 ) {
437 sdabsopts.parm(
"Diffraction:mRefPomP", ecm);
438 double sigND =
sigtot.sigmaND();
439 double mmin = sdabsopts.parm(
"Diffraction:mMinPert");
440 double powp = sdabsopts.parm(
"HIDiffraction:mPowPomP");
441 sdabsopts.parm(
"Diffraction:mPowPomP", powp,
true);
442 if ( powp > 0.0 ) sigND /= ((1.0 - pow(mmin/ecm, powp))/powp);
443 else sigND /= log(ecm/mmin);
444 sdabsopts.parm(
"Diffraction:sigmaRefPomP", sigND,
true);
446 if ( sdabsopts.mode(
"Angantyr:SASDmode") >= 3 ) {
447 sdabsopts.parm(
"Diffraction:mRefPomP", ecm);
448 double sigND =
sigtot.sigmaND();
449 sdabsopts.parm(
"Diffraction:sigmaRefPomP", sigND,
true);
450 sdabsopts.parm(
"Diffraction:mPowPomP", 0.0);
453 sdabsopts.mode(
"Beams:idA", idProjP);
454 sdabsopts.mode(
"Beams:idB", idTargP);
457 pythia[
HADRON]->settings.flag(
"ProcessLevel:all",
false);
458 pythia[
HADRON]->settings.flag(
"PartonLevel:all",
false);
459 pythia[
HADRON]->settings.flag(
"HadronLevel:all", dohad);
463 pythia[
SIGPP]->settings.mode(
"Beams:idA", idProjP);
464 pythia[
SIGPP]->settings.mode(
"Beams:idB", idTargP);
466 pythia[
SIGPN]->settings.mode(
"Beams:idA", idProjP);
467 pythia[
SIGPN]->settings.mode(
"Beams:idB", idTargN);
470 pythia[
SIGNP]->settings.mode(
"Beams:idA", idProjN);
471 pythia[
SIGNP]->settings.mode(
"Beams:idB", idTargP);
473 if ( idProjN && idTargN ) {
474 pythia[
SIGNN]->settings.mode(
"Beams:idA", idProjN);
475 pythia[
SIGNN]->settings.mode(
"Beams:idB", idTargN);
483 projPtr =
new GLISSANDOModel();
484 projPtr->
initPtr(idProj, *settingsPtr, *particleDataPtr, *rndmPtr);
489 targPtr =
new GLISSANDOModel();
490 targPtr->
initPtr(idTarg, *settingsPtr, *particleDataPtr, *rndmPtr);
494 else if ( mode(
"Angantyr:CollisionModel") == 1 )
495 collPtr =
new DoubleStrikman();
496 else if ( mode(
"Angantyr:CollisionModel") == 2 )
497 collPtr =
new DoubleStrikman(1);
498 else if ( mode(
"Angantyr:CollisionModel") == 3 )
499 collPtr =
new BlackSubCollisionModel();
501 collPtr =
new NaiveSubCollisionModel();
503 collPtr->initPtr(*projPtr, *targPtr,
sigtot, *settingsPtr,
505 if ( !collPtr->
init() )
return false;
508 bGenPtr =
HIHooksPtr->impactParameterGenerator();
510 bGenPtr =
new ImpactParameterGenerator();
511 bGenPtr->initPtr(*collPtr, *projPtr, *targPtr, *settingsPtr, *rndmPtr);
513 if ( !projPtr->init() )
return false;
514 if ( !targPtr->init() )
return false;
515 if ( !bGenPtr->
init() )
return false;
520 Redirect red(cout, oss);
521 hasSignal =
init(
SIGPP,
"signal process (pp)", 10);
525 if ( print ) cout <<
" Angantyr Info: No signal process specified. "
526 <<
"Assuming minimum bias." << endl;
530 if ( idTargN )
init(
SIGPN,
"signal process (pn)", 10);
531 if ( idProjN )
init(
SIGNP,
"signal process (np)", 10);
532 if ( idProjN && idTargN )
init(
SIGNN,
"signal process (nn)", 10);
540 init(
SASD,
"secondary absorptive processes as single diffraction.");
544 cout <<
" Angantyr Info: Initializing hadronisation processes." << endl;
546 settingsPtr->flag(
"ProcessLevel:all",
false);
558 bool print = flag(
"HeavyIon:showInit");
559 shared_ptr<InfoGrabber> ihg = make_shared<InfoGrabber>();
560 pythia[sel]->addUserHooksPtr(ihg);
561 if ( print ) cout <<
" Angantyr Info: Initializing " << name <<
"." << endl;
563 info[sel] = ihg->getInfo();
564 if ( n <= 0 )
return true;
565 if ( print ) cout <<
"Generating a few signal events for " << name
566 <<
" to build up statistics" << endl;
567 for (
int i = 0; i < 10; ++i )
pythia[sel]->
next();
579 int pytsel =
SIGPP + coll.nucleons();
585 infoPtr->errorMsg(
"Warning from PyHIa::next: "
586 "Could not setup signal sub collision.");
590 EventInfo Angantyr::getMBIAS(
const SubCollision * coll,
int procid) {
593 if ( bMode > 0 && procid == 101 ) bp = coll->bp;
594 HoldProcess hold(selectMB, procid, bp);
603 EventInfo Angantyr::getSASD(
const SubCollision * coll,
int procid) {
606 if ( bMode > 1 ) bp = coll->bp;
607 HoldProcess hold(selectSASD, procid, bp);
621 bool Angantyr::genAbs(
const multiset<SubCollision> & coll,
622 list<EventInfo> & subevents) {
624 vector<multiset<SubCollision>::const_iterator> abscoll;
626 vector<multiset<SubCollision>::const_iterator> abspart;
628 multiset<EventInfo> ndeve, sigeve;
631 for ( multiset<SubCollision>::iterator cit = coll.begin();
632 cit != coll.end(); ++cit ) {
634 if (!cit->proj->done() && !cit->targ->done() ) {
635 abscoll.push_back(cit);
638 assert( ie.code == 101 );
644 abspart.push_back(cit);
647 if ( abscoll.empty() )
return true;
649 int Nabs = abscoll.size();
650 int Nadd = abspart.size();
653 for (
int i = 0; i < Nabs + Nadd; ++i ) {
655 assert( ie.code == 101 );
659 vector<int> Nii(4, 0);
660 vector<double> w(4, 0.0);
667 for (
int i = 0, N = abscoll.size(); i < N; ++i )
668 ++Nii[abscoll[i]->nucleons()];
669 for (
int i = 0, N = abspart.size(); i < N; ++i )
670 ++Nii[abspart[i]->nucleons()];
681 wsum = Nii[0]*w[0] + Nii[1]*w[1] + Nii[2]*w[2] + Nii[3]*w[3];
682 P1 = 1.0 - pow(1.0 - w[0], Nii[0])*pow(1.0 - w[1], Nii[1])*
683 pow(1.0 - w[2], Nii[2])*pow(1.0 - w[3], Nii[3]);
687 bool noSignal = hasSignal;
692 multiset<EventInfo>::iterator it = ndeve.begin();
694 for (
int i = 0, N = abscoll.size(); i < N; ++i ) {
695 int b = abscoll[i]->nucleons();
697 && ( noSignal || w[b]*(wsum/P1 - 1.0)/(wsum - w[b]) > rndmPtr->flat())
703 subevents.push_back(ei);
704 if ( !setupFullCollision(subevents.back(), *abscoll[i],
709 if ( noSignal )
return false;
721 void Angantyr::addSASD(
const multiset<SubCollision> & coll) {
724 int ntry = mode(
"Angantyr:SDTries");
725 if ( settingsPtr->isMode(
"HI:SDTries") )
726 ntry = mode(
"HI:SDTries");
727 for ( multiset<SubCollision>::iterator cit = coll.begin();
728 cit != coll.end(); ++cit )
730 if ( cit->targ->done() && !cit->proj->done() ) {
732 for (
int itry = 0; itry < ntry; ++itry ) {
740 }
else if ( cit->proj->done() && !cit->targ->done() ) {
742 for (
int itry = 0; itry < ntry; ++itry ) {
758 bool Angantyr::addDD(
const multiset<SubCollision> & coll,
759 list<EventInfo> & subevents) {
761 for ( multiset<SubCollision>::iterator cit = coll.begin();
762 cit != coll.end(); ++cit )
764 !cit->proj->done() && !cit->targ->done() ) {
765 subevents.push_back(getDD(*cit));
766 if ( !setupFullCollision(subevents.back(), *cit,
777 bool Angantyr::addSD(
const multiset<SubCollision> & coll,
778 list<EventInfo> & subevents) {
780 for ( multiset<SubCollision>::iterator cit = coll.begin();
781 cit != coll.end(); ++cit )
782 if ( !cit->proj->done() && !cit->targ->done() ) {
784 subevents.push_back(getSDP(*cit));
785 if ( !setupFullCollision(subevents.back(), *cit,
790 subevents.push_back(getSDT(*cit));
791 if ( !setupFullCollision(subevents.back(), *cit,
804 void Angantyr::addSDsecond(
const multiset<SubCollision> & coll) {
806 int ntry = mode(
"Angantyr:SDTries");
807 if ( settingsPtr->isMode(
"HI:SDTries") ) ntry = mode(
"HI:SDTries");
808 for ( multiset<SubCollision>::iterator cit = coll.begin();
809 cit != coll.end(); ++cit ) {
810 if ( !cit->proj->done() &&
814 for (
int itry = 0; itry < ntry; ++itry ) {
823 if ( !cit->targ->done() &&
827 for (
int itry = 0; itry < ntry; ++itry ) {
843 bool Angantyr::addCD(
const multiset<SubCollision> & coll,
844 list<EventInfo> & subevents) {
846 for ( multiset<SubCollision>::iterator cit = coll.begin();
847 cit != coll.end(); ++cit )
849 !cit->proj->done() && !cit->targ->done() ) {
850 subevents.push_back(getCD(*cit));
851 if ( !setupFullCollision(subevents.back(), *cit,
863 void Angantyr::addCDsecond(
const multiset<SubCollision> & coll) {
865 for ( multiset<SubCollision>::iterator cit = coll.begin();
866 cit != coll.end(); ++cit ) {
888 bool Angantyr::addEL(
const multiset<SubCollision> & coll,
889 list<EventInfo> & subevents) {
891 for ( multiset<SubCollision>::iterator cit = coll.begin();
892 cit != coll.end(); ++cit )
894 !cit->proj->done() && !cit->targ->done() ) {
895 subevents.push_back(getEl(*cit));
896 if ( !setupFullCollision(subevents.back(), *cit,
907 void Angantyr::addELsecond(
const multiset<SubCollision> & coll) {
909 for ( multiset<SubCollision>::iterator cit = coll.begin();
910 cit != coll.end(); ++cit ) {
938 double ymax = ei.event[1].y();
939 Vec4 bmax = ei.coll->proj->bPos();
940 double ymin = ei.event[2].y();
941 Vec4 bmin = ei.coll->targ->bPos();
942 for (
int i = 0, N = ei.event.size(); i < N; ++i ) {
943 Vec4 shift = bmin + (bmax - bmin)*(ei.event[i].y() - ymin)/(ymax - ymin);
944 ei.event[i].vProdAdd( shift * FM2MM);
954 setupFullCollision(
EventInfo & ei,
const SubCollision & coll,
956 if ( !ei.ok )
return false;
957 coll.proj->select(ei, ptype);
958 coll.targ->select(ei, ttype);
961 ei.projs[coll.proj] = make_pair(1, ei.event.size());
963 ei.targs[coll.targ] = make_pair(2, ei.event.size());
965 ei.event[1].status(-203);
966 ei.event[1].mother1(1);
967 ei.event[1].mother2(0);
968 ei.event[2].status(-203);
969 ei.event[2].mother1(2);
970 ei.event[2].mother2(0);
971 return fixIsoSpin(ei);
978 int Angantyr::getBeam(
Event & ev,
int i) {
979 if (
int mom = ev[i].mother1() ) {
980 if ( ev[mom].status() != -203 && ev[mom].mother1() < mom )
981 return getBeam(ev, mom);
996 bool Angantyr::fixIsoSpin(
EventInfo & ei) {
1001 int pshift = 0, tshift = 0;
1002 if ( ei.event[1].id() == 2212 && ei.coll->proj->id() == 2112 )
1004 if ( ei.event[1].id() == -2212 && ei.coll->proj->id() == -2112 )
1007 ei.event[1].id(pshift*2112);
1008 if ( ei.event[2].id() == 2212 && ei.coll->targ->id() == 2112 )
1010 if ( ei.event[2].id() == -2212 && ei.coll->targ->id() == -2112 )
1013 ei.event[2].id(tshift*2112);
1015 if ( !pshift && !tshift )
return true;
1018 for (
int i = ei.event.size() - 1; i > 2 && ( pshift || tshift ); --i ) {
1019 if ( pshift && ( isRemnant(ei, i) || ei.event[i].status() == 14 )
1020 && getBeam(ei.event, i) == 1 ) {
1022 if ( ei.event[i].id() == 2*pshift ) newid = 1*pshift;
1023 if ( ei.event[i].id() == 2101*pshift ) newid = 1103*pshift;
1024 if ( ei.event[i].id() == 2103*pshift ) newid = 1103*pshift;
1025 if ( ei.event[i].id() == 2203*pshift ) newid = 2103*pshift;
1026 if ( ei.event[i].id() == 2212*pshift ) newid = 2112*pshift;
1028 ei.event[i].id(newid);
1033 if ( tshift && ( isRemnant(ei, i) || ei.event[i].status() == 14 )
1034 && getBeam(ei.event, i) == 2 ) {
1036 if ( ei.event[i].id() == 2*tshift ) newid = 1*tshift;
1037 if ( ei.event[i].id() == 2101*tshift ) newid = 1103*tshift;
1038 if ( ei.event[i].id() == 2103*tshift ) newid = 1103*tshift;
1039 if ( ei.event[i].id() == 2203*tshift ) newid = 2103*tshift;
1040 if ( ei.event[i].id() == 2212*tshift ) newid = 2112*tshift;
1042 ei.event[i].id(newid);
1049 if ( !pshift && !tshift )
return true;
1057 for (
int i = ei.event.size() - 1; i > 2 && ( pshift || tshift ); --i ) {
1058 if ( pshift && ei.event[i].isFinal() && ei.event[i].id() == 2*pshift) {
1059 if ( ei.event[i].y() > yselp ) {
1061 yselp = ei.event[i].y();
1064 if ( tshift && ei.event[i].isFinal() && ei.event[i].id() == 2*tshift) {
1065 if ( ei.event[i].y() < yselt ) {
1067 yselt = ei.event[i].y();
1072 ei.event[qselp].id(1*pshift);
1076 ei.event[qselt].id(1*tshift);
1080 return !pshift && !tshift;
1089 vector<int> Angantyr::
1090 findRecoilers(
const Event & e,
bool tside,
int beam,
int end,
1091 const Vec4 & pdiff,
const Vec4 & pbeam) {
1093 multimap<double,int> ordered;
1094 double mtd2 = pdiff.m2Calc() + pdiff.pT2();
1095 int dir = tside? -1: 1;
1096 double ymax = -log(pdiff.pNeg());
1097 if ( tside ) ymax = -log(pdiff.pPos());
1098 for (
int i = beam, N = end; i < N; ++i )
1099 if ( e[i].status() > 0 )
1100 ordered.insert(make_pair(e[i].y()*dir, i));
1102 double pzfree2 = 0.0;
1103 multimap<double,int>::iterator it = ordered.begin();
1109 while ( it != ordered.end() ) {
1110 if ( it->first > ymax )
break;
1111 int i = (*it++).second;
1112 Vec4 test = prec + e[i].p();
1113 double mtr2 = test.m2Calc() + test.pT2();
1114 double S = (pbeam + test).m2Calc();
1115 double pz2 = 0.25*(pow2(S - mtr2 - mtd2) - 4.0*mtr2*mtd2)/S;
1116 if ( pz2 < pzfree2 ) {
1143 return HIHooksPtr->addNucleonExcitation(ei, sub, colConnect);
1145 typedef map<Nucleon *, pair<int, int> >::iterator NucPos;
1147 NucPos recnuc = ei.projs.find(sub.coll->proj);
1148 if ( recnuc != ei.projs.end() ) tside =
true;
1149 NucPos rectarg = ei.targs.find(sub.coll->targ);
1150 if ( rectarg != ei.targs.end() ) {
1151 if ( tside ) infoPtr->errorMsg(
"Warning from Angantyr::"
1152 "addNucleonExcitation: Nucleon already added.");
1158 int olddiff = tside? 4: 3;
1159 int beam = tside? 2: 1;
1160 int recbeam = recnuc->second.first;
1161 int recend = recnuc->second.second;
1162 Vec4 pbeam = sub.event[beam].p();
1163 Vec4 pdiff = sub.event[olddiff].p();
1164 if ( sub.code == 106 ) pdiff += sub.event[5].p();
1168 rec =
HIHooksPtr->findRecoilers(ei.event, tside, recbeam, recend,
1170 else if ( recoilerMode == 2 )
1171 rec = findRecoilers(ei.event, tside, recbeam, recend, pdiff, pbeam);
1173 if ( tside && ei.code == 104 && ei.event[4].status() > 0 )
1175 else if ( !tside && ei.code == 103 && ei.event[3].status() > 0 )
1177 else if ( tside && ei.event[3].status() > 0 &&
1178 ( ei.code == 102 || ei.code == 106 ) )
1180 else if ( !tside && ei.event[4].status() > 0 &&
1181 ( ei.code == 102 || ei.code == 106 ) )
1184 for (
int i = recbeam, N = recend; i < N; ++i )
1185 if ( isRemnant(ei, i) && getBeam(ei.event, i) == recbeam )
1188 if ( rec.empty() )
return false;
1189 for (
int i = 0, N = rec.size(); i < N; ++i ) prec += ei.event[rec[i]].p();
1192 pair<RotBstMatrix,RotBstMatrix> R12;
1193 if ( !
getTransforms(prec, pdiff, pbeam, R12, ei.code, sub.code) )
1197 for (
int i = 0, N = rec.size(); i < N; ++i )
1198 ei.event[rec[i]].rotbst(R12.first);
1202 int newbeam = ei.event.size();
1203 ei.event.append(sub.event[beam]);
1204 ei.event.back().status(-203);
1205 ei.event.back().mother1(beam);
1206 ei.event.back().mother2(0);
1207 ei.event.back().daughter1(ei.event.size());
1208 int newdiff = ei.event.size();
1210 ei.event.append(sub.event[olddiff]);
1211 ei.event.back().rotbst(R12.second);
1212 ei.event.back().mother1(newbeam);
1213 ei.event.back().mother2(0);
1214 if ( sub.code == 102 ) {
1216 ei.targs[sub.coll->targ] = make_pair(newbeam, ei.event.size());
1218 ei.projs[sub.coll->proj] = make_pair(newbeam, ei.event.size());
1222 int idoff = tside? newdiff - olddiff: newdiff - olddiff - 1;
1223 if ( sub.code == 106 ) {
1227 idoff = newdiff - 5;
1228 ei.event.append(sub.event[5]);
1229 ei.event.back().rotbst(R12.second);
1230 ei.event.back().mother1(newbeam);
1231 ei.event.back().mother2(0);
1233 ei.event.back().daughter1(sub.event[olddiff].daughter1() + idoff);
1234 ei.event.back().daughter2(sub.event[olddiff].daughter2() + idoff);
1235 int coloff = ei.event.lastColTag();
1237 ei.event[0].p( ei.event[0].p() + pbeam );
1238 ei.event[0].m( ei.event[0].mCalc() );
1239 for (
int i = nextpos; i < sub.event.size(); ++i) {
1240 Particle temp = sub.event[i];
1243 if ( temp.mother1() == olddiff ) temp.mother1(newdiff);
1244 else if ( temp.mother1() > 0 ) temp.mother1(temp.mother1() + idoff );
1245 if ( temp.mother2() == olddiff ) temp.mother2(newdiff);
1246 else if ( temp.mother2() > 0 ) temp.mother2(temp.mother2() + idoff );
1247 if ( temp.daughter1() > 0 ) temp.daughter1( temp.daughter1() + idoff );
1248 if ( temp.daughter2() > 0 ) temp.daughter2( temp.daughter2() + idoff );
1249 if ( temp.col() > 0 ) temp.col( temp.col() + coloff );
1250 if ( temp.acol() > 0 ) temp.acol( temp.acol() + coloff );
1251 temp.rotbst(R12.second);
1253 ei.event.append( temp );
1256 addJunctions(ei.event, sub.event, coloff);
1259 ei.targs[sub.coll->targ] = make_pair(newbeam, ei.event.size());
1261 ei.projs[sub.coll->proj] = make_pair(newbeam, ei.event.size());
1273 pair<RotBstMatrix,RotBstMatrix> & R12,
1274 int code1,
int code2) {
1280 Ri.toCMframe(pbeam, prec);
1289 if ( pd1.pT() >= abs(pr2.pz()) ) {
1293 double the = asin(pd1.pT()/abs(pr2.pz()));
1295 R1.rot(the, pd1.phi());
1299 double S = (prec + pbeam).m2Calc();
1300 double mtr2 = pr2.pT2() + pr2.m2Calc();
1301 double mtd2 = pd1.pT2() + pd1.m2Calc();
1302 if ( sqrt(S) <= sqrt(mtr2) + sqrt(mtd2) ) {
1306 double z2 = 0.25*(mtr2*mtr2 + (mtd2 - S)*(mtd2 - S) - 2.0*mtr2*(mtd2 + S))/S;
1311 double z = sqrt(z2);
1312 double ppo2 = pow2(pr2.pNeg());
1313 double ppn2 = pow2(z + sqrt(z2 + mtr2));
1314 R1.bst(0.0, 0.0, -(ppn2 - ppo2)/(ppn2 + ppo2));
1316 ppo2 = pow2(pd1.pPos());
1317 ppn2 = pow2(z + sqrt(z2 + mtd2));
1319 R2.bst(0.0, 0.0, (ppn2 - ppo2)/(ppn2 + ppo2));
1325 RotBstMatrix Rf = Ri;
1333 R12.first = R12.second = Ri;
1334 R12.first.rotbst(R1);
1335 R12.second.rotbst(R2);
1336 R12.first.rotbst(Rf);
1337 R12.second.rotbst(Rf);
1338 prec.rotbst(R12.first);
1339 pdiff.rotbst(R12.second);
1353 int idoff = evnt.size() - 1;
1354 int coloff = evnt.lastColTag();
1356 for (
int i = 1; i < sub.size(); ++i) {
1357 Particle temp = sub[i];
1360 if ( temp.status() == -203 )
1363 if ( temp.mother1() > 0 ) temp.mother1(temp.mother1() + idoff );
1364 if ( temp.mother2() > 0 ) temp.mother2( temp.mother2() + idoff );
1366 if ( temp.daughter1() > 0 ) temp.daughter1( temp.daughter1() + idoff );
1367 if ( temp.daughter2() > 0 ) temp.daughter2( temp.daughter2() + idoff );
1368 if ( temp.col() > 0 ) temp.col( temp.col() + coloff );
1369 if ( temp.acol() > 0 ) temp.acol( temp.acol() + coloff );
1371 evnt.append( temp );
1374 addJunctions(evnt, sub, coloff);
1378 void Angantyr::addJunctions(
Event & ev,
Event & addev,
int coloff) {
1383 for (
int i = 0; i < addev.sizeJunction(); ++i) {
1384 tempJ = addev.getJunction(i);
1387 for (
int j = 0; j < 3; ++j) {
1388 begCol = tempJ.col(j);
1389 endCol = tempJ.endCol(j);
1390 if (begCol > 0) begCol += coloff;
1391 if (endCol > 0) endCol += coloff;
1392 tempJ.cols( j, begCol, endCol);
1395 ev.appendJunction( tempJ );
1407 double bp =
pythia[
SASD]->parm(
"Angantyr:SDTestB");
1410 if ( !ei.ok )
return false;
1417 if ( !
pythia[
HADRON]->forceHadronLevel(
false) )
return false;
1427 bool Angantyr::buildEvent(list<EventInfo> & subevents,
1428 const vector<Nucleon> & proj,
1429 const vector<Nucleon> & targ) {
1432 etmp.append(projPtr->produceIon(
false));
1433 etmp.append(targPtr->produceIon(
true));
1434 etmp[0].p(etmp[1].p() + etmp[2].p());
1435 etmp[0].m(etmp[0].mCalc());
1440 for ( list<EventInfo>::iterator sit = subevents.begin();
1441 sit != subevents.end(); ++sit ) {
1442 if ( sit->code >= 101 && sit->code <= 106 )
continue;
1444 hiInfo.select(sit->info);
1445 hiInfo.addSubCollision(*sit->coll);
1446 subevents.erase(sit);
1451 infoPtr->errorMsg(
"Warning from Angantyr::next:"
1452 " Failed to generate signal event.");
1456 hiInfo.select(subevents.begin()->info);
1459 for ( list<EventInfo>::iterator sit = subevents.begin();
1460 sit != subevents.end(); ++sit ) {
1462 hiInfo.addSubCollision(*sit->coll);
1477 const vector<Nucleon> & targ) {
1482 for (
int i = 0, N = proj.size(); i< N; ++i ) {
1483 if ( proj[i].event() )
hiInfo.addProjectileNucleon(proj[i]);
1486 double m =
pythia[
HADRON]->particleData.m0(proj[i].
id());
1487 double pz = sqrt(max(e*e - m*m, 0.0));
1488 if ( proj[i].
id() == 2212 ) {
1490 ppsum += Vec4(0.0, 0.0, pz, e);
1491 }
else if ( proj[i].
id() == 2112 ) {
1493 ppsum += Vec4(0.0, 0.0, pz, e);
1495 etmp.append(proj[i].
id(), 14, 1, 0, 0, 0, 0, 0, 0.0, 0.0, pz, e, m);
1501 for (
int i = 0, N = targ.size(); i< N; ++i ) {
1502 if ( targ[i].event() )
hiInfo.addTargetNucleon(targ[i]);
1505 double m =
pythia[
HADRON]->particleData.m0(targ[i].
id());
1506 double pz = -sqrt(max(e*e - m*m, 0.0));
1507 if ( targ[i].
id() == 2212 ) {
1509 tpsum += Vec4(0.0, 0.0, pz, e);
1510 }
else if ( targ[i].
id() == 2112 ) {
1512 tpsum += Vec4(0.0, 0.0, pz, e);
1514 etmp.append(targ[i].
id(), 14, 2, 0, 0, 0, 0, 0, 0.0, 0.0, pz, e, m);
1518 Vec4 ptot = etmp[0].p();
1519 for (
int i = 0, N = etmp.size(); i < N; ++i )
1520 if ( etmp[i].status() > 0 ) ptot -= etmp[i].p();
1522 if ( npp + nnp +npt + nnt == 0 )
return true;
1525 if ( npp + nnp > 1 ) {
1526 idp = 1000000009 + 10000*npp + 10*(nnp + npp);
1527 pdt.addParticle(idp,
"NucRem", 0, 3*npp, 0, ppsum.mCalc());
1528 pdt.particleDataEntryPtr(idp)->setHasChanged(
false);
1530 else if ( npp == 1 ) idp = 2212;
1531 else if ( nnp == 1 ) idp = 2112;
1533 if ( npt + nnt > 1 ) {
1534 idt = 1000000009 + 10000*npt + 10*(nnt + npt);
1535 pdt.addParticle(idt,
"NucRem", 0, 3*npt, 0, tpsum.mCalc());
1536 pdt.particleDataEntryPtr(idt)->setHasChanged(
false);
1538 else if ( npt == 1 ) idt = 2212;
1539 else if ( nnt == 1 ) idt = 2112;
1541 if ( npp + nnp > npt + nnt ) {
1542 if ( npt + nnt > 0 ) {
1543 etmp.append(idt, 14, 2, 0, 0, 0, 0, 0, tpsum, tpsum.mCalc());
1546 etmp.append(idp, 14, 1, 0, 0, 0, 0, 0, ptot, ptot.mCalc());
1548 if ( npp + nnp > 0 ) {
1549 etmp.append(idp, 14, 1, 0, 0, 0, 0, 0, ppsum, ppsum.mCalc());
1552 etmp.append(idt, 14, 2, 0, 0, 0, 0, 0, ptot, ptot.mCalc());
1563 if ( flag(
"Angantyr:SDTest") )
return nextSASD(104);
1573 double bweight = 0.0;
1574 Vec4 bvec = bGenPtr->
generate(bweight);
1576 subColls = collPtr->
getCollisions(projectile, target, bvec, T);
1577 hiInfo.addAttempt(T, bvec.pT(), bweight);
1578 hiInfo.subCollisionsPtr(&subColls);
1579 if ( flag(
"Angantyr:GlauberOnly") )
return true;
1580 if ( subColls.empty() )
continue;
1583 list<EventInfo> subevents;
1585 if ( !genAbs(subColls, subevents) ) {
1586 infoPtr->errorMsg(
"Warning from PyHIia::next: "
1587 "Could not setup signal or ND collisions.");
1590 if ( hasSignal && subevents.empty() )
continue;
1597 if ( !addDD(subColls, subevents) ) {
1598 infoPtr->errorMsg(
"Warning from PyHIia::next:"
1599 " Could not setup DD sub collision.");
1604 if ( !addSD(subColls, subevents) ) {
1605 infoPtr->errorMsg(
"Warning from PyHIia::next:"
1606 " Could not setup SD sub collision.");
1611 addSDsecond(subColls);
1614 if ( !addCD(subColls, subevents) ) {
1615 infoPtr->errorMsg(
"Warning from PyHIia::next:"
1616 " Could not setup CD sub collisions.");
1621 addCDsecond(subColls);
1624 if ( !addEL(subColls, subevents) ) {
1625 infoPtr->errorMsg(
"Warning from PyHIia::next:"
1626 " Could not setup elastic sub collisions.");
1631 addELsecond(subColls);
1634 if ( subevents.empty() )
continue;
1636 if ( !buildEvent(subevents, projectile, target) )
continue;
1643 if ( !
pythia[
HADRON]->forceHadronLevel(
false) )
continue;
1656 infoPtr->errorMsg(
"Abort from Angantyr::next: Too many "
1657 "attempts to generate a working impact parameter point. "
1658 "Consider reducing HeavyIon:bWidth.");
static bool getTransforms(Vec4 p1, Vec4 p2, const Vec4 &p1p, pair< RotBstMatrix, RotBstMatrix > &R12, int, int)
The nucleon is absorptively wounded.
This is an absorptive (non-diffractive) collision.
Both excited but with central diffraction.
virtual bool init()
Virtual init method.
Both projectile and target are diffractively excited.
Optional object for signal processes (nn).
virtual bool next()
Produce a collision involving heavy ions.
virtual bool hasProjectileModel() const
A suser-supplied NucleusModel for the projectile and target.
bool addNucleonExcitation(EventInfo &orig, EventInfo &add, bool colConnect=false)
int code
The code for the subprocess.
void initPtr(int idIn, Settings &settingsIn, ParticleData &particleDataIn, Rndm &rndIn)
Init method.
double avNDB() const
Return the average non-diffractive impact parameter.
double sigmaNDErr() const
The estimated statistical error on sigmaND().
static void addSpecialSettings(Settings &settings)
EventInfo getSignal(const SubCollision &coll)
Generate events from the internal Pythia oblects;.
double ordering
The ordering variable of this event.
virtual bool canFixIsoSpin() const
bool nextSASD(int proc)
Generate a single diffractive.
Optional object for signal processes (pp).
PythiaObject
Enumerate the different internal Pythia objects.
map< Nucleon *, pair< int, int > > projs
virtual bool canFindRecoilers() const
virtual bool hasImpactParameterGenerator() const
A user-supplied impact parameter generator.
bool canAddNucleonExcitation() const
Event event
The Event and info objects.
EventInfo mkEventInfo(Pythia &pyt, const SubCollision *coll=0)
Setup an EventInfo object from a Pythia instance.
double sigND() const
The non-diffractive (absorptive) cross section.
void failedExcitation()
Register a failed nucleon excitation.
virtual bool canShiftEvent() const
A user-supplied method for shifting the event in impact parameter space.
virtual multiset< SubCollision > getCollisions(vector< Nucleon > &proj, vector< Nucleon > &targ, const Vec4 &bvec, double &T)=0
Nucleon * targ
The target nucleon.
vector< Pythia * > pythia
void clearProcessLevel(Pythia &pyt)
This is an elastic scattering.
The projectile is diffractively excited.
virtual vector< Nucleon > generate() const =0
The nucleon is elastically scattered.
Single diffractive as one side of non-diffractive.
void sumUpMessages(Info &in, string tag, const Info &other)
virtual bool hasEventOrdering() const
A user-supplied ordering of events in (inverse) hardness.
virtual bool hasSubCollisionModel()
static void setupSpecials(Settings &settings, string match)
Duplicate setting on the form match: to settings on the form HImatch:
Optional object for signal processes (pn).
virtual bool init()
Initialize Angantyr.
virtual void init(int idProjIn, int idTargIn)
Initialize this user hook.
bool ok
Is the event properly generated?
Optional object for signal processes (np).
The target is diffractively excited.
const SubCollision * coll
The associated SubCollision object.
double sigmaTot() const
The Monte Carlo integrated total cross section in the current run.
Angantyr(Pythia &mainPythiaIn)
The nucleon is diffractively wounded.
long nAttempts() const
The number of attempted impact parameter points.
bool setUserHooksPtr(PythiaObject sel, UserHooks *userHooksPtrIn)
Set UserHooks for specific (or ALL) internal Pythia objects.
bool addNucleusRemnants(const vector< Nucleon > &proj, const vector< Nucleon > &targ)
virtual Vec4 generate(double &weight) const
double sigmaTotErr() const
The estimated statistical error on sigmaTot().
Status
Enum for specifying the status of a nucleon.
vector< string > pythiaNames
The names associated with the secondary pythia objects.
void addSubEvent(Event &evnt, Event &sub)
Add a sub-event to the final event record.
virtual bool canForceHadronLevel() const
A user supplied wrapper around the Pythia::forceHadronLevel()
double weight() const
The weight for this collision.
static bool isHeavyIon(Settings &settings)
virtual bool init()
Virtual init method.