Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
G4TheoFSGenerator.cc
Go to the documentation of this file.
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"
36#include "G4ReactionProduct.hh"
37#include "G4IonTable.hh"
39#include "G4CRCoalescence.hh"
41
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
54{
55 delete theParticleChange;
56}
57
58void 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
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);
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*)
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
287std::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}
@ isAlive
@ stopAndKill
std::vector< G4ReactionProduct * > G4ReactionProductVector
double G4double
Definition: G4Types.hh:83
int G4int
Definition: G4Types.hh:85
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
#define G4UniformRand()
Definition: Randomize.hh:52
Hep3Vector unit() const
Hep3Vector vect() const
void GenerateDeuterons(G4ReactionProductVector *result)
void SetP0Coalescence(const G4HadProjectile &thePrimary, G4String)
G4ReactionProductVector * Propagate(G4KineticTrackVector *theSecondaries, G4V3DNucleus *)
G4LorentzVector Get4Momentum() const
void SetStatusChange(G4HadFinalStateStatus aS)
void AddSecondary(G4DynamicParticle *aP, G4int mod=-1)
void SetEnergyChange(G4double anEnergy)
void SetMomentumChange(const G4ThreeVector &aV)
const G4ParticleDefinition * GetDefinition() const
G4double GetKineticEnergy() const
const G4LorentzVector & Get4Momentum() const
G4double GetGlobalTime() const
void SetParentResonanceDef(const G4ParticleDefinition *parentDef)
void SetTime(G4double aT)
void SetCreatorModelID(G4int id)
void SetParentResonanceID(const G4int parentID)
G4HadronicInteraction * FindModel(const G4String &name)
static G4HadronicInteractionRegistry * Instance()
virtual std::pair< G4double, G4double > GetEnergyMomentumCheckLevels() const
const G4String & GetModelName() const
static G4HadronicParameters * Instance()
G4double GetIonMass(G4int Z, G4int A, G4int nL=0, G4int lvl=0) const
Definition: G4IonTable.cc:1517
G4int GetA_asInt() const
Definition: G4Nucleus.hh:99
G4int GetZ_asInt() const
Definition: G4Nucleus.hh:105
G4int GetQuarkContent(G4int flavor) const
G4bool IsHypernucleus() const
G4int GetAntiQuarkContent(G4int flavor) const
G4IonTable * GetIonTable() const
static G4ParticleTable * GetParticleTable()
static G4int GetModelID(const G4int modelIndex)
static G4Proton * Proton()
Definition: G4Proton.cc:92
G4KineticTrackVector * Scatter(G4Nucleus &theNucleus, const G4DynamicParticle &thePrimary)
G4double GetFraction(G4Nucleus &theNucleus, const G4DynamicParticle &thePrimary)
G4TheoFSGenerator(const G4String &name="TheoFSGenerator")
std::pair< G4double, G4double > GetEnergyMomentumCheckLevels() const override
G4HadFinalState * ApplyYourself(const G4HadProjectile &thePrimary, G4Nucleus &theNucleus) override
void ModelDescription(std::ostream &outFile) const override
~G4TheoFSGenerator() override
virtual const std::vector< G4Nucleon > & GetNucleons()=0
virtual G4int GetMassNumber()=0
void ModelDescription(std::ostream &) const override
virtual G4V3DNucleus * GetProjectileNucleus() const
virtual G4V3DNucleus * GetWoundedNucleus() const =0
virtual G4KineticTrackVector * Scatter(const G4Nucleus &theNucleus, const G4DynamicParticle &thePrimary)=0
virtual G4ReactionProductVector * PropagateNuclNucl(G4KineticTrackVector *theSecondaries, G4V3DNucleus *theNucleus, G4V3DNucleus *theProjectileNucleus)
void SetPrimaryProjectile(const G4HadProjectile &aPrimary)
virtual void PropagateModelDescription(std::ostream &outFile) const
virtual G4ReactionProductVector * Propagate(G4KineticTrackVector *theSecondaries, G4V3DNucleus *theNucleus)=0
#define DBL_MAX
Definition: templates.hh:62