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)