Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/hadronic/models/theo_high_energy/src/G4TheoFSGenerator.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 // G4TheoFSGenerator
 28 //
 29 // 20110307  M. Kelsey -- Add call to new theTransport->SetPrimaryProjectile()
 30 //    to provide access to full initial state (for Bertini)
 31 // 20110805  M. Kelsey -- Follow change to G4V3DNucleus::GetNucleons()
 32 
 33 #include "G4DynamicParticle.hh"
 34 #include "G4TheoFSGenerator.hh"
 35 #include "G4ReactionProductVector.hh"
 36 #include "G4ReactionProduct.hh"
 37 #include "G4IonTable.hh"
 38 #include "G4HadronicParameters.hh"
 39 #include "G4CRCoalescence.hh"
 40 #include "G4HadronicInteractionRegistry.hh"
 41 
 42 G4TheoFSGenerator::G4TheoFSGenerator(const G4String& name)
 43     : G4HadronicInteraction(name)
 44     , theTransport(nullptr), theHighEnergyGenerator(nullptr)
 45     , theQuasielastic(nullptr)
 46     , theCosmicCoalescence(nullptr)
 47     , theStringModelID(-1)
 48 {
 49   theParticleChange = new G4HadFinalState;
 50   theStringModelID = G4PhysicsModelCatalog::GetModelID( "model_" + name );
 51 }
 52 
 53 G4TheoFSGenerator::~G4TheoFSGenerator()
 54 {
 55   delete theParticleChange;
 56 }
 57 
 58 void G4TheoFSGenerator::ModelDescription(std::ostream& outFile) const
 59 {
 60   outFile << GetModelName() <<" consists of a " << theHighEnergyGenerator->GetModelName()
 61     << " string model and a stage to de-excite the excited nuclear fragment.\n<p>"
 62     << "The string model simulates the interaction of\n"
 63           << "an incident hadron with a nucleus, forming \n"
 64           << "excited strings, decays these strings into hadrons,\n"
 65           << "and leaves an excited nucleus. \n"
 66           << "<p>The string model:\n";
 67   theHighEnergyGenerator->ModelDescription(outFile);
 68   outFile <<"\n<p>";
 69   theTransport->PropagateModelDescription(outFile);
 70 }
 71 
 72 G4HadFinalState * G4TheoFSGenerator::ApplyYourself(const G4HadProjectile & thePrimary, G4Nucleus &theNucleus)
 73 {
 74   // init particle change
 75   theParticleChange->Clear();
 76   theParticleChange->SetStatusChange(stopAndKill);
 77   G4double timePrimary=thePrimary.GetGlobalTime();
 78 
 79   // Temporarily dummy treatment of heavy (charm and bottom) hadron projectiles at low energies.
 80   // Cascade models are currently not applicable for heavy hadrons and string models cannot
 81   // handle them properly at low energies - let's say safely below ~100 MeV.
 82   // In these cases, we return as final state the initial state unchanged.
 83   // For most applications, this is a safe simplification, giving that the nearly all
 84   // slowly moving charm and bottom hadrons decay before any hadronic interaction can occur.
 85   // Note that we prefer not to use G4HadronicParameters::GetMinEnergyTransitionFTF_Cascade()
 86   // (typically ~3 GeV) because FTFP works reasonably well below such a value.
 87   const G4double energyThresholdForCharmAndBottomHadrons = 100.0*CLHEP::MeV;
 88   if ( thePrimary.GetKineticEnergy() < energyThresholdForCharmAndBottomHadrons  &&
 89        ( thePrimary.GetDefinition()->GetQuarkContent( 4 )     != 0  ||    // Has charm       constituent quark
 90    thePrimary.GetDefinition()->GetAntiQuarkContent( 4 ) != 0  ||    // Has anti-charm  constituent anti-quark
 91    thePrimary.GetDefinition()->GetQuarkContent( 5 )     != 0  ||    // Has bottom      constituent quark
 92    thePrimary.GetDefinition()->GetAntiQuarkContent( 5 ) != 0 ) ) {  // Has anti-bottom constituent anti-quark
 93     theParticleChange->SetStatusChange( isAlive );
 94     theParticleChange->SetEnergyChange( thePrimary.GetKineticEnergy() );
 95     theParticleChange->SetMomentumChange( thePrimary.Get4Momentum().vect().unit() );
 96     return theParticleChange;
 97   }
 98 
 99   // Temporarily dummy treatment of light hypernuclei projectiles at low energies.
100   // Bertini and Binary intra-nuclear cascade models are currently not applicable
101   // for hypernuclei and string models cannot handle them properly at low energies -
102   // let's say safely below ~100 MeV.
103   // In these cases, we return as final state the initial state unchanged.
104   // For most applications, this is a safe simplification, giving that the nearly all
105   // slowly moving hypernuclei decay before any hadronic interaction can occur.
106   // Note that we prefer not to use G4HadronicParameters::GetMinEnergyTransitionFTF_Cascade()
107   // (typically ~3 GeV) because FTFP works reasonably well below such a value.
108   // Note that for anti-hypernuclei, FTF model works fine down to zero kinetic energy,
109   // so there is no need of any extra, dummy treatment.
110   const G4double energyThresholdForHyperNuclei = 100.0*CLHEP::MeV;
111   if ( thePrimary.GetKineticEnergy() < energyThresholdForHyperNuclei  &&
112        thePrimary.GetDefinition()->IsHypernucleus() ) {
113     theParticleChange->SetStatusChange( isAlive );
114     theParticleChange->SetEnergyChange( thePrimary.GetKineticEnergy() );
115     theParticleChange->SetMomentumChange( thePrimary.Get4Momentum().vect().unit() );
116     return theParticleChange;
117   }
118 
119   // check if models have been registered, and use default, in case this is not true @@
120   
121   const G4DynamicParticle aPart(thePrimary.GetDefinition(),thePrimary.Get4Momentum().vect());
122 
123   if ( theQuasielastic ) 
124   {
125      if ( theQuasielastic->GetFraction(theNucleus, aPart) > G4UniformRand() )
126      {
127        //G4cout<<"___G4TheoFSGenerator: before Scatter (1) QE=" << theQuasielastic<<G4endl;
128        G4KineticTrackVector *result= theQuasielastic->Scatter(theNucleus, aPart);
129        //G4cout << "^^G4TheoFSGenerator: after Scatter (1) " << G4endl;
130        if (result)
131        {
132       for(auto & ptr : *result)
133       {
134         G4DynamicParticle * aNew = 
135      new G4DynamicParticle(ptr->GetDefinition(),
136                                  ptr->Get4Momentum().e(),
137                                  ptr->Get4Momentum().vect());
138         theParticleChange->AddSecondary(aNew, ptr->GetCreatorModelID());
139         delete ptr;
140       }
141       delete result;     
142        } 
143        else 
144        {
145       theParticleChange->SetStatusChange(isAlive);
146       theParticleChange->SetEnergyChange(thePrimary.GetKineticEnergy());
147       theParticleChange->SetMomentumChange(thePrimary.Get4Momentum().vect().unit());
148        }
149        return theParticleChange;
150      } 
151   }
152 
153   // get result from high energy model
154   G4KineticTrackVector * theInitialResult =
155                theHighEnergyGenerator->Scatter(theNucleus, aPart);
156 
157   // Assign the creator model ID
158   for ( auto & ptr : *theInitialResult ) {
159     ptr->SetCreatorModelID( theStringModelID );
160   }
161 
162   //#define DEBUG_initial_result
163   #ifdef DEBUG_initial_result
164       G4double E_out(0);
165       G4IonTable * ionTable=G4ParticleTable::GetParticleTable()->GetIonTable();
166       for(auto & ptr : *theInitialResult)
167       {
168          //G4cout << "TheoFS secondary, mom " << ptr->GetDefinition()->GetParticleName() 
169              //         << " " << ptr->Get4Momentum() << G4endl;
170          E_out += ptr->Get4Momentum().e();
171       }
172       G4double init_mass= ionTable->GetIonMass(theNucleus.GetZ_asInt(),theNucleus.GetA_asInt());
173           G4double init_E=aPart.Get4Momentum().e();
174       // residual nucleus
175 
176       const std::vector<G4Nucleon> & thy = theHighEnergyGenerator->GetWoundedNucleus()->GetNucleons();
177 
178       G4int resZ(0),resA(0);
179     G4double delta_m(0);
180       for(auto & nuc : thy)
181       {
182          if(nuc.AreYouHit()) {
183            ++resA;
184            if ( nuc.GetDefinition() == G4Proton::Proton() ) {
185            ++resZ;
186      delta_m += CLHEP::proton_mass_c2;
187          } else {
188      delta_m += CLHEP::neutron_mass_c2;
189          }  
190          }
191     }
192 
193       G4double final_mass(0);
194     if ( theNucleus.GetA_asInt() ) {
195      final_mass=ionTable->GetIonMass(theNucleus.GetZ_asInt()-resZ,theNucleus.GetA_asInt()- resA);
196       }
197     G4double E_excit=init_mass + init_E - final_mass - E_out;
198     G4cout << " Corrected delta mass " << init_mass - final_mass - delta_m << G4endl;
199       G4cout << "initial E, mass = " << init_E << ", " << init_mass << G4endl;
200       G4cout << "  final E, mass = " << E_out <<", " << final_mass << "  excitation_E " << E_excit << G4endl;
201   #endif
202 
203   G4ReactionProductVector * theTransportResult = nullptr;
204 
205   G4V3DNucleus* theProjectileNucleus = theHighEnergyGenerator->GetProjectileNucleus(); 
206   if(theProjectileNucleus == nullptr)
207   {
208     G4int hitCount = 0;
209     const std::vector<G4Nucleon>& they = theHighEnergyGenerator->GetWoundedNucleus()->GetNucleons();
210     for(auto & nuc : they)
211     {
212       if(nuc.AreYouHit()) ++hitCount;
213     }
214     if(hitCount != theHighEnergyGenerator->GetWoundedNucleus()->GetMassNumber() )
215     {
216       theTransport->SetPrimaryProjectile(thePrimary);
217       theTransportResult = 
218         theTransport->Propagate(theInitialResult, 
219                                 theHighEnergyGenerator->GetWoundedNucleus());
220       if ( !theTransportResult ) {
221         G4cout << "G4TheoFSGenerator: null ptr from transport propagate " << G4endl;
222         throw G4HadronicException(__FILE__, __LINE__, "Null ptr from transport propagate");
223       }
224     }
225     else
226     {
227       theTransportResult = theDecay.Propagate(theInitialResult, 
228                                  theHighEnergyGenerator->GetWoundedNucleus());
229       if ( theTransportResult == nullptr ) {
230          G4cout << "G4TheoFSGenerator: null ptr from decay propagate " << G4endl;
231          throw G4HadronicException(__FILE__, __LINE__, "Null ptr from decay propagate");
232       }   
233     }
234   } 
235   else 
236   { 
237     theTransport->SetPrimaryProjectile(thePrimary);
238     theTransportResult = theTransport->PropagateNuclNucl(theInitialResult, 
239                             theHighEnergyGenerator->GetWoundedNucleus(),
240                             theProjectileNucleus);
241     if ( !theTransportResult ) {
242        G4cout << "G4TheoFSGenerator: null ptr from transport propagate " << G4endl;
243        throw G4HadronicException(__FILE__, __LINE__, "Null ptr from transport propagate");
244     } 
245   }
246 
247   // If enabled, apply the Cosmic Rays (CR) coalescence to the list of secondaries produced so far.
248   // This algorithm can form deuterons and antideuterons by coalescence of, respectively,
249   // proton-neutron and antiproton-antineutron pairs close in momentum space.
250   // This can be useful in particular for Cosmic Ray applications.
251   if ( G4HadronicParameters::Instance()->EnableCRCoalescence() ) {
252     if(nullptr == theCosmicCoalescence) {
253       theCosmicCoalescence = (G4CRCoalescence*)
254         G4HadronicInteractionRegistry::Instance()->FindModel("G4CRCoalescence");
255       if(nullptr == theCosmicCoalescence) { 
256   theCosmicCoalescence = new G4CRCoalescence();
257       }
258     }
259     theCosmicCoalescence->SetP0Coalescence( thePrimary, theHighEnergyGenerator->GetModelName() );
260     theCosmicCoalescence->GenerateDeuterons( theTransportResult );
261   }
262     
263   // Fill particle change
264   for(auto & ptr : *theTransportResult)
265   {
266     G4DynamicParticle * aNewDP =
267        new G4DynamicParticle(ptr->GetDefinition(),
268                              ptr->GetTotalEnergy(),
269                              ptr->GetMomentum());
270     G4HadSecondary aNew = G4HadSecondary(aNewDP);
271     G4double time = std::max(ptr->GetFormationTime(), 0.0);
272     aNew.SetTime(timePrimary + time);
273     aNew.SetCreatorModelID(ptr->GetCreatorModelID());
274     aNew.SetParentResonanceDef(ptr->GetParentResonanceDef());
275     aNew.SetParentResonanceID(ptr->GetParentResonanceID());    
276     theParticleChange->AddSecondary(aNew);
277     delete ptr;
278   }
279   
280   // some garbage collection
281   delete theTransportResult;
282   
283   // Done
284   return theParticleChange;
285 }
286 
287 std::pair<G4double, G4double> G4TheoFSGenerator::GetEnergyMomentumCheckLevels() const
288 {
289   if ( theHighEnergyGenerator ) {
290    return theHighEnergyGenerator->GetEnergyMomentumCheckLevels();
291   } else {
292    return std::pair<G4double, G4double>(DBL_MAX, DBL_MAX);
293   }
294 }
295