Geant4  10.02.p01
G4RadioactiveDecay.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 // MODULE: G4RadioactiveDecay.cc
27 //
28 // Author: F Lei & P R Truscott
29 // Organisation: DERA UK
30 // Customer: ESA/ESTEC, NOORDWIJK
31 // Contract: 12115/96/JG/NL Work Order No. 3
32 //
33 // Documentation avaialable at http://www.space.dera.gov.uk/space_env/rdm.html
34 // These include:
35 // User Requirement Document (URD)
36 // Software Specification Documents (SSD)
37 // Software User Manual (SUM)
38 // Technical Note (TN) on the physics and algorithms
39 //
40 // The test and example programs are not included in the public release of
41 // G4 but they can be downloaded from
42 // http://www.space.qinetiq.com/space_env/rdm.html
43 //
44 // CHANGE HISTORY
45 // --------------
46 //
47 // 13 Oct 2015, L.G. Sarmiento Neutron emission added
48 //
49 // 06 Aug 2014, L.G. Sarmiento Proton decay mode added mimicking the alpha decay
50 //
51 // 03 Oct 2012, V. Ivanchenko removed internal table for mean free path
52 // similar to what is done for as G4Decay
53 // 10 July 2012, L. Desorgher
54 // -In LoadDecayTable:
55 // Add LoadedNuclei.push_back(theParentNucleus.GetParticleName());
56 // also for the case where user data files are used. Correction for bug
57 // 1324. Changes proposed by Joa L.
58 //
59 //
60 // 01 May 2012, L. Desorgher
61 // -Force the reading of user file to theIsotopeTable
62 // -Merge the development by Fan Lei for activation computation
63 //
64 // 17 Oct 2011, L. Desorgher
65 // -Add possibility for the user to load its own decay file.
66 // -Set halflifethreshold negative by default to allow the tracking of all
67 // excited nuclei resulting from a radioactive decay
68 //
69 // 01 June 2011, M. Kelsey -- Add directional biasing interface to allow for
70 // "collimation" of decay daughters.
71 // 16 February 2006, V.Ivanchenko fix problem in IsApplicable connected with
72 // 8.0 particle design
73 // 18 October 2002, F. Lei
74 // in the case of beta decay, added a check of the end-energy
75 // to ensure it is > 0.
76 // ENSDF occationally have beta decay entries with zero energies
77 //
78 // 27 Sepetember 2001, F. Lei
79 // verboselevel(0) used in constructor
80 //
81 // 01 November 2000, F.Lei
82 // added " ee = e0 +1. ;" as line 763
83 // tagged as "radiative_decay-V02-00-02"
84 // 28 October 2000, F Lei
85 // added fast beta decay mode. Many files have been changed.
86 // tagged as "radiative_decay-V02-00-01"
87 //
88 // 25 October 2000, F Lei, DERA UK
89 // 1) line 1185 added 'const' to work with tag "Track-V02-00-00"
90 // tagged as "radiative_decay-V02-00-00"
91 // 14 April 2000, F Lei, DERA UK
92 // 0.b.4 release. Changes are:
93 // 1) Use PhotonEvaporation instead of DiscreteGammaDeexcitation
94 // 2) VR: Significant efficiency improvement
95 //
96 // 29 February 2000, P R Truscott, DERA UK
97 // 0.b.3 release.
98 //
100 //
101 #include "G4RadioactiveDecay.hh"
103 
104 #include "G4SystemOfUnits.hh"
105 #include "G4DynamicParticle.hh"
106 #include "G4DecayProducts.hh"
107 #include "G4DecayTable.hh"
109 #include "G4ITDecay.hh"
110 #include "G4BetaDecayType.hh"
111 #include "G4BetaMinusDecay.hh"
112 #include "G4BetaPlusDecay.hh"
113 #include "G4ECDecay.hh"
114 #include "G4AlphaDecay.hh"
115 #include "G4ProtonDecay.hh"
116 #include "G4NeutronDecay.hh"
117 #include "G4VDecayChannel.hh"
118 #include "G4NuclearDecay.hh"
119 #include "G4RadioactiveDecayMode.hh"
120 #include "G4Ions.hh"
121 #include "G4IonTable.hh"
122 #include "G4BetaDecayType.hh"
123 #include "Randomize.hh"
124 #include "G4LogicalVolumeStore.hh"
125 #include "G4NuclearLevelManager.hh"
126 #include "G4NuclearLevelStore.hh"
127 #include "G4ThreeVector.hh"
128 #include "G4Electron.hh"
129 #include "G4Positron.hh"
130 #include "G4Neutron.hh"
131 #include "G4Gamma.hh"
132 #include "G4Alpha.hh"
133 #include "G4Proton.hh"
134 
135 #include "G4HadronicProcessType.hh"
136 #include "G4HadronicException.hh"
137 #include "G4LossTableManager.hh"
138 #include "G4VAtomDeexcitation.hh"
139 #include "G4UAtomicDeexcitation.hh"
140 
141 #include <vector>
142 #include <sstream>
143 #include <algorithm>
144 #include <fstream>
145 
146 using namespace CLHEP;
147 
150 
151 #ifdef G4MULTITHREADED
152 #include "G4AutoLock.hh"
153 G4Mutex G4RadioactiveDecay::radioactiveDecayMutex = G4MUTEX_INITIALIZER;
154 DecayTableMap* G4RadioactiveDecay::master_dkmap = 0;
155 #endif
156 
158  : G4VRestDiscreteProcess(processName, fDecay), isInitialised(false),
159  forceDecayDirection(0.,0.,0.), forceDecayHalfAngle(0.*deg), verboseLevel(0)
160 {
161 #ifdef G4VERBOSE
162  if (GetVerboseLevel() > 1) {
163  G4cout << "G4RadioactiveDecay constructor: processName = " << processName
164  << G4endl;
165  }
166 #endif
167 
169 
172 
173  // Reset the list of user defined data files
175 
176  // Instantiate the map of decay tables
177 #ifdef G4MULTITHREADED
178  G4AutoLock lk(&G4RadioactiveDecay::radioactiveDecayMutex);
179  if(!master_dkmap) master_dkmap = new DecayTableMap;
180 #endif
181  dkmap = new DecayTableMap;
182 
183  // Apply default values.
184  NSourceBin = 1;
185  SBin[0] = 0.* s;
186  SBin[1] = 1.* s;
187  SProfile[0] = 1.;
188  SProfile[1] = 0.;
189  NDecayBin = 1;
190  DBin[0] = 0. * s ;
191  DBin[1] = 1. * s;
192  DProfile[0] = 1.;
193  DProfile[1] = 0.;
194  decayWindows[0] = 0;
196  theRadioactivityTables.push_back(rTable);
197  NSplit = 1;
198  AnalogueMC = true ;
199  FBeta = false ;
200  BRBias = true ;
201  applyICM = true ;
202  applyARM = true ;
204 
205  // RDM applies to all logical volumes by default
206  isAllVolumesMode = true;
208 }
209 
210 
212 {
214  for (DecayTableMap::iterator i = dkmap->begin(); i != dkmap->end(); i++) {
215  delete i->second;
216  }
217  dkmap->clear();
218  delete dkmap;
219 }
220 
221 
223 {
224  // All particles other than G4Ions, are rejected by default
225  if (((const G4Ions*)(&aParticle))->GetExcitationEnergy() > 0.) {return true;}
226  if (aParticle.GetParticleName() == "GenericIon") {
227  return true;
228  } else if (!(aParticle.GetParticleType() == "nucleus")
229  || aParticle.GetPDGLifeTime() < 0. ) {
230  return false;
231  }
232 
233  // Determine whether the nuclide falls into the correct A and Z range
234  G4int A = ((const G4Ions*) (&aParticle))->GetAtomicMass();
235  G4int Z = ((const G4Ions*) (&aParticle))->GetAtomicNumber();
237  {return false;}
238  else if (Z > theNucleusLimits.GetZMax() || Z < theNucleusLimits.GetZMin())
239  {return false;}
240  return true;
241 }
242 
244 {
245  G4String key = aNucleus->GetParticleName();
246  DecayTableMap::iterator table_ptr = dkmap->find(key);
247 
248  G4DecayTable* theDecayTable = 0;
249  if (table_ptr == dkmap->end() ) { // If table not there,
250  theDecayTable = LoadDecayTable(*aNucleus); // load from file and
251  (*dkmap)[key] = theDecayTable; // store in library
252  } else {
253  theDecayTable = table_ptr->second;
254  }
255 
256  return theDecayTable;
257 }
258 
259 
261 {
262  G4LogicalVolumeStore* theLogicalVolumes;
263  G4LogicalVolume* volume;
264  theLogicalVolumes = G4LogicalVolumeStore::GetInstance();
265  for (size_t i = 0; i < theLogicalVolumes->size(); i++) {
266  volume=(*theLogicalVolumes)[i];
267  if (volume->GetName() == aVolume) {
268  ValidVolumes.push_back(aVolume);
269  std::sort(ValidVolumes.begin(), ValidVolumes.end());
270  // sort need for performing binary_search
271 #ifdef G4VERBOSE
272  if (GetVerboseLevel()>0)
273  G4cout << " RDM Applies to : " << aVolume << G4endl;
274 #endif
275  } else if(i == theLogicalVolumes->size()) {
276  G4cerr << "SelectAVolume: "<< aVolume
277  << " is not a valid logical volume name" << G4endl;
278  }
279  }
280 }
281 
282 
284 {
285  G4LogicalVolumeStore* theLogicalVolumes;
286  G4LogicalVolume* volume;
287  theLogicalVolumes = G4LogicalVolumeStore::GetInstance();
288  for (size_t i = 0; i < theLogicalVolumes->size(); i++){
289  volume=(*theLogicalVolumes)[i];
290  if (volume->GetName() == aVolume) {
291  std::vector<G4String>::iterator location;
292  location = std::find(ValidVolumes.begin(),ValidVolumes.end(),aVolume);
293  if (location != ValidVolumes.end()) {
294  ValidVolumes.erase(location);
295  std::sort(ValidVolumes.begin(), ValidVolumes.end());
296  isAllVolumesMode =false;
297  } else {
298  G4cerr << " DeselectVolume:" << aVolume << " is not in the list "
299  << G4endl;
300  }
301 #ifdef G4VERBOSE
302  if (GetVerboseLevel() > 0)
303  G4cout << " DeselectVolume: " << aVolume << " is removed from list "
304  << G4endl;
305 #endif
306  } else if (i == theLogicalVolumes->size()) {
307  G4cerr << " DeselectVolume:" << aVolume
308  << "is not a valid logical volume name" << G4endl;
309  }
310  }
311 }
312 
313 
315 {
316  G4LogicalVolumeStore* theLogicalVolumes;
317  G4LogicalVolume* volume;
318  theLogicalVolumes = G4LogicalVolumeStore::GetInstance();
319  ValidVolumes.clear();
320 #ifdef G4VERBOSE
321  if (GetVerboseLevel()>0)
322  G4cout << " RDM Applies to all Volumes" << G4endl;
323 #endif
324  for (size_t i = 0; i < theLogicalVolumes->size(); i++){
325  volume = (*theLogicalVolumes)[i];
326  ValidVolumes.push_back(volume->GetName());
327 #ifdef G4VERBOSE
328  if (GetVerboseLevel()>0)
329  G4cout << " RDM Applies to Volume " << volume->GetName() << G4endl;
330 #endif
331  }
332  std::sort(ValidVolumes.begin(), ValidVolumes.end());
333  // sort needed in order to allow binary_search
334  isAllVolumesMode=true;
335 }
336 
337 
339 {
340  ValidVolumes.clear();
341  isAllVolumesMode=false;
342 #ifdef G4VERBOSE
343  if (GetVerboseLevel() > 0) G4cout << "RDM removed from all volumes" << G4endl;
344 #endif
345 }
346 
347 
348 G4bool
350 {
351  // Check whether the radioactive decay rates table for the ion has already
352  // been calculated.
353  G4String aParticleName = aParticle.GetParticleName();
354  for (size_t i = 0; i < theDecayRateTableVector.size(); i++) {
355  if (theDecayRateTableVector[i].GetIonName() == aParticleName) return true;
356  }
357  return false;
358 }
359 
360 // GetDecayRateTable
361 // retrieve the decayratetable for the specified aParticle
362 
363 void
365 {
366  G4String aParticleName = aParticle.GetParticleName();
367 
368  for (size_t i = 0; i < theDecayRateTableVector.size(); i++) {
369  if (theDecayRateTableVector[i].GetIonName() == aParticleName) {
370  theDecayRateVector = theDecayRateTableVector[i].GetItsRates();
371  }
372  }
373 #ifdef G4VERBOSE
374  if (GetVerboseLevel() > 0) {
375  G4cout << "The DecayRate Table for " << aParticleName << " is selected."
376  << G4endl;
377  }
378 #endif
379 }
380 
381 // GetTaoTime performs the convolution of the source time profile function
382 // with the decay constants in the decay chain.
383 // The time profile is treated as a step function so that the convolution
384 // integral can be done bin-by-bin.
385 // The profile function should be normalized to 1. Is it??
386 
388 {
389  long double taotime = 0.L;
390  G4int nbin;
391  if ( t > SBin[NSourceBin]) {
392  nbin = NSourceBin;
393  } else {
394  nbin = 0;
395 
396  G4int loop = 0;
398  ed << " While count exceeded " << G4endl;
399  while (t > SBin[nbin]) { /* Loop checking, 01.09.2015, D.Wright */
400  loop++;
401  if (loop > 1000) {
402  G4Exception("G4RadioactiveDecay::GetTaoTime()", "HAD_RDM_100", JustWarning, ed);
403  break;
404  }
405 
406  nbin++;
407  }
408  nbin--;
409  }
410  long double lt = t ;
411  long double ltao = tao;
412 
413  if (nbin > 0) {
414  for (G4int i = 0; i < nbin; i++) {
415  taotime += (long double)SProfile[i] *
416  (std::exp(-(lt-(long double)SBin[i+1])/ltao)-std::exp(-(lt-(long double)SBin[i])/ltao));
417  }
418  }
419  taotime += (long double)SProfile[nbin] * (1.L-std::exp(-(lt-(long double)SBin[nbin])/ltao));
420  // Is the above line necessary? If so, the 1.L looks incorrect - should be an exp
421  // Also, it looks like the final integral should be multiplied by ltao
422 
423  if (taotime < 0.) {
424  G4cout <<" Tao time =: " <<taotime << " reset to zero!"<<G4endl;
425  G4cout <<" t = " << t <<" tao = " <<tao <<G4endl;
426  G4cout << SBin[nbin] << " " <<SBin[0] << G4endl;
427  taotime = 0.;
428  }
429 #ifdef G4VERBOSE
430  if (GetVerboseLevel() > 1)
431  G4cout <<" Tao time: " <<taotime <<G4endl;
432 #endif
433  return (G4double)taotime ;
434 }
435 
436 /*
437 // Other implementation tests to avoid use of long double
438 G4double G4RadioactiveDecay::GetTaoTime(const G4double t, const G4double tao)
439 {
440  long double taotime =0.L;
441  G4int nbin;
442  if ( t > SBin[NSourceBin]) {
443  nbin = NSourceBin;}
444  else {
445  nbin = 0;
446  while (t > SBin[nbin]) nbin++;
447  nbin--;}
448  long double lt = t ;
449  long double ltao = tao;
450  long double factor,factor1,dt1,dt;
451  if (nbin > 0) {
452  for (G4int i = 0; i < nbin; i++)
453  { long double s1=SBin[i];
454  long double s2=SBin[i+1];
455  dt1=(s2-s1)/ltao;
456  if (dt1 <50.) {
457  factor1=std::exp(dt1)-1.;
458  if (factor1<dt1) factor1 =dt1;
459  dt=(lt-s1)/ltao;
460  factor=std::exp(-dt);
461  }
462  else {
463  factor1=1.-std::exp(-dt1);
464  dt=(lt-s2)/ltao;
465  factor=std::exp(-dt);
466  }
467  G4cout<<(long double) SProfile[i] *factor*factor1<<'\t'<<std::endl;
468  long double test = (long double)SProfile[i] * (std::exp(-(lt-(long double)SBin[i+1])/ltao)-std::exp(-(lt-(long double)SBin[i])/ltao));
469  G4cout<<test<<std::endl;
470  taotime += (long double) SProfile[i] *factor*factor1;
471  }
472  }
473  long double s=SBin[nbin];
474  dt1=(lt-s)/ltao;
475  factor=1.-std::exp(-dt1);
476  taotime += (long double) SProfile[nbin] *factor;
477  if (taotime < 0.) {
478  G4cout <<" Tao time =: " <<taotime << " reset to zero!"<<G4endl;
479  G4cout <<" t = " << t <<" tao = " <<tao <<G4endl;
480  G4cout << SBin[nbin] << " " <<SBin[0] << G4endl;
481  taotime = 0.;
482  }
483 #ifdef G4VERBOSE
484  if (GetVerboseLevel()>1)
485  {G4cout <<" Tao time: " <<taotime <<G4endl;}
486 #endif
487  return (G4double)taotime ;
488 }
489 
490 
491 
492 G4double G4RadioactiveDecay::GetTaoTime(const G4double t, const G4double tao)
493 {
494  G4double taotime =0.;
495  G4int nbin;
496  if ( t > SBin[NSourceBin]) {
497  nbin = NSourceBin;}
498  else {
499  nbin = 0;
500  while (t > SBin[nbin]) nbin++;
501  nbin--;}
502  G4double lt = t ;
503  G4double ltao = tao;
504  G4double factor,factor1,dt1,dt;
505 
506  if (nbin > 0) {
507  for (G4int i = 0; i < nbin; i++)
508  { dt1=(SBin[i+1]-SBin[i])/ltao;
509  if (dt1 <50.) {
510  factor1=std::exp(dt1)-1.;
511  if (factor1<dt1) factor1 =dt1;
512  dt=(lt-SBin[i])/ltao;
513  factor=std::exp(-(lt-SBin[i])/ltao);
514  G4cout<<factor<<'\t'<<factor1<<std::endl;
515  }
516  else {
517  factor1=1.-std::exp(-dt1);
518  factor=std::exp(-(lt-SBin[i+1])/ltao);
519  }
520  G4cout<<factor<<'\t'<<factor1<<std::endl;
521  taotime += SProfile[i] *factor*factor1;
522  G4cout<<taotime<<std::endl;
523  }
524  }
525  dt1=(lt-SBin[nbin])/ltao;
526  factor=1.-std::exp(-dt1);
527  if (factor<(dt1-0.5*dt1*dt1)) factor =dt1-0.5*dt1*dt1;
528 
529 
530  taotime += SProfile[nbin] *factor;
531  G4cout<<factor<<'\t'<<taotime<<std::endl;
532  if (taotime < 0.) {
533  G4cout <<" Tao time =: " <<taotime << " reset to zero!"<<G4endl;
534  G4cout <<" t = " << t <<" tao = " <<tao <<G4endl;
535  G4cout << SBin[nbin] << " " <<SBin[0] << G4endl;
536  taotime = 0.;
537  }
538 
539 #ifdef G4VERBOSE
540  if (GetVerboseLevel()>1)
541  {G4cout <<" Tao time: " <<taotime <<G4endl;}
542 #endif
543  return (G4double)taotime ;
544 }
545 */
547 // //
548 // GetDecayTime //
549 // Randomly select a decay time for the decay process, following the //
550 // supplied decay time bias scheme. //
551 // //
553 
555 {
556  G4double decaytime = 0.;
557  G4double rand = G4UniformRand();
558  G4int i = 0;
559 
560  G4int loop = 0;
562  ed << " While count exceeded " << G4endl;
563  while ( DProfile[i] < rand) { /* Loop checking, 01.09.2015, D.Wright */
564  i++;
565  loop++;
566  if (loop > 100000) {
567  G4Exception("G4RadioactiveDecay::GetDecayTime()", "HAD_RDM_100", JustWarning, ed);
568  break;
569  }
570  }
571 
572  rand = G4UniformRand();
573  decaytime = DBin[i] + rand*(DBin[i+1]-DBin[i]);
574 #ifdef G4VERBOSE
575  if (GetVerboseLevel() > 1)
576  G4cout <<" Decay time: " <<decaytime/s <<"[s]" <<G4endl;
577 #endif
578  return decaytime;
579 }
580 
581 
583 {
584  G4int i = 0;
585 
586  G4int loop = 0;
588  ed << " While count exceeded " << G4endl;
589  while ( aDecayTime > DBin[i] ) { /* Loop checking, 01.09.2015, D.Wright */
590  i++;
591  loop++;
592  if (loop > 100000) {
593  G4Exception("G4RadioactiveDecay::GetDecayTimeBin()", "HAD_RDM_100", JustWarning, ed);
594  break;
595  }
596  }
597 
598  return i;
599 }
600 
602 // //
603 // GetMeanLifeTime (required by the base class) //
604 // //
606 
609 {
610  // For varience reduction implementation the time is set to 0 so as to
611  // force the particle to decay immediately.
612  // In analogueMC mode it return the particle's mean-life.
613 
614  G4double meanlife = 0.;
615  if (AnalogueMC) {
616  const G4DynamicParticle* theParticle = theTrack.GetDynamicParticle();
617  const G4ParticleDefinition* theParticleDef = theParticle->GetDefinition();
618  G4double theLife = theParticleDef->GetPDGLifeTime();
619 #ifdef G4VERBOSE
620  if (GetVerboseLevel() > 2) {
621  G4cout << "G4RadioactiveDecay::GetMeanLifeTime() " << G4endl;
622  G4cout << "KineticEnergy: " << theParticle->GetKineticEnergy()/GeV
623  << " GeV, Mass: " << theParticle->GetMass()/GeV
624  << " GeV, Life time: " << theLife/ns << " ns " << G4endl;
625  }
626 #endif
627  if (theParticleDef->GetPDGStable()) {meanlife = DBL_MAX;}
628  else if (theLife < 0.0) {meanlife = DBL_MAX;}
629  else {meanlife = theLife;}
630  // Set meanlife to zero for excited istopes which are not in the
631  // RDM database
632  if (((const G4Ions*)(theParticleDef))->GetExcitationEnergy() > 0. &&
633  meanlife == DBL_MAX) {meanlife = 0.;}
634  }
635 #ifdef G4VERBOSE
636  if (GetVerboseLevel() > 1)
637  G4cout << " mean life time: " << meanlife/s << " s " << G4endl;
638 #endif
639 
640  return meanlife;
641 }
642 
644 // //
645 // GetMeanFreePath for decay in flight //
646 // //
648 
651 {
652  const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
653  const G4ParticleDefinition* aParticleDef = aParticle->GetDefinition();
654  G4double tau = aParticleDef->GetPDGLifeTime();
655  G4double aMass = aParticle->GetMass();
656 
657 #ifdef G4VERBOSE
658  if (GetVerboseLevel() > 2) {
659  G4cout << "G4RadioactiveDecay::GetMeanFreePath() " << G4endl;
660  G4cout << " KineticEnergy: " << aParticle->GetKineticEnergy()/GeV
661  << " GeV, Mass: " << aMass/GeV << " GeV, tau: " << tau << " ns "
662  << G4endl;
663  }
664 #endif
665  G4double pathlength = DBL_MAX;
666  if (tau != -1) {
667  // Ion can decay
668 
669  if (tau < -1000.0) {
670  pathlength = DBL_MIN; // nuclide had very short lifetime or wasn't in table
671 
672  } else if (tau < 0.0) {
673  G4cout << aParticleDef->GetParticleName() << " has lifetime " << tau << G4endl;
675  ed << "Ion has negative lifetime " << tau
676  << " but is not stable. Setting mean free path to DBL_MAX" << G4endl;
677  G4Exception("G4RadioactiveDecay::GetMeanFreePath()", "HAD_RDM_011",
678  JustWarning, ed);
679  pathlength = DBL_MAX;
680 
681  } else {
682  // Calculate mean free path
683  G4double betaGamma = aParticle->GetTotalMomentum()/aMass;
684  pathlength = c_light*tau*betaGamma;
685 
686  if (pathlength < DBL_MIN) {
687  pathlength = DBL_MIN;
688 #ifdef G4VERBOSE
689  if (GetVerboseLevel() > 2) {
690  G4cout << "G4Decay::GetMeanFreePath: "
691  << aParticleDef->GetParticleName()
692  << " stops, kinetic energy = "
693  << aParticle->GetKineticEnergy()/keV <<" keV " << G4endl;
694  }
695 #endif
696  }
697  }
698  }
699 
700 #ifdef G4VERBOSE
701  if (GetVerboseLevel() > 1) {
702  G4cout << "mean free path: "<< pathlength/m << " m" << G4endl;
703  }
704 #endif
705  return pathlength;
706 }
707 
709 // //
710 // BuildPhysicsTable - initialisation of atomic de-excitation //
711 // //
713 
715 {
716  if (!isInitialised) {
717  isInitialised = true;
719  G4VAtomDeexcitation* p = theManager->AtomDeexcitation();
720  if (!p) {
722  theManager->SetAtomDeexcitation(atomDeex);
723  p = theManager->AtomDeexcitation();
724  }
725  p->SetFluo(true);
726  p->SetAuger(true);
728  }
729 }
730 
732 // //
733 // LoadDecayTable loads the decay scheme from the RadioactiveDecay database //
734 // for the parent nucleus. //
735 // //
737 
740 {
741  // Generate input data file name using Z and A of the parent nucleus
742  // file containing radioactive decay data.
743  G4int A = ((const G4Ions*)(&theParentNucleus))->GetAtomicMass();
744  G4int Z = ((const G4Ions*)(&theParentNucleus))->GetAtomicNumber();
745  G4double levelEnergy = ((const G4Ions*)(&theParentNucleus))->GetExcitationEnergy();
746  G4DecayTable* theDecayTable = 0;
747 
748 #ifdef G4MULTITHREADED
749  G4AutoLock lk(&G4RadioactiveDecay::radioactiveDecayMutex);
750 
751  G4String key = theParentNucleus.GetParticleName();
752  DecayTableMap::iterator master_table_ptr = master_dkmap->find(key);
753 
754  if (master_table_ptr != master_dkmap->end() ) { // If table is there
755  return master_table_ptr->second;
756  }
757 #endif
758 
759  // Create and initialise variables used in the method.
760  theDecayTable = new G4DecayTable();
761 
762  //Check if data have been provided by the user
763  G4String file= theUserRadioactiveDataFiles[1000*A+Z];
764 
765  if (file =="") {
766  if (!getenv("G4RADIOACTIVEDATA") ) {
767  G4cout << "Please setenv G4RADIOACTIVEDATA to point to the radioactive decay data files."
768  << G4endl;
769  throw G4HadronicException(__FILE__, __LINE__, " Please setenv G4RADIOACTIVEDATA to point to the radioactive decay data files.");
770  }
771  G4String dirName = getenv("G4RADIOACTIVEDATA");
772 
773  std::ostringstream os;
774  os <<dirName <<"/z" <<Z <<".a" <<A <<'\0';
775  file = os.str();
776  }
777 
778  std::ifstream DecaySchemeFile(file);
779 
780  G4bool found(false);
781  if (DecaySchemeFile) {
782  // Initialise variables used for reading in radioactive decay data.
783  const G4int nMode = 9;
784  G4bool modeFirstRecord[nMode];
785  G4double modeTotalBR[nMode] = {0.0};
786  G4double modeSumBR[nMode];
787  for (G4int i = 0; i < nMode; i++) {
788  modeFirstRecord[i] = true;
789  modeSumBR[i] = 0.0;
790  }
791 
792  G4bool complete(false);
793  char inputChars[100]={' '};
794  G4String inputLine;
795  G4String recordType("");
796  G4RadioactiveDecayMode theDecayMode;
797  G4double a(0.0);
798  G4double b(0.0);
799  G4double c(0.0);
800  G4BetaDecayType betaType(allowed);
801 
802  // Loop through each data file record until you identify the decay
803  // data relating to the nuclide of concern.
804 
805  G4int loop = 0;
807  ed << " While count exceeded " << G4endl;
808 
809  while (!complete && !DecaySchemeFile.getline(inputChars, 100).eof()) { /* Loop checking, 01.09.2015, D.Wright */
810  loop++;
811  if (loop > 100000) {
812  G4Exception("G4RadioactiveDecay::LoadDecayTable()", "HAD_RDM_100", JustWarning, ed);
813  break;
814  }
815 
816  inputLine = inputChars;
817  inputLine = inputLine.strip(1);
818  if (inputChars[0] != '#' && inputLine.length() != 0) {
819  std::istringstream tmpStream(inputLine);
820 
821  if (inputChars[0] == 'P') {
822  // Nucleus is a parent type. Check excitation level to see if it
823  // matches that of theParentNucleus
824  tmpStream >> recordType >> a >> b;
825  if (found) {
826  complete = true;
827  } else {
828  found = (std::abs(a*keV - levelEnergy) < levelTolerance);
829  }
830 
831  } else if (found) {
832  // The right part of the radioactive decay data file has been found. Search
833  // through it to determine the mode of decay of the subsequent records.
834  if (inputChars[0] == 'W') {
835 #ifdef G4VERBOSE
836  if (GetVerboseLevel() > 0) {
837  // a comment line identified and print out the message
838  G4cout << " Warning in G4RadioactiveDecay::LoadDecayTable " << G4endl;
839  G4cout << " In data file " << file << G4endl;
840  G4cout << " " << inputLine << G4endl;
841  }
842 #endif
843  } else {
844  tmpStream >> theDecayMode >> a >> b >> c >> betaType;
845  // Allowed transitions are the default. Forbidden transitions are
846  // indicated in the last column.
847  if (inputLine.length() < 80) betaType = allowed;
848  a /= 1000.;
849  c /= 1000.;
850 
851  switch (theDecayMode) {
852 
853  case IT: // Isomeric transition
854  {
855  G4ITDecay* anITChannel = new G4ITDecay(&theParentNucleus, b,
856  c*MeV, a*MeV);
857 // anITChannel->DumpNuclearInfo();
858  anITChannel->SetHLThreshold(halflifethreshold);
859  anITChannel->SetARM(applyARM);
860  theDecayTable->Insert(anITChannel);
861  }
862  break;
863 
864  case BetaMinus:
865  {
866  if (modeFirstRecord[1]) {
867  modeFirstRecord[1] = false;
868  modeTotalBR[1] = b;
869  } else {
870  G4BetaMinusDecay* aBetaMinusChannel =
871  new G4BetaMinusDecay(&theParentNucleus, b, c*MeV, a*MeV,
872  betaType);
873 // aBetaMinusChannel->DumpNuclearInfo();
874  aBetaMinusChannel->SetHLThreshold(halflifethreshold);
875  theDecayTable->Insert(aBetaMinusChannel);
876  modeSumBR[1] += b;
877  } // if not first record
878  }
879  break;
880 
881  case BetaPlus:
882  {
883  if (modeFirstRecord[2]) {
884  modeFirstRecord[2] = false;
885  modeTotalBR[2] = b;
886  } else {
887  G4BetaPlusDecay* aBetaPlusChannel =
888  new G4BetaPlusDecay(&theParentNucleus, b, c*MeV, a*MeV,
889  betaType);
890 // aBetaPlusChannel->DumpNuclearInfo();
891  aBetaPlusChannel->SetHLThreshold(halflifethreshold);
892  theDecayTable->Insert(aBetaPlusChannel);
893  modeSumBR[2] += b;
894  } // if not first record
895  }
896  break;
897 
898  case KshellEC: // K-shell electron capture
899 
900  if (modeFirstRecord[3]) {
901  modeFirstRecord[3] = false;
902  modeTotalBR[3] = b;
903  } else {
904  G4ECDecay* aKECChannel = new G4ECDecay(&theParentNucleus, b,
905  c*MeV, a*MeV, KshellEC);
906 // aKECChannel->DumpNuclearInfo();
907  aKECChannel->SetHLThreshold(halflifethreshold);
908  aKECChannel->SetARM(applyARM);
909  theDecayTable->Insert(aKECChannel);
910  modeSumBR[3] += b;
911  }
912  break;
913 
914  case LshellEC: // L-shell electron capture
915 
916  if (modeFirstRecord[4]) {
917  modeFirstRecord[4] = false;
918  modeTotalBR[4] = b;
919  } else {
920  G4ECDecay* aLECChannel = new G4ECDecay(&theParentNucleus, b,
921  c*MeV, a*MeV, LshellEC);
922 // aLECChannel->DumpNuclearInfo();
923  aLECChannel->SetHLThreshold(halflifethreshold);
924  aLECChannel->SetARM(applyARM);
925  theDecayTable->Insert(aLECChannel);
926  modeSumBR[4] += b;
927  }
928  break;
929 
930  case MshellEC: // M-shell electron capture
931  // In this implementation it is added to L-shell case
932  if (modeFirstRecord[5]) {
933  modeFirstRecord[5] = false;
934  modeTotalBR[5] = b;
935  } else {
936  G4ECDecay* aMECChannel = new G4ECDecay(&theParentNucleus, b,
937  c*MeV, a*MeV, MshellEC);
938 // aMECChannel->DumpNuclearInfo();
939  aMECChannel->SetHLThreshold(halflifethreshold);
940  aMECChannel->SetARM(applyARM);
941  theDecayTable->Insert(aMECChannel);
942  modeSumBR[5] += b;
943  }
944  break;
945 
946  case Alpha:
947  if (modeFirstRecord[6]) {
948  modeFirstRecord[6] = false;
949  modeTotalBR[6] = b;
950  } else {
951  G4AlphaDecay* anAlphaChannel =
952  new G4AlphaDecay(&theParentNucleus, b, c*MeV, a*MeV);
953 // anAlphaChannel->DumpNuclearInfo();
954  anAlphaChannel->SetHLThreshold(halflifethreshold);
955  theDecayTable->Insert(anAlphaChannel);
956  modeSumBR[6] += b;
957  }
958  break;
959 
960  case Proton:
961  if (modeFirstRecord[7]) {
962  modeFirstRecord[7] = false;
963  modeTotalBR[7] = b;
964  } else {
965  G4ProtonDecay* aProtonChannel =
966  new G4ProtonDecay(&theParentNucleus, b, c*MeV, a*MeV);
967 // aProtonChannel->DumpNuclearInfo();
968  aProtonChannel->SetHLThreshold(halflifethreshold);
969  theDecayTable->Insert(aProtonChannel);
970  modeSumBR[7] += b;
971  }
972  break;
973 
974  case Neutron:
975  if (modeFirstRecord[8]) {
976  modeFirstRecord[8] = false;
977  modeTotalBR[8] = b;
978  } else {
979  G4NeutronDecay* aNeutronChannel =
980  new G4NeutronDecay(&theParentNucleus, b, c*MeV, a*MeV);
981 // aNeutronChannel->DumpNuclearInfo();
982  aNeutronChannel->SetHLThreshold(halflifethreshold);
983  theDecayTable->Insert(aNeutronChannel);
984  modeSumBR[8] += b;
985  }
986  break;
987  case BDProton:
988  // Not yet implemented
989  // G4cout << " beta-delayed proton decay, a = " << a << ", b = " << b << ", c = " << c << G4endl;
990  break;
991  case BDNeutron:
992  // Not yet implemented
993  // G4cout << " beta-delayed neutron decay, a = " << a << ", b = " << b << ", c = " << c << G4endl;
994  break;
995  case Beta2Minus:
996  // Not yet implemented
997  // G4cout << " Double beta- decay, a = " << a << ", b = " << b << ", c = " << c << G4endl;
998  break;
999  case Beta2Plus:
1000  // Not yet implemented
1001  // G4cout << " Double beta+ decay, a = " << a << ", b = " << b << ", c = " << c << G4endl;
1002  break;
1003  case Proton2:
1004  // Not yet implemented
1005  // G4cout << " Double proton decay, a = " << a << ", b = " << b << ", c = " << c << G4endl;
1006  break;
1007  case Neutron2:
1008  // Not yet implemented
1009  // G4cout << " Double beta- decay, a = " << a << ", b = " << b << ", c = " << c << G4endl;
1010  break;
1011  case SpFission:
1012  // Not yet implemented
1013  //G4cout<<"Sp fission channel"<<a<<'\t'<<b<<'\t'<<c<<std::endl;
1014  break;
1015  case RDM_ERROR:
1016 
1017  default:
1018  G4Exception("G4RadioactiveDecay::LoadDecayTable()", "HAD_RDM_000",
1019  FatalException, "Selected decay mode does not exist");
1020  } // switch
1021  } // if char == W
1022  } // if char == P
1023  } // if char != #
1024  } // While
1025 
1026  // Go through the decay table and make sure that the branching ratios are
1027  // correctly normalised.
1028 
1029  G4VDecayChannel* theChannel = 0;
1030  G4NuclearDecay* theNuclearDecayChannel = 0;
1031  G4String mode = "";
1032 
1033  G4double theBR = 0.0;
1034  for (G4int i = 0; i < theDecayTable->entries(); i++) {
1035  theChannel = theDecayTable->GetDecayChannel(i);
1036  theNuclearDecayChannel = static_cast<G4NuclearDecay*>(theChannel);
1037  theDecayMode = theNuclearDecayChannel->GetDecayMode();
1038 
1039  if (theDecayMode != IT) {
1040  theBR = theChannel->GetBR();
1041  theChannel->SetBR(theBR*modeTotalBR[theDecayMode]/modeSumBR[theDecayMode]);
1042  }
1043  }
1044  } // if (DecaySchemeFile)
1045  DecaySchemeFile.close();
1046 
1047  if (!found && levelEnergy > 0) {
1048  // Case where IT cascade for excited isotopes has no entries in RDM database
1049  // Decay mode is isomeric transition.
1050  G4ITDecay* anITChannel = new G4ITDecay(&theParentNucleus, 1.0, 0.0, 0.0);
1051  anITChannel->SetHLThreshold(halflifethreshold);
1052  anITChannel->SetARM(applyARM);
1053  theDecayTable->Insert(anITChannel);
1054  }
1055  if (!theDecayTable) {
1056  // There is no radioactive decay data for this nucleus. Return a null
1057  // decay table.
1058  G4cerr << "G4RadoactiveDecay::LoadDecayTable() : cannot find ion radioactive decay file "
1059  << G4endl;
1060  theDecayTable = 0;
1061  return theDecayTable;
1062  }
1063 
1064  if (theDecayTable && GetVerboseLevel() > 1) {
1065  theDecayTable->DumpInfo();
1066  }
1067 
1068 #ifdef G4MULTITHREADED
1069  //(*master_dkmap)[key] = theDecayTable; // store in master library
1070 #endif
1071  return theDecayTable;
1072 }
1073 
1074 void
1076 {
1077  if (Z < 1 || A < 2) G4cout << "Z and A not valid!" << G4endl;
1078 
1079  std::ifstream DecaySchemeFile(filename);
1080  if (DecaySchemeFile) {
1081  G4int ID_ion = A*1000 + Z;
1082  theUserRadioactiveDataFiles[ID_ion] = filename;
1083  } else {
1084  G4cout << "The file " << filename << " does not exist!" << G4endl;
1085  }
1086 }
1087 
1088 
1089 void
1091  G4int theG, std::vector<G4double> theRates,
1092  std::vector<G4double> theTaos)
1093 {
1094  //fill the decay rate vector
1095  theDecayRate.SetZ(theZ);
1096  theDecayRate.SetA(theA);
1097  theDecayRate.SetE(theE);
1099  theDecayRate.SetDecayRateC(theRates);
1100  theDecayRate.SetTaos(theTaos);
1101 }
1102 
1103 
1104 void
1106 {
1107  // 1) To calculate all the coefficiecies required to derive the
1108  // radioactivities for all progeny of theParentNucleus
1109  //
1110  // 2) Add the coefficiencies to the decay rate table vector
1111  //
1112 
1113  //
1114  // Create and initialise variables used in the method.
1115  //
1116  theDecayRateVector.clear();
1117 
1118  G4int nGeneration = 0;
1119  std::vector<G4double> rates;
1120  std::vector<G4double> taos;
1121 
1122  // start rate is -1.
1123  // Eq.4.26 of the Technical Note
1124  rates.push_back(-1.);
1125  //
1126  //
1127  G4int A = ((const G4Ions*)(&theParentNucleus))->GetAtomicMass();
1128  G4int Z = ((const G4Ions*)(&theParentNucleus))->GetAtomicNumber();
1129  G4double E = ((const G4Ions*)(&theParentNucleus))->GetExcitationEnergy();
1130  G4double tao = theParentNucleus.GetPDGLifeTime();
1131  if (tao < 0.) tao = 1e-100;
1132  taos.push_back(tao);
1133  G4int nEntry = 0;
1134 
1135  // Fill the decay rate container (G4RadioactiveDecayRate) with the parent
1136  // isotope data
1137  SetDecayRate(Z,A,E,nGeneration,rates,taos); // Fill TP with parent lifetime
1138 
1139  // store the decay rate in decay rate vector
1140  theDecayRateVector.push_back(theDecayRate);
1141  nEntry++;
1142 
1143  // now start treating the sencondary generations..
1144 
1145  G4bool stable = false;
1146  G4int i;
1147  G4int j;
1148  G4VDecayChannel* theChannel = 0;
1149  G4NuclearDecay* theNuclearDecayChannel = 0;
1150 
1151  G4ITDecay* theITChannel = 0;
1152  G4BetaMinusDecay* theBetaMinusChannel = 0;
1153  G4BetaPlusDecay* theBetaPlusChannel = 0;
1154  G4AlphaDecay* theAlphaChannel = 0;
1155  G4ProtonDecay* theProtonChannel = 0;
1156  G4NeutronDecay* theNeutronChannel = 0;
1157  G4RadioactiveDecayMode theDecayMode;
1158  G4double theBR = 0.0;
1159  G4int AP = 0;
1160  G4int ZP = 0;
1161  G4int AD = 0;
1162  G4int ZD = 0;
1163  G4double EP = 0.;
1164  std::vector<G4double> TP;
1165  std::vector<G4double> RP;
1166  G4ParticleDefinition *theDaughterNucleus;
1167  G4double daughterExcitation;
1168  G4ParticleDefinition *aParentNucleus;
1169  G4IonTable* theIonTable;
1170  G4DecayTable *aTempDecayTable;
1171  G4double theRate;
1172  G4double TaoPlus;
1173  G4int nS = 0;
1174  G4int nT = nEntry;
1175  const G4int nMode = 9;
1176  G4double brs[nMode];
1177  //
1178  theIonTable =
1180 
1181  G4int loop = 0;
1183  ed << " While count exceeded " << G4endl;
1184 
1185  while (!stable) { /* Loop checking, 01.09.2015, D.Wright */
1186  loop++;
1187  if (loop > 10000) {
1188  G4Exception("G4RadioactiveDecay::AddDecayRateTable()", "HAD_RDM_100", JustWarning, ed);
1189  break;
1190  }
1191  nGeneration++;
1192  for (j = nS; j < nT; j++) {
1193  // First time through, get data for parent nuclide
1194  ZP = theDecayRateVector[j].GetZ();
1195  AP = theDecayRateVector[j].GetA();
1196  EP = theDecayRateVector[j].GetE();
1197  RP = theDecayRateVector[j].GetDecayRateC();
1198  TP = theDecayRateVector[j].GetTaos();
1199  if (GetVerboseLevel() > 0) {
1200  G4cout << "G4RadioactiveDecay::AddDecayRateTable : daughters of ("
1201  << ZP << ", " << AP << ", " << EP
1202  << ") are being calculated, generation = " << nGeneration
1203  << G4endl;
1204  }
1205 
1206  aParentNucleus = theIonTable->GetIon(ZP,AP,EP);
1207  aTempDecayTable = GetDecayTable(aParentNucleus);
1208 
1209  // Local decay table for accessing BRs and decay channels, but channels
1210  // stored in it are not used to perform the actual decays
1211  G4DecayTable* theDecayTable = new G4DecayTable();
1212 
1213  for (G4int k = 0; k < nMode; k++) brs[k] = 0.0;
1214 
1215  // Go through the decay table and sum all channels having the same decay mode
1216  for (i = 0; i < aTempDecayTable->entries(); i++) {
1217  theChannel = aTempDecayTable->GetDecayChannel(i);
1218  theNuclearDecayChannel = static_cast<G4NuclearDecay*>(theChannel);
1219  theDecayMode = theNuclearDecayChannel->GetDecayMode();
1220  daughterExcitation = theNuclearDecayChannel->GetDaughterExcitation();
1221  theDaughterNucleus = theNuclearDecayChannel->GetDaughterNucleus() ;
1222 
1223  AD = ((const G4Ions*)(theDaughterNucleus))->GetAtomicMass();
1224  ZD = ((const G4Ions*)(theDaughterNucleus))->GetAtomicNumber();
1225  G4NuclearLevelManager* levelManager =
1227  if (levelManager->NumberOfLevels() ) {
1228  const G4NuclearLevel* level =
1229  levelManager->NearestLevel (daughterExcitation);
1230 
1231  if (std::abs(daughterExcitation - level->Energy()) < levelTolerance) {
1232  // Level half-life is in ns and the threshold is set to 1 micros
1233  // by default, user can set it via the UI command
1234  if (level->HalfLife()*ns >= halflifethreshold){
1235  // save the metastable nucleus
1236  theDecayTable->Insert(theChannel);
1237  } else {
1238  brs[theDecayMode] += theChannel->GetBR();
1239  }
1240  } else {
1241  brs[theDecayMode] += theChannel->GetBR();
1242  }
1243  } else {
1244  brs[theDecayMode] += theChannel->GetBR();
1245  }
1246  } // Combine decay channels (loop i)
1247 
1248  brs[2] = brs[2]+brs[3]+brs[4]+brs[5]; // Combine beta+ and EC
1249  brs[3] = brs[4] =brs[5] = 0.0;
1250  for (i= 0; i<nMode; i++){ // loop over decay modes
1251  if (brs[i] > 0.) {
1252  switch ( i ) {
1253  case 0:
1254  // Decay mode is isomeric transition
1255  theITChannel = new G4ITDecay(aParentNucleus, brs[0], 0.0, 0.0);
1256 
1257  theDecayTable->Insert(theITChannel);
1258  break;
1259 
1260  case 1:
1261  // Decay mode is beta-
1262  theBetaMinusChannel = new G4BetaMinusDecay(aParentNucleus, brs[1],
1263  0.*MeV, 0.*MeV, allowed);
1264  theDecayTable->Insert(theBetaMinusChannel);
1265  break;
1266 
1267  case 2:
1268  // Decay mode is beta+ + EC.
1269  theBetaPlusChannel = new G4BetaPlusDecay(aParentNucleus, brs[2], // DHW: April 2015
1270  0.*MeV, 0.*MeV, allowed);
1271  theDecayTable->Insert(theBetaPlusChannel);
1272  break;
1273 
1274  case 6:
1275  // Decay mode is alpha.
1276  theAlphaChannel = new G4AlphaDecay(aParentNucleus, brs[6], 0.*MeV,
1277  0.*MeV);
1278  theDecayTable->Insert(theAlphaChannel);
1279  break;
1280 
1281  case 7:
1282  // Decay mode is proton.
1283  theProtonChannel = new G4ProtonDecay(aParentNucleus, brs[7], 0.*MeV,
1284  0.*MeV);
1285  theDecayTable->Insert(theProtonChannel);
1286  break;
1287  case 8:
1288  // Decay mode is neutron.
1289  theNeutronChannel = new G4NeutronDecay(aParentNucleus, brs[8], 0.*MeV,
1290  0.*MeV);
1291  theDecayTable->Insert(theNeutronChannel);
1292  break;
1293 
1294  default:
1295  break;
1296  }
1297  }
1298  }
1299  // loop over all branches in theDecayTable
1300  //
1301  for (i = 0; i < theDecayTable->entries(); i++){
1302  theChannel = theDecayTable->GetDecayChannel(i);
1303  theNuclearDecayChannel = static_cast<G4NuclearDecay*>(theChannel);
1304  theBR = theChannel->GetBR();
1305  theDaughterNucleus = theNuclearDecayChannel->GetDaughterNucleus();
1306 
1307  // First check if the decay of the original nucleus is an IT channel,
1308  // if true create a new ground-state nucleus
1309  if (theNuclearDecayChannel->GetDecayMode() == IT && nGeneration == 1) {
1310 
1311  A = ((const G4Ions*)(theDaughterNucleus))->GetAtomicMass();
1312  Z = ((const G4Ions*)(theDaughterNucleus))->GetAtomicNumber();
1313  theDaughterNucleus=theIonTable->GetIon(Z,A,0.);
1314  }
1315  if (IsApplicable(*theDaughterNucleus) && theBR &&
1316  aParentNucleus != theDaughterNucleus) {
1317  // need to make sure daughter has decay table
1318  aTempDecayTable = GetDecayTable(theDaughterNucleus);
1319 
1320  if (aTempDecayTable->entries() ) {
1321  A = ((const G4Ions*)(theDaughterNucleus))->GetAtomicMass();
1322  Z = ((const G4Ions*)(theDaughterNucleus))->GetAtomicNumber();
1323  E = ((const G4Ions*)(theDaughterNucleus))->GetExcitationEnergy();
1324 
1325  TaoPlus = theDaughterNucleus->GetPDGLifeTime();
1326  if (TaoPlus <= 0.) TaoPlus = 1e-100;
1327 
1328  // first set the taos, one simply need to add to the parent ones
1329  taos.clear();
1330  taos = TP; // load lifetimes of all previous generations
1331  size_t k;
1332  //check that TaoPlus differs from other taos from at least 1.e5 relative difference
1333  //for (k = 0; k < TP.size(); k++){
1334  //if (std::abs((TaoPlus-TP[k])/TP[k])<1.e-5 ) TaoPlus=1.00001*TP[k];
1335  //}
1336  taos.push_back(TaoPlus); // add daughter lifetime to list
1337  // now calculate the coefficiencies
1338  //
1339  // they are in two parts, first the less than n ones
1340  // Eq 4.24 of the TN
1341  rates.clear();
1342  long double ta1,ta2;
1343  ta2 = (long double)TaoPlus;
1344  for (k = 0; k < RP.size(); k++){
1345  ta1 = (long double)TP[k]; // loop over lifetimes of all previous generations
1346  if (ta1 == ta2) {
1347  theRate = 1.e100;
1348  } else {
1349  theRate = ta1/(ta1-ta2);
1350  }
1351  theRate = theRate * theBR * RP[k];
1352  rates.push_back(theRate);
1353  }
1354 
1355  // the second part: the n:n coefficiency
1356  // Eq 4.25 of the TN. Note Yn+1 is zero apart from Y1 which is -1
1357  // as treated at line 1013
1358  theRate = 0.;
1359  long double aRate, aRate1;
1360  aRate1 = 0.L;
1361  for (k = 0; k < RP.size(); k++){
1362  ta1 = (long double)TP[k];
1363  if (ta1 == ta2 ) {
1364  aRate = 1.e100;
1365  } else {
1366  aRate = ta2/(ta1-ta2);
1367  }
1368  aRate = aRate * (long double)(theBR * RP[k]);
1369  aRate1 += aRate;
1370  }
1371  theRate = -aRate1;
1372  rates.push_back(theRate);
1373  SetDecayRate (Z,A,E,nGeneration,rates,taos);
1374  theDecayRateVector.push_back(theDecayRate);
1375  nEntry++;
1376  } // there are entries in the table
1377  } // nuclide is OK to decay
1378  } // end of loop (i) over decay table branches
1379  // delete theDecayTable;
1380 
1381  } // Getting contents of decay rate vector (end loop on j)
1382  nS = nT;
1383  nT = nEntry;
1384  if (nS == nT) stable = true;
1385  } // while nuclide is not stable
1386 
1387  // end of while loop
1388  // the calculation completed here
1389 
1390 
1391  // fill the first part of the decay rate table
1392  // which is the name of the original particle (isotope)
1393  theDecayRateTable.SetIonName(theParentNucleus.GetParticleName());
1394 
1395  // now fill the decay table with the newly completed decay rate vector
1397 
1398  // finally add the decayratetable to the tablevector
1400 }
1401 
1403 // //
1404 // SetSourceTimeProfile //
1405 // read in the source time profile function (histogram) //
1406 // //
1408 
1410 {
1411  std::ifstream infile ( filename, std::ios::in );
1412  if (!infile) {
1414  ed << " Could not open file " << filename << G4endl;
1415  G4Exception("G4RadioactiveDecay::SetSourceTimeProfile()", "HAD_RDM_001",
1416  FatalException, ed);
1417  }
1418 
1419  G4double bin, flux;
1420  NSourceBin = -1;
1421 
1422  G4int loop = 0;
1424  ed << " While count exceeded " << G4endl;
1425 
1426  while (infile >> bin >> flux ) { /* Loop checking, 01.09.2015, D.Wright */
1427  loop++;
1428  if (loop > 10000) {
1429  G4Exception("G4RadioactiveDecay::SetSourceTimeProfile()", "HAD_RDM_100", JustWarning, ed);
1430  break;
1431  }
1432 
1433  NSourceBin++;
1434  if (NSourceBin > 99) {
1435  G4Exception("G4RadioactiveDecay::SetSourceTimeProfile()", "HAD_RDM_002",
1436  FatalException, "Input source time file too big (>100 rows)");
1437 
1438  } else {
1439  SBin[NSourceBin] = bin * s;
1440  SProfile[NSourceBin] = flux;
1441  }
1442  }
1444  infile.close();
1445 
1446 #ifdef G4VERBOSE
1447  if (GetVerboseLevel() > 1)
1448  G4cout <<" Source Timeprofile Nbin = " << NSourceBin <<G4endl;
1449 #endif
1450 }
1451 
1453 // //
1454 // SetDecayBiasProfile //
1455 // read in the decay bias scheme function (histogram) //
1456 // //
1458 
1460 {
1461 
1462  std::ifstream infile(filename, std::ios::in);
1463  if (!infile) G4Exception("G4RadioactiveDecay::SetDecayBias()", "HAD_RDM_003",
1464  FatalException, "Unable to open bias data file" );
1465 
1466  G4double bin, flux;
1467  G4int dWindows = 0;
1468  G4int i ;
1469 
1470  theRadioactivityTables.clear();
1471 
1472  NDecayBin = -1;
1473 
1474  G4int loop = 0;
1476  ed << " While count exceeded " << G4endl;
1477 
1478  while (infile >> bin >> flux ) { /* Loop checking, 01.09.2015, D.Wright */
1479  NDecayBin++;
1480  loop++;
1481  if (loop > 10000) {
1482  G4Exception("G4RadioactiveDecay::SetDecayBias()", "HAD_RDM_100", JustWarning, ed);
1483  break;
1484  }
1485 
1486  if (NDecayBin > 99) {
1487  G4Exception("G4RadioactiveDecay::SetDecayBias()", "HAD_RDM_004",
1488  FatalException, "Input bias file too big (>100 rows)" );
1489  } else {
1490  DBin[NDecayBin] = bin * s;
1491  DProfile[NDecayBin] = flux;
1492  if (flux > 0.) {
1493  decayWindows[NDecayBin] = dWindows;
1494  dWindows++;
1495  G4RadioactivityTable *rTable = new G4RadioactivityTable() ;
1496  theRadioactivityTables.push_back(rTable);
1497  }
1498  }
1499  }
1500  for ( i = 1; i<= NDecayBin; i++) DProfile[i] += DProfile[i-1];
1501  for ( i = 0; i<= NDecayBin; i++) DProfile[i] /= DProfile[NDecayBin];
1502  // converted to accumulated probabilities
1503 
1505  infile.close();
1506 
1507 #ifdef G4VERBOSE
1508  if (GetVerboseLevel() > 1)
1509  G4cout <<" Decay Bias Profile Nbin = " << NDecayBin <<G4endl;
1510 #endif
1511 }
1512 
1514 // //
1515 // DecayIt //
1516 // //
1518 
1521 {
1522  // Initialize G4ParticleChange object, get particle details and decay table
1523 
1525  const G4DynamicParticle* theParticle = theTrack.GetDynamicParticle();
1526  const G4ParticleDefinition* theParticleDef = theParticle->GetDefinition();
1527 
1528  // First check whether RDM applies to the current logical volume
1529  if (!isAllVolumesMode) {
1530  if (!std::binary_search(ValidVolumes.begin(), ValidVolumes.end(),
1531  theTrack.GetVolume()->GetLogicalVolume()->GetName())) {
1532 #ifdef G4VERBOSE
1533  if (GetVerboseLevel()>0) {
1534  G4cout <<"G4RadioactiveDecay::DecayIt : "
1535  << theTrack.GetVolume()->GetLogicalVolume()->GetName()
1536  << " is not selected for the RDM"<< G4endl;
1537  G4cout << " There are " << ValidVolumes.size() << " volumes" << G4endl;
1538  G4cout << " The Valid volumes are " << G4endl;
1539  for (size_t i = 0; i< ValidVolumes.size(); i++)
1540  G4cout << ValidVolumes[i] << G4endl;
1541  }
1542 #endif
1544 
1545  // Kill the parent particle.
1550  }
1551  }
1552 
1553  // Now check if particle is valid for RDM
1554  if (!(IsApplicable(*theParticleDef) ) ) {
1555  // Particle is not an ion or is outside the nucleuslimits for decay
1556 
1557 #ifdef G4VERBOSE
1558  if (GetVerboseLevel()>0) {
1559  G4cerr << "G4RadioactiveDecay::DecayIt : "
1560  << theParticleDef->GetParticleName()
1561  << " is not a valid nucleus for the RDM"<< G4endl;
1562  }
1563 #endif
1565 
1566  // Kill the parent particle
1571  }
1572  G4DecayTable* theDecayTable = GetDecayTable(theParticleDef);
1573 
1574  if (theDecayTable == 0 || theDecayTable->entries() == 0) {
1575  // No data in the decay table. Set particle change parameters
1576  // to indicate this.
1577 #ifdef G4VERBOSE
1578  if (GetVerboseLevel() > 0) {
1579  G4cerr <<"G4RadioactiveDecay::DecayIt : decay table not defined for ";
1580  G4cerr <<theParticleDef->GetParticleName() <<G4endl;
1581  }
1582 #endif
1584 
1585  // Kill the parent particle.
1590 
1591  } else {
1592  // Data found. Try to decay nucleus
1593  G4double energyDeposit = 0.0;
1594  G4double finalGlobalTime = theTrack.GetGlobalTime();
1595  G4double finalLocalTime = theTrack.GetLocalTime();
1596  G4int index;
1597  G4ThreeVector currentPosition;
1598  currentPosition = theTrack.GetPosition();
1599 
1600  // Check whether use Analogue or VR implementation
1601  if (AnalogueMC) {
1602 #ifdef G4VERBOSE
1603  if (GetVerboseLevel() > 0)
1604  G4cout <<"DecayIt: Analogue MC version " << G4endl;
1605 # endif
1606 
1607  G4DecayProducts* products = DoDecay(*theParticleDef);
1608 
1609  // Check if the product is the same as input and kill the track if
1610  // necessary to prevent infinite loop (11/05/10, F.Lei)
1611  if ( products->entries() == 1) {
1617  }
1618 
1619  // Get parent particle information and boost the decay products to the
1620  // laboratory frame based on this information.
1621 
1622  //The Parent Energy used for the boost should be the total energy of
1623  // the nucleus of the parent ion without the energy of the shell electrons
1624  // (correction for bug 1359 by L. Desorgher)
1625  G4double ParentEnergy = theParticle->GetKineticEnergy()
1626  + theParticle->GetParticleDefinition()->GetPDGMass();
1627  G4ThreeVector ParentDirection(theParticle->GetMomentumDirection());
1628 
1629  if (theTrack.GetTrackStatus() == fStopButAlive) {
1630  //this condition seems to be always True, further investigation is needed (L.Desorgher)
1631 
1632  // The particle is decayed at rest.
1633  // since the time is still for rest particle in G4 we need to add the
1634  // additional time lapsed between the particle come to rest and the
1635  // actual decay. This time is simply sampled with the mean-life of
1636  // the particle. But we need to protect the case PDGTime < 0.
1637  // (F.Lei 11/05/10)
1638  G4double temptime = -std::log( G4UniformRand())
1639  *theParticleDef->GetPDGLifeTime();
1640  if (temptime < 0.) temptime = 0.;
1641  finalGlobalTime += temptime;
1642  finalLocalTime += temptime;
1643  energyDeposit += theParticle->GetKineticEnergy();
1644  }
1645  products->Boost(ParentEnergy, ParentDirection);
1646 
1647  // Add products in theParticleChangeForRadDecay.
1648  G4int numberOfSecondaries = products->entries();
1650 #ifdef G4VERBOSE
1651  if (GetVerboseLevel()>1) {
1652  G4cout <<"G4RadioactiveDecay::DecayIt : Decay vertex :";
1653  G4cout <<" Time: " <<finalGlobalTime/ns <<"[ns]";
1654  G4cout <<" X:" <<(theTrack.GetPosition()).x() /cm <<"[cm]";
1655  G4cout <<" Y:" <<(theTrack.GetPosition()).y() /cm <<"[cm]";
1656  G4cout <<" Z:" <<(theTrack.GetPosition()).z() /cm <<"[cm]";
1657  G4cout << G4endl;
1658  G4cout <<"G4Decay::DecayIt : decay products in Lab. Frame" <<G4endl;
1659  products->DumpInfo();
1660  products->IsChecked();
1661  }
1662 #endif
1663  for (index=0; index < numberOfSecondaries; index++) {
1664  G4Track* secondary = new G4Track(products->PopProducts(),
1665  finalGlobalTime, currentPosition);
1666  secondary->SetGoodForTrackingFlag();
1667  secondary->SetTouchableHandle(theTrack.GetTouchableHandle());
1669  }
1670  delete products;
1671  // end of analogue MC algorithm
1672 
1673  } else {
1674  // Variance Reduction Method
1675 #ifdef G4VERBOSE
1676  if (GetVerboseLevel()>0)
1677  G4cout << "DecayIt: Variance Reduction version " << G4endl;
1678 #endif
1679  if (!IsRateTableReady(*theParticleDef)) {
1680  // if the decayrates are not ready, calculate them and
1681  // add to the rate table vector
1682  AddDecayRateTable(*theParticleDef);
1683  }
1684  //retrieve the rates
1685  GetDecayRateTable(*theParticleDef);
1686 
1687  // declare some of the variables required in the implementation
1688  G4ParticleDefinition* parentNucleus;
1689  G4IonTable* theIonTable;
1690  G4int PZ;
1691  G4int PA;
1692  G4double PE;
1693  G4String keyName;
1694  std::vector<G4double> PT;
1695  std::vector<G4double> PR;
1696  G4double taotime;
1697  long double decayRate;
1698 
1699  size_t i;
1700  size_t j;
1701  G4int numberOfSecondaries;
1702  G4int totalNumberOfSecondaries = 0;
1703  G4double currentTime = 0.;
1704  G4int ndecaych;
1705  G4DynamicParticle* asecondaryparticle;
1706  std::vector<G4DynamicParticle*> secondaryparticles;
1707  std::vector<G4double> pw;
1708  std::vector<G4double> ptime;
1709  pw.clear();
1710  ptime.clear();
1711 
1712  //now apply the nucleus splitting
1713  for (G4int n = 0; n < NSplit; n++) {
1714  // Get the decay time following the decay probability function
1715  // suppllied by user
1716  G4double theDecayTime = GetDecayTime();
1717  G4int nbin = GetDecayTimeBin(theDecayTime);
1718 
1719  // calculate the first part of the weight function
1720  G4double weight1 = 1.;
1721  if (nbin == 1) {
1722  weight1 = 1./DProfile[nbin-1]
1723  *(DBin[nbin]-DBin[nbin-1])/NSplit;
1724  } else if (nbin > 1) {
1725  weight1 = 1./(DProfile[nbin]-DProfile[nbin-2])
1726  *(DBin[nbin]-DBin[nbin-1])/NSplit;
1727  }
1728 
1729  // it should be calculated in seconds
1730  weight1 /= s ;
1731 
1732  // loop over all the possible secondaries of the nucleus
1733  // the first one is itself.
1734  for (i = 0; i < theDecayRateVector.size(); i++) {
1735  PZ = theDecayRateVector[i].GetZ();
1736  PA = theDecayRateVector[i].GetA();
1737  PE = theDecayRateVector[i].GetE();
1738  PT = theDecayRateVector[i].GetTaos();
1739  PR = theDecayRateVector[i].GetDecayRateC();
1740 
1741  // Calculate the decay rate of the isotope
1742  // decayRate is the radioactivity of isotope (PZ,PA,PE) at the
1743  // time 'theDecayTime'
1744  // it will be used to calculate the statistical weight of the
1745  // decay products of this isotope
1746 
1747  // G4cout <<"PA= "<< PA << " PZ= " << PZ << " PE= "<< PE <<G4endl;
1748  decayRate = 0.L;
1749  for (j = 0; j < PT.size(); j++) {
1750  taotime = GetTaoTime(theDecayTime,PT[j]);
1751  decayRate -= PR[j] * (long double)taotime;
1752  // Eq.4.23 of of the TN
1753  // note the negative here is required as the rate in the
1754  // equation is defined to be negative,
1755  // i.e. decay away, but we need positive value here.
1756 
1757  // G4cout << j << "\t"<< PT[j]/s <<"\t"<<PR[j]<< "\t"
1758  // << decayRate << G4endl;
1759  }
1760 
1761  // add the isotope to the radioactivity tables
1762  // G4cout <<theDecayTime/s <<"\t"<<nbin<<G4endl;
1763  // G4cout << theTrack.GetWeight() <<"\t"<<weight1<<"\t"<<decayRate<< G4endl;
1764  theRadioactivityTables[decayWindows[nbin-1]]->AddIsotope(PZ,PA,PE,weight1*decayRate,theTrack.GetWeight());
1765 
1766  // Now calculate the statistical weight
1767  // One needs to fold the source bias function with the decaytime
1768  // also need to include the track weight! (F.Lei, 28/10/10)
1769  G4double weight = weight1*decayRate*theTrack.GetWeight();
1770 
1771  // decay the isotope
1773  parentNucleus = theIonTable->GetIon(PZ,PA,PE);
1774 
1775  // Create a temprary products buffer.
1776  // Its contents to be transfered to the products at the end of the loop
1777  G4DecayProducts* tempprods = 0;
1778 
1779  // Decide whether to apply branching ratio bias or not
1780  if (BRBias) {
1781  G4DecayTable* decayTable = GetDecayTable(parentNucleus);
1782 
1783  ndecaych = G4int(decayTable->entries()*G4UniformRand());
1784  G4VDecayChannel* theDecayChannel = decayTable->GetDecayChannel(ndecaych);
1785  if (theDecayChannel == 0) {
1786  // Decay channel not found.
1787 #ifdef G4VERBOSE
1788  if (GetVerboseLevel()>0) {
1789  G4cerr << " G4RadioactiveDecay::DoIt : cannot determine decay channel ";
1790  G4cerr << " for this nucleus; decay as if no biasing active ";
1791  G4cerr << G4endl;
1792  decayTable ->DumpInfo();
1793  }
1794 #endif
1795  tempprods = DoDecay(*parentNucleus); // DHW 6 Dec 2010 - do decay as if no biasing
1796  // to avoid deref of temppprods = 0
1797  } else {
1798  // A decay channel has been identified, so execute the DecayIt.
1799  G4double tempmass = parentNucleus->GetPDGMass();
1800  tempprods = theDecayChannel->DecayIt(tempmass);
1801  weight *= (theDecayChannel->GetBR())*(decayTable->entries());
1802  }
1803  } else {
1804  tempprods = DoDecay(*parentNucleus);
1805  }
1806 
1807  // save the secondaries for buffers
1808  numberOfSecondaries = tempprods->entries();
1809  currentTime = finalGlobalTime + theDecayTime;
1810  for (index = 0; index < numberOfSecondaries; index++) {
1811  asecondaryparticle = tempprods->PopProducts();
1812  if (asecondaryparticle->GetDefinition()->GetBaryonNumber() < 5) {
1813  pw.push_back(weight);
1814  ptime.push_back(currentTime);
1815  secondaryparticles.push_back(asecondaryparticle);
1816  }
1817  }
1818  delete tempprods;
1819 
1820  } // end of i loop
1821  } // end of n loop
1822 
1823  // now deal with the secondaries in the two stl containers
1824  // and submmit them back to the tracking manager
1825  totalNumberOfSecondaries = pw.size();
1826  fParticleChangeForRadDecay.SetNumberOfSecondaries(totalNumberOfSecondaries);
1827  for (index=0; index < totalNumberOfSecondaries; index++) {
1828  G4Track* secondary = new G4Track(secondaryparticles[index],
1829  ptime[index], currentPosition);
1830  secondary->SetGoodForTrackingFlag();
1831  secondary->SetTouchableHandle(theTrack.GetTouchableHandle());
1832  secondary->SetWeight(pw[index]);
1834  }
1835  // make sure the original track is set to stop and its kinematic energy collected
1836  //
1837  //theTrack.SetTrackStatus(fStopButAlive);
1838  //energyDeposit += theParticle->GetKineticEnergy();
1839 
1840  } // End of Variance Reduction
1841 
1842  // Kill the parent particle
1846  // Reset NumberOfInteractionLengthLeft.
1848 
1849  return &fParticleChangeForRadDecay ;
1850  }
1851 }
1852 
1853 
1856 {
1857  G4DecayProducts* products = 0;
1858  G4DecayTable* theDecayTable = GetDecayTable(&theParticleDef);
1859 
1860  // Choose a decay channel.
1861 #ifdef G4VERBOSE
1862  if (GetVerboseLevel() > 0) G4cout << "Select a channel..." << G4endl;
1863 #endif
1864 
1865  // G4DecayTable::SelectADecayChannel checks to see if sum of daughter masses
1866  // exceeds parent mass. Pass it the parent mass + maximum Q value to account
1867  // for difference in mass defect.
1868  G4double parentPlusQ = theParticleDef.GetPDGMass() + 30.*MeV;
1869  G4VDecayChannel* theDecayChannel = theDecayTable->SelectADecayChannel(parentPlusQ);
1870 
1871  if (theDecayChannel == 0) {
1872  // Decay channel not found.
1873  G4cerr << "G4RadioactiveDecay::DoIt : can not determine decay channel";
1874  G4cerr << G4endl;
1875  } else {
1876  // A decay channel has been identified, so execute the DecayIt.
1877 #ifdef G4VERBOSE
1878  if (GetVerboseLevel() > 1) {
1879  G4cerr << "G4RadioactiveDecay::DoIt : selected decay channel addr:";
1880  G4cerr << theDecayChannel << G4endl;
1881  }
1882 #endif
1883  products = theDecayChannel->DecayIt(theParticleDef.GetPDGMass() );
1884 
1885  // Apply directional bias if requested by user
1886  CollimateDecay(products);
1887  }
1888 
1889  return products;
1890 }
1891 
1892 
1893 // Apply directional bias for "visible" daughters (e+-, gamma, n, p, alpha)
1894 
1896  if (origin == forceDecayDirection) return; // No collimation requested
1897  if (180.*deg == forceDecayHalfAngle) return;
1898  if (0 == products || 0 == products->entries()) return;
1899 
1900 #ifdef G4VERBOSE
1901  if (GetVerboseLevel() > 0) G4cout << "Begin of CollimateDecay..." << G4endl;
1902 #endif
1903 
1904  // Particles suitable for directional biasing (for if-blocks below)
1908  static const G4ParticleDefinition* gamma = G4Gamma::Definition();
1911 
1912  G4ThreeVector newDirection; // Re-use to avoid memory churn
1913  for (G4int i=0; i<products->entries(); i++) {
1914  G4DynamicParticle* daughter = (*products)[i];
1915  const G4ParticleDefinition* daughterType =
1916  daughter->GetParticleDefinition();
1917  if (daughterType == electron || daughterType == positron ||
1918  daughterType == neutron || daughterType == gamma ||
1919  daughterType == alpha || daughterType == proton) CollimateDecayProduct(daughter);
1920  }
1921 }
1922 
1924 #ifdef G4VERBOSE
1925  if (GetVerboseLevel() > 1) {
1926  G4cout << "CollimateDecayProduct for daughter "
1927  << daughter->GetParticleDefinition()->GetParticleName() << G4endl;
1928  }
1929 #endif
1930 
1932  if (origin != collimate) daughter->SetMomentumDirection(collimate);
1933 }
1934 
1935 
1936 // Choose random direction within collimation cone
1937 
1939  if (origin == forceDecayDirection) return origin; // Don't do collimation
1940  if (forceDecayHalfAngle == 180.*deg) return origin;
1941 
1943 
1944  // Return direction offset by random throw
1945  if (forceDecayHalfAngle > 0.) {
1946  // Generate uniform direction around central axis
1947  G4double phi = 2.*pi*G4UniformRand();
1948  G4double cosMin = std::cos(forceDecayHalfAngle);
1949  G4double cosTheta = (1.-cosMin)*G4UniformRand() + cosMin; // [cosMin,1.)
1950 
1951  dir.setPhi(dir.phi()+phi);
1952  dir.setTheta(dir.theta()+std::acos(cosTheta));
1953  }
1954 
1955 #ifdef G4VERBOSE
1956  if (GetVerboseLevel()>1)
1957  G4cout << " ChooseCollimationDirection returns " << dir << G4endl;
1958 #endif
1959 
1960  return dir;
1961 }
static const double cm
Definition: G4SIunits.hh:118
G4double GetBR() const
G4RadioactiveDecayRateVector theDecayRateTable
static const double MeV
Definition: G4SIunits.hh:211
G4DecayProducts * DoDecay(const G4ParticleDefinition &theParticleDef)
void SetBR(G4double value)
static G4LossTableManager * Instance()
G4double GetLocalTime() const
void SelectAVolume(const G4String aVolume)
std::map< G4String, G4DecayTable * > DecayTableMap
std::ostringstream G4ExceptionDescription
Definition: globals.hh:76
G4double GetKineticEnergy() const
CLHEP::Hep3Vector G4ThreeVector
G4bool IsRateTableReady(const G4ParticleDefinition &)
const G4DynamicParticle * GetDynamicParticle() const
void SetHLThreshold(G4double HLT)
std::vector< G4String > ValidVolumes
void SetARM(G4bool onoff)
Definition: G4ITDecay.hh:59
G4double HalfLife() const
void SetTaos(std::vector< G4double > value)
G4double z
Definition: TRTMaterials.hh:39
G4String strip(G4int strip_Type=trailing, char c=' ')
void SetDecayRateC(std::vector< G4double > value)
G4bool GetPDGStable() const
G4ParticleDefinition * GetIon(G4int Z, G4int A, G4int lvl=0)
Definition: G4IonTable.cc:491
G4double Energy() const
static G4Alpha * Definition()
Definition: G4Alpha.cc:49
const G4ThreeVector & GetPosition() const
G4int GetZMax() const
void AddSecondary(G4Track *aSecondary)
G4TrackStatus GetTrackStatus() const
G4RadioactiveDecayMode GetDecayMode()
G4RadioactiveDecayRates theDecayRateVector
static G4Electron * Definition()
Definition: G4Electron.cc:49
void SetTouchableHandle(const G4TouchableHandle &apValue)
G4VDecayChannel * GetDecayChannel(G4int index) const
G4double GetMeanLifeTime(const G4Track &theTrack, G4ForceCondition *condition)
G4int GetVerboseLevel() const
void SetMomentumDirection(const G4ThreeVector &aDirection)
static G4NuclearLevelStore * GetInstance()
G4ParticleDefinition * GetDefinition() const
G4double a
Definition: TRTMaterials.hh:39
void SetSourceTimeProfile(G4String filename)
G4bool IsApplicable(const G4ParticleDefinition &)
void Boost(G4double totalEnergy, const G4ThreeVector &momentumDirection)
static G4Positron * Definition()
Definition: G4Positron.cc:49
void ClearNumberOfInteractionLengthLeft()
Definition: G4VProcess.hh:447
int G4int
Definition: G4Types.hh:78
static const double L
Definition: G4SIunits.hh:123
G4int GetAMin() const
#define G4MUTEX_INITIALIZER
Definition: G4Threading.hh:175
const G4String & GetParticleName() const
void SetWeight(G4double aValue)
void ProposeLocalEnergyDeposit(G4double anEnergyPart)
void SetItsRates(G4RadioactiveDecayRates arate)
G4ParticleChangeForRadDecay fParticleChangeForRadDecay
G4double GetTotalMomentum() const
static G4Proton * Definition()
Definition: G4Proton.cc:49
static const double s
Definition: G4SIunits.hh:168
G4int entries() const
virtual void Initialize(const G4Track &)
G4IonTable * GetIonTable() const
#define G4UniformRand()
Definition: Randomize.hh:97
G4GLOB_DLL std::ostream G4cout
double A(double temperature)
Definition: G4Ions.hh:51
static const G4ThreeVector origin
void SetDecayRate(G4int, G4int, G4double, G4int, std::vector< G4double >, std::vector< G4double >)
static const double deg
Definition: G4SIunits.hh:151
G4double GetMass() const
G4int GetAMax() const
bool G4bool
Definition: G4Types.hh:79
void DumpInfo() const
const G4ThreeVector & GetMomentumDirection() const
void DumpInfo() const
void CollimateDecayProduct(G4DynamicParticle *product)
G4VDecayChannel * SelectADecayChannel(G4double parentMass=-1.)
Definition: G4DecayTable.cc:81
G4RadioactiveDecayMode
static G4LogicalVolumeStore * GetInstance()
G4ThreeVector ChooseCollimationDirection() const
G4int GetDecayTimeBin(const G4double aDecayTime)
void SetProcessSubType(G4int)
Definition: G4VProcess.hh:432
static const double GeV
Definition: G4SIunits.hh:214
const G4String & GetParticleType() const
Definition: G4Step.hh:76
const G4ParticleDefinition * GetParticleDefinition() const
const G4int n
G4double GetGlobalTime() const
G4double GetTaoTime(const G4double, const G4double)
G4NucleusLimits theNucleusLimits
const G4TouchableHandle & GetTouchableHandle() const
G4ParticleDefinition * GetDaughterNucleus()
G4BetaDecayType
G4DecayTable * GetDecayTable(const G4ParticleDefinition *)
G4NuclearLevelManager * GetManager(G4int Z, G4int A)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
void Insert(G4VDecayChannel *aChannel)
Definition: G4DecayTable.cc:60
G4double GetDaughterExcitation()
void SetARM(G4bool onoff)
Definition: G4ECDecay.hh:55
G4double GetMeanFreePath(const G4Track &theTrack, G4double previousStepSize, G4ForceCondition *condition)
G4RadioactiveDecayRate theDecayRate
static const G4double levelTolerance
G4int G4Mutex
Definition: G4Threading.hh:173
G4RadioactiveDecayRateTable theDecayRateTableVector
std::map< G4int, G4String > theUserRadioactiveDataFiles
static const double nanosecond
Definition: G4SIunits.hh:157
G4LogicalVolume * GetLogicalVolume() const
G4double GetPDGMass() const
static const double pi
Definition: G4SIunits.hh:74
static G4ParticleTable * GetParticleTable()
void GetDecayRateTable(const G4ParticleDefinition &)
G4RadioactiveDecaymessenger * theRadioactiveDecaymessenger
void SetNumberOfSecondaries(G4int totSecondaries)
const G4double x[NPOINTSGL]
G4DynamicParticle * PopProducts()
G4VParticleChange * pParticleChange
Definition: G4VProcess.hh:283
void AddDecayRateTable(const G4ParticleDefinition &)
#define DBL_MIN
Definition: templates.hh:75
G4DecayTable * LoadDecayTable(const G4ParticleDefinition &theParentNucleus)
static G4Neutron * Definition()
Definition: G4Neutron.cc:54
G4VPhysicalVolume * GetVolume() const
std::vector< G4RadioactivityTable * > theRadioactivityTables
G4double GetWeight() const
G4double GetPDGLifeTime() const
G4RadioactiveDecay(const G4String &processName="RadioactiveDecay")
#define G4endl
Definition: G4ios.hh:61
static const double m
Definition: G4SIunits.hh:128
G4ThreeVector forceDecayDirection
G4bool IsChecked() const
G4VAtomDeexcitation * AtomDeexcitation()
static const double keV
Definition: G4SIunits.hh:213
G4int entries() const
virtual G4DecayProducts * DecayIt(G4double parentMass=-1.0)=0
const G4String & GetName() const
double G4double
Definition: G4Types.hh:76
void ProposeTrackStatus(G4TrackStatus status)
void BuildPhysicsTable(const G4ParticleDefinition &)
G4ForceCondition
void SetAnalogueMonteCarlo(G4bool r)
static const G4double alpha
void DeselectAVolume(const G4String aVolume)
#define DBL_MAX
Definition: templates.hh:83
void SetAtomDeexcitation(G4VAtomDeexcitation *)
#define ns
Definition: xmlparse.cc:614
const G4NuclearLevel * NearestLevel(G4double energy, G4double eDiffMax=1.e+8) const
void AddUserDecayDataFile(G4int Z, G4int A, G4String filename)
void CollimateDecay(G4DecayProducts *products)
void SetDecayBias(G4String filename)
G4int GetZMin() const
static G4Gamma * Definition()
Definition: G4Gamma.cc:49
void SetGoodForTrackingFlag(G4bool value=true)
G4VParticleChange * DecayIt(const G4Track &theTrack, const G4Step &theStep)
G4GLOB_DLL std::ostream G4cerr