Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/hadronic/models/parton_string/diffraction/src/G4FTFModel.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 //
 27 //
 28 
 29 // ------------------------------------------------------------
 30 //      GEANT 4 class implementation file
 31 //
 32 //      ---------------- G4FTFModel ----------------
 33 //             by Gunter Folger, May 1998.
 34 //       class implementing the excitation in the FTF Parton String Model
 35 //
 36 //                Vladimir Uzhinsky, November - December 2012
 37 //       simulation of nucleus-nucleus interactions was implemented.
 38 // ------------------------------------------------------------
 39 
 40 #include <utility> 
 41 
 42 #include "G4FTFModel.hh"
 43 #include "G4ios.hh"
 44 #include "G4PhysicalConstants.hh"
 45 #include "G4SystemOfUnits.hh"
 46 #include "G4FTFParameters.hh"
 47 #include "G4FTFParticipants.hh"
 48 #include "G4DiffractiveSplitableHadron.hh"
 49 #include "G4InteractionContent.hh"
 50 #include "G4LorentzRotation.hh"
 51 #include "G4ParticleDefinition.hh"
 52 #include "G4ParticleTable.hh"
 53 #include "G4IonTable.hh"
 54 #include "G4KineticTrack.hh"
 55 #include "G4HyperNucleiProperties.hh"
 56 #include "G4Exp.hh"
 57 #include "G4Log.hh"
 58 
 59 //============================================================================
 60 
 61 //#define debugFTFmodel
 62 //#define debugReggeonCascade
 63 //#define debugPutOnMassShell
 64 //#define debugAdjust
 65 //#define debugBuildString
 66 
 67 
 68 //============================================================================
 69 
 70 G4FTFModel::G4FTFModel( const G4String& modelName ) : 
 71   G4VPartonStringModel( modelName ),
 72   theExcitation( new G4DiffractiveExcitation() ),
 73   theElastic( new G4ElasticHNScattering() ),
 74   theAnnihilation( new G4FTFAnnihilation() )
 75 {
 76   // ---> JVY theParameters = 0;
 77   theParameters = new G4FTFParameters();
 78   //
 79   NumberOfInvolvedNucleonsOfTarget = 0;
 80   NumberOfInvolvedNucleonsOfProjectile= 0;
 81   for ( G4int i = 0; i < 250; ++i ) {
 82     TheInvolvedNucleonsOfTarget[i] = 0;
 83     TheInvolvedNucleonsOfProjectile[i] = 0;
 84   }
 85 
 86   //LowEnergyLimit = 2000.0*MeV;
 87   LowEnergyLimit = 1000.0*MeV;
 88 
 89   HighEnergyInter = true;
 90 
 91   G4LorentzVector tmp( 0.0, 0.0, 0.0, 0.0 );
 92   ProjectileResidual4Momentum        = tmp;
 93   ProjectileResidualMassNumber       = 0;
 94   ProjectileResidualCharge           = 0;
 95   ProjectileResidualLambdaNumber     = 0;
 96   ProjectileResidualExcitationEnergy = 0.0;
 97 
 98   TargetResidual4Momentum            = tmp;
 99   TargetResidualMassNumber           = 0;
100   TargetResidualCharge               = 0;
101   TargetResidualExcitationEnergy     = 0.0;
102 
103   Bimpact = -1.0;
104   BinInterval = false;
105   Bmin = 0.0; 
106   Bmax = 0.0;
107   NumberOfProjectileSpectatorNucleons = 0;
108   NumberOfTargetSpectatorNucleons = 0;
109   NumberOfNNcollisions = 0;
110 
111   SetEnergyMomentumCheckLevels( 2.0*perCent, 150.0*MeV );
112 }
113 
114 
115 //============================================================================
116 
117 struct DeleteVSplitableHadron { void operator()( G4VSplitableHadron* aH ) { delete aH; } };
118 
119 
120 //============================================================================
121 
122 G4FTFModel::~G4FTFModel() {
123    // Because FTF model can be called for various particles
124    //
125    // ---> NOTE (JVY): This statement below is no longer true !!! 
126    // theParameters must be erased at the end of each call.
127    // Thus the delete is also in G4FTFModel::GetStrings() method.
128    // ---> JVY
129    //
130    if ( theParameters   != 0 ) delete theParameters; 
131    if ( theExcitation   != 0 ) delete theExcitation;
132    if ( theElastic      != 0 ) delete theElastic; 
133    if ( theAnnihilation != 0 ) delete theAnnihilation;
134 
135    // Erasing of strings created at annihilation.
136    if ( theAdditionalString.size() != 0 ) {
137      std::for_each( theAdditionalString.begin(), theAdditionalString.end(), 
138                     DeleteVSplitableHadron() );
139    }
140    theAdditionalString.clear();
141 
142    // Erasing of target involved nucleons.
143    if ( NumberOfInvolvedNucleonsOfTarget != 0 ) {
144      for ( G4int i = 0; i < NumberOfInvolvedNucleonsOfTarget; ++i ) {
145        G4VSplitableHadron* aNucleon = TheInvolvedNucleonsOfTarget[i]->GetSplitableHadron();
146        if ( aNucleon ) delete aNucleon;
147      }
148    }
149 
150    // Erasing of projectile involved nucleons.
151    if ( NumberOfInvolvedNucleonsOfProjectile != 0 ) {
152      for ( G4int i = 0; i < NumberOfInvolvedNucleonsOfProjectile; ++i ) {
153        G4VSplitableHadron* aNucleon = TheInvolvedNucleonsOfProjectile[i]->GetSplitableHadron();
154        if ( aNucleon ) delete aNucleon;
155      }
156    }
157 }
158 
159 
160 //============================================================================
161 
162 void G4FTFModel::Init( const G4Nucleus& aNucleus, const G4DynamicParticle& aProjectile ) {
163 
164   theProjectile = aProjectile;  
165 
166   G4double PlabPerParticle( 0.0 );  // Laboratory momentum Pz per particle/nucleon
167 
168   #ifdef debugFTFmodel
169   G4cout << "FTF init Proj Name " << theProjectile.GetDefinition()->GetParticleName() << G4endl
170          << "FTF init Proj Mass " << theProjectile.GetMass() 
171          << " " << theProjectile.GetMomentum() << G4endl
172          << "FTF init Proj B Q  " << theProjectile.GetDefinition()->GetBaryonNumber()
173          << " " << (G4int) theProjectile.GetDefinition()->GetPDGCharge() << G4endl 
174          << "FTF init Target A Z " << aNucleus.GetA_asInt() 
175          << " " << aNucleus.GetZ_asInt() << G4endl;
176   #endif
177 
178   theParticipants.Clean();
179 
180   theParticipants.SetProjectileNucleus( 0 );
181 
182   G4LorentzVector tmp( 0.0, 0.0, 0.0, 0.0 );
183   ProjectileResidualMassNumber       = 0;
184   ProjectileResidualCharge           = 0;
185   ProjectileResidualLambdaNumber     = 0;
186   ProjectileResidualExcitationEnergy = 0.0;
187   ProjectileResidual4Momentum        = tmp;
188   
189   TargetResidualMassNumber       = aNucleus.GetA_asInt();
190   TargetResidualCharge           = aNucleus.GetZ_asInt();
191   TargetResidualExcitationEnergy = 0.0;
192   TargetResidual4Momentum        = tmp;
193   G4double TargetResidualMass = G4ParticleTable::GetParticleTable()->GetIonTable()
194                                 ->GetIonMass( TargetResidualCharge, TargetResidualMassNumber );
195 
196   TargetResidual4Momentum.setE( TargetResidualMass );
197 
198   if ( std::abs( theProjectile.GetDefinition()->GetBaryonNumber() ) <= 1 ) { 
199     // Projectile is a hadron : meson or baryon
200     ProjectileResidualMassNumber = std::abs( theProjectile.GetDefinition()->GetBaryonNumber() );
201     ProjectileResidualCharge = G4int( theProjectile.GetDefinition()->GetPDGCharge() );
202     PlabPerParticle = theProjectile.GetMomentum().z();
203     ProjectileResidualExcitationEnergy = 0.0;
204     //G4double ProjectileResidualMass = theProjectile.GetMass();
205     ProjectileResidual4Momentum.setVect( theProjectile.GetMomentum() );
206     ProjectileResidual4Momentum.setE( theProjectile.GetTotalEnergy() );
207     if ( PlabPerParticle < LowEnergyLimit ) {
208       HighEnergyInter = false;
209     } else {
210       HighEnergyInter = true;
211     }
212   } else {
213     if ( theProjectile.GetDefinition()->GetBaryonNumber() > 1 ) { 
214       // Projectile is a nucleus      
215       ProjectileResidualMassNumber = theProjectile.GetDefinition()->GetBaryonNumber();
216       ProjectileResidualCharge = G4int( theProjectile.GetDefinition()->GetPDGCharge() );
217       ProjectileResidualLambdaNumber = theProjectile.GetDefinition()->GetNumberOfLambdasInHypernucleus();
218       PlabPerParticle = theProjectile.GetMomentum().z() / ProjectileResidualMassNumber;
219       if ( PlabPerParticle < LowEnergyLimit ) {
220         HighEnergyInter = false;
221       } else {
222         HighEnergyInter = true;
223       }
224       theParticipants.InitProjectileNucleus( ProjectileResidualMassNumber, ProjectileResidualCharge,
225                ProjectileResidualLambdaNumber );
226     } else if ( theProjectile.GetDefinition()->GetBaryonNumber() < -1 ) { 
227       // Projectile is an anti-nucleus
228       ProjectileResidualMassNumber = std::abs( theProjectile.GetDefinition()->GetBaryonNumber() );
229       ProjectileResidualCharge = std::abs( G4int( theProjectile.GetDefinition()->GetPDGCharge() ) );
230       ProjectileResidualLambdaNumber = theProjectile.GetDefinition()->GetNumberOfAntiLambdasInAntiHypernucleus();
231       PlabPerParticle = theProjectile.GetMomentum().z() / ProjectileResidualMassNumber;
232       if ( PlabPerParticle < LowEnergyLimit ) {
233         HighEnergyInter = false;
234       } else {
235         HighEnergyInter = true;
236       }
237       theParticipants.InitProjectileNucleus( ProjectileResidualMassNumber, ProjectileResidualCharge,
238                                              ProjectileResidualLambdaNumber );
239       theParticipants.GetProjectileNucleus()->StartLoop();
240       G4Nucleon* aNucleon;
241       while ( ( aNucleon = theParticipants.GetProjectileNucleus()->GetNextNucleon() ) ) {  /* Loop checking, 10.08.2015, A.Ribon */
242         if ( aNucleon->GetDefinition() == G4Proton::Definition() ) {
243           aNucleon->SetParticleType( G4AntiProton::Definition() ); 
244         } else if ( aNucleon->GetDefinition() == G4Neutron::Definition() ) {
245           aNucleon->SetParticleType( G4AntiNeutron::Definition() );
246         } else if ( aNucleon->GetDefinition() == G4Lambda::Definition() ) {
247     aNucleon->SetParticleType( G4AntiLambda::Definition() );
248   }
249       }
250     }
251 
252     G4ThreeVector BoostVector = theProjectile.GetMomentum() / theProjectile.GetTotalEnergy();
253     theParticipants.GetProjectileNucleus()->DoLorentzBoost( BoostVector );
254     theParticipants.GetProjectileNucleus()->DoLorentzContraction( BoostVector );
255     ProjectileResidualExcitationEnergy = 0.0;
256     //G4double ProjectileResidualMass = theProjectile.GetMass();
257     ProjectileResidual4Momentum.setVect( theProjectile.GetMomentum() );
258     ProjectileResidual4Momentum.setE( theProjectile.GetTotalEnergy() );
259   }
260 
261   // Init target nucleus (assumed to be never a hypernucleus)
262   theParticipants.Init( aNucleus.GetA_asInt(), aNucleus.GetZ_asInt() );
263 
264   NumberOfProjectileSpectatorNucleons = std::abs( theProjectile.GetDefinition()->GetBaryonNumber() );
265   NumberOfTargetSpectatorNucleons = aNucleus.GetA_asInt();
266   NumberOfNNcollisions = 0;
267 
268   // reset/recalculate everything for the new interaction
269   theParameters->InitForInteraction( theProjectile.GetDefinition(), aNucleus.GetA_asInt(),
270                                      aNucleus.GetZ_asInt(), PlabPerParticle ); 
271 
272   if ( theAdditionalString.size() != 0 ) {
273     std::for_each( theAdditionalString.begin(), theAdditionalString.end(), 
274                    DeleteVSplitableHadron() );
275   }
276   theAdditionalString.clear();
277 
278   #ifdef debugFTFmodel
279   G4cout << "FTF end of Init" << G4endl << G4endl;
280   #endif
281 
282   // In the case of Hydrogen target, for non-ion hadron projectiles,
283   // do NOT simulate quasi-elastic (by forcing to 0 the probability of
284   // elastic scatering in theParameters - which is used only by FTF).
285   // This is necessary because in this case quasi-elastic on a target nucleus
286   // with only one nucleon would be identical to the hadron elastic scattering,
287   // and the latter is already included in the elastic process 
288   // (i.e. G4HadronElasticProcess).
289   if ( std::abs( theProjectile.GetDefinition()->GetBaryonNumber() ) <= 1  &&
290        aNucleus.GetA_asInt() < 2 ) theParameters->SetProbabilityOfElasticScatt( 0.0 );
291 
292   if ( SampleBinInterval() ) theParticipants.SetBminBmax( GetBmin(), GetBmax() );
293 }
294 
295 
296 //============================================================================
297 
298 G4ExcitedStringVector* G4FTFModel::GetStrings() { 
299 
300   #ifdef debugFTFmodel
301   G4cout << "G4FTFModel::GetStrings() " << G4endl;
302   #endif
303 
304   G4ExcitedStringVector* theStrings = new G4ExcitedStringVector;
305   theParticipants.GetList( theProjectile, theParameters );
306 
307   SetImpactParameter( theParticipants.GetImpactParameter() );
308 
309   StoreInvolvedNucleon(); 
310 
311   G4bool Success( true );
312 
313   if ( HighEnergyInter ) {
314     ReggeonCascade(); 
315  
316     #ifdef debugFTFmodel
317     G4cout << "FTF PutOnMassShell " << G4endl;
318     #endif
319 
320     Success = PutOnMassShell(); 
321 
322     #ifdef debugFTFmodel
323     G4cout << "FTF PutOnMassShell Success?  " << Success << G4endl;
324     #endif
325 
326   }
327 
328   #ifdef debugFTFmodel
329   G4cout << "FTF ExciteParticipants " << G4endl;
330   #endif
331 
332   if ( Success ) Success = ExciteParticipants();
333 
334   #ifdef debugFTFmodel
335   G4cout << "FTF ExciteParticipants Success? " << Success << G4endl;
336   #endif
337 
338   if ( Success ) {       
339 
340     #ifdef debugFTFmodel
341     G4cout << "FTF BuildStrings ";
342     #endif
343 
344     BuildStrings( theStrings );
345 
346     #ifdef debugFTFmodel
347     G4cout << "FTF BuildStrings " << theStrings << " OK" << G4endl
348            << "FTF GetResiduals of Nuclei " << G4endl;
349     #endif
350 
351     GetResiduals();
352 
353     /*
354     if ( theParameters != 0 ) {
355       delete theParameters;
356       theParameters = 0;
357     }
358     */
359   } else if ( ! GetProjectileNucleus() ) {
360     // Erase the hadron projectile
361     std::vector< G4VSplitableHadron* > primaries;
362     theParticipants.StartLoop();
363     while ( theParticipants.Next() ) {  /* Loop checking, 10.08.2015, A.Ribon */
364       const G4InteractionContent& interaction = theParticipants.GetInteraction();
365       // Do not allow for duplicates
366       if ( primaries.end() == 
367            std::find( primaries.begin(), primaries.end(), interaction.GetProjectile() ) ) {
368         primaries.push_back( interaction.GetProjectile() );
369       }
370     }
371     std::for_each( primaries.begin(), primaries.end(), DeleteVSplitableHadron() );
372     primaries.clear();
373   }
374 
375   // Cleaning of the memory
376   G4VSplitableHadron* aNucleon = 0;
377 
378   // Erase the projectile nucleons
379   for ( G4int i = 0; i < NumberOfInvolvedNucleonsOfProjectile; ++i ) {
380     aNucleon = TheInvolvedNucleonsOfProjectile[i]->GetSplitableHadron();
381     if ( aNucleon ) delete aNucleon;
382   } 
383   NumberOfInvolvedNucleonsOfProjectile = 0;
384 
385   // Erase the target nucleons
386   for ( G4int i = 0; i < NumberOfInvolvedNucleonsOfTarget; ++i ) {
387     aNucleon = TheInvolvedNucleonsOfTarget[i]->GetSplitableHadron();
388     if ( aNucleon ) delete aNucleon;
389   } 
390   NumberOfInvolvedNucleonsOfTarget = 0;
391 
392   #ifdef debugFTFmodel
393   G4cout << "End of FTF. Go to fragmentation" << G4endl
394          << "To continue - enter 1, to stop - ^C" << G4endl;
395   #endif
396 
397   theParticipants.Clean();
398 
399   return theStrings;
400 }
401 
402 
403 //============================================================================
404 
405 void G4FTFModel::StoreInvolvedNucleon() {
406   //To store nucleons involved in the interaction
407 
408   NumberOfInvolvedNucleonsOfTarget = 0;
409 
410   G4V3DNucleus* theTargetNucleus = GetTargetNucleus();
411   theTargetNucleus->StartLoop();
412 
413   G4Nucleon* aNucleon;
414   while ( ( aNucleon = theTargetNucleus->GetNextNucleon() ) ) {  /* Loop checking, 10.08.2015, A.Ribon */
415     if ( aNucleon->AreYouHit() ) {
416       TheInvolvedNucleonsOfTarget[NumberOfInvolvedNucleonsOfTarget] = aNucleon;
417       NumberOfInvolvedNucleonsOfTarget++;
418     }
419   }
420 
421   #ifdef debugFTFmodel
422   G4cout << "G4FTFModel::StoreInvolvedNucleon -------------" << G4endl;
423   G4cout << "NumberOfInvolvedNucleonsOfTarget " << NumberOfInvolvedNucleonsOfTarget
424          << G4endl << G4endl;
425   #endif
426 
427 
428   if ( ! GetProjectileNucleus() ) return;  // The projectile is a hadron
429 
430   // The projectile is a nucleus or an anti-nucleus.
431 
432   NumberOfInvolvedNucleonsOfProjectile = 0;
433 
434   G4V3DNucleus* theProjectileNucleus = GetProjectileNucleus();
435   theProjectileNucleus->StartLoop();
436 
437   G4Nucleon* aProjectileNucleon;
438   while ( ( aProjectileNucleon = theProjectileNucleus->GetNextNucleon() ) ) {  /* Loop checking, 10.08.2015, A.Ribon */
439     if ( aProjectileNucleon->AreYouHit() ) {  
440       // Projectile nucleon was involved in the interaction.
441       TheInvolvedNucleonsOfProjectile[NumberOfInvolvedNucleonsOfProjectile] = aProjectileNucleon;
442       NumberOfInvolvedNucleonsOfProjectile++;
443     }
444   } 
445 
446   #ifdef debugFTFmodel
447   G4cout << "NumberOfInvolvedNucleonsOfProjectile " << NumberOfInvolvedNucleonsOfProjectile
448          << G4endl << G4endl;
449   #endif
450   return;
451 }                        
452 
453 
454 //============================================================================
455 
456 void G4FTFModel::ReggeonCascade() { 
457   // Implementation of the reggeon theory inspired model
458 
459   #ifdef debugReggeonCascade
460   G4cout << "G4FTFModel::ReggeonCascade -----------" << G4endl
461          << "theProjectile.GetTotalMomentum() " << theProjectile.GetTotalMomentum() << G4endl
462          << "theProjectile.GetTotalEnergy() " << theProjectile.GetTotalEnergy() << G4endl
463          << "ExcitationE/WN " << theParameters->GetExcitationEnergyPerWoundedNucleon() << G4endl;
464   #endif
465 
466   G4int InitNINt = NumberOfInvolvedNucleonsOfTarget;
467 
468   // Reggeon cascading in target nucleus
469   for ( G4int InvTN = 0; InvTN < InitNINt; InvTN++ ) { 
470     G4Nucleon* aTargetNucleon = TheInvolvedNucleonsOfTarget[ InvTN ];
471 
472     G4double CreationTime = aTargetNucleon->GetSplitableHadron()->GetTimeOfCreation();
473 
474     G4double XofWoundedNucleon = aTargetNucleon->GetPosition().x();
475     G4double YofWoundedNucleon = aTargetNucleon->GetPosition().y();
476            
477     G4V3DNucleus* theTargetNucleus = GetTargetNucleus();
478     theTargetNucleus->StartLoop();
479 
480     G4Nucleon* Neighbour(0);
481     while ( ( Neighbour = theTargetNucleus->GetNextNucleon() ) ) {  /* Loop checking, 10.08.2015, A.Ribon */
482       if ( ! Neighbour->AreYouHit() ) {
483         G4double impact2 = sqr( XofWoundedNucleon - Neighbour->GetPosition().x() ) +
484                            sqr( YofWoundedNucleon - Neighbour->GetPosition().y() );
485 
486         if ( G4UniformRand() < theParameters->GetCofNuclearDestruction() *
487                                G4Exp( -impact2 / theParameters->GetR2ofNuclearDestruction() )
488            ) {  
489           // The neighbour nucleon is involved in the reggeon cascade
490           TheInvolvedNucleonsOfTarget[ NumberOfInvolvedNucleonsOfTarget ] = Neighbour;
491           NumberOfInvolvedNucleonsOfTarget++;
492 
493           G4VSplitableHadron* targetSplitable; 
494           targetSplitable = new G4DiffractiveSplitableHadron( *Neighbour ); 
495 
496           Neighbour->Hit( targetSplitable );
497           targetSplitable->SetTimeOfCreation( CreationTime ); 
498           targetSplitable->SetStatus( 3 );  // 2->3
499         }
500       }
501     }
502   }
503 
504   #ifdef debugReggeonCascade
505   G4cout << "Final NumberOfInvolvedNucleonsOfTarget " 
506          << NumberOfInvolvedNucleonsOfTarget << G4endl << G4endl;
507   #endif
508 
509   if ( ! GetProjectileNucleus() ) return;
510 
511   // Nucleus-Nucleus Interaction : Destruction of Projectile
512   G4int InitNINp = NumberOfInvolvedNucleonsOfProjectile;
513 
514   //for ( G4int InvPN = 0; InvPN < NumberOfInvolvedNucleonsOfProjectile; InvPN++ ) { 
515   for ( G4int InvPN = 0; InvPN < InitNINp; InvPN++ ) { 
516     G4Nucleon* aProjectileNucleon = TheInvolvedNucleonsOfProjectile[ InvPN ];
517 
518     G4double CreationTime = aProjectileNucleon->GetSplitableHadron()->GetTimeOfCreation();
519 
520     G4double XofWoundedNucleon = aProjectileNucleon->GetPosition().x();
521     G4double YofWoundedNucleon = aProjectileNucleon->GetPosition().y();
522            
523     G4V3DNucleus* theProjectileNucleus = GetProjectileNucleus();
524     theProjectileNucleus->StartLoop();
525 
526     G4Nucleon* Neighbour( 0 );
527     while ( ( Neighbour = theProjectileNucleus->GetNextNucleon() ) ) {  /* Loop checking, 10.08.2015, A.Ribon */
528       if ( ! Neighbour->AreYouHit() ) {
529         G4double impact2= sqr( XofWoundedNucleon - Neighbour->GetPosition().x() ) +
530                           sqr( YofWoundedNucleon - Neighbour->GetPosition().y() );
531 
532         if ( G4UniformRand() < theParameters->GetCofNuclearDestructionPr() * 
533                                G4Exp( -impact2 / theParameters->GetR2ofNuclearDestruction() )
534            ) {
535           // The neighbour nucleon is involved in the reggeon cascade
536           TheInvolvedNucleonsOfProjectile[ NumberOfInvolvedNucleonsOfProjectile ] = Neighbour;
537           NumberOfInvolvedNucleonsOfProjectile++;
538 
539           G4VSplitableHadron* projectileSplitable; 
540           projectileSplitable = new G4DiffractiveSplitableHadron( *Neighbour ); 
541 
542           Neighbour->Hit( projectileSplitable );
543           projectileSplitable->SetTimeOfCreation( CreationTime );
544           projectileSplitable->SetStatus( 3 );
545         }
546       }
547     }
548   }
549 
550   #ifdef debugReggeonCascade
551   G4cout << "NumberOfInvolvedNucleonsOfProjectile "
552          << NumberOfInvolvedNucleonsOfProjectile << G4endl << G4endl;
553   #endif
554 }   
555 
556 
557 //============================================================================
558 
559 G4bool G4FTFModel::PutOnMassShell() {
560 
561   G4bool isProjectileNucleus = false;
562   if ( GetProjectileNucleus() ) isProjectileNucleus = true;
563 
564   #ifdef debugPutOnMassShell
565   G4cout << "PutOnMassShell start " << G4endl;
566   if ( isProjectileNucleus ) {
567     G4cout << "PutOnMassShell for Nucleus_Nucleus " << G4endl;
568   }
569   #endif
570 
571   G4LorentzVector Pprojectile( theProjectile.GetMomentum(), theProjectile.GetTotalEnergy() );
572   if ( Pprojectile.z() < 0.0 ) return false;
573 
574   G4bool isOk = true;
575   
576   G4LorentzVector Ptarget( 0.0, 0.0, 0.0, 0.0 );
577   G4LorentzVector PtargetResidual( 0.0, 0.0, 0.0, 0.0 );
578   G4double SumMasses = 0.0;
579   G4V3DNucleus* theTargetNucleus = GetTargetNucleus();
580   G4double TargetResidualMass = 0.0; 
581 
582   #ifdef debugPutOnMassShell
583   G4cout << "Target : ";
584   #endif
585   isOk = ComputeNucleusProperties( theTargetNucleus, Ptarget, PtargetResidual, SumMasses,
586                                    TargetResidualExcitationEnergy, TargetResidualMass,
587                                    TargetResidualMassNumber, TargetResidualCharge );
588   if ( ! isOk ) return false;
589 
590   G4double Mprojectile  = 0.0;
591   G4double M2projectile = 0.0;
592   G4LorentzVector Pproj( 0.0, 0.0, 0.0, 0.0 );
593   G4LorentzVector PprojResidual( 0.0, 0.0, 0.0, 0.0 );
594   G4V3DNucleus* thePrNucleus = GetProjectileNucleus();
595   G4double PrResidualMass = 0.0;
596 
597   if ( ! isProjectileNucleus ) {  // hadron-nucleus collision
598     Mprojectile  = Pprojectile.mag();
599     M2projectile = Pprojectile.mag2();
600     SumMasses += Mprojectile + 20.0*MeV;
601   } else {  // nucleus-nucleus or antinucleus-nucleus collision
602     #ifdef debugPutOnMassShell
603     G4cout << "Projectile : ";
604     #endif
605     isOk = ComputeNucleusProperties( thePrNucleus, Pproj, PprojResidual, SumMasses,
606                                      ProjectileResidualExcitationEnergy, PrResidualMass,
607                                      ProjectileResidualMassNumber, ProjectileResidualCharge );
608     if ( ! isOk ) return false;
609   }
610 
611   G4LorentzVector Psum = Pprojectile + Ptarget;   
612   G4double SqrtS = Psum.mag();
613   G4double     S = Psum.mag2();
614 
615   #ifdef debugPutOnMassShell
616   G4cout << "Psum " << Psum/GeV << " GeV" << G4endl << "SqrtS " << SqrtS/GeV << " GeV" << G4endl
617          << "SumMasses, PrResidualMass and TargetResidualMass " << SumMasses/GeV << " " 
618          << PrResidualMass/GeV << " " << TargetResidualMass/GeV << " GeV" << G4endl;
619   #endif
620 
621   if ( SqrtS < SumMasses ) return false;  // It is impossible to simulate after putting nuclear nucleons on mass-shell
622 
623   // Try to consider also the excitation energy of the residual nucleus, if this is
624   // possible, with the available energy; otherwise, set the excitation energy to zero.
625   G4double savedSumMasses = SumMasses;
626   if ( isProjectileNucleus ) {
627     SumMasses -= std::sqrt( sqr( PrResidualMass ) + PprojResidual.perp2() );
628     SumMasses += std::sqrt( sqr( PrResidualMass + ProjectileResidualExcitationEnergy ) 
629                             + PprojResidual.perp2() ); 
630   }
631   SumMasses -= std::sqrt( sqr( TargetResidualMass ) + PtargetResidual.perp2() );
632   SumMasses += std::sqrt( sqr( TargetResidualMass + TargetResidualExcitationEnergy )
633                           + PtargetResidual.perp2() );
634 
635   if ( SqrtS < SumMasses ) {
636     SumMasses = savedSumMasses;
637     if ( isProjectileNucleus ) ProjectileResidualExcitationEnergy = 0.0;
638     TargetResidualExcitationEnergy = 0.0;
639   }
640 
641   TargetResidualMass += TargetResidualExcitationEnergy;
642   if ( isProjectileNucleus ) PrResidualMass += ProjectileResidualExcitationEnergy;
643 
644   #ifdef debugPutOnMassShell
645   if ( isProjectileNucleus ) {
646     G4cout << "PrResidualMass ProjResidualExcitationEnergy " << PrResidualMass/GeV << " "
647      << ProjectileResidualExcitationEnergy << " MeV" << G4endl;
648   }
649   G4cout << "TargetResidualMass TargetResidualExcitationEnergy " << TargetResidualMass/GeV << " " 
650          << TargetResidualExcitationEnergy << " MeV" << G4endl
651          << "Sum masses " << SumMasses/GeV << G4endl;
652   #endif
653 
654   // Sampling of nucleons what can transfer to delta-isobars
655   if ( isProjectileNucleus  &&  thePrNucleus->GetMassNumber() != 1 ) {
656       isOk = GenerateDeltaIsobar( SqrtS, NumberOfInvolvedNucleonsOfProjectile,
657                                   TheInvolvedNucleonsOfProjectile, SumMasses );       
658   }
659   if ( theTargetNucleus->GetMassNumber() != 1 ) {
660     isOk = isOk  &&  GenerateDeltaIsobar( SqrtS, NumberOfInvolvedNucleonsOfTarget,
661                                           TheInvolvedNucleonsOfTarget, SumMasses );
662   }
663   if ( ! isOk ) return false;
664 
665   // Now we know that it is kinematically possible to produce a final state made
666   // of the involved nucleons (or corresponding delta-isobars) and a residual nucleus.
667   // We have to sample the kinematical variables which will allow to define the 4-momenta
668   // of the final state. The sampled kinematical variables refer to the center-of-mass frame.
669   // Notice that the sampling of the transverse momentum corresponds to take into account
670   // Fermi motion.
671 
672   G4LorentzRotation toCms( -1*Psum.boostVector() );
673   G4LorentzVector Ptmp = toCms*Pprojectile;
674   if ( Ptmp.pz() <= 0.0 ) return false;  // "String" moving backwards in c.m.s., abort collision!
675 
676   G4LorentzRotation toLab( toCms.inverse() );
677   
678   G4double YprojectileNucleus = 0.0;
679   if ( isProjectileNucleus ) {
680     Ptmp = toCms*Pproj;                      
681     YprojectileNucleus = Ptmp.rapidity();
682   }
683   Ptmp = toCms*Ptarget;                      
684   G4double YtargetNucleus = Ptmp.rapidity();
685 
686   // Ascribing of the involved nucleons Pt and Xminus
687   G4double DcorP = 0.0;
688   if ( isProjectileNucleus ) DcorP = theParameters->GetDofNuclearDestruction() / thePrNucleus->GetMassNumber();
689   G4double DcorT       = theParameters->GetDofNuclearDestruction() / theTargetNucleus->GetMassNumber();
690   G4double AveragePt2  = theParameters->GetPt2ofNuclearDestruction();
691   G4double maxPtSquare = theParameters->GetMaxPt2ofNuclearDestruction();
692 
693   #ifdef debugPutOnMassShell
694   if ( isProjectileNucleus ) {
695     G4cout << "Y projectileNucleus " << YprojectileNucleus << G4endl;
696   }
697   G4cout << "Y targetNucleus     " << YtargetNucleus << G4endl 
698          << "Dcor " << theParameters->GetDofNuclearDestruction()
699          << " DcorP DcorT " << DcorP << " " << DcorT << " AveragePt2 " << AveragePt2 << G4endl;
700   #endif
701 
702   G4double M2proj = M2projectile;  // Initialization needed only for hadron-nucleus collisions
703   G4double WplusProjectile = 0.0;
704   G4double M2target = 0.0;
705   G4double WminusTarget = 0.0;
706   G4int NumberOfTries = 0;
707   G4double ScaleFactor = 2.0;
708   G4bool OuterSuccess = true;
709 
710   const G4int maxNumberOfLoops = 1000;
711   G4int loopCounter = 0;
712   do {  // while ( ! OuterSuccess )
713     OuterSuccess = true;
714     const G4int maxNumberOfInnerLoops = 10000;
715     do {  // while ( SqrtS < Mprojectile + std::sqrt( M2target ) )
716       NumberOfTries++;
717       if ( NumberOfTries == 100*(NumberOfTries/100) ) {
718         // After many tries, it is convenient to reduce the values of DcorP, DcorT and
719         // AveragePt2, so that the sampled momenta (respectively, pz, and pt) of the
720   // involved nucleons (or corresponding delta-isomers) are smaller, and therefore
721         // it is more likely to satisfy the momentum conservation.
722         ScaleFactor /= 2.0;
723         DcorP       *= ScaleFactor;
724         DcorT       *= ScaleFactor;
725         AveragePt2  *= ScaleFactor;
726       }
727       if ( isProjectileNucleus ) {
728         // Sampling of kinematical properties of projectile nucleons
729         isOk = SamplingNucleonKinematics( AveragePt2, maxPtSquare, DcorP, 
730                                           thePrNucleus, PprojResidual, 
731                                           PrResidualMass, ProjectileResidualMassNumber,
732                                           NumberOfInvolvedNucleonsOfProjectile, 
733                                           TheInvolvedNucleonsOfProjectile, M2proj );
734       }
735       // Sampling of kinematical properties of target nucleons
736       isOk = isOk  &&  SamplingNucleonKinematics( AveragePt2, maxPtSquare, DcorT, 
737                                                   theTargetNucleus, PtargetResidual, 
738                                                   TargetResidualMass, TargetResidualMassNumber,
739                                                   NumberOfInvolvedNucleonsOfTarget, 
740                                                   TheInvolvedNucleonsOfTarget, M2target );
741       #ifdef debugPutOnMassShell
742       G4cout << "SqrtS, Mp+Mt, Mp, Mt " << SqrtS/GeV << " " 
743              << ( std::sqrt( M2proj ) + std::sqrt( M2target) )/GeV << " "
744              << std::sqrt( M2proj )/GeV << " " << std::sqrt( M2target )/GeV << G4endl;
745       #endif
746       if ( ! isOk ) return false;
747     } while ( ( SqrtS < std::sqrt( M2proj ) + std::sqrt( M2target ) ) &&
748               NumberOfTries < maxNumberOfInnerLoops );  /* Loop checking, 10.08.2015, A.Ribon */
749     if ( NumberOfTries >= maxNumberOfInnerLoops ) {
750       #ifdef debugPutOnMassShell
751       G4cout << "BAD situation: forced exit of the inner while loop!" << G4endl;
752       #endif
753       return false;
754     }
755     if ( isProjectileNucleus ) {
756       isOk = CheckKinematics( S, SqrtS, M2proj, M2target, YprojectileNucleus, true, 
757                               NumberOfInvolvedNucleonsOfProjectile, 
758                               TheInvolvedNucleonsOfProjectile,
759                               WminusTarget, WplusProjectile, OuterSuccess );
760     }
761     isOk = isOk  &&  CheckKinematics( S, SqrtS, M2proj, M2target, YtargetNucleus, false, 
762                                       NumberOfInvolvedNucleonsOfTarget, TheInvolvedNucleonsOfTarget,
763                                       WminusTarget, WplusProjectile, OuterSuccess );
764     if ( ! isOk ) return false;
765   } while ( ( ! OuterSuccess ) &&
766             ++loopCounter < maxNumberOfLoops );  /* Loop checking, 10.08.2015, A.Ribon */
767   if ( loopCounter >= maxNumberOfLoops ) {
768     #ifdef debugPutOnMassShell
769     G4cout << "BAD situation: forced exit of the while loop!" << G4endl;
770     #endif
771     return false;
772   }
773 
774   // Now the sampling is completed, and we can determine the kinematics of the
775   // whole system. This is done first in the center-of-mass frame, and then it is boosted
776   // to the lab frame. The transverse momentum of the residual nucleus is determined as
777   // the recoil of each hadron (nucleon or delta) which is emitted, i.e. in such a way
778   // to conserve (by construction) the transverse momentum.
779 
780   if ( ! isProjectileNucleus ) {  // hadron-nucleus collision
781 
782     G4double Pzprojectile = WplusProjectile/2.0 - M2projectile/2.0/WplusProjectile;
783     G4double Eprojectile  = WplusProjectile/2.0 + M2projectile/2.0/WplusProjectile;
784     Pprojectile.setPz( Pzprojectile ); 
785     Pprojectile.setE( Eprojectile );
786 
787     #ifdef debugPutOnMassShell
788     G4cout << "Proj after in CMS " << Pprojectile << G4endl;
789     #endif
790 
791     Pprojectile.transform( toLab );  
792     theProjectile.SetMomentum( Pprojectile.vect() );
793     theProjectile.SetTotalEnergy( Pprojectile.e() );
794 
795     theParticipants.StartLoop();
796     theParticipants.Next();
797     G4VSplitableHadron* primary = theParticipants.GetInteraction().GetProjectile();
798     primary->Set4Momentum( Pprojectile ); 
799 
800     #ifdef debugPutOnMassShell
801     G4cout << "Final proj. mom in Lab. " << primary->Get4Momentum() << G4endl;
802     #endif
803 
804   } else {  // nucleus-nucleus or antinucleus-nucleus collision
805 
806     isOk = FinalizeKinematics( WplusProjectile, true, toLab, PrResidualMass, 
807                                ProjectileResidualMassNumber, NumberOfInvolvedNucleonsOfProjectile,
808                                TheInvolvedNucleonsOfProjectile, ProjectileResidual4Momentum );
809 
810     #ifdef debugPutOnMassShell
811     G4cout << "Projectile Residual4Momentum in CMS " << ProjectileResidual4Momentum << G4endl;
812     #endif
813 
814     if ( ! isOk ) return false;
815 
816     ProjectileResidual4Momentum.transform( toLab );
817 
818     #ifdef debugPutOnMassShell
819     G4cout << "Projectile Residual4Momentum in Lab " << ProjectileResidual4Momentum << G4endl;
820     #endif
821 
822   }
823 
824   isOk = FinalizeKinematics( WminusTarget, false, toLab, TargetResidualMass, 
825                              TargetResidualMassNumber, NumberOfInvolvedNucleonsOfTarget,
826                              TheInvolvedNucleonsOfTarget, TargetResidual4Momentum );
827 
828   #ifdef debugPutOnMassShell
829   G4cout << "Target Residual4Momentum in CMS " << TargetResidual4Momentum << G4endl;
830   #endif
831 
832   if ( ! isOk ) return false;
833 
834   TargetResidual4Momentum.transform( toLab );
835 
836   #ifdef debugPutOnMassShell
837   G4cout << "Target Residual4Momentum in Lab " << TargetResidual4Momentum << G4endl;
838   #endif
839 
840   return true;
841 
842 }
843 
844 
845 //============================================================================
846 
847 G4bool G4FTFModel::ExciteParticipants() {
848 
849   #ifdef debugBuildString
850   G4cout << "G4FTFModel::ExciteParticipants() " << G4endl;
851   #endif
852 
853   G4bool Success( false );
854   G4int MaxNumOfInelCollisions = G4int( theParameters->GetMaxNumberOfCollisions() );
855   if ( MaxNumOfInelCollisions > 0 ) {  //  Plab > Pbound, normal application of FTF is possible
856     G4double ProbMaxNumber = theParameters->GetMaxNumberOfCollisions() - MaxNumOfInelCollisions;
857     if ( G4UniformRand() < ProbMaxNumber ) MaxNumOfInelCollisions++;
858   } else { 
859     // Plab < Pbound, normal application of FTF is impossible,low energy corrections applied
860     MaxNumOfInelCollisions = 1;
861   }
862 
863   #ifdef debugBuildString
864   G4cout << "MaxNumOfInelCollisions per hadron/nucleon " << MaxNumOfInelCollisions << G4endl;
865   #endif
866 
867   G4int CurrentInteraction( 0 );
868   theParticipants.StartLoop();
869 
870   G4bool InnerSuccess( true );
871   while ( theParticipants.Next() ) {  /* Loop checking, 10.08.2015, A.Ribon */
872     CurrentInteraction++;
873     const G4InteractionContent& collision = theParticipants.GetInteraction();
874     G4VSplitableHadron* projectile = collision.GetProjectile();
875     G4Nucleon* ProjectileNucleon = collision.GetProjectileNucleon();
876     G4VSplitableHadron* target = collision.GetTarget();
877     G4Nucleon* TargetNucleon = collision.GetTargetNucleon();
878 
879     #ifdef debugBuildString
880     G4cout << G4endl << "Interaction # Status    " << CurrentInteraction << " " 
881            << collision.GetStatus() << G4endl << "Pr* Tr* " << projectile << " "
882            << target << G4endl << "projectile->GetStatus target->GetStatus "
883            << projectile->GetStatus() << " " << target->GetStatus() << G4endl
884            << "projectile->GetSoftC  target->GetSoftC  " << projectile->GetSoftCollisionCount()
885            << " " << target->GetSoftCollisionCount() << G4endl;
886     #endif
887 
888     if ( collision.GetStatus() ) {
889       if ( G4UniformRand() < theParameters->GetProbabilityOfElasticScatt() ) { 
890         // Elastic scattering
891 
892         #ifdef debugBuildString
893         G4cout << "Elastic scattering" << G4endl;
894         #endif
895 
896         if ( ! HighEnergyInter ) {
897           G4bool Annihilation = false;
898           G4bool Result = AdjustNucleons( projectile, ProjectileNucleon, target,
899                                           TargetNucleon, Annihilation );
900           if ( ! Result ) continue;
901          } 
902          InnerSuccess = theElastic->ElasticScattering( projectile, target, theParameters );
903       } else if ( G4UniformRand() > theParameters->GetProbabilityOfAnnihilation() ) { 
904         // Inelastic scattering
905 
906         #ifdef debugBuildString
907         G4cout << "Inelastic interaction" << G4endl
908                << "MaxNumOfInelCollisions per hadron/nucleon " << MaxNumOfInelCollisions << G4endl;
909         #endif
910 
911         if ( ! HighEnergyInter ) {
912           G4bool Annihilation = false;
913           G4bool Result = AdjustNucleons( projectile, ProjectileNucleon, target,
914                                           TargetNucleon, Annihilation );
915           if ( ! Result ) continue;
916         } 
917         if ( G4UniformRand() < 
918              ( 1.0 - target->GetSoftCollisionCount()     / MaxNumOfInelCollisions )  *
919              ( 1.0 - projectile->GetSoftCollisionCount() / MaxNumOfInelCollisions ) ) {
920           //if ( ! HighEnergyInter ) {
921           //  G4bool Annihilation = false;
922           //  G4bool Result = AdjustNucleons( projectile, ProjectileNucleon, target,
923           //                                  TargetNucleon, Annihilation );
924           //  if ( ! Result ) continue;
925           //} 
926           if ( theExcitation->ExciteParticipants( projectile, target, theParameters, theElastic ) ) {
927             InnerSuccess = true;
928             NumberOfNNcollisions++;
929             #ifdef debugBuildString
930             G4cout << "FTF excitation Successfull " << G4endl;
931             // G4cout << "After  pro " << projectile->Get4Momentum() << " " 
932             //        << projectile->Get4Momentum().mag() << G4endl
933             //        << "After  tar " << target->Get4Momentum() << " "
934             //        << target->Get4Momentum().mag() << G4endl;
935             #endif
936           } else {
937             InnerSuccess = theElastic->ElasticScattering( projectile, target, theParameters );
938             #ifdef debugBuildString
939             G4cout << "FTF excitation Non InnerSuccess of Elastic scattering " 
940                    << InnerSuccess << G4endl;
941             #endif
942           }
943         } else {  // The inelastic interactition was rejected -> elastic scattering
944           #ifdef debugBuildString
945           G4cout << "Elastic scat. at rejection inelastic scattering" << G4endl;
946           #endif
947           //if ( ! HighEnergyInter ) {
948           //  G4bool Annihilation = false;
949           //  G4bool Result = AdjustNucleons( projectile, ProjectileNucleon, target,
950           //                                  TargetNucleon, Annihilation );
951           //  if ( ! Result) continue;
952           //} 
953           InnerSuccess = theElastic->ElasticScattering( projectile, target, theParameters );
954         } 
955       } else {  // Annihilation
956 
957         #ifdef debugBuildString
958         G4cout << "Annihilation" << G4endl;
959         #endif
960 
961         // At last, annihilation
962         if ( ! HighEnergyInter ) {
963           G4bool Annihilation = true;
964           G4bool Result = AdjustNucleons( projectile, ProjectileNucleon, target,
965                                           TargetNucleon, Annihilation );
966           if ( ! Result ) continue;
967         }
968 
969         G4VSplitableHadron* AdditionalString = 0;
970         if ( theAnnihilation->Annihilate( projectile, target, AdditionalString, theParameters ) ) {
971           InnerSuccess = true;
972           #ifdef debugBuildString
973           G4cout << "Annihilation successfull. " << "*AdditionalString " 
974                  << AdditionalString << G4endl;
975           //G4cout << "After  pro " << projectile->Get4Momentum() << G4endl;
976           //G4cout << "After  tar " << target->Get4Momentum() << G4endl;
977           #endif
978 
979           if ( AdditionalString != 0 ) theAdditionalString.push_back( AdditionalString );
980 
981           NumberOfNNcollisions++;
982 
983           // Skipping possible interactions of the annihilated nucleons 
984           while ( theParticipants.Next() ) {   /* Loop checking, 10.08.2015, A.Ribon */  
985             G4InteractionContent& acollision = theParticipants.GetInteraction();
986             G4VSplitableHadron* NextProjectileNucleon = acollision.GetProjectile();
987             G4VSplitableHadron* NextTargetNucleon = acollision.GetTarget();
988             if ( projectile == NextProjectileNucleon  ||  target == NextTargetNucleon ) {
989               acollision.SetStatus( 0 );
990             }
991           }
992 
993           // Continue the interactions
994           theParticipants.StartLoop(); 
995           for ( G4int i = 0; i < CurrentInteraction; ++i ) theParticipants.Next();
996     
997           /*
998           if ( target->GetStatus() == 4 ) {
999             // Skipping possible interactions of the annihilated nucleons 
1000             while ( theParticipants.Next() ) {    
1001               G4InteractionContent& acollision = theParticipants.GetInteraction();
1002               G4VSplitableHadron* NextProjectileNucleon = acollision.GetProjectile();
1003               G4VSplitableHadron* NextTargetNucleon = acollision.GetTarget();
1004               if ( target == NextTargetNucleon ) { acollision.SetStatus( 0 ); }
1005             }
1006           }
1007           theParticipants.StartLoop(); 
1008           for ( G4int I = 0; I < CurrentInteraction; ++I ) theParticipants.Next();
1009           */
1010 
1011         }
1012       } 
1013     }
1014 
1015     if( InnerSuccess ) Success = true;
1016 
1017     #ifdef debugBuildString
1018     G4cout << "----------------------------- Final properties " << G4endl
1019            << "projectile->GetStatus target->GetStatus " << projectile->GetStatus() 
1020            << " " << target->GetStatus() << G4endl << "projectile->GetSoftC  target->GetSoftC  "
1021            << projectile->GetSoftCollisionCount() << " " << target->GetSoftCollisionCount()
1022            << G4endl << "ExciteParticipants() Success? " << Success << G4endl;
1023     #endif
1024 
1025   }  // end of while ( theParticipants.Next() )
1026 
1027   return Success;
1028 }
1029 
1030 
1031 //============================================================================
1032 
1033 G4bool G4FTFModel::AdjustNucleons( G4VSplitableHadron* SelectedAntiBaryon,
1034                                    G4Nucleon* ProjectileNucleon,
1035                                    G4VSplitableHadron* SelectedTargetNucleon,
1036                                    G4Nucleon* TargetNucleon,
1037                                    G4bool Annihilation ) {
1038 
1039   #ifdef debugAdjust
1040   G4cout << "AdjustNucleons ---------------------------------------" << G4endl
1041          << "Proj is nucleus? " << GetProjectileNucleus() << G4endl
1042          << "Proj 4mom " << SelectedAntiBaryon->Get4Momentum() << G4endl
1043          << "Targ 4mom " << SelectedTargetNucleon->Get4Momentum() << G4endl
1044          << "Pr ResidualMassNumber Pr ResidualCharge Pr ResidualExcitationEnergy "
1045          << ProjectileResidualMassNumber << " " << ProjectileResidualCharge << " "
1046          << ProjectileResidualExcitationEnergy << G4endl
1047          << "Tr ResidualMassNumber Tr ResidualCharge Tr ResidualExcitationEnergy  "
1048          << TargetResidualMassNumber << " " << TargetResidualCharge << " "
1049          << TargetResidualExcitationEnergy << G4endl
1050          << "Collis. pr tr " << SelectedAntiBaryon->GetSoftCollisionCount() << " "
1051          << SelectedTargetNucleon->GetSoftCollisionCount() << G4endl;
1052   #endif
1053 
1054   if ( SelectedAntiBaryon->GetSoftCollisionCount() != 0  && 
1055        SelectedTargetNucleon->GetSoftCollisionCount() != 0 ) {
1056     return true; // Selected hadrons were adjusted before.   
1057   }
1058 
1059   G4int interactionCase = 0;
1060   if (    ( ! GetProjectileNucleus()  &&
1061             SelectedAntiBaryon->GetSoftCollisionCount() == 0  &&
1062             SelectedTargetNucleon->GetSoftCollisionCount() == 0 )
1063        ||
1064           ( SelectedAntiBaryon->GetSoftCollisionCount() != 0  && 
1065             SelectedTargetNucleon->GetSoftCollisionCount() == 0 ) ) {
1066     // The case of hadron-nucleus interactions, or
1067     // the case when projectile nuclear nucleon participated in
1068     // a collision, but target nucleon did not participate.
1069     interactionCase = 1;
1070     #ifdef debugAdjust 
1071     G4cout << "case 1, hA prcol=0 trcol=0, AA prcol#0 trcol=0" << G4endl;
1072     #endif
1073     if ( TargetResidualMassNumber < 1 ) {
1074       return false;
1075     }
1076     if ( SelectedAntiBaryon->Get4Momentum().rapidity() < TargetResidual4Momentum.rapidity() ) {
1077       return false;
1078     }
1079     if ( TargetResidualMassNumber == 1 ) {
1080       TargetResidualMassNumber       = 0;
1081       TargetResidualCharge           = 0;
1082       TargetResidualExcitationEnergy = 0.0;
1083       SelectedTargetNucleon->Set4Momentum( TargetResidual4Momentum );
1084       TargetResidual4Momentum = G4LorentzVector( 0.0, 0.0, 0.0, 0.0 );
1085       return true;
1086     }
1087   } else if ( SelectedAntiBaryon->GetSoftCollisionCount() == 0  && 
1088               SelectedTargetNucleon->GetSoftCollisionCount() != 0 ) {
1089     // It is assumed that in the case there is ProjectileResidualNucleus
1090     interactionCase = 2;
1091     #ifdef debugAdjust
1092     G4cout << "case 2,  prcol=0 trcol#0" << G4endl;
1093     #endif
1094     if ( ProjectileResidualMassNumber < 1 ) {
1095       return false;
1096     }
1097     if ( ProjectileResidual4Momentum.rapidity() <= 
1098          SelectedTargetNucleon->Get4Momentum().rapidity() ) {
1099       return false;
1100     }
1101     if ( ProjectileResidualMassNumber == 1 ) {
1102       ProjectileResidualMassNumber       = 0;
1103       ProjectileResidualCharge           = 0;
1104       ProjectileResidualExcitationEnergy = 0.0;
1105       SelectedAntiBaryon->Set4Momentum( ProjectileResidual4Momentum );        
1106       ProjectileResidual4Momentum = G4LorentzVector( 0.0, 0.0, 0.0, 0.0 );
1107       return true;
1108     }
1109   } else {  // It has to be a nucleus-nucleus interaction
1110     interactionCase = 3;
1111     #ifdef debugAdjust
1112     G4cout << "case 3,  prcol=0 trcol=0" << G4endl;
1113     #endif
1114     if ( ! GetProjectileNucleus() ) {
1115       return false;
1116     }
1117     #ifdef debugAdjust
1118     G4cout << "Proj res Init " << ProjectileResidual4Momentum << G4endl
1119            << "Targ res Init " << TargetResidual4Momentum << G4endl
1120            << "ProjectileResidualMassNumber ProjectileResidualCharge (ProjectileResidualLambdaNumber)" 
1121            << ProjectileResidualMassNumber << " " << ProjectileResidualCharge
1122            << " (" << ProjectileResidualLambdaNumber << ") " << G4endl
1123            << "TargetResidualMassNumber TargetResidualCharge " << TargetResidualMassNumber
1124            << " " << TargetResidualCharge << G4endl;
1125     #endif
1126   }
1127 
1128   CommonVariables common;
1129   G4int returnCode = AdjustNucleonsAlgorithm_beforeSampling( interactionCase, SelectedAntiBaryon,
1130                                                              ProjectileNucleon, SelectedTargetNucleon,
1131                                                              TargetNucleon, Annihilation, common );
1132   G4bool returnResult = false;
1133   if ( returnCode == 0 ) {
1134     returnResult = true;  // Successfully ended: no need of extra work
1135   } else if ( returnCode == 1 ) {
1136     // The part before sampling has been successfully completed: now try the sampling
1137     returnResult = AdjustNucleonsAlgorithm_Sampling( interactionCase, common );
1138     if ( returnResult ) {  // The sampling has completed successfully: do the last part
1139       AdjustNucleonsAlgorithm_afterSampling( interactionCase, SelectedAntiBaryon, 
1140                                              SelectedTargetNucleon, common ); 
1141     }
1142   }
1143 
1144   return returnResult;
1145 }
1146 
1147 //-------------------------------------------------------------------
1148 
1149 G4int G4FTFModel::AdjustNucleonsAlgorithm_beforeSampling( G4int interactionCase,
1150                                                           G4VSplitableHadron* SelectedAntiBaryon,
1151                                                           G4Nucleon* ProjectileNucleon,
1152                                                           G4VSplitableHadron* SelectedTargetNucleon,
1153                                                           G4Nucleon* TargetNucleon,
1154                                                           G4bool Annihilation,
1155                                                           G4FTFModel::CommonVariables& common ) {
1156   // First of the three utility methods used only by AdjustNucleons: prepare for sampling.
1157   // This method returns an integer code - instead of a boolean, with the following meaning:
1158   //   "0" : successfully ended and nothing else needs to be done (i.e. no sampling);
1159   //   "1" : successfully completed, but the work needs to be continued, i.e. try to sample;
1160   //  "99" : unsuccessfully ended, nothing else can be done.
1161   G4int returnCode = 99;
1162 
1163   G4double ExcitationEnergyPerWoundedNucleon = theParameters->GetExcitationEnergyPerWoundedNucleon();
1164  
1165   // some checks and initializations
1166   if ( interactionCase == 1 ) {
1167     common.Psum = SelectedAntiBaryon->Get4Momentum() + TargetResidual4Momentum;
1168     #ifdef debugAdjust
1169     G4cout << "Targ res Init " << TargetResidual4Momentum << G4endl;
1170     #endif
1171     common.Pprojectile = SelectedAntiBaryon->Get4Momentum();
1172   } else if ( interactionCase == 2 ) {
1173     common.Psum = ProjectileResidual4Momentum + SelectedTargetNucleon->Get4Momentum();
1174     common.Pprojectile = ProjectileResidual4Momentum;
1175   } else if ( interactionCase == 3 ) {
1176     common.Psum = ProjectileResidual4Momentum + TargetResidual4Momentum; 
1177     common.Pprojectile = ProjectileResidual4Momentum;
1178   }
1179 
1180   // transform momenta to cms and then rotate parallel to z axis
1181   common.toCms = G4LorentzRotation( -1*common.Psum.boostVector() ); 
1182   common.Ptmp = common.toCms * common.Pprojectile;
1183   common.toCms.rotateZ( -1*common.Ptmp.phi() );
1184   common.toCms.rotateY( -1*common.Ptmp.theta() );
1185   common.Pprojectile.transform( common.toCms );
1186   common.toLab = common.toCms.inverse();
1187   common.SqrtS = common.Psum.mag();
1188   common.S = sqr( common.SqrtS );
1189 
1190   // get properties of the target residual and/or projectile residual
1191   G4bool Stopping = false;
1192   if ( interactionCase == 1 ) {
1193     common.TResidualMassNumber = TargetResidualMassNumber - 1;
1194     common.TResidualCharge =   TargetResidualCharge 
1195                              - G4int( TargetNucleon->GetDefinition()->GetPDGCharge() );
1196     common.TResidualExcitationEnergy =   TargetResidualExcitationEnergy
1197                                        - ExcitationEnergyPerWoundedNucleon*G4Log( G4UniformRand() );
1198     if ( common.TResidualMassNumber <= 1 ) {
1199       common.TResidualExcitationEnergy = 0.0;
1200     }
1201     if ( common.TResidualMassNumber != 0 ) {
1202       common.TResidualMass = G4ParticleTable::GetParticleTable()->GetIonTable()
1203                              ->GetIonMass( common.TResidualCharge, common.TResidualMassNumber );
1204     }
1205     common.TNucleonMass = TargetNucleon->GetDefinition()->GetPDGMass();
1206     common.SumMasses =   SelectedAntiBaryon->Get4Momentum().mag() + common.TNucleonMass 
1207                        + common.TResidualMass;
1208     #ifdef debugAdjust
1209     G4cout << "Annihilation " << Annihilation << G4endl;
1210     #endif
1211   } else if ( interactionCase == 2 ) {
1212     common.Ptarget = common.toCms * SelectedTargetNucleon->Get4Momentum();
1213     common.TResidualMassNumber = ProjectileResidualMassNumber - 1;
1214     common.TResidualCharge =   ProjectileResidualCharge 
1215                              - std::abs( G4int(ProjectileNucleon->GetDefinition()->GetPDGCharge()) );
1216     common.TResidualExcitationEnergy =   ProjectileResidualExcitationEnergy 
1217                                        - ExcitationEnergyPerWoundedNucleon*G4Log( G4UniformRand() );
1218     if ( common.TResidualMassNumber <= 1 ) {
1219       common.TResidualExcitationEnergy = 0.0;
1220     }
1221     if ( common.TResidualMassNumber != 0 ) {
1222       common.TResidualMass = G4ParticleTable::GetParticleTable()->GetIonTable()
1223                              ->GetIonMass( common.TResidualCharge, common.TResidualMassNumber );
1224     }
1225     common.TNucleonMass = ProjectileNucleon->GetDefinition()->GetPDGMass();
1226     common.SumMasses =   SelectedTargetNucleon->Get4Momentum().mag() + common.TNucleonMass 
1227                        + common.TResidualMass;
1228     #ifdef debugAdjust
1229     G4cout << "SelectedTN.mag() PNMass + PResidualMass " 
1230            << SelectedTargetNucleon->Get4Momentum().mag() << " " 
1231            << common.TNucleonMass << " " << common.TResidualMass << G4endl;
1232     #endif
1233   } else if ( interactionCase == 3 ) {
1234     common.Ptarget = common.toCms * TargetResidual4Momentum;
1235     common.PResidualMassNumber = ProjectileResidualMassNumber - 1;
1236     common.PResidualCharge =   ProjectileResidualCharge 
1237                              - std::abs( G4int(ProjectileNucleon->GetDefinition()->GetPDGCharge()) );
1238     common.PResidualLambdaNumber = ProjectileResidualLambdaNumber;
1239     if ( ProjectileNucleon->GetDefinition() == G4Lambda::Definition()  ||
1240    ProjectileNucleon->GetDefinition() == G4AntiLambda::Definition() ) {
1241       --common.PResidualLambdaNumber;  
1242     }
1243     common.PResidualExcitationEnergy =   ProjectileResidualExcitationEnergy 
1244                                        - ExcitationEnergyPerWoundedNucleon*G4Log( G4UniformRand() );
1245     if ( common.PResidualMassNumber <= 1 ) {
1246       common.PResidualExcitationEnergy = 0.0;
1247     }
1248     if ( common.PResidualMassNumber != 0 ) {
1249       if ( common.PResidualMassNumber == 1 ) {
1250         if ( std::abs( common.PResidualCharge ) == 1 ) {
1251           common.PResidualMass = G4Proton::Definition()->GetPDGMass();       
1252         } else if ( common.PResidualLambdaNumber == 1 ) {
1253           common.PResidualMass = G4Lambda::Definition()->GetPDGMass();
1254         } else {
1255           common.PResidualMass = G4Neutron::Definition()->GetPDGMass();
1256         }
1257       } else {
1258         if ( common.PResidualLambdaNumber > 0 ) {
1259           if ( common.PResidualMassNumber == 2 ) {
1260             common.PResidualMass = G4Lambda::Definition()->GetPDGMass();
1261       if ( std::abs( common.PResidualCharge ) == 1 ) {   // lambda + proton
1262         common.PResidualMass += G4Proton::Definition()->GetPDGMass();
1263       } else if ( common.PResidualLambdaNumber == 1 ) {  // lambda + neutron
1264         common.PResidualMass += G4Neutron::Definition()->GetPDGMass();
1265       } else {                                           // lambda + lambda
1266         common.PResidualMass += G4Lambda::Definition()->GetPDGMass();
1267       }
1268     } else {
1269       common.PResidualMass = G4HyperNucleiProperties::GetNuclearMass( common.PResidualMassNumber,
1270                         std::abs( common.PResidualCharge ),
1271                       common.PResidualLambdaNumber );
1272     }
1273         } else {
1274     common.PResidualMass = G4ParticleTable::GetParticleTable()->GetIonTable()->
1275                            GetIonMass( std::abs( common.PResidualCharge ), common.PResidualMassNumber );
1276         }
1277       }
1278     }
1279     common.PNucleonMass = ProjectileNucleon->GetDefinition()->GetPDGMass();  // On-shell (anti-)nucleon mass 
1280     common.TResidualMassNumber = TargetResidualMassNumber - 1;
1281     common.TResidualCharge =   TargetResidualCharge
1282                              - G4int( TargetNucleon->GetDefinition()->GetPDGCharge() );
1283     common.TResidualExcitationEnergy =   TargetResidualExcitationEnergy 
1284                                        - ExcitationEnergyPerWoundedNucleon*G4Log( G4UniformRand() );
1285     if ( common.TResidualMassNumber <= 1 ) {
1286       common.TResidualExcitationEnergy = 0.0;
1287     }
1288     if ( common.TResidualMassNumber != 0 ) {
1289       common.TResidualMass = G4ParticleTable::GetParticleTable()->GetIonTable()->
1290                              GetIonMass( common.TResidualCharge, common.TResidualMassNumber );
1291     }
1292     common.TNucleonMass = TargetNucleon->GetDefinition()->GetPDGMass();  // On-shell nucleon mass
1293     common.SumMasses =   common.PNucleonMass + common.PResidualMass + common.TNucleonMass 
1294                        + common.TResidualMass;
1295     #ifdef debugAdjust
1296     G4cout << "PNucleonMass PResidualMass TNucleonMass TResidualMass " << common.PNucleonMass 
1297            << " " << common.PResidualMass << " " << common.TNucleonMass << " " 
1298            << common.TResidualMass << G4endl
1299            << "PResidualExcitationEnergy " << common.PResidualExcitationEnergy << G4endl
1300            << "TResidualExcitationEnergy " << common.TResidualExcitationEnergy << G4endl;
1301     #endif
1302   }  // End-if on interactionCase
1303 
1304   if ( ! Annihilation ) {
1305     if ( common.SqrtS < common.SumMasses ) {
1306       #ifdef debugAdjust
1307       G4cout << "SqrtS < SumMasses " << common.SqrtS << " " << common.SumMasses << G4endl;
1308       #endif
1309       return returnCode;  // Unsuccessfully ended, nothing else can be done
1310     } 
1311     if ( interactionCase == 1  ||  interactionCase == 2 ) {
1312       if ( common.SqrtS < common.SumMasses + common.TResidualExcitationEnergy ) {
1313         #ifdef debugAdjust
1314         G4cout << "TResidualExcitationEnergy : before " << common.TResidualExcitationEnergy << G4endl;
1315         #endif
1316         common.TResidualExcitationEnergy = common.SqrtS - common.SumMasses;
1317         #ifdef debugAdjust
1318         G4cout << "TResidualExcitationEnergy : after " << common.TResidualExcitationEnergy << G4endl;
1319         #endif
1320         Stopping = true;
1321         return returnCode;  // unsuccessfully ended, nothing else can be done
1322       }
1323     } else if ( interactionCase == 3 ) {
1324       #ifdef debugAdjust
1325       G4cout << "SqrtS < SumMasses + PResidualExcitationEnergy + TResidualExcitationEnergy "
1326              << common.SqrtS << " " << common.SumMasses + common.PResidualExcitationEnergy + common.TResidualExcitationEnergy
1327              << G4endl;
1328       #endif
1329       if ( common.SqrtS <   common.SumMasses + common.PResidualExcitationEnergy
1330                           + common.TResidualExcitationEnergy ) { 
1331         Stopping = true;
1332         if ( common.PResidualExcitationEnergy <= 0.0 ) {
1333           common.TResidualExcitationEnergy = common.SqrtS - common.SumMasses;
1334         } else if ( common.TResidualExcitationEnergy <= 0.0 ) {
1335           common.PResidualExcitationEnergy = common.SqrtS - common.SumMasses;
1336         } else {
1337           G4double Fraction = ( common.SqrtS - common.SumMasses )
1338             /  ( common.PResidualExcitationEnergy + common.TResidualExcitationEnergy );
1339           common.PResidualExcitationEnergy *= Fraction;
1340           common.TResidualExcitationEnergy *= Fraction;
1341         }
1342       }
1343     }
1344   }  // End-if on ! Annihilation
1345 
1346   if ( Annihilation ) {
1347     #ifdef debugAdjust
1348     G4cout << "SqrtS < SumMasses - TNucleonMass " << common.SqrtS << " " 
1349            << common.SumMasses - common.TNucleonMass << G4endl;
1350     #endif
1351     if ( common.SqrtS < common.SumMasses - common.TNucleonMass ) {
1352       return returnCode;  // unsuccessfully ended, nothing else can be done
1353     } 
1354     #ifdef debugAdjust
1355     G4cout << "SqrtS < SumMasses " << common.SqrtS << " " << common.SumMasses << G4endl;
1356     #endif
1357     if ( common.SqrtS < common.SumMasses ) {
1358       if ( interactionCase == 2  ||  interactionCase == 3 ) {
1359         common.TResidualExcitationEnergy = 0.0;
1360       }  
1361       common.TNucleonMass =   common.SqrtS - ( common.SumMasses - common.TNucleonMass )
1362                             - common.TResidualExcitationEnergy;  // Off-shell nucleon mass 
1363       #ifdef debugAdjust
1364       G4cout << "TNucleonMass " << common.TNucleonMass << G4endl;
1365       #endif
1366       common.SumMasses = common.SqrtS - common.TResidualExcitationEnergy;
1367       Stopping = true;
1368       #ifdef debugAdjust
1369       G4cout << "SqrtS < SumMasses " << common.SqrtS << " " << common.SumMasses << G4endl;
1370       #endif
1371     }
1372     if ( interactionCase == 1  ||  interactionCase == 2 ) {
1373       if ( common.SqrtS < common.SumMasses + common.TResidualExcitationEnergy ) {
1374         common.TResidualExcitationEnergy = common.SqrtS - common.SumMasses; 
1375         Stopping = true;
1376       }
1377     } else if ( interactionCase == 3 ) {
1378       if ( common.SqrtS <   common.SumMasses + common.PResidualExcitationEnergy
1379                           + common.TResidualExcitationEnergy ) {
1380         Stopping = true;
1381         if ( common.PResidualExcitationEnergy <= 0.0 ) {
1382           common.TResidualExcitationEnergy = common.SqrtS - common.SumMasses;
1383         } else if ( common.TResidualExcitationEnergy <= 0.0 ) {
1384           common.PResidualExcitationEnergy = common.SqrtS - common.SumMasses;
1385         } else {
1386           G4double Fraction = ( common.SqrtS - common.SumMasses ) / 
1387             ( common.PResidualExcitationEnergy + common.TResidualExcitationEnergy );
1388           common.PResidualExcitationEnergy *= Fraction;
1389           common.TResidualExcitationEnergy *= Fraction;
1390         }
1391       }
1392     }
1393   }  // End-if on Annihilation
1394 
1395   #ifdef debugAdjust
1396   G4cout << "Stopping " << Stopping << G4endl;
1397   #endif
1398 
1399   if ( Stopping ) {
1400     // All 3-momenta of particles = 0
1401     common.Ptmp.setPx( 0.0 ); common.Ptmp.setPy( 0.0 ); common.Ptmp.setPz( 0.0 );
1402     // New projectile
1403     if ( interactionCase == 1 ) {
1404       common.Ptmp.setE( SelectedAntiBaryon->Get4Momentum().mag() );
1405     } else if ( interactionCase == 2 ) {
1406       common.Ptmp.setE( common.TNucleonMass );
1407     } else if ( interactionCase == 3 ) {
1408       common.Ptmp.setE( common.PNucleonMass );
1409     }
1410     #ifdef debugAdjust
1411     G4cout << "Proj stop " << common.Ptmp << G4endl;
1412     #endif
1413     common.Pprojectile = common.Ptmp; 
1414     common.Pprojectile.transform( common.toLab );  // From center-of-mass to Lab frame
1415     //---AR-Jul2019 : To avoid unphysical projectile (anti-)fragments at rest, save the
1416     //                original momentum of the anti-baryon in the center-of-mass frame.
1417     G4LorentzVector saveSelectedAntiBaryon4Momentum = SelectedAntiBaryon->Get4Momentum();
1418     saveSelectedAntiBaryon4Momentum.transform( common.toCms );  // From Lab to center-of-mass frame
1419     //---
1420     SelectedAntiBaryon->Set4Momentum( common.Pprojectile );
1421     // New target nucleon
1422     if ( interactionCase == 1  ||  interactionCase == 3 ) {
1423       common.Ptmp.setE( common.TNucleonMass );
1424     } else if ( interactionCase == 2 ) {
1425       common.Ptmp.setE( SelectedTargetNucleon->Get4Momentum().mag() );
1426     }
1427     #ifdef debugAdjust
1428     G4cout << "Targ stop " << common.Ptmp << G4endl;
1429     #endif
1430     common.Ptarget = common.Ptmp; 
1431     common.Ptarget.transform( common.toLab );  // From center-of-mass to Lab frame
1432     //---AR-Jul2019 : To avoid unphysical target fragments at rest, save the original
1433     //                momentum of the target nucleon in the center-of-mass frame.
1434     G4LorentzVector saveSelectedTargetNucleon4Momentum = SelectedTargetNucleon->Get4Momentum();
1435     saveSelectedTargetNucleon4Momentum.transform( common.toCms );  // From Lab to center-of-mass frame
1436     //---
1437     SelectedTargetNucleon->Set4Momentum( common.Ptarget );
1438     // New target residual
1439     if ( interactionCase == 1  ||  interactionCase == 3 ) {
1440       common.Ptmp.setPx( 0.0 ); common.Ptmp.setPy( 0.0 ); common.Ptmp.setPz( 0.0 );
1441       TargetResidualMassNumber       = common.TResidualMassNumber;
1442       TargetResidualCharge           = common.TResidualCharge;
1443       TargetResidualExcitationEnergy = common.TResidualExcitationEnergy;
1444       //---AR-Jul2019 : To avoid unphysical target fragments at rest, use the saved
1445       //                original momentum of the target nucleon (instead of setting 0).
1446       //                This is a rough and simple approach!
1447       //common.Ptmp.setE( common.TResidualMass + TargetResidualExcitationEnergy );
1448       common.Ptmp.setPx( -saveSelectedTargetNucleon4Momentum.x() ); 
1449       common.Ptmp.setPy( -saveSelectedTargetNucleon4Momentum.y() ); 
1450       common.Ptmp.setPz( -saveSelectedTargetNucleon4Momentum.z() );
1451       common.Ptmp.setE( std::sqrt( sqr( common.TResidualMass + TargetResidualExcitationEnergy ) + common.Ptmp.vect().mag2() ) ); 
1452       //---
1453       #ifdef debugAdjust
1454       G4cout << "Targ Resi stop " << common.Ptmp << G4endl;
1455       #endif
1456       common.Ptmp.transform( common.toLab );  // From center-of-mass to Lab frame
1457       TargetResidual4Momentum = common.Ptmp;
1458     }
1459     // New projectile residual
1460     if ( interactionCase == 2  ||  interactionCase == 3 ) {
1461       common.Ptmp.setPx( 0.0 ); common.Ptmp.setPy( 0.0 ); common.Ptmp.setPz( 0.0 );
1462       if ( interactionCase == 2 ) {
1463         ProjectileResidualMassNumber       = common.TResidualMassNumber;
1464         ProjectileResidualCharge           = common.TResidualCharge;
1465   ProjectileResidualLambdaNumber     = 0;  // The target nucleus and its residual are never hypernuclei
1466         ProjectileResidualExcitationEnergy = common.TResidualExcitationEnergy;
1467         common.Ptmp.setE( common.TResidualMass + ProjectileResidualExcitationEnergy ); 
1468       } else {
1469         ProjectileResidualMassNumber       = common.PResidualMassNumber;
1470         ProjectileResidualCharge           = common.PResidualCharge;
1471   ProjectileResidualLambdaNumber     = common.PResidualLambdaNumber;
1472         ProjectileResidualExcitationEnergy = common.PResidualExcitationEnergy;
1473         //---AR-Jul2019 : To avoid unphysical projectile (anti-)fragments at rest, use the
1474         //                saved original momentum of the anti-baryon (instead of setting 0).
1475         //                This is a rough and simple approach!
1476         //common.Ptmp.setE( common.PResidualMass + ProjectileResidualExcitationEnergy );
1477         common.Ptmp.setPx( -saveSelectedAntiBaryon4Momentum.x() ); 
1478         common.Ptmp.setPy( -saveSelectedAntiBaryon4Momentum.y() ); 
1479         common.Ptmp.setPz( -saveSelectedAntiBaryon4Momentum.z() );
1480         common.Ptmp.setE( std::sqrt( sqr( common.PResidualMass + ProjectileResidualExcitationEnergy ) + common.Ptmp.vect().mag2() ) ); 
1481         //---
1482       }
1483       #ifdef debugAdjust
1484       G4cout << "Proj Resi stop " << common.Ptmp << G4endl;
1485       #endif
1486       common.Ptmp.transform( common.toLab );  // From center-of-mass to Lab frame
1487       ProjectileResidual4Momentum = common.Ptmp;
1488     }
1489     return returnCode = 0;  // successfully ended and nothing else needs to be done (i.e. no sampling)
1490   }  // End-if on Stopping
1491 
1492   // Initializations before sampling
1493   if ( interactionCase == 1 ) {
1494     common.Mprojectile  = common.Pprojectile.mag();
1495     common.M2projectile = common.Pprojectile.mag2();
1496     common.TResidual4Momentum = common.toCms * TargetResidual4Momentum;
1497     common.YtargetNucleus = common.TResidual4Momentum.rapidity();
1498     common.TResidualMass += common.TResidualExcitationEnergy;
1499   } else if ( interactionCase == 2 ) {
1500     common.Mtarget  = common.Ptarget.mag();
1501     common.M2target = common.Ptarget.mag2();
1502     common.TResidual4Momentum = common.toCms * ProjectileResidual4Momentum;
1503     common.YprojectileNucleus = common.TResidual4Momentum.rapidity();
1504     common.TResidualMass += common.TResidualExcitationEnergy;
1505   } else if ( interactionCase == 3 ) {
1506     common.PResidual4Momentum = common.toCms * ProjectileResidual4Momentum;
1507     common.YprojectileNucleus = common.PResidual4Momentum.rapidity();
1508     common.TResidual4Momentum = common.toCms*TargetResidual4Momentum;
1509     common.YtargetNucleus = common.TResidual4Momentum.rapidity();
1510     common.PResidualMass += common.PResidualExcitationEnergy;
1511     common.TResidualMass += common.TResidualExcitationEnergy;
1512   }
1513   #ifdef debugAdjust
1514   G4cout << "YprojectileNucleus " << common.YprojectileNucleus << G4endl;
1515   #endif
1516 
1517   return returnCode = 1;  // successfully completed, but the work needs to be continued, i.e. try to sample
1518 }
1519 
1520 
1521 //-------------------------------------------------------------------
1522 
1523 G4bool G4FTFModel::AdjustNucleonsAlgorithm_Sampling( G4int interactionCase,
1524                                                      G4FTFModel::CommonVariables& common ) {
1525   // Second of the three utility methods used only by AdjustNucleons: do the sampling.
1526   // This method returns "false" if it fails to sample properly, else it returns "true".
1527 
1528   // Ascribing of the involved nucleons Pt and X 
1529   G4double Dcor = theParameters->GetDofNuclearDestruction();
1530   G4double DcorP = 0.0, DcorT = 0.0;
1531   if ( ProjectileResidualMassNumber != 0 ) DcorP = Dcor / G4double(ProjectileResidualMassNumber);
1532   if ( TargetResidualMassNumber != 0 )     DcorT = Dcor / G4double(TargetResidualMassNumber);
1533   G4double AveragePt2 = theParameters->GetPt2ofNuclearDestruction();
1534   G4double maxPtSquare = theParameters->GetMaxPt2ofNuclearDestruction();
1535 
1536   G4double ScaleFactor = 1.0;
1537   G4bool OuterSuccess = true;
1538   const G4int maxNumberOfLoops = 1000;
1539   const G4int maxNumberOfTries = 10000;
1540   G4int loopCounter = 0;
1541   G4int NumberOfTries = 0;
1542   do {  // Outmost do while loop
1543     OuterSuccess = true;
1544     G4bool loopCondition = false;
1545     do {  // Intermediate do while loop
1546       if ( NumberOfTries == 100*(NumberOfTries/100) ) { 
1547         // At large number of tries it would be better to reduce the values
1548         ScaleFactor /= 2.0;
1549         DcorP      *= ScaleFactor;
1550         DcorT      *= ScaleFactor;
1551         AveragePt2 *= ScaleFactor;
1552         #ifdef debugAdjust
1553         //G4cout << "NumberOfTries ScaleFactor " << NumberOfTries << " " << ScaleFactor << G4endl;
1554         #endif
1555       }
1556 
1557       // Some kinematics
1558       if ( interactionCase == 1 ) {
1559       } else if ( interactionCase == 2 ) {
1560         #ifdef debugAdjust
1561         G4cout << "ProjectileResidualMassNumber " << ProjectileResidualMassNumber << G4endl;
1562         #endif
1563         if ( ProjectileResidualMassNumber > 1 ) {
1564           common.PtNucleon = GaussianPt( AveragePt2, maxPtSquare );
1565         } else {
1566           common.PtNucleon = G4ThreeVector( 0.0, 0.0, 0.0 );
1567         }
1568         common.PtResidual = - common.PtNucleon;
1569         common.Mprojectile =   std::sqrt( sqr( common.TNucleonMass ) + common.PtNucleon.mag2() )
1570                              + std::sqrt( sqr( common.TResidualMass ) + common.PtResidual.mag2() );
1571         #ifdef debugAdjust
1572         G4cout << "SqrtS < Mtarget + Mprojectile " << common.SqrtS << "  " << common.Mtarget
1573                << " " << common.Mprojectile << " "  << common.Mtarget + common.Mprojectile << G4endl;
1574         #endif
1575         common.M2projectile = sqr( common.Mprojectile );
1576         if ( common.SqrtS < common.Mtarget + common.Mprojectile ) {
1577           OuterSuccess = false; 
1578           loopCondition = true;
1579           continue;
1580         }
1581       } else if ( interactionCase == 3 ) {
1582         if ( ProjectileResidualMassNumber > 1 ) {            
1583           common.PtNucleonP = GaussianPt( AveragePt2, maxPtSquare );
1584         } else {
1585           common.PtNucleonP = G4ThreeVector( 0.0, 0.0, 0.0 );
1586         }
1587         common.PtResidualP = - common.PtNucleonP;
1588         if ( TargetResidualMassNumber > 1 ) { 
1589           common.PtNucleonT = GaussianPt( AveragePt2, maxPtSquare );
1590         } else {
1591           common.PtNucleonT = G4ThreeVector( 0.0, 0.0, 0.0 );
1592         }
1593         common.PtResidualT = - common.PtNucleonT;
1594         common.Mprojectile =   std::sqrt( sqr( common.PNucleonMass )  + common.PtNucleonP.mag2() ) 
1595                              + std::sqrt( sqr( common.PResidualMass ) + common.PtResidualP.mag2() );
1596         common.M2projectile = sqr( common.Mprojectile );
1597         common.Mtarget =   std::sqrt( sqr( common.TNucleonMass )  + common.PtNucleonT.mag2() )
1598                          + std::sqrt( sqr( common.TResidualMass ) + common.PtResidualT.mag2() );
1599         common.M2target = sqr( common.Mtarget );
1600         if ( common.SqrtS < common.Mprojectile + common.Mtarget ) {
1601           OuterSuccess = false; 
1602           loopCondition = true;
1603           continue;
1604         }
1605       }  // End-if on interactionCase
1606 
1607       G4int numberOfTimesExecuteInnerLoop = 1;
1608       if ( interactionCase == 3 ) numberOfTimesExecuteInnerLoop = 2;
1609       for ( G4int iExecute = 0; iExecute < numberOfTimesExecuteInnerLoop; iExecute++ ) {
1610 
1611         G4bool InnerSuccess = true;
1612         G4bool isTargetToBeHandled = ( interactionCase == 1 || 
1613                                        ( interactionCase == 3 && iExecute == 1 ) );
1614         G4bool condition = false;
1615         if ( isTargetToBeHandled ) {
1616           condition = ( TargetResidualMassNumber > 1 );
1617   } else {  // Projectile to be handled
1618           condition = ( ProjectileResidualMassNumber > 1 );
1619         }
1620         if ( condition ) { 
1621           const G4int maxNumberOfInnerLoops = 1000;
1622           G4int innerLoopCounter = 0;
1623           do {  // Inner do while loop
1624             InnerSuccess = true;
1625             if ( isTargetToBeHandled ) {
1626               G4double Xcenter = 0.0;
1627               if ( interactionCase == 1 ) {
1628                 common.PtNucleon = GaussianPt( AveragePt2, maxPtSquare );
1629                 common.PtResidual = - common.PtNucleon;
1630                 common.Mtarget =   std::sqrt( sqr( common.TNucleonMass )  + common.PtNucleon.mag2() ) 
1631                                  + std::sqrt( sqr( common.TResidualMass ) + common.PtResidual.mag2() );
1632                 if ( common.SqrtS < common.Mprojectile + common.Mtarget ) {
1633                   InnerSuccess = false; 
1634                   continue;
1635                 }
1636                 Xcenter = std::sqrt( sqr( common.TNucleonMass ) + common.PtNucleon.mag2() ) 
1637                           / common.Mtarget;
1638               } else {
1639                 Xcenter = std::sqrt( sqr( common.TNucleonMass ) + common.PtNucleonT.mag2() ) 
1640                           / common.Mtarget;
1641               }
1642               G4ThreeVector tmpX = GaussianPt( DcorT*DcorT, 1.0 );
1643               common.XminusNucleon = Xcenter + tmpX.x();
1644               if ( common.XminusNucleon <= 0.0  ||  common.XminusNucleon >= 1.0 ) {
1645                 InnerSuccess = false; 
1646                 continue;
1647               }
1648               common.XminusResidual = 1.0 - common.XminusNucleon;
1649             } else {  // Projectile to be handled
1650               G4ThreeVector tmpX = GaussianPt( DcorP*DcorP, 1.0 );
1651               G4double Xcenter = 0.0;
1652               if ( interactionCase == 2 ) {
1653                 Xcenter = std::sqrt( sqr( common.TNucleonMass ) + common.PtNucleon.mag2() ) 
1654                           / common.Mprojectile;
1655               } else {
1656                 Xcenter = std::sqrt( sqr( common.PNucleonMass ) + common.PtNucleonP.mag2() ) 
1657                           / common.Mprojectile;
1658               }
1659               common.XplusNucleon = Xcenter + tmpX.x();
1660               if ( common.XplusNucleon <= 0.0  ||  common.XplusNucleon >= 1.0 ) {
1661                 InnerSuccess = false; 
1662                 continue;
1663               }
1664               common.XplusResidual = 1.0 - common.XplusNucleon;
1665             }  // End-if on isTargetToBeHandled
1666           } while ( ( ! InnerSuccess ) &&                            // Inner do while loop
1667                       ++innerLoopCounter < maxNumberOfInnerLoops );  /* Loop checking, 10.08.2015, A.Ribon */ 
1668           if ( innerLoopCounter >= maxNumberOfInnerLoops ) {
1669             #ifdef debugAdjust
1670             G4cout << "BAD situation: forced exit of the inner while loop!" << G4endl;
1671             #endif
1672             return false;
1673           }
1674         } else {  // condition is false
1675           if ( isTargetToBeHandled ) {
1676             common.XminusNucleon  = 1.0;
1677             common.XminusResidual = 1.0;  // It must be 0, but in the calculation of Pz, E is problematic
1678           } else {  // Projectile to be handled
1679             common.XplusNucleon  = 1.0;
1680             common.XplusResidual = 1.0;   // It must be 0, but in the calculation of Pz, E is problematic
1681           } 
1682         }  // End-if on condition
1683 
1684       }  // End of for loop on iExecute
1685 
1686       if ( interactionCase == 1 ) {
1687         common.M2target =    ( sqr( common.TNucleonMass )  + common.PtNucleon.mag2() ) 
1688                              / common.XminusNucleon 
1689                           +  ( sqr( common.TResidualMass ) + common.PtResidual.mag2() ) 
1690                              / common.XminusResidual;
1691         loopCondition = ( common.SqrtS < common.Mprojectile + std::sqrt( common.M2target ) );
1692       } else if ( interactionCase == 2 ) {
1693         #ifdef debugAdjust
1694         G4cout << "TNucleonMass PtNucleon XplusNucleon " << common.TNucleonMass << " " 
1695                << common.PtNucleon << " " << common.XplusNucleon << G4endl
1696                << "TResidualMass PtResidual XplusResidual " << common.TResidualMass << " " 
1697                << common.PtResidual << "  " << common.XplusResidual << G4endl;
1698         #endif
1699         common.M2projectile =    ( sqr( common.TNucleonMass )  + common.PtNucleon.mag2() ) 
1700                                  / common.XplusNucleon 
1701                               +  ( sqr( common.TResidualMass ) + common.PtResidual.mag2() ) 
1702                                  / common.XplusResidual;
1703         #ifdef debugAdjust
1704         G4cout << "SqrtS < Mtarget + std::sqrt(M2projectile) " << common.SqrtS << "  " 
1705                << common.Mtarget << " " << std::sqrt( common.M2projectile ) << " "
1706                << common.Mtarget + std::sqrt( common.M2projectile ) << G4endl;
1707         #endif
1708         loopCondition = ( common.SqrtS < common.Mtarget + std::sqrt( common.M2projectile ) );
1709       } else if ( interactionCase == 3 ) {
1710         #ifdef debugAdjust
1711         G4cout << "PtNucleonP " << common.PtNucleonP << " " << common.PtResidualP << G4endl
1712                << "XplusNucleon XplusResidual " << common.XplusNucleon 
1713                << " " << common.XplusResidual << G4endl
1714                << "PtNucleonT " << common.PtNucleonT << " " << common.PtResidualT << G4endl
1715                << "XminusNucleon XminusResidual " << common.XminusNucleon 
1716                << " " << common.XminusResidual << G4endl;
1717         #endif
1718         common.M2projectile =   ( sqr( common.PNucleonMass ) + common.PtNucleonP.mag2() ) 
1719                                 / common.XplusNucleon 
1720                               + ( sqr( common.PResidualMass) + common.PtResidualP.mag2() ) 
1721                                 / common.XplusResidual;
1722         common.M2target =    ( sqr( common.TNucleonMass )  + common.PtNucleonT.mag2() ) 
1723                              / common.XminusNucleon 
1724                           +  ( sqr( common.TResidualMass ) + common.PtResidualT.mag2() ) 
1725                              / common.XminusResidual;
1726         loopCondition = ( common.SqrtS < (   std::sqrt( common.M2projectile ) 
1727              + std::sqrt( common.M2target ) ) );
1728       }  // End-if on interactionCase
1729 
1730     } while ( loopCondition &&                       // Intermediate do while loop
1731               ++NumberOfTries < maxNumberOfTries );  /* Loop checking, 10.08.2015, A.Ribon */
1732     if ( NumberOfTries >= maxNumberOfTries ) { 
1733       #ifdef debugAdjust
1734       G4cout << "BAD situation: forced exit of the intermediate while loop!" << G4endl;
1735       #endif
1736       return false;
1737     }
1738 
1739     // kinematics
1740     G4double Yprojectile = 0.0, YprojectileNucleon = 0.0, Ytarget = 0.0, YtargetNucleon = 0.0;
1741     G4double DecayMomentum2 = sqr( common.S ) + sqr( common.M2projectile ) + sqr( common.M2target )
1742                               - 2.0 * ( common.S * ( common.M2projectile + common.M2target )
1743                                         + common.M2projectile * common.M2target );
1744     if ( interactionCase == 1 ) {
1745       common.WminusTarget = (   common.S - common.M2projectile + common.M2target 
1746                               + std::sqrt( DecayMomentum2 ) ) / 2.0 / common.SqrtS;
1747       common.WplusProjectile = common.SqrtS - common.M2target / common.WminusTarget;
1748       common.Pzprojectile =   common.WplusProjectile / 2.0 
1749                             - common.M2projectile / 2.0 / common.WplusProjectile;
1750       common.Eprojectile =    common.WplusProjectile / 2.0 
1751                             + common.M2projectile / 2.0 / common.WplusProjectile;
1752       Yprojectile  = 0.5 * G4Log(   ( common.Eprojectile + common.Pzprojectile )
1753                                   / ( common.Eprojectile - common.Pzprojectile ) );
1754       #ifdef debugAdjust
1755       G4cout << "DecayMomentum2 " << DecayMomentum2 << G4endl
1756              << "WminusTarget WplusProjectile " << common.WminusTarget 
1757              << " " << common.WplusProjectile << G4endl 
1758              << "Yprojectile " << Yprojectile << G4endl;
1759       #endif
1760       common.Mt2targetNucleon = sqr( common.TNucleonMass ) + common.PtNucleon.mag2();
1761       common.PztargetNucleon = - common.WminusTarget * common.XminusNucleon / 2.0
1762                                + common.Mt2targetNucleon 
1763                                  / ( 2.0 * common.WminusTarget * common.XminusNucleon );
1764       common.EtargetNucleon =   common.WminusTarget * common.XminusNucleon / 2.0
1765                               + common.Mt2targetNucleon
1766                                 / ( 2.0 * common.WminusTarget * common.XminusNucleon );
1767       YtargetNucleon = 0.5 * G4Log(   ( common.EtargetNucleon + common.PztargetNucleon )
1768                                     / ( common.EtargetNucleon - common.PztargetNucleon ) );
1769       #ifdef debugAdjust
1770       G4cout << "YtN Ytr YtN-Ytr " << " " << YtargetNucleon << " " << common.YtargetNucleus 
1771              << " " << YtargetNucleon - common.YtargetNucleus << G4endl
1772              << "YtN Ypr YtN-Ypr " << " " << YtargetNucleon << " " << Yprojectile
1773              << " " << YtargetNucleon - Yprojectile << G4endl;
1774       #endif
1775       if ( std::abs( YtargetNucleon - common.YtargetNucleus ) > 2  ||
1776            Yprojectile < YtargetNucleon ) {
1777         OuterSuccess = false; 
1778         continue;
1779       }
1780     } else if ( interactionCase == 2 ) {
1781       common.WplusProjectile = (   common.S + common.M2projectile - common.M2target 
1782                                  + std::sqrt( DecayMomentum2 ) ) / 2.0 / common.SqrtS;
1783       common.WminusTarget = common.SqrtS - common.M2projectile / common.WplusProjectile;
1784       common.Pztarget = - common.WminusTarget / 2.0 + common.M2target / 2.0 / common.WminusTarget;
1785       common.Etarget =    common.WminusTarget / 2.0 + common.M2target / 2.0 / common.WminusTarget;
1786       Ytarget = 0.5 * G4Log(   ( common.Etarget + common.Pztarget )
1787                              / ( common.Etarget - common.Pztarget ) );
1788       #ifdef debugAdjust
1789       G4cout << "DecayMomentum2 " << DecayMomentum2 << G4endl
1790              << "WminusTarget WplusProjectile " << common.WminusTarget 
1791              << " " << common.WplusProjectile << G4endl 
1792              << "Ytarget " << Ytarget << G4endl;
1793       #endif
1794       common.Mt2projectileNucleon = sqr( common.TNucleonMass ) + common.PtNucleon.mag2();
1795       common.PzprojectileNucleon =   common.WplusProjectile * common.XplusNucleon / 2.0
1796                                    - common.Mt2projectileNucleon
1797                                      / ( 2.0 * common.WplusProjectile * common.XplusNucleon );
1798       common.EprojectileNucleon =    common.WplusProjectile * common.XplusNucleon / 2.0 
1799                                    + common.Mt2projectileNucleon
1800                                      / ( 2.0 * common.WplusProjectile * common.XplusNucleon );
1801       YprojectileNucleon = 0.5 * G4Log(   ( common.EprojectileNucleon + common.PzprojectileNucleon )
1802                                         / ( common.EprojectileNucleon - common.PzprojectileNucleon) );
1803       #ifdef debugAdjust
1804       G4cout << "YpN Ypr YpN-Ypr " << " " << YprojectileNucleon << " " << common.YprojectileNucleus
1805              << " " << YprojectileNucleon - common.YprojectileNucleus << G4endl
1806              << "YpN Ytr YpN-Ytr " << " " << YprojectileNucleon << " " << Ytarget
1807              << " " << YprojectileNucleon - Ytarget << G4endl;
1808       #endif
1809       if ( std::abs( YprojectileNucleon - common.YprojectileNucleus ) > 2  ||
1810            Ytarget > YprojectileNucleon ) {
1811         OuterSuccess = false; 
1812         continue;
1813       }
1814     } else if ( interactionCase == 3 ) {
1815       common.WplusProjectile = (   common.S + common.M2projectile - common.M2target 
1816                                  + std::sqrt( DecayMomentum2 ) ) / 2.0 / common.SqrtS;
1817       common.WminusTarget = common.SqrtS - common.M2projectile / common.WplusProjectile;
1818       common.Mt2projectileNucleon = sqr( common.PNucleonMass ) + common.PtNucleonP.mag2();
1819       common.PzprojectileNucleon =   common.WplusProjectile * common.XplusNucleon / 2.0
1820                                    - common.Mt2projectileNucleon
1821                                      / ( 2.0 * common.WplusProjectile * common.XplusNucleon );
1822       common.EprojectileNucleon =    common.WplusProjectile * common.XplusNucleon / 2.0
1823                                    + common.Mt2projectileNucleon
1824                                      / ( 2.0 * common.WplusProjectile * common.XplusNucleon );
1825       YprojectileNucleon = 0.5 * G4Log(   ( common.EprojectileNucleon + common.PzprojectileNucleon )
1826                                         / ( common.EprojectileNucleon - common.PzprojectileNucleon ) );
1827       common.Mt2targetNucleon = sqr( common.TNucleonMass ) + common.PtNucleonT.mag2();
1828       common.PztargetNucleon = - common.WminusTarget * common.XminusNucleon / 2.0
1829                                + common.Mt2targetNucleon
1830                                  / ( 2.0 * common.WminusTarget * common.XminusNucleon );
1831       common.EtargetNucleon =    common.WminusTarget * common.XminusNucleon / 2.0
1832                                + common.Mt2targetNucleon
1833                                  / ( 2.0 * common.WminusTarget * common.XminusNucleon );
1834       YtargetNucleon = 0.5 * G4Log(   ( common.EtargetNucleon + common.PztargetNucleon )
1835                                     / ( common.EtargetNucleon - common.PztargetNucleon ) ); 
1836       if ( std::abs( YtargetNucleon - common.YtargetNucleus ) > 2          ||
1837            std::abs( YprojectileNucleon - common.YprojectileNucleus ) > 2  ||
1838            YprojectileNucleon < YtargetNucleon ) {
1839         OuterSuccess = false;
1840         continue;
1841       }
1842     }  // End-if on interactionCase
1843 
1844   } while ( ( ! OuterSuccess ) &&                // Outmost do while loop
1845             ++loopCounter < maxNumberOfLoops );  /* Loop checking, 10.08.2015, A.Ribon */
1846   if ( loopCounter >= maxNumberOfLoops ) {
1847     #ifdef debugAdjust
1848     G4cout << "BAD situation: forced exit of the while loop!" << G4endl;
1849     #endif
1850     return false;
1851   }
1852 
1853   return true;
1854 }
1855 
1856 //-------------------------------------------------------------------
1857 
1858 void G4FTFModel::AdjustNucleonsAlgorithm_afterSampling( G4int interactionCase,
1859                                                         G4VSplitableHadron* SelectedAntiBaryon,
1860                                                         G4VSplitableHadron* SelectedTargetNucleon,
1861                                                         G4FTFModel::CommonVariables& common ) {
1862   // Third of the three utility methods used only by AdjustNucleons: do the final kinematics
1863   // and transform back.
1864 
1865   // New projectile
1866   if ( interactionCase == 1 ) {
1867     common.Pprojectile.setPz( common.Pzprojectile );  
1868     common.Pprojectile.setE( common.Eprojectile );
1869   } else if ( interactionCase == 2 ) {
1870     common.Pprojectile.setPx( common.PtNucleon.x() ); 
1871     common.Pprojectile.setPy( common.PtNucleon.y() );
1872     common.Pprojectile.setPz( common.PzprojectileNucleon );
1873     common.Pprojectile.setE( common.EprojectileNucleon ); 
1874   } else if ( interactionCase == 3 ) {
1875     common.Pprojectile.setPx( common.PtNucleonP.x() );
1876     common.Pprojectile.setPy( common.PtNucleonP.y() );
1877     common.Pprojectile.setPz( common.PzprojectileNucleon );
1878     common.Pprojectile.setE( common.EprojectileNucleon );
1879   }
1880   #ifdef debugAdjust
1881   G4cout << "Proj after in CMS " << common.Pprojectile << G4endl;
1882   #endif
1883   common.Pprojectile.transform( common.toLab );
1884   SelectedAntiBaryon->Set4Momentum( common.Pprojectile );
1885   #ifdef debugAdjust
1886   G4cout << "Proj after in Lab " << common.Pprojectile << G4endl;
1887   #endif
1888 
1889   // New target nucleon
1890   if ( interactionCase == 1 ) {
1891     common.Ptarget.setPx( common.PtNucleon.x() );
1892     common.Ptarget.setPy( common.PtNucleon.y() );
1893     common.Ptarget.setPz( common.PztargetNucleon );
1894     common.Ptarget.setE( common.EtargetNucleon ); 
1895   } else if ( interactionCase == 2 ) {
1896     common.Ptarget.setPz( common.Pztarget ); 
1897     common.Ptarget.setE( common.Etarget );
1898   } else if ( interactionCase == 3 ) {
1899     common.Ptarget.setPx( common.PtNucleonT.x() );
1900     common.Ptarget.setPy( common.PtNucleonT.y() );
1901     common.Ptarget.setPz( common.PztargetNucleon );
1902     common.Ptarget.setE( common.EtargetNucleon );
1903   }
1904   #ifdef debugAdjust
1905   G4cout << "Targ after in CMS " << common.Ptarget << G4endl;
1906   #endif
1907   common.Ptarget.transform( common.toLab );
1908   SelectedTargetNucleon->Set4Momentum( common.Ptarget );
1909   #ifdef debugAdjust
1910   G4cout << "Targ after in Lab " << common.Ptarget << G4endl;
1911   #endif
1912 
1913   // New target residual
1914   if ( interactionCase == 1  ||  interactionCase == 3 ) {
1915     TargetResidualMassNumber       = common.TResidualMassNumber;
1916     TargetResidualCharge           = common.TResidualCharge;
1917     TargetResidualExcitationEnergy = common.TResidualExcitationEnergy;
1918     #ifdef debugAdjust
1919     G4cout << "TargetResidualMassNumber TargetResidualCharge TargetResidualExcitationEnergy "
1920            << TargetResidualMassNumber << " " << TargetResidualCharge << " "
1921            << TargetResidualExcitationEnergy << G4endl;
1922     #endif
1923     if ( TargetResidualMassNumber != 0 ) {
1924       G4double Mt2 = 0.0;
1925       if ( interactionCase == 1 ) {
1926         Mt2 = sqr( common.TResidualMass ) + common.PtResidual.mag2();
1927         TargetResidual4Momentum.setPx( common.PtResidual.x() );
1928         TargetResidual4Momentum.setPy( common.PtResidual.y() );
1929       } else {  // interactionCase == 3
1930         Mt2 = sqr( common.TResidualMass ) + common.PtResidualT.mag2();
1931         TargetResidual4Momentum.setPx( common.PtResidualT.x() );
1932         TargetResidual4Momentum.setPy( common.PtResidualT.y() );
1933       }
1934       G4double Pz = - common.WminusTarget * common.XminusResidual / 2.0
1935                     + Mt2 / ( 2.0 * common.WminusTarget * common.XminusResidual );
1936       G4double E =    common.WminusTarget * common.XminusResidual / 2.0 
1937                     + Mt2 / ( 2.0 * common.WminusTarget * common.XminusResidual );
1938       TargetResidual4Momentum.setPz( Pz );
1939       TargetResidual4Momentum.setE( E ) ;
1940       TargetResidual4Momentum.transform( common.toLab );
1941     } else {
1942       TargetResidual4Momentum = G4LorentzVector( 0.0, 0.0, 0.0, 0.0 );
1943     }
1944     #ifdef debugAdjust
1945     G4cout << "Tr N R " << common.Ptarget << G4endl << "       " << TargetResidual4Momentum << G4endl;
1946     #endif
1947   }
1948 
1949   // New projectile residual
1950   if ( interactionCase == 2  ||  interactionCase == 3 ) {
1951     if ( interactionCase == 2 ) {
1952       ProjectileResidualMassNumber       = common.TResidualMassNumber;
1953       ProjectileResidualCharge           = common.TResidualCharge;
1954       ProjectileResidualExcitationEnergy = common.TResidualExcitationEnergy;
1955       ProjectileResidualLambdaNumber     = common.PResidualLambdaNumber;
1956     } else {  // interactionCase == 3
1957       ProjectileResidualMassNumber       = common.PResidualMassNumber;
1958       ProjectileResidualCharge           = common.PResidualCharge;
1959       ProjectileResidualExcitationEnergy = common.PResidualExcitationEnergy;
1960       ProjectileResidualLambdaNumber     = common.PResidualLambdaNumber;
1961     }
1962     #ifdef debugAdjust
1963     G4cout << "ProjectileResidualMassNumber ProjectileResidualCharge  Lambdas ProjectileResidualExcitationEnergy "
1964            << ProjectileResidualMassNumber << " " << ProjectileResidualCharge << " "
1965            << ProjectileResidualLambdaNumber << " "
1966            << ProjectileResidualExcitationEnergy << G4endl;
1967     #endif
1968     if ( ProjectileResidualMassNumber != 0 ) {
1969       G4double Mt2 = 0.0;
1970       if ( interactionCase == 2 ) {
1971         Mt2 = sqr( common.TResidualMass ) + common.PtResidual.mag2();
1972         ProjectileResidual4Momentum.setPx( common.PtResidual.x() );
1973         ProjectileResidual4Momentum.setPy( common.PtResidual.y() );
1974       } else {  // interactionCase == 3
1975         Mt2 = sqr( common.PResidualMass ) + common.PtResidualP.mag2();
1976         ProjectileResidual4Momentum.setPx( common.PtResidualP.x() );
1977         ProjectileResidual4Momentum.setPy( common.PtResidualP.y() );
1978       }
1979       G4double Pz =   common.WplusProjectile * common.XplusResidual / 2.0
1980                     - Mt2 / ( 2.0 * common.WplusProjectile * common.XplusResidual );
1981       G4double E  =   common.WplusProjectile * common.XplusResidual / 2.0 
1982                     + Mt2 / ( 2.0 * common.WplusProjectile * common.XplusResidual );
1983       ProjectileResidual4Momentum.setPz( Pz );
1984       ProjectileResidual4Momentum.setE( E );
1985       ProjectileResidual4Momentum.transform( common.toLab );
1986     } else {
1987       ProjectileResidual4Momentum = G4LorentzVector( 0.0, 0.0, 0.0, 0.0 );
1988     }
1989     #ifdef debugAdjust
1990     G4cout << "Pr N R " << common.Pprojectile << G4endl 
1991            << "       " << ProjectileResidual4Momentum << G4endl;
1992     #endif
1993   }
1994 
1995 }
1996 
1997 
1998 //============================================================================
1999 
2000 void G4FTFModel::BuildStrings( G4ExcitedStringVector* strings ) {
2001   // Loop over all collisions; find all primaries, and all targets 
2002   // (targets may be duplicate in the List (to unique G4VSplitableHadrons) ).
2003 
2004   G4ExcitedString* FirstString( 0 );     // If there will be a kink,
2005   G4ExcitedString* SecondString( 0 );    // two strings will be produced.
2006 
2007   if ( ! GetProjectileNucleus() ) {
2008 
2009     std::vector< G4VSplitableHadron* > primaries;
2010     theParticipants.StartLoop();
2011     while ( theParticipants.Next() ) {  /* Loop checking, 10.08.2015, A.Ribon */
2012       const G4InteractionContent& interaction = theParticipants.GetInteraction();
2013       //  do not allow for duplicates ...
2014       if ( interaction.GetStatus() ) {
2015         if ( primaries.end() == std::find( primaries.begin(), primaries.end(), 
2016                                            interaction.GetProjectile() ) ) {
2017           primaries.push_back( interaction.GetProjectile() );
2018         }
2019       }
2020     }
2021 
2022     #ifdef debugBuildString
2023     G4cout << "G4FTFModel::BuildStrings()" << G4endl
2024            << "Number of projectile strings " << primaries.size() << G4endl;
2025     #endif
2026 
2027     for ( unsigned int ahadron = 0; ahadron < primaries.size(); ahadron++ ) {
2028       G4bool isProjectile( true );
2029       //G4cout << "primaries[ ahadron ] " << primaries[ ahadron ] << G4endl;
2030       //if ( primaries[ ahadron ]->GetStatus() <= 1 ) isProjectile = true;
2031       FirstString = 0; SecondString = 0;
2032       if ( primaries[ahadron]->GetStatus() == 0 ) {
2033        theExcitation->CreateStrings( primaries[ ahadron ], isProjectile, 
2034                                      FirstString, SecondString, theParameters );
2035        NumberOfProjectileSpectatorNucleons--;
2036       } else if ( primaries[ahadron]->GetStatus() == 1  
2037                && primaries[ahadron]->GetSoftCollisionCount() != 0 ) {
2038        theExcitation->CreateStrings( primaries[ ahadron ], isProjectile, 
2039                                      FirstString, SecondString, theParameters );
2040        NumberOfProjectileSpectatorNucleons--;
2041       } else if ( primaries[ahadron]->GetStatus() == 1  
2042                && primaries[ahadron]->GetSoftCollisionCount() == 0 ) {
2043        G4LorentzVector ParticleMomentum=primaries[ahadron]->Get4Momentum();
2044        G4KineticTrack* aTrack = new G4KineticTrack( primaries[ahadron]->GetDefinition(),
2045                                                     primaries[ahadron]->GetTimeOfCreation(),
2046                                                     primaries[ahadron]->GetPosition(),
2047                                                     ParticleMomentum );
2048        FirstString = new G4ExcitedString( aTrack );
2049       } else if (primaries[ahadron]->GetStatus() == 2) {
2050        G4LorentzVector ParticleMomentum=primaries[ahadron]->Get4Momentum();
2051        G4KineticTrack* aTrack = new G4KineticTrack( primaries[ahadron]->GetDefinition(),
2052                                                     primaries[ahadron]->GetTimeOfCreation(),
2053                                                     primaries[ahadron]->GetPosition(),
2054                                                     ParticleMomentum );
2055        FirstString = new G4ExcitedString( aTrack );
2056        NumberOfProjectileSpectatorNucleons--;
2057       } else {
2058         G4cout << "Something wrong in FTF Model Build String" << G4endl;
2059       }
2060 
2061       if ( FirstString  != 0 ) strings->push_back( FirstString );
2062       if ( SecondString != 0 ) strings->push_back( SecondString );
2063 
2064       #ifdef debugBuildString
2065       G4cout << "FirstString & SecondString? " << FirstString << " " << SecondString << G4endl;
2066       if ( FirstString->IsExcited() ) {
2067         G4cout << "Quarks on the FirstString ends " << FirstString->GetRightParton()->GetPDGcode()
2068                << " " << FirstString->GetLeftParton()->GetPDGcode() << G4endl;
2069       } else {
2070         G4cout << "Kinetic track is stored" << G4endl;
2071       }
2072       #endif
2073 
2074     }
2075 
2076     #ifdef debugBuildString
2077     if ( FirstString->IsExcited() ) {
2078       G4cout << "Check 1 string " << strings->operator[](0)->GetRightParton()->GetPDGcode() 
2079              << " " << strings->operator[](0)->GetLeftParton()->GetPDGcode() << G4endl << G4endl;
2080     }
2081     #endif
2082 
2083     std::for_each( primaries.begin(), primaries.end(), DeleteVSplitableHadron() );
2084     primaries.clear();
2085 
2086   } else {  // Projectile is a nucleus
2087 
2088     #ifdef debugBuildString
2089     G4cout << "Building of projectile-like strings" << G4endl;
2090     #endif
2091 
2092     G4bool isProjectile = true;
2093     for ( G4int ahadron = 0; ahadron < NumberOfInvolvedNucleonsOfProjectile; ahadron++ ) {
2094 
2095       #ifdef debugBuildString
2096       G4cout << "Nucleon #, status, intCount " << ahadron << " "
2097              << TheInvolvedNucleonsOfProjectile[ ahadron ]->GetSplitableHadron()->GetStatus() 
2098              << " " << TheInvolvedNucleonsOfProjectile[ ahadron ]->GetSplitableHadron()
2099                        ->GetSoftCollisionCount()<<G4endl;
2100       #endif
2101 
2102       G4VSplitableHadron* aProjectile = 
2103           TheInvolvedNucleonsOfProjectile[ ahadron ]->GetSplitableHadron();
2104 
2105       #ifdef debugBuildString
2106       G4cout << G4endl << "ahadron aProjectile Status " << ahadron << " " << aProjectile
2107              << " " << aProjectile->GetStatus() << G4endl;
2108       #endif
2109 
2110       FirstString = 0; SecondString = 0;
2111       if ( aProjectile->GetStatus() == 0 ) {  // A nucleon took part in non-diffractive interaction
2112 
2113         #ifdef debugBuildString
2114         G4cout << "Case1 aProjectile->GetStatus() == 0 " << G4endl;
2115         #endif
2116 
2117         theExcitation->CreateStrings( 
2118                            TheInvolvedNucleonsOfProjectile[ ahadron ]->GetSplitableHadron(),
2119                            isProjectile, FirstString, SecondString, theParameters );
2120         NumberOfProjectileSpectatorNucleons--;
2121       } else if ( aProjectile->GetStatus() == 1 && aProjectile->GetSoftCollisionCount() != 0 ) { 
2122         // Nucleon took part in diffractive interaction
2123 
2124         #ifdef debugBuildString
2125         G4cout << "Case2 aProjectile->GetStatus() !=0 St==1 SoftCol!=0" << G4endl;
2126         #endif
2127 
2128         theExcitation->CreateStrings( 
2129                            TheInvolvedNucleonsOfProjectile[ ahadron ]->GetSplitableHadron(),
2130                            isProjectile, FirstString, SecondString, theParameters );
2131         NumberOfProjectileSpectatorNucleons--;
2132       } else if ( aProjectile->GetStatus() == 1  &&  aProjectile->GetSoftCollisionCount() == 0  &&
2133                   HighEnergyInter ) {
2134         // Nucleon was considered as a paricipant of an interaction,
2135         // but the interaction was skipped due to annihilation.
2136         // It is now considered as an involved nucleon at high energies.
2137 
2138         #ifdef debugBuildString
2139         G4cout << "Case3 aProjectile->GetStatus() !=0 St==1 SoftCol==0" << G4endl;
2140         #endif
2141 
2142         G4LorentzVector ParticleMomentum = aProjectile->Get4Momentum();
2143         G4KineticTrack* aTrack = new G4KineticTrack( aProjectile->GetDefinition(),
2144                                                      aProjectile->GetTimeOfCreation(),
2145                                                      aProjectile->GetPosition(),
2146                                                      ParticleMomentum );
2147         FirstString = new G4ExcitedString( aTrack );
2148 
2149         #ifdef debugBuildString
2150         G4cout << " Strings are built for nucleon marked for an interaction, but"
2151                << " the interaction was skipped." << G4endl;
2152         #endif
2153 
2154       } else if ( aProjectile->GetStatus() == 2  ||  aProjectile->GetStatus() == 3 ) {
2155         // Nucleon which was involved in the Reggeon cascading
2156 
2157         #ifdef debugBuildString
2158         G4cout << "Case4 aProjectile->GetStatus() !=0 St==2 " << G4endl;
2159         #endif
2160 
2161         G4LorentzVector ParticleMomentum = aProjectile->Get4Momentum();
2162         G4KineticTrack* aTrack = new G4KineticTrack( aProjectile->GetDefinition(),
2163                                                      aProjectile->GetTimeOfCreation(),
2164                                                      aProjectile->GetPosition(),
2165                                                      ParticleMomentum );
2166         FirstString = new G4ExcitedString( aTrack );
2167 
2168         #ifdef debugBuildString
2169         G4cout << " Strings are build for involved nucleon." << G4endl;
2170         #endif
2171 
2172         if ( aProjectile->GetStatus() == 2 ) NumberOfProjectileSpectatorNucleons--;
2173       } else {
2174 
2175         #ifdef debugBuildString
2176         G4cout << "Case5 " << G4endl;
2177         #endif
2178 
2179         //TheInvolvedNucleonsOfProjectile[ ahadron ]->Hit( 0 );
2180         //G4cout << TheInvolvedNucleonsOfProjectile[ ahadron ]->GetSplitableHadron() << G4endl;
2181 
2182         #ifdef debugBuildString
2183         G4cout << " No string" << G4endl;
2184         #endif
2185 
2186       }
2187 
2188       if ( FirstString  != 0 ) strings->push_back( FirstString );
2189       if ( SecondString != 0 ) strings->push_back( SecondString );
2190     }
2191   } 
2192 
2193   #ifdef debugBuildString
2194   G4cout << "Building of target-like strings" << G4endl;
2195   #endif
2196 
2197   G4bool isProjectile = false;
2198   for ( G4int ahadron = 0; ahadron < NumberOfInvolvedNucleonsOfTarget; ahadron++ ) {
2199     G4VSplitableHadron* aNucleon = TheInvolvedNucleonsOfTarget[ ahadron ]->GetSplitableHadron();
2200 
2201     #ifdef debugBuildString
2202     G4cout << "Nucleon #, status, intCount " << aNucleon << " " << ahadron << " "
2203            << aNucleon->GetStatus() << " " << aNucleon->GetSoftCollisionCount()<<G4endl;;
2204     #endif
2205 
2206     FirstString = 0 ; SecondString = 0;
2207 
2208     if ( aNucleon->GetStatus() == 0 ) { // A nucleon took part in non-diffractive interaction
2209       theExcitation->CreateStrings( aNucleon, isProjectile, 
2210                                     FirstString, SecondString, theParameters );
2211       NumberOfTargetSpectatorNucleons--;
2212 
2213       #ifdef debugBuildString
2214       G4cout << " 1 case A string is build" << G4endl;
2215       #endif
2216 
2217     } else if ( aNucleon->GetStatus() == 1  &&  aNucleon->GetSoftCollisionCount() != 0 ) {
2218       // A nucleon took part in diffractive interaction
2219       theExcitation->CreateStrings( aNucleon, isProjectile,
2220                                     FirstString, SecondString, theParameters );
2221 
2222       #ifdef debugBuildString
2223       G4cout << " 2 case A string is build, nucleon was excited." << G4endl;
2224       #endif
2225 
2226       NumberOfTargetSpectatorNucleons--;
2227 
2228     } else if ( aNucleon->GetStatus() == 1  &&  aNucleon->GetSoftCollisionCount() == 0  &&
2229                 HighEnergyInter ) {
2230       // A nucleon was considered as a participant but due to annihilation
2231       // its interactions were skipped. It will be considered as involved one
2232       // at high energies.
2233 
2234       G4LorentzVector ParticleMomentum = aNucleon->Get4Momentum();
2235       G4KineticTrack* aTrack = new G4KineticTrack( aNucleon->GetDefinition(),
2236                                                    aNucleon->GetTimeOfCreation(),
2237                                                    aNucleon->GetPosition(),
2238                                                    ParticleMomentum );
2239 
2240       FirstString = new G4ExcitedString( aTrack );
2241 
2242       #ifdef debugBuildString
2243       G4cout << "3 case A string is build" << G4endl;
2244       #endif
2245 
2246     } else if ( aNucleon->GetStatus() == 1  &&  aNucleon->GetSoftCollisionCount() == 0  &&
2247                 ! HighEnergyInter ) {
2248       // A nucleon was considered as a participant but due to annihilation
2249       // its interactions were skipped. It will be returned to nucleus
2250       // at low energies energies.
2251       aNucleon->SetStatus( 5 );  // 4->5
2252       // ??? delete aNucleon;
2253 
2254       #ifdef debugBuildString
2255       G4cout << "4 case A string is not build" << G4endl;
2256       #endif
2257 
2258     } else if ( aNucleon->GetStatus() == 2  ||   // A nucleon took part in quark exchange
2259                 aNucleon->GetStatus() == 3  ) {  // A nucleon was involved in Reggeon cascading
2260       G4LorentzVector ParticleMomentum = aNucleon->Get4Momentum();
2261       G4KineticTrack* aTrack = new G4KineticTrack( aNucleon->GetDefinition(),
2262                                                    aNucleon->GetTimeOfCreation(),
2263                                                    aNucleon->GetPosition(),
2264                                                    ParticleMomentum );
2265       FirstString = new G4ExcitedString( aTrack );
2266 
2267       #ifdef debugBuildString
2268       G4cout << "5 case A string is build" << G4endl;
2269       #endif
2270 
2271       if ( aNucleon->GetStatus() == 2 ) NumberOfTargetSpectatorNucleons--;
2272 
2273     } else {
2274 
2275       #ifdef debugBuildString
2276       G4cout << "6 case No string" << G4endl;
2277       #endif
2278 
2279     }
2280 
2281     if ( FirstString  != 0 ) strings->push_back( FirstString );
2282     if ( SecondString != 0 ) strings->push_back( SecondString );
2283 
2284   }
2285 
2286   #ifdef debugBuildString
2287   G4cout << G4endl << "theAdditionalString.size() " << theAdditionalString.size() 
2288          << G4endl << G4endl;
2289   #endif
2290 
2291   isProjectile = true;
2292   if ( theAdditionalString.size() != 0 ) {
2293     for ( unsigned int  ahadron = 0; ahadron < theAdditionalString.size(); ahadron++ ) {
2294       //if ( theAdditionalString[ ahadron ]->GetStatus() <= 1 ) isProjectile = true; 
2295       FirstString = 0; SecondString = 0;
2296       theExcitation->CreateStrings( theAdditionalString[ ahadron ], isProjectile,
2297                                     FirstString, SecondString, theParameters );
2298       if ( FirstString  != 0 ) strings->push_back( FirstString );
2299       if ( SecondString != 0 ) strings->push_back( SecondString );
2300     }
2301   }
2302 
2303   //for ( unsigned int ahadron = 0; ahadron < strings->size(); ahadron++ ) {
2304   //  G4cout << ahadron << " " << strings->operator[]( ahadron )->GetRightParton()->GetPDGcode()
2305   //         << " " << strings->operator[]( ahadron )->GetLeftParton()->GetPDGcode() << G4endl;
2306   //}
2307   //G4cout << "------------------------" << G4endl;
2308 
2309   return;
2310 }
2311 
2312 
2313 //============================================================================
2314 
2315 void G4FTFModel::GetResiduals() {
2316   // This method is needed for the correct application of G4PrecompoundModelInterface
2317 
2318   #ifdef debugFTFmodel
2319   G4cout << "GetResiduals(): HighEnergyInter? GetProjectileNucleus()?"
2320          << HighEnergyInter << " " << GetProjectileNucleus() << G4endl;
2321   #endif
2322 
2323   if ( HighEnergyInter ) {
2324 
2325     #ifdef debugFTFmodel
2326     G4cout << "NumberOfInvolvedNucleonsOfTarget "<< NumberOfInvolvedNucleonsOfTarget << G4endl;
2327     #endif
2328 
2329     G4double DeltaExcitationE = TargetResidualExcitationEnergy / 
2330                                 G4double( NumberOfInvolvedNucleonsOfTarget );
2331     G4LorentzVector DeltaPResidualNucleus = TargetResidual4Momentum /
2332                                             G4double( NumberOfInvolvedNucleonsOfTarget );
2333 
2334     for ( G4int i = 0; i < NumberOfInvolvedNucleonsOfTarget; ++i ) {
2335       G4Nucleon* aNucleon = TheInvolvedNucleonsOfTarget[i];
2336 
2337       #ifdef debugFTFmodel
2338       G4VSplitableHadron* targetSplitable = aNucleon->GetSplitableHadron();
2339       G4cout << i << " Hit? " << aNucleon->AreYouHit() << " pointer " << targetSplitable << G4endl;
2340       if ( targetSplitable ) G4cout << i << "Status " << targetSplitable->GetStatus() << G4endl;
2341       #endif
2342 
2343       G4LorentzVector tmp = -DeltaPResidualNucleus;
2344       aNucleon->SetMomentum( tmp );
2345       aNucleon->SetBindingEnergy( DeltaExcitationE );
2346     }
2347 
2348     if ( TargetResidualMassNumber != 0 ) {
2349       G4ThreeVector bstToCM = TargetResidual4Momentum.findBoostToCM();
2350 
2351       G4V3DNucleus* theTargetNucleus = GetTargetNucleus();
2352       G4LorentzVector residualMomentum( 0.0, 0.0, 0.0, 0.0 );
2353       G4Nucleon* aNucleon = 0;
2354       theTargetNucleus->StartLoop();
2355       while ( ( aNucleon = theTargetNucleus->GetNextNucleon() ) ) {  /* Loop checking, 10.08.2015, A.Ribon */
2356         if ( ! aNucleon->AreYouHit() ) { 
2357           G4LorentzVector tmp = aNucleon->Get4Momentum(); tmp.boost( bstToCM );
2358           aNucleon->SetMomentum( tmp );
2359           residualMomentum += tmp;
2360         }
2361       }
2362 
2363       residualMomentum /= TargetResidualMassNumber;
2364 
2365       G4double Mass = TargetResidual4Momentum.mag();
2366       G4double SumMasses = 0.0;
2367   
2368       aNucleon = 0;
2369       theTargetNucleus->StartLoop();
2370       while ( ( aNucleon = theTargetNucleus->GetNextNucleon() ) ) {  /* Loop checking, 10.08.2015, A.Ribon */
2371         if ( ! aNucleon->AreYouHit() ) { 
2372           G4LorentzVector tmp = aNucleon->Get4Momentum() - residualMomentum;
2373           G4double E = std::sqrt( tmp.vect().mag2() +
2374                                   sqr( aNucleon->GetDefinition()->GetPDGMass() - aNucleon->GetBindingEnergy() ) );
2375           tmp.setE( E );  aNucleon->SetMomentum( tmp );
2376           SumMasses += E;
2377         }
2378       }
2379 
2380       G4double Chigh = Mass / SumMasses; G4double Clow = 0.0; G4double C;
2381       const G4int maxNumberOfLoops = 1000;
2382       G4int loopCounter = 0;
2383       do {
2384         C = ( Chigh + Clow ) / 2.0;
2385         SumMasses = 0.0;
2386         aNucleon = 0;
2387         theTargetNucleus->StartLoop();
2388         while ( ( aNucleon = theTargetNucleus->GetNextNucleon() ) ) {  /* Loop checking, 10.08.2015, A.Ribon */
2389           if ( ! aNucleon->AreYouHit() ) { 
2390             G4LorentzVector tmp = aNucleon->Get4Momentum();
2391             G4double E = std::sqrt( tmp.vect().mag2()*sqr(C) +
2392                                     sqr( aNucleon->GetDefinition()->GetPDGMass() - aNucleon->GetBindingEnergy() ) );
2393             SumMasses += E;
2394           }
2395         }
2396 
2397         if ( SumMasses > Mass ) Chigh = C;
2398         else                    Clow  = C;
2399 
2400       } while ( Chigh - Clow > 0.01  &&
2401                 ++loopCounter < maxNumberOfLoops );  /* Loop checking, 10.08.2015, A.Ribon */
2402       if ( loopCounter >= maxNumberOfLoops ) {
2403         #ifdef debugFTFmodel
2404         G4cout << "BAD situation: forced exit of the first while loop in G4FTFModel::GetResidual" << G4endl
2405                << "\t return immediately from the method!" << G4endl;
2406         #endif
2407         return;
2408       }
2409 
2410       aNucleon = 0;
2411       theTargetNucleus->StartLoop();
2412       while ( ( aNucleon = theTargetNucleus->GetNextNucleon() ) ) {  /* Loop checking, 10.08.2015, A.Ribon */
2413         if ( !aNucleon->AreYouHit() ) { 
2414           G4LorentzVector tmp = aNucleon->Get4Momentum()*C;
2415           G4double E = std::sqrt( tmp.vect().mag2()+
2416                                   sqr( aNucleon->GetDefinition()->GetPDGMass()-aNucleon->GetBindingEnergy() ) );
2417           tmp.setE( E ); tmp.boost( -bstToCM );  
2418           aNucleon->SetMomentum( tmp );     
2419         }
2420       }
2421     }
2422 
2423     if ( ! GetProjectileNucleus() ) return;  // The projectile is a hadron
2424 
2425     #ifdef debugFTFmodel
2426     G4cout << "NumberOfInvolvedNucleonsOfProjectile " << NumberOfInvolvedNucleonsOfProjectile
2427            << G4endl << "ProjectileResidualExcitationEnergy ProjectileResidual4Momentum "
2428            << ProjectileResidualExcitationEnergy << "  " << ProjectileResidual4Momentum << G4endl;
2429     #endif
2430 
2431     DeltaExcitationE = ProjectileResidualExcitationEnergy /
2432                        G4double( NumberOfInvolvedNucleonsOfProjectile );
2433     DeltaPResidualNucleus = ProjectileResidual4Momentum /
2434                             G4double( NumberOfInvolvedNucleonsOfProjectile );
2435 
2436     for ( G4int i = 0; i < NumberOfInvolvedNucleonsOfProjectile; ++i ) {
2437       G4Nucleon* aNucleon = TheInvolvedNucleonsOfProjectile[i];
2438 
2439       #ifdef debugFTFmodel
2440       G4VSplitableHadron* projSplitable = aNucleon->GetSplitableHadron();
2441       G4cout << i << " Hit? " << aNucleon->AreYouHit() << " pointer " << projSplitable << G4endl;
2442       if ( projSplitable ) G4cout << i << "Status " << projSplitable->GetStatus() << G4endl;
2443       #endif
2444 
2445       G4LorentzVector tmp = -DeltaPResidualNucleus;
2446       aNucleon->SetMomentum( tmp );
2447       aNucleon->SetBindingEnergy( DeltaExcitationE );
2448     }
2449 
2450     if ( ProjectileResidualMassNumber != 0 ) {
2451       G4ThreeVector bstToCM = ProjectileResidual4Momentum.findBoostToCM();
2452 
2453       G4V3DNucleus* theProjectileNucleus = GetProjectileNucleus();
2454       G4LorentzVector residualMomentum( 0.0, 0.0, 0.0, 0.0);
2455       G4Nucleon* aNucleon = 0;
2456       theProjectileNucleus->StartLoop();
2457       while ( ( aNucleon = theProjectileNucleus->GetNextNucleon() ) ) {  /* Loop checking, 10.08.2015, A.Ribon */
2458         if ( ! aNucleon->AreYouHit() ) { 
2459           G4LorentzVector tmp = aNucleon->Get4Momentum(); tmp.boost( bstToCM );
2460           aNucleon->SetMomentum( tmp );
2461           residualMomentum += tmp;
2462         }
2463       }
2464 
2465       residualMomentum /= ProjectileResidualMassNumber;
2466 
2467       G4double Mass = ProjectileResidual4Momentum.mag();
2468       G4double SumMasses= 0.0;
2469   
2470       aNucleon = 0;
2471       theProjectileNucleus->StartLoop();
2472       while ( ( aNucleon = theProjectileNucleus->GetNextNucleon() ) ) {  /* Loop checking, 10.08.2015, A.Ribon */
2473         if ( ! aNucleon->AreYouHit() ) { 
2474           G4LorentzVector tmp = aNucleon->Get4Momentum() - residualMomentum;
2475           G4double E=std::sqrt( tmp.vect().mag2() +
2476                                 sqr(aNucleon->GetDefinition()->GetPDGMass()-aNucleon->GetBindingEnergy() ) );
2477           tmp.setE( E );  aNucleon->SetMomentum( tmp );
2478           SumMasses += E;
2479         }
2480       }
2481 
2482       G4double Chigh = Mass / SumMasses; G4double Clow = 0.0; G4double C;
2483       const G4int maxNumberOfLoops = 1000;
2484       G4int loopCounter = 0;
2485       do {
2486         C = ( Chigh + Clow ) / 2.0;
2487 
2488         SumMasses = 0.0;
2489         aNucleon = 0;
2490         theProjectileNucleus->StartLoop();
2491         while ( ( aNucleon = theProjectileNucleus->GetNextNucleon() ) ) {  /* Loop checking, 10.08.2015, A.Ribon */
2492           if ( ! aNucleon->AreYouHit() ) { 
2493             G4LorentzVector tmp = aNucleon->Get4Momentum();
2494             G4double E = std::sqrt( tmp.vect().mag2()*sqr(C) +
2495                                     sqr( aNucleon->GetDefinition()->GetPDGMass() - aNucleon->GetBindingEnergy() ) );
2496             SumMasses += E;
2497           }
2498         }
2499 
2500         if ( SumMasses > Mass) Chigh = C;
2501         else                   Clow  = C;
2502 
2503       } while ( Chigh - Clow > 0.01  &&
2504                 ++loopCounter < maxNumberOfLoops );  /* Loop checking, 10.08.2015, A.Ribon */
2505       if ( loopCounter >= maxNumberOfLoops ) {
2506         #ifdef debugFTFmodel
2507         G4cout << "BAD situation: forced exit of the second while loop in G4FTFModel::GetResidual" << G4endl
2508                << "\t return immediately from the method!" << G4endl;
2509         #endif
2510         return;
2511       }
2512 
2513       aNucleon = 0;
2514       theProjectileNucleus->StartLoop();
2515       while ( ( aNucleon = theProjectileNucleus->GetNextNucleon() ) ) {  /* Loop checking, 10.08.2015, A.Ribon */
2516         if ( ! aNucleon->AreYouHit() ) { 
2517           G4LorentzVector tmp = aNucleon->Get4Momentum()*C;
2518           G4double E = std::sqrt( tmp.vect().mag2() +
2519                                   sqr( aNucleon->GetDefinition()->GetPDGMass() - aNucleon->GetBindingEnergy() ) );
2520           tmp.setE( E ); tmp.boost( -bstToCM );  
2521           aNucleon->SetMomentum( tmp ); 
2522         }
2523       }
2524     }   // End of if ( ProjectileResidualMassNumber != 0 )
2525   
2526     #ifdef debugFTFmodel
2527     G4cout << "End projectile" << G4endl;
2528     #endif
2529    
2530   } else {  // Related to the condition: if ( HighEnergyInter )
2531 
2532     #ifdef debugFTFmodel
2533     G4cout << "Low energy interaction: Target nucleus --------------" << G4endl
2534            << "Tr ResidualMassNumber Tr ResidualCharge Tr ResidualExcitationEnergy  "
2535            << TargetResidualMassNumber << " " << TargetResidualCharge << " "
2536            << TargetResidualExcitationEnergy << G4endl;
2537     #endif
2538 
2539     G4int NumberOfTargetParticipant( 0 );
2540     for ( G4int i = 0; i < NumberOfInvolvedNucleonsOfTarget; ++i ) {
2541       G4Nucleon* aNucleon = TheInvolvedNucleonsOfTarget[i];
2542       G4VSplitableHadron* targetSplitable = aNucleon->GetSplitableHadron();
2543       if ( targetSplitable->GetSoftCollisionCount() != 0 ) NumberOfTargetParticipant++;
2544     } 
2545 
2546     G4double DeltaExcitationE( 0.0 );
2547     G4LorentzVector DeltaPResidualNucleus = G4LorentzVector( 0.0, 0.0, 0.0, 0.0 );
2548 
2549     if ( NumberOfTargetParticipant != 0 ) {
2550       DeltaExcitationE = TargetResidualExcitationEnergy / G4double( NumberOfTargetParticipant );
2551       DeltaPResidualNucleus = TargetResidual4Momentum / G4double( NumberOfTargetParticipant );
2552     }
2553 
2554     for ( G4int i = 0; i < NumberOfInvolvedNucleonsOfTarget; ++i ) {
2555       G4Nucleon* aNucleon = TheInvolvedNucleonsOfTarget[i];
2556       G4VSplitableHadron* targetSplitable = aNucleon->GetSplitableHadron();
2557       if ( targetSplitable->GetSoftCollisionCount() != 0 ) {
2558         G4LorentzVector tmp = -DeltaPResidualNucleus;
2559         aNucleon->SetMomentum( tmp );
2560         aNucleon->SetBindingEnergy( DeltaExcitationE );
2561       } else {
2562         delete targetSplitable;  
2563         targetSplitable = 0; 
2564         aNucleon->Hit( targetSplitable );
2565         aNucleon->SetBindingEnergy( 0.0 );
2566       }
2567     } 
2568 
2569     #ifdef debugFTFmodel
2570     G4cout << "NumberOfTargetParticipant " << NumberOfTargetParticipant << G4endl
2571            << "TargetResidual4Momentum  " << TargetResidual4Momentum << G4endl;
2572     #endif
2573 
2574     if ( ! GetProjectileNucleus() ) return;  // The projectile is a hadron
2575 
2576     #ifdef debugFTFmodel
2577     G4cout << "Low energy interaction: Projectile nucleus --------------" << G4endl
2578            << "Pr ResidualMassNumber Pr ResidualCharge Pr ResidualExcitationEnergy "
2579            << ProjectileResidualMassNumber << " " << ProjectileResidualCharge << " "
2580            << ProjectileResidualExcitationEnergy << G4endl;
2581     #endif
2582 
2583     G4int NumberOfProjectileParticipant( 0 );
2584     for ( G4int i = 0; i < NumberOfInvolvedNucleonsOfProjectile; ++i ) {
2585       G4Nucleon* aNucleon = TheInvolvedNucleonsOfProjectile[i];
2586       G4VSplitableHadron* projectileSplitable = aNucleon->GetSplitableHadron();
2587       if ( projectileSplitable->GetSoftCollisionCount() != 0 ) NumberOfProjectileParticipant++;
2588     }
2589  
2590     #ifdef debugFTFmodel
2591     G4cout << "NumberOfProjectileParticipant" << G4endl;
2592     #endif
2593 
2594     DeltaExcitationE = 0.0;
2595     DeltaPResidualNucleus = G4LorentzVector( 0.0, 0.0, 0.0, 0.0 );
2596 
2597     if ( NumberOfProjectileParticipant != 0 ) {
2598       DeltaExcitationE = ProjectileResidualExcitationEnergy / G4double( NumberOfProjectileParticipant );
2599       DeltaPResidualNucleus = ProjectileResidual4Momentum / G4double( NumberOfProjectileParticipant );
2600     }
2601     //G4cout << "DeltaExcitationE DeltaPResidualNucleus " << DeltaExcitationE
2602     //       << " " << DeltaPResidualNucleus << G4endl;
2603     for ( G4int i = 0; i < NumberOfInvolvedNucleonsOfProjectile; ++i ) {
2604       G4Nucleon* aNucleon = TheInvolvedNucleonsOfProjectile[i];
2605       G4VSplitableHadron* projectileSplitable = aNucleon->GetSplitableHadron();
2606       if ( projectileSplitable->GetSoftCollisionCount() != 0 ) {
2607         G4LorentzVector tmp = -DeltaPResidualNucleus;
2608         aNucleon->SetMomentum( tmp );
2609         aNucleon->SetBindingEnergy( DeltaExcitationE );
2610       } else {
2611         delete projectileSplitable;  
2612         projectileSplitable = 0; 
2613         aNucleon->Hit( projectileSplitable );
2614         aNucleon->SetBindingEnergy( 0.0 );
2615       } 
2616     } 
2617 
2618     #ifdef debugFTFmodel
2619     G4cout << "NumberOfProjectileParticipant " << NumberOfProjectileParticipant << G4endl
2620            << "ProjectileResidual4Momentum " << ProjectileResidual4Momentum << G4endl;
2621     #endif
2622 
2623   }  // End of the condition: if ( HighEnergyInter )
2624 
2625   #ifdef debugFTFmodel
2626   G4cout << "End GetResiduals -----------------" << G4endl;
2627   #endif
2628 
2629 }
2630 
2631 
2632 //============================================================================
2633 
2634 G4ThreeVector G4FTFModel::GaussianPt( G4double AveragePt2, G4double maxPtSquare ) const {
2635 
2636   G4double Pt2( 0.0 ), Pt( 0.0 );
2637 
2638   if (AveragePt2 > 0.0) {
2639     const G4double ymax = maxPtSquare/AveragePt2;
2640     if ( ymax < 200. ) {
2641       Pt2 = -AveragePt2 * G4Log( 1.0 + G4UniformRand() * ( G4Exp( -ymax ) -1.0 ) );
2642     } else {
2643       Pt2 = -AveragePt2 * G4Log( 1.0 - G4UniformRand() ); 
2644     }
2645     Pt = std::sqrt( Pt2 );
2646   }
2647 
2648   G4double phi = G4UniformRand() * twopi;
2649  
2650   return G4ThreeVector( Pt*std::cos(phi), Pt*std::sin(phi), 0.0 );    
2651 }
2652 
2653 //============================================================================
2654 
2655 G4bool G4FTFModel::
2656 ComputeNucleusProperties( G4V3DNucleus* nucleus,               // input parameter 
2657                           G4LorentzVector& nucleusMomentum,    // input & output parameter
2658                           G4LorentzVector& residualMomentum,   // input & output parameter
2659                           G4double& sumMasses,                 // input & output parameter
2660                           G4double& residualExcitationEnergy,  // input & output parameter
2661                           G4double& residualMass,              // input & output parameter
2662                           G4int& residualMassNumber,           // input & output parameter
2663                           G4int& residualCharge ) {            // input & output parameter
2664 
2665   // This method, which is called only by PutOnMassShell, computes some nucleus properties for:
2666   // -  either the target nucleus (which is never an antinucleus): this for any kind
2667   //    of hadronic interaction (hadron-nucleus, nucleus-nucleus, antinucleus-nucleus);
2668   // -  or the projectile nucleus or antinucleus: this only in the case of nucleus-nucleus
2669   //    or antinucleus-nucleus interaction.
2670   // This method assumes that the all the parameters have been initialized by the caller;
2671   // the action of this method consists in modifying all these parameters, except the
2672   // first one. The return value is "false" only in the case the pointer to the nucleus
2673   // is null.
2674 
2675   if ( ! nucleus ) return false;
2676 
2677   G4double ExcitationEnergyPerWoundedNucleon = 
2678     theParameters->GetExcitationEnergyPerWoundedNucleon();
2679 
2680   // Loop over the nucleons of the nucleus. 
2681   // The nucleons that have been involved in the interaction (either from Glauber or
2682   // Reggeon Cascading) will be candidate to be emitted.
2683   // All the remaining nucleons will be the nucleons of the candidate residual nucleus.
2684   // The variable sumMasses is the amount of energy corresponding to:
2685   //     1. transverse mass of each involved nucleon
2686   //     2. 20.0*MeV separation energy for each involved nucleon
2687   //     3. transverse mass of the residual nucleus
2688   // In this first evaluation of sumMasses, the excitation energy of the residual nucleus
2689   // (residualExcitationEnergy, estimated by adding a constant value to each involved
2690   // nucleon) is not taken into account.
2691   G4int residualNumberOfLambdas = 0;  // Projectile nucleus and its residual can be a hypernucleus
2692   G4Nucleon* aNucleon = 0;
2693   nucleus->StartLoop();
2694   while ( ( aNucleon = nucleus->GetNextNucleon() ) ) {  /* Loop checking, 10.08.2015, A.Ribon */
2695     nucleusMomentum += aNucleon->Get4Momentum();
2696     if ( aNucleon->AreYouHit() ) {  // Involved nucleons
2697       // Consider in sumMasses the nominal, i.e. on-shell, masses of the nucleons
2698       // (not the current masses, which could be different because the nucleons are off-shell).
2699       sumMasses += std::sqrt( sqr( aNucleon->GetDefinition()->GetPDGMass() ) 
2700                               +  aNucleon->Get4Momentum().perp2() );                     
2701       sumMasses += 20.0*MeV;  // Separation energy for a nucleon
2702 
2703       //residualExcitationEnergy += ExcitationEnergyPerWoundedNucleon;  // In G4 10.1
2704       residualExcitationEnergy += -ExcitationEnergyPerWoundedNucleon*G4Log( G4UniformRand() );
2705 
2706       residualMassNumber--;
2707       // The absolute value below is needed only in the case of anti-nucleus.
2708       residualCharge -= std::abs( G4int( aNucleon->GetDefinition()->GetPDGCharge() ) );
2709     } else {   // Spectator nucleons
2710       residualMomentum += aNucleon->Get4Momentum();
2711       if ( aNucleon->GetDefinition() == G4Lambda::Definition()  ||
2712      aNucleon->GetDefinition() == G4AntiLambda::Definition() ) {
2713   ++residualNumberOfLambdas;
2714       }
2715     }
2716   }
2717   #ifdef debugPutOnMassShell
2718   G4cout << "ExcitationEnergyPerWoundedNucleon " << ExcitationEnergyPerWoundedNucleon << G4endl
2719          << "\t Residual Charge, MassNumber (Number of Lambdas)" << residualCharge << " "
2720    << residualMassNumber << " (" << residualNumberOfLambdas << ") "
2721          << G4endl << "\t Initial Momentum " << nucleusMomentum
2722          << G4endl << "\t Residual Momentum   " << residualMomentum << G4endl;
2723   #endif
2724   residualMomentum.setPz( 0.0 ); 
2725   residualMomentum.setE( 0.0 );
2726   if ( residualMassNumber == 0 ) {
2727     residualMass = 0.0;
2728     residualExcitationEnergy = 0.0;
2729   } else {
2730     if ( residualMassNumber == 1 ) {
2731       if ( std::abs( residualCharge ) == 1 ) {
2732         residualMass = G4Proton::Definition()->GetPDGMass();
2733       } else if ( residualNumberOfLambdas == 1 ) {
2734         residualMass = G4Lambda::Definition()->GetPDGMass();
2735       } else {
2736         residualMass = G4Neutron::Definition()->GetPDGMass();
2737       } 
2738       residualExcitationEnergy = 0.0;
2739     } else {
2740       if ( residualNumberOfLambdas > 0 ) {
2741         if ( residualMassNumber == 2 ) {
2742     residualMass = G4Lambda::Definition()->GetPDGMass();
2743           if ( std::abs( residualCharge ) == 1 ) {      // lambda + proton
2744             residualMass += G4Proton::Definition()->GetPDGMass();
2745     } else if ( residualNumberOfLambdas == 1 ) {  // lambda + neutron
2746       residualMass += G4Neutron::Definition()->GetPDGMass();
2747           } else {                                      // lambda + lambda
2748       residualMass += G4Lambda::Definition()->GetPDGMass();
2749           }
2750         } else {
2751     residualMass = G4HyperNucleiProperties::GetNuclearMass( residualMassNumber, std::abs( residualCharge ),
2752                     residualNumberOfLambdas );
2753         }
2754       } else {
2755         residualMass = G4ParticleTable::GetParticleTable()->GetIonTable()->
2756                  GetIonMass( std::abs( residualCharge ), residualMassNumber );
2757       }
2758     }
2759     residualMass += residualExcitationEnergy;
2760   }
2761   sumMasses += std::sqrt( sqr( residualMass ) + residualMomentum.perp2() );
2762   return true;
2763 }
2764 
2765 
2766 //============================================================================
2767 
2768 G4bool G4FTFModel::
2769 GenerateDeltaIsobar( const G4double sqrtS,                  // input parameter
2770                      const G4int numberOfInvolvedNucleons,  // input parameter
2771                      G4Nucleon* involvedNucleons[],         // input & output parameter
2772                      G4double& sumMasses ) {                // input & output parameter
2773 
2774   // This method, which is called only by PutOnMassShell, check whether is possible to
2775   // re-interpret some of the involved nucleons as delta-isobars:
2776   // - either by replacing a proton (2212) with a Delta+ (2214),
2777   // - or by replacing a neutron (2112) with a Delta0 (2114).
2778   // The on-shell mass of these delta-isobars is ~1232 MeV, so  ~292-294 MeV  heavier than
2779   // the corresponding nucleon on-shell mass. However  400.0*MeV  is considered to estimate
2780   // the max number of deltas compatible with the available energy.
2781   // The delta-isobars are considered with the same transverse momentum as their
2782   // corresponding nucleons.
2783   // This method assumes that all the parameters have been initialized by the caller;
2784   // the action of this method consists in modifying (eventually) involveNucleons and
2785   // sumMasses. The return value is "false" only in the case that the input parameters
2786   // have unphysical values.
2787 
2788   if ( sqrtS < 0.0  ||  numberOfInvolvedNucleons <= 0  ||  sumMasses < 0.0 ) return false;
2789 
2790   const G4double probDeltaIsobar = 0.05;
2791 
2792   G4int maxNumberOfDeltas = G4int( (sqrtS - sumMasses)/(400.0*MeV) );
2793   G4int numberOfDeltas = 0;
2794 
2795   for ( G4int i = 0; i < numberOfInvolvedNucleons; ++i ) {
2796 
2797     if ( G4UniformRand() < probDeltaIsobar  &&  numberOfDeltas < maxNumberOfDeltas ) {
2798       numberOfDeltas++;
2799       if ( ! involvedNucleons[i] ) continue;
2800       // Skip any eventual lambda (that can be present in a projectile hypernucleus)
2801       if ( involvedNucleons[i]->GetDefinition() == G4Lambda::Definition()  ||
2802      involvedNucleons[i]->GetDefinition() == G4AntiLambda::Definition() ) continue;
2803       G4VSplitableHadron* splitableHadron = involvedNucleons[i]->GetSplitableHadron();
2804       G4double massNuc = std::sqrt( sqr( splitableHadron->GetDefinition()->GetPDGMass() )
2805                                     + splitableHadron->Get4Momentum().perp2() );
2806       // The absolute value below is needed in the case of an antinucleus. 
2807       G4int pdgCode = std::abs( splitableHadron->GetDefinition()->GetPDGEncoding() );
2808       const G4ParticleDefinition* old_def = splitableHadron->GetDefinition();
2809       G4int newPdgCode = pdgCode/10; newPdgCode = newPdgCode*10 + 4; // Delta
2810       if ( splitableHadron->GetDefinition()->GetPDGEncoding() < 0 ) newPdgCode *= -1;
2811       const G4ParticleDefinition* ptr = 
2812         G4ParticleTable::GetParticleTable()->FindParticle( newPdgCode );
2813       splitableHadron->SetDefinition( ptr );
2814       G4double massDelta = std::sqrt( sqr( splitableHadron->GetDefinition()->GetPDGMass() )
2815                                       + splitableHadron->Get4Momentum().perp2() );
2816       //G4cout << i << " " << sqrtS/GeV << " " << sumMasses/GeV << " " << massDelta/GeV
2817       //       << " " << massNuc << G4endl;
2818       if ( sqrtS < sumMasses + massDelta - massNuc ) {  // Change cannot be accepted!
2819         splitableHadron->SetDefinition( old_def );
2820         break;
2821       } else {  // Change is accepted
2822         sumMasses += ( massDelta - massNuc );
2823       }
2824     } 
2825   }
2826 
2827   return true;
2828 }
2829 
2830 
2831 //============================================================================
2832 
2833 G4bool G4FTFModel::
2834 SamplingNucleonKinematics( G4double averagePt2,                   // input parameter
2835                            const G4double maxPt2,                 // input parameter
2836                            G4double dCor,                         // input parameter
2837                            G4V3DNucleus* nucleus,                 // input parameter
2838                            const G4LorentzVector& pResidual,      // input parameter
2839                            const G4double residualMass,           // input parameter
2840                            const G4int residualMassNumber,        // input parameter
2841                            const G4int numberOfInvolvedNucleons,  // input parameter 
2842                            G4Nucleon* involvedNucleons[],         // input & output parameter
2843                            G4double& mass2 ) {                    // output parameter
2844 
2845   // This method, which is called only by PutOnMassShell, does the sampling of:
2846   // -  either the target nucleons: this for any kind of hadronic interactions
2847   //    (hadron-nucleus, nucleus-nucleus, antinucleus-nucleus);
2848   // -  or the projectile nucleons or antinucleons: this only in the case of
2849   //    nucleus-nucleus or antinucleus-nucleus interactions, respectively.
2850   // This method assumes that all the parameters have been initialized by the caller;
2851   // the action of this method consists in changing the properties of the nucleons
2852   // whose pointers are in the vector involvedNucleons, as well as changing the
2853   // variable mass2.
2854 #ifdef debugPutOnMassShell
2855   G4cout << "G4FTFModel::SamplingNucleonKinematics:" << G4endl;
2856   G4cout << " averagePt2= " << averagePt2 << " maxPt2= " << maxPt2
2857    << " dCor= " << dCor << " resMass(GeV)= " << residualMass/GeV
2858    << " resMassN= " << residualMassNumber 
2859          << " nNuc= " << numberOfInvolvedNucleons
2860    << " lv= " << pResidual << G4endl;   
2861 #endif
2862 
2863   if ( ! nucleus  ||  numberOfInvolvedNucleons < 1 ) return false;
2864 
2865   if ( residualMassNumber == 0  &&  numberOfInvolvedNucleons == 1 ) {
2866     dCor = 0.0; 
2867     averagePt2 = 0.0;
2868   } 
2869 
2870   G4bool success = true;                            
2871 
2872   G4double SumMasses = residualMass; 
2873   G4double invN = 1.0 / (G4double)numberOfInvolvedNucleons;
2874 
2875   // to avoid problems due to precision lost a tolerance is added
2876   const G4double eps = 1.e-10;  
2877   const G4int maxNumberOfLoops = 1000;
2878   G4int loopCounter = 0;
2879   do {
2880 
2881     success = true;
2882 
2883     // Sampling of nucleon Pt 
2884     G4ThreeVector ptSum( 0.0, 0.0, 0.0 );
2885     if( averagePt2 > 0.0 ) {
2886       for ( G4int i = 0; i < numberOfInvolvedNucleons; ++i ) {
2887   G4Nucleon* aNucleon = involvedNucleons[i];
2888   if ( ! aNucleon ) continue;
2889   G4ThreeVector tmpPt = GaussianPt( averagePt2, maxPt2 );
2890   ptSum += tmpPt;
2891   G4LorentzVector tmp( tmpPt.x(), tmpPt.y(), 0.0, 0.0 );
2892   aNucleon->SetMomentum( tmp );
2893       }
2894     }
2895 
2896     G4double deltaPx = ( ptSum.x() - pResidual.x() )*invN;
2897     G4double deltaPy = ( ptSum.y() - pResidual.y() )*invN;
2898 
2899     SumMasses = residualMass;
2900     for ( G4int i = 0; i < numberOfInvolvedNucleons; ++i ) {
2901       G4Nucleon* aNucleon = involvedNucleons[i];
2902       if ( ! aNucleon ) continue;
2903       G4double px = aNucleon->Get4Momentum().px() - deltaPx;
2904       G4double py = aNucleon->Get4Momentum().py() - deltaPy;
2905       G4double MtN = std::sqrt( sqr( aNucleon->GetSplitableHadron()->GetDefinition()->GetPDGMass() )
2906                                 + sqr( px ) + sqr( py ) );
2907       SumMasses += MtN;
2908       G4LorentzVector tmp( px, py, 0.0, MtN);
2909       aNucleon->SetMomentum( tmp );
2910     }
2911 
2912     // Sampling X of nucleon
2913     G4double xSum = 0.0;
2914 
2915     for ( G4int i = 0; i < numberOfInvolvedNucleons; ++i ) {
2916       G4Nucleon* aNucleon = involvedNucleons[i];
2917       if ( ! aNucleon ) continue;
2918      
2919       G4double x = 0.0;
2920       if( 0.0 != dCor ) {
2921   G4ThreeVector tmpX = GaussianPt( dCor*dCor, 1.0 );
2922         x = tmpX.x();
2923       } 
2924       x += aNucleon->Get4Momentum().e()/SumMasses;
2925       if ( x < -eps  ||  x > 1.0 + eps ) { 
2926         success = false; 
2927         break;
2928       }
2929       x = std::min(1.0, std::max(x, 0.0));
2930       xSum += x;
2931       // The energy is in the lab (instead of cms) frame but it will not be used
2932 
2933       G4LorentzVector tmp( aNucleon->Get4Momentum().x(), 
2934                            aNucleon->Get4Momentum().y(), 
2935                            x, aNucleon->Get4Momentum().e() );
2936       aNucleon->SetMomentum( tmp );
2937     }
2938 
2939     if ( xSum < -eps || xSum > 1.0 + eps ) success = false;
2940     if ( ! success ) continue;
2941 
2942     G4double delta = ( residualMassNumber == 0 ) ? std::min( xSum - 1.0, 0.0 )*invN : 0.0;
2943 
2944     xSum = 1.0;
2945     mass2 = 0.0;
2946     for ( G4int i = 0; i < numberOfInvolvedNucleons; ++i ) {
2947       G4Nucleon* aNucleon = involvedNucleons[i];
2948       if ( ! aNucleon ) continue;
2949       G4double x = aNucleon->Get4Momentum().pz() - delta;
2950       xSum -= x;
2951 
2952       if ( residualMassNumber == 0 ) {
2953         if ( x <= -eps || x > 1.0 + eps ) {
2954           success = false; 
2955           break;
2956         }
2957       } else {
2958         if ( x <= -eps || x > 1.0 + eps || xSum <= -eps || xSum > 1.0 + eps ) {
2959           success = false; 
2960           break;
2961         }
2962       } 
2963       x = std::min( 1.0, std::max(x, eps) );
2964 
2965       mass2 += sqr( aNucleon->Get4Momentum().e() ) / x;
2966 
2967       G4LorentzVector tmp( aNucleon->Get4Momentum().px(), aNucleon->Get4Momentum().py(), 
2968                            x, aNucleon->Get4Momentum().e() );
2969       aNucleon->SetMomentum( tmp );
2970     }
2971     if ( ! success ) continue;
2972     xSum = std::min( 1.0, std::max(xSum, eps) );
2973 
2974     if ( residualMassNumber > 0 ) mass2 += ( sqr( residualMass ) + pResidual.perp2() ) / xSum;
2975     
2976     #ifdef debugPutOnMassShell
2977     G4cout << "success: " << success << " Mt(GeV)= " 
2978      << std::sqrt( mass2 )/GeV << G4endl;
2979     #endif
2980 
2981   } while ( ( ! success ) &&
2982             ++loopCounter < maxNumberOfLoops );  /* Loop checking, 10.08.2015, A.Ribon */
2983   return ( loopCounter < maxNumberOfLoops );
2984 }
2985 
2986 
2987 //============================================================================
2988 
2989 G4bool G4FTFModel::
2990 CheckKinematics( const G4double sValue,                 // input parameter
2991                  const G4double sqrtS,                  // input parameter
2992                  const G4double projectileMass2,        // input parameter
2993                  const G4double targetMass2,            // input parameter
2994                  const G4double nucleusY,               // input parameter
2995                  const G4bool isProjectileNucleus,      // input parameter
2996                  const G4int numberOfInvolvedNucleons,  // input parameter 
2997                  G4Nucleon* involvedNucleons[],         // input parameter
2998                  G4double& targetWminus,                // output parameter
2999                  G4double& projectileWplus,             // output parameter
3000                  G4bool& success ) {                    // input & output parameter
3001 
3002   // This method, which is called only by PutOnMassShell, checks whether the
3003   // kinematics is acceptable or not.
3004   // This method assumes that all the parameters have been initialized by the caller;
3005   // notice that the input boolean parameter isProjectileNucleus is meant to be true
3006   // only in the case of nucleus or antinucleus projectile.
3007   // The action of this method consists in computing targetWminus and projectileWplus
3008   // and setting the parameter success to false in the case that the kinematics should
3009   // be rejeted.
3010 
3011   G4double decayMomentum2 = sqr( sValue ) + sqr( projectileMass2 ) + sqr( targetMass2 )
3012                             - 2.0*( sValue*( projectileMass2 + targetMass2 ) 
3013                                     + projectileMass2*targetMass2 );
3014   targetWminus = ( sValue - projectileMass2 + targetMass2 + std::sqrt( decayMomentum2 ) )
3015                  / 2.0 / sqrtS;
3016   projectileWplus = sqrtS - targetMass2/targetWminus;
3017   G4double projectilePz = projectileWplus/2.0 - projectileMass2/2.0/projectileWplus;
3018   G4double projectileE  = projectileWplus/2.0 + projectileMass2/2.0/projectileWplus;
3019   G4double projectileY  = 0.5 * G4Log( (projectileE + projectilePz)/
3020                                        (projectileE - projectilePz) );
3021   G4double targetPz = -targetWminus/2.0 + targetMass2/2.0/targetWminus;
3022   G4double targetE  =  targetWminus/2.0 + targetMass2/2.0/targetWminus;
3023   G4double targetY  = 0.5 * G4Log( (targetE + targetPz)/(targetE - targetPz) );
3024 
3025   #ifdef debugPutOnMassShell
3026   G4cout << "decayMomentum2 " << decayMomentum2 << G4endl 
3027          << "\t targetWminus projectileWplus " << targetWminus << " " << projectileWplus << G4endl
3028          << "\t projectileY targetY " << projectileY << " " << targetY << G4endl;
3029   if ( isProjectileNucleus ) {
3030     G4cout << "Order# of Wounded nucleon i, nucleon Y proj Y nuclY - proj Y " << G4endl;
3031   } else {
3032     G4cout << "Order# of Wounded nucleon i, nucleon Y targ Y nuclY - targ Y " << G4endl;
3033   }
3034   G4cout << G4endl;
3035   #endif
3036   
3037   for ( G4int i = 0; i < numberOfInvolvedNucleons; ++i ) {
3038     G4Nucleon* aNucleon = involvedNucleons[i];
3039     if ( ! aNucleon ) continue;
3040     G4LorentzVector tmp = aNucleon->Get4Momentum();
3041     G4double mt2 = sqr( tmp.x() ) + sqr( tmp.y() ) +
3042                    sqr( aNucleon->GetSplitableHadron()->GetDefinition()->GetPDGMass() );
3043     G4double x = tmp.z();
3044     G4double pz = -targetWminus*x/2.0 + mt2/(2.0*targetWminus*x);
3045     G4double e =   targetWminus*x/2.0 + mt2/(2.0*targetWminus*x);
3046     if ( isProjectileNucleus ) {
3047       pz = projectileWplus*x/2.0 - mt2/(2.0*projectileWplus*x);
3048       e =  projectileWplus*x/2.0 + mt2/(2.0*projectileWplus*x);
3049     }
3050     G4double nucleonY = 0.5 * G4Log( (e + pz)/(e - pz) ); 
3051 
3052     #ifdef debugPutOnMassShell
3053     if( isProjectileNucleus ) {
3054       G4cout << " " << i << " " << nucleonY << " " << projectileY << " " <<nucleonY - projectileY << G4endl;
3055     } else {
3056       G4cout << " " << i << " " << nucleonY << " " << targetY     << " " <<nucleonY - targetY << G4endl;
3057     }
3058     G4cout << G4endl;
3059     #endif
3060 
3061     if ( std::abs( nucleonY - nucleusY ) > 2  ||  
3062          ( isProjectileNucleus  &&  targetY > nucleonY )  ||
3063          ( ! isProjectileNucleus  &&  projectileY < nucleonY ) ) {
3064       success = false; 
3065       break;
3066     } 
3067   }
3068   return true;
3069 }  
3070 
3071   
3072 //============================================================================
3073 
3074 G4bool G4FTFModel::
3075 FinalizeKinematics( const G4double w,                            // input parameter
3076                     const G4bool isProjectileNucleus,            // input parameter
3077                     const G4LorentzRotation& boostFromCmsToLab,  // input parameter
3078                     const G4double residualMass,                 // input parameter
3079                     const G4int residualMassNumber,              // input parameter
3080                     const G4int numberOfInvolvedNucleons,        // input parameter 
3081                     G4Nucleon* involvedNucleons[],               // input & output parameter
3082               G4LorentzVector& residual4Momentum ) {       // output parameter
3083 
3084   // This method, which is called only by PutOnMassShell, finalizes the kinematics:
3085   // this method is called when we are sure that the sampling of the kinematics is
3086   // acceptable.
3087   // This method assumes that all the parameters have been initialized by the caller;
3088   // notice that the input boolean parameter isProjectileNucleus is meant to be true
3089   // only in the case of nucleus or antinucleus projectile: this information is needed
3090   // because the sign of pz (in the center-of-mass frame) in this case is opposite
3091   // with respect to the case of a normal hadron projectile.
3092   // The action of this method consists in modifying the momenta of the nucleons
3093   // (in the lab frame) and computing the residual 4-momentum (in the center-of-mass
3094   // frame).
3095 
3096   G4ThreeVector residual3Momentum( 0.0, 0.0, 1.0 );
3097 
3098   for ( G4int i = 0; i < numberOfInvolvedNucleons; ++i ) {
3099     G4Nucleon* aNucleon = involvedNucleons[i];
3100     if ( ! aNucleon ) continue;
3101     G4LorentzVector tmp = aNucleon->Get4Momentum();
3102     residual3Momentum -= tmp.vect();
3103     G4double mt2 = sqr( tmp.x() ) + sqr( tmp.y() ) +
3104                    sqr( aNucleon->GetSplitableHadron()->GetDefinition()->GetPDGMass() );
3105     G4double x = tmp.z();
3106     G4double pz = -w * x / 2.0  +  mt2 / ( 2.0 * w * x );
3107     G4double e  =  w * x / 2.0  +  mt2 / ( 2.0 * w * x );
3108     // Reverse the sign of pz in the case of nucleus or antinucleus projectile
3109     if ( isProjectileNucleus ) pz *= -1.0;
3110     tmp.setPz( pz ); 
3111     tmp.setE( e );
3112     tmp.transform( boostFromCmsToLab );
3113     aNucleon->SetMomentum( tmp );
3114     G4VSplitableHadron* splitableHadron = aNucleon->GetSplitableHadron();
3115     splitableHadron->Set4Momentum( tmp );
3116   }
3117 
3118   G4double residualMt2 = sqr( residualMass ) + sqr( residual3Momentum.x() )
3119                        + sqr( residual3Momentum.y() );
3120 
3121   #ifdef debugPutOnMassShell
3122   if ( isProjectileNucleus ) {
3123     G4cout << "Wminus Proj and residual3Momentum.z() " << w << " " << residual3Momentum.z() << G4endl;
3124   } else {
3125     G4cout << "Wplus  Targ and residual3Momentum.z() " << w << " " << residual3Momentum.z() << G4endl;
3126   }
3127   #endif
3128 
3129   G4double residualPz = 0.0;
3130   G4double residualE  = 0.0;
3131   if ( residualMassNumber != 0 ) {
3132     residualPz = -w * residual3Momentum.z() / 2.0 + 
3133                   residualMt2 / ( 2.0 * w * residual3Momentum.z() );
3134     residualE  =  w * residual3Momentum.z() / 2.0 + 
3135                   residualMt2 / ( 2.0 * w * residual3Momentum.z() );
3136     // Reverse the sign of residualPz in the case of nucleus or antinucleus projectile
3137     if ( isProjectileNucleus ) residualPz *= -1.0;
3138   }
3139 
3140   residual4Momentum.setPx( residual3Momentum.x() );
3141   residual4Momentum.setPy( residual3Momentum.y() );
3142   residual4Momentum.setPz( residualPz ); 
3143   residual4Momentum.setE( residualE );
3144 
3145   return true;
3146 }
3147 
3148   
3149 //============================================================================
3150 
3151 void G4FTFModel::ModelDescription( std::ostream& desc ) const {
3152   desc << "                 FTF (Fritiof) Model               \n" 
3153        << "The FTF model is based on the well-known FRITIOF   \n"
3154        << "model (B. Andersson et al., Nucl. Phys. B281, 289  \n"
3155        << "(1987)). Its first program implementation was given\n"
3156        << "by B. Nilsson-Almquist and E. Stenlund (Comp. Phys.\n"
3157        << "Comm. 43, 387 (1987)). The Fritiof model assumes   \n"
3158        << "that all hadron-hadron interactions are binary     \n"
3159        << "reactions, h_1+h_2->h_1'+h_2' where h_1' and h_2'  \n"
3160        << "are excited states of the hadrons with continuous  \n"
3161        << "mass spectra. The excited hadrons are considered as\n"
3162        << "QCD-strings, and the corresponding LUND-string     \n"
3163        << "fragmentation model is applied for a simulation of \n"
3164        << "their decays.                                      \n"
3165        << "   The Fritiof model assumes that in the course of \n"
3166        << "a hadron-nucleus interaction a string originated   \n"
3167        << "from the projectile can interact with various intra\n"
3168        << "nuclear nucleons and becomes into highly excited   \n"
3169        << "states. The probability of multiple interactions is\n"
3170        << "calculated in the Glauber approximation. A cascading\n"
3171        << "of secondary particles was neglected as a rule. Due\n"
3172        << "to these, the original Fritiof model fails to des- \n"
3173        << "cribe a nuclear destruction and slow particle spectra.\n"
3174        << "   In order to overcome the difficulties we enlarge\n"
3175        << "the model by the reggeon theory inspired model of  \n"
3176        << "nuclear desctruction (Kh. Abdel-Waged and V.V. Uzhi-\n"
3177        << "nsky, Phys. Atom. Nucl. 60, 828 (1997); Yad. Fiz. 60, 925\n"
3178        << "(1997)). Momenta of the nucleons ejected from a nuc-\n"
3179        << "leus in the reggeon cascading are sampled according\n"
3180        << "to a Fermi motion algorithm presented in (EMU-01   \n"
3181        << "Collaboration (M.I. Adamovich et al.) Zeit. fur Phys.\n"
3182        << "A358, 337 (1997)).                                 \n"
3183        << "   New features were also added to the Fritiof model\n"
3184        << "implemented in Geant4: a simulation of elastic had-\n"
3185        << "ron-nucleon scatterings, a simulation of binary \n"
3186        << "reactions like NN>NN* in hadron-nucleon interactions,\n"
3187        << "a separate simulation of single diffractive and non-\n"
3188        << " diffractive events. These allowed to describe after\n"
3189        << "model parameter tuning a wide set of experimental  \n"
3190        << "data.                                              \n";
3191 }
3192 
3193