Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/hadronic/models/parton_string/management/src/G4VPartonStringModel.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 //      GEANT 4 class implementation file
 30 //
 31 //      ---------------- G4VPartonStringModel ----------------
 32 //             by Gunter Folger, May 1998.
 33 //      abstract class for all Parton String Models
 34 // ------------------------------------------------------------
 35 // debug switch
 36 //#define debug_PartonStringModel
 37 //#define debug_heavyHadrons
 38 // ------------------------------------------------------------
 39 
 40 #include "G4VPartonStringModel.hh"
 41 #include "G4ios.hh"
 42 #include "G4ShortLivedConstructor.hh"
 43 
 44 #include "G4ParticleTable.hh"
 45 #include "G4IonTable.hh"
 46 
 47 G4VPartonStringModel::G4VPartonStringModel(const G4String& modelName)
 48     : G4VHighEnergyGenerator(modelName),
 49       stringFragmentationModel(nullptr)
 50 {
 51   //  Make shure Shotrylived particles are constructed.
 52   //  VI: should not instantiate particles by any model
 53   /*
 54   G4ShortLivedConstructor ShortLived;
 55   ShortLived.ConstructParticle();
 56   */
 57 }
 58 
 59 G4VPartonStringModel::~G4VPartonStringModel()
 60 {
 61 }
 62 
 63 G4KineticTrackVector * G4VPartonStringModel::Scatter(const G4Nucleus &theNucleus, 
 64                                                 const G4DynamicParticle &aPrimary)
 65 {  
 66   G4ExcitedStringVector * strings = nullptr;
 67   G4DynamicParticle thePrimary=aPrimary;
 68   G4LorentzVector SumStringMom(0.,0.,0.,0.);
 69   G4KineticTrackVector * theResult = 0;
 70   G4Nucleon * theNuclNucleon(nullptr);
 71 
 72   #ifdef debug_PartonStringModel
 73   G4cout<<G4endl;
 74   G4cout<<"-----------------------Parton-String model is runnung ------------"<<G4endl;
 75   G4cout<<"Projectile Name Mass "<<thePrimary.GetDefinition()->GetParticleName()<<" "
 76                                  <<thePrimary.GetMass()<<G4endl;
 77   G4cout<<"           Momentum  "<<thePrimary.Get4Momentum()<<G4endl;
 78   G4cout<<"Target nucleus   A Z "<<theNucleus.GetA_asInt()<<" "
 79                                  <<theNucleus.GetZ_asInt()<<G4endl<<G4endl; 
 80   G4int Bsum=thePrimary.GetDefinition()->GetBaryonNumber() + theNucleus.GetA_asInt();
 81   G4int Qsum=thePrimary.GetDefinition()->GetPDGCharge() + theNucleus.GetZ_asInt();
 82   G4cout<<"Initial baryon number "<<Bsum<<G4endl;
 83   G4cout<<"Initial charge        "<<Qsum<<G4endl;
 84   G4cout<<"-------------- Parton-String model:  Generation of strings -------"<<G4endl<<G4endl;
 85   Bsum -= theNucleus.GetA_asInt();  Qsum -= theNucleus.GetZ_asInt();
 86   if(GetProjectileNucleus()) {
 87     Bsum -= thePrimary.GetDefinition()->GetBaryonNumber();
 88     Qsum -= thePrimary.GetDefinition()->GetPDGCharge();
 89   }
 90   G4int QsumSec(0), BsumSec(0);
 91   G4LorentzVector SumPsecondr(0.,0.,0.,0.);
 92   #endif
 93 
 94   G4LorentzRotation toZ;
 95   G4LorentzVector Ptmp=thePrimary.Get4Momentum();
 96   toZ.rotateZ(-1*Ptmp.phi());
 97   toZ.rotateY(-1*Ptmp.theta());
 98   thePrimary.Set4Momentum(toZ*Ptmp);
 99   G4LorentzRotation toLab(toZ.inverse());
100 
101   G4bool Success=true;
102   G4int attempts = 0, maxAttempts=1000;
103   do
104   {
105     if (attempts++ > maxAttempts ) 
106     {
107       Init(theNucleus,thePrimary);  // To put a nucleus into ground state
108                                              // But marks of hitted nucleons are left. They must be erased.
109       G4V3DNucleus * ResNucleus = GetWoundedNucleus(); 
110       theNuclNucleon = ResNucleus->StartLoop() ? ResNucleus->GetNextNucleon() : nullptr;
111       while( theNuclNucleon )
112       {
113         if(theNuclNucleon->AreYouHit()) theNuclNucleon->Hit(nullptr);
114         theNuclNucleon = ResNucleus->GetNextNucleon();
115       }
116 
117       G4V3DNucleus * ProjResNucleus = GetProjectileNucleus();
118       if(ProjResNucleus != 0)
119       {
120         theNuclNucleon = ProjResNucleus->StartLoop() ? ProjResNucleus->GetNextNucleon() : nullptr;
121         while( theNuclNucleon )
122         {
123           if(theNuclNucleon->AreYouHit()) theNuclNucleon->Hit(nullptr);
124           theNuclNucleon = ProjResNucleus->GetNextNucleon();
125         }
126       }
127 
128       G4ExceptionDescription ed;
129       ed << "Projectile Name Mass " <<thePrimary.GetDefinition()->GetParticleName()
130          << " " << thePrimary.GetMass()<< G4endl;
131       ed << "           Momentum  " << thePrimary.Get4Momentum() <<G4endl;
132       ed << "Target nucleus   A Z " << theNucleus.GetA_asInt() << " "
133                                       << theNucleus.GetZ_asInt() <<G4endl;
134       ed << "Initial states of projectile and target nucleus will be returned!"<<G4endl;
135       G4Exception( "G4VPartonStringModel::Scatter(): fails to generate or fragment strings ",
136                    "HAD_PARTON_STRING_001", JustWarning, ed );
137 
138       G4ThreeVector Position(0.,0.,2*ResNucleus->GetOuterRadius());
139       G4KineticTrack* Hadron = new G4KineticTrack(aPrimary.GetParticleDefinition(), 0.,
140                                                   Position, aPrimary.Get4Momentum());
141       if(theResult == nullptr) theResult = new G4KineticTrackVector();
142       theResult->push_back(Hadron);
143       return theResult;
144     }
145 
146     Success=true;
147 
148     Init(theNucleus,thePrimary);
149 
150     strings = GetStrings();
151 
152     if (strings->empty()) { Success=false; continue; }
153 
154     // G4double stringEnergy(0);
155     SumStringMom=G4LorentzVector(0.,0.,0.,0.);
156 
157     #ifdef debug_PartonStringModel
158     G4cout<<"------------ Parton-String model: Number of produced strings ---- "<<strings->size()<<G4endl;
159     #endif
160 
161     #ifdef debug_heavyHadrons
162     // Check charm and bottom numbers of the projectile:
163     G4int count_charm_projectile  = thePrimary.GetDefinition()->GetQuarkContent( 4 ) -
164                                     thePrimary.GetDefinition()->GetAntiQuarkContent( 4 );
165     G4int count_bottom_projectile = thePrimary.GetDefinition()->GetQuarkContent( 5 ) -
166                                     thePrimary.GetDefinition()->GetAntiQuarkContent( 5 );
167     G4int count_charm_strings = 0, count_bottom_strings = 0;
168     G4int count_charm_hadrons = 0, count_bottom_hadrons = 0;
169     #endif
170     
171     for ( unsigned int astring=0; astring < strings->size(); astring++)
172     {
173       //    rotate string to lab frame, models have it aligned to z
174       if((*strings)[astring]->IsExcited())
175       {
176         // stringEnergy += (*strings)[astring]->GetLeftParton()->Get4Momentum().t();
177         // stringEnergy += (*strings)[astring]->GetRightParton()->Get4Momentum().t();
178         (*strings)[astring]->LorentzRotate(toLab);
179         SumStringMom+=(*strings)[astring]->Get4Momentum();
180         #ifdef debug_PartonStringModel
181         G4cout<<"String No "<<astring+1<<" "<<(*strings)[astring]->Get4Momentum()<<" "
182                             <<(*strings)[astring]->Get4Momentum().mag()
183               <<" Partons   "<<(*strings)[astring]->GetLeftParton()->GetDefinition()->GetPDGEncoding()
184               <<"          "<<(*strings)[astring]->GetRightParton()->GetDefinition()->GetPDGEncoding()<<G4endl;
185         #endif
186 
187         #ifdef debug_heavyHadrons
188   G4int left_charm =      (*strings)[astring]->GetLeftParton()->GetDefinition()->GetQuarkContent( 4 );
189   G4int left_anticharm =  (*strings)[astring]->GetLeftParton()->GetDefinition()->GetAntiQuarkContent( 4 );
190   G4int right_charm =     (*strings)[astring]->GetRightParton()->GetDefinition()->GetQuarkContent( 4 );
191   G4int right_anticharm = (*strings)[astring]->GetRightParton()->GetDefinition()->GetAntiQuarkContent( 4 );
192   G4int left_bottom =      (*strings)[astring]->GetLeftParton()->GetDefinition()->GetQuarkContent( 5 );
193   G4int left_antibottom =  (*strings)[astring]->GetLeftParton()->GetDefinition()->GetAntiQuarkContent( 5 );
194   G4int right_bottom =     (*strings)[astring]->GetRightParton()->GetDefinition()->GetQuarkContent( 5 );
195   G4int right_antibottom = (*strings)[astring]->GetRightParton()->GetDefinition()->GetAntiQuarkContent( 5 );
196   if ( left_charm  != 0  ||  left_anticharm  != 0  ||  right_charm  != 0  ||  right_anticharm  != 0  ||
197        left_bottom != 0  ||  left_antibottom != 0  ||  right_bottom != 0  ||  right_antibottom != 0 ) {
198     count_charm_strings  += left_charm  - left_anticharm  + right_charm  - right_anticharm;
199     count_bottom_strings += left_bottom - left_antibottom + right_bottom - right_antibottom;
200     G4cout << "G4VPartonStringModel::Scatter : string #" << astring << " ("
201      << (*strings)[astring]->GetLeftParton()->GetDefinition()->GetParticleName() << " , "
202      << (*strings)[astring]->GetRightParton()->GetDefinition()->GetParticleName() << ")" << G4endl;
203   }
204         #endif  
205       }
206       else
207       {
208         // stringEnergy += (*strings)[astring]->GetKineticTrack()->Get4Momentum().t();
209         (*strings)[astring]->LorentzRotate(toLab);
210         SumStringMom+=(*strings)[astring]->GetKineticTrack()->Get4Momentum();
211         #ifdef debug_PartonStringModel
212         G4cout<<"A track No "<<astring+1<<" "
213               <<(*strings)[astring]->GetKineticTrack()->Get4Momentum()<<" "
214               <<(*strings)[astring]->GetKineticTrack()->Get4Momentum().mag()<<" "
215               <<(*strings)[astring]->GetKineticTrack()->GetDefinition()->GetParticleName()<<G4endl;
216         #endif
217 
218         #ifdef debug_heavyHadrons
219   G4int charm =      (*strings)[astring]->GetKineticTrack()->GetDefinition()->GetQuarkContent( 4 );
220   G4int anticharm =  (*strings)[astring]->GetKineticTrack()->GetDefinition()->GetAntiQuarkContent( 4 );
221   G4int bottom =     (*strings)[astring]->GetKineticTrack()->GetDefinition()->GetQuarkContent( 5 );
222   G4int antibottom = (*strings)[astring]->GetKineticTrack()->GetDefinition()->GetAntiQuarkContent( 5 );
223         if ( charm != 0  ||  anticharm != 0  ||  bottom != 0  || antibottom != 0 ) {
224     count_charm_strings +=  charm  - anticharm;
225     count_bottom_strings += bottom - antibottom;
226     G4cout << "G4VPartonStringModel::Scatter : track #" << astring << "\t"
227                  << (*strings)[astring]->GetKineticTrack()->GetDefinition()->GetParticleName() << G4endl;
228   }
229         #endif
230       }
231     }
232 
233     #ifdef debug_heavyHadrons
234     if ( count_charm_projectile != count_charm_strings ) {
235       G4cout << "G4VPartonStringModel::Scatter : CHARM VIOLATION in String formation ! #projectile="
236        << count_charm_projectile << " ; #strings=" << count_charm_strings << G4endl;
237     }
238     if ( count_bottom_projectile != count_bottom_strings ) {
239       G4cout << "G4VPartonStringModel::Scatter : BOTTOM VIOLATION in String formation ! #projectile="
240        << count_bottom_projectile << " ; #strings=" << count_bottom_strings << G4endl;
241     }
242     #endif
243     
244     #ifdef debug_PartonStringModel
245     G4cout<<G4endl<<"SumString4Mom "<<SumStringMom<<G4endl;
246     G4LorentzVector TargetResidual4Momentum(0.,0.,0.,0.);
247     G4LorentzVector ProjectileResidual4Momentum(0.,0.,0.,0.);
248     G4int hitsT(0), charged_hitsT(0);
249     G4int hitsP(0), charged_hitsP(0);
250     G4double ExcitationEt(0.), ExcitationEp(0.);
251     #endif
252 
253     // We assume that the target nucleus is never a hypernucleus, whereas
254     // the projectile nucleus can be a light hypernucleus or anti-hypernucleus.
255     
256     G4V3DNucleus * ProjResNucleus = GetProjectileNucleus();
257 
258     G4int numberProtonProjectileResidual( 0 ), numberNeutronProjectileResidual( 0 );
259     G4int numberLambdaProjectileResidual( 0 );
260     if(ProjResNucleus != 0)
261     {
262       theNuclNucleon = ProjResNucleus->StartLoop() ? ProjResNucleus->GetNextNucleon() : nullptr;
263       G4int numberProtonProjectileHits( 0 ), numberNeutronProjectileHits( 0 );
264       G4int numberLambdaProjectileHits( 0 );
265       while( theNuclNucleon )
266       {
267         if(theNuclNucleon->AreYouHit())
268         {
269           G4LorentzVector tmp=toLab*theNuclNucleon->Get4Momentum();
270     const G4ParticleDefinition* def = theNuclNucleon->GetDefinition();
271           #ifdef debug_PartonStringModel
272           ProjectileResidual4Momentum += tmp;
273           hitsP++;
274           if ( def == G4Proton::Definition() || def == G4AntiProton::Definition() ) ++charged_hitsP;
275           ExcitationEp +=theNuclNucleon->GetBindingEnergy();
276           #endif
277           theNuclNucleon->SetMomentum(tmp);
278           if ( def == G4Proton::Definition()  || def == G4AntiProton::Definition() )  ++numberProtonProjectileHits;
279           if ( def == G4Neutron::Definition() || def == G4AntiNeutron::Definition() ) ++numberNeutronProjectileHits;
280           if ( def == G4Lambda::Definition()  || def == G4AntiLambda::Definition() )  ++numberLambdaProjectileHits;
281         }
282         theNuclNucleon = ProjResNucleus->GetNextNucleon();
283       }
284       G4int numberLambdaProjectile = 0;
285       if ( thePrimary.GetDefinition()->IsHypernucleus() ) {
286   numberLambdaProjectile = thePrimary.GetDefinition()->GetNumberOfLambdasInHypernucleus();
287       } else if ( thePrimary.GetDefinition()->IsAntiHypernucleus() ) {
288   numberLambdaProjectile = thePrimary.GetDefinition()->GetNumberOfAntiLambdasInAntiHypernucleus();
289       }
290       #ifdef debug_PartonStringModel
291       G4cout<<"Projectile residual A, Z (numberOfLambdasOrAntiLambdas) and E* "
292             <<thePrimary.GetDefinition()->GetBaryonNumber() - hitsP<<" "
293             <<thePrimary.GetDefinition()->GetPDGCharge()    - charged_hitsP<<" ("
294       << numberLambdaProjectile - numberLambdaProjectileHits << ") "
295             <<ExcitationEp<<G4endl;
296       G4cout<<"Projectile residual 4 momentum  "<<ProjectileResidual4Momentum<<G4endl;
297       #endif
298       numberProtonProjectileResidual = std::max( std::abs( G4int( thePrimary.GetDefinition()->GetPDGCharge() ) ) -
299              numberProtonProjectileHits, 0 );
300       numberLambdaProjectileResidual = std::max( numberLambdaProjectile - numberLambdaProjectileHits, 0 );
301       numberNeutronProjectileResidual = std::max( std::abs( thePrimary.GetDefinition()->GetBaryonNumber() ) -
302                                                   std::abs( G4int( thePrimary.GetDefinition()->GetPDGCharge() ) ) -
303               numberLambdaProjectile - numberNeutronProjectileHits, 0 );
304     }
305 
306     G4V3DNucleus * ResNucleus = GetWoundedNucleus(); 
307 
308     // loop over wounded nucleus
309     theNuclNucleon = ResNucleus->StartLoop() ? ResNucleus->GetNextNucleon() : nullptr;
310     G4int numberProtonTargetHits( 0 ), numberNeutronTargetHits( 0 );
311     while( theNuclNucleon )
312     {
313       if(theNuclNucleon->AreYouHit())
314       {
315         G4LorentzVector tmp=toLab*theNuclNucleon->Get4Momentum();
316         #ifdef debug_PartonStringModel
317         TargetResidual4Momentum += tmp;
318         hitsT++;
319         if ( theNuclNucleon->GetDefinition() == G4Proton::Proton() )  ++charged_hitsT;
320         ExcitationEt +=theNuclNucleon->GetBindingEnergy();
321         #endif
322         theNuclNucleon->SetMomentum(tmp);
323         if ( theNuclNucleon->GetDefinition() == G4Proton::Proton() )   ++numberProtonTargetHits;
324         if ( theNuclNucleon->GetDefinition() == G4Neutron::Neutron() ) ++numberNeutronTargetHits;
325       }
326       theNuclNucleon = ResNucleus->GetNextNucleon();
327     }
328 
329     #ifdef debug_PartonStringModel
330     G4cout<<"Target residual A, Z and E* "
331           <<theNucleus.GetA_asInt() - hitsT<<" "
332           <<theNucleus.GetZ_asInt() - charged_hitsT<<" "
333           <<ExcitationEt<<G4endl;
334     G4cout<<"Target residual 4 momentum "<<TargetResidual4Momentum<<G4endl;
335     Bsum+=(        hitsT +         hitsP);
336     Qsum+=(charged_hitsT + charged_hitsP);
337     G4cout<<"Hitted # of nucleons of projectile and target "<<hitsP<<" "<<hitsT<<G4endl;
338     G4cout<<"Hitted # of protons of projectile and target  "
339           <<charged_hitsP<<" "<<charged_hitsT<<G4endl<<G4endl;
340     G4cout<<"Bsum Qsum "<<Bsum<<" "<<Qsum<<G4endl<<G4endl;
341     #endif
342 
343     // Re-sample in the case of unphysical nuclear residual:
344     // 1 (H), 2 (2He), and 3 (3Li) protons alone without neutrons can exist, but not more;
345     // no bound states of 2 or more neutrons without protons can exist.
346     G4int numberProtonTargetResidual = theNucleus.GetZ_asInt() - numberProtonTargetHits;
347     G4int numberNeutronTargetResidual = theNucleus.GetA_asInt() - theNucleus.GetZ_asInt() - numberNeutronTargetHits;
348     G4bool unphysicalResidual = false;
349     if ( ( numberProtonTargetResidual > 3   &&  numberNeutronTargetResidual == 0 ) ||
350          ( numberProtonTargetResidual == 0  &&  numberNeutronTargetResidual > 1  ) ) {
351       unphysicalResidual = true;
352       //G4cout << "***UNPHYSICAL TARGET RESIDUAL*** Z=" << numberProtonTargetResidual 
353       //       << " ; N=" << numberNeutronTargetResidual;
354     }
355     // The projectile residual can be a hypernucleus or anti-hypernucleus:
356     // only the following combinations are currently allowed in Geant4:
357     // p-n-lambda (hypertriton), p-n-n-lambda (hyperH4), p-p-n-lambda (hyperAlpha),
358     // p-p-n-n-lambda (hyperHe5), n-n-lambda-lambda (doublehyperdoubleneutron),
359     // p-n-lambda-lambda (doubleHyperH4)
360     if ( ( numberProtonProjectileResidual > 3   &&  numberNeutronProjectileResidual == 0 ) ||
361          ( numberProtonProjectileResidual == 0  &&  numberNeutronProjectileResidual > 1  &&
362      numberLambdaProjectileResidual == 0 ) ||
363    ( numberProtonProjectileResidual == 0  &&  numberNeutronProjectileResidual <= 1  &&
364      numberLambdaProjectileResidual > 0 ) ||
365    ( numberProtonProjectileResidual == 0  &&  numberNeutronProjectileResidual > 2  &&
366      numberLambdaProjectileResidual > 0 ) ||
367    ( numberLambdaProjectileResidual > 2 ) ||
368    ( numberProtonProjectileResidual > 0  &&  numberNeutronProjectileResidual == 0  &&
369      numberLambdaProjectileResidual > 0 ) ||
370    ( numberProtonProjectileResidual > 1  &&  numberNeutronProjectileResidual > 1  &&
371      numberLambdaProjectileResidual > 1 )
372    ) {
373       unphysicalResidual = true;
374       //G4cout << "***UNPHYSICAL PROJECTILE RESIDUAL*** Z=" << numberProtonProjectileResidual
375       //       << " ; N=" << numberNeutronProjectileResidual
376       //       << " ; L=" << numberLambdaProjectileResidual;
377     }
378     if ( unphysicalResidual ) {
379       //G4cout << " -> REJECTING COLLISION because of unphysical residual !" << G4endl;
380       Success = false;
381       continue;
382     }
383 
384     //=========================================================================================
385     //                              Fragment strings
386     #ifdef debug_PartonStringModel
387     G4cout<<"---------------- Attempt to fragment strings ------------- "<<attempts<<G4endl;
388     #endif
389 
390     G4double InvMass=SumStringMom.mag();
391     G4double SumMass(0.); 
392 
393     #ifdef debug_PartonStringModel
394     QsumSec=0; BsumSec=0;
395     SumPsecondr=G4LorentzVector(0.,0.,0.,0.);
396     #endif
397 
398     if(theResult != nullptr)
399     {
400       std::for_each(theResult->begin(), theResult->end(), DeleteKineticTrack());
401       delete theResult;
402     }
403 
404     theResult = stringFragmentationModel->FragmentStrings(strings);
405 
406     #ifdef debug_PartonStringModel
407     G4cout<<"String fragmentation success (OK - #0, Not OK - 0) : "<<theResult<<G4endl;
408     #endif
409 
410     if(theResult == 0) {Success=false; continue;}
411 
412     #ifdef debug_PartonStringModel
413     G4cout<<"Parton-String model: Number of produced particles "<<theResult->size()<<G4endl;
414     SumPsecondr = G4LorentzVector(0.,0.,0.,0.);
415     QsumSec = 0; BsumSec = 0;
416     #endif
417 
418     SumMass=0.;
419     for ( unsigned int i=0; i < theResult->size(); i++)
420     {
421       SumMass+=(*theResult)[i]->Get4Momentum().mag();
422       #ifdef debug_PartonStringModel
423       G4cout<<i<<" : "<<(*theResult)[i]->GetDefinition()->GetParticleName()<<" "
424                       <<(*theResult)[i]->Get4Momentum()<<" "
425                       <<(*theResult)[i]->Get4Momentum().mag()<<" "
426                       <<(*theResult)[i]->GetDefinition()->GetPDGMass()<<G4endl;
427       SumPsecondr+=(*theResult)[i]->Get4Momentum();
428       BsumSec += (*theResult)[i]->GetDefinition()->GetBaryonNumber();
429       QsumSec += (*theResult)[i]->GetDefinition()->GetPDGCharge();
430       #endif
431 
432       #ifdef debug_heavyHadrons
433       G4int charm =      (*theResult)[i]->GetDefinition()->GetQuarkContent( 4 );
434       G4int anticharm =  (*theResult)[i]->GetDefinition()->GetAntiQuarkContent( 4 );
435       G4int bottom =     (*theResult)[i]->GetDefinition()->GetQuarkContent( 5 );
436       G4int antibottom = (*theResult)[i]->GetDefinition()->GetAntiQuarkContent( 5 );
437       if ( charm != 0  ||  anticharm != 0  ||  bottom != 0  || antibottom != 0 ) {
438         count_charm_hadrons +=  charm - anticharm;          
439         count_bottom_hadrons += bottom - antibottom;
440   G4cout << "G4VPartonStringModel::Scatter : hadron #" << i << "\t"
441                << (*theResult)[i]->GetDefinition()->GetParticleName() << G4endl;
442       }
443       #endif  
444     }
445 
446     #ifdef debug_heavyHadrons
447     if ( count_charm_projectile != count_charm_hadrons ) {
448       G4cout << "G4VPartonStringModel::Scatter : CHARM VIOLATION in String hadronization ! #projectile="
449        << count_charm_projectile << " ; #hadrons=" << count_charm_hadrons << G4endl;
450     }
451     if ( count_bottom_projectile != count_bottom_hadrons ) {
452       G4cout << "G4VPartonStringModel::Scatter : BOTTOM VIOLATION in String hadronization ! #projectile="
453        << count_bottom_projectile << " ; #hadrons=" << count_bottom_hadrons << G4endl;
454     }
455     #endif
456     
457     #ifdef debug_PartonStringModel
458     G4cout<<G4endl<<"-----------------------Parton-String model: balances -------------"<<G4endl;
459     if(Qsum != QsumSec) {
460       G4cout<<"Charge is not conserved!!! ----"<<G4endl; 
461       G4cout<<" Qsum != QsumSec "<<Qsum<<" "<<QsumSec<<G4endl;
462     }
463     if(Bsum != BsumSec) {
464       G4cout<<"Baryon number is not conserved!!!"<<G4endl;
465       G4cout<<" Bsum != BsumSec "<<Bsum<<" "<<BsumSec<<G4endl;
466     }
467     #endif
468 
469     if((SumMass > InvMass)||(SumMass == 0.)) {Success=false;}
470     std::for_each(strings->begin(), strings->end(), DeleteString() );
471     delete strings;
472 
473   } while(!Success);
474 
475   #ifdef debug_PartonStringModel
476   G4cout        <<"Baryon number balance "<<Bsum-BsumSec<<G4endl;
477   G4cout        <<"Charge balance        "<<Qsum-QsumSec<<G4endl;
478   G4cout        <<"4 momentum balance    "<<SumStringMom-SumPsecondr<<G4endl; 
479   G4cout<<"---------------------End of Parton-String model work -------------"<<G4endl<<G4endl;
480   #endif
481 
482   return theResult;
483 }
484 
485 void G4VPartonStringModel::ModelDescription(std::ostream& outFile) const
486 {
487   outFile << GetModelName() << " has no description yet.\n";
488 }
489 
490 G4V3DNucleus * G4VPartonStringModel::GetProjectileNucleus() const 
491 { return nullptr; }
492 
493