Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/hadronic/models/parton_string/diffraction/src/G4DiffractiveExcitation.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 implemetation file
 31 //
 32 //      ---------------- G4DiffractiveExcitation --------------
 33 //             by Gunter Folger, October 1998.
 34 //        diffractive Excitation used by strings models
 35 //             Take a projectile and a target
 36 //             excite the projectile and target
 37 //  Essential changed by V. Uzhinsky in November - December 2006
 38 //  in order to put it in a correspondence with original FRITIOF
 39 //  model. Variant of FRITIOF with nucleon de-excitation is implemented.
 40 //  Other changes by V.Uzhinsky in May 2007 were introduced to fit
 41 //  meson-nucleon interactions. Additional changes by V. Uzhinsky
 42 //  were introduced in December 2006. They treat diffraction dissociation
 43 //  processes more exactly.
 44 //  Correct treatment of the diffraction dissociation - 2012, V. Uzhinsky
 45 //  Mass distributions for resonances and uu-diquark suppression in protons,
 46 //  and dd-diquarks suppression in neutrons were introduced by V. Uzhinsky, 2014
 47 // ---------------------------------------------------------------------
 48 
 49 #include "globals.hh"
 50 #include "Randomize.hh"
 51 #include "G4PhysicalConstants.hh"
 52 #include "G4SystemOfUnits.hh"
 53 
 54 #include "G4DiffractiveExcitation.hh"
 55 #include "G4FTFParameters.hh"
 56 #include "G4ElasticHNScattering.hh"
 57 
 58 #include "G4RotationMatrix.hh"
 59 #include "G4ParticleDefinition.hh" 
 60 #include "G4ParticleTable.hh"
 61 #include "G4SampleResonance.hh"
 62 #include "G4VSplitableHadron.hh"
 63 #include "G4ExcitedString.hh"
 64 #include "G4Neutron.hh"
 65 
 66 #include "G4Exp.hh"
 67 #include "G4Log.hh"
 68 #include "G4Pow.hh"
 69 
 70 //#include "G4ios.hh"
 71 
 72 //============================================================================
 73 
 74 //#define debugFTFexcitation
 75 //#define debug_heavyHadrons
 76 
 77 //============================================================================
 78 
 79 G4DiffractiveExcitation::G4DiffractiveExcitation() {}
 80 
 81 
 82 //============================================================================
 83 
 84 G4DiffractiveExcitation::~G4DiffractiveExcitation() {}
 85 
 86 
 87 //============================================================================
 88 
 89 G4bool G4DiffractiveExcitation::ExciteParticipants( G4VSplitableHadron*    projectile, 
 90                                                     G4VSplitableHadron*    target,
 91                                                     G4FTFParameters*       theParameters,
 92                                                     G4ElasticHNScattering* theElastic ) const {
 93 
 94   #ifdef debugFTFexcitation
 95   G4cout << G4endl << "FTF ExciteParticipants --------------" << G4endl;
 96   #endif
 97 
 98   CommonVariables common;
 99 
100   // Projectile parameters
101   common.Pprojectile = projectile->Get4Momentum();
102   if ( common.Pprojectile.z() < 0.0 ) return false;
103   common.ProjectilePDGcode = projectile->GetDefinition()->GetPDGEncoding();
104   common.absProjectilePDGcode = std::abs( common.ProjectilePDGcode );
105   common.M0projectile = projectile->GetDefinition()->GetPDGMass();  //Uzhi Aug.2019  common.Pprojectile.mag();
106   G4double ProjectileRapidity = common.Pprojectile.rapidity();
107 
108   // Target parameters
109   common.Ptarget = target->Get4Momentum();
110   common.TargetPDGcode = target->GetDefinition()->GetPDGEncoding();
111   common.absTargetPDGcode = std::abs( common.TargetPDGcode );
112   common.M0target = target->GetDefinition()->GetPDGMass();  //Uzhi Aug.2019  common.Ptarget.mag();
113   G4double TargetRapidity = common.Ptarget.rapidity();
114 
115   // Kinematical properties of the interactions
116   G4LorentzVector Psum = common.Pprojectile + common.Ptarget;  // 4-momentum in Lab.
117   common.S = Psum.mag2();
118   common.SqrtS = std::sqrt( common.S ); 
119 
120   // Check off-shellness of the participants
121   G4bool toBePutOnMassShell = true;  //Uzhi Aug.2019  false;
122   common.MminProjectile = common.BrW.GetMinimumMass( projectile->GetDefinition() );
123   /* Uzhi Aug.2019
124   if ( common.M0projectile < common.MminProjectile ) {
125     toBePutOnMassShell = true;
126     common.M0projectile = common.BrW.SampleMass( projectile->GetDefinition(), 
127                                                  projectile->GetDefinition()->GetPDGMass() 
128                                                  + 5.0*projectile->GetDefinition()->GetPDGWidth() );
129   }
130   */
131   common.M0projectile2 = common.M0projectile * common.M0projectile;
132   common.ProjectileDiffStateMinMass    = theParameters->GetProjMinDiffMass();
133   common.ProjectileNonDiffStateMinMass = theParameters->GetProjMinNonDiffMass();
134   if ( common.M0projectile > common.ProjectileDiffStateMinMass ) {
135     common.ProjectileDiffStateMinMass    = common.MminProjectile + 220.0*MeV;  //Uzhi Aug.2019  common.M0projectile + 220.0*MeV;
136     common.ProjectileNonDiffStateMinMass = common.MminProjectile + 220.0*MeV;  //Uzhi Aug.2019  common.M0projectile + 220.0*MeV;
137     if ( common.absProjectilePDGcode > 3000 ) {  // Strange baryon
138       common.ProjectileDiffStateMinMass    += 140.0*MeV;
139       common.ProjectileNonDiffStateMinMass += 140.0*MeV;
140     }
141   }
142   common.MminTarget = common.BrW.GetMinimumMass( target->GetDefinition() );
143   /* Uzhi Aug.2019
144   if ( common.M0target < common.MminTarget ) {
145     toBePutOnMassShell = true;
146     common.M0target = common.BrW.SampleMass( target->GetDefinition(),
147                                              target->GetDefinition()->GetPDGMass() 
148                                              + 5.0*target->GetDefinition()->GetPDGWidth() );
149   }
150   */
151   common.M0target2 = common.M0target * common.M0target;
152   common.TargetDiffStateMinMass    = theParameters->GetTarMinDiffMass();
153   common.TargetNonDiffStateMinMass = theParameters->GetTarMinNonDiffMass();
154   if ( common.M0target > common.TargetDiffStateMinMass ) {
155     common.TargetDiffStateMinMass    = common.MminTarget + 220.0*MeV;  //Uzhi Aug.2019  common.M0target + 220.0*MeV;
156     common.TargetNonDiffStateMinMass = common.MminTarget + 220.0*MeV;  //Uzhi Aug.2019  common.M0target + 220.0*MeV;
157     if ( common.absTargetPDGcode > 3000 ) {  // Strange baryon
158       common.TargetDiffStateMinMass    += 140.0*MeV;
159       common.TargetNonDiffStateMinMass += 140.0*MeV;
160     }
161   };
162   #ifdef debugFTFexcitation
163   G4cout << "Proj Targ PDGcodes " << common.ProjectilePDGcode << " " << common.TargetPDGcode << G4endl
164          << "Mprojectile  Y " << common.Pprojectile.mag() << " " << ProjectileRapidity << G4endl        // Uzhi Aug.2019
165          << "M0projectile Y " << common.M0projectile << " " << ProjectileRapidity << G4endl;
166   G4cout << "Mtarget      Y " << common.Ptarget.mag() << " " << TargetRapidity << G4endl                // Uzhi Aug.2019
167          << "M0target     Y " << common.M0target << " " << TargetRapidity << G4endl;
168   G4cout << "Pproj " << common.Pprojectile << G4endl << "Ptarget " << common.Ptarget << G4endl;
169   #endif
170 
171   // Transform momenta to cms and then rotate parallel to z axis;
172   common.toCms = G4LorentzRotation( -1 * Psum.boostVector() );
173   G4LorentzVector Ptmp = common.toCms * common.Pprojectile;
174   if ( Ptmp.pz() <= 0.0 ) return false;  // "String" moving backwards in  CMS, abort collision!
175   common.toCms.rotateZ( -1*Ptmp.phi() );
176   common.toCms.rotateY( -1*Ptmp.theta() );
177   common.toLab = common.toCms.inverse();
178   common.Pprojectile.transform( common.toCms );
179   common.Ptarget.transform( common.toCms );
180 
181   G4double SumMasses = common.M0projectile + common.M0target;  // + 220.0*MeV;
182   #ifdef debugFTFexcitation
183   G4cout << "SqrtS     " << common.SqrtS << G4endl << "M0pr M0tr SumM " << common.M0projectile 
184          << " " << common.M0target << " " << SumMasses << G4endl;
185   #endif
186   if ( common.SqrtS < SumMasses ) return false;  // The model cannot work at low energy
187 
188   common.PZcms2 = ( sqr( common.S ) + sqr( common.M0projectile2 ) + sqr( common.M0target2 )
189                     - 2.0 * ( common.S * ( common.M0projectile2 + common.M0target2 ) 
190                               + common.M0projectile2 * common.M0target2 ) ) / 4.0 / common.S;
191   #ifdef debugFTFexcitation
192   G4cout << "PZcms2 after toBePutOnMassShell " << common.PZcms2 << G4endl;
193   #endif
194   if ( common.PZcms2 < 0.0 ) return false;  // It can be in an interaction with off-shell nuclear nucleon
195 
196   common.PZcms = std::sqrt( common.PZcms2 );
197   if ( toBePutOnMassShell ) {
198     if ( common.Pprojectile.z() > 0.0 ) {
199       common.Pprojectile.setPz(  common.PZcms );
200       common.Ptarget.setPz(     -common.PZcms );
201     } else {
202       common.Pprojectile.setPz( -common.PZcms );
203       common.Ptarget.setPz(      common.PZcms );
204     }
205     common.Pprojectile.setE( std::sqrt( common.M0projectile2 
206                                         + common.Pprojectile.x() * common.Pprojectile.x() 
207                                         + common.Pprojectile.y() * common.Pprojectile.y() 
208                                         + common.PZcms2 ) );
209     common.Ptarget.setE( std::sqrt( common.M0target2 
210                                     + common.Ptarget.x() * common.Ptarget.x()
211                                     + common.Ptarget.y() * common.Ptarget.y() 
212                                     + common.PZcms2 ) );
213   }
214   #ifdef debugFTFexcitation
215   G4cout << "Start --------------------" << G4endl << "Proj M0 Mdif Mndif " << common.M0projectile
216          << " " << common.ProjectileDiffStateMinMass << "  " << common.ProjectileNonDiffStateMinMass
217          << G4endl
218          << "Targ M0 Mdif Mndif " << common.M0target << " " << common.TargetDiffStateMinMass 
219          << " " << common.TargetNonDiffStateMinMass << G4endl << "SqrtS " << common.SqrtS << G4endl
220          << "Proj CMS " << common.Pprojectile << G4endl << "Targ CMS " << common.Ptarget << G4endl;
221   #endif
222 
223   // Check for possible quark exchange
224   ProjectileRapidity = common.Pprojectile.rapidity();
225   TargetRapidity = common.Ptarget.rapidity();
226   G4double QeNoExc = theParameters->GetProcProb( 0, ProjectileRapidity - TargetRapidity );
227   G4double QeExc   = theParameters->GetProcProb( 1, ProjectileRapidity - TargetRapidity ) *
228                      theParameters->GetProcProb( 4, ProjectileRapidity - TargetRapidity );
229   common.ProbProjectileDiffraction = 
230     theParameters->GetProcProb( 2, ProjectileRapidity - TargetRapidity );
231   common.ProbTargetDiffraction = 
232     theParameters->GetProcProb( 3, ProjectileRapidity - TargetRapidity );
233   common.ProbOfDiffraction = common.ProbProjectileDiffraction + common.ProbTargetDiffraction;
234   #ifdef debugFTFexcitation
235   G4cout << "Proc Probs " << QeNoExc << " " << QeExc << " " 
236          << common.ProbProjectileDiffraction << " " << common.ProbTargetDiffraction << G4endl 
237          << "ProjectileRapidity " << ProjectileRapidity << G4endl;
238   #endif
239 
240   if ( QeNoExc + QeExc + common.ProbProjectileDiffraction + common.ProbTargetDiffraction > 1.0 ) {
241     QeNoExc = 1.0 - QeExc - common.ProbProjectileDiffraction - common.ProbTargetDiffraction;
242   }
243   if ( QeExc + QeNoExc != 0.0 ) {
244     common.ProbExc = QeExc / ( QeExc + QeNoExc );
245   }
246   if ( 1.0 - QeExc - QeNoExc > 0.0 ) { 
247     common.ProbProjectileDiffraction /= ( 1.0 - QeExc - QeNoExc );
248     common.ProbTargetDiffraction     /= ( 1.0 - QeExc - QeNoExc );
249   }
250   #ifdef debugFTFexcitation
251   G4cout << "Proc Probs " << QeNoExc << " " << QeExc << " " 
252          << common.ProbProjectileDiffraction << " " << common.ProbTargetDiffraction << G4endl 
253          << "ProjectileRapidity " << ProjectileRapidity << G4endl;
254   #endif
255 
256   // Try out charge exchange
257   G4int returnCode = 1;
258   if ( G4UniformRand() < QeExc + QeNoExc ) {
259     returnCode = ExciteParticipants_doChargeExchange( projectile, target, theParameters, 
260                                                       theElastic, common );
261   }
262 
263   G4bool returnResult = false;
264   if ( returnCode == 0 ) {
265     returnResult = true;  // Successfully ended: no need of extra work
266   } else if ( returnCode == 1 ) {
267 
268     common.ProbOfDiffraction = common.ProbProjectileDiffraction + common.ProbTargetDiffraction;
269     #ifdef debugFTFexcitation
270     G4cout << "Excitation --------------------" << G4endl
271            << "Proj M0 MdMin MndMin " << common.M0projectile << " " 
272            << common.ProjectileDiffStateMinMass << "  " << common.ProjectileNonDiffStateMinMass
273            << G4endl
274            << "Targ M0 MdMin MndMin " << common.M0target << " " << common.TargetDiffStateMinMass
275            << " " << common.TargetNonDiffStateMinMass << G4endl << "SqrtS " << common.SqrtS 
276            << G4endl
277            << "Prob: ProjDiff TargDiff + Sum " << common.ProbProjectileDiffraction << " " 
278            << common.ProbTargetDiffraction << " " << common.ProbOfDiffraction << G4endl;
279     #endif
280     if ( common.ProbOfDiffraction != 0.0 ) {
281       common.ProbProjectileDiffraction /= common.ProbOfDiffraction;
282     } else {
283       common.ProbProjectileDiffraction = 0.0;
284     }
285     #ifdef debugFTFexcitation
286     G4cout << "Prob: ProjDiff TargDiff + Sum " << common.ProbProjectileDiffraction << " " 
287            << common.ProbTargetDiffraction << " " << common.ProbOfDiffraction << G4endl;
288     #endif
289     common.ProjectileDiffStateMinMass2    = sqr( common.ProjectileDiffStateMinMass );
290     common.ProjectileNonDiffStateMinMass2 = sqr( common.ProjectileNonDiffStateMinMass );
291     common.TargetDiffStateMinMass2        = sqr( common.TargetDiffStateMinMass );
292     common.TargetNonDiffStateMinMass2     = sqr( common.TargetNonDiffStateMinMass );
293     // Choose between diffraction and non-diffraction process
294     if ( G4UniformRand() < common.ProbOfDiffraction ) {
295       
296       returnResult = ExciteParticipants_doDiffraction( projectile, target, theParameters, common );
297       
298     } else {
299       
300       returnResult = ExciteParticipants_doNonDiffraction( projectile, target, theParameters, common );
301       
302     }
303     if ( returnResult ) {
304       common.Pprojectile += common.Qmomentum;
305       common.Ptarget     -= common.Qmomentum;
306       // Transform back and update SplitableHadron Participant.
307       common.Pprojectile.transform( common.toLab );
308       common.Ptarget.transform( common.toLab );
309       #ifdef debugFTFexcitation
310       G4cout << "Mproj " << common.Pprojectile.mag() << G4endl << "Mtarg " << common.Ptarget.mag()
311              << G4endl;
312       #endif
313       projectile->Set4Momentum( common.Pprojectile );
314       target->Set4Momentum( common.Ptarget );
315       projectile->IncrementCollisionCount( 1 );
316       target->IncrementCollisionCount( 1 );
317     }
318   }
319 
320   return returnResult;
321 }
322 
323 //-----------------------------------------------------------------------------
324 
325 G4int G4DiffractiveExcitation::
326 ExciteParticipants_doChargeExchange( G4VSplitableHadron*    projectile, 
327                                      G4VSplitableHadron*    target,
328                                      G4FTFParameters*       theParameters,
329                                      G4ElasticHNScattering* theElastic,
330                                      G4DiffractiveExcitation::CommonVariables& common ) const {
331   // First of the three utility methods used only by ExciteParticipants: 
332   // it does the sampling for the charge-exchange case.
333   // This method returns an integer code - instead of a boolean, with the following meaning:
334   //   "0" : successfully ended and nothing else needs to be done;
335   //   "1" : successfully completed, but the work needs to be continued;
336   //  "99" : unsuccessfully ended, nothing else can be done.
337   G4int returnCode = 99;
338 
339   G4double DeltaProbAtQuarkExchange = theParameters->GetDeltaProbAtQuarkExchange();
340   G4ParticleDefinition* TestParticle = 0;
341   G4double MtestPr = 0.0, MtestTr = 0.0;
342 
343   #ifdef debugFTFexcitation
344   G4cout << "Q exchange --------------------------" << G4endl;
345   #endif
346 
347   // The target hadron is always a nucleon (i.e. either a proton or a neutron,
348   // never an antinucleon), therefore only a quark (not an antiquark) can be
349   // exchanged between the projectile hadron and the target hadron (otherwise
350   // we could get a quark-quark-antiquark system which cannot be a bound state).
351   // This implies that any projectile meson or anti-meson - given that it has
352   // a constituent quark in all cases - can have charge exchange with a target
353   // hadron. Instead, any projectile anti-baryon can never have charge exchange
354   // with a target hadron (because it has only constituent anti-quarks);
355   // projectile baryons, instead can have charge exchange with a target hadron.
356   
357   G4int NewProjCode = 0, NewTargCode = 0, ProjQ1 = 0, ProjQ2 = 0, ProjQ3  = 0;
358   //  Projectile unpacking
359   if ( common.absProjectilePDGcode < 1000 ) {  // projectile is meson 
360     UnpackMeson(  common.ProjectilePDGcode, ProjQ1, ProjQ2 );  
361   } else {                                     // projectile is baryon
362     UnpackBaryon( common.ProjectilePDGcode, ProjQ1, ProjQ2, ProjQ3 );
363   }
364   //  Target unpacking
365   G4int TargQ1 = 0, TargQ2 = 0, TargQ3 = 0;
366   UnpackBaryon( common.TargetPDGcode, TargQ1, TargQ2, TargQ3 ); 
367   #ifdef debugFTFexcitation
368   G4cout << "Proj Quarks " << ProjQ1 << " " << ProjQ2 << " " << ProjQ3 << G4endl
369          << "Targ Quarks " << TargQ1 << " " << TargQ2 << " " << TargQ3 << G4endl;
370   #endif
371   
372   // Sampling of exchanged quarks
373   G4int ProjExchangeQ = 0, TargExchangeQ = 0;
374   if ( common.absProjectilePDGcode < 1000 ) {  // projectile is meson 
375 
376     G4bool isProjQ1Quark = false;
377     ProjExchangeQ = ProjQ2;
378     if ( ProjQ1 > 0 ) {  // ProjQ1 is a quark
379       isProjQ1Quark = true;
380       ProjExchangeQ = ProjQ1;
381     }
382     // Exchange of non-identical quarks is allowed
383     G4int NpossibleStates = 0;
384     if ( ProjExchangeQ != TargQ1 ) NpossibleStates++;
385     if ( ProjExchangeQ != TargQ2 ) NpossibleStates++;
386     if ( ProjExchangeQ != TargQ3 ) NpossibleStates++;  
387     G4int Nsampled = (G4int)G4RandFlat::shootInt( G4long( NpossibleStates ) )+1;
388     NpossibleStates = 0;
389     if ( ProjExchangeQ != TargQ1 ) {
390       if ( ++NpossibleStates == Nsampled ) {
391         TargExchangeQ = TargQ1; TargQ1 = ProjExchangeQ; 
392         isProjQ1Quark ? ProjQ1 = TargExchangeQ : ProjQ2 = TargExchangeQ;
393       }
394     }
395     if ( ProjExchangeQ != TargQ2 ) {
396       if ( ++NpossibleStates == Nsampled ) {
397         TargExchangeQ = TargQ2; TargQ2 = ProjExchangeQ;
398         isProjQ1Quark ? ProjQ1 = TargExchangeQ : ProjQ2 = TargExchangeQ;
399       }
400     }
401     if ( ProjExchangeQ != TargQ3 ) {
402       if ( ++NpossibleStates == Nsampled ) {
403         TargExchangeQ = TargQ3; TargQ3 = ProjExchangeQ;
404         isProjQ1Quark ? ProjQ1 = TargExchangeQ : ProjQ2 = TargExchangeQ;
405       }
406     }
407     #ifdef debugFTFexcitation
408     G4cout << "Exchanged Qs in Pr Tr " << ProjExchangeQ << " " << TargExchangeQ << G4endl;
409     #endif
410 
411     G4int aProjQ1 = std::abs( ProjQ1 ), aProjQ2 = std::abs( ProjQ2 );
412     G4bool ProjExcited = false;
413     const G4int maxNumberOfAttempts = 50;
414     G4int attempts = 0;
415     while ( attempts++ < maxNumberOfAttempts ) {  /* Loop checking, 10.08.2015, A.Ribon */
416 
417       // Determination of a new projectile ID which satisfies energy-momentum conservation
418       G4double ProbSpin0 = 0.5;
419       G4double Ksi = G4UniformRand();
420       if ( aProjQ1 == aProjQ2 ) {
421         if ( G4UniformRand() < ProbSpin0 ) {  // Meson spin = 0 (pseudo-scalar)
422           if ( aProjQ1 < 3 ) {
423             NewProjCode = 111;                // pi0
424             if ( Ksi < 0.5 ) {
425               NewProjCode = 221;              // eta
426               if ( Ksi < 0.25 ) {
427                 NewProjCode = 331;            // eta'
428               }
429             } 
430           } else if ( aProjQ1 == 3 ) {
431               NewProjCode = 221;              // eta
432               if ( Ksi < 0.5 ) {
433                 NewProjCode = 331;            // eta'
434               }
435           } else if ( aProjQ1 == 4 ) {
436       NewProjCode = 441;                // eta_c(1S)
437     } else if ( aProjQ1 == 5 ) {
438       NewProjCode = 551;                // eta_b(1S)
439     }
440         } else {                              // Meson spin = 1 (vector meson)
441           if ( aProjQ1 < 3 ) {
442             NewProjCode = 113;                // rho0
443             if ( Ksi < 0.5 ) {
444               NewProjCode = 223;              // omega
445             } 
446           } else if ( aProjQ1 == 3 ) {
447             NewProjCode = 333;                // phi
448           } else if ( aProjQ1 == 4 ) {
449       NewProjCode = 443;                // J/psi(1S)
450     } else if ( aProjQ1 == 5 ) {
451       NewProjCode = 553;                // Upsilon(1S)
452     }
453         }
454       } else {
455         if ( aProjQ1 > aProjQ2 ) {
456           NewProjCode = aProjQ1*100 + aProjQ2*10 + 1;
457         } else {
458           NewProjCode = aProjQ2*100 + aProjQ1*10 + 1;
459         }
460       }
461       #ifdef debugFTFexcitation
462       G4cout << "NewProjCode " << NewProjCode << G4endl;
463       #endif
464       // Decide (with 50% probability) whether the projectile hadrons is excited,
465       // but not in the case of charmed and bottom hadrons (because in Geant4
466       // there are no excited charmed and bottom states).
467       ProjExcited = false;
468       if ( aProjQ1 <= 3  &&  aProjQ2 <= 3  &&  G4UniformRand() < 0.5 ) {
469         NewProjCode += 2;  // Excited meson (J=1 -> 2*J+1=2+1=3, last digit of the PDG code) 
470         ProjExcited = true;
471       }
472 
473       // So far we have used the absolute values of the PDG codes of the two constituent quarks:
474       // now look at their signed values to set properly the signed of the meson's PDG code.
475       G4int value = ProjQ1, absValue = aProjQ1, Qquarks = 0;
476       for ( G4int iQ = 0; iQ < 2; ++iQ ) {  // 0 : first quark; 1 : second quark
477         if ( iQ == 1 ) {
478           value = ProjQ2; absValue = aProjQ2;
479         }
480         if ( absValue == 2  ||  absValue == 4 ) {  // u or c
481           Qquarks += 2*value/absValue;  // u, c : positively charged +2 (e/3 unit)
482         } else {
483           Qquarks -= value/absValue;    // d, s, b : negatively charged -1 (e/3 unit)
484         }
485       }
486       // If Qquarks is positive, the sign of NewProjCode is fine.
487       // If Qquarks is negative, then the sign of NewProjCode needs to be reversed.
488       // If Qquarks is zero, then we need to distinguish between 3 cases:
489       // 1. If aProjQ1 and aProjQ2 are the same, then the sign of NewProjCode is fine
490       //    (because the antiparticle is the same as the particle, e.g. eta, eta').
491       // 2. If aProjQ1 and aProjQ2 are not the same, given that Qquarks is zero,
492       //    we have only two possibilities:
493       //    a. aProjQ1 and aProjQ2 are two different down-type quarks, i.e.
494       //       (s,d) or (b,d), or (b,s). In this case, the sign of NewProjCode
495       //       is fine (because the heaviest of the two down-type quarks has
496       //       to be anti-quark belonging to the initial projectile, which
497       //       implies a meson with positive PDG code, e.g. B0 (bbar,d), Bs (bbar,s).
498       //    b. aProjQ1 and aProjQ2 are two different up-type quarks, i.e. (u,c).
499       //       The heaviest of the two (c) has to be an anti-quark (cbar) left
500       //       in the projectile, therefore the sign of NewProjCode needs to be
501       //       reverse: 421 -> -421 anti_D0 (cbar,u)
502       if ( Qquarks < 0  || ( Qquarks == 0  &&  aProjQ1 != aProjQ2  &&  aProjQ1%2 == 0 ) ) {
503   NewProjCode *= -1;
504       }
505       #ifdef debugFTFexcitation
506       G4cout << "NewProjCode +2 or 0 " << NewProjCode << G4endl;
507       G4cout<<"+++++++++++++++++++++++++++++++++++++++"<<G4endl;
508       G4cout<<ProjQ1<<" "<<ProjQ2<<" "<<Qquarks<<G4endl;
509       G4cout<<"+++++++++++++++++++++++++++++++++++++++"<<G4endl;
510       #endif
511 
512       // Proj 
513       TestParticle = G4ParticleTable::GetParticleTable()->FindParticle( NewProjCode );
514       if ( ! TestParticle ) continue;
515       common.MminProjectile = common.BrW.GetMinimumMass( TestParticle );
516       if ( common.SqrtS - common.M0target < common.MminProjectile ) continue;
517       MtestPr = common.BrW.SampleMass( TestParticle, TestParticle->GetPDGMass() 
518                                                      + 5.0*TestParticle->GetPDGWidth() );
519       #ifdef debugFTFexcitation
520       G4cout << "TestParticle Name " << NewProjCode << " " << TestParticle->GetParticleName()
521              << G4endl
522              << "MtestPart MtestPart0 "<<MtestPr<<" "<<TestParticle->GetPDGMass()<<G4endl
523              << "M0projectile projectile PDGMass " << common.M0projectile << " " 
524              << projectile->GetDefinition()->GetPDGMass() << G4endl;
525       #endif
526 
527       // Targ
528       NewTargCode = NewNucleonId( TargQ1, TargQ2, TargQ3 );
529       #ifdef debugFTFexcitation
530       G4cout << "New TrQ " << TargQ1 << " " << TargQ2 << " " << TargQ3 << G4endl
531              << "NewTargCode " << NewTargCode << G4endl;
532       #endif
533       
534       // If the target has not heavy (charm or bottom) constituent quark,
535       // see whether a Delta isobar can be created.
536       if ( TargQ1 <= 3  &&  TargQ2 <= 3  &&  TargQ3 <= 3 ) {
537         if ( TargQ1 != TargQ2  &&  TargQ1 != TargQ3  &&  TargQ2 != TargQ3 ) {  // Lambda or Sigma0 ?
538           if ( G4UniformRand() < 0.5 ) {
539             NewTargCode += 2;
540           } else if ( G4UniformRand() < 0.75 ) {
541             NewTargCode = 3122;  // Lambda
542           }
543         } else if ( TargQ1 == TargQ2  &&  TargQ1 == TargQ3 ) {
544           NewTargCode += 2; ProjExcited = true;                         // Create Delta isobar
545         } else if ( target->GetDefinition()->GetPDGiIsospin() == 3 ) {  // Delta was the target
546           if ( G4UniformRand() > DeltaProbAtQuarkExchange ) {
547             NewTargCode += 2; ProjExcited = true;
548           }
549         } else if ( ! ProjExcited  &&
550                     G4UniformRand() < DeltaProbAtQuarkExchange  &&      // Nucleon was the target
551                     common.SqrtS > common.M0projectile +                // Delta mass
552                          G4ParticleTable::GetParticleTable()->FindParticle( 2224 )->GetPDGMass() ) {
553           NewTargCode += 2;  // Create Delta isobar
554         }
555       }
556 
557       // Protection against:
558       // - Lambda* (i.e. excited Lambda state)         NOT existing in PDG ,   ->  Lambda
559       // - Sigma*  (i.e. excited Sigma hyperon states) NOT existing in Geant4  ->  Sigma
560       // - Xi*     (i.e. excited Xi hyperon states)    NOT existing in Geant4  ->  Xi
561       if ( NewTargCode == 3124  ||   // Lambda* NOT existing in PDG !
562      NewTargCode == 3224  ||   // Sigma*+ NOT existing in Geant4
563      NewTargCode == 3214  ||   // Sigma*0 NOT existing in Geant4
564      NewTargCode == 3114  ||   // Sigma*- NOT existing in Geant4
565      NewTargCode == 3324  ||   // Xi*0    NOT existing in Geant4
566      NewTargCode == 3314  ) {  // Xi*-    NOT existing in Geant4
567   //G4cout << "G4DiffractiveExcitation::ExciteParticipants_doChargeExchange INEXISTING TARGET PDGcode="
568   //       << NewTargCode << G4endl;
569   NewTargCode -= 2;  // Corresponding ground-state hyperon
570       }
571       
572       // Special treatment for charmed and bottom baryons : in Geant4 there are no Xi_c' and Xi_b'
573       // so we need to transform them by hand to Xi_c and Xi_b, respectively.
574       #ifdef debug_heavyHadrons
575       G4int initialNewTargCode = NewTargCode;
576       #endif
577       if      ( NewTargCode == 4322 ) NewTargCode = 4232;  // Xi_c'+  ->  Xi_c+
578       else if ( NewTargCode == 4312 ) NewTargCode = 4132;  // Xi_c'0  ->  Xi_c0
579       else if ( NewTargCode == 5312 ) NewTargCode = 5132;  // Xi_b'-  ->  Xi_b-
580       else if ( NewTargCode == 5322 ) NewTargCode = 5232;  // Xi_b'0  ->  Xi_b0
581       #ifdef debug_heavyHadrons
582       if ( NewTargCode != initialNewTargCode ) {
583   G4cout << "G4DiffractiveExcitation::ExciteParticipants_doChargeExchange : forcing (inexisting in G4)" << G4endl
584          << "\t target heavy baryon with pdgCode=" << initialNewTargCode
585          << " into pdgCode=" << NewTargCode << G4endl;
586       }
587       #endif
588       
589       TestParticle = G4ParticleTable::GetParticleTable()->FindParticle( NewTargCode );
590       if ( ! TestParticle ) continue;
591       #ifdef debugFTFexcitation
592       G4cout << "New targ " << NewTargCode << " " << TestParticle->GetParticleName() << G4endl;
593       #endif
594       common.MminTarget = common.BrW.GetMinimumMass( TestParticle );
595       if ( common.SqrtS - MtestPr < common.MminTarget ) continue;
596       MtestTr = common.BrW.SampleMass( TestParticle, TestParticle->GetPDGMass() 
597                                                      + 5.0*TestParticle->GetPDGWidth() );
598       if ( common.SqrtS > MtestPr + MtestTr ) break;
599 
600     }  // End of while loop
601     if ( attempts >= maxNumberOfAttempts ) return returnCode;  // unsuccessfully ended, nothing else can be done
602 
603     if ( MtestPr >= common.Pprojectile.mag()  ||  projectile->GetStatus() != 0 ) { 
604       common.M0projectile = MtestPr;
605     }
606     #ifdef debugFTFexcitation
607     G4cout << "M0projectile After check " << common.M0projectile << G4endl;
608     #endif
609     common.M0projectile2 = common.M0projectile * common.M0projectile;
610     common.ProjectileDiffStateMinMass    = common.M0projectile + 220.0*MeV;  // 220 MeV=m_pi+80 MeV 
611     common.ProjectileNonDiffStateMinMass = common.M0projectile + 220.0*MeV;  // 220 MeV=m_pi+80 MeV
612     if ( MtestTr >= common.Ptarget.mag()  ||  target->GetStatus() != 0 ) {
613       common.M0target = MtestTr;
614     }
615     common.M0target2 = common.M0target * common.M0target;
616     #ifdef debugFTFexcitation
617     G4cout << "New targ M0 M0^2 " << common.M0target << " " << common.M0target2 << G4endl;
618     #endif
619     common.TargetDiffStateMinMass    = common.M0target + 220.0*MeV;          // 220 MeV=m_pi+80 MeV;    
620     common.TargetNonDiffStateMinMass = common.M0target + 220.0*MeV;          // 220 MeV=m_pi+80 MeV; 
621 
622   } else {  // of the if ( common.absProjectilePDGcode < 1000 ) ; the projectile is baryon now
623 
624     // If it is a projectile anti-baryon, no quark exchange is possible with a target hadron,
625     // therefore returns immediately 1 (which means "successfully completed, but the work
626     // needs to be continued").
627     if ( common.ProjectilePDGcode < 0 ) return 1;
628 
629     // Choose randomly, with equal probability, whether to consider the quarks of the 
630     // projectile or target hadron for selecting the flavour of the exchanged quark.
631     G4bool isProjectileExchangedQ = false;
632     G4int firstQ      = TargQ1, secondQ      = TargQ2, thirdQ      = TargQ3;
633     G4int otherFirstQ = ProjQ1, otherSecondQ = ProjQ2, otherThirdQ = ProjQ3;
634     if ( G4UniformRand() < 0.5 ) {
635       isProjectileExchangedQ = true;
636       firstQ      = ProjQ1; secondQ      = ProjQ2; thirdQ      = ProjQ3;
637       otherFirstQ = TargQ1; otherSecondQ = TargQ2; otherThirdQ = TargQ3;
638     }
639     // Choose randomly, with equal probability, which of the three quarks of the
640     // selected (projectile or target) hadron is the exhanged quark.
641     G4int exchangedQ = 0;
642     G4double Ksi = G4UniformRand();
643     if ( Ksi < 0.333333 ) {
644       exchangedQ = firstQ;
645     } else if ( 0.333333 <= Ksi  &&  Ksi < 0.666667 ) {
646       exchangedQ = secondQ;
647     } else {
648       exchangedQ = thirdQ;
649     }
650     #ifdef debugFTFexcitation
651     G4cout << "Exchange Qs isProjectile Q " << isProjectileExchangedQ << " " << exchangedQ << " ";
652     #endif
653     // The exchanged quarks (one of the projectile hadron and one of the target hadron)
654     // are always accepted if they have different flavour, else (i.e. when they have the
655     // same flavour) they are accepted only with a specified probability.
656     G4double probSame = theParameters->GetProbOfSameQuarkExchange();
657     const G4int MaxCount = 100;
658     G4int count = 0, otherExchangedQ = 0; 
659     do {
660       if ( exchangedQ != otherFirstQ  ||  G4UniformRand() < probSame ) {
661         otherExchangedQ = otherFirstQ; otherFirstQ = exchangedQ; exchangedQ = otherExchangedQ;
662       } else {
663         if ( exchangedQ != otherSecondQ  ||  G4UniformRand() < probSame ) {
664           otherExchangedQ = otherSecondQ; otherSecondQ = exchangedQ; exchangedQ = otherExchangedQ;
665         } else {
666           if ( exchangedQ != otherThirdQ  ||  G4UniformRand() < probSame ) {
667             otherExchangedQ = otherThirdQ; otherThirdQ = exchangedQ; exchangedQ = otherExchangedQ;
668           }
669         }
670       }
671     } while ( otherExchangedQ == 0  &&  ++count < MaxCount );
672     if ( count >= MaxCount ) return returnCode;  // All attempts failed: unsuccessfully ended, nothing else can be done 
673     // Swap (between projectile and target hadron) the two quarks that have been sampled
674     // as "exchanged" quarks.
675     if ( Ksi < 0.333333 ) {
676       firstQ = exchangedQ;
677     } else if ( 0.333333 <= Ksi  &&  Ksi < 0.666667 ) {
678       secondQ = exchangedQ;
679     } else {
680       thirdQ = exchangedQ;
681     }
682     if ( isProjectileExchangedQ ) {
683       ProjQ1 = firstQ;      ProjQ2 = secondQ;      ProjQ3 = thirdQ;
684       TargQ1 = otherFirstQ; TargQ2 = otherSecondQ; TargQ3 = otherThirdQ;
685     } else {
686       TargQ1 = firstQ;      TargQ2 = secondQ;      TargQ3 = thirdQ;
687       ProjQ1 = otherFirstQ; ProjQ2 = otherSecondQ; ProjQ3 = otherThirdQ;
688     }
689     #ifdef debugFTFexcitation
690     G4cout << "Exchange Qs Pr  Tr " << ( isProjectileExchangedQ ? exchangedQ : otherExchangedQ )
691            << " " << ( isProjectileExchangedQ ? otherExchangedQ : exchangedQ ) << G4endl;
692     #endif
693 
694     NewProjCode = NewNucleonId( ProjQ1, ProjQ2, ProjQ3 );
695     NewTargCode = NewNucleonId( TargQ1, TargQ2, TargQ3 );
696     // Decide whether the new projectile hadron is a Delta particle; 
697     // then decide whether the new target hadron is a Delta particle.
698     // Notice that a Delta particle has the last PDG digit "4" (because its spin is 3/2),
699     // whereas a nucleon has "2" (because its spin is 1/2).
700     // If the new projectile hadron or the new target hadron has a heavy (c or b)
701     // constituent quark, then skip this part (because Geant4 does not have
702     // excited charm and bottom hadrons).
703     for ( G4int iHadron = 0; iHadron < 2; iHadron++ ) {
704       // First projectile hadron, then target hadron
705       G4int codeQ1 = ProjQ1, codeQ2 = ProjQ2, codeQ3 = ProjQ3, newHadCode = NewProjCode;
706       G4double massConstraint = common.M0target;
707       G4bool isHadronADelta = ( projectile->GetDefinition()->GetPDGiIsospin() == 3 );
708       if ( iHadron == 1 ) {  // Target hadron
709         codeQ1 = TargQ1, codeQ2 = TargQ2, codeQ3 = TargQ3, newHadCode = NewTargCode;
710         massConstraint = common.M0projectile;
711         isHadronADelta = ( target->GetDefinition()->GetPDGiIsospin() == 3 );
712       }
713       if ( codeQ1 > 3  ||  codeQ2 > 3  ||  codeQ3 > 3 ) continue;  // No excited charm or bottom states in Geant4
714       if ( codeQ1 == codeQ2  &&  codeQ1 == codeQ3 ) {  // The three quarks are the same
715         newHadCode += 2;  // Delta++ (uuu) or Delta- (ddd) : spin 3/2, last PDG digit = 4 (so +2 wrt p or n)
716       } else if ( isHadronADelta ) {  // Hadron (projectile or target) was Delta
717         if ( G4UniformRand() > DeltaProbAtQuarkExchange ) { 
718           newHadCode += 2;  // Delta+ (uud) or Delta0 (udd) : spin 3/2, last PDG digit = 4 (so +2 wrt p or n)
719         } else {
720           newHadCode += 0;  // No delta (so the last PDG digit remains 2)
721         }
722       } else {  // Hadron (projectile or target) was Nucleon
723         if ( G4UniformRand() < DeltaProbAtQuarkExchange  &&  
724              common.SqrtS > G4ParticleTable::GetParticleTable()->FindParticle( 2224 )->GetPDGMass() 
725                             + massConstraint ) {
726           newHadCode += 2;  // Delta+ (uud) or Delta0 (udd) : spin 3/2, last PDG digit = 4 (so +2 wrt p or n)
727         } else { 
728           newHadCode += 0;  // No delta (so the last PDG digit remains 2)
729         }
730       }
731       if ( iHadron == 0 ) {  // Projectile hadron
732         NewProjCode = newHadCode;
733       } else {               // Target hadron
734         NewTargCode = newHadCode;
735       }
736     }
737     #ifdef debugFTFexcitation
738     G4cout << "NewProjCode NewTargCode " << NewProjCode << " " << NewTargCode << G4endl;
739     #endif
740 
741     // Protection against:
742     // - Lambda* (i.e. excited Lambda state)         NOT existing in PDG ,   ->  Lambda
743     // - Sigma*  (i.e. excited Sigma hyperon states) NOT existing in Geant4  ->  Sigma
744     // - Xi*     (i.e. excited Xi hyperon states)    NOT existing in Geant4  ->  Xi
745     if ( NewProjCode == 3124  ||   // Lambda* NOT existing in PDG !
746    NewProjCode == 3224  ||   // Sigma*+ NOT existing in Geant4
747    NewProjCode == 3214  ||   // Sigma*0 NOT existing in Geant4
748    NewProjCode == 3114  ||   // Sigma*- NOT existing in Geant4
749    NewProjCode == 3324  ||   // Xi*0    NOT existing in Geant4
750    NewProjCode == 3314  ) {  // Xi*-    NOT existing in Geant4
751       //G4cout << "G4DiffractiveExcitation::ExciteParticipants_doChargeExchange INEXISTING PROJECTILE PDGcode="
752       //       << NewProjCode << G4endl;
753       NewProjCode -= 2;  // Corresponding ground-state hyperon
754     }
755     if ( NewTargCode == 3124  ||   // Lambda* NOT existing in PDG !
756    NewTargCode == 3224  ||   // Sigma*+ NOT existing in Geant4
757    NewTargCode == 3214  ||   // Sigma*0 NOT existing in Geant4
758    NewTargCode == 3114  ||   // Sigma*- NOT existing in Geant4
759    NewTargCode == 3324  ||   // Xi*0    NOT existing in Geant4
760    NewTargCode == 3314  ) {  // Xi*-    NOT existing in Geant4
761       //G4cout << "G4DiffractiveExcitation::ExciteParticipants_doChargeExchange INEXISTING TARGET PDGcode="
762       //       << NewTargCode << G4endl;
763       NewTargCode -= 2;  // Corresponding ground-state hyperon
764     }
765 
766     // Special treatment for charmed and bottom baryons : in Geant4 there are no Xi_c' and Xi_b'
767     // so we need to transform them by hand to the, respectively, Xi_c and Xi_b.
768     #ifdef debug_heavyHadrons
769     G4int initialNewProjCode = NewProjCode, initialNewTargCode = NewTargCode;
770     #endif
771     if      ( NewProjCode == 4322 ) NewProjCode = 4232;  // Xi_c'+  ->  Xi_c+
772     else if ( NewProjCode == 4312 ) NewProjCode = 4132;  // Xi_c'0  ->  Xi_c0
773     else if ( NewProjCode == 5312 ) NewProjCode = 5132;  // Xi_b'-  ->  Xi_b-
774     else if ( NewProjCode == 5322 ) NewProjCode = 5232;  // Xi_b'0  ->  Xi_b0
775     if      ( NewTargCode == 4322 ) NewTargCode = 4232;  // Xi_c'+  ->  Xi_c+
776     else if ( NewTargCode == 4312 ) NewTargCode = 4132;  // Xi_c'0  ->  Xi_c0
777     else if ( NewTargCode == 5312 ) NewTargCode = 5132;  // Xi_b'-  ->  Xi_b-
778     else if ( NewTargCode == 5322 ) NewTargCode = 5232;  // Xi_b'0  ->  Xi_b0
779     #ifdef debug_heavyHadrons
780     if ( NewProjCode != initialNewProjCode  ||  NewTargCode != initialNewTargCode ) {
781       G4cout << "G4DiffractiveExcitation::ExciteParticipants_doChargeExchange : forcing (inexisting in G4)" << G4endl
782              << "\t heavy baryon into an existing one:" << G4endl;
783       if ( NewProjCode != initialNewProjCode ) {
784   G4cout << "\t \t projectile baryon with pdgCode=" << initialNewProjCode
785          << " into pdgCode=" << NewProjCode << G4endl;
786       }
787       if ( NewTargCode != initialNewTargCode ) {
788         G4cout << "\t \t target baryon with pdgCode=" << initialNewTargCode
789          << " into pdgCode=" << NewTargCode << G4endl;
790       }
791     }
792     #endif
793 
794     // Sampling of the masses of the projectile and target nucleons.
795     // Because of energy conservation, the ordering of the sampling matters:
796     // randomly, half of the time we sample first the target nucleon mass and
797     // then the projectile nucleon mass, and the other half of the time we
798     // sample first the projectile nucleon mass and then the target nucleon mass.
799     G4VSplitableHadron* firstHadron  = target;
800     G4VSplitableHadron* secondHadron = projectile;
801     G4int firstHadronCode = NewTargCode, secondHadronCode = NewProjCode;
802     G4double massConstraint = common.M0projectile;
803     G4bool isFirstTarget = true;
804     if ( G4UniformRand() < 0.5 ) {
805       // Sample first the projectile nucleon mass, then the target nucleon mass.
806       firstHadron  = projectile;      secondHadron = target;
807       firstHadronCode = NewProjCode;  secondHadronCode = NewTargCode;
808       massConstraint = common.M0target;
809       isFirstTarget = false;
810     }
811     G4double Mtest1st = 0.0, Mtest2nd = 0.0, Mmin1st = 0.0, Mmin2nd = 0.0;
812     for ( int iSamplingCase = 0; iSamplingCase < 2; iSamplingCase++ ) {
813       G4VSplitableHadron* aHadron = firstHadron;
814       G4int aHadronCode = firstHadronCode;
815       if ( iSamplingCase == 1 ) {  // Second nucleon mass sampling
816         aHadron = secondHadron; aHadronCode = secondHadronCode; massConstraint = Mtest1st;
817       }
818       G4double MtestHadron = 0.0, MminHadron = 0.0;
819       if ( aHadron->GetStatus() == 1  ||  aHadron->GetStatus() == 2 ) { 
820         TestParticle = G4ParticleTable::GetParticleTable()->FindParticle( aHadronCode );
821         if ( ! TestParticle ) return returnCode;  // Not possible to find such a hadron: unsuccessfully ended, nothing else can be done
822         MminHadron = common.BrW.GetMinimumMass( TestParticle );
823         if ( common.SqrtS - massConstraint < MminHadron ) return returnCode;  // Kinematically impossible: unsuccessfully ended, nothing else can be done
824         if ( TestParticle->GetPDGWidth() == 0.0 ) { 
825           MtestHadron = common.BrW.SampleMass( TestParticle, TestParticle->GetPDGMass() );
826         } else {
827           const G4int maxNumberOfAttempts = 50;
828           G4int attempts = 0;
829           while ( attempts < maxNumberOfAttempts ) {
830             attempts++;
831             MtestHadron = common.BrW.SampleMass( TestParticle, TestParticle->GetPDGMass() 
832                                                  + 5.0*TestParticle->GetPDGWidth() );
833             if ( common.SqrtS < MtestHadron + massConstraint ) {  
834               continue;  // Kinematically unacceptable: try again
835             } else {  
836               break;     // Kinematically acceptable: the mass sampling is successful 
837             }
838           }
839           if ( attempts >= maxNumberOfAttempts ) return returnCode;  // All attempts failed: unsuccessfully ended, nothing else can be done
840         }
841       }
842       if ( iSamplingCase == 0 ) {  
843         Mtest1st = MtestHadron;  Mmin1st = MminHadron;
844       } else {
845         Mtest2nd = MtestHadron;  Mmin2nd = MminHadron;
846       }
847     }  // End for loop on the two sampling cases (1st and 2nd)
848     if ( isFirstTarget ) {
849       MtestTr = Mtest1st;    MtestPr = Mtest2nd;
850       common.MminTarget = Mmin1st;  common.MminProjectile = Mmin2nd;
851     } else {
852       MtestTr = Mtest2nd;    MtestPr = Mtest1st;
853       common.MminTarget = Mmin2nd;  common.MminProjectile = Mmin1st;
854     }
855  
856     if ( MtestPr != 0.0 ) {
857       common.M0projectile = MtestPr;
858       common.M0projectile2 = common.M0projectile * common.M0projectile;
859       common.ProjectileDiffStateMinMass =    common.M0projectile + 220.0*MeV;  // 220 MeV=m_pi+80 MeV
860       common.ProjectileNonDiffStateMinMass = common.M0projectile + 220.0*MeV;  // 220 MeV=m_pi+80 MeV
861     }      
862     if ( MtestTr != 0.0 ) {
863       common.M0target = MtestTr;
864       common.M0target2 = common.M0target * common.M0target;
865       common.TargetDiffStateMinMass    = common.M0target + 220.0*MeV;          // 220 MeV=m_pi+80 MeV;    
866       common.TargetNonDiffStateMinMass = common.M0target + 220.0*MeV;          // 220 MeV=m_pi+80 MeV; 
867     }
868 
869   }  // End of if ( common.absProjectilePDGcode < 1000 )
870 
871   // If we assume that final state hadrons after the charge exchange will be
872   // in the ground states, we have to put 
873   if ( common.SqrtS < common.M0projectile + common.M0target ) return returnCode;  // unsuccessfully ended, nothing else can be done
874 
875   common.PZcms2 = ( sqr( common.S ) + sqr( common.M0projectile2 ) + sqr( common.M0target2 )
876                     - 2.0 * ( common.S * ( common.M0projectile2 + common.M0target2 )
877                               + common.M0projectile2 * common.M0target2 ) ) / 4.0 / common.S;
878   #ifdef debugFTFexcitation
879   G4cout << "At the end// NewProjCode " << NewProjCode << G4endl 
880          << "At the end// NewTargCode " << NewTargCode << G4endl
881          << "M0pr  M0tr  SqS " << common.M0projectile << " " << common.M0target << " " 
882          << common.SqrtS << G4endl
883          << "M0pr2 M0tr2 SqS " << common.M0projectile2 << " " << common.M0target2 << " "
884          << common.SqrtS << G4endl
885          << "PZcms2 after the change " << common.PZcms2 << G4endl << G4endl;
886   #endif
887   if ( common.PZcms2 < 0.0 ) return returnCode; // It can be if energy is not sufficient for Delta;
888                                                 // unsuccessfully ended, nothing else can be done
889   projectile->SetDefinition( G4ParticleTable::GetParticleTable()->FindParticle( NewProjCode ) );
890   target->SetDefinition( G4ParticleTable::GetParticleTable()->FindParticle( NewTargCode ) );
891   common.PZcms = std::sqrt( common.PZcms2 );
892   common.Pprojectile.setPz( common.PZcms );
893   common.Pprojectile.setE( std::sqrt( common.M0projectile2 + common.PZcms2 ) );
894   common.Ptarget.setPz(    -common.PZcms );
895   common.Ptarget.setE( std::sqrt( common.M0target2 + common.PZcms2 ) );
896   #ifdef debugFTFexcitation
897   G4cout << "Proj Targ and Proj+Targ in CMS" << G4endl << common.Pprojectile << G4endl 
898          << common.Ptarget << G4endl << common.Pprojectile + common.Ptarget << G4endl;
899   #endif
900 
901   if ( projectile->GetStatus() != 0 ) projectile->SetStatus( 2 );
902   if ( target->GetStatus()     != 0 ) target->SetStatus( 2 );
903 
904   // Check for possible excitation of the participants
905   if ( common.SqrtS < common.M0projectile + common.TargetDiffStateMinMass  ||
906        common.SqrtS < common.ProjectileDiffStateMinMass + common.M0target  ||
907        common.ProbOfDiffraction == 0.0 ) common.ProbExc = 0.0;
908 
909   if ( G4UniformRand() > common.ProbExc ) {  // Make elastic scattering
910     #ifdef debugFTFexcitation
911     G4cout << "Make elastic scattering of new hadrons" << G4endl;
912     #endif
913     common.Pprojectile.transform( common.toLab );
914     common.Ptarget.transform( common.toLab );
915     projectile->Set4Momentum( common.Pprojectile );
916     target->Set4Momentum( common.Ptarget );
917     G4bool Result = theElastic->ElasticScattering( projectile, target, theParameters );
918     #ifdef debugFTFexcitation
919     G4cout << "Result of el. scatt " << Result << G4endl << "Proj Targ and Proj+Targ in Lab"
920            << G4endl << projectile->Get4Momentum() << G4endl << target->Get4Momentum() << G4endl
921            << projectile->Get4Momentum() + target->Get4Momentum() << " " 
922            << (projectile->Get4Momentum() + target->Get4Momentum()).mag() << G4endl;
923     #endif
924     if ( Result ) returnCode = 0;  // successfully ended and nothing else needs to be done 
925     return returnCode;
926   }
927 
928   #ifdef debugFTFexcitation
929   G4cout << "Make excitation of new hadrons" << G4endl;
930   #endif
931 
932   // Redefinition of ProbOfDiffraction because the probabilities are changed due to quark exchange
933   common.ProbOfDiffraction = common.ProbProjectileDiffraction + common.ProbTargetDiffraction;
934   if ( common.ProbOfDiffraction != 0.0 ) {
935     common.ProbProjectileDiffraction /= common.ProbOfDiffraction;
936     common.ProbTargetDiffraction     /= common.ProbOfDiffraction;
937   }
938 
939   return returnCode = 1;  // successfully completed, but the work needs to be continued
940 }
941 
942 //-----------------------------------------------------------------------------
943 
944 G4bool G4DiffractiveExcitation::
945 ExciteParticipants_doDiffraction( G4VSplitableHadron* projectile, G4VSplitableHadron* target,
946                                   G4FTFParameters* theParameters, 
947                                   G4DiffractiveExcitation::CommonVariables& common ) const {
948   // Second of the three utility methods used only by ExciteParticipants: 
949   // it does the sampling for the diffraction case, either projectile or target diffraction.
950 
951   G4bool isProjectileDiffraction = false;
952   if ( G4UniformRand() < common.ProbProjectileDiffraction ) {  // projectile diffraction
953     isProjectileDiffraction = true;
954     #ifdef debugFTFexcitation
955     G4cout << "projectile diffraction" << G4endl;
956     #endif
957     common.ProjMassT2 = common.ProjectileDiffStateMinMass2;
958     common.ProjMassT  = common.ProjectileDiffStateMinMass;
959     common.TargMassT2 = common.M0target2;
960     common.TargMassT  = common.M0target;
961   } else {                                                     // target diffraction
962     #ifdef debugFTFexcitation
963     G4cout << "Target diffraction" << G4endl;
964     #endif
965     common.ProjMassT2 = common.M0projectile2;
966     common.ProjMassT  = common.M0projectile; 
967     common.TargMassT2 = common.TargetDiffStateMinMass2;
968     common.TargMassT  = common.TargetDiffStateMinMass;
969   }
970 
971   // Check whether the interaction is possible
972   if ( common.SqrtS < common.ProjMassT + common.TargMassT ) return false;
973   
974   common.PZcms2 = ( sqr( common.S ) + sqr( common.ProjMassT2 ) + sqr( common.TargMassT2 )
975                     - 2.0 * ( common.S * ( common.ProjMassT2 + common.TargMassT2 )
976                           + common.ProjMassT2 * common.TargMassT2 ) ) / 4.0 / common.S;
977   if ( common.PZcms2 < 0.0 ) return false;
978   common.maxPtSquare = common.PZcms2;
979 
980   G4double DiffrAveragePt2 = theParameters->GetAvaragePt2ofElasticScattering()*1.2;
981   G4bool loopCondition = true;
982   G4int whilecount = 0;
983   do {  // Generate pt and mass of projectile
984 
985     whilecount++;
986     if ( whilecount > 1000 ) {
987       common.Qmomentum = G4LorentzVector( 0.0, 0.0, 0.0, 0.0 );
988       return false;  //  Ignore this interaction
989     };
990 
991     common.Qmomentum = G4LorentzVector( GaussianPt( DiffrAveragePt2, common.maxPtSquare ), 0 );
992     common.Pt2 = G4ThreeVector( common.Qmomentum.vect() ).mag2();
993     if ( isProjectileDiffraction ) {  // projectile diffraction
994       common.ProjMassT2 = common.ProjectileDiffStateMinMass2 + common.Pt2;
995       common.TargMassT2 = common.M0target2 + common.Pt2;
996     } else {                          // target diffraction
997       common.ProjMassT2 = common.M0projectile2 + common.Pt2;
998       common.TargMassT2 = common.TargetDiffStateMinMass2 + common.Pt2;
999     }
1000     common.ProjMassT = std::sqrt( common.ProjMassT2 );
1001     common.TargMassT = std::sqrt( common.TargMassT2 );
1002     if ( common.SqrtS < common.ProjMassT + common.TargMassT ) continue;
1003 
1004     common.PZcms2 = ( sqr( common.S ) + sqr( common.ProjMassT2 ) + sqr( common.TargMassT2 )
1005                       - 2.0 * ( common.S * ( common.ProjMassT2 + common.TargMassT2 )
1006                                 + common.ProjMassT2 * common.TargMassT2 ) ) / 4.0 / common.S;
1007     if ( common.PZcms2 < 0.0 ) continue;
1008 
1009     common.PZcms = std::sqrt( common.PZcms2 );
1010     if ( isProjectileDiffraction ) {  // projectile diffraction
1011       common.PMinusMin = std::sqrt( common.ProjMassT2 + common.PZcms2 ) - common.PZcms; 
1012       common.PMinusMax = common.SqrtS - common.TargMassT;
1013       common.PMinusNew = ChooseP( common.PMinusMin, common.PMinusMax );
1014       common.TMinusNew = common.SqrtS - common.PMinusNew;
1015       common.Qminus = common.Ptarget.minus() - common.TMinusNew;
1016       common.TPlusNew = common.TargMassT2 / common.TMinusNew;
1017       common.Qplus = common.Ptarget.plus() - common.TPlusNew;
1018       common.Qmomentum.setPz( (common.Qplus - common.Qminus)/2.0 );
1019       common.Qmomentum.setE(  (common.Qplus + common.Qminus)/2.0 );
1020       loopCondition = ( ( common.Pprojectile + common.Qmomentum ).mag2() <  
1021                         common.ProjectileDiffStateMinMass2 ); 
1022     } else {                          // target diffraction
1023       common.TPlusMin = std::sqrt( common.TargMassT2 + common.PZcms2 ) - common.PZcms;
1024       common.TPlusMax = common.SqrtS - common.ProjMassT;
1025       common.TPlusNew = ChooseP( common.TPlusMin, common.TPlusMax );
1026       common.PPlusNew = common.SqrtS - common.TPlusNew;
1027       common.Qplus = common.PPlusNew - common.Pprojectile.plus();
1028       common.PMinusNew = common.ProjMassT2 / common.PPlusNew;
1029       common.Qminus = common.PMinusNew - common.Pprojectile.minus();
1030       common.Qmomentum.setPz( (common.Qplus - common.Qminus)/2.0 );
1031       common.Qmomentum.setE(  (common.Qplus + common.Qminus)/2.0 );
1032       loopCondition =  ( ( common.Ptarget - common.Qmomentum ).mag2() < 
1033                          common.TargetDiffStateMinMass2 );
1034     }
1035 
1036   } while ( loopCondition );  /* Loop checking, 10.08.2015, A.Ribon */
1037           // Repeat the sampling because there was not any excitation
1038 
1039   if ( isProjectileDiffraction ) {  // projectile diffraction
1040     projectile->SetStatus( 0 );
1041     if ( projectile->GetStatus() == 2 ) projectile->SetStatus( 1 );
1042     if ( target->GetStatus() == 1  &&  target->GetSoftCollisionCount() == 0 ) target->SetStatus( 2 );
1043   } else {                          // target diffraction
1044     target->SetStatus( 0 );
1045   }
1046 
1047   return true;
1048 }
1049  
1050 //-----------------------------------------------------------------------------
1051 
1052 G4bool G4DiffractiveExcitation::
1053 ExciteParticipants_doNonDiffraction( G4VSplitableHadron* projectile,
1054                                      G4VSplitableHadron* target,
1055                                      G4FTFParameters*    theParameters,
1056                                      G4DiffractiveExcitation::CommonVariables& common ) const {
1057   // Third of the three utility methods used only by ExciteParticipants: 
1058   // it does the sampling for the non-diffraction case.
1059 
1060   #ifdef debugFTFexcitation
1061   G4cout << "Non-diffraction process" << G4endl;
1062   #endif
1063 
1064   // Check whether the interaction is possible
1065   common.ProjMassT2 = common.ProjectileNonDiffStateMinMass2;
1066   common.ProjMassT  = common.ProjectileNonDiffStateMinMass;
1067   common.TargMassT2 = common.TargetNonDiffStateMinMass2;
1068   common.TargMassT  = common.TargetNonDiffStateMinMass;
1069   if ( common.SqrtS < common.ProjMassT + common.TargMassT ) return false;
1070 
1071   common.PZcms2 = ( sqr( common.S ) + sqr( common.ProjMassT2 ) + sqr( common.TargMassT2 )
1072                   - 2.0 * ( common.S * ( common.ProjMassT2 + common.TargMassT2 )
1073                         + common.ProjMassT2 * common.TargMassT2 ) ) / 4.0 / common.S;
1074   common.maxPtSquare = common.PZcms2;
1075   
1076   G4int whilecount = 0;
1077   do {  // Generate pt and masses
1078 
1079     whilecount++;
1080     if ( whilecount > 1000 ) {
1081       common.Qmomentum = G4LorentzVector( 0.0, 0.0, 0.0, 0.0 );
1082       return false;  // Ignore this interaction
1083     };
1084 
1085     common.Qmomentum = G4LorentzVector( GaussianPt( theParameters->GetAveragePt2(), 
1086                                                     common.maxPtSquare ), 0 );
1087     common.Pt2 = G4ThreeVector( common.Qmomentum.vect() ).mag2();
1088     common.ProjMassT2 = common.ProjectileNonDiffStateMinMass2 + common.Pt2;
1089     common.ProjMassT  = std::sqrt( common.ProjMassT2 );
1090     common.TargMassT2 = common.TargetNonDiffStateMinMass2 + common.Pt2;
1091     common.TargMassT  = std::sqrt( common.TargMassT2 );
1092     if ( common.SqrtS < common.ProjMassT + common.TargMassT ) continue;
1093 
1094     common.PZcms2 =( sqr( common.S ) + sqr( common.ProjMassT2 ) + sqr( common.TargMassT2 )
1095                      - 2.0 * ( common.S * ( common.ProjMassT2 + common.TargMassT2 )
1096                                + common.ProjMassT2 * common.TargMassT2 ) ) / 4.0 / common.S;
1097     if ( common.PZcms2 < 0.0 ) continue;
1098 
1099     common.PZcms = std::sqrt( common.PZcms2 );
1100     common.PMinusMin = std::sqrt( common.ProjMassT2 + common.PZcms2 ) - common.PZcms;
1101     common.PMinusMax = common.SqrtS - common.TargMassT;
1102     common.TPlusMin = std::sqrt( common.TargMassT2 + common.PZcms2 ) - common.PZcms;
1103     common.TPlusMax = common.SqrtS - common.ProjMassT;
1104 
1105     if ( G4UniformRand() <= 0.5 ) {  // Random choice projectile or target sampling
1106       if ( G4UniformRand() < theParameters->GetProbLogDistrPrD() ) {
1107         common.PMinusNew = ChooseP( common.PMinusMin, common.PMinusMax );
1108       } else {
1109         common.PMinusNew = ( common.PMinusMax - common.PMinusMin )*G4UniformRand() + common.PMinusMin;
1110       }
1111       if ( G4UniformRand() < theParameters->GetProbLogDistr() ) {
1112         common.TPlusNew = ChooseP( common.TPlusMin, common.TPlusMax );
1113       } else {
1114         common.TPlusNew = ( common.TPlusMax - common.TPlusMin )*G4UniformRand() + common.TPlusMin;
1115       }
1116     } else {
1117       if ( G4UniformRand() < theParameters->GetProbLogDistr() ) {
1118         common.TPlusNew = ChooseP( common.TPlusMin, common.TPlusMax );
1119       } else {
1120         common.TPlusNew = ( common.TPlusMax - common.TPlusMin )*G4UniformRand() + common.TPlusMin;
1121       }
1122       if ( G4UniformRand() < theParameters->GetProbLogDistrPrD() ) {
1123         common.PMinusNew = ChooseP( common.PMinusMin, common.PMinusMax );
1124       } else {
1125         common.PMinusNew = ( common.PMinusMax - common.PMinusMin )*G4UniformRand() + common.PMinusMin;
1126       }
1127     }
1128 
1129     common.Qminus = common.PMinusNew - common.Pprojectile.minus();
1130     common.Qplus = -( common.TPlusNew - common.Ptarget.plus() );
1131     common.Qmomentum.setPz( (common.Qplus - common.Qminus)/2.0 );
1132     common.Qmomentum.setE(  (common.Qplus + common.Qminus)/2.0 );
1133     #ifdef debugFTFexcitation
1134     G4cout <<"Sampled: Mpr, MdifPr, Mtr, MdifTr "<<G4endl
1135            << ( common.Pprojectile + common.Qmomentum ).mag() << " " 
1136            << common.ProjectileNonDiffStateMinMass << G4endl 
1137            << ( common.Ptarget - common.Qmomentum ).mag() << " "
1138            << common.TargetNonDiffStateMinMass << G4endl;
1139     #endif
1140 
1141   } while ( ( common.Pprojectile + common.Qmomentum ).mag2() < 
1142             common.ProjectileNonDiffStateMinMass2  ||  // No double Diffraction
1143             ( common.Ptarget - common.Qmomentum ).mag2() <  
1144             common.TargetNonDiffStateMinMass2 );  /* Loop checking, 10.08.2015, A.Ribon */
1145 
1146   projectile->SetStatus( 0 );
1147   target->SetStatus( 0 );
1148   return true;
1149 }
1150 
1151 
1152 //============================================================================
1153 
1154 void G4DiffractiveExcitation::CreateStrings( G4VSplitableHadron* hadron, 
1155                                              G4bool isProjectile,
1156                                              G4ExcitedString*& FirstString, 
1157                                              G4ExcitedString*& SecondString,
1158                                              G4FTFParameters* theParameters ) const {
1159 
1160   //G4cout << "Create Strings SplitUp " << hadron << G4endl
1161   //       << "Defin " << hadron->GetDefinition() << G4endl
1162   //       << "Defin " << hadron->GetDefinition()->GetPDGEncoding() << G4endl;
1163 
1164   G4bool HadronIsString = hadron->IsSplit();
1165   if( ! HadronIsString ) hadron->SplitUp();
1166 
1167   G4Parton* start = hadron->GetNextParton();
1168   if ( start == nullptr ) { 
1169     G4cout << " G4FTFModel::String() Error: No start parton found" << G4endl;
1170     FirstString = 0; SecondString = 0;
1171     return;
1172   }
1173 
1174   G4Parton* end = hadron->GetNextParton();
1175   if ( end == nullptr ) { 
1176     G4cout << " G4FTFModel::String() Error: No end parton found" <<  G4endl;
1177     FirstString = 0; SecondString = 0;
1178     return;
1179   }
1180 
1181   //G4cout << start << " " << start->GetPDGcode() << " " << end << " " << end->GetPDGcode()
1182   //       << G4endl
1183   //       << "Create string " << start->GetPDGcode() << " " << end->GetPDGcode() << G4endl;
1184 
1185   if ( HadronIsString ) {
1186     if ( isProjectile ) {
1187       FirstString = new G4ExcitedString( end, start, +1 );
1188     } else {
1189       FirstString = new G4ExcitedString( end, start, -1 );
1190     }
1191     FirstString->SetTimeOfCreation( hadron->GetTimeOfCreation() );
1192     FirstString->SetPosition( hadron->GetPosition() );
1193     SecondString = 0;
1194     return;
1195   }
1196 
1197   G4LorentzVector Phadron = hadron->Get4Momentum();
1198   //G4cout << "String mom " << Phadron << G4endl;
1199   G4LorentzVector Pstart( 0.0, 0.0, 0.0, 0.0 );
1200   G4LorentzVector Pend( 0.0, 0.0, 0.0, 0.0 );
1201   G4LorentzVector Pkink( 0.0, 0.0, 0.0, 0.0 );
1202   G4LorentzVector PkinkQ1( 0.0, 0.0, 0.0, 0.0 );
1203   G4LorentzVector PkinkQ2( 0.0, 0.0, 0.0, 0.0 );
1204 
1205   G4int PDGcode_startQ = std::abs( start->GetDefinition()->GetPDGEncoding() );
1206   G4int PDGcode_endQ   = std::abs(   end->GetDefinition()->GetPDGEncoding() );
1207   //G4cout << "PDGcode_startQ " << PDGcode_startQ << " PDGcode_endQ   " << PDGcode_endQ << G4endl;
1208 
1209   G4double Wmin( 0.0 );
1210   if ( isProjectile ) {
1211     Wmin = theParameters->GetProjMinDiffMass();
1212   } else {
1213     Wmin = theParameters->GetTarMinDiffMass();
1214   }
1215 
1216   G4double W = hadron->Get4Momentum().mag();
1217   G4double W2 = W*W;
1218   G4double Pt( 0.0 ), x1( 0.0 ), x3( 0.0 );  // x2( 0.0 ) 
1219   G4bool Kink = false;
1220 
1221   if ( ! ( ( start->GetDefinition()->GetParticleSubType() == "di_quark"  &&
1222                end->GetDefinition()->GetParticleSubType() == "di_quark"  )  ||
1223            ( start->GetDefinition()->GetParticleSubType() == "quark"     &&
1224                end->GetDefinition()->GetParticleSubType() == "quark"     ) ) ) { 
1225     // Kinky strings are allowed only for qq-q strings;
1226     // Kinky strings are impossible for other systems (qq-qqbar, q-qbar)
1227     // according to the analysis of Pbar P interactions
1228 
1229     if ( W > Wmin ) {  // Kink is possible
1230       if ( hadron->GetStatus() == 0 ) {
1231         G4double Pt2kink = theParameters->GetPt2Kink(); // For non-diffractive
1232         if ( Pt2kink ) {
1233           Pt = std::sqrt( Pt2kink * ( G4Pow::GetInstance()->powA( W2/16.0/Pt2kink + 1.0, G4UniformRand() ) - 1.0 ) );
1234         } else {
1235           Pt = 0.0;
1236         }
1237       } else {
1238         Pt = 0.0;
1239       }
1240 
1241       if ( Pt > 500.0*MeV ) {
1242         G4double Ymax = G4Log( W/2.0/Pt + std::sqrt( W2/4.0/Pt/Pt - 1.0 ) );
1243         G4double Y = Ymax*( 1.0 - 2.0*G4UniformRand() );
1244         x1 = 1.0 - Pt/W * G4Exp( Y );
1245         x3 = 1.0 - Pt/W * G4Exp(-Y );
1246         //x2 = 2.0 - x1 - x3;
1247 
1248         G4double Mass_startQ = 650.0*MeV;
1249         if ( PDGcode_startQ <  3 ) Mass_startQ =  325.0*MeV;  // For constituent up or down quark
1250         if ( PDGcode_startQ == 3 ) Mass_startQ =  500.0*MeV;  // For constituent strange quark
1251         if ( PDGcode_startQ == 4 ) Mass_startQ = 1600.0*MeV;  // For constituent charm quark
1252         if ( PDGcode_startQ == 5 ) Mass_startQ = 4500.0*MeV;  // For constituent bottom quark
1253         G4double Mass_endQ = 650.0*MeV;
1254         if ( PDGcode_endQ <  3 ) Mass_endQ =  325.0*MeV;      // For constituent up or down quark
1255         if ( PDGcode_endQ == 3 ) Mass_endQ =  500.0*MeV;      // For constituent strange quark
1256         if ( PDGcode_endQ == 4 ) Mass_endQ = 1600.0*MeV;      // For constituent charm quark
1257         if ( PDGcode_endQ == 5 ) Mass_endQ = 4500.0*MeV;      // For constituent bottom quark
1258 
1259         G4double P2_1 = W2*x1*x1/4.0 - Mass_endQ*Mass_endQ;
1260         G4double P2_3 = W2*x3*x3/4.0 - Mass_startQ*Mass_startQ;
1261         G4double P2_2 = sqr( (2.0 - x1 - x3)*W/2.0 );
1262         if ( P2_1 <= 0.0  ||  P2_3 <= 0.0 ) { 
1263           Kink = false;
1264         } else {
1265           G4double P_1 = std::sqrt( P2_1 );
1266           G4double P_2 = std::sqrt( P2_2 );
1267           G4double P_3 = std::sqrt( P2_3 );
1268           G4double CosT12 = ( P2_3 - P2_1 - P2_2 ) / (2.0*P_1*P_2);
1269           G4double CosT13 = ( P2_2 - P2_1 - P2_3 ) / (2.0*P_1*P_3);
1270 
1271           if ( std::abs( CosT12 ) > 1.0  ||  std::abs( CosT13 ) > 1.0 ) {
1272             Kink = false;
1273           } else { 
1274             Kink = true; 
1275             Pt = P_2 * std::sqrt( 1.0 - CosT12*CosT12 );  // because system was rotated
1276             Pstart.setPx( -Pt ); Pstart.setPy( 0.0 ); Pstart.setPz( P_3*CosT13 ); 
1277             Pend.setPx(   0.0 ); Pend.setPy(   0.0 ); Pend.setPz(          P_1 ); 
1278             Pkink.setPx(   Pt ); Pkink.setPy(  0.0 ); Pkink.setPz(  P_2*CosT12 );
1279             Pstart.setE( x3*W/2.0 );                
1280             Pkink.setE( Pkink.vect().mag() );
1281             Pend.setE( x1*W/2.0 );
1282 
1283             G4double XkQ = GetQuarkFractionOfKink( 0.0, 1.0 );
1284             if ( Pkink.getZ() > 0.0 ) {
1285               if ( XkQ > 0.5 ) {
1286                 PkinkQ1 = XkQ*Pkink;
1287               } else {
1288                 PkinkQ1 = (1.0 - XkQ)*Pkink;
1289               }
1290             } else {
1291               if ( XkQ > 0.5 ) {
1292                 PkinkQ1 = (1.0 - XkQ)*Pkink;
1293               } else {
1294                 PkinkQ1 = XkQ*Pkink;
1295               }
1296             }
1297 
1298             PkinkQ2 = Pkink - PkinkQ1;
1299             // Minimizing Pt1^2+Pt3^2
1300             G4double Cos2Psi = ( sqr(x1) - sqr(x3) + 2.0*sqr( x3*CosT13 ) ) /
1301                                std::sqrt( sqr( sqr(x1) - sqr(x3) ) + sqr( 2.0*x1*x3*CosT13 ) );
1302             G4double Psi = std::acos( Cos2Psi );
1303 
1304             G4LorentzRotation Rotate;
1305             if ( isProjectile ) {
1306               Rotate.rotateY( Psi );
1307             } else {
1308               Rotate.rotateY( pi + Psi );
1309             }                   
1310             Rotate.rotateZ( twopi * G4UniformRand() );
1311             Pstart *= Rotate;
1312             Pkink *= Rotate;
1313             PkinkQ1 *= Rotate;
1314             PkinkQ2 *= Rotate;
1315             Pend *= Rotate;
1316           }
1317         }  // End of if ( P2_1 <= 0.0  ||  P2_3 <= 0.0 )
1318       }  // End of if ( Pt > 500.0*MeV )
1319     } // End of if ( W > Wmin ) : check for a kink
1320   }  // end of qq-q string selection
1321 
1322   if ( Kink ) {  // Kink is possible
1323 
1324     //G4cout << "Kink is sampled!" << G4endl;
1325     std::vector< G4double > QuarkProbabilitiesAtGluonSplitUp = 
1326         theParameters->GetQuarkProbabilitiesAtGluonSplitUp();
1327 
1328     G4int QuarkInGluon( 1 ); G4double Ksi = G4UniformRand();
1329     for ( unsigned int Iq = 0; Iq < 3; Iq++ ) {
1330       //G4cout << "Iq " << Iq << G4endl;
1331       if ( Ksi > QuarkProbabilitiesAtGluonSplitUp[Iq] ) QuarkInGluon++;
1332     }
1333     //G4cout << "Last Iq " << QuarkInGluon << G4endl;
1334     G4Parton* Gquark = new G4Parton( QuarkInGluon );
1335     G4Parton* Ganti_quark = new G4Parton( -QuarkInGluon );
1336     //G4cout << "Lorentz " << G4endl;
1337 
1338     G4LorentzRotation toCMS( -1 * Phadron.boostVector() );
1339     G4LorentzRotation toLab( toCMS.inverse() );
1340     //G4cout << "Pstart " << Pstart << G4endl;
1341     //G4cout << "Pend   " << Pend << G4endl;
1342     //G4cout << "Kink1  " <<PkinkQ1<<G4endl;
1343     //G4cout << "Kink2  " <<PkinkQ2<<G4endl;
1344     //G4cout << "Pstart " << Pstart << G4endl<<G4endl;
1345 
1346     Pstart.transform( toLab );  start->Set4Momentum( Pstart );
1347     PkinkQ1.transform( toLab );
1348     PkinkQ2.transform( toLab );
1349     Pend.transform( toLab );    end->Set4Momentum( Pend );
1350     //G4cout << "Pstart " << Pstart << G4endl;
1351     //G4cout << "Pend   " << Pend << G4endl;
1352     //G4cout << "Defin " << hadron->GetDefinition()<< G4endl;
1353     //G4cout << "Defin " << hadron->GetDefinition()->GetPDGEncoding()<< G4endl;
1354 
1355     //G4int absPDGcode = std::abs( hadron->GetDefinition()->GetPDGEncoding() );
1356     G4int absPDGcode = 1500;
1357     if ( start->GetDefinition()->GetParticleSubType() == "quark"  &&
1358          end->GetDefinition()->GetParticleSubType() == "quark" ) {
1359       absPDGcode = 110;
1360     }
1361     //G4cout << "absPDGcode " << absPDGcode << G4endl;
1362 
1363     if ( absPDGcode < 1000 ) {  // meson
1364       if ( isProjectile ) { // Projectile
1365         if ( end->GetDefinition()->GetPDGEncoding() > 0 ) {  // A quark on the end
1366           FirstString  = new G4ExcitedString( end   , Ganti_quark, +1 );
1367           SecondString = new G4ExcitedString( Gquark, start      , +1 );
1368           Ganti_quark->Set4Momentum( PkinkQ1 );
1369           Gquark->Set4Momentum( PkinkQ2 );
1370         } else {  // Anti_Quark on the end
1371           FirstString  = new G4ExcitedString( end        , Gquark, +1 );
1372           SecondString = new G4ExcitedString( Ganti_quark, start , +1 );
1373           Gquark->Set4Momentum( PkinkQ1 );
1374           Ganti_quark->Set4Momentum( PkinkQ2 );
1375         }
1376       } else {  // Target
1377         if ( end->GetDefinition()->GetPDGEncoding() > 0 ) { // A quark on the end
1378           FirstString  = new G4ExcitedString( Ganti_quark, end   , -1 );
1379           SecondString = new G4ExcitedString( start      , Gquark, -1 );
1380           Ganti_quark->Set4Momentum( PkinkQ2 );
1381           Gquark->Set4Momentum( PkinkQ1 );
1382         } else {  // Anti_Quark on the end
1383           FirstString  = new G4ExcitedString( Gquark, end        , -1 );
1384           SecondString = new G4ExcitedString( start , Ganti_quark, -1 );
1385           Gquark->Set4Momentum( PkinkQ2 );
1386           Ganti_quark->Set4Momentum( PkinkQ1 );
1387         }
1388       }
1389     } else {  // Baryon/AntiBaryon
1390       if ( isProjectile ) {  // Projectile
1391         if ( end->GetDefinition()->GetParticleType() == "diquarks"  &&
1392              end->GetDefinition()->GetPDGEncoding() > 0 ) {  // DiQuark on the end
1393           FirstString  = new G4ExcitedString( end        , Gquark, +1 );
1394           SecondString = new G4ExcitedString( Ganti_quark, start , +1 );
1395           Gquark->Set4Momentum( PkinkQ1 );
1396           Ganti_quark->Set4Momentum( PkinkQ2 );
1397         } else {                            // Anti_DiQuark on the end or quark
1398           FirstString  = new G4ExcitedString( end   , Ganti_quark, +1 );
1399           SecondString = new G4ExcitedString( Gquark, start      , +1 );
1400           Ganti_quark->Set4Momentum( PkinkQ1 );
1401           Gquark->Set4Momentum( PkinkQ2 );
1402         }
1403       } else {  // Target
1404         if ( end->GetDefinition()->GetParticleType() == "diquarks"  &&
1405              end->GetDefinition()->GetPDGEncoding() > 0 ) {  // DiQuark on the end
1406           Gquark->Set4Momentum( PkinkQ1 );
1407           Ganti_quark->Set4Momentum( PkinkQ2 );
1408           FirstString  = new G4ExcitedString(         end, Gquark, -1 );
1409           SecondString = new G4ExcitedString( Ganti_quark,  start, -1 );
1410         } else {  // Anti_DiQuark on the end or Q
1411           FirstString  = new G4ExcitedString( Ganti_quark, end   , -1 );
1412           SecondString = new G4ExcitedString( start      , Gquark, -1 );
1413           Gquark->Set4Momentum( PkinkQ2 );
1414           Ganti_quark->Set4Momentum( PkinkQ1 );
1415         }
1416       }
1417     }
1418 
1419     FirstString->SetTimeOfCreation( hadron->GetTimeOfCreation() );
1420     FirstString->SetPosition( hadron->GetPosition() );
1421     SecondString->SetTimeOfCreation( hadron->GetTimeOfCreation() );
1422     SecondString->SetPosition( hadron->GetPosition() );
1423   
1424   } else {  // Kink is impossible
1425 
1426     if ( isProjectile ) {
1427       FirstString = new G4ExcitedString( end, start, +1 );
1428     } else {
1429       FirstString = new G4ExcitedString( end, start, -1 );
1430     }
1431     FirstString->SetTimeOfCreation( hadron->GetTimeOfCreation() );
1432     FirstString->SetPosition( hadron->GetPosition() );
1433     SecondString = 0;
1434     // momenta of string ends
1435     G4LorentzVector HadronMom = hadron->Get4Momentum();
1436     G4LorentzVector Pstart1 = G4LorentzVector( HadronMom.px()/2.0, HadronMom.py()/2.0, 0.0, 0.0 );  //    Quark momentum
1437     G4LorentzVector   Pend1 = G4LorentzVector( HadronMom.px()/2.0, HadronMom.py()/2.0, 0.0, 0.0 );  // Di-quark momentum
1438     G4double Pz  = HadronMom.pz();
1439     G4double Eh  = HadronMom.e();
1440     G4double Pt2 = sqr( HadronMom.px() ) + sqr( HadronMom.py() );
1441     G4double Mt2 = HadronMom.mt2();
1442     G4double Exp = std::sqrt( sqr(Pz) + ( sqr(Mt2) - 4.0*sqr(Eh)*Pt2/4.0 )/Mt2 )/2.0;
1443     G4double Pzq  = Pz/2.0 - Exp;                      Pstart1.setZ( Pzq );
1444     G4double Eq   = std::sqrt( sqr(Pzq) + Pt2/4.0 );   Pstart1.setE( Eq );
1445     G4double Pzqq = Pz/2.0 + Exp;                      Pend1.setZ(Pzqq);
1446     G4double Eqq  = std::sqrt( sqr(Pzqq) + Pt2/4.0 );  Pend1.setE(Eqq);
1447     start->Set4Momentum( Pstart1 );
1448     end->Set4Momentum( Pend1 );
1449     Pstart = Pstart1;  Pend = Pend1;
1450 
1451   }  // End of "if (Kink)"
1452 
1453   //G4cout << "Quarks in the string at creation" << FirstString->GetRightParton()->GetPDGcode()
1454   //       << " " << FirstString->GetLeftParton()->GetPDGcode() << G4endl
1455   //       << FirstString << " " << SecondString << G4endl;
1456 
1457   #ifdef G4_FTFDEBUG
1458   G4cout << " generated string flavors          " << start->GetPDGcode() << " / " 
1459          << end->GetPDGcode() << G4endl << " generated string momenta:   quark " 
1460          << start->Get4Momentum() << "mass : " << start->Get4Momentum().mag() << G4endl
1461          << " generated string momenta: Diquark " << end->Get4Momentum() << "mass : " 
1462          << end->Get4Momentum().mag() << G4endl << " sum of ends                       "
1463          << Pstart + Pend << G4endl << " Original                          " 
1464          << hadron->Get4Momentum() << " "<<hadron->Get4Momentum().mag() << G4endl;
1465   #endif
1466 
1467   return;
1468 }
1469 
1470 
1471 //============================================================================
1472 
1473 G4double G4DiffractiveExcitation::ChooseP( G4double Pmin, G4double Pmax ) const {
1474   // Choose an x between Xmin and Xmax with P(x) ~ 1/x . 
1475   // To be improved...
1476   G4double range = Pmax - Pmin;                    
1477   if ( Pmin <= 0.0 || range <= 0.0 ) {
1478     G4cout << " Pmin, range : " << Pmin << " , " << range << G4endl;
1479     throw G4HadronicException( __FILE__, __LINE__,
1480                                "G4DiffractiveExcitation::ChooseP : Invalid arguments " );
1481   }
1482   G4double P = Pmin * G4Pow::GetInstance()->powA( Pmax/Pmin, G4UniformRand() ); 
1483   //G4double P = (Pmax - Pmin) * G4UniformRand() + Pmin;
1484   return P;
1485 }
1486 
1487 
1488 //============================================================================
1489 
1490 G4ThreeVector G4DiffractiveExcitation::GaussianPt( G4double AveragePt2, G4double maxPtSquare ) const {
1491   //  @@ this method is used in FTFModel as well. Should go somewhere common!
1492   G4double Pt2( 0.0 );
1493   if ( AveragePt2 <= 0.0 ) {
1494     Pt2 = 0.0;
1495   } else {
1496     Pt2 = -AveragePt2 * G4Log( 1.0 + G4UniformRand() * 
1497                                        ( G4Exp( -maxPtSquare/AveragePt2 ) - 1.0 ) );
1498   }
1499   G4double Pt = std::sqrt( Pt2 );
1500   G4double phi = G4UniformRand() * twopi;
1501   return G4ThreeVector( Pt * std::cos( phi ), Pt * std::sin( phi ), 0.0 );
1502 }
1503 
1504 
1505 //============================================================================
1506 
1507 G4double G4DiffractiveExcitation::GetQuarkFractionOfKink( G4double zmin, G4double zmax ) const {
1508   G4double z, yf;
1509   const G4int maxNumberOfLoops = 10000;
1510   G4int loopCounter = 0;
1511   do {
1512     z = zmin + G4UniformRand() * (zmax - zmin);
1513     yf = z*z + sqr(1.0 - z);
1514   } while ( ( G4UniformRand() > yf ) && 
1515             ++loopCounter < maxNumberOfLoops );  /* Loop checking, 10.08.2015, A.Ribon */
1516   if ( loopCounter >= maxNumberOfLoops ) {
1517     z = 0.5*(zmin + zmax);  // Just something acceptable, without any physics consideration.
1518   }
1519   return z;
1520 }
1521 
1522 
1523 //============================================================================
1524 
1525 void G4DiffractiveExcitation::UnpackMeson( const G4int IdPDG, G4int& Q1, G4int& Q2 ) const {
1526   G4int absIdPDG = std::abs( IdPDG );
1527   if ( ! ( absIdPDG == 111 || absIdPDG == 221 || absIdPDG == 331 ||     // Pi0  ,  Eta ,   Eta'
1528            absIdPDG == 441 || absIdPDG == 443 || absIdPDG == 553 ) ) {  // Etac ,  J/psi , Upsilon 
1529     // All other projectile mesons (including charmed and bottom ones)
1530     Q1 =  absIdPDG / 100;
1531     Q2 = (absIdPDG % 100) / 10;
1532     G4int anti = 1 - 2 * ( std::max( Q1, Q2 ) % 2 );
1533     if ( IdPDG < 0 ) anti *= -1;
1534     Q1 *= anti;
1535     Q2 *= -1 * anti;
1536   } else {
1537     if ( absIdPDG == 441 || absIdPDG == 443 ) {  // Etac , J/psi
1538       Q1 =  4; Q2 = -4;
1539     } else if ( absIdPDG == 553 ) {              // Upsilon
1540       Q1 =  5; Q2 = -5;
1541     } else {                                     // Pi0 , Eta , Eta'
1542       if ( G4UniformRand() < 0.5 ) {
1543   Q1 = 1; Q2 = -1;
1544       } else {
1545   Q1 = 2; Q2 = -2;
1546       }
1547     }
1548   }
1549   return;
1550 }
1551 
1552 
1553 //============================================================================
1554 
1555 void G4DiffractiveExcitation::UnpackBaryon( G4int IdPDG, 
1556                                             G4int& Q1, G4int& Q2, G4int& Q3 ) const {
1557   Q1 = IdPDG          / 1000;
1558   Q2 = (IdPDG % 1000) / 100;
1559   Q3 = (IdPDG % 100)  / 10;
1560   return;
1561 }
1562 
1563 
1564 //============================================================================
1565 
1566 G4int G4DiffractiveExcitation::NewNucleonId( G4int Q1, G4int Q2, G4int Q3 ) const {
1567   // Order the three integers in such a way that Q1 >= Q2 >= Q3
1568   G4int TmpQ( 0 );
1569   if ( Q3 > Q2 ) {
1570     TmpQ = Q2;
1571     Q2 = Q3;
1572     Q3 = TmpQ;
1573   } else if ( Q3 > Q1 ) {
1574     TmpQ = Q1;
1575     Q1 = Q3;
1576     Q3 = TmpQ;
1577   }
1578   if ( Q2 > Q1 ) {
1579     TmpQ = Q1;
1580     Q1 = Q2;
1581     Q2 = TmpQ;
1582   }
1583   // By now Q1 >= Q2 >= Q3
1584   G4int NewCode = Q1*1000 + Q2*100 + Q3*10 + 2;
1585   return NewCode;
1586 }
1587 
1588 
1589 //============================================================================
1590 
1591 G4DiffractiveExcitation::G4DiffractiveExcitation( const G4DiffractiveExcitation& ) {
1592   throw G4HadronicException( __FILE__, __LINE__, 
1593                              "G4DiffractiveExcitation copy constructor not meant to be called" );
1594 }
1595 
1596 
1597 //============================================================================
1598 
1599 const G4DiffractiveExcitation & G4DiffractiveExcitation::operator=( const G4DiffractiveExcitation& ) {
1600   throw G4HadronicException( __FILE__, __LINE__, 
1601                              "G4DiffractiveExcitation = operator not meant to be called" );
1602   return *this;
1603 }
1604 
1605 
1606 //============================================================================
1607 
1608 G4bool G4DiffractiveExcitation::operator==( const G4DiffractiveExcitation& ) const {
1609   throw G4HadronicException( __FILE__, __LINE__, 
1610                              "G4DiffractiveExcitation == operator not meant to be called" );
1611 }
1612 
1613 
1614 //============================================================================
1615 
1616 G4bool G4DiffractiveExcitation::operator!= ( const G4DiffractiveExcitation& ) const {
1617   throw G4HadronicException( __FILE__, __LINE__, 
1618                              "G4DiffractiveExcitation != operator not meant to be called" );
1619 }
1620 
1621