Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/hadronic/models/parton_string/qgsm/src/G4QGSParticipants.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  1 //
  2 // ********************************************************************
  3 // * License and Disclaimer                                           *
  4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.                             *
 10 // *                                                                  *
 11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                                                  *
 18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboration.                      *
 20 // * By using,  copying,  modifying or  distributing the software (or *
 21 // * any work based  on the software)  you  agree  to acknowledge its *
 22 // * use  in  resulting  scientific  publications,  and indicate your *
 23 // * acceptance of all terms of the Geant4 Software license.          *
 24 // ********************************************************************
 25 //
 26 #include <utility>
 27 
 28 #include "G4QGSParticipants.hh"
 29 #include "globals.hh"
 30 #include "G4SystemOfUnits.hh"
 31 #include "G4LorentzVector.hh"
 32 #include "G4V3DNucleus.hh" 
 33 #include "G4ParticleTable.hh"
 34 #include "G4IonTable.hh"
 35 #include "G4PhysicalConstants.hh"
 36 
 37 #include "G4Exp.hh"
 38 #include "G4Log.hh"
 39 #include "G4Pow.hh"
 40 
 41 //#define debugQGSParticipants
 42 //#define debugPutOnMassShell
 43 
 44 // Class G4QGSParticipants 
 45 
 46 // Promoting model parameters from local variables class properties
 47 G4ThreadLocal G4int G4QGSParticipants_NPart = 0;
 48 
 49 G4QGSParticipants::G4QGSParticipants()
 50   : theDiffExcitaton(), ModelMode(SOFT), nCutMax(7),
 51     ThresholdParameter(0.0*GeV), QGSMThreshold(3.0*GeV),
 52     theNucleonRadius(1.5*fermi), theCurrentVelocity(G4ThreeVector()),
 53     theProjectileSplitable(nullptr), Regge(nullptr),
 54     InteractionMode(ALL), alpha(-0.5), beta(2.5), sigmaPt(0.0),
 55     NumberOfInvolvedNucleonsOfTarget(0), NumberOfInvolvedNucleonsOfProjectile(0),
 56     ProjectileResidual4Momentum(G4LorentzVector()), ProjectileResidualMassNumber(0),
 57     ProjectileResidualCharge(0), ProjectileResidualExcitationEnergy(0.0),
 58     TargetResidual4Momentum(G4LorentzVector()), TargetResidualMassNumber(0),
 59     TargetResidualCharge(0), TargetResidualExcitationEnergy(0.0),
 60     CofNuclearDestruction(0.0), R2ofNuclearDestruction(0.0),
 61     ExcitationEnergyPerWoundedNucleon(0.0), DofNuclearDestruction(0.0),
 62     Pt2ofNuclearDestruction(0.0), MaxPt2ofNuclearDestruction(0.0)
 63 {
 64   for (size_t i=0; i < 250; ++i) {
 65     TheInvolvedNucleonsOfTarget[i] = nullptr;
 66     TheInvolvedNucleonsOfProjectile[i] = nullptr;
 67   }
 68   // Parameters setting
 69   SetCofNuclearDestruction( 1.0 );
 70   SetR2ofNuclearDestruction( 1.5*fermi*fermi );
 71   SetDofNuclearDestruction( 0.3 );
 72   SetPt2ofNuclearDestruction( 0.075*GeV*GeV );
 73   SetMaxPt2ofNuclearDestruction( 1.0*GeV*GeV );
 74   SetExcitationEnergyPerWoundedNucleon( 40.0*MeV );
 75 
 76   sigmaPt=0.25*sqr(GeV);
 77 }
 78 
 79 G4QGSParticipants::G4QGSParticipants(const G4QGSParticipants &right)
 80   : G4VParticipants(), ModelMode(right.ModelMode), nCutMax(right.nCutMax),
 81     ThresholdParameter(right.ThresholdParameter),
 82     QGSMThreshold(right.QGSMThreshold),
 83     theNucleonRadius(right.theNucleonRadius),
 84     theCurrentVelocity(right.theCurrentVelocity),
 85     theProjectileSplitable(right.theProjectileSplitable),
 86     Regge(right.Regge), InteractionMode(right.InteractionMode),
 87     alpha(right.alpha), beta(right.beta), sigmaPt(right.sigmaPt),
 88     NumberOfInvolvedNucleonsOfTarget(right.NumberOfInvolvedNucleonsOfTarget),
 89     NumberOfInvolvedNucleonsOfProjectile(right.NumberOfInvolvedNucleonsOfProjectile),
 90     ProjectileResidual4Momentum(right.ProjectileResidual4Momentum),
 91     ProjectileResidualMassNumber(right.ProjectileResidualMassNumber),
 92     ProjectileResidualCharge(right.ProjectileResidualCharge),
 93     ProjectileResidualExcitationEnergy(right.ProjectileResidualExcitationEnergy),
 94     TargetResidual4Momentum(right.TargetResidual4Momentum),
 95     TargetResidualMassNumber(right.TargetResidualMassNumber),
 96     TargetResidualCharge(right.TargetResidualCharge),
 97     TargetResidualExcitationEnergy(right.TargetResidualExcitationEnergy),
 98     CofNuclearDestruction(right.CofNuclearDestruction),
 99     R2ofNuclearDestruction(right.R2ofNuclearDestruction),
100     ExcitationEnergyPerWoundedNucleon(right.ExcitationEnergyPerWoundedNucleon),
101     DofNuclearDestruction(right.DofNuclearDestruction),
102     Pt2ofNuclearDestruction(right.Pt2ofNuclearDestruction),
103     MaxPt2ofNuclearDestruction(right.MaxPt2ofNuclearDestruction)
104 {
105   for (size_t i=0; i < 250; ++i) {
106     TheInvolvedNucleonsOfTarget[i] = right.TheInvolvedNucleonsOfTarget[i];
107     TheInvolvedNucleonsOfProjectile[i] = right.TheInvolvedNucleonsOfProjectile[i];
108   }
109 }
110 
111 G4QGSParticipants::~G4QGSParticipants() {}
112 
113 void G4QGSParticipants::BuildInteractions(const G4ReactionProduct  &thePrimary) 
114 {
115   theProjectile = thePrimary;
116 
117   Regge = new G4Reggeons(theProjectile.GetDefinition());
118 
119   SetProjectileNucleus( 0 );
120 
121   NumberOfInvolvedNucleonsOfProjectile= 0;
122   G4LorentzVector tmp( 0.0, 0.0, 0.0, 0.0 );
123   ProjectileResidualMassNumber       = 0;
124   ProjectileResidualCharge           = 0;
125   ProjectileResidualExcitationEnergy = 0.0;
126   ProjectileResidual4Momentum        = tmp;
127 
128   NumberOfInvolvedNucleonsOfTarget= 0;
129   TargetResidualMassNumber       = theNucleus->GetMassNumber();
130   TargetResidualCharge           = theNucleus->GetCharge();
131   TargetResidualExcitationEnergy = 0.0;
132 
133   theNucleus->StartLoop();
134   G4Nucleon* NuclearNucleon;
135   while ( ( NuclearNucleon = theNucleus->GetNextNucleon() ) ) {  
136     tmp+=NuclearNucleon->Get4Momentum();
137   } 
138   TargetResidual4Momentum        = tmp;
139 
140   if ( std::abs( theProjectile.GetDefinition()->GetBaryonNumber() ) <= 1 ) { 
141     // Projectile is a hadron : meson or baryon
142     ProjectileResidualMassNumber = std::abs( theProjectile.GetDefinition()->GetBaryonNumber() );
143     ProjectileResidualCharge = G4int( theProjectile.GetDefinition()->GetPDGCharge() );
144     ProjectileResidualExcitationEnergy = 0.0;
145     ProjectileResidual4Momentum.setVect( theProjectile.GetMomentum() );
146     ProjectileResidual4Momentum.setE( theProjectile.GetTotalEnergy() );
147   } 
148 
149   #ifdef debugQGSParticipants
150     G4cout <<G4endl<< "G4QGSParticipants::BuildInteractions---------" << G4endl
151            << "thePrimary " << thePrimary.GetDefinition()->GetParticleName()<<" "
152            <<ProjectileResidual4Momentum<<G4endl;
153     G4cout << "Target A and Z  " << theNucleus->GetMassNumber() <<" "<<theNucleus->GetCharge()<<" "
154            << TargetResidual4Momentum<<G4endl;
155   #endif
156 
157   G4bool Success( true );
158 
159   const G4int maxNumberOfLoops = 1000;
160   G4int loopCounter = 0;
161   do
162   {
163     const G4int maxNumberOfInternalLoops = 1000;
164     G4int internalLoopCounter = 0;
165     do
166     {
167       if(std::abs(theProjectile.GetDefinition()->GetPDGEncoding()) < 100.0) 
168       {
169         SelectInteractions(theProjectile);  // for lepton projectile
170       }
171       else
172       {
173         GetList( theProjectile );  // Get list of participating nucleons for hadron projectile
174       }
175 
176       if ( theInteractions.size() == 0 ) return;
177 
178       StoreInvolvedNucleon();       // Store participating nucleon
179 
180       ReggeonCascade();             // Make reggeon cascading. Involve nucleons in the cascading.
181 
182       Success = PutOnMassShell();   // Ascribe momenta to the involved and participating nucleons
183 
184       if(!Success) PrepareInitialState( thePrimary );
185 
186     } while( (!Success) && ++internalLoopCounter < maxNumberOfInternalLoops );
187 
188     if ( internalLoopCounter >= maxNumberOfInternalLoops ) {
189       Success = false;
190     }
191    
192     if ( Success ) {
193       #ifdef debugQGSParticipants
194         G4cout<<G4endl<<"PerformDiffractiveCollisions(); if they happend." <<G4endl;
195       #endif
196 
197       PerformDiffractiveCollisions();
198 
199       #ifdef debugQGSParticipants
200         G4cout<<G4endl<<"SplitHadrons();" <<G4endl;
201       #endif
202 
203       SplitHadrons(); 
204 
205       if( theProjectileSplitable && theProjectileSplitable->GetStatus() == 0) {
206         #ifdef debugQGSParticipants
207           G4cout<<"Perform non-Diffractive Collisions if they happend. Determine Parton Momenta and so on." <<G4endl;
208         #endif 
209         Success = DeterminePartonMomenta(); 
210       }
211 
212       if(!Success) PrepareInitialState( thePrimary );
213     }
214   } while( (!Success) && ++loopCounter < maxNumberOfLoops );
215 
216   if ( loopCounter >= maxNumberOfLoops ) {
217     Success = false;
218     #ifdef debugQGSParticipants
219       G4cout<<"NOT Successful ======" <<G4endl;
220     #endif
221   }
222 
223   if ( Success ) {
224     CreateStrings();  // To create strings
225 
226     GetResiduals();   // To calculate residual nucleus properties
227 
228     #ifdef debugQGSParticipants
229       G4cout<<"All O.K. ======" <<G4endl;
230     #endif
231   }
232 
233   // clean-up, if necessary
234   #ifdef debugQGSParticipants
235     G4cout<<"Clearing "<<G4endl;
236     G4cout<<"theInteractions.size() "<<theInteractions.size()<<G4endl;
237   #endif
238 
239   if( Regge ) delete Regge;
240 
241   std::for_each( theInteractions.begin(), theInteractions.end(), DeleteInteractionContent() );
242   theInteractions.clear();
243 
244   // Erasing of target involved nucleons.
245   #ifdef debugQGSParticipants
246     G4cout<<"Erasing of involved target nucleons "<<NumberOfInvolvedNucleonsOfTarget<<G4endl;
247   #endif
248 
249   if ( NumberOfInvolvedNucleonsOfTarget != 0 ) {
250      for ( G4int i = 0; i < NumberOfInvolvedNucleonsOfTarget; i++ ) {
251       G4VSplitableHadron* aNucleon = TheInvolvedNucleonsOfTarget[i]->GetSplitableHadron();
252       if ( (aNucleon != 0 ) && (aNucleon->GetStatus() >= 1) ) delete aNucleon;
253      }
254   }
255 
256   // Erasing of projectile involved nucleons.
257   if ( NumberOfInvolvedNucleonsOfProjectile != 0 ) {
258      for ( G4int i = 0; i < NumberOfInvolvedNucleonsOfProjectile; i++ ) {
259        G4VSplitableHadron* aNucleon = TheInvolvedNucleonsOfProjectile[i]->GetSplitableHadron();
260        if ( aNucleon ) delete aNucleon;
261      }
262   }
263 
264   #ifdef debugQGSParticipants
265     G4cout<<"Delition of target nucleons from soft interactions "<<theTargets.size()
266           <<G4endl<<G4endl;
267   #endif
268   std::for_each(theTargets.begin(), theTargets.end(), DeleteSplitableHadron());
269   theTargets.clear();
270 
271   if ( theProjectileSplitable ) {
272     delete theProjectileSplitable;
273     theProjectileSplitable = 0;
274   }
275 }
276 
277 //===========================================================
278 void G4QGSParticipants::PrepareInitialState( const G4ReactionProduct& thePrimary ) 
279 {
280   // Clearing of the arrays
281   // Erasing of the projectile
282   G4InteractionContent* anIniteraction = theInteractions[0];
283   G4VSplitableHadron* pProjectile = anIniteraction->GetProjectile();
284   if( pProjectile ) delete pProjectile;
285 
286   std::for_each(theInteractions.begin(), theInteractions.end(), DeleteInteractionContent());
287   theInteractions.clear();
288 
289   // Erasing of the envolved nucleons and target nucleons from diffraction dissociations
290   theNucleus->StartLoop();
291   G4Nucleon* aNucleon;
292   while ( ( aNucleon = theNucleus->GetNextNucleon() ) ) 
293   {
294     if ( aNucleon->AreYouHit() ) {
295       G4VSplitableHadron* splaNucleon = aNucleon->GetSplitableHadron();
296       if ( (splaNucleon != 0) && (splaNucleon->GetStatus() >=1) ) delete splaNucleon;
297       aNucleon->Hit(nullptr);
298       NumberOfInvolvedNucleonsOfTarget--;
299     } 
300   }
301 
302   // Erasing of nuclear nucleons participated in soft interactions
303   std::for_each(theTargets.begin(), theTargets.end(), DeleteSplitableHadron());
304   theTargets.clear();
305 
306   // Preparation to a new attempt
307   theProjectile = thePrimary;
308 
309   theNucleus->Init(theNucleus->GetMassNumber(), theNucleus->GetCharge());
310   theNucleus->SortNucleonsIncZ();       
311   DoLorentzBoost(-theCurrentVelocity);  // Lorentz boost of the target nucleus
312 
313   if (theNucleus->GetMassNumber() == 1)
314   {
315     G4ThreeVector aPos = G4ThreeVector(0.,0.,0.);
316     theNucleus->StartLoop();
317     G4Nucleon* tNucleon=theNucleus->GetNextNucleon();
318     tNucleon->SetPosition(aPos);
319   }
320 
321   G4LorentzVector Tmp( 0.0, 0.0, 0.0, 0.0 );
322   NumberOfInvolvedNucleonsOfTarget= 0;
323   TargetResidualMassNumber       = theNucleus->GetMassNumber();
324   TargetResidualCharge           = theNucleus->GetCharge();
325   TargetResidualExcitationEnergy = 0.0;
326 
327   G4Nucleon* NuclearNucleon;
328   while ( ( NuclearNucleon = theNucleus->GetNextNucleon() ) )
329               {Tmp+=NuclearNucleon->Get4Momentum();} 
330 
331   TargetResidual4Momentum = Tmp;
332 }
333 
334 //===========================================================
335 void G4QGSParticipants::GetList( const G4ReactionProduct& thePrimary ) { 
336   #ifdef debugQGSParticipants
337     G4cout<<G4endl<<"G4QGSParticipants::GetList +++++++++++++"<<G4endl;
338   #endif
339 
340   // Direction: True - Proj, False - Target
341   theProjectileSplitable = new G4QGSMSplitableHadron(thePrimary, TRUE);
342   theProjectileSplitable->SetStatus(1);
343 
344   G4LorentzVector aPrimaryMomentum(thePrimary.GetMomentum(), thePrimary.GetTotalEnergy());
345   G4LorentzVector aNucleonMomentum(0.,0.,0., 938.0*MeV);
346 
347   G4double SS=(aPrimaryMomentum + aNucleonMomentum).mag2();
348 
349   Regge->SetS(SS);
350 
351   //--------------------------------------
352   theNucleus->StartLoop();
353   G4Nucleon * tNucleon = theNucleus->GetNextNucleon();
354 
355   if ( ! tNucleon ) {
356     #ifdef debugQGSParticipants
357       G4cout << "QGSM - BAD situation: pNucleon is NULL ! Leaving immediately!" << G4endl;
358     #endif
359     return;
360   }
361 
362   G4double theNucleusOuterR = theNucleus->GetOuterRadius();
363 
364   if (theNucleus->GetMassNumber() == 1)
365   {
366     G4ThreeVector aPos = G4ThreeVector(0.,0.,0.);
367     tNucleon->SetPosition(aPos);
368     theNucleusOuterR = 0.;
369   }
370 
371   // Determination of participating nucleons of nucleus ------------------------------------
372 
373   std::for_each(theInteractions.begin(), theInteractions.end(), DeleteInteractionContent());
374   theInteractions.clear();
375 
376   G4int MaxPower=thePrimary.GetMomentum().mag()/(3.3*GeV); if(MaxPower < 1) MaxPower=1;
377 
378   const G4int maxNumberOfLoops = 1000;
379 
380   G4int NumberOfTries = 0;
381   G4double Scale = 1.0;
382 
383   G4int loopCounter = -1;
384   while( (theInteractions.size() == 0) && ++loopCounter < maxNumberOfLoops )
385   {
386     InteractionMode = ALL;  // Mode = ALL, WITHOUT_R, NON_DIFF
387 
388     // choose random impact parameter of a collision
389     std::pair<G4double, G4double> theImpactParameter;
390 
391     NumberOfTries++;
392     if( NumberOfTries == 100*(NumberOfTries/100) ) Scale /=2.0;
393 
394     theImpactParameter = theNucleus->ChooseImpactXandY(theNucleusOuterR/Scale + theNucleonRadius);
395     G4double impactX = theImpactParameter.first;
396     G4double impactY = theImpactParameter.second;
397 
398     #ifdef debugQGSParticipants
399       G4cout<<"InteractionMode "<<InteractionMode<<G4endl;
400       G4cout<<"Impact parameter (fm ) "<<std::sqrt(sqr(impactX)+sqr(impactY))/fermi<<" "<<G4endl;
401       G4int nucleonCount = -1;
402     #endif
403 
404     // loop over nucleons to find collisions
405     theNucleus->StartLoop();
406     G4QGSParticipants_NPart = 0;
407 
408     G4double Power=MaxPower;
409 
410     while( (tNucleon = theNucleus->GetNextNucleon()) )
411     {
412       if(Power <= 0.) break;
413 
414       G4LorentzVector nucleonMomentum=tNucleon->Get4Momentum();
415 
416       G4double Distance2 = sqr(impactX - tNucleon->GetPosition().x()) + 
417                            sqr(impactY - tNucleon->GetPosition().y());
418 
419       G4double Pint(0.);                    // A probability of interaction at given impact parameter 
420       G4double Pprd(0.), Ptrd(0.), Pdd(0.); // Probabilities of Proj. diffr., Target diffr., Double diffr. 
421       G4double Pnd (0.), Pnvr(0.);          // Probabilities of non-diffr. and quark exchange  
422       G4int    NcutPomerons(0);             // Number of cutted pomerons
423 
424       Regge->GetProbabilities(std::sqrt(Distance2), InteractionMode,
425             Pint, Pprd, Ptrd, Pdd, Pnd, Pnvr);
426       #ifdef debugQGSParticipants
427         nucleonCount++;
428         G4cout<<"Nucleon & its impact parameter: "<<nucleonCount<<" "<<std::sqrt(Distance2)/fermi<<" (fm)"<<G4endl;
429         G4cout<<"Probability of interaction:     "<<Pint<<G4endl;
430   G4cout<<"Probability of PrD, TrD, DD:    "<<Pprd<<" "<<Ptrd<<" "<<Pdd<<G4endl;
431   G4cout<<"Probability of NonDiff, QuarkExc.: "<<Pnd<<" "<<Pnvr<<" in inel. inter."<<G4endl;
432       #endif
433 
434       if (Pint > G4UniformRand())
435       {                             // An interaction is happend.
436 
437         G4double rndNumber = G4UniformRand();
438         G4int InteractionType(0);
439 
440         if((InteractionMode==ALL)||(InteractionMode==WITHOUT_R))     // Mode = ALL, WITHOUT_R, NON_DIFF 
441         {
442     if(      rndNumber < Pprd )              {InteractionType = PrD;  InteractionMode = WITHOUT_R;}
443     else if( rndNumber < Pprd+Ptrd)          {InteractionType = TrD;  InteractionMode = WITHOUT_R;}
444     else if( rndNumber < Pprd+Ptrd+Pdd)      {InteractionType = DD;   InteractionMode = WITHOUT_R;}
445     else if( rndNumber < Pprd+Ptrd+Pdd+Pnd ) {InteractionType = NonD; InteractionMode = NON_DIFF;
446                   NcutPomerons =  Regge->ncPomerons();                }
447     else                               {InteractionType = Qexc; InteractionMode = ALL;      }
448         }
449         else  // InteractionMode == NON_DIFF
450         {
451           InteractionMode = NON_DIFF;
452     if( rndNumber < Ptrd )           {InteractionType = TrD; }
453     else if( rndNumber < Ptrd + Pnd) {InteractionType = NonD;  NcutPomerons =  Regge->ncPomerons();}
454         }
455 
456         if( (InteractionType == NonD) && (NcutPomerons == 0)) continue; 
457 
458         G4QGSParticipants_NPart ++;
459         G4QGSMSplitableHadron* aTargetSPB = new G4QGSMSplitableHadron(*tNucleon);
460         tNucleon->Hit(aTargetSPB);
461 
462         #ifdef debugQGSParticipants
463           G4cout<<"An interaction is happend."<<G4endl;
464           G4cout<<"Target nucleon - "<<nucleonCount<<" "
465                 <<tNucleon->GetDefinition()->GetParticleName()<<G4endl;
466           G4cout<<"Interaction type:"<<InteractionType
467                 <<" (0 -PrD, 1 - TrD, 2 - DD, 3 - NonD, 4 - Qexc)"<<G4endl;
468           G4cout<<"New Inter.  mode:"<<InteractionMode
469                 <<" (0 -ALL, 1 - WITHOUT_R, 2 - NON_DIFF)"<<G4endl;
470           if( InteractionType == NonD )
471             G4cout<<"Number of cutted pomerons: "<<NcutPomerons<<G4endl;
472         #endif
473 
474         if((InteractionType == PrD) || (InteractionType == TrD) || (InteractionType == DD) ||
475      (InteractionType == Qexc))
476         {                                  // diffractive-like interaction occurs
477           #ifdef debugQGSParticipants
478             G4cout<<"Diffractive-like interaction occurs"<<G4endl;
479           #endif
480 
481           G4InteractionContent * aInteraction = new G4InteractionContent(theProjectileSplitable);
482           theProjectileSplitable->SetStatus(1*theProjectileSplitable->GetStatus());
483 
484           aInteraction->SetTarget(aTargetSPB);
485           aInteraction->SetTargetNucleon(tNucleon);
486           aTargetSPB->SetCollisionCount(0);
487           aTargetSPB->SetStatus(1);
488 
489           aInteraction->SetNumberOfDiffractiveCollisions(1);
490           aInteraction->SetNumberOfSoftCollisions(0);
491           aInteraction->SetStatus(InteractionType);
492           theInteractions.push_back(aInteraction);
493         }
494         else
495         {                               // nondiffractive interaction occurs
496           #ifdef debugQGSParticipants
497             G4cout<<"Non-diffractive interaction occurs, max NcutPomerons "<<NcutPomerons<<G4endl;
498           #endif
499 
500     G4int nCuts;
501 
502           G4int Vncut=0; 
503     for(nCuts = 0; nCuts < NcutPomerons; nCuts++) 
504     {       
505       if( G4UniformRand() < Power/MaxPower ){Vncut++; Power--; if(Power <= 0.) break;}
506     }
507           nCuts=Vncut;
508 
509     if( nCuts == 0 ) {delete aTargetSPB; tNucleon->Hit(nullptr); continue;} 
510 
511           #ifdef debugQGSParticipants
512             G4cout<<"Number of cuts in the interaction "<<nCuts<<G4endl;
513           #endif
514 
515     aTargetSPB->IncrementCollisionCount(nCuts);
516           aTargetSPB->SetStatus(0);
517           theTargets.push_back(aTargetSPB);
518 
519     theProjectileSplitable->IncrementCollisionCount(nCuts);
520           theProjectileSplitable->SetStatus(0*theProjectileSplitable->GetStatus());
521 
522     G4InteractionContent * aInteraction = new G4InteractionContent(theProjectileSplitable);
523     aInteraction->SetTarget(aTargetSPB);
524           aInteraction->SetTargetNucleon(tNucleon);
525     aInteraction->SetNumberOfSoftCollisions(nCuts);
526           aInteraction->SetStatus(InteractionType);
527     theInteractions.push_back(aInteraction);
528         }
529       }    // End of if (Pint > G4UniformRand())
530     }     // End of while( (tNucleon = theNucleus->GetNextNucleon()) )
531 
532     #ifdef debugQGSParticipants
533       G4cout << G4endl<<"Number of wounded nucleons "<<G4QGSParticipants_NPart<<G4endl;
534     #endif
535 
536   }  // End of while( (theInteractions.size() == 0) && ++loopCounter < maxNumberOfLoops )
537 
538   if ( loopCounter >= maxNumberOfLoops ) {
539     #ifdef debugQGSParticipants
540       G4cout <<"BAD situation: forced loop exit!" << G4endl;
541     #endif
542     // Perhaps there is something to set here...
543     // Decrease impact parameter ??
544     // Select collisions with only diffraction ??
545     // Selecy only non-diffractive interactions ??
546   }
547   //------------------------------------------------------------
548   std::vector<G4InteractionContent*>::iterator i;
549 
550   if( theInteractions.size() != 0)
551   {
552     if( InteractionMode == ALL )  // It can be if all interactions were quark-exchange. 
553     {                             // Only the first one will be saved, all other will be erased.
554       i = theInteractions.end()-1;
555 
556       while ( theInteractions.size() != 1 )  
557       {
558         G4InteractionContent* anInteraction = *i;
559         G4Nucleon * pNucleon = anInteraction->GetTargetNucleon(); pNucleon->Hit(nullptr);
560         delete anInteraction->GetTarget();
561   delete *i;
562   i=theInteractions.erase(i);
563   i--;
564       }
565     }
566     else
567     {                             // All quark exchanges will be erased
568       i = theInteractions.begin();
569       while ( i != theInteractions.end() )  
570       {
571         G4InteractionContent* anInteraction = *i;
572 
573         if( anInteraction->GetStatus() == Qexc )
574         {
575           G4Nucleon*        aTargetNucleon = anInteraction->GetTargetNucleon();
576     aTargetNucleon->Hit(nullptr);
577 
578           delete anInteraction->GetTarget();
579     delete *i;
580     i=theInteractions.erase(i);
581         }
582         else
583         {
584           i++;
585         }
586       }
587     }
588   }
589 }
590 
591 //=============================================================
592 void G4QGSParticipants::StoreInvolvedNucleon() 
593 { //To store nucleons involved in the interaction
594 
595   NumberOfInvolvedNucleonsOfTarget = 0;
596 
597   theNucleus->StartLoop();
598 
599   G4Nucleon* aNucleon;
600   while ( ( aNucleon = theNucleus->GetNextNucleon() ) ) {
601     if ( aNucleon->AreYouHit() ) {
602       TheInvolvedNucleonsOfTarget[NumberOfInvolvedNucleonsOfTarget] = aNucleon;
603       NumberOfInvolvedNucleonsOfTarget++;
604     }
605   }
606 
607   #ifdef debugQGSParticipants
608     G4cout << G4endl<<"G4QGSParticipants::StoreInvolvedNucleon() if they were "<<G4endl
609            <<"Stored # of wounded nucleons of target "
610            << NumberOfInvolvedNucleonsOfTarget <<G4endl;
611   #endif
612   return;
613 }                        
614 
615 //=============================================================
616 
617 void G4QGSParticipants::ReggeonCascade() 
618 { // Implementation of the reggeon theory inspired model of nuclear destruction 
619   #ifdef debugQGSParticipants
620     G4cout << G4endl<<"Reggeon cascading ........."<<G4endl;
621     G4cout<<"C of nucl. desctruction "<<GetCofNuclearDestruction()
622           <<" R2 "<<GetR2ofNuclearDestruction()/fermi/fermi<<" fermi^2"<<G4endl; 
623   #endif
624 
625   G4int InitNINt = NumberOfInvolvedNucleonsOfTarget;
626 
627   // Reggeon cascading in target nucleus
628   for ( G4int InvTN = 0; InvTN < InitNINt; InvTN++ ) { 
629     G4Nucleon* aTargetNucleon = TheInvolvedNucleonsOfTarget[ InvTN ];
630 
631     G4double CreationTime = aTargetNucleon->GetSplitableHadron()->GetTimeOfCreation();
632 
633     G4double XofWoundedNucleon = aTargetNucleon->GetPosition().x();
634     G4double YofWoundedNucleon = aTargetNucleon->GetPosition().y();
635            
636     G4V3DNucleus* theTargetNucleus = theNucleus;
637     theTargetNucleus->StartLoop();
638 
639     #ifdef debugQGSParticipants
640       G4int TrgNuc=0;
641     #endif
642     G4Nucleon* Neighbour(0);
643     while ( ( Neighbour = theTargetNucleus->GetNextNucleon() ) ) {
644       #ifdef debugQGSParticipants
645         TrgNuc++;
646       #endif
647       if ( ! Neighbour->AreYouHit() ) {
648         G4double impact2 = sqr( XofWoundedNucleon - Neighbour->GetPosition().x() ) +
649                            sqr( YofWoundedNucleon - Neighbour->GetPosition().y() );
650 
651         if ( G4UniformRand() < GetCofNuclearDestruction() *
652                                G4Exp( -impact2 / GetR2ofNuclearDestruction() )
653            ) {  
654           // The neighbour nucleon is involved in the reggeon cascade
655           #ifdef debugQGSParticipants
656             G4cout<<"Target nucleon involved in reggeon cascading No "<<TrgNuc<<" "
657                   <<Neighbour->GetDefinition()->GetParticleName()<<G4endl;
658           #endif
659           TheInvolvedNucleonsOfTarget[ NumberOfInvolvedNucleonsOfTarget ] = Neighbour;
660           NumberOfInvolvedNucleonsOfTarget++;
661 
662           G4QGSMSplitableHadron* targetSplitable = new G4QGSMSplitableHadron( *Neighbour ); 
663 
664           Neighbour->Hit( targetSplitable );
665           targetSplitable->SetTimeOfCreation( CreationTime ); 
666           targetSplitable->SetStatus( 2 );
667           targetSplitable->SetCollisionCount(0);
668 
669           G4InteractionContent * anInteraction = new G4InteractionContent(theProjectileSplitable);
670           anInteraction->SetTarget(targetSplitable);
671           anInteraction->SetTargetNucleon(Neighbour);
672 
673           anInteraction->SetNumberOfDiffractiveCollisions(1);
674           anInteraction->SetNumberOfSoftCollisions(0);
675           anInteraction->SetStatus(3);
676           theInteractions.push_back(anInteraction);
677         }
678       }
679     }
680   }
681 
682   #ifdef debugQGSParticipants
683     G4cout <<"Number of new involved nucleons "<<NumberOfInvolvedNucleonsOfTarget - InitNINt<<G4endl;
684   #endif
685   return;
686 }   
687 
688 //============================================================================
689 
690 G4bool G4QGSParticipants::PutOnMassShell() {
691 
692   G4bool isProjectileNucleus = false;
693   if ( GetProjectileNucleus() ) {
694     isProjectileNucleus = true;
695   }
696 
697   #ifdef debugPutOnMassShell
698     G4cout <<G4endl<< "PutOnMassShell start ..............." << G4endl;
699     if ( isProjectileNucleus ) {G4cout << "PutOnMassShell for Nucleus_Nucleus " << G4endl;}
700   #endif
701 
702   G4LorentzVector Pprojectile( theProjectile.GetMomentum(), theProjectile.GetTotalEnergy() );
703   if ( Pprojectile.z() < 0.0 ) {
704     return false;
705   }
706 
707   G4bool isOk = true;
708   
709   G4LorentzVector Ptarget( 0.0, 0.0, 0.0, 0.0 );
710   G4LorentzVector PtargetResidual( 0.0, 0.0, 0.0, 0.0 );
711   G4double SumMasses = 0.0;
712   G4V3DNucleus* theTargetNucleus = GetTargetNucleus();
713   G4double TargetResidualMass = 0.0; 
714 
715   #ifdef debugPutOnMassShell
716     G4cout << "Target : ";
717   #endif
718 
719   isOk = ComputeNucleusProperties( theTargetNucleus, Ptarget, PtargetResidual, SumMasses,
720                                    TargetResidualExcitationEnergy, TargetResidualMass,
721                                    TargetResidualMassNumber, TargetResidualCharge );
722 
723   if ( ! isOk ) return false;
724 
725   G4double Mprojectile  = 0.0;
726   G4double M2projectile = 0.0;
727   G4LorentzVector Pproj( 0.0, 0.0, 0.0, 0.0 );
728   G4LorentzVector PprojResidual( 0.0, 0.0, 0.0, 0.0 );
729   G4V3DNucleus* thePrNucleus = GetProjectileNucleus();
730   G4double PrResidualMass = 0.0;
731 
732   if ( ! isProjectileNucleus ) {  // hadron-nucleus collision
733     Mprojectile  = Pprojectile.mag();
734     M2projectile = Pprojectile.mag2();
735     SumMasses += Mprojectile + 20.0*MeV;                          // Maybe DM must be larger?
736   } else {  // nucleus-nucleus or antinucleus-nucleus collision
737 
738     #ifdef debugPutOnMassShell
739       G4cout << "Projectile : ";
740     #endif
741 
742     isOk = ComputeNucleusProperties( thePrNucleus, Pproj, PprojResidual, SumMasses,
743                                      ProjectileResidualExcitationEnergy, PrResidualMass,
744                                      ProjectileResidualMassNumber, ProjectileResidualCharge );
745     if ( ! isOk ) return false;
746   }
747 
748   G4LorentzVector Psum = Pprojectile + Ptarget;   
749   G4double SqrtS = Psum.mag();
750   G4double     S = Psum.mag2();
751 
752   #ifdef debugPutOnMassShell
753     G4cout << "Pproj "<<Pprojectile<<G4endl;
754     G4cout << "Ptarg "<<Ptarget<<G4endl;
755     G4cout << "Psum " << Psum/GeV << " GeV" << G4endl << "SqrtS " << SqrtS/GeV << " GeV" << G4endl
756            << "SumMasses, PrResidualMass and TargetResidualMass " << SumMasses/GeV << " " 
757            << PrResidualMass/GeV << " " << TargetResidualMass/GeV << " GeV" << G4endl;
758     G4cout << "Ptar res. "<<PtargetResidual<<G4endl;
759   #endif
760 
761   if ( SqrtS < SumMasses ) {
762     return false;  // It is impossible to simulate after putting nuclear nucleons on mass-shell.
763   }
764 
765   // Try to consider also the excitation energy of the residual nucleus, if this is
766   // possible, with the available energy; otherwise, set the excitation energy to zero.
767 
768   G4double savedSumMasses = SumMasses;
769   if ( isProjectileNucleus ) {
770     SumMasses -= std::sqrt( sqr( PrResidualMass ) + PprojResidual.perp2() );
771     SumMasses += std::sqrt( sqr( PrResidualMass + ProjectileResidualExcitationEnergy ) 
772                             + PprojResidual.perp2() ); 
773   }
774   SumMasses -= std::sqrt( sqr( TargetResidualMass ) + PtargetResidual.perp2() );
775   SumMasses += std::sqrt( sqr( TargetResidualMass + TargetResidualExcitationEnergy )
776                           + PtargetResidual.perp2() );
777 
778   if ( SqrtS < SumMasses ) {
779     SumMasses = savedSumMasses;
780     if ( isProjectileNucleus ) {
781       ProjectileResidualExcitationEnergy = 0.0;
782     }
783     TargetResidualExcitationEnergy = 0.0;
784   }
785 
786   TargetResidualMass += TargetResidualExcitationEnergy;
787   if ( isProjectileNucleus ) {
788     PrResidualMass += ProjectileResidualExcitationEnergy;
789   }
790 
791   #ifdef debugPutOnMassShell
792     if ( isProjectileNucleus ) {
793       G4cout << "PrResidualMass ProjResidualExcitationEnergy " << PrResidualMass/GeV << " "
794        << ProjectileResidualExcitationEnergy << " MeV" << G4endl;
795     }
796     G4cout << "TargetResidualMass TargetResidualExcitationEnergy " << TargetResidualMass/GeV << " GeV " 
797            << TargetResidualExcitationEnergy << " MeV" << G4endl
798            << "Sum masses " << SumMasses/GeV << G4endl;
799   #endif
800 
801   // Sampling of nucleons what can transfer to delta-isobars
802   if ( isProjectileNucleus  &&  thePrNucleus->GetMassNumber() != 1 ) {
803     isOk = GenerateDeltaIsobar( SqrtS, NumberOfInvolvedNucleonsOfProjectile,
804                                 TheInvolvedNucleonsOfProjectile, SumMasses );       
805   }
806   if ( theTargetNucleus->GetMassNumber() != 1 ) {
807     isOk = isOk  &&
808            GenerateDeltaIsobar( SqrtS, NumberOfInvolvedNucleonsOfTarget,
809                                 TheInvolvedNucleonsOfTarget, SumMasses );
810   }
811   if ( ! isOk ) return false;
812 
813   // Now we know that it is kinematically possible to produce a final state made
814   // of the involved nucleons (or corresponding delta-isobars) and a residual nucleus.
815   // We have to sample the kinematical variables which will allow to define the 4-momenta
816   // of the final state. The sampled kinematical variables refer to the center-of-mass frame.
817   // Notice that the sampling of the transverse momentum corresponds to take into account
818   // Fermi motion.
819 
820   // If target is nucleon - return ?
821 
822   G4LorentzRotation toCms( -1*Psum.boostVector() );
823   G4LorentzVector Ptmp = toCms*Pprojectile;
824   if ( Ptmp.pz() <= 0.0 ) {  // "String" moving backwards in c.m.s., abort collision!
825     return false; 
826   }
827 
828   G4LorentzRotation toLab( toCms.inverse() );
829   
830   G4double YprojectileNucleus = 0.0;
831   if ( isProjectileNucleus ) {
832     Ptmp = toCms*Pproj;                      
833     YprojectileNucleus = Ptmp.rapidity();
834   }
835   Ptmp = toCms*Ptarget;                      
836   G4double YtargetNucleus = Ptmp.rapidity();
837 
838   // Ascribing of the involved nucleons Pt and Xminus
839   G4double DcorP = 0.0;
840   if ( isProjectileNucleus ) {
841     DcorP = GetDofNuclearDestruction() / thePrNucleus->GetMassNumber();
842   }
843   G4double DcorT       = GetDofNuclearDestruction() / theTargetNucleus->GetMassNumber();
844   G4double AveragePt2  = GetPt2ofNuclearDestruction();
845   G4double maxPtSquare = GetMaxPt2ofNuclearDestruction();
846 
847   #ifdef debugPutOnMassShell
848     if ( isProjectileNucleus ) {
849       G4cout << "Y projectileNucleus " << YprojectileNucleus << G4endl;
850     }
851     G4cout << "Y targetNucleus     " << YtargetNucleus << G4endl 
852            << "Dcor " << GetDofNuclearDestruction()
853            << " DcorP DcorT " << DcorP << " " << DcorT << " AveragePt2 " << AveragePt2 << G4endl;
854   #endif
855 
856   G4double M2proj = M2projectile;  // Initialization needed only for hadron-nucleus collisions
857   G4double WplusProjectile = 0.0;
858   G4double M2target = 0.0;
859   G4double WminusTarget = 0.0;
860   G4int NumberOfTries = 0;
861   G4double ScaleFactor = 1.0;
862   G4bool OuterSuccess = true;
863 
864   const G4int maxNumberOfLoops = 1000;
865   G4int loopCounter = 0;
866   do {
867     G4double sqrtM2proj = 0.0, sqrtM2target = 0.0;
868     OuterSuccess = true;
869     const G4int maxNumberOfTries = 1000;
870     do {
871       NumberOfTries++;
872       if ( NumberOfTries == 100*(NumberOfTries/100) ) {
873         // After many tries, it is convenient to reduce the values of DcorP, DcorT and
874         // AveragePt2, so that the sampled momenta (respectively, pz, and pt) of the
875   // involved nucleons (or corresponding delta-isomers) are smaller, and therefore
876         // it is more likely to satisfy the momentum conservation.
877         ScaleFactor /= 2.0;
878         DcorP       *= ScaleFactor;
879         DcorT       *= ScaleFactor;
880         AveragePt2  *= ScaleFactor;
881       }
882       if ( isProjectileNucleus ) {
883         // Sampling of kinematical properties of projectile nucleons
884         isOk = SamplingNucleonKinematics( AveragePt2, maxPtSquare, DcorP, 
885                                           thePrNucleus, PprojResidual, 
886                                           PrResidualMass, ProjectileResidualMassNumber,
887                                           NumberOfInvolvedNucleonsOfProjectile, 
888                                           TheInvolvedNucleonsOfProjectile, M2proj );
889       }
890       // Sampling of kinematical properties of target nucleons
891       isOk = isOk  &&
892              SamplingNucleonKinematics( AveragePt2, maxPtSquare, DcorT, 
893                                         theTargetNucleus, PtargetResidual, 
894                                         TargetResidualMass, TargetResidualMassNumber,
895                                         NumberOfInvolvedNucleonsOfTarget, 
896                                         TheInvolvedNucleonsOfTarget, M2target );
897 
898       if ( M2proj < 0.0 ) {
899         if( M2proj < -0.000001 ) { 
900     G4ExceptionDescription ed;
901     ed << "Projectile " << theProjectile.GetDefinition()->GetParticleName()
902        << "  Target (Z,A)=(" << theTargetNucleus->GetCharge() << "," << theTargetNucleus->GetMassNumber() 
903            << ")  M2proj=" << M2proj << "  ->  sets it to 0.0 !" << G4endl;
904     G4Exception( "G4QGSParticipants::PutOnMassShell(): negative projectile squared mass!",
905            "HAD_QGSPARTICIPANTS_002", JustWarning, ed );
906   }
907         M2proj = 0.0;
908       } 
909       sqrtM2proj = std::sqrt( M2proj );
910       if ( M2target < 0.0 ) {
911         G4ExceptionDescription ed;
912         ed << "Projectile " << theProjectile.GetDefinition()->GetParticleName()
913            << "  Target (Z,A)=(" << theTargetNucleus->GetCharge() << "," << theTargetNucleus->GetMassNumber() 
914            << ")  M2target=" << M2target << "  ->  sets it to 0.0 !" << G4endl;
915         G4Exception( "G4QGSParticipants::PutOnMassShell(): negative target squared mass!",
916                     "HAD_QGSPARTICIPANTS_003", JustWarning, ed );
917         M2target = 0.0;
918       };
919       sqrtM2target = std::sqrt( M2target );
920 
921       #ifdef debugPutOnMassShell
922         G4cout << "SqrtS, Mp+Mt, Mp, Mt " << SqrtS/GeV << " " 
923                << ( sqrtM2proj + sqrtM2target )/GeV << " "
924                << sqrtM2proj/GeV << " " << sqrtM2target/GeV << G4endl;
925       #endif
926 
927       if ( ! isOk ) return false;
928     } while ( ( SqrtS < ( sqrtM2proj + sqrtM2target ) ) &&
929               ++NumberOfTries < maxNumberOfTries );  /* Loop checking, 07.08.2015, A.Ribon */
930     if ( NumberOfTries >= maxNumberOfTries ) {
931       return false;
932     }
933     if ( isProjectileNucleus ) {
934       isOk = CheckKinematics( S, SqrtS, M2proj, M2target, YprojectileNucleus, true, 
935                               NumberOfInvolvedNucleonsOfProjectile, 
936                               TheInvolvedNucleonsOfProjectile,
937                               WminusTarget, WplusProjectile, OuterSuccess );
938     }
939     isOk = isOk  &&
940            CheckKinematics( S, SqrtS, M2proj, M2target, YtargetNucleus, false, 
941                             NumberOfInvolvedNucleonsOfTarget, TheInvolvedNucleonsOfTarget,
942                             WminusTarget, WplusProjectile, OuterSuccess );
943     if ( ! isOk ) return false;
944   } while ( ( ! OuterSuccess ) && 
945             ++loopCounter < maxNumberOfLoops );  /* Loop checking, 07.08.2015, A.Ribon */
946   if ( loopCounter >= maxNumberOfLoops ) {
947     return false;
948   }
949 
950   // Now the sampling is completed, and we can determine the kinematics of the
951   // whole system. This is done first in the center-of-mass frame, and then it is boosted
952   // to the lab frame. The transverse momentum of the residual nucleus is determined as
953   // the recoil of each hadron (nucleon or delta) which is emitted, i.e. in such a way
954   // to conserve (by construction) the transverse momentum.
955 
956   if ( ! isProjectileNucleus ) {  // hadron-nucleus collision
957 
958     G4double Pzprojectile = WplusProjectile/2.0 - M2projectile/2.0/WplusProjectile;
959     G4double Eprojectile  = WplusProjectile/2.0 + M2projectile/2.0/WplusProjectile;
960     Pprojectile.setPz( Pzprojectile ); 
961     Pprojectile.setE( Eprojectile );
962 
963     #ifdef debugPutOnMassShell
964       G4cout << "Proj after in CMS " << Pprojectile/GeV <<" GeV"<< G4endl;
965     #endif
966 
967     Pprojectile.transform( toLab );  
968     theProjectile.SetMomentum( Pprojectile.vect() );
969     theProjectile.SetTotalEnergy( Pprojectile.e() );
970 
971     if ( theProjectileSplitable ) theProjectileSplitable->Set4Momentum(Pprojectile);
972 
973     #ifdef debugPutOnMassShell
974       G4cout << "Final proj. mom in Lab. " <<theProjectile.GetMomentum()/GeV<<" "
975                                            <<theProjectile.GetTotalEnergy()/GeV<<" GeV"<<G4endl;
976     #endif
977 
978   } else {  // nucleus-nucleus or antinucleus-nucleus collision
979 
980     isOk = FinalizeKinematics( WplusProjectile, true, toLab, PrResidualMass, 
981                                ProjectileResidualMassNumber, NumberOfInvolvedNucleonsOfProjectile,
982                                TheInvolvedNucleonsOfProjectile, ProjectileResidual4Momentum );
983 
984     #ifdef debugPutOnMassShell
985       G4cout << "Projectile Residual4Momentum in CMS " << ProjectileResidual4Momentum/GeV <<" GeV"<< G4endl;
986     #endif
987 
988     if ( ! isOk ) return false;
989 
990     ProjectileResidual4Momentum.transform( toLab );
991 
992     #ifdef debugPutOnMassShell
993       G4cout << "Projectile Residual4Momentum in Lab " << ProjectileResidual4Momentum/GeV <<" GeV"<< G4endl;
994     #endif
995 
996   }
997 
998   isOk = FinalizeKinematics( WminusTarget, false, toLab, TargetResidualMass, 
999                              TargetResidualMassNumber, NumberOfInvolvedNucleonsOfTarget,
1000                              TheInvolvedNucleonsOfTarget, TargetResidual4Momentum );
1001 
1002   #ifdef debugPutOnMassShell
1003     G4cout << "Target Residual4Momentum in CMS " << TargetResidual4Momentum/GeV << " GeV "<< G4endl;
1004   #endif
1005 
1006   if ( ! isOk ) return false;
1007 
1008   TargetResidual4Momentum.transform( toLab );
1009 
1010   #ifdef debugPutOnMassShell
1011     G4cout << "Target Residual4Momentum in Lab " << TargetResidual4Momentum/GeV << " GeV "<< G4endl;
1012   #endif
1013 
1014   return true;
1015 
1016 }
1017 
1018 //============================================================================
1019 
1020 G4ThreeVector G4QGSParticipants::GaussianPt( G4double AveragePt2, G4double maxPtSquare ) const {
1021   //  @@ this method is used in FTFModel as well. Should go somewhere common!
1022 
1023   G4double Pt2( 0.0 ), Pt(0.0);
1024   if ( AveragePt2 > 0.0 ) {
1025     G4double x = maxPtSquare/AveragePt2;
1026     Pt2 = (x < 200) ?
1027       -AveragePt2 * G4Log( 1.0 + G4UniformRand() * ( G4Exp( -x ) -1.0 ) )
1028       : -AveragePt2 * G4Log( 1.0 - G4UniformRand() );
1029     Pt = std::sqrt( Pt2 );
1030   }
1031   G4double phi = G4UniformRand() * twopi;
1032 
1033   return G4ThreeVector( Pt*std::cos(phi), Pt*std::sin(phi), 0.0 );    
1034 }
1035 //============================================================================
1036 
1037 G4bool G4QGSParticipants::
1038 ComputeNucleusProperties( G4V3DNucleus* nucleus,               // input parameter 
1039                           G4LorentzVector& nucleusMomentum,    // input & output parameter
1040                           G4LorentzVector& residualMomentum,   // input & output parameter
1041                           G4double& sumMasses,                 // input & output parameter
1042                           G4double& residualExcitationEnergy,  // input & output parameter
1043                           G4double& residualMass,              // input & output parameter
1044                           G4int& residualMassNumber,           // input & output parameter
1045                           G4int& residualCharge ) {            // input & output parameter
1046 
1047   // This method, which is called only by PutOnMassShell, computes some nucleus properties for:
1048   // -  either the target nucleus (which is never an antinucleus): this for any kind
1049   //    of hadronic interaction (hadron-nucleus, nucleus-nucleus, antinucleus-nucleus);
1050   // -  or the projectile nucleus or antinucleus: this only in the case of nucleus-nucleus
1051   //    or antinucleus-nucleus interaction.
1052   // This method assumes that the all the parameters have been initialized by the caller;
1053   // the action of this method consists in modifying all these parameters, except the
1054   // first one. The return value is "false" only in the case the pointer to the nucleus
1055   // is null.
1056 
1057   if ( ! nucleus ) return false;
1058 
1059   G4double ExcitationEPerWoundedNucleon = GetExcitationEnergyPerWoundedNucleon();
1060 
1061   // Loop over the nucleons of the nucleus. 
1062   // The nucleons that have been involved in the interaction (either from Glauber or
1063   // Reggeon Cascading) will be candidate to be emitted.
1064   // All the remaining nucleons will be the nucleons of the candidate residual nucleus.
1065   // The variable sumMasses is the amount of energy corresponding to:
1066   //     1. transverse mass of each involved nucleon
1067   //     2. 20.0*MeV separation energy for each involved nucleon
1068   //     3. transverse mass of the residual nucleus
1069   // In this first evaluation of sumMasses, the excitation energy of the residual nucleus
1070   // (residualExcitationEnergy, estimated by adding a constant value to each involved
1071   // nucleon) is not taken into account.
1072   G4Nucleon* aNucleon = 0;
1073   nucleus->StartLoop();
1074   while ( ( aNucleon = nucleus->GetNextNucleon() ) ) {  /* Loop checking, 07.08.2015, A.Ribon */
1075     nucleusMomentum += aNucleon->Get4Momentum();
1076     if ( aNucleon->AreYouHit() ) {  // Involved nucleons
1077       // Consider in sumMasses the nominal, i.e. on-shell, masses of the nucleons
1078       // (not the current masses, which could be different because the nucleons are off-shell).
1079 
1080       sumMasses += std::sqrt( sqr( aNucleon->GetDefinition()->GetPDGMass() ) 
1081                               +  aNucleon->Get4Momentum().perp2() );                     
1082       sumMasses += 20.0*MeV;  // Separation energy for a nucleon
1083 
1084       //residualExcitationEnergy += ExcitationEPerWoundedNucleon;
1085       residualExcitationEnergy += -ExcitationEPerWoundedNucleon*G4Log( G4UniformRand());
1086       residualMassNumber--;
1087       // The absolute value below is needed only in the case of anti-nucleus.
1088       residualCharge -= std::abs( G4int( aNucleon->GetDefinition()->GetPDGCharge() ) );
1089     } else {   // Spectator nucleons
1090       residualMomentum += aNucleon->Get4Momentum();
1091     }
1092   }
1093   #ifdef debugPutOnMassShell
1094     G4cout << "ExcitationEnergyPerWoundedNucleon " << ExcitationEPerWoundedNucleon <<" MeV"<<G4endl
1095            << "\t Residual Charge, MassNumber " << residualCharge << " " << residualMassNumber
1096            << G4endl << "\t Initial Momentum " << nucleusMomentum/GeV<<" GeV"
1097            << G4endl << "\t Residual Momentum   " << residualMomentum/GeV<<" GeV"<<G4endl;
1098   #endif
1099 
1100   residualMomentum.setPz( 0.0 ); 
1101   residualMomentum.setE( 0.0 );
1102   if ( residualMassNumber == 0 ) {
1103     residualMass = 0.0;
1104     residualExcitationEnergy = 0.0;
1105   } else {
1106     residualMass = G4ParticleTable::GetParticleTable()->GetIonTable()->
1107                      GetIonMass( residualCharge, residualMassNumber );
1108     if ( residualMassNumber == 1 ) {
1109       residualExcitationEnergy = 0.0;
1110     }
1111   }
1112   sumMasses += std::sqrt( sqr( residualMass ) + residualMomentum.perp2() );
1113   return true;
1114 }
1115 
1116 
1117 //============================================================================
1118 
1119 G4bool G4QGSParticipants::
1120 GenerateDeltaIsobar( const G4double sqrtS,                  // input parameter
1121                      const G4int numberOfInvolvedNucleons,  // input parameter
1122                      G4Nucleon* involvedNucleons[],         // input & output parameter
1123                      G4double& sumMasses ) {                // input & output parameter
1124 
1125   // This method, which is called only by PutOnMassShell, check whether is possible to
1126   // re-interpret some of the involved nucleons as delta-isobars:
1127   // - either by replacing a proton (2212) with a Delta+ (2214),
1128   // - or by replacing a neutron (2112) with a Delta0 (2114).
1129   // The on-shell mass of these delta-isobars is ~1232 MeV, so  ~292-294 MeV  heavier than
1130   // the corresponding nucleon on-shell mass. However  400.0*MeV  is considered to estimate
1131   // the max number of deltas compatible with the available energy.
1132   // The delta-isobars are considered with the same transverse momentum as their
1133   // corresponding nucleons.
1134   // This method assumes that all the parameters have been initialized by the caller;
1135   // the action of this method consists in modifying (eventually) involveNucleons and
1136   // sumMasses. The return value is "false" only in the case that the input parameters
1137   // have unphysical values.
1138 
1139   if ( sqrtS < 0.0  ||  numberOfInvolvedNucleons <= 0  ||  sumMasses < 0.0 ) return false;
1140 
1141   //const G4double ProbDeltaIsobar = 0.05;  // Uzhi 6.07.2012
1142   //const G4double ProbDeltaIsobar = 0.25;  // Uzhi 13.06.2013 
1143   const G4double probDeltaIsobar = 0.10;  // A.R. 07.08.2013
1144 
1145   G4int maxNumberOfDeltas = G4int( (sqrtS - sumMasses)/(400.0*MeV) );
1146   G4int numberOfDeltas = 0;
1147 
1148   for ( G4int i = 0; i < numberOfInvolvedNucleons; i++ ) {
1149     //G4cout << "i maxNumberOfDeltas probDeltaIsobar " << i << " " << maxNumberOfDeltas
1150     //       << " " << probDeltaIsobar << G4endl;
1151     if ( G4UniformRand() < probDeltaIsobar  &&  numberOfDeltas < maxNumberOfDeltas ) {
1152       numberOfDeltas++;
1153       if ( ! involvedNucleons[i] ) continue;
1154       G4VSplitableHadron* splitableHadron = involvedNucleons[i]->GetSplitableHadron();
1155       G4double massNuc = std::sqrt( sqr( splitableHadron->GetDefinition()->GetPDGMass() )
1156                                     + splitableHadron->Get4Momentum().perp2() );
1157       //AR The absolute value below is needed in the case of an antinucleus. 
1158       G4int pdgCode = std::abs( splitableHadron->GetDefinition()->GetPDGEncoding() );
1159       const G4ParticleDefinition* old_def = splitableHadron->GetDefinition();
1160       G4int newPdgCode = pdgCode/10; newPdgCode = newPdgCode*10 + 4; // Delta
1161       if ( splitableHadron->GetDefinition()->GetPDGEncoding() < 0 ) newPdgCode *= -1;
1162       const G4ParticleDefinition* ptr = 
1163         G4ParticleTable::GetParticleTable()->FindParticle( newPdgCode );
1164       splitableHadron->SetDefinition( ptr );
1165       G4double massDelta = std::sqrt( sqr( splitableHadron->GetDefinition()->GetPDGMass() )
1166                                       + splitableHadron->Get4Momentum().perp2() );
1167       //G4cout << i << " " << sqrtS/GeV << " " << sumMasses/GeV << " " << massDelta/GeV
1168       //       << " " << massNuc << G4endl;
1169       if ( sqrtS < sumMasses + massDelta - massNuc ) {  // Change cannot be accepted!
1170         splitableHadron->SetDefinition( old_def );
1171         break;
1172       } else {  // Change is accepted
1173         sumMasses += ( massDelta - massNuc );
1174       }
1175     } 
1176   }
1177   //G4cout << "maxNumberOfDeltas numberOfDeltas " << maxNumberOfDeltas << " " 
1178   //       << numberOfDeltas << G4endl;
1179   return true;
1180 }
1181 
1182 
1183 //============================================================================
1184 
1185 G4bool G4QGSParticipants::
1186 SamplingNucleonKinematics( G4double averagePt2,                   // input parameter
1187                            const G4double maxPt2,                 // input parameter
1188                            G4double dCor,                         // input parameter
1189                            G4V3DNucleus* nucleus,                 // input parameter
1190                            const G4LorentzVector& pResidual,      // input parameter
1191                            const G4double residualMass,           // input parameter
1192                            const G4int residualMassNumber,        // input parameter
1193                            const G4int numberOfInvolvedNucleons,  // input parameter 
1194                            G4Nucleon* involvedNucleons[],         // input & output parameter
1195                            G4double& mass2 ) {                    // output parameter
1196 
1197   // This method, which is called only by PutOnMassShell, does the sampling of:
1198   // -  either the target nucleons: this for any kind of hadronic interactions
1199   //    (hadron-nucleus, nucleus-nucleus, antinucleus-nucleus);
1200   // -  or the projectile nucleons or antinucleons: this only in the case of
1201   //    nucleus-nucleus or antinucleus-nucleus interactions, respectively.
1202   // This method assumes that all the parameters have been initialized by the caller;
1203   // the action of this method consists in changing the properties of the nucleons
1204   // whose pointers are in the vector involvedNucleons, as well as changing the
1205   // variable mass2.
1206 
1207   if ( ! nucleus ) return false;
1208 
1209   if ( residualMassNumber == 0  &&  numberOfInvolvedNucleons == 1 ) {
1210     dCor = 0.0; 
1211     averagePt2 = 0.0;
1212   } 
1213 
1214   G4bool success = true;                            
1215 
1216   G4double SumMasses = residualMass; 
1217   for ( G4int i = 0; i < numberOfInvolvedNucleons; i++ ) {
1218     G4Nucleon* aNucleon = involvedNucleons[i];
1219     if ( ! aNucleon ) continue;
1220     SumMasses += aNucleon->GetSplitableHadron()->GetDefinition()->GetPDGMass();
1221   }
1222 
1223   const G4int maxNumberOfLoops = 1000;
1224   G4int loopCounter = 0;
1225   do {
1226 
1227     success = true;
1228     G4ThreeVector ptSum( 0.0, 0.0, 0.0 );
1229     G4double xSum = 0.0;
1230 
1231     for ( G4int i = 0; i < numberOfInvolvedNucleons; i++ ) {
1232       G4Nucleon* aNucleon = involvedNucleons[i];
1233       if ( ! aNucleon ) continue;
1234       G4ThreeVector tmpPt = GaussianPt( averagePt2, maxPt2 );
1235       ptSum += tmpPt;
1236       G4ThreeVector tmpX = GaussianPt( dCor*dCor, 1.0 );
1237       G4double x = tmpX.x() +
1238                    aNucleon->GetSplitableHadron()->GetDefinition()->GetPDGMass()/SumMasses;
1239       if ( x < 0.0  ||  x > 1.0 ) { 
1240         success = false; 
1241         break;
1242       }
1243       xSum += x;
1244       //AR The energy is in the lab (instead of cms) frame but it will not be used.
1245       G4LorentzVector tmp( tmpPt.x(), tmpPt.y(), x, aNucleon->Get4Momentum().e() );
1246       aNucleon->SetMomentum( tmp );
1247     }
1248 
1249     if ( xSum < 0.0  ||  xSum > 1.0 ) success = false;
1250 
1251     if ( ! success ) continue;
1252 
1253     G4double deltaPx = ( ptSum.x() - pResidual.x() ) / numberOfInvolvedNucleons;
1254     G4double deltaPy = ( ptSum.y() - pResidual.y() ) / numberOfInvolvedNucleons;
1255     G4double delta = 0.0;
1256     if ( residualMassNumber == 0 ) {
1257       delta = ( xSum - 1.0 ) / numberOfInvolvedNucleons;
1258     } else {
1259       delta = 0.0;
1260     }
1261 
1262     xSum = 1.0;
1263     mass2 = 0.0;
1264     for ( G4int i = 0; i < numberOfInvolvedNucleons; i++ ) {
1265       G4Nucleon* aNucleon = involvedNucleons[i];
1266       if ( ! aNucleon ) continue;
1267       G4double x = aNucleon->Get4Momentum().pz() - delta;
1268       xSum -= x;               
1269       if ( residualMassNumber == 0 ) {
1270         if ( x <= 0.0  ||  x > 1.0 ) {
1271           success = false; 
1272           break;
1273         }
1274       } else {
1275         if ( x <= 0.0  ||  x > 1.0  ||  xSum <= 0.0  ||  xSum > 1.0 ) {
1276           success = false; 
1277           break;
1278         }
1279       }                                          
1280       G4double px = aNucleon->Get4Momentum().px() - deltaPx;
1281       G4double py = aNucleon->Get4Momentum().py() - deltaPy;
1282       mass2 += ( sqr( aNucleon->GetSplitableHadron()->GetDefinition()->GetPDGMass() )
1283                     + sqr( px ) + sqr( py ) ) / x;
1284       G4LorentzVector tmp( px, py, x, aNucleon->Get4Momentum().e() );
1285       aNucleon->SetMomentum( tmp );
1286     }
1287 
1288     if ( success  &&  residualMassNumber != 0 ) {
1289       mass2 += ( sqr( residualMass ) + pResidual.perp2() ) / xSum;
1290     }
1291 
1292     #ifdef debugPutOnMassShell
1293       G4cout << "success " << success << G4endl << " Mt " << std::sqrt( mass2 )/GeV << G4endl;
1294     #endif
1295 
1296   } while ( ( ! success ) && 
1297             ++loopCounter < maxNumberOfLoops );  /* Loop checking, 07.08.2015, A.Ribon */
1298   if ( loopCounter >= maxNumberOfLoops ) {
1299     success = false;
1300   }
1301 
1302   return success;
1303 }
1304 
1305 
1306 //============================================================================
1307 
1308 G4bool G4QGSParticipants::
1309 CheckKinematics( const G4double sValue,                 // input parameter
1310                  const G4double sqrtS,                  // input parameter
1311                  const G4double projectileMass2,        // input parameter
1312                  const G4double targetMass2,            // input parameter
1313                  const G4double nucleusY,               // input parameter
1314                  const G4bool isProjectileNucleus,      // input parameter
1315                  const G4int numberOfInvolvedNucleons,  // input parameter 
1316                  G4Nucleon* involvedNucleons[],         // input parameter
1317                  G4double& targetWminus,                // output parameter
1318                  G4double& projectileWplus,             // output parameter
1319                  G4bool& success ) {                    // input & output parameter
1320 
1321   // This method, which is called only by PutOnMassShell, checks whether the
1322   // kinematics is acceptable or not.
1323   // This method assumes that all the parameters have been initialized by the caller;
1324   // notice that the input boolean parameter isProjectileNucleus is meant to be true
1325   // only in the case of nucleus or antinucleus projectile.
1326   // The action of this method consists in computing targetWminus and projectileWplus
1327   // and setting the parameter success to false in the case that the kinematics should
1328   // be rejeted.
1329 
1330   G4double decayMomentum2 = sqr( sValue ) + sqr( projectileMass2 ) + sqr( targetMass2 )
1331                             - 2.0*sValue*projectileMass2 - 2.0*sValue*targetMass2 
1332                             - 2.0*projectileMass2*targetMass2;
1333   targetWminus = ( sValue - projectileMass2 + targetMass2 + std::sqrt( decayMomentum2 ) )
1334                  / 2.0 / sqrtS;
1335   projectileWplus = sqrtS - targetMass2/targetWminus;
1336   G4double projectilePz = projectileWplus/2.0 - projectileMass2/2.0/projectileWplus;
1337   G4double projectileE  = projectileWplus/2.0 + projectileMass2/2.0/projectileWplus;
1338   G4double projectileY(1.0e5);
1339   if (projectileE - projectilePz > 0.) {
1340            projectileY  = 0.5 * G4Log( (projectileE + projectilePz)/
1341                                        (projectileE - projectilePz) );
1342   }
1343   G4double targetPz = -targetWminus/2.0 + targetMass2/2.0/targetWminus;
1344   G4double targetE  =  targetWminus/2.0 + targetMass2/2.0/targetWminus;
1345   G4double targetY  = 0.5 * G4Log( (targetE + targetPz)/(targetE - targetPz) );
1346 
1347   #ifdef debugPutOnMassShell
1348     G4cout << "decayMomentum2 " << decayMomentum2 << G4endl 
1349            << "\t targetWminus projectileWplus " << targetWminus << " " << projectileWplus << G4endl
1350            << "\t projectileY targetY " << projectileY << " " << targetY << G4endl;
1351   #endif
1352 
1353   for ( G4int i = 0; i < numberOfInvolvedNucleons; i++ ) {
1354     G4Nucleon* aNucleon = involvedNucleons[i];
1355     if ( ! aNucleon ) continue;
1356     G4LorentzVector tmp = aNucleon->Get4Momentum();
1357     G4double mt2 = sqr( tmp.x() ) + sqr( tmp.y() ) +
1358                    sqr( aNucleon->GetSplitableHadron()->GetDefinition()->GetPDGMass() );
1359     G4double x = tmp.z();
1360     G4double pz = -targetWminus*x/2.0 + mt2/(2.0*targetWminus*x);
1361     G4double e =   targetWminus*x/2.0 + mt2/(2.0*targetWminus*x);
1362     if ( isProjectileNucleus ) {
1363       pz = projectileWplus*x/2.0 - mt2/(2.0*projectileWplus*x);
1364       e =  projectileWplus*x/2.0 + mt2/(2.0*projectileWplus*x);
1365     }
1366     G4double nucleonY = 0.5 * G4Log( (e + pz)/(e - pz) ); 
1367 
1368     #ifdef debugPutOnMassShell
1369       G4cout << "i nY pY nY-AY AY " << i << " " << nucleonY << " " << projectileY <<G4endl;
1370     #endif
1371 
1372     if ( std::abs( nucleonY - nucleusY ) > 2  ||  
1373          ( isProjectileNucleus  &&  targetY > nucleonY )  ||
1374          ( ! isProjectileNucleus  &&  projectileY < nucleonY ) ) {
1375       success = false; 
1376       break;
1377     } 
1378   }
1379   return true;
1380 }  
1381 
1382   
1383 //============================================================================
1384 
1385 G4bool G4QGSParticipants::
1386 FinalizeKinematics( const G4double w,                            // input parameter
1387                     const G4bool isProjectileNucleus,            // input parameter
1388                     const G4LorentzRotation& boostFromCmsToLab,  // input parameter
1389                     const G4double residualMass,                 // input parameter
1390                     const G4int residualMassNumber,              // input parameter
1391                     const G4int numberOfInvolvedNucleons,        // input parameter 
1392                     G4Nucleon* involvedNucleons[],               // input & output parameter
1393               G4LorentzVector& residual4Momentum ) {       // output parameter
1394 
1395   // This method, which is called only by PutOnMassShell, finalizes the kinematics:
1396   // this method is called when we are sure that the sampling of the kinematics is
1397   // acceptable.
1398   // This method assumes that all the parameters have been initialized by the caller;
1399   // notice that the input boolean parameter isProjectileNucleus is meant to be true
1400   // only in the case of nucleus or antinucleus projectile: this information is needed
1401   // because the sign of pz (in the center-of-mass frame) in this case is opposite
1402   // with respect to the case of a normal hadron projectile.
1403   // The action of this method consists in modifying the momenta of the nucleons
1404   // (in the lab frame) and computing the residual 4-momentum (in the center-of-mass
1405   // frame).
1406 
1407   G4ThreeVector residual3Momentum( 0.0, 0.0, 1.0 );
1408 
1409   for ( G4int i = 0; i < numberOfInvolvedNucleons; i++ ) {
1410     G4Nucleon* aNucleon = involvedNucleons[i];
1411     if ( ! aNucleon ) continue;
1412     G4LorentzVector tmp = aNucleon->Get4Momentum();
1413     residual3Momentum -= tmp.vect();
1414     G4double mt2 = sqr( tmp.x() ) + sqr( tmp.y() ) +
1415                    sqr( aNucleon->GetSplitableHadron()->GetDefinition()->GetPDGMass() );
1416     G4double x = tmp.z();
1417     G4double pz = -w * x / 2.0  +  mt2 / ( 2.0 * w * x );
1418     G4double e  =  w * x / 2.0  +  mt2 / ( 2.0 * w * x );
1419     // Reverse the sign of pz in the case of nucleus or antinucleus projectile
1420     if ( isProjectileNucleus ) pz *= -1.0;
1421     tmp.setPz( pz ); 
1422     tmp.setE( e );
1423     tmp.transform( boostFromCmsToLab );
1424     aNucleon->SetMomentum( tmp );
1425     G4VSplitableHadron* splitableHadron = aNucleon->GetSplitableHadron();
1426     splitableHadron->Set4Momentum( tmp );
1427     #ifdef debugPutOnMassShell
1428       G4cout << "Target involved nucleon No, name, 4Mom " 
1429             << i<<" "<<aNucleon->GetDefinition()->GetParticleName()<<" "<<tmp<< G4endl;
1430     #endif
1431   }
1432 
1433   G4double residualMt2 = sqr( residualMass ) + sqr( residual3Momentum.x() )
1434                        + sqr( residual3Momentum.y() );
1435 
1436   #ifdef debugPutOnMassShell
1437     G4cout <<G4endl<< "w residual3Momentum.z() " << w << " " << residual3Momentum.z() << G4endl;
1438   #endif
1439 
1440   G4double residualPz = 0.0;
1441   G4double residualE  = 0.0;
1442   if ( residualMassNumber != 0 ) {
1443     residualPz = -w * residual3Momentum.z() / 2.0 + 
1444                   residualMt2 / ( 2.0 * w * residual3Momentum.z() );
1445     residualE  =  w * residual3Momentum.z() / 2.0 + 
1446                   residualMt2 / ( 2.0 * w * residual3Momentum.z() );
1447     // Reverse the sign of residualPz in the case of nucleus or antinucleus projectile
1448     if ( isProjectileNucleus ) residualPz *= -1.0;
1449   }
1450 
1451   residual4Momentum.setPx( residual3Momentum.x() );
1452   residual4Momentum.setPy( residual3Momentum.y() );
1453   residual4Momentum.setPz( residualPz ); 
1454   residual4Momentum.setE( residualE );
1455 
1456   return true;
1457 }
1458 
1459 //======================================================
1460 void G4QGSParticipants::PerformDiffractiveCollisions()
1461 {
1462   #ifdef debugQGSParticipants
1463    G4cout<<G4endl<<"PerformDiffractiveCollisions()......"<<G4endl
1464          <<"theInteractions.size() "<<theInteractions.size()<<G4endl;
1465   #endif
1466 
1467   unsigned int i;
1468   for (i = 0; i < theInteractions.size(); i++)
1469   {
1470     G4InteractionContent* anIniteraction = theInteractions[i];
1471     #ifdef debugQGSParticipants
1472       G4cout<<"Interaction # and its status "
1473             <<i<<" "<<theInteractions[i]->GetStatus()<<G4endl;
1474     #endif
1475 
1476     G4int InterStatus = theInteractions[i]->GetStatus(); 
1477     if ( (InterStatus == PrD) || (InterStatus == TrD) || (InterStatus == DD))
1478     {  // Selection of diffractive interactions
1479       #ifdef debugQGSParticipants
1480         G4cout<<"Simulation of diffractive interaction. "<<InterStatus <<" PrD/TrD/DD/ND/Qech - 0,1,2,3,4"<<G4endl;
1481       #endif
1482 
1483       G4VSplitableHadron* aTarget = anIniteraction->GetTarget();
1484 
1485       #ifdef debugQGSParticipants
1486         G4cout<<"The proj. before inter "
1487               <<theProjectileSplitable->Get4Momentum()<<" "
1488               <<theProjectileSplitable->Get4Momentum().mag()<<G4endl;
1489         G4cout<<"The targ. before inter " <<aTarget->Get4Momentum()<<" "
1490               <<aTarget->Get4Momentum().mag()<<G4endl;
1491       #endif
1492 
1493       if ( InterStatus == PrD ) 
1494         theSingleDiffExcitation.ExciteParticipants(theProjectileSplitable, aTarget, TRUE); 
1495 
1496       if ( InterStatus == TrD ) 
1497         theSingleDiffExcitation.ExciteParticipants(theProjectileSplitable, aTarget, FALSE);
1498 
1499       if ( InterStatus == DD ) 
1500         theDiffExcitaton.ExciteParticipants(theProjectileSplitable, aTarget);
1501 
1502       #ifdef debugQGSParticipants
1503         G4cout<<"The proj. after  inter " <<theProjectileSplitable->Get4Momentum()<<" "
1504               <<theProjectileSplitable->Get4Momentum().mag()<<G4endl;
1505   G4cout<<"The targ. after  inter " <<aTarget->Get4Momentum()<<" "
1506               <<aTarget->Get4Momentum().mag()<<G4endl;
1507       #endif
1508     }
1509 
1510     if ( InterStatus == Qexc )
1511     {  // Quark exchange process
1512       #ifdef debugQGSParticipants
1513         G4cout<<"Simulation of interaction with quark exchange."<<G4endl;
1514       #endif
1515       G4VSplitableHadron* aTarget = anIniteraction->GetTarget();
1516 
1517       #ifdef debugQGSParticipants
1518         G4cout<<"The proj. before inter " <<theProjectileSplitable->Get4Momentum()<<" "
1519               <<theProjectileSplitable->Get4Momentum().mag()<<G4endl;
1520         G4cout<<"The targ. before inter "<<aTarget->Get4Momentum()<<" "
1521               <<aTarget->Get4Momentum().mag()<<G4endl;
1522       #endif
1523 
1524       theQuarkExchange.ExciteParticipants(theProjectileSplitable, aTarget);
1525 
1526       #ifdef debugQGSParticipants
1527         G4cout<<"The proj. after  inter " <<theProjectileSplitable->Get4Momentum()<<" "
1528               <<theProjectileSplitable->Get4Momentum().mag()<<G4endl;
1529   G4cout<<"The targ. after  inter " <<aTarget->Get4Momentum()<<" "
1530               <<aTarget->Get4Momentum().mag()<<G4endl;
1531       #endif
1532     }
1533   }
1534 }
1535 
1536 //======================================================
1537 G4bool G4QGSParticipants::DeterminePartonMomenta()
1538 {
1539   if ( ! theProjectileSplitable ) return false;
1540 
1541   const G4double aHugeValue = 1.0e+10;
1542 
1543   #ifdef debugQGSParticipants
1544     G4cout<<G4endl<<"DeterminePartonMomenta()......"<<G4endl;
1545     G4cout<<"theProjectile status (0 -nondiffr, #0 diffr./reggeon):  "<<theProjectileSplitable->GetStatus()<<G4endl;
1546   #endif
1547 
1548   if (theProjectileSplitable->GetStatus() != 0) {return false;} // There were only diffractive interactions.
1549 
1550   G4LorentzVector Projectile4Momentum  = theProjectileSplitable->Get4Momentum();
1551   G4LorentzVector Psum = Projectile4Momentum;
1552 
1553   G4double VqM_pr(0.), VaqM_pr(0.), VqM_tr(350.), VqqM_tr(700);
1554   if (std::abs(theProjectile.GetDefinition()->GetBaryonNumber()) != 0) {VqM_pr=350*MeV; VaqM_pr=700*MeV;}
1555 
1556   #ifdef debugQGSParticipants
1557     G4cout<<"Projectile 4 momentum "<<Psum<<G4endl
1558           <<"Target nucleon momenta at start"<<G4endl;
1559     G4int NuclNo=0;
1560   #endif
1561 
1562   std::vector<G4VSplitableHadron*>::iterator i;
1563 
1564   for (i = theTargets.begin(); i != theTargets.end(); i++ )
1565   {
1566     Psum += (*i)->Get4Momentum();
1567     #ifdef debugQGSParticipants
1568       G4cout<<"Nusleus nucleon # and its 4Mom. "<<NuclNo<<" "<<(*i)->Get4Momentum()<<G4endl;
1569       NuclNo++;
1570     #endif
1571   }
1572 
1573   G4LorentzRotation toCms( -1*Psum.boostVector() );
1574 
1575   G4LorentzVector Ptmp = toCms*Projectile4Momentum;
1576 
1577   toCms.rotateZ( -1*Ptmp.phi() );
1578   toCms.rotateY( -1*Ptmp.theta() );
1579   G4LorentzRotation toLab(toCms.inverse());
1580   Projectile4Momentum.transform( toCms );
1581   //  Ptarget.transform( toCms );
1582 
1583   #ifdef debugQGSParticipants
1584     G4cout<<G4endl<<"In CMS---------------"<<G4endl;
1585     G4cout<<"Projectile 4 Mom "<<Projectile4Momentum<<G4endl;
1586     NuclNo=0;
1587   #endif
1588 
1589   G4LorentzVector Target4Momentum(0.,0.,0.,0.);
1590   for(i = theTargets.begin(); i != theTargets.end(); i++ )
1591   {
1592     G4LorentzVector tmp= (*i)->Get4Momentum();  tmp.transform( toCms );
1593     (*i)->Set4Momentum( tmp );
1594     #ifdef debugQGSParticipants
1595       G4cout<<"Target nucleon # and 4Mom "<<" "<<NuclNo<<" "<<(*i)->Get4Momentum()<<G4endl;
1596       NuclNo++;
1597     #endif
1598     Target4Momentum += tmp;
1599   }
1600 
1601   G4double S     = Psum.mag2();
1602   G4double SqrtS = std::sqrt(S);
1603 
1604   #ifdef debugQGSParticipants
1605     G4cout<<"Sum of target nucleons 4 momentum "<<Target4Momentum<<G4endl<<G4endl;
1606     G4cout<<"Target nucleons mom: px, py, z_1, m_i"<<G4endl;
1607     NuclNo=0;
1608   #endif
1609 
1610   //G4double PplusProjectile = Projectile4Momentum.plus();
1611   G4double PminusTarget    = Target4Momentum.minus();
1612   
1613   for(i = theTargets.begin(); i != theTargets.end(); i++ )
1614   {
1615     G4LorentzVector tmp = (*i)->Get4Momentum(); // tmp.boost(bstToCM);
1616 
1617     //AR-19Jan2017 : the following line is causing a strange crash when Geant4
1618     //               is built in optimized mode.
1619     //               To fix it, I get the mass square instead of directly the
1620     //               mass from the Lorentz vector, and then I take care of the
1621     //               square root. If the mass square is negative, a JustWarning
1622     //               exception is thrown, and the mass is set to 0.
1623     //G4double Mass = tmp.mag();
1624     G4double Mass2 = tmp.mag2();
1625     G4double Mass = 0.0;
1626     if ( Mass2 < 0.0 ) {
1627       G4ExceptionDescription ed;
1628       ed << "Projectile " << theProjectile.GetDefinition()->GetParticleName()
1629          << "  4-momentum " << Psum << G4endl;
1630       ed << "LorentzVector tmp " << tmp << "  with Mass2 " << Mass2 << G4endl;
1631       G4Exception( "G4QGSParticipants::DeterminePartonMomenta(): 4-momentum with negative mass!",
1632                    "HAD_QGSPARTICIPANTS_001", JustWarning, ed );
1633     } else {
1634       Mass = std::sqrt( Mass2 );
1635     }
1636 
1637     tmp.setPz(tmp.minus()/PminusTarget);   tmp.setE(Mass);
1638     (*i)->Set4Momentum(tmp); 
1639     #ifdef debugQGSParticipants
1640       G4cout<<"Target nucleons # and mom: "<<NuclNo<<" "<<(*i)->Get4Momentum()<<G4endl;
1641       NuclNo++;
1642     #endif
1643   }
1644 
1645   //+++++++++++++++++++++++++++++++++++++++++++
1646 
1647   G4double SigPt = sigmaPt;
1648   G4Parton* aParton(0);
1649   G4ThreeVector aPtVector(0.,0.,0.);
1650   G4LorentzVector tmp(0.,0.,0.,0.);
1651 
1652   G4double Mt(0.);
1653   G4double ProjSumMt(0.), ProjSumMt2perX(0.);
1654   G4double TargSumMt(0.), TargSumMt2perX(0.);
1655 
1656 
1657   G4double aBeta = beta;   // Member of the class
1658 
1659   const G4ParticleDefinition* theProjectileDefinition = theProjectileSplitable->GetDefinition();
1660   if (theProjectileDefinition == G4PionMinus::PionMinusDefinition()) aBeta = 1.;
1661   if (theProjectileDefinition == G4Gamma::GammaDefinition())         aBeta = 1.;
1662   if (theProjectileDefinition == G4PionPlus::PionPlusDefinition())   aBeta = 1.;
1663   if (theProjectileDefinition == G4PionZero::PionZeroDefinition())   aBeta = 1.;
1664   if (theProjectileDefinition == G4KaonPlus::KaonPlusDefinition())   aBeta = 0.;
1665   if (theProjectileDefinition == G4KaonMinus::KaonMinusDefinition()) aBeta = 0.;
1666 
1667   G4double Xmin = 0.;
1668 
1669   G4bool Success = true;  G4int attempt = 0;
1670   const G4int maxNumberOfAttempts = 1000;
1671   do
1672   {
1673     attempt++;  if( attempt ==  100*(attempt/100) ) {SigPt/=2.;}
1674 
1675     ProjSumMt=0.; ProjSumMt2perX=0.;
1676     TargSumMt=0.; TargSumMt2perX=0.;
1677 
1678     Success = true;
1679     G4int nSeaPair = theProjectileSplitable->GetSoftCollisionCount()-1;
1680     #ifdef debugQGSParticipants
1681       G4cout<<"attempt ------------------------ "<<attempt<<G4endl;
1682       G4cout<<"nSeaPair of proj "<<nSeaPair<<G4endl;
1683     #endif
1684 
1685     G4double SumPx = 0.;
1686     G4double SumPy = 0.;
1687     G4double SumZ = 0.;
1688     G4int NumberOfUnsampledSeaQuarks = 2*nSeaPair;
1689 
1690     G4double Qmass=0.;
1691     for (G4int aSeaPair = 0; aSeaPair < nSeaPair; aSeaPair++)
1692     {
1693       aParton = theProjectileSplitable->GetNextParton();   // for quarks
1694       #ifdef debugQGSParticipants
1695         G4cout<<"Sea quarks: "<<aSeaPair<<" "<<aParton->GetDefinition()->GetParticleName();
1696       #endif
1697       aPtVector = GaussianPt(SigPt, aHugeValue);
1698       tmp.setPx(aPtVector.x()); tmp.setPy(aPtVector.y());
1699       SumPx += aPtVector.x();   SumPy += aPtVector.y();
1700       Mt = std::sqrt(aPtVector.mag2()+sqr(Qmass));
1701       ProjSumMt += Mt; 
1702 
1703       // Sampling of Z fraction
1704       tmp.setPz(SampleX(Xmin, NumberOfUnsampledSeaQuarks, 2*nSeaPair, aBeta)*(1.0-SumZ)); 
1705       SumZ += tmp.z();
1706 
1707       NumberOfUnsampledSeaQuarks--;
1708       ProjSumMt2perX +=sqr(Mt)/tmp.pz();
1709       tmp.setE(sqr(Mt));
1710       aParton->Set4Momentum(tmp);
1711 
1712       aParton = theProjectileSplitable->GetNextAntiParton();   // for anti-quarks
1713       #ifdef debugQGSParticipants
1714         G4cout<<" "<<aParton->GetDefinition()->GetParticleName()<<G4endl;
1715         G4cout<<"              "<<tmp<<" "<<SumZ<<G4endl;
1716       #endif
1717       aPtVector = GaussianPt(SigPt, aHugeValue);
1718       tmp.setPx(aPtVector.x()); tmp.setPy(aPtVector.y());
1719       SumPx += aPtVector.x();   SumPy += aPtVector.y();
1720       Mt = std::sqrt(aPtVector.mag2()+sqr(Qmass));
1721       ProjSumMt += Mt; 
1722 
1723       // Sampling of Z fraction
1724       tmp.setPz(SampleX(Xmin, NumberOfUnsampledSeaQuarks, 2*nSeaPair, aBeta)*(1.0-SumZ)); 
1725       SumZ += tmp.z();
1726 
1727       NumberOfUnsampledSeaQuarks--;
1728       ProjSumMt2perX +=sqr(Mt)/tmp.pz();
1729       tmp.setE(sqr(Mt));
1730       aParton->Set4Momentum(tmp);
1731       #ifdef debugQGSParticipants
1732         G4cout<<"              "<<tmp<<" "<<SumZ<<G4endl;
1733       #endif
1734     } 
1735 
1736     // For valence quark
1737     aParton = theProjectileSplitable->GetNextParton();   // for quarks
1738     #ifdef debugQGSParticipants
1739       G4cout<<"Val quark of Pr"<<" "<<aParton->GetDefinition()->GetParticleName();
1740     #endif
1741     aPtVector = GaussianPt(SigPt, aHugeValue);
1742     tmp.setPx(aPtVector.x()); tmp.setPy(aPtVector.y());
1743     SumPx += aPtVector.x();   SumPy += aPtVector.y();
1744     Mt = std::sqrt(aPtVector.mag2()+sqr(VqM_pr));
1745     ProjSumMt += Mt;
1746 
1747     // Sampling of Z fraction
1748     tmp.setPz(SampleX(Xmin, NumberOfUnsampledSeaQuarks, 2*nSeaPair, aBeta)*(1.0-SumZ)); 
1749     SumZ += tmp.z();
1750 
1751     ProjSumMt2perX +=sqr(Mt)/tmp.pz();
1752     tmp.setE(sqr(Mt));
1753     aParton->Set4Momentum(tmp);
1754 
1755     // For valence di-quark
1756     aParton = theProjectileSplitable->GetNextAntiParton();
1757     #ifdef debugQGSParticipants
1758       G4cout<<" "<<aParton->GetDefinition()->GetParticleName()<<G4endl;
1759       G4cout<<"              "<<tmp<<" "<<SumZ<<" (z-fraction)"<<G4endl;
1760     #endif
1761     tmp.setPx(-SumPx); tmp.setPy(-SumPy);
1762     //Uzhi 2019  Mt = std::sqrt(aPtVector.mag2()+sqr(VaqM_pr));
1763     Mt = std::sqrt( sqr(SumPx) + sqr(SumPy) + sqr(VaqM_pr) );  //Uzhi 2019
1764     ProjSumMt += Mt;
1765     tmp.setPz(1.-SumZ);
1766 
1767     ProjSumMt2perX +=sqr(Mt)/tmp.pz();  // QQmass=750 MeV
1768     tmp.setE(sqr(Mt));
1769     aParton->Set4Momentum(tmp);
1770     #ifdef debugQGSParticipants
1771       G4cout<<"              "<<tmp<<" "<<SumZ+(1.-SumZ)<<" (z-fraction)"<<G4endl;
1772       NuclNo=0;
1773     #endif
1774 
1775     // End of work with the projectile
1776 
1777     // Work with target nucleons 
1778 
1779     for(i = theTargets.begin(); i != theTargets.end(); i++ )
1780     {
1781       nSeaPair = (*i)->GetSoftCollisionCount()-1;
1782       #ifdef debugQGSParticipants
1783         G4cout<<"nSeaPair of target N "<<nSeaPair<<G4endl
1784               <<"Target nucleon 4Mom "<<(*i)->Get4Momentum()<<G4endl;
1785       #endif
1786 
1787       SumPx = (*i)->Get4Momentum().px() * (-1.);
1788       SumPy = (*i)->Get4Momentum().py() * (-1.);
1789       SumZ  = 0.;
1790 
1791       NumberOfUnsampledSeaQuarks = 2*nSeaPair;
1792 
1793       Qmass=0;  
1794       for (G4int aSeaPair = 0; aSeaPair < nSeaPair; aSeaPair++)
1795       {
1796         aParton = (*i)->GetNextParton();   // for quarks
1797         #ifdef debugQGSParticipants
1798           G4cout<<"Sea quarks: "<<aSeaPair<<" "<<aParton->GetDefinition()->GetParticleName();
1799         #endif
1800         aPtVector = GaussianPt(SigPt, aHugeValue);
1801         tmp.setPx(aPtVector.x()); tmp.setPy(aPtVector.y());
1802         SumPx += aPtVector.x();   SumPy += aPtVector.y();
1803         Mt=std::sqrt(aPtVector.mag2()+sqr(Qmass));
1804         TargSumMt += Mt; 
1805 
1806         // Sampling of Z fraction
1807         tmp.setPz(SampleX(Xmin, NumberOfUnsampledSeaQuarks, 2*nSeaPair, aBeta)*(1.0-SumZ));
1808         SumZ += tmp.z();
1809         tmp.setPz((*i)->Get4Momentum().pz()*tmp.pz());
1810         NumberOfUnsampledSeaQuarks--;
1811         TargSumMt2perX +=sqr(Mt)/tmp.pz();
1812         tmp.setE(sqr(Mt));
1813         aParton->Set4Momentum(tmp);
1814 
1815         aParton = (*i)->GetNextAntiParton();   // for anti-quarks
1816         #ifdef debugQGSParticipants
1817           G4cout<<" "<<aParton->GetDefinition()->GetParticleName()<<G4endl;
1818           G4cout<<"              "<<tmp<<" "<<SumZ<<G4endl;
1819         #endif
1820         aPtVector = GaussianPt(SigPt, aHugeValue);
1821         tmp.setPx(aPtVector.x()); tmp.setPy(aPtVector.y());
1822         SumPx += aPtVector.x();   SumPy += aPtVector.y();
1823         Mt=std::sqrt(aPtVector.mag2()+sqr(Qmass));
1824         TargSumMt += Mt; 
1825 
1826         // Sampling of Z fraction
1827         tmp.setPz(SampleX(Xmin, NumberOfUnsampledSeaQuarks, 2*nSeaPair, aBeta)*(1.0-SumZ)); 
1828         SumZ += tmp.z();
1829         tmp.setPz((*i)->Get4Momentum().pz()*tmp.pz());
1830         NumberOfUnsampledSeaQuarks--;
1831         TargSumMt2perX +=sqr(Mt)/tmp.pz();
1832         tmp.setE(sqr(Mt));
1833         aParton->Set4Momentum(tmp);
1834         #ifdef debugQGSParticipants
1835           G4cout<<"              "<<tmp<<" "<<" "<<SumZ<<G4endl;
1836         #endif
1837       } 
1838 
1839       // Valence quark
1840       aParton = (*i)->GetNextParton();   // for quarks
1841       #ifdef debugQGSParticipants
1842         G4cout<<"Val quark of Tr"<<" "<<aParton->GetDefinition()->GetParticleName();
1843       #endif
1844       aPtVector = GaussianPt(SigPt, aHugeValue);
1845       tmp.setPx(aPtVector.x()); tmp.setPy(aPtVector.y());
1846       SumPx += aPtVector.x();   SumPy += aPtVector.y();
1847       Mt=std::sqrt(aPtVector.mag2()+sqr(VqM_tr));
1848       TargSumMt += Mt; 
1849 
1850       // Sampling of Z fraction
1851       tmp.setPz(SampleX(Xmin, NumberOfUnsampledSeaQuarks, 2*nSeaPair, aBeta)*(1.0-SumZ)); 
1852       SumZ += tmp.z();
1853       tmp.setPz((*i)->Get4Momentum().pz()*tmp.pz());
1854       TargSumMt2perX +=sqr(Mt)/tmp.pz();
1855       tmp.setE(sqr(Mt));
1856       aParton->Set4Momentum(tmp);
1857 
1858       // Valence di-quark
1859       aParton = (*i)->GetNextAntiParton();   // for quarks
1860       #ifdef debugQGSParticipants
1861         G4cout<<" "<<aParton->GetDefinition()->GetParticleName()<<G4endl;
1862         G4cout<<"              "<<tmp<<" "<<SumZ<<" (total z-sum) "<<G4endl;
1863       #endif
1864       tmp.setPx(-SumPx);                  tmp.setPy(-SumPy);
1865       //Uzhi 2019  Mt=std::sqrt(aPtVector.mag2()+sqr(VqqM_tr));
1866       Mt=std::sqrt( sqr(SumPx) + sqr(SumPy) + sqr(VqqM_tr) );  //Uzhi 2019   
1867       TargSumMt += Mt; 
1868 
1869       tmp.setPz((*i)->Get4Momentum().pz()*(1.0 - SumZ));
1870       TargSumMt2perX +=sqr(Mt)/tmp.pz();
1871       tmp.setE(sqr(Mt));
1872       aParton->Set4Momentum(tmp);
1873       #ifdef debugQGSParticipants
1874         G4cout<<"              "<<tmp<<" "<<1.0<<" "<<(*i)->Get4Momentum().pz()<<G4endl;
1875       #endif
1876 
1877     }   // End of for(i = theTargets.begin(); i != theTargets.end(); i++ )
1878 
1879     if( ProjSumMt      + TargSumMt      > SqrtS ) {
1880       Success = false; continue;}
1881     if( std::sqrt(ProjSumMt2perX) + std::sqrt(TargSumMt2perX) > SqrtS ) {
1882       Success = false; continue;}
1883 
1884   } while( (!Success) &&
1885            attempt < maxNumberOfAttempts );  /* Loop checking, 07.08.2015, A.Ribon */
1886 
1887   if ( attempt >= maxNumberOfAttempts ) {
1888     return false;
1889   }
1890 
1891   //+++++++++++++++++++++++++++++++++++++++++++
1892 
1893   G4double DecayMomentum2 = sqr(S) + sqr(ProjSumMt2perX) + sqr(TargSumMt2perX)
1894                - 2.0*S*ProjSumMt2perX - 2.0*S*TargSumMt2perX - 2.0*ProjSumMt2perX*TargSumMt2perX;
1895 
1896   G4double targetWminus=( S - ProjSumMt2perX + TargSumMt2perX + std::sqrt( DecayMomentum2 ))/2.0/SqrtS;
1897   G4double projectileWplus = SqrtS - TargSumMt2perX/targetWminus;
1898 
1899   G4LorentzVector Tmp(0.,0.,0.,0.);
1900   G4double z(0.);
1901 
1902   G4int nSeaPair = theProjectileSplitable->GetSoftCollisionCount()-1;
1903   #ifdef debugQGSParticipants
1904     G4cout<<"Backward transformation ===================="<<G4endl;
1905     G4cout<<"nSeaPair of proj "<<nSeaPair<<G4endl;
1906   #endif
1907 
1908   for (G4int aSeaPair = 0; aSeaPair < nSeaPair; aSeaPair++)
1909   {
1910     aParton = theProjectileSplitable->GetNextParton();   // for quarks
1911     #ifdef debugQGSParticipants
1912       G4cout<<"Sea quarks: "<<aSeaPair<<" "<<aParton->GetDefinition()->GetParticleName();
1913     #endif
1914     Tmp =aParton->Get4Momentum(); z=Tmp.z();
1915 
1916     Tmp.setPz(projectileWplus*z/2.0 - Tmp.e()/(2.0*z*projectileWplus));
1917     Tmp.setE( projectileWplus*z/2.0 + Tmp.e()/(2.0*z*projectileWplus)); 
1918     Tmp.transform( toLab );
1919 
1920     aParton->Set4Momentum(Tmp);
1921 
1922     aParton = theProjectileSplitable->GetNextAntiParton();          // for anti-quarks
1923     #ifdef debugQGSParticipants
1924       G4cout<<" "<<aParton->GetDefinition()->GetParticleName()<<G4endl;
1925       G4cout<<"              "<<Tmp<<" "<<Tmp.mag()<<G4endl;
1926     #endif
1927     Tmp =aParton->Get4Momentum(); z=Tmp.z(); 
1928     Tmp.setPz(projectileWplus*z/2.0 - Tmp.e()/(2.0*z*projectileWplus));
1929     Tmp.setE( projectileWplus*z/2.0 + Tmp.e()/(2.0*z*projectileWplus)); 
1930     Tmp.transform( toLab );
1931 
1932     aParton->Set4Momentum(Tmp);
1933     #ifdef debugQGSParticipants
1934       G4cout<<"              "<<Tmp<<" "<<Tmp.mag()<<G4endl;
1935     #endif
1936   } 
1937 
1938   // For valence quark
1939   aParton = theProjectileSplitable->GetNextParton();   // for quarks
1940   #ifdef debugQGSParticipants
1941     G4cout<<"Val quark of Pr"<<" "<<aParton->GetDefinition()->GetParticleName();
1942   #endif
1943   Tmp =aParton->Get4Momentum(); z=Tmp.z(); 
1944   Tmp.setPz(projectileWplus*z/2.0 - Tmp.e()/(2.0*z*projectileWplus));
1945   Tmp.setE( projectileWplus*z/2.0 + Tmp.e()/(2.0*z*projectileWplus)); 
1946   Tmp.transform( toLab );
1947 
1948   aParton->Set4Momentum(Tmp);
1949 
1950   // For valence di-quark
1951   aParton = theProjectileSplitable->GetNextAntiParton();
1952   #ifdef debugQGSParticipants
1953     G4cout<<" "<<aParton->GetDefinition()->GetParticleName()<<G4endl;
1954     G4cout<<"              "<<Tmp<<" "<<Tmp.mag()<<" (mass)"<<G4endl;
1955   #endif
1956   Tmp =aParton->Get4Momentum(); z=Tmp.z(); 
1957   Tmp.setPz(projectileWplus*z/2.0 - Tmp.e()/(2.0*z*projectileWplus));
1958   Tmp.setE( projectileWplus*z/2.0 + Tmp.e()/(2.0*z*projectileWplus)); 
1959   Tmp.transform( toLab );
1960 
1961   aParton->Set4Momentum(Tmp);
1962 
1963   #ifdef debugQGSParticipants
1964     G4cout<<"              "<<Tmp<<" "<<Tmp.mag()<<" (mass)"<<G4endl;
1965     NuclNo=0;
1966   #endif
1967 
1968   // End of work with the projectile
1969 
1970   // Work with target nucleons 
1971   for(i = theTargets.begin(); i != theTargets.end(); i++ )
1972   {
1973     nSeaPair = (*i)->GetSoftCollisionCount()-1;
1974     #ifdef debugQGSParticipants
1975       G4cout<<"nSeaPair of target and N# "<<nSeaPair<<" "<<NuclNo<<G4endl;
1976       NuclNo++;
1977     #endif
1978     for (G4int aSeaPair = 0; aSeaPair < nSeaPair; aSeaPair++)
1979     {
1980       aParton = (*i)->GetNextParton();   // for quarks
1981       #ifdef debugQGSParticipants
1982         G4cout<<"Sea quarks: "<<aSeaPair<<" "<<aParton->GetDefinition()->GetParticleName();
1983       #endif
1984       Tmp =aParton->Get4Momentum(); z=Tmp.z(); 
1985       Tmp.setPz(-targetWminus*z/2.0 + Tmp.e()/(2.0*z*targetWminus));
1986       Tmp.setE(  targetWminus*z/2.0 + Tmp.e()/(2.0*z*targetWminus)); 
1987       Tmp.transform( toLab );
1988 
1989       aParton->Set4Momentum(Tmp);
1990 
1991       aParton = (*i)->GetNextAntiParton();   // for quarks
1992       #ifdef debugQGSParticipants
1993         G4cout<<" "<<aParton->GetDefinition()->GetParticleName()<<G4endl;
1994         G4cout<<"              "<<Tmp<<" "<<Tmp.mag()<<G4endl;
1995       #endif
1996       Tmp =aParton->Get4Momentum(); z=Tmp.z(); 
1997       Tmp.setPz(-targetWminus*z/2.0 + Tmp.e()/(2.0*z*targetWminus));
1998       Tmp.setE(  targetWminus*z/2.0 + Tmp.e()/(2.0*z*targetWminus)); 
1999       Tmp.transform( toLab );
2000 
2001       aParton->Set4Momentum(Tmp);
2002       #ifdef debugQGSParticipants
2003         G4cout<<"              "<<Tmp<<" "<<Tmp.mag()<<G4endl;
2004       #endif
2005     } 
2006 
2007     // Valence quark
2008 
2009     aParton = (*i)->GetNextParton();   // for quarks
2010     #ifdef debugQGSParticipants
2011       G4cout<<"Val quark of Tr"<<" "<<aParton->GetDefinition()->GetParticleName();
2012     #endif
2013     Tmp =aParton->Get4Momentum(); z=Tmp.z(); 
2014     Tmp.setPz(-targetWminus*z/2.0 + Tmp.e()/(2.0*z*targetWminus));
2015     Tmp.setE(  targetWminus*z/2.0 + Tmp.e()/(2.0*z*targetWminus)); 
2016     Tmp.transform( toLab );
2017 
2018     aParton->Set4Momentum(Tmp);
2019 
2020     // Valence di-quark
2021     aParton = (*i)->GetNextAntiParton();   // for quarks
2022     #ifdef debugQGSParticipants
2023       G4cout<<" "<<aParton->GetDefinition()->GetParticleName()<<G4endl;
2024       G4cout<<"              "<<Tmp<<" "<<Tmp.mag()<<" (mass)"<<G4endl;
2025     #endif
2026     Tmp =aParton->Get4Momentum(); z=Tmp.z(); 
2027     Tmp.setPz(-targetWminus*z/2.0 + Tmp.e()/(2.0*z*targetWminus));
2028     Tmp.setE(  targetWminus*z/2.0 + Tmp.e()/(2.0*z*targetWminus)); 
2029     Tmp.transform( toLab );
2030 
2031     aParton->Set4Momentum(Tmp);
2032     #ifdef debugQGSParticipants
2033       G4cout<<"              "<<Tmp<<" "<<Tmp.mag()<<" (mass)"<<G4endl;
2034       NuclNo++;
2035     #endif
2036   }   // End of for(i = theTargets.begin(); i != theTargets.end(); i++ )
2037 
2038   return true;
2039 }
2040 
2041 //======================================================
2042 G4double G4QGSParticipants::
2043 SampleX(G4double, G4int nSea, G4int, G4double aBeta)
2044 {
2045   G4double Oalfa = 1./(alpha + 1.);
2046   G4double Obeta = 1./(aBeta + (alpha + 1.)*nSea + 1.);  // ?
2047  
2048   G4double Ksi1, Ksi2, r1, r2, r12;
2049   const G4int maxNumberOfLoops = 1000;
2050   G4int loopCounter = 0;
2051   do
2052   {
2053     Ksi1 = G4UniformRand(); r1 = G4Pow::GetInstance()->powA(Ksi1,Oalfa);
2054     Ksi2 = G4UniformRand(); r2 = G4Pow::GetInstance()->powA(Ksi2,Obeta); 
2055     r12=r1+r2;
2056   } while( ( r12 > 1.) &&
2057            ++loopCounter < maxNumberOfLoops );  /* Loop checking, 07.08.2015, A.Ribon */
2058   if ( loopCounter >= maxNumberOfLoops ) {
2059     return 0.5;  // Just an acceptable value, without any physics consideration.
2060   }
2061 
2062   G4double result = r1/r12;
2063   return result;
2064 } 
2065 
2066 //======================================================
2067 void G4QGSParticipants::CreateStrings()
2068 {
2069 
2070   #ifdef debugQGSParticipants
2071     G4cout<<"CreateStrings() ..................."<<G4endl;
2072   #endif
2073 
2074   if ( ! theProjectileSplitable ) {
2075     #ifdef debugQGSParticipants
2076       G4cout<<"BAD situation: theProjectileSplitable is NULL ! Returning immediately"<<G4endl;
2077     #endif
2078     return;
2079   }
2080 
2081   #ifdef debugQGSParticipants
2082     G4cout<<"theProjectileSplitable->GetStatus() "<<theProjectileSplitable->GetStatus()<<G4endl;
2083     G4LorentzVector str4Mom;
2084   #endif
2085 
2086   if( theProjectileSplitable->GetStatus() == 1 )  // The projectile has participated only in diffr. inter.
2087   {
2088     G4ThreeVector Position = theProjectileSplitable->GetPosition();
2089 
2090     G4PartonPair * aPair = new G4PartonPair(theProjectileSplitable->GetNextParton(), 
2091                                             theProjectileSplitable->GetNextAntiParton(),
2092                     G4PartonPair::DIFFRACTIVE, G4PartonPair::TARGET);
2093     #ifdef debugQGSParticipants
2094       G4cout << "Pr. Diffr. String: Qs 4mom X " <<G4endl;
2095       G4cout << "              " << aPair->GetParton1()->GetPDGcode()   << " "
2096          << aPair->GetParton1()->Get4Momentum() << " "
2097          << aPair->GetParton1()->GetX()         << " " << G4endl;
2098       G4cout << "              " << aPair->GetParton2()->GetPDGcode()   << " "
2099          << aPair->GetParton2()->Get4Momentum() << " "
2100          << aPair->GetParton2()->GetX()         << " " << G4endl;
2101       str4Mom += aPair->GetParton1()->Get4Momentum();
2102       str4Mom += aPair->GetParton2()->Get4Momentum();
2103     #endif
2104 
2105     thePartonPairs.push_back(aPair);
2106   }
2107 
2108   G4int N_EnvTarg = NumberOfInvolvedNucleonsOfTarget;
2109 
2110   for ( G4int i = 0; i < N_EnvTarg; i++ ) { 
2111     G4Nucleon* aTargetNucleon = TheInvolvedNucleonsOfTarget[ i ];
2112 
2113     G4VSplitableHadron* HitTargetNucleon = aTargetNucleon->GetSplitableHadron();
2114 
2115     #ifdef debugQGSParticipants
2116       G4cout<<"Involved Nucleon # and its status "<<i<<" "<<HitTargetNucleon->GetStatus()<<G4endl;
2117     #endif    
2118     if( HitTargetNucleon->GetStatus() >= 1)  // Create diffractive string
2119     {
2120       G4ThreeVector Position     = HitTargetNucleon->GetPosition();
2121 
2122       G4PartonPair * aPair = new G4PartonPair(HitTargetNucleon->GetNextParton(), 
2123                                               HitTargetNucleon->GetNextAntiParton(),
2124                       G4PartonPair::DIFFRACTIVE, G4PartonPair::TARGET);
2125       #ifdef debugQGSParticipants
2126         G4cout << "Tr. Diffr. String: Qs 4mom X " <<G4endl;
2127   G4cout << "Diffr. String " << aPair->GetParton1()->GetPDGcode()   << " "
2128            << aPair->GetParton1()->Get4Momentum() << " "
2129            << aPair->GetParton1()->GetX()         << " " << G4endl;
2130   G4cout << "              " << aPair->GetParton2()->GetPDGcode()   << " "
2131            << aPair->GetParton2()->Get4Momentum() << " "
2132            << aPair->GetParton2()->GetX()         << " " << G4endl;
2133 
2134   str4Mom += aPair->GetParton1()->Get4Momentum();
2135   str4Mom += aPair->GetParton2()->Get4Momentum();
2136       #endif
2137 
2138       thePartonPairs.push_back(aPair);
2139     }
2140   }
2141 
2142   //-----------------------------------------
2143   #ifdef debugQGSParticipants
2144     G4int IntNo=0;    
2145     G4cout<<"Strings created in soft interactions"<<G4endl;
2146   #endif 
2147   std::vector<G4InteractionContent*>::iterator i;
2148   i = theInteractions.begin();
2149   while ( i != theInteractions.end() )  /* Loop checking, 07.08.2015, A.Ribon */
2150   {
2151     G4InteractionContent* anIniteraction = *i;
2152     G4PartonPair * aPair = NULL;
2153 
2154     #ifdef debugQGSParticipants
2155       G4cout<<"An interaction # and soft coll. # "<<IntNo<<" "
2156             <<anIniteraction->GetNumberOfSoftCollisions()<<G4endl;
2157       IntNo++;
2158     #endif 
2159     if (anIniteraction->GetNumberOfSoftCollisions())
2160     {
2161       G4VSplitableHadron* pProjectile = anIniteraction->GetProjectile();
2162       G4VSplitableHadron* pTarget     = anIniteraction->GetTarget();
2163 
2164       for (G4int j = 0; j < anIniteraction->GetNumberOfSoftCollisions(); j++)
2165       {
2166         aPair = new G4PartonPair(pTarget->GetNextParton(), pProjectile->GetNextAntiParton(),
2167          G4PartonPair::SOFT, G4PartonPair::TARGET);
2168   #ifdef debugQGSParticipants
2169     G4cout << "SoftPair " << aPair->GetParton1()->GetPDGcode()   << " "
2170      << aPair->GetParton1()->Get4Momentum() << " "
2171      << aPair->GetParton1()->Get4Momentum().mag()<<G4endl;
2172     G4cout << "         " << aPair->GetParton2()->GetPDGcode()   << " "
2173      << aPair->GetParton2()->Get4Momentum() << " "
2174       <<aPair->GetParton2()->Get4Momentum().mag()<<G4endl;
2175     str4Mom += aPair->GetParton1()->Get4Momentum();
2176     str4Mom += aPair->GetParton2()->Get4Momentum();
2177   #endif
2178 
2179   thePartonPairs.push_back(aPair);
2180 
2181   aPair = new G4PartonPair(pProjectile->GetNextParton(), pTarget->GetNextAntiParton(),
2182          G4PartonPair::SOFT, G4PartonPair::PROJECTILE);
2183   #ifdef debugQGSParticipants
2184     G4cout << "SoftPair " << aPair->GetParton1()->GetPDGcode()   << " "
2185      << aPair->GetParton1()->Get4Momentum() << " "
2186            << aPair->GetParton1()->Get4Momentum().mag()<<G4endl;
2187     G4cout << "         " << aPair->GetParton2()->GetPDGcode()   << " "
2188      << aPair->GetParton2()->Get4Momentum() << " "
2189      << aPair->GetParton2()->Get4Momentum().mag()<<G4endl;
2190   #endif
2191   #ifdef debugQGSParticipants
2192     str4Mom += aPair->GetParton1()->Get4Momentum();
2193     str4Mom += aPair->GetParton2()->Get4Momentum();
2194   #endif
2195 
2196   thePartonPairs.push_back(aPair);
2197       }
2198 
2199       delete *i;
2200       i=theInteractions.erase(i);    // i now points to the next interaction
2201     } 
2202     else 
2203     {
2204       i++;
2205     }
2206   }  // End of while ( i != theInteractions.end() ) 
2207   #ifdef debugQGSParticipants
2208     G4cout << "Sum of strings 4 momenta " << str4Mom << G4endl<<G4endl;
2209   #endif
2210 }
2211 
2212 //============================================================================
2213 
2214 void G4QGSParticipants::GetResiduals() {
2215   // This method is needed for the correct application of G4PrecompoundModelInterface
2216 
2217   #ifdef debugQGSParticipants
2218     G4cout << "GetResiduals(): GetProjectileNucleus()? " <<  GetProjectileNucleus() << G4endl;
2219   #endif
2220 
2221   #ifdef debugQGSParticipants
2222     G4cout << "NumberOfInvolvedNucleonsOfTarget "<< NumberOfInvolvedNucleonsOfTarget << G4endl;
2223   #endif
2224 
2225   G4double DeltaExcitationE = TargetResidualExcitationEnergy / G4double( NumberOfInvolvedNucleonsOfTarget );
2226   G4LorentzVector DeltaPResidualNucleus = TargetResidual4Momentum /
2227                                           G4double( NumberOfInvolvedNucleonsOfTarget );
2228 
2229   for ( G4int i = 0; i < NumberOfInvolvedNucleonsOfTarget; i++ ) {
2230     G4Nucleon* aNucleon = TheInvolvedNucleonsOfTarget[i];
2231 
2232     #ifdef debugQGSParticipants
2233       G4VSplitableHadron* targetSplitable = aNucleon->GetSplitableHadron();
2234       G4cout << i << " Hit? " << aNucleon->AreYouHit() << " " << targetSplitable << G4endl;
2235       if ( targetSplitable ) G4cout << i << "Status " << targetSplitable->GetStatus() << G4endl;
2236     #endif
2237 
2238     G4LorentzVector tmp = -DeltaPResidualNucleus;
2239     aNucleon->SetMomentum( tmp );
2240     aNucleon->SetBindingEnergy( DeltaExcitationE );
2241   }
2242 
2243   //------------------------------------- 
2244   if( TargetResidualMassNumber != 0 )
2245   {
2246     G4ThreeVector bstToCM =TargetResidual4Momentum.findBoostToCM();
2247 
2248     G4V3DNucleus* theTargetNucleus = GetTargetNucleus();
2249     G4LorentzVector residualMomentum(0.,0.,0.,0.);
2250     G4Nucleon* aNucleon = 0;
2251     theTargetNucleus->StartLoop();
2252     while ( ( aNucleon = theTargetNucleus->GetNextNucleon() ) ) {  /* Loop checking, 07.08.2015, A.Ribon */
2253       if ( !aNucleon->AreYouHit() ) { 
2254         G4LorentzVector tmp=aNucleon->Get4Momentum(); tmp.boost(bstToCM);
2255         aNucleon->SetMomentum(tmp);
2256         residualMomentum +=tmp;
2257       }
2258     }
2259 
2260     residualMomentum/=TargetResidualMassNumber;
2261 
2262     G4double Mass = TargetResidual4Momentum.mag();
2263     G4double SumMasses=0.;
2264   
2265     aNucleon = 0;
2266     theTargetNucleus->StartLoop();
2267     while ( ( aNucleon = theTargetNucleus->GetNextNucleon() ) ) {  /* Loop checking, 07.08.2015, A.Ribon */
2268       if ( !aNucleon->AreYouHit() ) { 
2269         G4LorentzVector tmp=aNucleon->Get4Momentum() - residualMomentum;
2270         G4double E=std::sqrt(tmp.vect().mag2()+
2271                              sqr(aNucleon->GetDefinition()->GetPDGMass()-aNucleon->GetBindingEnergy()));
2272         tmp.setE(E);  aNucleon->SetMomentum(tmp);
2273         SumMasses+=E;
2274       }
2275     }
2276 
2277     G4double Chigh=Mass/SumMasses; G4double Clow=0; G4double C;
2278     const G4int maxNumberOfLoops = 1000;
2279     G4int loopCounter = 0;
2280     do
2281     {
2282       C=(Chigh+Clow)/2.;
2283 
2284       SumMasses=0.;
2285       aNucleon = 0;
2286       theTargetNucleus->StartLoop();
2287       while ( ( aNucleon = theTargetNucleus->GetNextNucleon() ) ) {  /* Loop checking, 07.08.2015, A.Ribon */
2288         if ( !aNucleon->AreYouHit() ) { 
2289           G4LorentzVector tmp=aNucleon->Get4Momentum();
2290           G4double E=std::sqrt(tmp.vect().mag2()*sqr(C)+
2291                                sqr(aNucleon->GetDefinition()->GetPDGMass()-aNucleon->GetBindingEnergy()));
2292           SumMasses+=E;
2293         }
2294       }
2295 
2296       if(SumMasses > Mass) {Chigh=C;}
2297       else                 {Clow =C;}
2298 
2299     } while( (Chigh-Clow > 0.01) &&
2300              ++loopCounter < maxNumberOfLoops );  /* Loop checking, 07.08.2015, A.Ribon */
2301     if ( loopCounter >= maxNumberOfLoops ) {
2302       #ifdef debugQGSParticipants
2303         G4cout <<"BAD situation: forced loop exit!" << G4endl;
2304       #endif
2305       // Perhaps there is something to set here...
2306     } else {
2307       aNucleon = 0;
2308       theTargetNucleus->StartLoop();
2309       while ( ( aNucleon = theTargetNucleus->GetNextNucleon() ) ) {  /* Loop checking, 07.08.2015, A.Ribon */
2310         if ( !aNucleon->AreYouHit() ) { 
2311           G4LorentzVector tmp=aNucleon->Get4Momentum()*C;
2312           G4double E=std::sqrt(tmp.vect().mag2()+
2313                                sqr(aNucleon->GetDefinition()->GetPDGMass()-aNucleon->GetBindingEnergy()));
2314           tmp.setE(E); tmp.boost(-bstToCM);  
2315           aNucleon->SetMomentum(tmp);     
2316         }
2317       }
2318     }
2319 
2320   }  // End of if( TargetResidualMassNumber != 0 )
2321   //-------------------------------------
2322    
2323   #ifdef debugQGSParticipants
2324     G4cout << "End GetResiduals -----------------" << G4endl;
2325   #endif
2326 
2327 }
2328 
2329 
2330 //======================================================
2331 void G4QGSParticipants::PerformSoftCollisions()  // It is not used
2332 {
2333   std::vector<G4InteractionContent*>::iterator i;
2334   G4LorentzVector str4Mom;
2335   i = theInteractions.begin();
2336   while ( i != theInteractions.end() )  /* Loop checking, 07.08.2015, A.Ribon */
2337   {
2338     G4InteractionContent* anIniteraction = *i;
2339     G4PartonPair * aPair = NULL;
2340     if (anIniteraction->GetNumberOfSoftCollisions())
2341     {
2342       G4VSplitableHadron* pProjectile = anIniteraction->GetProjectile();
2343       G4VSplitableHadron* pTarget     = anIniteraction->GetTarget();
2344       for (G4int j = 0; j < anIniteraction->GetNumberOfSoftCollisions(); j++)
2345       {
2346         aPair = new G4PartonPair(pTarget->GetNextParton(), pProjectile->GetNextAntiParton(),
2347          G4PartonPair::SOFT, G4PartonPair::TARGET);
2348   #ifdef debugQGSParticipants
2349     G4cout << "SoftPair " << aPair->GetParton1()->GetPDGcode() << " "
2350      << aPair->GetParton1()->Get4Momentum() << " "
2351      << aPair->GetParton1()->GetX() << " " << G4endl;
2352     G4cout << "         " << aPair->GetParton2()->GetPDGcode() << " "
2353      << aPair->GetParton2()->Get4Momentum() << " "
2354      << aPair->GetParton2()->GetX() << " " << G4endl;
2355   #endif
2356   #ifdef debugQGSParticipants
2357     str4Mom += aPair->GetParton1()->Get4Momentum();
2358     str4Mom += aPair->GetParton2()->Get4Momentum();
2359   #endif
2360   thePartonPairs.push_back(aPair);
2361   aPair = new G4PartonPair(pProjectile->GetNextParton(), pTarget->GetNextAntiParton(),
2362          G4PartonPair::SOFT, G4PartonPair::PROJECTILE);
2363   #ifdef debugQGSParticipants
2364     G4cout << "SoftPair " << aPair->GetParton1()->GetPDGcode() << " "
2365      << aPair->GetParton1()->Get4Momentum() << " "
2366      << aPair->GetParton1()->GetX() << " " << G4endl;
2367     G4cout << "         " << aPair->GetParton2()->GetPDGcode() << " "
2368      << aPair->GetParton2()->Get4Momentum() << " "
2369      << aPair->GetParton2()->GetX() << " " << G4endl;
2370   #endif
2371   #ifdef debugQGSParticipants
2372     str4Mom += aPair->GetParton1()->Get4Momentum();
2373     str4Mom += aPair->GetParton2()->Get4Momentum();
2374   #endif
2375   thePartonPairs.push_back(aPair);
2376       }
2377       delete *i;
2378       i=theInteractions.erase(i);    // i now points to the next interaction
2379     } else {
2380       i++;
2381     }
2382   }
2383   #ifdef debugQGSParticipants
2384     G4cout << " string 4 mom " << str4Mom << G4endl;
2385   #endif
2386 }
2387 
2388 
2389 //************************************************
2390 G4VSplitableHadron* G4QGSParticipants::SelectInteractions(const G4ReactionProduct  &thePrimary) 
2391 {
2392   // Check reaction threshold  - goes to CheckThreshold
2393 
2394   theProjectileSplitable = new G4QGSMSplitableHadron(thePrimary, TRUE);
2395   theProjectileSplitable->SetStatus(1);
2396 
2397   G4LorentzVector aPrimaryMomentum(thePrimary.GetMomentum(), thePrimary.GetTotalEnergy());
2398   G4LorentzVector aTargetNMomentum(0.,0.,0.,938.);
2399 
2400   if ((!(aPrimaryMomentum.e()>-1)) && (!(aPrimaryMomentum.e()<1)) )
2401   {
2402     throw G4HadronicException(__FILE__, __LINE__,
2403             "G4GammaParticipants::SelectInteractions: primary nan energy.");
2404   }
2405   G4double S = (aPrimaryMomentum + aTargetNMomentum).mag2();
2406   G4double ThresholdMass = thePrimary.GetMass() + 938.;
2407   ModelMode = SOFT;
2408 
2409   #ifdef debugQGSParticipants
2410     G4cout << "Gamma projectile - SelectInteractions " << G4endl;
2411     G4cout<<"Energy and Nucleus "<<thePrimary.GetTotalEnergy()<<" "<<theNucleus->GetMassNumber()<<G4endl;
2412     G4cout << "SqrtS ThresholdMass ModelMode " <<std::sqrt(S)<<" "<<ThresholdMass<<" "<<ModelMode<< G4endl;
2413   #endif
2414 
2415   if (sqr(ThresholdMass + ThresholdParameter) > S)
2416   {
2417     ModelMode = DIFFRACTIVE;
2418   }
2419   if (sqr(ThresholdMass + QGSMThreshold) > S) // thus only diffractive in cascade!
2420   {
2421     ModelMode = DIFFRACTIVE;
2422   }
2423 
2424   // first find the collisions HPW
2425   std::for_each(theInteractions.begin(), theInteractions.end(), DeleteInteractionContent());
2426   theInteractions.clear();
2427 
2428   G4int theCurrent = G4int(theNucleus->GetMassNumber()*G4UniformRand());
2429   G4int NucleonNo=0;
2430 
2431   theNucleus->StartLoop();
2432   G4Nucleon * pNucleon = 0;
2433 
2434   while( (pNucleon = theNucleus->GetNextNucleon()) )  /* Loop checking, 07.08.2015, A.Ribon */
2435   { if(NucleonNo == theCurrent) break; NucleonNo++; }
2436 
2437   if ( pNucleon ) {
2438     G4QGSMSplitableHadron* aTarget = new G4QGSMSplitableHadron(*pNucleon);
2439 
2440     pNucleon->Hit(aTarget);
2441 
2442     if ( (0.06 > G4UniformRand() &&(ModelMode==SOFT)) || (ModelMode==DIFFRACTIVE ) )
2443     {
2444       G4InteractionContent * aInteraction = new G4InteractionContent(theProjectileSplitable);
2445       theProjectileSplitable->SetStatus(1*theProjectileSplitable->GetStatus());
2446 
2447       aInteraction->SetTarget(aTarget);
2448       aInteraction->SetTargetNucleon(pNucleon);
2449       aTarget->SetCollisionCount(0);
2450       aTarget->SetStatus(1);
2451 
2452       aInteraction->SetNumberOfDiffractiveCollisions(1);
2453       aInteraction->SetNumberOfSoftCollisions(0);
2454       aInteraction->SetStatus(1);
2455 
2456       theInteractions.push_back(aInteraction);
2457     }
2458     else
2459     {
2460       // nondiffractive soft interaction occurs
2461       aTarget->IncrementCollisionCount(1);
2462       aTarget->SetStatus(0);
2463       theTargets.push_back(aTarget);
2464 
2465       theProjectileSplitable->IncrementCollisionCount(1);
2466       theProjectileSplitable->SetStatus(0*theProjectileSplitable->GetStatus());
2467 
2468       G4InteractionContent * aInteraction = new G4InteractionContent(theProjectileSplitable);
2469       aInteraction->SetTarget(aTarget);
2470       aInteraction->SetTargetNucleon(pNucleon);
2471       aInteraction->SetNumberOfSoftCollisions(1);
2472       aInteraction->SetStatus(3);
2473       theInteractions.push_back(aInteraction);
2474     }
2475   }
2476   return theProjectileSplitable;
2477 }
2478