79 const G4Fragment G4CollisionOutput::emptyFragment;
83 : verboseLevel(0), eex_rest(0), on_shell(false) {
85 G4cout <<
" >>> G4CollisionOutput::G4CollisionOutput" <<
G4endl;
92 verboseLevel = right.verboseLevel;
93 outgoingParticles = right.outgoingParticles;
94 outgoingNuclei = right.outgoingNuclei;
95 recoilFragments = right.recoilFragments;
96 eex_rest = right.eex_rest;
97 on_shell = right.on_shell;
103 outgoingNuclei.clear();
104 outgoingParticles.clear();
105 recoilFragments.clear();
115 ? recoilFragments[index] : emptyFragment);
124 recoilFragments = right.recoilFragments;
133 outgoingParticles.insert(outgoingParticles.end(),
134 particles.begin(), particles.end());
138 outgoingNuclei.insert(outgoingNuclei.end(), nuclea.begin(), nuclea.end());
148 for (
unsigned i=0; i<cparticles.size(); i++)
155 if (!rproducts)
return;
158 G4cout <<
" >>> G4CollisionOutput::addOutgoingParticles(G4RPVector)"
162 G4ReactionProductVector::const_iterator j;
163 for (j=rproducts->begin(); j!=rproducts->end(); ++j) {
173 <<
"), momentum " << mom <<
" GeV" <<
G4endl;
181 if (verboseLevel>1)
G4cout << outgoingParticles.back() <<
G4endl;
187 if (verboseLevel>1)
G4cout << outgoingNuclei.back() <<
G4endl;
197 outgoingParticles.erase(outgoingParticles.begin()+(size_t)index);
202 outgoingNuclei.erase(outgoingNuclei.begin()+(size_t)index);
209 std::find(outgoingParticles.begin(), outgoingParticles.end(), particle);
210 if (pos != outgoingParticles.end()) outgoingParticles.erase(pos);
215 std::find(outgoingNuclei.begin(), outgoingNuclei.end(),
nuclei);
216 if (pos != outgoingNuclei.end()) outgoingNuclei.erase(pos);
222 if (index < 0) recoilFragments.clear();
224 recoilFragments.erase(recoilFragments.begin()+(size_t)index);
231 if (verboseLevel > 1)
232 G4cout <<
" >>> G4CollisionOutput::getTotalOutputMomentum" <<
G4endl;
237 tot_mom += outgoingParticles[i].getMomentum();
240 tot_mom += outgoingNuclei[i].getMomentum();
243 tot_mom += recoilFragments[i].GetMomentum()/
GeV;
250 if (verboseLevel > 1)
251 G4cout <<
" >>> G4CollisionOutput::getTotalCharge" <<
G4endl;
256 charge +=
G4int(outgoingParticles[i].getCharge());
259 charge +=
G4int(outgoingNuclei[i].getCharge());
262 charge += recoilFragments[i].GetZ_asInt();
269 if (verboseLevel > 1)
270 G4cout <<
" >>> G4CollisionOutput::getTotalBaryonNumber" <<
G4endl;
275 baryon += outgoingParticles[i].baryon();
278 baryon +=
G4int(outgoingNuclei[i].getA());
281 baryon += recoilFragments[i].GetA_asInt();
288 if (verboseLevel > 1)
289 G4cout <<
" >>> G4CollisionOutput::getTotalStrangeness" <<
G4endl;
294 strange += outgoingParticles[i].getStrangeness();
302 os <<
" Output: " <<
G4endl
307 os << outgoingParticles[i] << G4endl;
311 os << outgoingNuclei[i] << G4endl;
313 os << recoilFragments[i] << G4endl;
320 if (verboseLevel > 1)
321 G4cout <<
" >>> G4CollisionOutput::boostToLabFrame" <<
G4endl;
324 for(; ipart != outgoingParticles.end(); ipart++) {
328 std::sort(outgoingParticles.begin(), outgoingParticles.end(),
332 for (; inuc != outgoingNuclei.end(); inuc++) {
339 for (; ifrag != recoilFragments.end(); ifrag++) {
340 fmom = ifrag->GetMomentum() /
GeV;
350 mom = convertor.
rotate(mom);
359 if (verboseLevel > 1)
360 G4cout <<
" >>> G4CollisionOutput::rotateEvent" <<
G4endl;
363 for(; ipart != outgoingParticles.end(); ipart++)
364 ipart->setMomentum(ipart->getMomentum()*=rotate);
367 for (; inuc != outgoingNuclei.end(); inuc++)
368 inuc->setMomentum(inuc->getMomentum()*=rotate);
371 for (; ifrag != recoilFragments.end(); ifrag++) {
373 ifrag->SetMomentum(mom*=rotate);
380 if (verboseLevel > 1)
381 G4cout <<
" >>> G4CollisionOutput::trivialize" <<
G4endl;
385 if (
G4InuclNuclei* nuclei_target = dynamic_cast<G4InuclNuclei*>(target)) {
386 outgoingNuclei.push_back(*nuclei_target);
390 outgoingParticles.push_back(*particle);
393 if (
G4InuclNuclei* nuclei_bullet = dynamic_cast<G4InuclNuclei*>(bullet)) {
394 outgoingNuclei.push_back(*nuclei_bullet);
398 outgoingParticles.push_back(*particle);
405 if (verboseLevel > 1)
406 G4cout <<
" >>> G4CollisionOutput::setOnShell" <<
G4endl;
415 if(verboseLevel > 2){
416 G4cout <<
" bullet momentum = " << ini_mom.
e() <<
", "<< ini_mom.
x() <<
", "<< ini_mom.
y()<<
", "<< ini_mom.
z()<<
G4endl;
417 G4cout <<
" target momentum = " << momt.
e()<<
", "<< momt.
x()<<
", "<< momt.
y()<<
", "<< momt.
z()<<
G4endl;
418 G4cout <<
" Fstate momentum = " << out_mom.
e()<<
", "<< out_mom.
x()<<
", "<< out_mom.
y()<<
", "<< out_mom.
z()<<
G4endl;
423 mom_non_cons = ini_mom - out_mom;
429 if(verboseLevel > 2) {
431 G4cout <<
" momentum non conservation: " << G4endl
432 <<
" e " << enc <<
" p " << pnc << G4endl
433 <<
" remaining exitation " << eex_rest <<
G4endl;
436 if (std::fabs(enc) <= accuracy && pnc <= accuracy) {
444 if (verboseLevel > 2)
G4cout <<
" re-balancing four-momenta" <<
G4endl;
453 for (
G4int ip=npart-1; ip>=0; ip--) {
454 if (outgoingParticles[ip].getKineticEnergy()+enc > 0.) {
455 last_mom = outgoingParticles[ip].getMomentum();
456 last_mom += mom_non_cons;
457 outgoingParticles[ip].setMomentum(last_mom);
461 }
else if (nnuc > 0) {
462 for (
G4int in=nnuc-1; in>=0; in--) {
463 if (outgoingNuclei[in].getKineticEnergy()+enc > 0.) {
464 last_mom = outgoingNuclei[in].getMomentum();
465 last_mom += mom_non_cons;
466 outgoingNuclei[in].setMomentum(last_mom);
470 }
else if (nfrag > 0) {
471 for (
G4int ifr=nfrag-1; ifr>=0; ifr--) {
473 last_mom = recoilFragments[ifr].GetMomentum()/
GeV;
474 if ((last_mom.
e()-last_mom.
m())+enc > 0.) {
475 last_mom += mom_non_cons;
476 recoilFragments[ifr].SetMomentum(last_mom*
GeV);
484 mom_non_cons = ini_mom - out_mom;
485 pnc = mom_non_cons.
rho();
486 enc = mom_non_cons.
e();
488 if(verboseLevel > 2){
490 G4cout <<
" momentum non conservation after (1): " << G4endl
491 <<
" e " << enc <<
" p " << pnc <<
G4endl;
495 G4bool need_hard_tuning =
true;
499 for (
G4int i=0; i < nfrag; i++) {
500 G4double eex = recoilFragments[0].GetExcitationEnergy();
501 if (eex > 0.0 && eex + encMeV >= 0.0) {
508 need_hard_tuning =
false;
512 }
else if (nnuc > 0) {
513 for (
G4int i=0; i < nnuc; i++) {
514 G4double eex = outgoingNuclei[i].getExitationEnergy();
515 if (eex > 0.0 && eex + encMeV >= 0.0) {
516 outgoingNuclei[i].setExitationEnergy(eex+encMeV);
517 need_hard_tuning =
false;
521 if (need_hard_tuning && encMeV > 0.) {
522 outgoingNuclei[0].setExitationEnergy(encMeV);
523 need_hard_tuning =
false;
527 if (!need_hard_tuning) {
533 if (verboseLevel > 2)
534 G4cout <<
" trying hard (particle-pair) tuning" <<
G4endl;
564 std::pair<std::pair<G4int, G4int>,
G4int> tune_par = selectPairToTune(enc);
565 std::pair<G4int, G4int> tune_particles = tune_par.first;
566 G4int mom_ind = tune_par.second;
569 (tune_particles.first >= 0 && tune_particles.second >= 0 &&
572 if (!tuning_possible) {
573 if (verboseLevel > 2)
G4cout <<
" tuning impossible " <<
G4endl;
577 if(verboseLevel > 2) {
578 G4cout <<
" p1 " << tune_particles.first <<
" p2 " << tune_particles.second
579 <<
" ind " << mom_ind <<
G4endl;
582 G4LorentzVector mom1 = outgoingParticles[tune_particles.first].getMomentum();
583 G4LorentzVector mom2 = outgoingParticles[tune_particles.second].getMomentum();
585 if (tuneSelectedPair(mom1, mom2, mom_ind)) {
586 outgoingParticles[tune_particles.first ].setMomentum(mom1);
587 outgoingParticles[tune_particles.second].setMomentum(mom2);
594 mom_non_cons = ini_mom - out_mom;
595 pnc = mom_non_cons.
rho();
596 enc = mom_non_cons.e();
598 on_shell = (std::fabs(enc) < accuracy || pnc < accuracy);
600 if(verboseLevel > 2) {
601 G4cout <<
" momentum non conservation tuning: " << G4endl
602 <<
" e " << enc <<
" p " << pnc
603 << (on_shell?
" success":
" FAILURE") << G4endl;
614 eex_rest += outgoingNuclei[i].getExitationEnergyInGeV();
616 eex_rest += recoilFragments[i].GetExcitationEnergy() /
GeV;
620 std::pair<std::pair<G4int, G4int>,
G4int>
621 G4CollisionOutput::selectPairToTune(
G4double de)
const {
622 if (verboseLevel > 2)
623 G4cout <<
" >>> G4CollisionOutput::selectPairToTune" <<
G4endl;
625 std::pair<G4int, G4int> tup(-1, -1);
627 std::pair<std::pair<G4int, G4int>,
G4int> tuner(tup, i3);
629 if (outgoingParticles.size() < 2)
return tuner;
634 G4double pcut = 0.3 * std::sqrt(1.88 * std::fabs(de));
637 for (
G4int i = 0; i <
G4int(outgoingParticles.size())-1; i++) {
640 for (
G4int j = i+1; j <
G4int(outgoingParticles.size()); j++) {
644 if (mom1[l]*mom2[l]<0.0) {
645 if (std::fabs(mom1[l])>pcut && std::fabs(mom2[l])>pcut) {
646 G4double psum = std::fabs(mom1[l]) + std::fabs(mom2[l]);
661 if (i3 < 0)
return tuner;
667 tuner.first.first = (p1>0.) ? ibest1 : ibest2;
668 tuner.first.second = (p1>0.) ? ibest2 : ibest1;
670 tuner.first.first = (p1<0.) ? ibest2 : ibest1;
671 tuner.first.second = (p1<0.) ? ibest1 : ibest2;
680 G4int mom_ind)
const {
681 if (verboseLevel > 2)
682 G4cout <<
" >>> G4CollisionOutput::tuneSelectedPair" <<
G4endl;
684 G4double newE12 = mom1.
e() + mom2.
e() + mom_non_cons.
e();
685 G4double R = 0.5 * (newE12*newE12 + mom2.
e()*mom2.
e() - mom1.
e()*mom1.
e()) / newE12;
686 G4double Q = -(mom1[mom_ind] + mom2[mom_ind]) / newE12;
688 G4double W = (R * Q + mom2[mom_ind]) * UDQ;
693 if (verboseLevel > 2)
G4cout <<
" DET < 0 : tuning failed" <<
G4endl;
698 G4double x1 = -(W + std::sqrt(DET));
699 G4double x2 = -(W - std::sqrt(DET));
705 if (mom_non_cons.
e() > 0.0) {
707 if (R + Q * x1 >= 0.0) {
712 if (!xset && x2 > 0.0) {
713 if (R + Q * x2 >= 0.0) {
720 if (R + Q * x1 >= 0.) {
725 if (!xset && x2 < 0.0) {
726 if (R + Q * x2 >= 0.0) {
734 if (verboseLevel > 2)
G4cout <<
" no appropriate solution found" <<
G4endl;
void trivialise(G4InuclParticle *bullet, G4InuclParticle *target)
G4CollisionOutput & operator=(const G4CollisionOutput &right)
void addOutgoingNuclei(const std::vector< G4InuclNuclei > &nuclea)
G4LorentzVector getMomentum() const
void removeRecoilFragment(G4int index=-1)
void printCollisionOutput(std::ostream &os=G4cout) const
void addOutgoingParticle(const G4InuclElementaryParticle &particle)
G4LorentzVector rotate(const G4LorentzVector &mom) const
G4LorentzVector backToTheLab(const G4LorentzVector &mom) const
G4LorentzVector getTotalOutputMomentum() const
const G4InuclElementaryParticle & getParticle() const
const G4String & GetParticleName() const
G4int GetAtomicNumber() const
std::vector< G4ReactionProduct * > G4ReactionProductVector
void setVectM(const Hep3Vector &spatial, double mass)
void add(const G4CollisionOutput &right)
G4GLOB_DLL std::ostream G4cout
G4int getTotalStrangeness() const
G4int numberOfOutgoingParticles() const
void boostToLabFrame(const G4LorentzConvertor &convertor)
void removeOutgoingParticle(G4int index)
void rotateEvent(const G4LorentzRotation &rotate)
G4int GetAtomicMass() const
G4int numberOfOutgoingNuclei() const
G4bool reflectionNeeded() const
void addOutgoingParticles(const std::vector< G4InuclElementaryParticle > &particles)
G4int getTotalBaryonNumber() const
static constexpr double GeV
std::vector< G4InuclNuclei >::const_iterator nucleiIterator
G4int getTotalCharge() const
std::vector< G4InuclElementaryParticle >::iterator particleIterator
void setRemainingExitationEnergy()
std::vector< G4Fragment >::iterator fragmentIterator
G4int numberOfFragments() const
void removeOutgoingNucleus(G4int index)
const G4Fragment & getRecoilFragment(G4int index=0) const
static const G4double pos
void setOnShell(G4InuclParticle *bullet, G4InuclParticle *target)