ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4RadioactiveDecay.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4RadioactiveDecay.cc
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 "G4TritonDecay.hh"
116 #include "G4ProtonDecay.hh"
117 #include "G4NeutronDecay.hh"
118 #include "G4SFDecay.hh"
119 #include "G4VDecayChannel.hh"
120 #include "G4NuclearDecay.hh"
121 #include "G4RadioactiveDecayMode.hh"
122 #include "G4Fragment.hh"
123 #include "G4Ions.hh"
124 #include "G4IonTable.hh"
125 #include "G4BetaDecayType.hh"
126 #include "Randomize.hh"
127 #include "G4LogicalVolumeStore.hh"
128 #include "G4NuclearLevelData.hh"
129 #include "G4DeexPrecoParameters.hh"
130 #include "G4EmParameters.hh"
131 #include "G4LevelManager.hh"
132 #include "G4ThreeVector.hh"
133 #include "G4Electron.hh"
134 #include "G4Positron.hh"
135 #include "G4Neutron.hh"
136 #include "G4Gamma.hh"
137 #include "G4Alpha.hh"
138 #include "G4Triton.hh"
139 #include "G4Proton.hh"
140 
141 #include "G4HadronicProcessType.hh"
142 #include "G4HadronicProcessStore.hh"
143 #include "G4HadronicException.hh"
144 #include "G4PhotonEvaporation.hh"
145 
146 #include <vector>
147 #include <sstream>
148 #include <algorithm>
149 #include <fstream>
150 
151 using namespace CLHEP;
152 
155 
156 #ifdef G4MULTITHREADED
157 #include "G4AutoLock.hh"
158 G4Mutex G4RadioactiveDecay::radioactiveDecayMutex = G4MUTEX_INITIALIZER;
159 DecayTableMap* G4RadioactiveDecay::master_dkmap = 0;
160 
161 G4int& G4RadioactiveDecay::NumberOfInstances()
162 {
163  static G4int numberOfInstances = 0;
164  return numberOfInstances;
165 }
166 #endif
167 
169  : G4VRestDiscreteProcess(processName, fDecay), isInitialised(false),
170  forceDecayDirection(0.,0.,0.), forceDecayHalfAngle(0.*deg), dirPath(""),
171  verboseLevel(1)
172 {
173 #ifdef G4VERBOSE
174  if (GetVerboseLevel() > 1) {
175  G4cout << "G4RadioactiveDecay constructor: processName = " << processName
176  << G4endl;
177  }
178 #endif
179 
180  G4cout << " G4RadioactiveDecay is deprecated and will be removed in Geant4 version 11. " << G4endl;
181  G4cout << " Please replace it with G4RadioactiveDecayBase if you want the unbiased radioactive deacy process." << G4endl;
182  G4cout << " If you want the general process, with optional biasing, use G4Radioactivation. " << G4endl;
183 
185 
188 
189  // Set up photon evaporation for use in G4ITDecay
191  // photonEvaporation->SetVerboseLevel(2);
193  photonEvaporation->SetICM(true);
194 
195  // Check data directory
196  char* path_var = std::getenv("G4RADIOACTIVEDATA");
197  if (!path_var) {
198  G4Exception("G4RadioactiveDecay()","HAD_RDM_200",FatalException,
199  "Environment variable G4RADIOACTIVEDATA is not set");
200  } else {
201  dirPath = path_var; // convert to string
202  std::ostringstream os;
203  os << dirPath << "/z1.a3"; // used as a dummy
204  std::ifstream testFile;
205  testFile.open(os.str() );
206  if (!testFile.is_open() )
207  G4Exception("G4RadioactiveDecay()","HAD_RDM_201",FatalException,
208  "Environment variable G4RADIOACTIVEDATA is set, but does not point to correct directory");
209  }
210 
211  // Reset the list of user defined data files
213 
214  // Instantiate the map of decay tables
215 #ifdef G4MULTITHREADED
216  G4AutoLock lk(&G4RadioactiveDecay::radioactiveDecayMutex);
217  NumberOfInstances()++;
218  if(!master_dkmap) master_dkmap = new DecayTableMap;
219 #endif
220  dkmap = new DecayTableMap;
221 
222  // Apply default values.
223  NSourceBin = 1;
224  SBin[0] = 0.* s;
225  SBin[1] = 1.* s;
226  SProfile[0] = 1.;
227  SProfile[1] = 0.;
228  NDecayBin = 1;
229  DBin[0] = 0. * s ;
230  DBin[1] = 1. * s;
231  DProfile[0] = 1.;
232  DProfile[1] = 0.;
233  decayWindows[0] = 0;
235  theRadioactivityTables.push_back(rTable);
236  NSplit = 1;
237  AnalogueMC = true ;
238  FBeta = false ;
239  BRBias = true ;
240  applyICM = true ;
241  applyARM = true ;
243 
244  // RDM applies to all logical volumes by default
245  isAllVolumesMode = true;
248 }
249 
250 
251 void G4RadioactiveDecay::ProcessDescription(std::ostream& outFile) const
252 {
253  outFile << "The radioactive decay process (G4RadioactiveDecay) handles the\n"
254  << "alpha, beta+, beta-, electron capture and isomeric transition\n"
255  << "decays of nuclei (G4GenericIon) with masses A > 4.\n"
256  << "The required half-lives and decay schemes are retrieved from\n"
257  << "the RadioactiveDecay database which was derived from ENSDF.\n";
258 }
259 
260 
262 {
264  delete photonEvaporation;
265  for (DecayTableMap::iterator i = dkmap->begin(); i != dkmap->end(); i++) {
266  delete i->second;
267  }
268  dkmap->clear();
269  delete dkmap;
270 #ifdef G4MULTITHREADED
271  G4AutoLock lk(&G4RadioactiveDecay::radioactiveDecayMutex);
272  --NumberOfInstances();
273  if(NumberOfInstances()==0)
274  {
275  for (DecayTableMap::iterator i = master_dkmap->begin(); i != master_dkmap->end(); i++) {
276  delete i->second;
277  }
278  master_dkmap->clear();
279  delete master_dkmap;
280  }
281 #endif
282 }
283 
284 
286 {
287  // All particles other than G4Ions are rejected by default
288  if (((const G4Ions*)(&aParticle))->GetExcitationEnergy() > 0.) {
289  return true; // Not ground state - decay
290  }
291 
292  if (aParticle.GetParticleName() == "GenericIon") {
293  return true;
294  } else if (!(aParticle.GetParticleType() == "nucleus")
295  || aParticle.GetPDGLifeTime() < 0. ) {
296  return false; // Nuclide is stable - no decay
297  }
298 
299  // At this point nuclide must be an unstable ground state
300  // Determine whether it falls into the correct A and Z range
301  G4int A = ((const G4Ions*) (&aParticle))->GetAtomicMass();
302  G4int Z = ((const G4Ions*) (&aParticle))->GetAtomicNumber();
303 
305  {return false;}
306  else if (Z > theNucleusLimits.GetZMax() || Z < theNucleusLimits.GetZMin())
307  {return false;}
308  return true;
309 }
310 
312 {
313  G4String key = aNucleus->GetParticleName();
314  DecayTableMap::iterator table_ptr = dkmap->find(key);
315 
316  G4DecayTable* theDecayTable = 0;
317  if (table_ptr == dkmap->end() ) { // If table not there,
318  theDecayTable = LoadDecayTable(*aNucleus); // load from file and
319  if(theDecayTable) (*dkmap)[key] = theDecayTable; // store in library
320  } else {
321  theDecayTable = table_ptr->second;
322  }
323 
324  return theDecayTable;
325 }
326 
327 
329 {
330  G4LogicalVolumeStore* theLogicalVolumes;
332  theLogicalVolumes = G4LogicalVolumeStore::GetInstance();
333  for (size_t i = 0; i < theLogicalVolumes->size(); i++) {
334  volume=(*theLogicalVolumes)[i];
335  if (volume->GetName() == aVolume) {
336  ValidVolumes.push_back(aVolume);
337  std::sort(ValidVolumes.begin(), ValidVolumes.end());
338  // sort need for performing binary_search
339 #ifdef G4VERBOSE
340  if (GetVerboseLevel()>1)
341  G4cout << " RDM Applies to : " << aVolume << G4endl;
342 #endif
343  } else if(i == theLogicalVolumes->size()) {
345  ed << aVolume << " is not a valid logical volume name. Decay not activated for it."
346  << G4endl;
347  G4Exception("G4RadioactiveDecayBase::SelectAVolume()", "HAD_RDM_300",
348  JustWarning, ed);
349  }
350  }
351 }
352 
353 
355 {
356  G4LogicalVolumeStore* theLogicalVolumes;
358  theLogicalVolumes = G4LogicalVolumeStore::GetInstance();
359  for (size_t i = 0; i < theLogicalVolumes->size(); i++){
360  volume=(*theLogicalVolumes)[i];
361  if (volume->GetName() == aVolume) {
362  std::vector<G4String>::iterator location;
363  location = std::find(ValidVolumes.begin(),ValidVolumes.end(),aVolume);
364  if (location != ValidVolumes.end()) {
365  ValidVolumes.erase(location);
366  std::sort(ValidVolumes.begin(), ValidVolumes.end());
367  isAllVolumesMode =false;
368  } else {
370  ed << aVolume << " is not in the list " << G4endl;
371  G4Exception("G4RadioactiveDecayBase::DeselectAVolume()", "HAD_RDM_300",
372  JustWarning, ed);
373  }
374 #ifdef G4VERBOSE
375  if (GetVerboseLevel() > 0)
376  G4cout << " DeselectVolume: " << aVolume << " is removed from list "
377  << G4endl;
378 #endif
379  } else if (i == theLogicalVolumes->size()) {
381  ed << aVolume << " is not a valid logical volume name " << G4endl;
382  G4Exception("G4RadioactiveDecayBase::SelectAVolume()", "HAD_RDM_300",
383  JustWarning, ed);
384  }
385  }
386 }
387 
388 
390 {
391  G4LogicalVolumeStore* theLogicalVolumes;
393  theLogicalVolumes = G4LogicalVolumeStore::GetInstance();
394  ValidVolumes.clear();
395 #ifdef G4VERBOSE
396  if (GetVerboseLevel()>1)
397  G4cout << " RDM Applies to all Volumes" << G4endl;
398 #endif
399  for (size_t i = 0; i < theLogicalVolumes->size(); i++){
400  volume = (*theLogicalVolumes)[i];
401  ValidVolumes.push_back(volume->GetName());
402 #ifdef G4VERBOSE
403  if (GetVerboseLevel()>1)
404  G4cout << " RDM Applies to Volume " << volume->GetName() << G4endl;
405 #endif
406  }
407  std::sort(ValidVolumes.begin(), ValidVolumes.end());
408  // sort needed in order to allow binary_search
409  isAllVolumesMode=true;
410 }
411 
412 
414 {
415  ValidVolumes.clear();
416  isAllVolumesMode=false;
417 #ifdef G4VERBOSE
418  if (GetVerboseLevel() > 1) G4cout << "RDM removed from all volumes" << G4endl;
419 #endif
420 }
421 
422 
423 G4bool
425 {
426  // Check whether the radioactive decay rates table for the ion has already
427  // been calculated.
428  G4String aParticleName = aParticle.GetParticleName();
429  for (size_t i = 0; i < theParentChainTable.size(); i++) {
430  if (theParentChainTable[i].GetIonName() == aParticleName) return true;
431  }
432  return false;
433 }
434 
435 // retrieve the decayratetable for the specified aParticle
436 void
438 {
439  G4String aParticleName = aParticle.GetParticleName();
440 
441  for (size_t i = 0; i < theParentChainTable.size(); i++) {
442  if (theParentChainTable[i].GetIonName() == aParticleName) {
443  theDecayRateVector = theParentChainTable[i].GetItsRates();
444  }
445  }
446 #ifdef G4VERBOSE
447  if (GetVerboseLevel() > 1) {
448  G4cout << "The DecayRate Table for " << aParticleName << " is selected."
449  << G4endl;
450  }
451 #endif
452 }
453 
454 /* DHW: long double version - only few % improvement, but don't delete yet
455 G4double
456 G4RadioactiveDecay::ConvolveSourceTimeProfile(const G4double t, const G4double tau)
457 {
458  long double convolvedTime = 0.L;
459  G4int nbin;
460  if ( t > SBin[NSourceBin]) {
461  nbin = NSourceBin;
462  } else {
463  nbin = 0;
464 
465  G4int loop = 0;
466  while (t > SBin[nbin]) {
467  loop++;
468  if (loop > 1000) {
469  G4Exception("G4RadioactiveDecay::ConvolveSourceTimeProfile()",
470  "HAD_RDM_100", JustWarning, "While loop count exceeded");
471  break;
472  }
473 
474  nbin++;
475  }
476  nbin--;
477  }
478 
479  long double lt = t ;
480  long double ltau = tau;
481  long double earg = 0.L;
482  if (nbin > 0) {
483  for (G4int i = 0; i < nbin; i++) {
484  earg = (long double)(SBin[i+1] - SBin[i])/ltau;
485  if (earg < 100.) {
486  convolvedTime += (long double)SProfile[i] *
487  std::exp(((long double)SBin[i] - lt)/ltau) *
488  std::expm1(earg);
489  } else {
490  convolvedTime += (long double)SProfile[i] *
491  (std::exp(-(lt-(long double)SBin[i+1])/ltau)-std::exp(-(lt-(long double)SBin[i])/ltau));
492  }
493  }
494  }
495  // Use -expm1 instead of 1 - exp
496  convolvedTime -= (long double)SProfile[nbin] * std::expm1(((long double)SBin[nbin] - lt)/ltau);
497 
498  if (convolvedTime < 0.) {
499  G4cout << " Convolved time =: " << convolvedTime << " reset to zero! " << G4endl;
500  G4cout << " t = " << t << " tau = " << tau << G4endl;
501  G4cout << SBin[nbin] << " " << SBin[0] << G4endl;
502  convolvedTime = 0.;
503  }
504 #ifdef G4VERBOSE
505  if (GetVerboseLevel() > 1)
506  G4cout << " Convolved time: " << convolvedTime << G4endl;
507 #endif
508  return (G4double)convolvedTime;
509 }
510 */
511 
512 // ConvolveSourceTimeProfile performs the convolution of the source time profile
513 // function with a single exponential characterized by a decay constant in the
514 // decay chain. The time profile is treated as a set of step functions so that
515 // the convolution integral can be done bin-by-bin.
516 // This implements Eq. 4.13 of DERA technical note, with SProfile[i] = F(t')
517 
518 G4double
520 {
521  G4double convolvedTime = 0.0;
522  G4int nbin;
523  if ( t > SBin[NSourceBin]) {
524  nbin = NSourceBin;
525  } else {
526  nbin = 0;
527 
528  G4int loop = 0;
529  while (t > SBin[nbin]) { // Loop checking, 01.09.2015, D.Wright
530  loop++;
531  if (loop > 1000) {
532  G4Exception("G4RadioactiveDecay::ConvolveSourceTimeProfile()",
533  "HAD_RDM_100", JustWarning,"While loop count exceeded");
534  break;
535  }
536  nbin++;
537  }
538  nbin--;
539  }
540 
541  // Use expm1 wherever possible to avoid large cancellation errors in
542  // 1 - exp(x) for small x
543  G4double earg = 0.0;
544  if (nbin > 0) {
545  for (G4int i = 0; i < nbin; i++) {
546  earg = (SBin[i+1] - SBin[i])/tau;
547  if (earg < 100.) {
548  convolvedTime += SProfile[i] * std::exp((SBin[i] - t)/tau) *
549  std::expm1(earg);
550  } else {
551  convolvedTime += SProfile[i] *
552  (std::exp(-(t-SBin[i+1])/tau)-std::exp(-(t-SBin[i])/tau));
553  }
554  }
555  }
556  convolvedTime -= SProfile[nbin] * std::expm1((SBin[nbin] - t)/tau);
557  // tau divided out of final result to provide probability of decay in window
558 
559  if (convolvedTime < 0.) {
560  G4cout << " Convolved time =: " << convolvedTime << " reset to zero! " << G4endl;
561  G4cout << " t = " << t << " tau = " << tau << G4endl;
562  G4cout << SBin[nbin] << " " << SBin[0] << G4endl;
563  convolvedTime = 0.;
564  }
565 #ifdef G4VERBOSE
566  if (GetVerboseLevel() > 1)
567  G4cout << " Convolved time: " << convolvedTime << G4endl;
568 #endif
569  return convolvedTime;
570 }
571 
572 
574 // //
575 // GetDecayTime //
576 // Randomly select a decay time for the decay process, following the //
577 // supplied decay time bias scheme. //
578 // //
580 
582 {
583  G4double decaytime = 0.;
584  G4double rand = G4UniformRand();
585  G4int i = 0;
586 
587  G4int loop = 0;
588  while ( DProfile[i] < rand) { /* Loop checking, 01.09.2015, D.Wright */
589  i++;
590  loop++;
591  if (loop > 100000) {
592  G4Exception("G4RadioactiveDecay::GetDecayTime()", "HAD_RDM_100",
593  JustWarning, "While loop count exceeded");
594  break;
595  }
596  }
597 
598  rand = G4UniformRand();
599  decaytime = DBin[i] + rand*(DBin[i+1]-DBin[i]);
600 #ifdef G4VERBOSE
601  if (GetVerboseLevel() > 1)
602  G4cout <<" Decay time: " <<decaytime/s <<"[s]" <<G4endl;
603 #endif
604  return decaytime;
605 }
606 
607 
609 {
610  G4int i = 0;
611 
612  G4int loop = 0;
613  while ( aDecayTime > DBin[i] ) { /* Loop checking, 01.09.2015, D.Wright */
614  i++;
615  loop++;
616  if (loop > 100000) {
617  G4Exception("G4RadioactiveDecay::GetDecayTimeBin()", "HAD_RDM_100",
618  JustWarning, "While loop count exceeded");
619  break;
620  }
621  }
622 
623  return i;
624 }
625 
627 // //
628 // GetMeanLifeTime (required by the base class) //
629 // //
631 
634 {
635  // For variance reduction the time is set to 0 so as to force the particle
636  // to decay immediately.
637  // In analogueMC mode it returns the particle's mean-life.
638 
639  G4double meanlife = 0.;
640  if (AnalogueMC) {
641  const G4DynamicParticle* theParticle = theTrack.GetDynamicParticle();
642  const G4ParticleDefinition* theParticleDef = theParticle->GetDefinition();
643  G4double theLife = theParticleDef->GetPDGLifeTime();
644 #ifdef G4VERBOSE
645  if (GetVerboseLevel() > 2) {
646  G4cout << "G4RadioactiveDecay::GetMeanLifeTime() " << G4endl;
647  G4cout << "KineticEnergy: " << theParticle->GetKineticEnergy()/GeV
648  << " GeV, Mass: " << theParticle->GetMass()/GeV
649  << " GeV, Life time: " << theLife/ns << " ns " << G4endl;
650  }
651 #endif
652  if (theParticleDef->GetPDGStable()) {meanlife = DBL_MAX;}
653  else if (theLife < 0.0) {meanlife = DBL_MAX;}
654  else {meanlife = theLife;}
655  // Set meanlife to zero for excited istopes which are not in the
656  // RDM database
657  if (((const G4Ions*)(theParticleDef))->GetExcitationEnergy() > 0. &&
658  meanlife == DBL_MAX) {meanlife = 0.;}
659  }
660 #ifdef G4VERBOSE
661  if (GetVerboseLevel() > 2)
662  G4cout << " mean life time: " << meanlife/s << " s " << G4endl;
663 #endif
664 
665  return meanlife;
666 }
667 
669 // //
670 // GetMeanFreePath for decay in flight //
671 // //
673 
676 {
677  const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
678  const G4ParticleDefinition* aParticleDef = aParticle->GetDefinition();
679  G4double tau = aParticleDef->GetPDGLifeTime();
680  G4double aMass = aParticle->GetMass();
681 
682 #ifdef G4VERBOSE
683  if (GetVerboseLevel() > 2) {
684  G4cout << "G4RadioactiveDecay::GetMeanFreePath() " << G4endl;
685  G4cout << " KineticEnergy: " << aParticle->GetKineticEnergy()/GeV
686  << " GeV, Mass: " << aMass/GeV << " GeV, tau: " << tau << " ns "
687  << G4endl;
688  }
689 #endif
690  G4double pathlength = DBL_MAX;
691  if (tau != -1) {
692  // Ion can decay
693 
694  if (tau < -1000.0) {
695  pathlength = DBL_MIN; // nuclide had very short lifetime or wasn't in table
696 
697  } else if (tau < 0.0) {
698  G4cout << aParticleDef->GetParticleName() << " has lifetime " << tau << G4endl;
700  ed << "Ion has negative lifetime " << tau
701  << " but is not stable. Setting mean free path to DBL_MAX" << G4endl;
702  G4Exception("G4RadioactiveDecay::GetMeanFreePath()", "HAD_RDM_011",
703  JustWarning, ed);
704  pathlength = DBL_MAX;
705 
706  } else {
707  // Calculate mean free path
708  G4double betaGamma = aParticle->GetTotalMomentum()/aMass;
709  pathlength = c_light*tau*betaGamma;
710 
711  if (pathlength < DBL_MIN) {
712  pathlength = DBL_MIN;
713 #ifdef G4VERBOSE
714  if (GetVerboseLevel() > 2) {
715  G4cout << "G4Decay::GetMeanFreePath: "
716  << aParticleDef->GetParticleName()
717  << " stops, kinetic energy = "
718  << aParticle->GetKineticEnergy()/keV <<" keV " << G4endl;
719  }
720 #endif
721  }
722  }
723  }
724 
725 #ifdef G4VERBOSE
726  if (GetVerboseLevel() > 1) {
727  G4cout << "mean free path: "<< pathlength/m << " m" << G4endl;
728  }
729 #endif
730  return pathlength;
731 }
732 
734 // //
735 // BuildPhysicsTable - enable print of parameters //
736 // //
738 
740 {
741  if (!isInitialised) {
742  isInitialised = true;
743 #ifdef G4VERBOSE
745 #endif
746  }
749 }
750 
752 // //
753 // StreamInfo - stream out parameters //
754 // //
756 
757 void G4RadioactiveDecay::StreamInfo(std::ostream& os, const G4String& endline)
758 {
759  G4DeexPrecoParameters* deex =
762 
763  G4int prec = os.precision(5);
764  os << "======================================================================="
765  << endline;
766  os << "====== Radioactive Decay Physics Parameters ========"
767  << endline;
768  os << "======================================================================="
769  << endline;
770  os << "Max life time "
771  << deex->GetMaxLifeTime()/CLHEP::ps << " ps" << endline;
772  os << "Internal e- conversion flag "
773  << deex->GetInternalConversionFlag() << endline;
774  os << "Stored internal conversion coefficients "
775  << deex->StoreICLevelData() << endline;
776  os << "Enable correlated gamma emission "
777  << deex->CorrelatedGamma() << endline;
778  os << "Max 2J for sampling of angular correlations "
779  << deex->GetTwoJMAX() << endline;
780  os << "Atomic de-excitation enabled "
781  << emparam->Fluo() << endline;
782  os << "Auger electron emission enabled "
783  << emparam->Auger() << endline;
784  os << "Auger cascade enabled "
785  << emparam->AugerCascade() << endline;
786  os << "Check EM cuts disabled for atomic de-excitation "
787  << emparam->DeexcitationIgnoreCut() << endline;
788  os << "Use Bearden atomic level energies "
789  << emparam->BeardenFluoDir() << endline;
790  os << "======================================================================="
791  << endline;
792  os.precision(prec);
793 }
794 
796 // //
797 // LoadDecayTable loads the decay scheme from the RadioactiveDecay database //
798 // for the parent nucleus. //
799 // //
801 
804 {
805  // Generate input data file name using Z and A of the parent nucleus
806  // file containing radioactive decay data.
807  G4int A = ((const G4Ions*)(&theParentNucleus))->GetAtomicMass();
808  G4int Z = ((const G4Ions*)(&theParentNucleus))->GetAtomicNumber();
809 
810  G4double levelEnergy = ((const G4Ions*)(&theParentNucleus))->GetExcitationEnergy();
811  G4Ions::G4FloatLevelBase floatingLevel =
812  ((const G4Ions*)(&theParentNucleus))->GetFloatLevelBase();
813 
814 #ifdef G4MULTITHREADED
815  G4AutoLock lk(&G4RadioactiveDecay::radioactiveDecayMutex);
816 
817  G4String key = theParentNucleus.GetParticleName();
818  DecayTableMap::iterator master_table_ptr = master_dkmap->find(key);
819 
820  if (master_table_ptr != master_dkmap->end() ) { // If table is there
821  return master_table_ptr->second;
822  }
823 #endif
824 
825  //Check if data have been provided by the user
827 
828  if (file == "") {
829  std::ostringstream os;
830  os << dirPath << "/z" << Z << ".a" << A << '\0';
831  file = os.str();
832  }
833 
834  G4DecayTable* theDecayTable = new G4DecayTable();
835  G4bool found(false); // True if energy level matches one in table
836 
837  std::ifstream DecaySchemeFile;
838  DecaySchemeFile.open(file);
839 
840  if (DecaySchemeFile.good()) {
841  // Initialize variables used for reading in radioactive decay data
842  G4bool floatMatch(false);
843  const G4int nMode = 12;
844  G4double modeTotalBR[nMode] = {0.0};
845  G4double modeSumBR[nMode];
846  for (G4int i = 0; i < nMode; i++) {
847  modeSumBR[i] = 0.0;
848  }
849 
850  char inputChars[120]={' '};
851  G4String inputLine;
852  G4String recordType("");
853  G4String floatingFlag("");
854  G4String daughterFloatFlag("");
855  G4Ions::G4FloatLevelBase daughterFloatLevel;
856  G4RadioactiveDecayMode theDecayMode;
857  G4double decayModeTotal(0.0);
858  G4double parentExcitation(0.0);
859  G4double a(0.0);
860  G4double b(0.0);
861  G4double c(0.0);
862  G4double dummy(0.0);
863  G4BetaDecayType betaType(allowed);
864 
865  // Loop through each data file record until you identify the decay
866  // data relating to the nuclide of concern.
867 
868  G4bool complete(false); // bool insures only one set of values read for any
869  // given parent energy level
870  G4int loop = 0;
871  while (!complete && !DecaySchemeFile.getline(inputChars, 120).eof()) { /* Loop checking, 01.09.2015, D.Wright */
872  loop++;
873  if (loop > 100000) {
874  G4Exception("G4RadioactiveDecay::LoadDecayTable()", "HAD_RDM_100",
875  JustWarning, "While loop count exceeded");
876  break;
877  }
878 
879  inputLine = inputChars;
880  inputLine = inputLine.strip(1);
881  if (inputChars[0] != '#' && inputLine.length() != 0) {
882  std::istringstream tmpStream(inputLine);
883 
884  if (inputChars[0] == 'P') {
885  // Nucleus is a parent type. Check excitation level to see if it
886  // matches that of theParentNucleus
887  tmpStream >> recordType >> parentExcitation >> floatingFlag >> dummy;
888  // "dummy" takes the place of half-life
889  // Now read in from ENSDFSTATE in particle category
890 
891  if (found) {
892  complete = true;
893  } else {
894  // Take first level which matches excitation energy regardless of floating level
895  found = (std::abs(parentExcitation*keV - levelEnergy) < levelTolerance);
896  if (floatingLevel != noFloat) {
897  // If floating level specificed, require match of both energy and floating level
898  floatMatch = (floatingLevel == G4Ions::FloatLevelBase(floatingFlag.back()) );
899  if (!floatMatch) found = false;
900  }
901  }
902 
903  } else if (found) {
904  // The right part of the radioactive decay data file has been found. Search
905  // through it to determine the mode of decay of the subsequent records.
906 
907  // Store for later the total decay probability for each decay mode
908  if (inputLine.length() < 72) {
909  tmpStream >> theDecayMode >> dummy >> decayModeTotal;
910  switch (theDecayMode) {
911  case IT:
912  {
913  G4ITDecay* anITChannel = new G4ITDecay(&theParentNucleus, decayModeTotal,
914  0.0, 0.0, photonEvaporation);
915  anITChannel->SetHLThreshold(halflifethreshold);
916  anITChannel->SetARM(applyARM);
917  theDecayTable->Insert(anITChannel);
918 // anITChannel->DumpNuclearInfo();
919  }
920  break;
921  case BetaMinus:
922  modeTotalBR[1] = decayModeTotal; break;
923  case BetaPlus:
924  modeTotalBR[2] = decayModeTotal; break;
925  case KshellEC:
926  modeTotalBR[3] = decayModeTotal; break;
927  case LshellEC:
928  modeTotalBR[4] = decayModeTotal; break;
929  case MshellEC:
930  modeTotalBR[5] = decayModeTotal; break;
931  case NshellEC:
932  modeTotalBR[6] = decayModeTotal; break;
933  case Alpha:
934  modeTotalBR[7] = decayModeTotal; break;
935  case Proton:
936  modeTotalBR[8] = decayModeTotal; break;
937  case Neutron:
938  modeTotalBR[9] = decayModeTotal; break;
939  case BDProton:
940  break;
941  case BDNeutron:
942  break;
943  case Beta2Minus:
944  break;
945  case Beta2Plus:
946  break;
947  case Proton2:
948  break;
949  case Neutron2:
950  break;
951  case SpFission:
952  modeTotalBR[10] = decayModeTotal; break;
953  case Triton:
954  modeTotalBR[11] = decayModeTotal; break;
955  case RDM_ERROR:
956 
957  default:
958  G4Exception("G4RadioactiveDecay::LoadDecayTable()", "HAD_RDM_000",
959  FatalException, "Selected decay mode does not exist");
960  } // switch
961 
962  } else {
963  if (inputLine.length() < 84) {
964  tmpStream >> theDecayMode >> a >> daughterFloatFlag >> b >> c;
965  betaType = allowed;
966  } else {
967  tmpStream >> theDecayMode >> a >> daughterFloatFlag >> b >> c >> betaType;
968  }
969 
970  // Allowed transitions are the default. Forbidden transitions are
971  // indicated in the last column.
972  a /= 1000.;
973  c /= 1000.;
974  b/=100.;
975  daughterFloatLevel = G4Ions::FloatLevelBase(daughterFloatFlag.back());
976 
977  switch (theDecayMode) {
978  case BetaMinus:
979  {
980  G4BetaMinusDecay* aBetaMinusChannel =
981  new G4BetaMinusDecay(&theParentNucleus, b, c*MeV, a*MeV,
982  daughterFloatLevel, betaType);
983 // aBetaMinusChannel->DumpNuclearInfo();
984  aBetaMinusChannel->SetHLThreshold(halflifethreshold);
985  theDecayTable->Insert(aBetaMinusChannel);
986  modeSumBR[1] += b;
987  }
988  break;
989 
990  case BetaPlus:
991  {
992  G4BetaPlusDecay* aBetaPlusChannel =
993  new G4BetaPlusDecay(&theParentNucleus, b, c*MeV, a*MeV,
994  daughterFloatLevel, betaType);
995 // aBetaPlusChannel->DumpNuclearInfo();
996  aBetaPlusChannel->SetHLThreshold(halflifethreshold);
997  theDecayTable->Insert(aBetaPlusChannel);
998  modeSumBR[2] += b;
999  }
1000  break;
1001 
1002  case KshellEC: // K-shell electron capture
1003  {
1004  G4ECDecay* aKECChannel =
1005  new G4ECDecay(&theParentNucleus, b, c*MeV, a*MeV,
1006  daughterFloatLevel, KshellEC);
1007 // aKECChannel->DumpNuclearInfo();
1008  aKECChannel->SetHLThreshold(halflifethreshold);
1009  aKECChannel->SetARM(applyARM);
1010  theDecayTable->Insert(aKECChannel);
1011  modeSumBR[3] += b;
1012  }
1013  break;
1014 
1015  case LshellEC: // L-shell electron capture
1016  {
1017  G4ECDecay* aLECChannel =
1018  new G4ECDecay(&theParentNucleus, b, c*MeV, a*MeV,
1019  daughterFloatLevel, LshellEC);
1020 // aLECChannel->DumpNuclearInfo();
1021  aLECChannel->SetHLThreshold(halflifethreshold);
1022  aLECChannel->SetARM(applyARM);
1023  theDecayTable->Insert(aLECChannel);
1024  modeSumBR[4] += b;
1025  }
1026  break;
1027 
1028  case MshellEC: // M-shell electron capture
1029  {
1030  G4ECDecay* aMECChannel =
1031  new G4ECDecay(&theParentNucleus, b, c*MeV, a*MeV,
1032  daughterFloatLevel, MshellEC);
1033 // aMECChannel->DumpNuclearInfo();
1034  aMECChannel->SetHLThreshold(halflifethreshold);
1035  aMECChannel->SetARM(applyARM);
1036  theDecayTable->Insert(aMECChannel);
1037  modeSumBR[5] += b;
1038  }
1039  break;
1040 
1041  case NshellEC: // N-shell electron capture
1042  {
1043  G4ECDecay* aNECChannel =
1044  new G4ECDecay(&theParentNucleus, b, c*MeV, a*MeV,
1045  daughterFloatLevel, NshellEC);
1046 // aNECChannel->DumpNuclearInfo();
1047  aNECChannel->SetHLThreshold(halflifethreshold);
1048  aNECChannel->SetARM(applyARM);
1049  theDecayTable->Insert(aNECChannel);
1050  modeSumBR[6] += b;
1051  }
1052  break;
1053 
1054  case Alpha:
1055  {
1056  G4AlphaDecay* anAlphaChannel =
1057  new G4AlphaDecay(&theParentNucleus, b, c*MeV, a*MeV,
1058  daughterFloatLevel);
1059 // anAlphaChannel->DumpNuclearInfo();
1060  anAlphaChannel->SetHLThreshold(halflifethreshold);
1061  theDecayTable->Insert(anAlphaChannel);
1062  modeSumBR[7] += b;
1063  }
1064  break;
1065 
1066  case Proton:
1067  {
1068  G4ProtonDecay* aProtonChannel =
1069  new G4ProtonDecay(&theParentNucleus, b, c*MeV, a*MeV,
1070  daughterFloatLevel);
1071 // aProtonChannel->DumpNuclearInfo();
1072  aProtonChannel->SetHLThreshold(halflifethreshold);
1073  theDecayTable->Insert(aProtonChannel);
1074  modeSumBR[8] += b;
1075  }
1076  break;
1077 
1078  case Neutron:
1079  {
1080  G4NeutronDecay* aNeutronChannel =
1081  new G4NeutronDecay(&theParentNucleus, b, c*MeV, a*MeV,
1082  daughterFloatLevel);
1083 // aNeutronChannel->DumpNuclearInfo();
1084  aNeutronChannel->SetHLThreshold(halflifethreshold);
1085  theDecayTable->Insert(aNeutronChannel);
1086  modeSumBR[9] += b;
1087  }
1088  break;
1089 
1090  case BDProton:
1091  // Not yet implemented
1092  // G4cout << " beta-delayed proton decay, a = " << a << ", b = " << b << ", c = " << c << G4endl;
1093  break;
1094  case BDNeutron:
1095  // Not yet implemented
1096  // G4cout << " beta-delayed neutron decay, a = " << a << ", b = " << b << ", c = " << c << G4endl;
1097  break;
1098  case Beta2Minus:
1099  // Not yet implemented
1100  // G4cout << " Double beta- decay, a = " << a << ", b = " << b << ", c = " << c << G4endl;
1101  break;
1102  case Beta2Plus:
1103  // Not yet implemented
1104  // G4cout << " Double beta+ decay, a = " << a << ", b = " << b << ", c = " << c << G4endl;
1105  break;
1106  case Proton2:
1107  // Not yet implemented
1108  // G4cout << " Double proton decay, a = " << a << ", b = " << b << ", c = " << c << G4endl;
1109  break;
1110  case Neutron2:
1111  // Not yet implemented
1112  // G4cout << " Double beta- decay, a = " << a << ", b = " << b << ", c = " << c << G4endl;
1113  break;
1114  case SpFission:
1115  {
1116  G4SFDecay* aSpontFissChannel =
1117 // new G4SFDecay(&theParentNucleus, decayModeTotal, 0.0, 0.0);
1118  new G4SFDecay(&theParentNucleus, b, c*MeV, a*MeV,
1119  daughterFloatLevel);
1120  theDecayTable->Insert(aSpontFissChannel);
1121  modeSumBR[10] += b;
1122  }
1123  break;
1124  case Triton:
1125  {
1126  G4TritonDecay* aTritonChannel =
1127  new G4TritonDecay(&theParentNucleus, b, c*MeV, a*MeV,
1128  daughterFloatLevel);
1129  // anTritonChannel->DumpNuclearInfo();
1130  aTritonChannel->SetHLThreshold(halflifethreshold);
1131  theDecayTable->Insert(aTritonChannel);
1132  modeSumBR[11] += b;
1133  }
1134  break;
1135 
1136  case RDM_ERROR:
1137 
1138  default:
1139  G4Exception("G4RadioactiveDecay::LoadDecayTable()", "HAD_RDM_000",
1140  FatalException, "Selected decay mode does not exist");
1141  } // switch
1142  } // line < 72
1143  } // if char == P
1144  } // if char != #
1145  } // While
1146 
1147  // Go through the decay table and make sure that the branching ratios are
1148  // correctly normalised.
1149 
1150  G4VDecayChannel* theChannel = 0;
1151  G4NuclearDecay* theNuclearDecayChannel = 0;
1152  G4String mode = "";
1153 
1154  G4double theBR = 0.0;
1155  for (G4int i = 0; i < theDecayTable->entries(); i++) {
1156  theChannel = theDecayTable->GetDecayChannel(i);
1157  theNuclearDecayChannel = static_cast<G4NuclearDecay*>(theChannel);
1158  theDecayMode = theNuclearDecayChannel->GetDecayMode();
1159 
1160  if (theDecayMode != IT) {
1161  theBR = theChannel->GetBR();
1162  theChannel->SetBR(theBR*modeTotalBR[theDecayMode]/modeSumBR[theDecayMode]);
1163  }
1164  }
1165  } // decay file exists
1166 
1167  DecaySchemeFile.close();
1168 
1169  if (!found && levelEnergy > 0) {
1170  // Case where IT cascade for excited isotopes has no entries in RDM database
1171  // Decay mode is isomeric transition.
1172  G4ITDecay* anITChannel = new G4ITDecay(&theParentNucleus, 1.0, 0.0, 0.0,
1174  anITChannel->SetHLThreshold(halflifethreshold);
1175  anITChannel->SetARM(applyARM);
1176  theDecayTable->Insert(anITChannel);
1177  }
1178 
1179  if (theDecayTable && GetVerboseLevel() > 1) {
1180  theDecayTable->DumpInfo();
1181  }
1182 
1183 #ifdef G4MULTITHREADED
1184  //(*master_dkmap)[key] = theDecayTable; // store in master library
1185 #endif
1186  return theDecayTable;
1187 }
1188 
1189 void
1191 {
1192  if (Z < 1 || A < 2) G4cout << "Z and A not valid!" << G4endl;
1193 
1194  std::ifstream DecaySchemeFile(filename);
1195  if (DecaySchemeFile) {
1196  G4int ID_ion = A*1000 + Z;
1198  } else {
1199  G4cout << "The file " << filename << " does not exist!" << G4endl;
1200  }
1201 }
1202 
1203 
1204 void
1206  G4int theG, std::vector<G4double> theCoefficients,
1207  std::vector<G4double> theTaos)
1208 // Why not make this a method of G4RadioactiveDecayRate? (e.g. SetParameters)
1209 {
1210  //fill the decay rate vector
1211  ratesToDaughter.SetZ(theZ);
1212  ratesToDaughter.SetA(theA);
1213  ratesToDaughter.SetE(theE);
1215  ratesToDaughter.SetDecayRateC(theCoefficients);
1216  ratesToDaughter.SetTaos(theTaos);
1217 }
1218 
1219 
1222 {
1223  // Use extended Bateman equation to calculate the radioactivities of all
1224  // progeny of theParentNucleus. The coefficients required to do this are
1225  // calculated using the method of P. Truscott (Ph.D. thesis and
1226  // DERA Technical Note DERA/CIS/CIS2/7/36/4/10) 11 January 2000.
1227  // Coefficients are then added to the decay rate table vector
1228 
1229  // Create and initialise variables used in the method.
1230  theDecayRateVector.clear();
1231 
1232  G4int nGeneration = 0;
1233 
1234  std::vector<G4double> taos;
1235 
1236  // Dimensionless A coefficients of Eqs. 4.24 and 4.25 of the TN
1237  std::vector<G4double> Acoeffs;
1238 
1239  // According to Eq. 4.26 the first coefficient (A_1:1) is -1
1240  Acoeffs.push_back(-1.);
1241 
1242  G4int A = ((const G4Ions*)(&theParentNucleus))->GetAtomicMass();
1243  G4int Z = ((const G4Ions*)(&theParentNucleus))->GetAtomicNumber();
1244  G4double E = ((const G4Ions*)(&theParentNucleus))->GetExcitationEnergy();
1245  G4double tao = theParentNucleus.GetPDGLifeTime();
1246  if (tao < 0.) tao = 1e-100;
1247  taos.push_back(tao);
1248  G4int nEntry = 0;
1249 
1250  // Fill the decay rate container (G4RadioactiveDecayRatesToDaughter) with
1251  // the parent isotope data
1252  SetDecayRate(Z,A,E,nGeneration,Acoeffs,taos);
1253 
1254  // store the decay rate in decay rate vector
1256  nEntry++;
1257 
1258  // Now start treating the secondary generations.
1259  G4bool stable = false;
1260  G4int i;
1261  G4int j;
1262  G4VDecayChannel* theChannel = 0;
1263  G4NuclearDecay* theNuclearDecayChannel = 0;
1264 
1265  G4ITDecay* theITChannel = 0;
1266  G4BetaMinusDecay* theBetaMinusChannel = 0;
1267  G4BetaPlusDecay* theBetaPlusChannel = 0;
1268  G4AlphaDecay* theAlphaChannel = 0;
1269  G4ProtonDecay* theProtonChannel = 0;
1270  G4TritonDecay* theTritonChannel = 0;
1271  G4NeutronDecay* theNeutronChannel = 0;
1272  G4SFDecay* theFissionChannel = 0;
1273 
1274  G4RadioactiveDecayMode theDecayMode;
1275  G4double theBR = 0.0;
1276  G4int AP = 0;
1277  G4int ZP = 0;
1278  G4int AD = 0;
1279  G4int ZD = 0;
1280  G4double EP = 0.;
1281  std::vector<G4double> TP;
1282  std::vector<G4double> RP; // A coefficients of the previous generation
1283  G4ParticleDefinition *theDaughterNucleus;
1284  G4double daughterExcitation;
1285  G4double nearestEnergy = 0.0;
1286  G4int nearestLevelIndex = 0;
1287  G4ParticleDefinition *aParentNucleus;
1288  G4IonTable* theIonTable;
1289  G4DecayTable* parentDecayTable;
1290  G4double theRate;
1291  G4double TaoPlus;
1292  G4int nS = 0; // Running index of first decay in a given generation
1293  G4int nT = nEntry; // Total number of decays accumulated over entire history
1294  const G4int nMode = 12;
1295  G4double brs[nMode];
1296 
1297  //
1298  theIonTable =
1300 
1301  G4int loop = 0;
1302 
1303  while (!stable) { /* Loop checking, 01.09.2015, D.Wright */
1304  loop++;
1305  if (loop > 10000) {
1306  G4Exception("G4RadioactiveDecay::CalculateChainsFromParent()", "HAD_RDM_100",
1307  JustWarning, "While loop count exceeded");
1308  break;
1309  }
1310  nGeneration++;
1311  for (j = nS; j < nT; j++) {
1312  // First time through, get data for parent nuclide
1313  ZP = theDecayRateVector[j].GetZ();
1314  AP = theDecayRateVector[j].GetA();
1315  EP = theDecayRateVector[j].GetE();
1316  RP = theDecayRateVector[j].GetDecayRateC();
1317  TP = theDecayRateVector[j].GetTaos();
1318  if (GetVerboseLevel() > 1) {
1319  G4cout << "G4RadioactiveDecay::CalculateChainsFromParent: daughters of ("
1320  << ZP << ", " << AP << ", " << EP
1321  << ") are being calculated, generation = " << nGeneration
1322  << G4endl;
1323  }
1324 // G4cout << " Taus = " << G4endl;
1325 // for (G4int ii = 0; ii < TP.size(); ii++) G4cout << TP[ii] << ", " ;
1326 // G4cout << G4endl;
1327 
1328  aParentNucleus = theIonTable->GetIon(ZP,AP,EP);
1329  parentDecayTable = GetDecayTable(aParentNucleus);
1330 
1331  G4DecayTable* summedDecayTable = new G4DecayTable();
1332  // This instance of G4DecayTable is for accumulating BRs and decay
1333  // channels. It will contain one decay channel per type of decay
1334  // (alpha, beta, etc.); its branching ratio will be the sum of all
1335  // branching ratios for that type of decay of the parent. If the
1336  // halflife of a particular channel is longer than some threshold,
1337  // that channel will be inserted specifically and its branching
1338  // ratio will not be included in the above sums.
1339  // This instance is not used to perform actual decays.
1340 
1341  for (G4int k = 0; k < nMode; k++) brs[k] = 0.0;
1342 
1343  // Go through the decay table and sum all channels having the same decay mode
1344  for (i = 0; i < parentDecayTable->entries(); i++) {
1345  theChannel = parentDecayTable->GetDecayChannel(i);
1346  theNuclearDecayChannel = static_cast<G4NuclearDecay*>(theChannel);
1347  theDecayMode = theNuclearDecayChannel->GetDecayMode();
1348  daughterExcitation = theNuclearDecayChannel->GetDaughterExcitation();
1349  theDaughterNucleus = theNuclearDecayChannel->GetDaughterNucleus() ;
1350 
1351  AD = ((const G4Ions*)(theDaughterNucleus))->GetAtomicMass();
1352  ZD = ((const G4Ions*)(theDaughterNucleus))->GetAtomicNumber();
1353  const G4LevelManager* levelManager =
1355 
1356  if (levelManager->NumberOfTransitions() ) {
1357  nearestEnergy = levelManager->NearestLevelEnergy(daughterExcitation);
1358  if (std::abs(daughterExcitation - nearestEnergy) < levelTolerance) {
1359  // Level half-life is in ns and the threshold is set to 1 micros
1360  // by default, user can set it via the UI command
1361  nearestLevelIndex = levelManager->NearestLevelIndex(daughterExcitation);
1362  if (levelManager->LifeTime(nearestLevelIndex)*ns >= halflifethreshold){
1363  // save the metastable nucleus
1364  summedDecayTable->Insert(theChannel);
1365  } else {
1366  brs[theDecayMode] += theChannel->GetBR();
1367  }
1368  } else {
1369  brs[theDecayMode] += theChannel->GetBR();
1370  }
1371  } else {
1372  brs[theDecayMode] += theChannel->GetBR();
1373  }
1374  } // Combine decay channels (loop i)
1375 
1376  brs[2] = brs[2]+brs[3]+brs[4]+brs[5]+brs[6]; // Combine beta+ and EC
1377  brs[3] = brs[4] = brs[5] = brs[6] = 0.0;
1378  for (i = 0; i < nMode; i++) { // loop over decay modes
1379  if (brs[i] > 0.) {
1380  switch (i) {
1381  case 0:
1382  // Decay mode is isomeric transition
1383  theITChannel = new G4ITDecay(aParentNucleus, brs[0], 0.0, 0.0,
1385 
1386  summedDecayTable->Insert(theITChannel);
1387  break;
1388 
1389  case 1:
1390  // Decay mode is beta-
1391  theBetaMinusChannel = new G4BetaMinusDecay(aParentNucleus, brs[1],
1392  0.*MeV, 0.*MeV,
1393  noFloat, allowed);
1394  summedDecayTable->Insert(theBetaMinusChannel);
1395  break;
1396 
1397  case 2:
1398  // Decay mode is beta+ + EC.
1399  theBetaPlusChannel = new G4BetaPlusDecay(aParentNucleus, brs[2], // DHW: April 2015
1400  0.*MeV, 0.*MeV,
1401  noFloat, allowed);
1402  summedDecayTable->Insert(theBetaPlusChannel);
1403  break;
1404 
1405  case 7:
1406  // Decay mode is alpha.
1407  theAlphaChannel = new G4AlphaDecay(aParentNucleus, brs[7], 0.*MeV,
1408  0.*MeV, noFloat);
1409  summedDecayTable->Insert(theAlphaChannel);
1410  break;
1411 
1412  case 8:
1413  // Decay mode is proton.
1414  theProtonChannel = new G4ProtonDecay(aParentNucleus, brs[8], 0.*MeV,
1415  0.*MeV, noFloat);
1416  summedDecayTable->Insert(theProtonChannel);
1417  break;
1418 
1419  case 9:
1420  // Decay mode is neutron.
1421  theNeutronChannel = new G4NeutronDecay(aParentNucleus, brs[9], 0.*MeV,
1422  0.*MeV, noFloat);
1423  summedDecayTable->Insert(theNeutronChannel);
1424  break;
1425 
1426  case 10:
1427  // Decay mode is spontaneous fission
1428  theFissionChannel = new G4SFDecay(aParentNucleus, brs[10], 0.*MeV,
1429  0.*MeV, noFloat);
1430  summedDecayTable->Insert(theFissionChannel);
1431  break;
1432  case 11:
1433  // Decay mode is triton.
1434  theTritonChannel = new G4TritonDecay(aParentNucleus, brs[11], 0.*MeV,
1435  0.*MeV, noFloat);
1436  summedDecayTable->Insert(theTritonChannel);
1437  break;
1438 
1439  default:
1440  break;
1441  }
1442  }
1443  }
1444  // loop over all branches in summedDecayTable
1445  //
1446  for (i = 0; i < summedDecayTable->entries(); i++){
1447  theChannel = summedDecayTable->GetDecayChannel(i);
1448  theNuclearDecayChannel = static_cast<G4NuclearDecay*>(theChannel);
1449  theBR = theChannel->GetBR();
1450  theDaughterNucleus = theNuclearDecayChannel->GetDaughterNucleus();
1451 
1452  // First check if the decay of the original nucleus is an IT channel,
1453  // if true create a new ground-state nucleus
1454  if (theNuclearDecayChannel->GetDecayMode() == IT && nGeneration == 1) {
1455 
1456  A = ((const G4Ions*)(theDaughterNucleus))->GetAtomicMass();
1457  Z = ((const G4Ions*)(theDaughterNucleus))->GetAtomicNumber();
1458  theDaughterNucleus=theIonTable->GetIon(Z,A,0.);
1459  }
1460  if (IsApplicable(*theDaughterNucleus) && theBR &&
1461  aParentNucleus != theDaughterNucleus) {
1462  // need to make sure daughter has decay table
1463  parentDecayTable = GetDecayTable(theDaughterNucleus);
1464 
1465  if (parentDecayTable->entries() ) {
1466  A = ((const G4Ions*)(theDaughterNucleus))->GetAtomicMass();
1467  Z = ((const G4Ions*)(theDaughterNucleus))->GetAtomicNumber();
1468  E = ((const G4Ions*)(theDaughterNucleus))->GetExcitationEnergy();
1469 
1470  TaoPlus = theDaughterNucleus->GetPDGLifeTime();
1471  if (TaoPlus <= 0.) TaoPlus = 1e-100;
1472 
1473  // first set the taos, one simply need to add to the parent ones
1474  taos.clear();
1475  taos = TP; // load lifetimes of all previous generations
1476  size_t k;
1477  //check that TaoPlus differs from other taos from at least 1.e5 relative difference
1478  //for (k = 0; k < TP.size(); k++){
1479  //if (std::abs((TaoPlus-TP[k])/TP[k])<1.e-5 ) TaoPlus=1.00001*TP[k];
1480  //}
1481  taos.push_back(TaoPlus); // add daughter lifetime to list
1482  // now calculate the coefficiencies
1483  //
1484  // they are in two parts, first the less than n ones
1485  // Eq 4.24 of the TN
1486  Acoeffs.clear();
1487  long double ta1,ta2;
1488  ta2 = (long double)TaoPlus;
1489  for (k = 0; k < RP.size(); k++){
1490  ta1 = (long double)TP[k]; // loop over lifetimes of all previous generations
1491  if (ta1 == ta2) {
1492  theRate = 1.e100;
1493  } else {
1494  theRate = ta1/(ta1-ta2);
1495  }
1496  theRate = theRate * theBR * RP[k];
1497  Acoeffs.push_back(theRate);
1498  }
1499 
1500  // the second part: the n:n coefficiency
1501  // Eq 4.25 of the TN. Note Yn+1 is zero apart from Y1 which is -1
1502  // as treated at line 1013
1503  theRate = 0.;
1504  long double aRate, aRate1;
1505  aRate1 = 0.L;
1506  for (k = 0; k < RP.size(); k++){
1507  ta1 = (long double)TP[k];
1508  if (ta1 == ta2 ) {
1509  aRate = 1.e100;
1510  } else {
1511  aRate = ta2/(ta1-ta2);
1512  }
1513  aRate = aRate * (long double)(theBR * RP[k]);
1514  aRate1 += aRate;
1515  }
1516  theRate = -aRate1;
1517  Acoeffs.push_back(theRate);
1518  SetDecayRate (Z,A,E,nGeneration,Acoeffs,taos);
1520  nEntry++;
1521  } // there are entries in the table
1522  } // nuclide is OK to decay
1523  } // end of loop (i) over decay table branches
1524 
1525  delete summedDecayTable;
1526 
1527  } // Getting contents of decay rate vector (end loop on j)
1528  nS = nT;
1529  nT = nEntry;
1530  if (nS == nT) stable = true;
1531  } // while nuclide is not stable
1532 
1533  // end of while loop
1534  // the calculation completed here
1535 
1536 
1537  // fill the first part of the decay rate table
1538  // which is the name of the original particle (isotope)
1539  chainsFromParent.SetIonName(theParentNucleus.GetParticleName());
1540 
1541  // now fill the decay table with the newly completed decay rate vector
1543 
1544  // finally add the decayratetable to the tablevector
1546 }
1547 
1549 // //
1550 // SetSourceTimeProfile //
1551 // read in the source time profile function (histogram) //
1552 // //
1554 
1556 {
1557  std::ifstream infile ( filename, std::ios::in );
1558  if (!infile) {
1560  ed << " Could not open file " << filename << G4endl;
1561  G4Exception("G4RadioactiveDecay::SetSourceTimeProfile()", "HAD_RDM_001",
1562  FatalException, ed);
1563  }
1564 
1565  G4double bin, flux;
1566  NSourceBin = -1;
1567 
1568  G4int loop = 0;
1569  while (infile >> bin >> flux) { /* Loop checking, 01.09.2015, D.Wright */
1570  loop++;
1571  if (loop > 10000) {
1572  G4Exception("G4RadioactiveDecay::SetSourceTimeProfile()", "HAD_RDM_100",
1573  JustWarning, "While loop count exceeded");
1574  break;
1575  }
1576 
1577  NSourceBin++;
1578  if (NSourceBin > 99) {
1579  G4Exception("G4RadioactiveDecay::SetSourceTimeProfile()", "HAD_RDM_002",
1580  FatalException, "Input source time file too big (>100 rows)");
1581 
1582  } else {
1583  SBin[NSourceBin] = bin * s;
1584  SProfile[NSourceBin] = flux;
1585  }
1586  }
1588  infile.close();
1589 
1590 #ifdef G4VERBOSE
1591  if (GetVerboseLevel() > 1)
1592  G4cout <<" Source Timeprofile Nbin = " << NSourceBin <<G4endl;
1593 #endif
1594 }
1595 
1597 // //
1598 // SetDecayBiasProfile //
1599 // read in the decay bias scheme function (histogram) //
1600 // //
1602 
1604 {
1605 
1606  std::ifstream infile(filename, std::ios::in);
1607  if (!infile) G4Exception("G4RadioactiveDecay::SetDecayBias()", "HAD_RDM_003",
1608  FatalException, "Unable to open bias data file" );
1609 
1610  G4double bin, flux;
1611  G4int dWindows = 0;
1612  G4int i ;
1613 
1614  theRadioactivityTables.clear();
1615 
1616  NDecayBin = -1;
1617 
1618  G4int loop = 0;
1619  while (infile >> bin >> flux ) { /* Loop checking, 01.09.2015, D.Wright */
1620  NDecayBin++;
1621  loop++;
1622  if (loop > 10000) {
1623  G4Exception("G4RadioactiveDecay::SetDecayBias()", "HAD_RDM_100",
1624  JustWarning, "While loop count exceeded");
1625  break;
1626  }
1627 
1628  if (NDecayBin > 99) {
1629  G4Exception("G4RadioactiveDecay::SetDecayBias()", "HAD_RDM_004",
1630  FatalException, "Input bias file too big (>100 rows)" );
1631  } else {
1632  DBin[NDecayBin] = bin * s;
1633  DProfile[NDecayBin] = flux;
1634  if (flux > 0.) {
1635  decayWindows[NDecayBin] = dWindows;
1636  dWindows++;
1637  G4RadioactivityTable *rTable = new G4RadioactivityTable() ;
1638  theRadioactivityTables.push_back(rTable);
1639  }
1640  }
1641  }
1642  for ( i = 1; i<= NDecayBin; i++) DProfile[i] += DProfile[i-1];
1643  for ( i = 0; i<= NDecayBin; i++) DProfile[i] /= DProfile[NDecayBin];
1644  // converted to accumulated probabilities
1645 
1647  infile.close();
1648 
1649 #ifdef G4VERBOSE
1650  if (GetVerboseLevel() > 1)
1651  G4cout <<" Decay Bias Profile Nbin = " << NDecayBin <<G4endl;
1652 #endif
1653 }
1654 
1656 // //
1657 // DecayIt //
1658 // //
1660 
1663 {
1664  // Initialize G4ParticleChange object, get particle details and decay table
1665 
1668  const G4DynamicParticle* theParticle = theTrack.GetDynamicParticle();
1669  const G4ParticleDefinition* theParticleDef = theParticle->GetDefinition();
1670 
1671  // First check whether RDM applies to the current logical volume
1672  if (!isAllVolumesMode) {
1673  if (!std::binary_search(ValidVolumes.begin(), ValidVolumes.end(),
1674  theTrack.GetVolume()->GetLogicalVolume()->GetName())) {
1675 #ifdef G4VERBOSE
1676  if (GetVerboseLevel()>1) {
1677  G4cout <<"G4RadioactiveDecay::DecayIt : "
1678  << theTrack.GetVolume()->GetLogicalVolume()->GetName()
1679  << " is not selected for the RDM"<< G4endl;
1680  G4cout << " There are " << ValidVolumes.size() << " volumes" << G4endl;
1681  G4cout << " The Valid volumes are " << G4endl;
1682  for (size_t i = 0; i< ValidVolumes.size(); i++)
1683  G4cout << ValidVolumes[i] << G4endl;
1684  }
1685 #endif
1687 
1688  // Kill the parent particle.
1693  }
1694  }
1695 
1696  // Now check if particle is valid for RDM
1697  if (!(IsApplicable(*theParticleDef) ) ) {
1698  // Particle is not an ion or is outside the nucleuslimits for decay
1699 #ifdef G4VERBOSE
1700  if (GetVerboseLevel() > 1) {
1701  G4cout << " G4RadioactiveDecay::DecayIt : "
1702  << theParticleDef->GetParticleName()
1703  << " is not a valid nucleus for the RDM. "<< G4endl;
1704  G4cout << " Set particle change accordingly. " << G4endl;
1705  }
1706 #endif
1708 
1709  // Kill the parent particle
1714  }
1715  G4DecayTable* theDecayTable = GetDecayTable(theParticleDef);
1716 
1717  if (theDecayTable == 0 || theDecayTable->entries() == 0) {
1718  // No data in the decay table. Set particle change parameters
1719  // to indicate this.
1720 #ifdef G4VERBOSE
1721  if (GetVerboseLevel() > 1) {
1722  G4cout <<" G4RadioactiveDecay::DecayIt : decay table not defined for ";
1723  G4cout << theParticleDef->GetParticleName() << G4endl;
1724  G4cout << " Set particle change to indicate this. " << G4endl;
1725  }
1726 #endif
1728 
1729  // Kill the parent particle.
1734 
1735  } else {
1736  // Data found. Try to decay nucleus
1737  G4double energyDeposit = 0.0;
1738  G4double finalGlobalTime = theTrack.GetGlobalTime();
1739  G4double finalLocalTime = theTrack.GetLocalTime();
1740  G4int index;
1741  G4ThreeVector currentPosition;
1742  currentPosition = theTrack.GetPosition();
1743 
1744  // Check whether use Analogue or VR implementation
1745  if (AnalogueMC) {
1746 #ifdef G4VERBOSE
1747  if (GetVerboseLevel() > 1)
1748  G4cout <<"DecayIt: Analogue MC version " << G4endl;
1749 # endif
1750 
1751  G4DecayProducts* products = DoDecay(*theParticleDef);
1752 
1753  // Check if the product is the same as input and kill the track if
1754  // necessary to prevent infinite loop (11/05/10, F.Lei)
1755  if ( products->entries() == 1) {
1761  }
1762 
1763  // Get parent particle information and boost the decay products to the
1764  // laboratory frame based on this information.
1765 
1766  //The Parent Energy used for the boost should be the total energy of
1767  // the nucleus of the parent ion without the energy of the shell electrons
1768  // (correction for bug 1359 by L. Desorgher)
1769  G4double ParentEnergy = theParticle->GetKineticEnergy()
1770  + theParticle->GetParticleDefinition()->GetPDGMass();
1771  G4ThreeVector ParentDirection(theParticle->GetMomentumDirection());
1772 
1773  if (theTrack.GetTrackStatus() == fStopButAlive) {
1774  //this condition seems to be always True, further investigation is needed (L.Desorgher)
1775 
1776  // The particle is decayed at rest.
1777  // since the time is still for rest particle in G4 we need to add the
1778  // additional time lapsed between the particle come to rest and the
1779  // actual decay. This time is simply sampled with the mean-life of
1780  // the particle. But we need to protect the case PDGTime < 0.
1781  // (F.Lei 11/05/10)
1782  G4double temptime = -std::log( G4UniformRand())
1783  *theParticleDef->GetPDGLifeTime();
1784  if (temptime < 0.) temptime = 0.;
1785  finalGlobalTime += temptime;
1786  finalLocalTime += temptime;
1787  energyDeposit += theParticle->GetKineticEnergy();
1788  }
1789  products->Boost(ParentEnergy, ParentDirection);
1790 
1791  // Add products in theParticleChangeForRadDecay.
1792  G4int numberOfSecondaries = products->entries();
1794 #ifdef G4VERBOSE
1795  if (GetVerboseLevel()>1) {
1796  G4cout <<"G4RadioactiveDecay::DecayIt : Decay vertex :";
1797  G4cout <<" Time: " <<finalGlobalTime/ns <<"[ns]";
1798  G4cout <<" X:" <<(theTrack.GetPosition()).x() /cm <<"[cm]";
1799  G4cout <<" Y:" <<(theTrack.GetPosition()).y() /cm <<"[cm]";
1800  G4cout <<" Z:" <<(theTrack.GetPosition()).z() /cm <<"[cm]";
1801  G4cout << G4endl;
1802  G4cout <<"G4Decay::DecayIt : decay products in Lab. Frame" <<G4endl;
1803  products->DumpInfo();
1804  products->IsChecked();
1805  }
1806 #endif
1807  for (index=0; index < numberOfSecondaries; index++) {
1808  G4Track* secondary = new G4Track(products->PopProducts(),
1809  finalGlobalTime, currentPosition);
1810 
1812  //Change for atomics relaxation
1813  if (theRadDecayMode == IT && index>0){
1814  if (index == numberOfSecondaries-1) secondary->SetCreatorModelIndex(IT);
1815  else secondary->SetCreatorModelIndex(30);
1816  }
1818  && index <numberOfSecondaries-1){
1819  secondary->SetCreatorModelIndex(30);
1820  }
1821  secondary->SetGoodForTrackingFlag();
1822  secondary->SetTouchableHandle(theTrack.GetTouchableHandle());
1824  }
1825  delete products;
1826  // end of analogue MC algorithm
1827 
1828  } else {
1829  // Variance Reduction Method
1830 #ifdef G4VERBOSE
1831  if (GetVerboseLevel()>0)
1832  G4cout << "DecayIt: Variance Reduction version " << G4endl;
1833 #endif
1834  // Get decay chains for the given nuclide
1835  if (!IsRateTableReady(*theParticleDef)) CalculateChainsFromParent(*theParticleDef);
1836  GetChainsFromParent(*theParticleDef);
1837 
1838  // declare some of the variables required in the implementation
1839  G4ParticleDefinition* parentNucleus;
1840  G4IonTable* theIonTable;
1841  G4int PZ;
1842  G4int PA;
1843  G4double PE;
1844  G4String keyName;
1845  std::vector<G4double> PT;
1846  std::vector<G4double> PR;
1847  G4double tauprob;
1848  long double decayRate;
1849 
1850  size_t i;
1851 // size_t j;
1852  G4int numberOfSecondaries;
1853  G4int totalNumberOfSecondaries = 0;
1854  G4double currentTime = 0.;
1855  G4int ndecaych;
1856  G4DynamicParticle* asecondaryparticle;
1857  std::vector<G4DynamicParticle*> secondaryparticles;
1858  std::vector<G4double> pw;
1859  std::vector<G4double> ptime;
1860  pw.clear();
1861  ptime.clear();
1862 
1863  //now apply the nucleus splitting
1864  for (G4int n = 0; n < NSplit; n++) {
1865  // Get the decay time following the decay probability function
1866  // suppllied by user
1867  G4double theDecayTime = GetDecayTime();
1868  G4int nbin = GetDecayTimeBin(theDecayTime);
1869 
1870  // calculate the first part of the weight function
1871  G4double weight1 = 1.;
1872  if (nbin == 1) {
1873  weight1 = 1./DProfile[nbin-1]
1874  *(DBin[nbin]-DBin[nbin-1])/NSplit;
1875  } else if (nbin > 1) {
1876  weight1 = 1./(DProfile[nbin]-DProfile[nbin-2])
1877  *(DBin[nbin]-DBin[nbin-1])/NSplit;
1878  }
1879 
1880  // it should be calculated in seconds
1881  weight1 /= s ;
1882 
1883  // Loop over all the possible secondaries of the nucleus
1884  // the first one is itself.
1885  for (i = 0; i < theDecayRateVector.size(); i++) {
1886  PZ = theDecayRateVector[i].GetZ();
1887  PA = theDecayRateVector[i].GetA();
1888  PE = theDecayRateVector[i].GetE();
1889  PT = theDecayRateVector[i].GetTaos();
1890  PR = theDecayRateVector[i].GetDecayRateC();
1891 
1892  // The array of arrays theDecayRateVector contains all possible decay
1893  // chains of a given parent nucleus (ZP,AP,EP) to a given descendant
1894  // nuclide (Z,A,E).
1895  //
1896  // theDecayRateVector[0] contains the decay parameters of the parent
1897  // nucleus
1898  // PZ = ZP
1899  // PA = AP
1900  // PE = EP
1901  // PT[] = {TP}
1902  // PR[] = {RP}
1903  //
1904  // theDecayRateVector[1] contains the decay of the parent to the first
1905  // generation daughter (Z1,A1,E1).
1906  // PZ = Z1
1907  // PA = A1
1908  // PE = E1
1909  // PT[] = {TP, T1}
1910  // PR[] = {RP, R1}
1911  //
1912  // theDecayRateVector[2] contains the decay of the parent to the first
1913  // generation daughter (Z1,A1,E1) and the decay of the first
1914  // generation daughter to the second generation daughter (Z2,A2,E2).
1915  // PZ = Z2
1916  // PA = A2
1917  // PE = E2
1918  // PT[] = {TP, T1, T2}
1919  // PR[] = {RP, R1, R2}
1920  //
1921  // theDecayRateVector[3] may contain a branch chain
1922  // PZ = Z2a
1923  // PA = A2a
1924  // PE = E2a
1925  // PT[] = {TP, T1, T2a}
1926  // PR[] = {RP, R1, R2a}
1927  //
1928  // and so on.
1929 
1930  // Calculate the decay rate of the isotope. decayRate is the
1931  // radioactivity of isotope (PZ,PA,PE) at 'theDecayTime'.
1932  // It will be used to calculate the statistical weight of the
1933  // decay products of this isotope
1934 
1935  // For each nuclide, calculate all the decay chains which can reach
1936  // the parent nuclide
1937  decayRate = 0.L;
1938  for (G4int j = 0; j < G4int(PT.size()); j++) {
1939  tauprob = ConvolveSourceTimeProfile(theDecayTime,PT[j]);
1940  // tauprob is dimensionless, PR has units of s-1
1941  decayRate -= PR[j] * (long double)tauprob;
1942  // Eq.4.23 of of the TN
1943  // note the negative here is required as the rate in the
1944  // equation is defined to be negative,
1945  // i.e. decay away, but we need positive value here.
1946 
1947  // G4cout << j << "\t" << PT[j]/s << "\t" << PR[j] << "\t" << decayRate << G4endl;
1948  }
1949 
1950  // At this point any negative decay rates are probably small enough
1951  // (order 10**-30) that negative values are likely due to cancellation
1952  // errors. Set them to zero.
1953  if (decayRate < 0.0) decayRate = 0.0;
1954 /*
1955  if (decayRate < 0.0) {
1956  if (-decayRate > 1.0e-30) {
1957  G4ExceptionDescription ed;
1958  ed << " Negative decay probability (magnitude > 1e-30) \n"
1959  << " in variance reduction branch " << G4endl;
1960  G4Exception("G4RadioactiveDecay::DecayIt()",
1961  "HAD_RDM_200", JustWarning, ed);
1962  } else {
1963  // Decay probability is small enough that negative value is likely
1964  // due to cancellation errors. Set it to zero.
1965  decayRate = 0.0;
1966  }
1967  }
1968 
1969  if (decayRate < 0.0) G4cout << " NEGATIVE decay rate = " << decayRate << G4endl;
1970 */
1971  // G4cout << theDecayTime/s << "\t" << nbin << G4endl;
1972  // G4cout << theTrack.GetWeight() << "\t" << weight1 << "\t" << decayRate << G4endl;
1973 
1974  // Add isotope to the radioactivity tables
1975  // One table for each observation time window specifed in
1976  // SetDecayBias(G4String filename)
1978  ->AddIsotope(PZ,PA,PE,weight1*decayRate,theTrack.GetWeight());
1979 
1980  // Now calculate the statistical weight
1981  // One needs to fold the source bias function with the decaytime
1982  // also need to include the track weight! (F.Lei, 28/10/10)
1983  G4double weight = weight1*decayRate*theTrack.GetWeight();
1984 
1985  // Decay the isotope
1987  parentNucleus = theIonTable->GetIon(PZ,PA,PE);
1988 
1989  // Create a temprary products buffer.
1990  // Its contents to be transfered to the products at the end of the loop
1991  G4DecayProducts* tempprods = 0;
1992 
1993  // Decide whether to apply branching ratio bias or not
1994  if (BRBias) {
1995  G4DecayTable* decayTable = GetDecayTable(parentNucleus);
1996 
1997  ndecaych = G4int(decayTable->entries()*G4UniformRand());
1998  G4VDecayChannel* theDecayChannel = decayTable->GetDecayChannel(ndecaych);
1999  if (theDecayChannel == 0) {
2000  // Decay channel not found.
2001 #ifdef G4VERBOSE
2002  if (GetVerboseLevel() > 0) {
2003  G4cout << " G4RadioactiveDecay::DoIt : cannot determine decay ";
2004  G4cout << " channel for this nucleus; decay as if no biasing active ";
2005  G4cout << G4endl;
2006  decayTable ->DumpInfo();
2007  }
2008 #endif
2009  tempprods = DoDecay(*parentNucleus); // DHW 6 Dec 2010 - do decay as if no biasing
2010  // to avoid deref of temppprods = 0
2011  } else {
2012  // A decay channel has been identified, so execute the DecayIt.
2013  G4double tempmass = parentNucleus->GetPDGMass();
2014  tempprods = theDecayChannel->DecayIt(tempmass);
2015  weight *= (theDecayChannel->GetBR())*(decayTable->entries());
2016  }
2017  } else {
2018  tempprods = DoDecay(*parentNucleus);
2019  }
2020 
2021  // Save the secondaries for buffers
2022  numberOfSecondaries = tempprods->entries();
2023  currentTime = finalGlobalTime + theDecayTime;
2024  for (index = 0; index < numberOfSecondaries; index++) {
2025  asecondaryparticle = tempprods->PopProducts();
2026  if (asecondaryparticle->GetDefinition()->GetPDGStable() ) {
2027  pw.push_back(weight);
2028  ptime.push_back(currentTime);
2029  secondaryparticles.push_back(asecondaryparticle);
2030  } else if (((const G4Ions*)(asecondaryparticle->GetDefinition()))->GetExcitationEnergy() > 0.
2031  && weight > 0.) {
2032  // Compute the gamma
2033  // Generate gammas and XRays from excited nucleus, added by L.Desorgher
2034  G4ParticleDefinition* apartDef =asecondaryparticle->GetDefinition();
2035  AddDeexcitationSpectrumForBiasMode(apartDef,weight,currentTime,pw,ptime,secondaryparticles);
2036  }
2037  }
2038  delete tempprods;
2039 
2040  } // end of i loop
2041  } // end of n loop
2042 
2043  // now deal with the secondaries in the two stl containers
2044  // and submmit them back to the tracking manager
2045  totalNumberOfSecondaries = pw.size();
2046  fParticleChangeForRadDecay.SetNumberOfSecondaries(totalNumberOfSecondaries);
2047  for (index=0; index < totalNumberOfSecondaries; index++) {
2048  G4Track* secondary = new G4Track(secondaryparticles[index],
2049  ptime[index], currentPosition);
2050  secondary->SetGoodForTrackingFlag();
2051  secondary->SetTouchableHandle(theTrack.GetTouchableHandle());
2052  secondary->SetWeight(pw[index]);
2054  }
2055  // make sure the original track is set to stop and its kinematic energy collected
2056  //
2057  //theTrack.SetTrackStatus(fStopButAlive);
2058  //energyDeposit += theParticle->GetKineticEnergy();
2059 
2060  } // End of Variance Reduction
2061 
2062  // Kill the parent particle
2066  // Reset NumberOfInteractionLengthLeft.
2068 
2070  }
2071 }
2072 
2073 
2076 {
2077  G4DecayProducts* products = 0;
2078  G4DecayTable* theDecayTable = GetDecayTable(&theParticleDef);
2079 
2080  // Choose a decay channel.
2081  // G4DecayTable::SelectADecayChannel checks to see if sum of daughter masses
2082  // exceeds parent mass. Pass it the parent mass + maximum Q value to account
2083  // for difference in mass defect.
2084  G4double parentPlusQ = theParticleDef.GetPDGMass() + 30.*MeV;
2085  G4VDecayChannel* theDecayChannel = theDecayTable->SelectADecayChannel(parentPlusQ);
2086  if (theDecayChannel == 0) {
2087  // Decay channel not found.
2089  ed << " Cannot determine decay channel for " << theParticleDef.GetParticleName() << G4endl;
2090  G4Exception("G4RadioactiveDecay::DoDecay", "HAD_RDM_013",
2091  FatalException, ed);
2092  } else {
2093  // A decay channel has been identified, so execute the DecayIt.
2094 #ifdef G4VERBOSE
2095  if (GetVerboseLevel() > 1) {
2096  G4cout << "G4RadioactiveDecay::DoIt : selected decay channel address:";
2097  G4cout << theDecayChannel << G4endl;
2098  }
2099 #endif
2100  theRadDecayMode = (static_cast<G4NuclearDecay*>(theDecayChannel))->GetDecayMode();
2101  products = theDecayChannel->DecayIt(theParticleDef.GetPDGMass() );
2102 
2103  // Apply directional bias if requested by user
2104  CollimateDecay(products);
2105  }
2106 
2107  return products;
2108 }
2109 
2110 
2111 // Apply directional bias for "visible" daughters (e+-, gamma, n, p, alpha)
2112 
2114  if (origin == forceDecayDirection) return; // No collimation requested
2115  if (180.*deg == forceDecayHalfAngle) return;
2116  if (0 == products || 0 == products->entries()) return;
2117 
2118 #ifdef G4VERBOSE
2119  if (GetVerboseLevel() > 1) G4cout << "Begin decay collimation " << G4endl;
2120 #endif
2121 
2122  // Particles suitable for directional biasing (for if-blocks below)
2126  static const G4ParticleDefinition* gamma = G4Gamma::Definition();
2130 
2131  G4ThreeVector newDirection; // Re-use to avoid memory churn
2132  for (G4int i=0; i<products->entries(); i++) {
2133  G4DynamicParticle* daughter = (*products)[i];
2134  const G4ParticleDefinition* daughterType =
2135  daughter->GetParticleDefinition();
2136  if (daughterType == electron || daughterType == positron ||
2137  daughterType == neutron || daughterType == gamma ||
2138  daughterType == alpha || daughterType == triton || daughterType == proton) CollimateDecayProduct(daughter);
2139  }
2140 }
2141 
2143 #ifdef G4VERBOSE
2144  if (GetVerboseLevel() > 1) {
2145  G4cout << "CollimateDecayProduct for daughter "
2146  << daughter->GetParticleDefinition()->GetParticleName() << G4endl;
2147  }
2148 #endif
2149 
2151  if (origin != collimate) daughter->SetMomentumDirection(collimate);
2152 }
2153 
2154 
2155 // Choose random direction within collimation cone
2156 
2158  if (origin == forceDecayDirection) return origin; // Don't do collimation
2159  if (forceDecayHalfAngle == 180.*deg) return origin;
2160 
2162 
2163  // Return direction offset by random throw
2164  if (forceDecayHalfAngle > 0.) {
2165  // Generate uniform direction around central axis
2166  G4double phi = 2.*pi*G4UniformRand();
2167  G4double cosMin = std::cos(forceDecayHalfAngle);
2168  G4double cosTheta = (1.-cosMin)*G4UniformRand() + cosMin; // [cosMin,1.)
2169 
2170  dir.setPhi(dir.phi()+phi);
2171  dir.setTheta(dir.theta()+std::acos(cosTheta));
2172  }
2173 
2174 #ifdef G4VERBOSE
2175  if (GetVerboseLevel()>1)
2176  G4cout << " ChooseCollimationDirection returns " << dir << G4endl;
2177 #endif
2178 
2179  return dir;
2180 }
2181 
2182 // Add gamma, X-ray, conversion and auger electrons for bias mode
2183 void
2185  G4double weight,G4double currentTime,
2186  std::vector<double>& weights_v,
2187  std::vector<double>& times_v,
2188  std::vector<G4DynamicParticle*>& secondaries_v)
2189 {
2190  G4double elevel = ((const G4Ions*)(apartDef))->GetExcitationEnergy();
2191  G4double life_time = apartDef->GetPDGLifeTime();
2192  G4ITDecay* anITChannel = 0;
2193 
2194  while (life_time < halflifethreshold && elevel > 0.) {
2195  anITChannel = new G4ITDecay(apartDef, 100., elevel, elevel, photonEvaporation);
2196  G4DecayProducts* pevap_products = anITChannel->DecayIt(0.);
2197  G4int nb_pevapSecondaries = pevap_products->entries();
2198 
2199  G4DynamicParticle* a_pevap_secondary = 0;
2200  G4ParticleDefinition* secDef = 0;
2201  for (G4int ind = 0; ind < nb_pevapSecondaries; ind++) {
2202  a_pevap_secondary = pevap_products->PopProducts();
2203  secDef = a_pevap_secondary->GetDefinition();
2204 
2205  if (secDef->GetBaryonNumber() > 4) {
2206  elevel = ((const G4Ions*)(secDef))->GetExcitationEnergy();
2207  life_time = secDef->GetPDGLifeTime();
2208  apartDef = secDef;
2209  if (secDef->GetPDGStable() ) {
2210  weights_v.push_back(weight);
2211  times_v.push_back(currentTime);
2212  secondaries_v.push_back(a_pevap_secondary);
2213  }
2214  } else {
2215  weights_v.push_back(weight);
2216  times_v.push_back(currentTime);
2217  secondaries_v.push_back(a_pevap_secondary);
2218  }
2219  }
2220 
2221  delete anITChannel;
2222  }
2223 }
2224 
2225