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