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
G4ParticleHPFinalState.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//080721 Create adjust_final_state method by T. Koi
28//080801 Residual reconstruction with theNDLDataA,Z (A, Z, and momentum are adjusted) by T. Koi
29//101110 Set lower limit for gamma energy(1keV) by T. Koi
30// P. Arce, June-2014 Conversion neutron_hp to particle_hp
31//
32
34
36#include "G4SystemOfUnits.hh"
37#include "G4IonTable.hh"
38#include "G4Gamma.hh"
39#include "G4Neutron.hh"
40#include "G4Proton.hh"
41#include "G4Deuteron.hh"
42#include "G4Triton.hh"
43#include "G4He3.hh"
44#include "G4Alpha.hh"
45
46
48{
49
50 G4double minimum_energy = 1*keV;
51
52 if ( G4ParticleHPManager::GetInstance()->GetDoNotAdjustFinalState() ) return;
53
54 G4int nSecondaries = (G4int)theResult.Get()->GetNumberOfSecondaries();
55
56 G4int sum_Z = 0;
57 G4int sum_A = 0;
58 G4int max_SecZ = 0;
59 G4int max_SecA = 0;
60 G4int imaxA = -1;
61 for ( G4int i = 0 ; i < nSecondaries ; ++i )
62 {
64 max_SecZ = std::max ( max_SecZ , theResult.Get()->GetSecondary( i )->GetParticle()->GetDefinition()->GetAtomicNumber() );
66 max_SecA = std::max ( max_SecA , theResult.Get()->GetSecondary( i )->GetParticle()->GetDefinition()->GetAtomicMass() );
67 if ( theResult.Get()->GetSecondary( i )->GetParticle()->GetDefinition()->GetAtomicMass() == max_SecA ) imaxA = i;
68#ifdef G4PHPDEBUG
69 if( std::getenv("G4ParticleHPDebug")) G4cout << "G4ParticleHPFinalState::adjust_final_stat SECO " << i << " " <<theResult.Get()->GetSecondary( i )->GetParticle()->GetDefinition()->GetParticleName() << G4endl;
70#endif
71
72 }
73
74 G4ParticleDefinition* resi_pd = 0;
75
76 G4double baseZNew = theBaseZ;
77 G4double baseANew = theBaseA;
79 baseANew ++;
80 } else if( theProjectile == G4Proton::Proton() ) {
81 baseZNew ++;
82 baseANew ++;
83 } else if( theProjectile == G4Deuteron::Deuteron() ) {
84 baseZNew ++;
85 baseANew += 2;
86 } else if( theProjectile == G4Triton::Triton() ) {
87 baseZNew ++;
88 baseANew += 3;
89 } else if( theProjectile == G4He3::He3() ) {
90 baseZNew += 2;
91 baseANew += 3;
92 } else if( theProjectile == G4Alpha::Alpha() ) {
93 baseZNew += 2;
94 baseANew += 4;
95 }
96
97#ifdef G4PHPDEBUG
98 if( std::getenv("G4ParticleHPDebug")) G4cout << "G4ParticleHPFinalState::adjust_final_stat BaseZ " << baseZNew << " BaseA " << baseANew << " sum_Z " << sum_Z << " sum_A " << sum_A << G4endl;
99#endif
100
101 G4bool needOneMoreSec = false;
102 G4ParticleDefinition* oneMoreSec_pd = 0;
103 if ( (G4int)(baseZNew - sum_Z) == 0 && (G4int)(baseANew - sum_A) == 0 )
104 {
105 //All secondaries are already created;
106 resi_pd = theResult.Get()->GetSecondary( imaxA )->GetParticle()->GetDefinition();
107 }
108 else
109 {
110 if ( max_SecA >= G4int(baseANew - sum_A) )
111 {
112 //Most heavy secondary is interpreted as residual
113 resi_pd = theResult.Get()->GetSecondary( imaxA )->GetParticle()->GetDefinition();
114 needOneMoreSec = true;
115 }
116 else
117 {
118 //creation of residual is required
119 resi_pd = G4IonTable::GetIonTable()->GetIon ( G4int(baseZNew - sum_Z),
120 G4int(baseANew - sum_A) , 0.0 );
121 }
122
123 if ( needOneMoreSec )
124 {
125 if ( G4int(baseZNew - sum_Z) == 0 && G4int(baseANew - sum_A) > 0 )
126 {
127 //In this case, one neutron is added to secondaries
128 if ( G4int(baseANew - sum_A) > 1 )
129 G4cout << "More than one neutron is required for the balance of baryon number!"
130 << G4endl;
131 oneMoreSec_pd = G4Neutron::Neutron();
132 }
133 else
134 {
135#ifdef G4PHPDEBUG
136 if( std::getenv("G4ParticleHPDebug")) G4cout << this << "G4ParticleHPFinalState oneMoreSec_pd Z " << baseZNew << " - " << sum_Z << " A " << baseANew << " - " << sum_A << " projectile " << theProjectile->GetParticleName() << G4endl;
137#endif
138 oneMoreSec_pd = G4IonTable::GetIonTable()->GetIon ( G4int(baseZNew - sum_Z),
139 G4int(baseANew - sum_A) , 0.0 );
140 if( !oneMoreSec_pd ) {
141 G4cerr << this << "G4ParticleHPFinalState oneMoreSec_pd Z " << baseZNew << " - " << sum_Z << " A " << baseANew << " - " << sum_A << " projectile " << theProjectile->GetParticleName() << G4endl;
142 G4Exception("G4ParticleHPFinalState:adjust_final_state",
143 "Warning",
145 "No adjustment will be done!");
146 return;
147 }
148 }
149 }
150
151 if ( resi_pd == 0 )
152 {
153 // theNDLDataZ,A has the Z and A of used NDL file
154 G4double ndlZNew = theNDLDataZ;
155 G4double ndlANew = theNDLDataA;
157 ndlANew ++;
158 } else if( theProjectile == G4Proton::Proton() ) {
159 ndlZNew ++;
160 ndlANew ++;
161 } else if( theProjectile == G4Deuteron::Deuteron() ) {
162 ndlZNew ++;
163 ndlANew += 2;
164 } else if( theProjectile == G4Triton::Triton() ) {
165 ndlZNew ++;
166 ndlANew += 3;
167 } else if( theProjectile == G4He3::He3() ) {
168 ndlZNew += 2;
169 ndlANew += 3;
170 } else if( theProjectile == G4Alpha::Alpha() ) {
171 ndlZNew += 2;
172 ndlANew += 4;
173 }
174 // theNDLDataZ,A has the Z and A of used NDL file
175 if ( G4int(ndlZNew - sum_Z) == 0 && G4int(ndlANew - sum_A) == 0 )
176 {
177 G4int dif_Z = G4int( theNDLDataZ - theBaseZ );
178 G4int dif_A = G4int( theNDLDataA - theBaseA );
179 resi_pd = G4IonTable::GetIonTable()->GetIon ( max_SecZ - dif_Z , max_SecA - dif_A , 0.0 );
180 if( !resi_pd ) {
181 G4cerr << "G4ParticleHPFinalState resi_pd Z " << max_SecZ << " - " << dif_Z << " A " << max_SecA << " - " << dif_A << " projectile " << theProjectile->GetParticleName() << G4endl;
182 G4Exception("G4ParticleHPFinalState:adjust_final_state",
183 "Warning",
185 "No adjustment will be done!");
186 return;
187 }
188
189 for ( G4int i = 0 ; i < nSecondaries ; ++i )
190 {
191 if ( theResult.Get()->GetSecondary( i )->GetParticle()->GetDefinition()->GetAtomicNumber() == max_SecZ
192 && theResult.Get()->GetSecondary( i )->GetParticle()->GetDefinition()->GetAtomicMass() == max_SecA )
193 {
195 p = p * resi_pd->GetPDGMass()/ G4IonTable::GetIonTable()->GetIon ( max_SecZ , max_SecA , 0.0 )->GetPDGMass();
196 theResult.Get()->GetSecondary( i )->GetParticle()->SetDefinition( resi_pd );
198 }
199 }
200 }
201 }
202 }
203
204 G4LorentzVector secs_4p_lab( 0.0 );
205
207 G4double fast = 0;
208 G4double slow = 1;
209 G4int ifast = 0;
210 G4int islow = 0;
211 G4int ires = -1;
212
213 for ( G4int i = 0 ; i < n_sec ; ++i )
214 {
215 secs_4p_lab += theResult.Get()->GetSecondary( i )->GetParticle()->Get4Momentum();
216
217 G4double beta = 0;
219 {
220 beta = theResult.Get()->GetSecondary( i )->GetParticle()->Get4Momentum().beta();
221 }
222 else
223 {
224 beta = 1;
225 }
226
227 if ( theResult.Get()->GetSecondary( i )->GetParticle()->GetDefinition() == resi_pd ) ires = i;
228
229 if ( slow > beta && beta != 0 )
230 {
231 slow = beta;
232 islow = i;
233 }
234
235 if ( fast <= beta )
236 {
237 if ( fast != 1 )
238 {
239 fast = beta;
240 ifast = i;
241 }
242 else
243 {
244 // fast is already photon then check E
246 if ( e > theResult.Get()->GetSecondary( ifast )->GetParticle()->Get4Momentum().e() )
247 {
248 // among photons, the highest E becomes the fastest
249 ifast = i;
250 }
251 }
252 }
253 }
254
255 G4LorentzVector dif_4p = init_4p_lab - secs_4p_lab;
256
257 G4LorentzVector p4(0);
258 if ( ires == -1 )
259 {
260 // Create and Add Residual Nucleus
261 ires = nSecondaries;
262 nSecondaries += 1;
263
264 G4DynamicParticle* res = new G4DynamicParticle ( resi_pd , dif_4p.v() );
265 theResult.Get()->AddSecondary ( res, secID );
266
267 p4 = res->Get4Momentum();
268 if ( slow > p4.beta() )
269 {
270 slow = p4.beta();
271 islow = ires;
272 }
273 dif_4p = init_4p_lab - ( secs_4p_lab + p4 );
274 }
275
276 if ( needOneMoreSec && oneMoreSec_pd)
277 //
278 // fca: this is not a fix, this is a crash avoidance...
279 // fca: the baryon number is still wrong, most probably because it
280 // fca: should have been decreased, but since we could not create a particle
281 // fca: we just do not add it
282 //
283 {
284 nSecondaries += 1;
285 G4DynamicParticle* one = new G4DynamicParticle ( oneMoreSec_pd , dif_4p.v() );
286 theResult.Get()->AddSecondary ( one, secID );
287 p4 = one->Get4Momentum();
288 if ( slow > p4.beta() )
289 {
290 slow = p4.beta();
291 islow = nSecondaries-1; //Because the first is 0th, so the last becomes "nSecondaries-1"
292 }
293 dif_4p = init_4p_lab - ( secs_4p_lab + p4 );
294 }
295
296 // Which is bigger dif_p or dif_e
297
298 if ( dif_4p.v().mag() < std::abs( dif_4p.e() ) )
299 {
300 // Adjust p
301 if ( minimum_energy < dif_4p.v().mag() && dif_4p.v().mag() < 1*MeV )
302 {
303
304 nSecondaries += 1;
305 theResult.Get()->AddSecondary ( new G4DynamicParticle ( G4Gamma::Gamma() , dif_4p.v() ), secID );
306 }
307 }
308 else
309 {
310
311 // dif_p > dif_e
312 // at first momentum
313 // Move residual momentum
314
315 p4 = theResult.Get()->GetSecondary( ires )->GetParticle()->Get4Momentum();
316 theResult.Get()->GetSecondary( ires )->GetParticle()->SetMomentum( p4.v() + dif_4p.v() );
317 dif_4p = init_4p_lab - ( secs_4p_lab - p4 + theResult.Get()->GetSecondary( ires )->GetParticle()->Get4Momentum() );
318 }
319
320 G4double dif_e = dif_4p.e() - ( dif_4p.v() ).mag();
321
322 if ( dif_e > 0 )
323 {
324
325 // create 2 gamma
326
327 nSecondaries += 2;
328 G4double e1 = ( dif_4p.e() -dif_4p.v().mag() ) / 2;
329
330 if ( minimum_energy < e1 )
331 {
332 G4double costh = 2.*G4UniformRand()-1.;
333 G4double phi = twopi*G4UniformRand();
334 G4ThreeVector dir( std::sin(std::acos(costh))*std::cos(phi),
335 std::sin(std::acos(costh))*std::sin(phi),
336 costh);
338 theResult.Get()->AddSecondary ( new G4DynamicParticle ( G4Gamma::Gamma() , -e1*dir ), secID );
339 }
340 }
341 else // dif_e < 0
342 {
343 // At first reduce KE of the fastest secondary;
346 G4ThreeVector dir = ( theResult.Get()->GetSecondary( ifast )->GetParticle()->GetMomentum() ).unit();
347
348 if ( ke0 + dif_e > 0 )
349 {
350 theResult.Get()->GetSecondary( ifast )->GetParticle()->SetKineticEnergy( ke0 + dif_e );
351 G4ThreeVector dp = p0 - theResult.Get()->GetSecondary( ifast )->GetParticle()->GetMomentum();
352
354 //theResult.GetSecondary( islow )->GetParticle()->SetMomentum( p - dif_e*dir );
355 theResult.Get()->GetSecondary( islow )->GetParticle()->SetMomentum( p + dp );
356 }
357 }
358}
@ JustWarning
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:59
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
G4GLOB_DLL std::ostream G4cerr
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
#define G4UniformRand()
Definition: Randomize.hh:52
double mag() const
Hep3Vector v() const
static G4Alpha * Alpha()
Definition: G4Alpha.cc:88
value_type & Get() const
Definition: G4Cache.hh:315
static G4Deuteron * Deuteron()
Definition: G4Deuteron.cc:93
void SetDefinition(const G4ParticleDefinition *aParticleDefinition)
G4ParticleDefinition * GetDefinition() const
G4LorentzVector Get4Momentum() const
G4double GetKineticEnergy() const
void SetMomentum(const G4ThreeVector &momentum)
G4ThreeVector GetMomentum() const
void SetKineticEnergy(G4double aEnergy)
static G4Gamma * Gamma()
Definition: G4Gamma.cc:85
void AddSecondary(G4DynamicParticle *aP, G4int mod=-1)
std::size_t GetNumberOfSecondaries() const
G4HadSecondary * GetSecondary(size_t i)
G4DynamicParticle * GetParticle()
static G4He3 * He3()
Definition: G4He3.cc:93
G4ParticleDefinition * GetIon(G4int Z, G4int A, G4int lvl=0)
Definition: G4IonTable.cc:522
static G4IonTable * GetIonTable()
Definition: G4IonTable.cc:170
static G4Neutron * Neutron()
Definition: G4Neutron.cc:103
G4int GetAtomicNumber() const
G4int GetAtomicMass() const
const G4String & GetParticleName() const
G4ParticleDefinition * theProjectile
G4Cache< G4HadFinalState * > theResult
void adjust_final_state(G4LorentzVector)
static G4ParticleHPManager * GetInstance()
static G4Proton * Proton()
Definition: G4Proton.cc:92
static G4Triton * Triton()
Definition: G4Triton.cc:93