source: trunk/source/processes/hadronic/models/radioactive_decay/src/G4RadioactiveDecay.cc @ 1334

Last change on this file since 1334 was 1315, checked in by garnier, 14 years ago

update geant4-09-04-beta-cand-01 interfaces-V09-03-09 vis-V09-03-08

File size: 53.4 KB
Line 
1//
2// ********************************************************************
3// * License and Disclaimer                                           *
4// *                                                                  *
5// * The  Geant4 software  is  copyright of the Copyright Holders  of *
6// * the Geant4 Collaboration.  It is provided  under  the terms  and *
7// * conditions of the Geant4 Software License,  included in the file *
8// * LICENSE and available at  http://cern.ch/geant4/license .  These *
9// * include a list of copyright holders.                             *
10// *                                                                  *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work  make  any representation or  warranty, express or implied, *
14// * regarding  this  software system or assume any liability for its *
15// * use.  Please see the license in the file  LICENSE  and URL above *
16// * for the full disclaimer and the limitation of liability.         *
17// *                                                                  *
18// * This  code  implementation is the result of  the  scientific and *
19// * technical work of the GEANT4 collaboration.                      *
20// * By using,  copying,  modifying or  distributing the software (or *
21// * any work based  on the software)  you  agree  to acknowledge its *
22// * use  in  resulting  scientific  publications,  and indicate your *
23// * acceptance of all terms of the Geant4 Software license.          *
24// ********************************************************************
25//
26// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
27//
28// MODULE:              G4RadioactiveDecay.cc
29//
30// Author:              F Lei & P R Truscott
31// Organisation:        DERA UK
32// Customer:            ESA/ESTEC, NOORDWIJK
33// Contract:            12115/96/JG/NL Work Order No. 3
34//
35// Documentation avaialable at http://www.space.dera.gov.uk/space_env/rdm.html
36//   These include:
37//       User Requirement Document (URD)
38//       Software Specification Documents (SSD)
39//       Software User Manual (SUM)
40//       Technical Note (TN) on the physics and algorithms
41//
42//    The test and example programs are not included in the public release of
43//    G4 but they can be downloaded from
44//      http://www.space.qinetiq.com/space_env/rdm.html
45//
46// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
47//
48// CHANGE HISTORY
49// --------------
50// 16 February 2006, V.Ivanchenko fix problem in IsApplicable connected with
51//            8.0 particle design
52// 18 October 2002, F. Lei
53//            in the case of beta decay, added a check of the end-energy
54//            to ensure it is > 0.
55//            ENSDF occationally have beta decay entries with zero energies
56//
57// 27 Sepetember 2001, F. Lei
58//            verboselevel(0) used in constructor
59//
60// 01 November 2000, F.Lei
61//            added " ee = e0 +1. ;" as line 763
62//            tagged as "radiative_decay-V02-00-02"             
63// 28 October 2000, F Lei
64//            added fast beta decay mode. Many files have been changed.
65//            tagged as "radiative_decay-V02-00-01"
66//
67// 25 October 2000, F Lei, DERA UK
68//            1) line 1185 added 'const' to work with tag "Track-V02-00-00"
69//            tagged as "radiative_decay-V02-00-00"
70// 14 April 2000, F Lei, DERA UK
71// 0.b.4 release. Changes are:
72//            1) Use PhotonEvaporation instead of DiscreteGammaDeexcitation
73//            2) VR: Significant efficiency improvement
74//
75// 29 February 2000, P R Truscott, DERA UK
76// 0.b.3 release.
77//
78// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
79///////////////////////////////////////////////////////////////////////////////
80//
81#include "G4RadioactiveDecay.hh"
82#include "G4RadioactiveDecaymessenger.hh"
83
84#include "G4DynamicParticle.hh"
85#include "G4DecayProducts.hh"
86#include "G4DecayTable.hh"
87#include "G4PhysicsLogVector.hh"
88#include "G4ParticleChangeForRadDecay.hh"
89#include "G4ITDecayChannel.hh"
90#include "G4BetaMinusDecayChannel.hh"
91#include "G4BetaPlusDecayChannel.hh"
92#include "G4KshellECDecayChannel.hh"
93#include "G4LshellECDecayChannel.hh"
94#include "G4MshellECDecayChannel.hh"
95#include "G4AlphaDecayChannel.hh"
96#include "G4VDecayChannel.hh"
97#include "G4RadioactiveDecayMode.hh"
98#include "G4Ions.hh"
99#include "G4IonTable.hh"
100#include "G4RIsotopeTable.hh"
101#include "G4BetaFermiFunction.hh"
102#include "Randomize.hh"
103#include "G4LogicalVolumeStore.hh"
104#include "G4NuclearLevelManager.hh"
105#include "G4NuclearLevelStore.hh"
106
107#include "G4HadTmpUtil.hh"
108
109#include <vector>
110#include <sstream>
111#include <algorithm>
112#include <fstream>
113
114using namespace CLHEP;
115
116const G4double   G4RadioactiveDecay::levelTolerance =2.0*keV;
117
118///////////////////////////////////////////////////////////////////////////////
119//
120//
121// Constructor
122//
123G4RadioactiveDecay::G4RadioactiveDecay
124  (const G4String& processName)
125  :G4VRestDiscreteProcess(processName, fDecay), HighestBinValue(10.0),
126   LowestBinValue(1.0e-3), TotBin(200), verboseLevel(0)
127{
128#ifdef G4VERBOSE
129  if (GetVerboseLevel()>1) {
130    G4cout <<"G4RadioactiveDecay constructor    Name: ";
131    G4cout <<processName << G4endl;   }
132#endif
133
134  theRadioactiveDecaymessenger = new G4RadioactiveDecaymessenger(this);
135  theIsotopeTable              = new G4RIsotopeTable();
136  aPhysicsTable                = 0;
137  pParticleChange              = &fParticleChangeForRadDecay;
138 
139  //
140  // Now register the Isotopetable with G4IonTable.
141  //
142  G4IonTable *theIonTable =
143    (G4IonTable *)(G4ParticleTable::GetParticleTable()->GetIonTable());
144  G4VIsotopeTable *aVirtualTable = theIsotopeTable;
145  theIonTable->RegisterIsotopeTable(aVirtualTable);
146  //
147  //
148  // Reset the contents of the list of nuclei for which decay scheme data
149  // have been loaded.
150  //
151  LoadedNuclei.clear();
152  //
153  //
154  // Apply default values.
155  //
156  NSourceBin  = 1;
157  SBin[0]     = 0.* s;
158  SBin[1]     = 1e10 * s;
159  SProfile[0] = 1.;
160  SProfile[1] = 1.;
161  NDecayBin   = 1;
162  DBin[0]     = 9.9e9 * s ;
163  DBin[1]     = 1e10 * s;
164  DProfile[0] = 1.;
165  DProfile[1] = 0.;
166  NSplit      = 1;
167  AnalogueMC  = true ;
168  FBeta       = false ;
169  BRBias      = true ;
170  applyICM    = true ;
171  applyARM    = true ;
172  halflifethreshold = 1e-6*second;
173  //
174  // RDM applies to xall logical volumes as default
175  SelectAllVolumes();
176}
177////////////////////////////////////////////////////////////////////////////////
178//
179//
180// Destructor
181//
182G4RadioactiveDecay::~G4RadioactiveDecay()
183{
184  if (aPhysicsTable != 0)
185    {
186      aPhysicsTable->clearAndDestroy();
187      delete aPhysicsTable;
188    }
189  //  delete theIsotopeTable;
190  delete theRadioactiveDecaymessenger;
191}
192
193///////////////////////////////////////////////////////////////////////////////
194//
195//
196// IsApplicable
197//
198G4bool G4RadioactiveDecay::IsApplicable( const G4ParticleDefinition &
199  aParticle)
200{
201  //
202  //
203  // All particles, other than G4Ions, are rejected by default.
204  //
205  if (((const G4Ions*)(&aParticle))->GetExcitationEnergy() > 0.) {return true;}
206  if (aParticle.GetParticleName() == "GenericIon")      {return true;}
207  else if (!(aParticle.GetParticleType() == "nucleus") || aParticle.GetPDGLifeTime() < 0. ) {return false;}
208  //
209  //
210  // Determine whether the nuclide falls into the correct A and Z range.
211  //
212  G4int A = ((const G4Ions*) (&aParticle))->GetAtomicMass();
213  G4int Z = ((const G4Ions*) (&aParticle))->GetAtomicNumber();
214  if( A> theNucleusLimits.GetAMax() || A< theNucleusLimits.GetAMin())
215    {return false;}
216  else if( Z> theNucleusLimits.GetZMax() || Z< theNucleusLimits.GetZMin())
217    {return false;}
218  return true;
219}
220///////////////////////////////////////////////////////////////////////////////
221//
222//
223// IsLoaded
224//
225G4bool G4RadioactiveDecay::IsLoaded(const G4ParticleDefinition &
226  aParticle)
227{
228  //
229  //
230  // Check whether the radioactive decay data on the ion have already been
231  // loaded.
232  //
233  return std::binary_search(LoadedNuclei.begin(),
234                       LoadedNuclei.end(),
235                       aParticle.GetParticleName());
236}
237////////////////////////////////////////////////////////////////////////////////
238//
239//
240// SelectAVolume
241//
242void G4RadioactiveDecay::SelectAVolume(const G4String aVolume)
243{
244 
245  G4LogicalVolumeStore *theLogicalVolumes;
246  G4LogicalVolume *volume;
247  theLogicalVolumes=G4LogicalVolumeStore::GetInstance();
248  for (size_t i = 0; i < theLogicalVolumes->size(); i++){
249    volume=(*theLogicalVolumes)[i];
250    if (volume->GetName() == aVolume) {
251      ValidVolumes.push_back(aVolume);
252      std::sort(ValidVolumes.begin(), ValidVolumes.end());
253      // sort need for performing binary_search
254#ifdef G4VERBOSE
255      if (GetVerboseLevel()>0)
256        G4cout << " RDM Applies to : " << aVolume << G4endl; 
257#endif
258    }else if(i ==  theLogicalVolumes->size())
259      {
260        G4cerr << "SelectAVolume: "<<aVolume << " is not a valid logical volume name"<< G4endl; 
261      }
262  }
263}
264////////////////////////////////////////////////////////////////////////////////
265//
266//
267// DeSelectAVolume
268//
269void G4RadioactiveDecay::DeselectAVolume(const G4String aVolume)
270{
271  G4LogicalVolumeStore *theLogicalVolumes;
272  G4LogicalVolume *volume;
273  theLogicalVolumes=G4LogicalVolumeStore::GetInstance();
274  for (size_t i = 0; i < theLogicalVolumes->size(); i++){
275    volume=(*theLogicalVolumes)[i];
276    if (volume->GetName() == aVolume) {
277      std::vector<G4String>::iterator location;
278      location = std::find(ValidVolumes.begin(),ValidVolumes.end(),aVolume);
279      if (location != ValidVolumes.end()) {
280        ValidVolumes.erase(location);
281        std::sort(ValidVolumes.begin(), ValidVolumes.end());
282      }else{
283        G4cerr << " DeselectVolume:" << aVolume << " is not in the list"<< G4endl; 
284      }   
285#ifdef G4VERBOSE
286      if (GetVerboseLevel()>0)
287        G4cout << " DeselectVolume: " << aVolume << " is removed from list"<<G4endl; 
288#endif
289    }else if(i ==  theLogicalVolumes->size())
290      {
291        G4cerr << " DeselectVolume:" << aVolume << "is not a valid logical volume name"<< G4endl; 
292      }
293  }
294}
295////////////////////////////////////////////////////////////////////////////////
296//
297//
298// SelectAllVolumes
299//
300void G4RadioactiveDecay::SelectAllVolumes() 
301{
302  G4LogicalVolumeStore *theLogicalVolumes;
303  G4LogicalVolume *volume;
304  theLogicalVolumes=G4LogicalVolumeStore::GetInstance();
305  ValidVolumes.clear();
306#ifdef G4VERBOSE
307  if (GetVerboseLevel()>0)
308    G4cout << " RDM Applies to all Volumes"  << G4endl;
309#endif
310  for (size_t i = 0; i < theLogicalVolumes->size(); i++){
311    volume=(*theLogicalVolumes)[i];
312    ValidVolumes.push_back(volume->GetName());   
313#ifdef G4VERBOSE
314    if (GetVerboseLevel()>0)
315      G4cout << "         RDM Applies to Volume "  << volume->GetName() << G4endl;
316#endif
317  }
318  std::sort(ValidVolumes.begin(), ValidVolumes.end());
319  // sort needed in order to allow binary_search
320}
321////////////////////////////////////////////////////////////////////////////////
322//
323//
324// DeSelectAllVolumes
325//
326void G4RadioactiveDecay::DeselectAllVolumes() 
327{
328  ValidVolumes.clear();
329#ifdef G4VERBOSE
330  if (GetVerboseLevel()>0)
331    G4cout << " RDM removed from all volumes" << G4endl; 
332#endif
333 
334}
335
336///////////////////////////////////////////////////////////////////////////////
337//
338//
339// IsRateTableReady
340//
341G4bool G4RadioactiveDecay::IsRateTableReady(const G4ParticleDefinition &
342  aParticle)
343{
344  //
345  //
346  // Check whether the radioactive decay rates table on the ion has already
347  // been calculated.
348  //
349  G4String aParticleName = aParticle.GetParticleName();
350  for (size_t i = 0; i < theDecayRateTableVector.size(); i++)
351    {
352      if (theDecayRateTableVector[i].GetIonName() == aParticleName)
353        return true ;
354    }
355  return false;
356}
357////////////////////////////////////////////////////////////////////////////////
358//
359//
360// GetDecayRateTable
361//
362// retrieve the decayratetable for the specified aParticle
363//
364void G4RadioactiveDecay::GetDecayRateTable(const G4ParticleDefinition &
365  aParticle)
366{
367
368  G4String aParticleName = aParticle.GetParticleName();
369
370  for (size_t i = 0; i < theDecayRateTableVector.size(); i++)
371    {
372      if (theDecayRateTableVector[i].GetIonName() == aParticleName)
373        {
374          theDecayRateVector = theDecayRateTableVector[i].GetItsRates() ;
375        }
376    }
377#ifdef G4VERBOSE
378        if (GetVerboseLevel()>0)
379          {
380            G4cout <<"The DecayRate Table for "
381                   << aParticleName << " is selected." <<  G4endl;
382          }
383#endif
384}
385////////////////////////////////////////////////////////////////////////////////
386//
387//
388// GetTaoTime
389//
390// to perform the convilution of the sourcetimeprofile function with the
391// decay constants in the decay chain.
392//
393G4double G4RadioactiveDecay::GetTaoTime(G4double t, G4double tao)
394{
395  G4double taotime =0.;
396  G4int nbin;
397  if ( t > SBin[NSourceBin]) {
398    nbin  = NSourceBin;}
399  else {
400    nbin = 0;
401    while (t > SBin[nbin]) nbin++;
402    nbin--;}
403  if (nbin > 0) { 
404    for (G4int i = 0; i < nbin; i++) 
405      {
406        taotime += SProfile[i] * (std::exp(-(t-SBin[i+1])/tao)-std::exp(-(t-SBin[i])/tao));
407      }
408  }
409  taotime +=  SProfile[nbin] * (1-std::exp(-(t-SBin[nbin])/tao));
410#ifdef G4VERBOSE
411  if (GetVerboseLevel()>1)
412    {G4cout <<" Tao time: " <<taotime <<G4endl;}
413#endif
414  return  taotime ;
415}
416 
417////////////////////////////////////////////////////////////////////////////////
418//
419//
420// GetDecayTime
421//
422// Randomly select a decay time for the decay process, following the supplied
423// decay time bias scheme.
424//
425G4double G4RadioactiveDecay::GetDecayTime()
426{
427  G4double decaytime = 0.;
428  G4double rand = G4UniformRand();
429  G4int i = 0;
430  while ( DProfile[i] < rand) i++;
431  rand = G4UniformRand();
432  decaytime = DBin[i] + rand*(DBin[i+1]-DBin[i]);
433#ifdef G4VERBOSE
434  if (GetVerboseLevel()>1)
435    {G4cout <<" Decay time: " <<decaytime <<"[ns]" <<G4endl;}
436#endif
437  return  decaytime;       
438}
439
440////////////////////////////////////////////////////////////////////////////////
441//
442//
443// GetDecayTimeBin
444//
445//
446//
447G4int G4RadioactiveDecay::GetDecayTimeBin(const G4double aDecayTime)
448{
449  for (G4int i = 0; i < NDecayBin; i++) 
450    {
451      if ( aDecayTime > DBin[i]) return i+1;     
452    }
453  return  1;
454}
455////////////////////////////////////////////////////////////////////////////////
456//
457//
458// GetMeanLifeTime
459//
460// this is required by the base class
461//
462G4double G4RadioactiveDecay::GetMeanLifeTime(const G4Track& theTrack,
463                                             G4ForceCondition* )
464{
465  // For varience reduction implementation the time is set to 0 so as to
466  // force the particle to decay immediately.
467  // in analogueMC mode it return the particles meanlife.
468  //
469  G4double meanlife = 0.;
470  if (AnalogueMC) {
471    const G4DynamicParticle* theParticle = theTrack.GetDynamicParticle();
472    G4ParticleDefinition* theParticleDef = theParticle->GetDefinition();
473    G4double theLife = theParticleDef->GetPDGLifeTime();
474     
475#ifdef G4VERBOSE
476    if (GetVerboseLevel()>2)
477      {
478        G4cout <<"G4RadioactiveDecay::GetMeanLifeTime() " <<G4endl;
479        G4cout <<"KineticEnergy:" <<theParticle->GetKineticEnergy()/GeV <<"[GeV]";
480        G4cout <<"Mass:" <<theParticle->GetMass()/GeV <<"[GeV]"; 
481        G4cout <<"Life time: " <<theLife/ns <<"[ns]" << G4endl;
482      }
483#endif
484    if (theParticleDef->GetPDGStable()) {meanlife = DBL_MAX;}
485    else if (theLife < 0.0) {meanlife = DBL_MAX;}
486    else {meanlife = theLife;}
487  // set the meanlife to zero for excited istopes which is not in the RDM database
488    if (((const G4Ions*)(theParticleDef))->GetExcitationEnergy() > 0. && meanlife == DBL_MAX) {meanlife = 0.;}
489  }
490#ifdef G4VERBOSE
491  if (GetVerboseLevel()>1)
492    {G4cout <<"mean life time: " <<meanlife <<"[ns]" <<G4endl;}
493#endif
494 
495  return  meanlife;
496}
497////////////////////////////////////////////////////////////////////////////////
498//
499//
500// GetMeanFreePath
501//
502// it is of similar functions to GetMeanFreeTime
503//
504G4double G4RadioactiveDecay::GetMeanFreePath (const G4Track& aTrack,
505                                              G4double, G4ForceCondition*)
506{
507  // constants
508  G4bool isOutRange ;
509 
510  // get particle
511  const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
512 
513  // returns the mean free path in GEANT4 internal units
514  G4double pathlength;
515  G4ParticleDefinition* aParticleDef = aParticle->GetDefinition();
516  G4double aCtau = c_light * aParticleDef->GetPDGLifeTime();
517  G4double aMass = aParticle->GetMass();
518 
519#ifdef G4VERBOSE
520  if (GetVerboseLevel()>2) {
521    G4cout << "G4RadioactiveDecay::GetMeanFreePath() "<< G4endl;
522    G4cout << "KineticEnergy:" << aParticle->GetKineticEnergy()/GeV <<"[GeV]";
523    G4cout << "Mass:" << aMass/GeV <<"[GeV]";
524    G4cout << "c*Tau:" << aCtau/m <<"[m]" <<G4endl;
525  }
526#endif
527 
528  // check if the particle is stable?
529  if (aParticleDef->GetPDGStable()) {
530    pathlength = DBL_MAX;
531   
532  } else if (aCtau < 0.0) {
533    pathlength =  DBL_MAX;
534   
535    //check if the particle has very short life time ?
536  } else if (aCtau < DBL_MIN) {
537    pathlength =  DBL_MIN;
538   
539    //check if zero mass
540  } else if (aMass <  DBL_MIN)  {
541    pathlength =  DBL_MAX;
542#ifdef G4VERBOSE
543    if (GetVerboseLevel()>1) {
544      G4cerr << " Zero Mass particle " << G4endl;
545    }
546#endif
547   } else {
548     //calculate the mean free path
549     // by using normalized kinetic energy (= Ekin/mass)
550     G4double   rKineticEnergy = aParticle->GetKineticEnergy()/aMass;
551     if ( rKineticEnergy > HighestBinValue) {
552       // beta >> 1
553       pathlength = ( rKineticEnergy + 1.0)* aCtau;
554     } else if ( rKineticEnergy > LowestBinValue) {
555       // check if aPhysicsTable exists
556       if (aPhysicsTable == 0) BuildPhysicsTable(*aParticleDef);
557       // beta is in the range valid for PhysicsTable
558       pathlength = aCtau *
559         ((*aPhysicsTable)(0))-> GetValue(rKineticEnergy,isOutRange);
560     } else if ( rKineticEnergy < DBL_MIN ) {
561       // too slow particle
562#ifdef G4VERBOSE
563       if (GetVerboseLevel()>2) {
564         G4cout << "G4Decay::GetMeanFreePath()   !!particle stops!!";
565         G4cout << aParticleDef->GetParticleName() << G4endl;
566         G4cout << "KineticEnergy:" << aParticle->GetKineticEnergy()/GeV <<"[GeV]";
567       }
568#endif
569       pathlength = DBL_MIN;
570     } else {
571       // beta << 1
572       pathlength = (aParticle->GetTotalMomentum())/aMass*aCtau ;
573     }
574   }
575#ifdef G4VERBOSE
576   if (GetVerboseLevel()>1) {
577     G4cout << "mean free path: "<< pathlength/m << "[m]" << G4endl;
578   }
579#endif
580   return  pathlength;
581}
582////////////////////////////////////////////////////////////////////////////////
583//
584//
585//
586//
587void G4RadioactiveDecay::BuildPhysicsTable(const G4ParticleDefinition&)
588{
589  // if aPhysicsTableis has already been created, do nothing
590  if (aPhysicsTable != 0) return;
591
592  // create  aPhysicsTable
593  if (GetVerboseLevel()>1) G4cerr <<" G4Decay::BuildPhysicsTable() "<< G4endl;
594  aPhysicsTable = new G4PhysicsTable(1);
595
596  //create physics vector
597  G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
598                                                       LowestBinValue,
599                                                       HighestBinValue,
600                                                       TotBin);
601
602  G4double beta, gammainv;
603  // fill physics Vector
604  G4int i;
605  for ( i = 0 ; i < TotBin ; i++ ) {
606      gammainv = 1.0/(aVector->GetLowEdgeEnergy(i) + 1.0);
607      beta  = std::sqrt((1.0 - gammainv)*(1.0 +gammainv));
608      aVector->PutValue(i, beta/gammainv);
609  }
610  aPhysicsTable->insert(aVector);
611}
612///////////////////////////////////////////////////////////////////////////////
613//
614// LoadDecayTable
615//
616//     To load the decay scheme from the Radioactivity database for
617//     theParentNucleus.
618//
619G4DecayTable *G4RadioactiveDecay::LoadDecayTable (G4ParticleDefinition &theParentNucleus)
620{
621  //
622  //
623  // Create and initialise variables used in the method.
624  //
625  G4DecayTable *theDecayTable = new G4DecayTable();
626  //
627  //
628  // Determine the filename of the file containing radioactive decay data.  Open
629  // it.
630  //
631  G4int A    = ((const G4Ions*)(&theParentNucleus))->GetAtomicMass();
632  G4int Z    = ((const G4Ions*)(&theParentNucleus))->GetAtomicNumber();
633  G4double E = ((const G4Ions*)(&theParentNucleus))->GetExcitationEnergy();
634
635  if ( !getenv("G4RADIOACTIVEDATA") ) {
636    G4cout << "Please setenv G4RADIOACTIVEDATA to point to the radioactive decay data files." << G4endl;
637    throw G4HadronicException(__FILE__, __LINE__, 
638              "Please setenv G4RADIOACTIVEDATA to point to the radioactive decay data files.");
639  }
640  G4String dirName = getenv("G4RADIOACTIVEDATA");
641  LoadedNuclei.push_back(theParentNucleus.GetParticleName());
642  std::sort( LoadedNuclei.begin(), LoadedNuclei.end() );
643  // sort needed to allow binary_search
644
645  std::ostringstream os;
646  os <<dirName <<"/z" <<Z <<".a" <<A <<'\0';
647  G4String file = os.str();
648
649 
650  std::ifstream DecaySchemeFile(file);
651  G4bool found(false);
652  if (DecaySchemeFile) { 
653    //
654    //
655    // Initialise variables used for reading in radioactive decay data.
656    //
657    G4int    nMode = 7;
658    G4bool   modeFirstRecord[7];
659    G4double modeTotalBR[7];
660    G4double modeSumBR[7];
661    G4int i;
662    for (i=0; i<nMode; i++) {
663      modeFirstRecord[i] = true;
664      modeSumBR[i]       = 0.0;
665    }
666   
667    G4bool complete(false);
668    char inputChars[80]={' '};
669    G4String inputLine;
670    G4String recordType("");
671    G4RadioactiveDecayMode theDecayMode;
672    G4double a(0.0);
673    G4double b(0.0);
674    G4double c(0.0);
675    G4double n(1.0);
676    G4double e0;
677    //
678    //
679    // Go through each record in the data file until you identify the decay
680    // data relating to the nuclide of concern.
681    //
682    //  while (!complete && -DecaySchemeFile.getline(inputChars, 80).eof() != EOF)
683    while (!complete && !DecaySchemeFile.getline(inputChars, 80).eof()) {
684      inputLine = inputChars;
685      //    G4String::stripType stripend(1);
686      //    inputLine = inputLine.strip(stripend);
687      inputLine = inputLine.strip(1);
688      if (inputChars[0] != '#' && inputLine.length() != 0) {
689        std::istringstream tmpStream(inputLine);
690        if (inputChars[0] == 'P') {
691          //
692          //
693          // Nucleus is a parent type.  Check the excitation level to see if it matches
694          // that of theParentNucleus
695          //
696          tmpStream >>recordType >>a >>b;
697          if (found) {complete = true;}
698          else {found = (std::abs(a*keV - E)<levelTolerance);}
699        } else if (found) {
700          //
701          //
702          // The right part of the radioactive decay data file has been found.  Search
703          // through it to determine the mode of decay of the subsequent records.
704          //
705          if (inputChars[0] == 'W') {
706#ifdef G4VERBOSE
707            if (GetVerboseLevel()>0) {
708              // a comment line identified and print out the message
709              //
710              G4cout << " Warning in G4RadioactiveDecay::LoadDecayTable " << G4endl;
711              G4cout << "   In data file " << file << G4endl;
712              G4cout << "   " << inputLine << G4endl;
713            }
714#endif
715          }     
716          else {
717            tmpStream >>theDecayMode >>a >>b >>c;
718            a/=1000.;
719            c/=1000.;
720                 
721            //  cout<< "The decay mode is [LoadTable] "<<theDecayMode<<G4endl;
722                 
723            switch (theDecayMode) {
724            case IT:
725              {
726                //
727                //
728                // Decay mode is isomeric transition.
729                //
730                G4ITDecayChannel *anITChannel = new G4ITDecayChannel
731                  (GetVerboseLevel(), (const G4Ions*) &theParentNucleus, b);
732                anITChannel->SetICM(applyICM);
733                anITChannel->SetARM(applyARM);
734                anITChannel->SetHLThreshold(halflifethreshold);
735                theDecayTable->Insert(anITChannel);
736                break;
737              }
738            case BetaMinus:
739              {
740                //
741                //
742                // Decay mode is beta-.
743                //
744                if (modeFirstRecord[1])
745                  {modeFirstRecord[1] = false; modeTotalBR[1] = b;}
746                else {
747                  if (c > 0.) {
748                    // to work out the Fermi function normalization factor first
749                    G4BetaFermiFunction* aBetaFermiFunction = new G4BetaFermiFunction (A, (Z+1));
750                    e0 = c*MeV/0.511;
751                    n = aBetaFermiFunction->GetFFN(e0);
752                               
753                    // now to work out the histogram and initialise the random generator
754                    G4int npti = 100;                           
755                    G4double* pdf = new G4double[npti];
756                    G4int ptn;
757                    G4double g,e,ee,f;
758                    ee = e0+1.;
759                    for (ptn=0; ptn<npti; ptn++) {
760                      // e =e0*(ptn+1.)/102.;
761                      // bug fix (#662) (flei, 22/09/2004)
762                      e =e0*(ptn+0.5)/100.;
763                      g = e+1.;
764                      f = std::sqrt(g*g-1)*(ee-g)*(ee-g)*g;
765                      // Special treatment for K-40 (problem #1068) (flei,06/05/2010)
766                      if (theParentNucleus.GetParticleName() == "K40[0.0]") f *=
767                        (std::pow((g*g-1),3)+std::pow((ee-g),6)+7*(g*g-1)*std::pow((ee-g),2)*(g*g-1+std::pow((ee-g),2)));
768                      pdf[ptn] = f*aBetaFermiFunction->GetFF(e);
769                    }             
770                    RandGeneral* aRandomEnergy = new RandGeneral( pdf, npti); 
771                    G4BetaMinusDecayChannel *aBetaMinusChannel = new
772                      G4BetaMinusDecayChannel (GetVerboseLevel(), &theParentNucleus,
773                                               b, c*MeV, a*MeV, n, FBeta, aRandomEnergy);
774                    theDecayTable->Insert(aBetaMinusChannel);
775                    modeSumBR[1] += b;
776                    delete[] pdf;
777                    delete aBetaFermiFunction;
778                  }
779                }
780                break;
781              case BetaPlus:
782                //
783                //
784                // Decay mode is beta+.
785                //
786                if (modeFirstRecord[2])
787                  {modeFirstRecord[2] = false; modeTotalBR[2] = b;}
788                else {
789                  //  e0 = c*MeV/0.511;
790                  // bug fix (#662) (flei, 22/09/2004)
791                  // need to test e0 as there are some data files (e.g. z67.a162) which have entries for beta+
792                  // with Q < 2Me
793                  //
794                  e0 = c*MeV/0.511 -2.;
795                  if (e0 > 0.) {
796                    G4BetaFermiFunction* aBetaFermiFunction = new G4BetaFermiFunction (A, -(Z-1));
797                               
798                    n = aBetaFermiFunction->GetFFN(e0);
799                               
800                    // now to work out the histogram and initialise the random generator
801                    G4int npti = 100;                           
802                    G4double* pdf = new G4double[npti];
803                    G4int ptn;
804                    G4double g,e,ee,f;
805                    ee = e0+1.;
806                    for (ptn=0; ptn<npti; ptn++) {
807                      // e =e0*(ptn+1.)/102.;
808                      // bug fix (#662) (flei, 22/09/2004)
809                      e =e0*(ptn+0.5)/100.;
810                      g = e+1.;
811                      f = std::sqrt(g*g-1)*(ee-g)*(ee-g)*g;
812                      pdf[ptn] = f*aBetaFermiFunction->GetFF(e);
813                    }
814                    RandGeneral* aRandomEnergy = new RandGeneral( pdf, npti); 
815                    G4BetaPlusDecayChannel *aBetaPlusChannel = new 
816                      G4BetaPlusDecayChannel (GetVerboseLevel(), &theParentNucleus,
817                                              b, c*MeV, a*MeV, n, FBeta, aRandomEnergy);
818                    theDecayTable->Insert(aBetaPlusChannel);
819                    modeSumBR[2] += b;
820                               
821                    delete[] pdf;
822                    delete aBetaFermiFunction;       
823                  }
824                }
825                break;
826              case KshellEC:
827                //
828                //
829                // Decay mode is K-electron capture.
830                //
831                if (modeFirstRecord[3])
832                  {modeFirstRecord[3] = false; modeTotalBR[3] = b;}
833                else {
834                  G4KshellECDecayChannel *aKECChannel = new
835                    G4KshellECDecayChannel (GetVerboseLevel(), &theParentNucleus,
836                                            b, c*MeV, a*MeV);
837                  aKECChannel->SetICM(applyICM);
838                  aKECChannel->SetARM(applyARM);
839                  aKECChannel->SetHLThreshold(halflifethreshold);
840                  theDecayTable->Insert(aKECChannel);
841                  //delete aKECChannel;
842                  modeSumBR[3] += b;
843                }
844                break;
845              case LshellEC:
846                //
847                //
848                // Decay mode is L-electron capture.
849                //
850                if (modeFirstRecord[4])
851                  {modeFirstRecord[4] = false; modeTotalBR[4] = b;}
852                else {
853                  G4LshellECDecayChannel *aLECChannel = new
854                    G4LshellECDecayChannel (GetVerboseLevel(), &theParentNucleus,
855                                            b, c*MeV, a*MeV);
856                  aLECChannel->SetICM(applyICM);
857                  aLECChannel->SetARM(applyARM);
858                  aLECChannel->SetHLThreshold(halflifethreshold);
859                  theDecayTable->Insert(aLECChannel);
860                  //delete aLECChannel;
861                  modeSumBR[4] += b;
862                }
863                break;
864              case MshellEC:
865                //
866                //
867                // Decay mode is M-electron capture. In this implementation it is added to L-shell case
868                //
869                if (modeFirstRecord[5])
870                  {modeFirstRecord[5] = false; modeTotalBR[5] = b;}
871                else {
872                  G4MshellECDecayChannel *aMECChannel = new
873                    G4MshellECDecayChannel (GetVerboseLevel(), &theParentNucleus,
874                                            b, c*MeV, a*MeV);
875                  aMECChannel->SetICM(applyICM);
876                  aMECChannel->SetARM(applyARM);
877                  aMECChannel->SetHLThreshold(halflifethreshold);
878                  theDecayTable->Insert(aMECChannel);
879                  modeSumBR[5] += b;
880                }
881                break;
882              case Alpha:
883                //
884                //
885                // Decay mode is alpha.
886                //
887                if (modeFirstRecord[6])
888                  {modeFirstRecord[6] = false; modeTotalBR[6] = b;}
889                else {
890                  G4AlphaDecayChannel *anAlphaChannel = new
891                    G4AlphaDecayChannel (GetVerboseLevel(), &theParentNucleus,
892                                         b, c*MeV, a*MeV);
893                  theDecayTable->Insert(anAlphaChannel);
894                  //          delete anAlphaChannel;
895                  modeSumBR[6] += b;
896                }
897                break;
898              case ERROR:
899              default:
900                G4Exception("G4RadioactiveDecay::LoadDecayTable()", "601",
901                            FatalException, "Error in decay mode selection");
902               
903              }
904            }
905          }
906        }
907      }
908    }   
909    //
910    //
911    // Go through the decay table and make sure that the branching ratios are
912    // correctly normalised.
913    //
914    G4VDecayChannel       *theChannel             = 0;
915    G4NuclearDecayChannel *theNuclearDecayChannel = 0;
916    G4String mode                     = "";
917    G4int j                           = 0;
918    G4double theBR                    = 0.0;
919    for (i=0; i<theDecayTable->entries(); i++) {
920      theChannel             = theDecayTable->GetDecayChannel(i);
921      theNuclearDecayChannel = static_cast<G4NuclearDecayChannel *>(theChannel);
922      theDecayMode           = theNuclearDecayChannel->GetDecayMode();
923      j          = 0;
924      if (theDecayMode != IT) {
925        theBR = theChannel->GetBR();
926        theChannel->SetBR(theBR*modeTotalBR[theDecayMode]/modeSumBR[theDecayMode]);
927      }
928    } 
929  }             
930  DecaySchemeFile.close();             
931  if (!found && E > 0.) {
932    // cases where IT cascade for exited isotopes without entry in RDM database
933    // Decay mode is isomeric transition.
934    //
935    G4ITDecayChannel *anITChannel = new G4ITDecayChannel
936      (GetVerboseLevel(), (const G4Ions*) &theParentNucleus, 1);
937    anITChannel->SetICM(applyICM);
938    anITChannel->SetARM(applyARM);
939    anITChannel->SetHLThreshold(halflifethreshold);
940    theDecayTable->Insert(anITChannel);
941  } 
942  if (!theDecayTable) {
943    //
944    // There is no radioactive decay data for this nucleus.  Return a null
945    // decay table.
946    //
947    G4cerr <<"G4RadoactiveDecay::LoadDecayTable() : cannot find ion radioactive decay file " <<G4endl;
948    theDecayTable = 0;
949    return theDecayTable;
950  }     
951  if (theDecayTable && GetVerboseLevel()>1)
952    {
953      G4cout <<"G4RadioactiveDecay::LoadDecayTable()" << G4endl;
954      G4cout << "  No. of  entries: "<< theDecayTable->entries() <<G4endl;
955      theDecayTable ->DumpInfo();
956    }
957
958  return theDecayTable;
959}
960
961////////////////////////////////////////////////////////////////////////
962//
963//
964void G4RadioactiveDecay::SetDecayRate(G4int theZ, G4int theA, G4double theE, 
965                                       G4int theG, std::vector<G4double> theRates, 
966                                       std::vector<G4double> theTaos)
967{ 
968  //fill the decay rate vector
969  theDecayRate.SetZ(theZ);
970  theDecayRate.SetA(theA);
971  theDecayRate.SetE(theE);
972  theDecayRate.SetGeneration(theG);
973  theDecayRate.SetDecayRateC(theRates);
974  theDecayRate.SetTaos(theTaos);
975}
976//////////////////////////////////////////////////////////////////////////
977//
978//
979void G4RadioactiveDecay::AddDecayRateTable(const G4ParticleDefinition &theParentNucleus)
980{
981  // 1) To calculate all the coefficiecies required to derive the radioactivities for all
982  // progeny of theParentNucleus
983  //
984  // 2) Add the coefficiencies to the decay rate table vector
985  //
986 
987  //
988  // Create and initialise variables used in the method.
989  //
990
991  theDecayRateVector.clear();
992 
993  G4int nGeneration = 0;
994  std::vector<G4double> rates;
995  std::vector<G4double> taos;
996 
997  // start rate is -1.
998  rates.push_back(-1.);
999  //
1000  //
1001  G4int A = ((const G4Ions*)(&theParentNucleus))->GetAtomicMass();
1002  G4int Z = ((const G4Ions*)(&theParentNucleus))->GetAtomicNumber();
1003  G4double E = ((const G4Ions*)(&theParentNucleus))->GetExcitationEnergy();
1004  G4double tao = theParentNucleus.GetPDGLifeTime();
1005  taos.push_back(tao);
1006  G4int nEntry = 0;
1007 
1008  //fill the decay rate with the intial isotope data
1009  SetDecayRate(Z,A,E,nGeneration,rates,taos);
1010
1011  // store the decay rate in decay rate vector
1012  theDecayRateVector.push_back(theDecayRate);
1013  nEntry++;
1014
1015  // now start treating the sencondary generations..
1016
1017  G4bool stable = false;
1018  G4int i;
1019  G4int j;
1020  G4VDecayChannel       *theChannel             = 0;
1021  G4NuclearDecayChannel *theNuclearDecayChannel = 0;
1022  G4ITDecayChannel *theITChannel = 0;
1023  G4BetaMinusDecayChannel *theBetaMinusChannel = 0;
1024  G4BetaPlusDecayChannel *theBetaPlusChannel = 0;
1025  G4AlphaDecayChannel *theAlphaChannel = 0;
1026  G4RadioactiveDecayMode theDecayMode;
1027  //  G4NuclearLevelManager levelManager;
1028  //const G4NuclearLevel* level;
1029  G4double theBR = 0.0;
1030  G4int AP = 0;
1031  G4int ZP = 0;
1032  G4int AD = 0;
1033  G4int ZD = 0;
1034  G4double EP = 0.;
1035  std::vector<G4double> TP;
1036  std::vector<G4double> RP;
1037  G4ParticleDefinition *theDaughterNucleus;
1038  G4double daughterExcitation;
1039  G4ParticleDefinition *aParentNucleus;
1040  G4IonTable* theIonTable;
1041  G4DecayTable *aTempDecayTable;
1042  G4double theRate;
1043  G4double TaoPlus;
1044  G4int nS = 0;
1045  G4int nT = nEntry;
1046  G4double brs[7];
1047  //
1048  theIonTable = (G4IonTable *)(G4ParticleTable::GetParticleTable()->GetIonTable());
1049 
1050  while (!stable) {
1051    nGeneration++;
1052    for (j = nS; j< nT; j++) {
1053      ZP = theDecayRateVector[j].GetZ();
1054      AP = theDecayRateVector[j].GetA();
1055      EP = theDecayRateVector[j].GetE();
1056      RP = theDecayRateVector[j].GetDecayRateC();
1057      TP = theDecayRateVector[j].GetTaos();     
1058      if (GetVerboseLevel()>0){
1059        G4cout <<"G4RadioactiveDecay::AddDecayRateTable : "
1060               << " daughters of ("<< ZP <<", "<<AP<<", "
1061               << EP <<") "
1062               << " are being calculated. "       
1063               <<" generation = "
1064               << nGeneration << G4endl;
1065      }
1066      aParentNucleus = theIonTable->GetIon(ZP,AP,EP);
1067      if (!IsLoaded(*aParentNucleus)){
1068        aParentNucleus->SetDecayTable(LoadDecayTable(*aParentNucleus));
1069      }
1070      aTempDecayTable = aParentNucleus->GetDecayTable();
1071      //
1072      //
1073      // Go through the decay table and to combine the same decay channels
1074      //
1075      for (i=0; i< 7; i++) brs[i] = 0.0;
1076     
1077      G4DecayTable *theDecayTable = new G4DecayTable();
1078     
1079      for (i=0; i<aTempDecayTable->entries(); i++) {
1080        theChannel             = aTempDecayTable->GetDecayChannel(i);
1081        theNuclearDecayChannel = static_cast<G4NuclearDecayChannel *>(theChannel);
1082        theDecayMode           = theNuclearDecayChannel->GetDecayMode();
1083        daughterExcitation = theNuclearDecayChannel->GetDaughterExcitation ();
1084        theDaughterNucleus = theNuclearDecayChannel->GetDaughterNucleus () ;
1085        AD = ((const G4Ions*)(theDaughterNucleus))->GetAtomicMass();
1086        ZD = ((const G4Ions*)(theDaughterNucleus))->GetAtomicNumber(); 
1087        G4NuclearLevelManager * levelManager = G4NuclearLevelStore::GetInstance()->GetManager (ZD, AD);
1088        if ( levelManager->NumberOfLevels() ) {
1089          const G4NuclearLevel* level = levelManager->NearestLevel (daughterExcitation);
1090
1091          if (std::abs(daughterExcitation - level->Energy()) < levelTolerance) {
1092           
1093            // Level hafe life is in ns and the gate as 1 micros by default
1094            if ( theDecayMode == 0 && level->HalfLife()*ns >= halflifethreshold ){   
1095              // some further though may needed here
1096              theDecayTable->Insert(theChannel);
1097            } 
1098            else{
1099              brs[theDecayMode] += theChannel->GetBR();
1100            }
1101          }
1102          else {
1103            brs[theDecayMode] += theChannel->GetBR();
1104          }
1105        }
1106        else{
1107          brs[theDecayMode] += theChannel->GetBR();
1108        }
1109      }     
1110      brs[2] = brs[2]+brs[3]+brs[4]+brs[5];
1111      brs[3] = brs[4] =brs[5] =  0.0;
1112      for (i= 0; i<7; i++){
1113        if (brs[i] > 0) {
1114          switch ( i ) {
1115          case 0:
1116            //
1117            //
1118            // Decay mode is isomeric transition.
1119            //
1120           
1121            theITChannel =  new G4ITDecayChannel
1122              (0, (const G4Ions*) aParentNucleus, brs[0]);
1123           
1124            theDecayTable->Insert(theITChannel);
1125            break;
1126           
1127          case 1:
1128            //
1129            //
1130            // Decay mode is beta-.
1131            //
1132            theBetaMinusChannel = new G4BetaMinusDecayChannel (0, aParentNucleus,
1133                                                               brs[1], 0.*MeV, 0.*MeV, 1, false, 0);
1134            theDecayTable->Insert(theBetaMinusChannel);
1135           
1136            break;
1137           
1138          case 2:
1139            //
1140            //
1141            // Decay mode is beta+ + EC.
1142            //
1143            theBetaPlusChannel = new G4BetaPlusDecayChannel (GetVerboseLevel(), aParentNucleus,
1144                                                             brs[2], 0.*MeV, 0.*MeV, 1, false, 0);
1145            theDecayTable->Insert(theBetaPlusChannel);
1146            break;                   
1147           
1148          case 6:
1149            //
1150            //
1151            // Decay mode is alpha.
1152            //
1153            theAlphaChannel = new G4AlphaDecayChannel (GetVerboseLevel(), aParentNucleus,
1154                                                       brs[6], 0.*MeV, 0.*MeV);
1155            theDecayTable->Insert(theAlphaChannel);
1156            break;
1157           
1158          default:
1159            break;
1160          }
1161        }
1162      }
1163       
1164      //
1165      // loop over all braches in theDecayTable
1166      //
1167      for ( i=0; i<theDecayTable->entries(); i++){
1168        theChannel             = theDecayTable->GetDecayChannel(i);
1169        theNuclearDecayChannel = static_cast<G4NuclearDecayChannel *>(theChannel);
1170        theBR = theChannel->GetBR();
1171        theDaughterNucleus = theNuclearDecayChannel->GetDaughterNucleus();
1172       
1173        //
1174        // now test if the daughterNucleus is a valid one
1175        //
1176        if (IsApplicable(*theDaughterNucleus) && theBR
1177            && aParentNucleus != theDaughterNucleus ) {
1178          // need to make sure daugher has decaytable
1179          if (!IsLoaded(*theDaughterNucleus)){
1180            theDaughterNucleus->SetDecayTable(LoadDecayTable(*theDaughterNucleus));
1181          }
1182          if (theDaughterNucleus->GetDecayTable()->entries() ) {
1183            //
1184            A = ((const G4Ions*)(theDaughterNucleus))->GetAtomicMass();
1185            Z = ((const G4Ions*)(theDaughterNucleus))->GetAtomicNumber();
1186            E = ((const G4Ions*)(theDaughterNucleus))->GetExcitationEnergy();
1187         
1188            TaoPlus = theDaughterNucleus->GetPDGLifeTime();
1189            //          cout << TaoPlus <<G4endl;
1190            if (TaoPlus > 0.) {
1191              // first set the taos, one simply need to add to the parent ones
1192              taos.clear();
1193              taos = TP;
1194              taos.push_back(TaoPlus);
1195              // now calculate the coefficiencies
1196              //
1197              // they are in two parts, first the les than n ones
1198              rates.clear();
1199              size_t k;
1200              for (k = 0; k < RP.size(); k++){
1201                theRate = TP[k]/(TP[k]-TaoPlus) * theBR * RP[k];
1202                rates.push_back(theRate);
1203              }
1204              //
1205              // the sencond part: the n:n coefficiency
1206              theRate = 0.;
1207              for (k = 0; k < RP.size(); k++){
1208                theRate -=TaoPlus/(TP[k]-TaoPlus) * theBR * RP[k];
1209              }
1210              rates.push_back(theRate);               
1211              SetDecayRate (Z,A,E,nGeneration,rates,taos);
1212              theDecayRateVector.push_back(theDecayRate);
1213              nEntry++;
1214            } 
1215          }
1216        } 
1217        // end of testing daughter nucleus
1218      }
1219      // end of i loop( the branches)
1220    }
1221    //end of for j loop
1222    nS = nT;
1223    nT = nEntry;
1224    if (nS == nT) stable = true;
1225  }
1226 
1227  //end of while loop
1228  // the calculation completed here
1229 
1230 
1231  // fill the first part of the decay rate table
1232  // which is the name of the original particle (isotope)
1233  //
1234  theDecayRateTable.SetIonName(theParentNucleus.GetParticleName()); 
1235  //
1236  //
1237  // now fill the decay table with the newly completed decay rate vector
1238  //
1239 
1240  theDecayRateTable.SetItsRates(theDecayRateVector);
1241 
1242  //
1243  // finally add the decayratetable to the tablevector
1244  //
1245  theDecayRateTableVector.push_back(theDecayRateTable);
1246}
1247 
1248////////////////////////////////////////////////////////////////////////////////
1249//
1250//
1251// SetSourceTimeProfile
1252//
1253//  read in the source time profile function (histogram)
1254//
1255
1256void G4RadioactiveDecay::SetSourceTimeProfile(G4String filename)
1257{
1258  std::ifstream infile ( filename, std::ios::in );
1259  if ( !infile ) G4Exception(__FILE__, G4inttostring(__LINE__), FatalException,  "Unable to open source data file" );
1260 
1261  float bin, flux;
1262  NSourceBin = -1;
1263  while (infile >> bin >> flux ) {
1264    NSourceBin++;
1265    if (NSourceBin > 99)  G4Exception(__FILE__, G4inttostring(__LINE__), FatalException,  "input source data file too big (>100 rows)" );
1266    SBin[NSourceBin] = bin * s;
1267    SProfile[NSourceBin] = flux;
1268  }
1269  SetAnalogueMonteCarlo(0);
1270#ifdef G4VERBOSE
1271  if (GetVerboseLevel()>1)
1272    {G4cout <<" Source Timeprofile Nbin = " << NSourceBin <<G4endl;}
1273#endif
1274}
1275
1276////////////////////////////////////////////////////////////////////////////////
1277//
1278//
1279// SetDecayBiasProfile
1280//
1281// read in the decay bias scheme function (histogram)
1282//
1283void G4RadioactiveDecay::SetDecayBias(G4String filename)
1284{
1285  std::ifstream infile ( filename, std::ios::in);
1286  if ( !infile ) G4Exception(__FILE__, G4inttostring(__LINE__), FatalException,  "Unable to open bias data file" );
1287 
1288  float bin, flux;
1289  NDecayBin = -1;
1290  while (infile >> bin >> flux ) {
1291    NDecayBin++;
1292    if (NDecayBin > 99)  G4Exception(__FILE__, G4inttostring(__LINE__), FatalException,  "input bias data file too big (>100 rows)" );
1293    DBin[NDecayBin] = bin * s;
1294    DProfile[NDecayBin] = flux;
1295  }
1296  G4int i ;
1297  for ( i = 1; i<= NDecayBin; i++) DProfile[i] += DProfile[i-1];
1298  for ( i = 0; i<= NDecayBin; i++) DProfile[i] /= DProfile[NDecayBin];
1299  SetAnalogueMonteCarlo(0);
1300#ifdef G4VERBOSE
1301  if (GetVerboseLevel()>1)
1302    {G4cout <<" Decay Bias Profile  Nbin = " << NDecayBin <<G4endl;}
1303#endif
1304}
1305
1306////////////////////////////////////////////////////////////////////////////////
1307//
1308//
1309// DecayIt
1310//
1311G4VParticleChange* G4RadioactiveDecay::DecayIt(const G4Track& theTrack, const G4Step& )
1312{
1313  //
1314  // Initialize the G4ParticleChange object. Get the particle details and the
1315  // decay table.
1316  //
1317  fParticleChangeForRadDecay.Initialize(theTrack);
1318  const G4DynamicParticle* theParticle = theTrack.GetDynamicParticle();
1319  G4ParticleDefinition *theParticleDef = theParticle->GetDefinition();
1320
1321  // First check whether RDM applies to the current logical volume
1322  //
1323  if(!std::binary_search(ValidVolumes.begin(),
1324                    ValidVolumes.end(), 
1325                    theTrack.GetVolume()->GetLogicalVolume()->GetName()))
1326    {
1327#ifdef G4VERBOSE
1328      if (GetVerboseLevel()>0)
1329        {
1330          G4cout <<"G4RadioactiveDecay::DecayIt : "
1331                 << theTrack.GetVolume()->GetLogicalVolume()->GetName()
1332                 << " is not selected for the RDM"<< G4endl;
1333          G4cout << " There are " << ValidVolumes.size() << " volumes" << G4endl;
1334          G4cout << " The Valid volumes are " << G4endl;
1335          for (size_t i = 0; i< ValidVolumes.size(); i++)
1336            G4cout << ValidVolumes[i] << G4endl;
1337        }
1338#endif
1339      fParticleChangeForRadDecay.SetNumberOfSecondaries(0);
1340      //
1341      //
1342      // Kill the parent particle.
1343      //
1344      fParticleChangeForRadDecay.ProposeTrackStatus( fStopAndKill ) ;
1345      fParticleChangeForRadDecay.ProposeLocalEnergyDeposit(0.0);
1346      ClearNumberOfInteractionLengthLeft();
1347      return &fParticleChangeForRadDecay;
1348    }
1349   
1350  // now check is the particle is valid for RDM
1351  //
1352  if (!(IsApplicable(*theParticleDef)))
1353    { 
1354      //
1355      // The particle is not a Ion or outside the nucleuslimits for decay
1356      //
1357#ifdef G4VERBOSE
1358      if (GetVerboseLevel()>0)
1359        {
1360          G4cerr <<"G4RadioactiveDecay::DecayIt : "
1361                 <<theParticleDef->GetParticleName() 
1362                 << " is not a valid nucleus for the RDM"<< G4endl;
1363        }
1364#endif
1365      fParticleChangeForRadDecay.SetNumberOfSecondaries(0);
1366      //
1367      //
1368      // Kill the parent particle.
1369      //
1370      fParticleChangeForRadDecay.ProposeTrackStatus( fStopAndKill ) ;
1371      fParticleChangeForRadDecay.ProposeLocalEnergyDeposit(0.0);
1372      ClearNumberOfInteractionLengthLeft();
1373      return &fParticleChangeForRadDecay;
1374    }
1375 
1376  if (!IsLoaded(*theParticleDef))
1377    {
1378      theParticleDef->SetDecayTable(LoadDecayTable(*theParticleDef));
1379    }
1380  G4DecayTable *theDecayTable = theParticleDef->GetDecayTable();
1381 
1382  if  (theDecayTable == 0 || theDecayTable->entries() == 0 )
1383    {
1384      //
1385      //
1386      // There are no data in the decay table.  Set the particle change parameters
1387      // to indicate this.
1388      //
1389#ifdef G4VERBOSE
1390      if (GetVerboseLevel()>0)
1391        {
1392          G4cerr <<"G4RadioactiveDecay::DecayIt : decay table not defined  for ";
1393          G4cerr <<theParticleDef->GetParticleName() <<G4endl;
1394        }
1395#endif
1396      fParticleChangeForRadDecay.SetNumberOfSecondaries(0);
1397      //
1398      //
1399      // Kill the parent particle.
1400      //
1401      fParticleChangeForRadDecay.ProposeTrackStatus( fStopAndKill ) ;
1402      fParticleChangeForRadDecay.ProposeLocalEnergyDeposit(0.0);
1403      ClearNumberOfInteractionLengthLeft();
1404      return &fParticleChangeForRadDecay;
1405    }
1406  else 
1407    { 
1408      //
1409      // now try to  decay it
1410      //
1411      G4double energyDeposit = 0.0;
1412      G4double finalGlobalTime = theTrack.GetGlobalTime();
1413      G4int index;
1414      G4ThreeVector currentPosition;
1415      currentPosition = theTrack.GetPosition();
1416     
1417      // check whether use Analogue or VR implementation
1418      //
1419      if (AnalogueMC){
1420        //
1421        // Aanalogue MC
1422#ifdef G4VERBOSE
1423        if (GetVerboseLevel()>0)
1424          {
1425            G4cout <<"DecayIt:  Analogue MC version " << G4endl;
1426          }
1427#endif
1428        //
1429        G4DecayProducts *products = DoDecay(*theParticleDef);
1430        //
1431        // check if the product is the same as input and kill the track if necessary to prevent infinite loop
1432        // (11/05/10, F.Lei)
1433        //
1434        if ( products->entries() == 1) {
1435          fParticleChangeForRadDecay.SetNumberOfSecondaries(0);
1436          fParticleChangeForRadDecay.ProposeTrackStatus( fStopAndKill ) ;
1437          fParticleChangeForRadDecay.ProposeLocalEnergyDeposit(0.0);
1438          ClearNumberOfInteractionLengthLeft();
1439          return &fParticleChangeForRadDecay;
1440        }       
1441        //
1442        // Get parent particle information and boost the decay products to the
1443        // laboratory frame based on this information.
1444        //
1445        G4double ParentEnergy = theParticle->GetTotalEnergy();
1446        G4ThreeVector ParentDirection(theParticle->GetMomentumDirection());
1447       
1448        if (theTrack.GetTrackStatus() == fStopButAlive )
1449          {
1450            //
1451            //
1452            // The particle is decayed at rest.
1453            //
1454            // since the time is still for rest particle in G4 we need to add the additional
1455            // time lapsed between the particle come to rest and the actual decay. This time
1456            // is simply sampled with the mean-life of the particle.
1457            // but we need to protect the case PDGTime < 0. (F.Lei 11/05/10)
1458            G4double temptime =  -std::log( G4UniformRand()) * theParticleDef->GetPDGLifeTime();
1459            if (temptime <0.) temptime =0.; 
1460            finalGlobalTime += temptime ;
1461            energyDeposit += theParticle->GetKineticEnergy();
1462          }
1463        else
1464          {
1465            //
1466            //
1467            // The particle is decayed in flight (PostStep case).
1468            //
1469            products->Boost( ParentEnergy, ParentDirection);
1470          }
1471        //
1472        //
1473        // Add products in theParticleChangeForRadDecay.
1474        //
1475        G4int numberOfSecondaries = products->entries();
1476        fParticleChangeForRadDecay.SetNumberOfSecondaries(numberOfSecondaries);
1477#ifdef G4VERBOSE
1478        if (GetVerboseLevel()>1) {
1479          G4cout <<"G4RadioactiveDecay::DecayIt : Decay vertex :";
1480          G4cout <<" Time: " <<finalGlobalTime/ns <<"[ns]";
1481          G4cout <<" X:" <<(theTrack.GetPosition()).x() /cm <<"[cm]";
1482          G4cout <<" Y:" <<(theTrack.GetPosition()).y() /cm <<"[cm]";
1483          G4cout <<" Z:" <<(theTrack.GetPosition()).z() /cm <<"[cm]";
1484          G4cout <<G4endl;
1485          G4cout <<"G4Decay::DecayIt  : decay products in Lab. Frame" <<G4endl;
1486          products->DumpInfo();
1487        }
1488#endif
1489        for (index=0; index < numberOfSecondaries; index++) 
1490          {
1491            G4Track* secondary = new G4Track
1492              (products->PopProducts(), finalGlobalTime, currentPosition);
1493            secondary->SetGoodForTrackingFlag();
1494                        secondary->SetTouchableHandle(theTrack.GetTouchableHandle());
1495            fParticleChangeForRadDecay.AddSecondary(secondary);
1496          }
1497        delete products;
1498        //
1499        // end of analogue MC algarithm
1500        //
1501      }
1502      else {
1503        //
1504        // Varaice Reduction Method
1505        //
1506#ifdef G4VERBOSE
1507        if (GetVerboseLevel()>0)
1508          {
1509            G4cout <<"DecayIt:  Variance Reduction version " << G4endl;
1510          }
1511#endif
1512        if (!IsRateTableReady(*theParticleDef)) {
1513          // if the decayrates are not ready, calculate them and
1514          // add to the rate table vector
1515          AddDecayRateTable(*theParticleDef);
1516        }
1517        //retrieve the rates
1518        GetDecayRateTable(*theParticleDef);
1519        //
1520        // declare some of the variables required in the implementation
1521        //
1522        G4ParticleDefinition* parentNucleus;
1523        G4IonTable *theIonTable;
1524        G4int PZ;
1525        G4int PA;
1526        G4double PE;
1527        std::vector<G4double> PT;
1528        std::vector<G4double> PR;
1529        G4double taotime;
1530        G4double decayRate;
1531       
1532        size_t i;
1533        size_t j;
1534        G4int numberOfSecondaries;
1535        G4int totalNumberOfSecondaries = 0;
1536        G4double currentTime = 0.;
1537        G4int ndecaych;
1538        G4DynamicParticle* asecondaryparticle;
1539        //      G4DecayProducts* products = 0;
1540        std::vector<G4DynamicParticle*> secondaryparticles;
1541        std::vector<G4double> pw;
1542        std::vector<G4double> ptime;
1543        pw.clear();
1544        ptime.clear();
1545        //now apply the nucleus splitting
1546        //
1547        //
1548        for (G4int n = 0; n < NSplit; n++)
1549          {
1550            /*
1551            //
1552            // Get the decay time following the decay probability function
1553            // suppllied by user
1554            //
1555            G4double theDecayTime = GetDecayTime();
1556           
1557            G4int nbin = GetDecayTimeBin(theDecayTime);
1558           
1559            // claculate the first part of the weight function
1560           
1561            G4double weight1 =1./DProfile[nbin-1]
1562              *(DBin[nbin]-DBin[nbin-1])
1563              /NSplit;
1564            if (nbin > 1) {
1565               weight1 = 1./(DProfile[nbin]-DProfile[nbin-2])
1566                 *(DBin[nbin]-DBin[nbin-1])
1567                 /NSplit;}
1568            // it should be calculated in seconds
1569            weight1 /= s ;
1570            */
1571            //
1572            // loop over all the possible secondaries of the nucleus
1573            // the first one is itself.
1574            //
1575            for ( i = 0; i<theDecayRateVector.size(); i++){
1576              PZ = theDecayRateVector[i].GetZ();
1577              PA = theDecayRateVector[i].GetA();
1578              PE = theDecayRateVector[i].GetE();
1579              PT = theDecayRateVector[i].GetTaos();
1580              PR = theDecayRateVector[i].GetDecayRateC();
1581
1582              //
1583              // Get the decay time following the decay probability function
1584              // suppllied by user
1585              //
1586              G4double theDecayTime = GetDecayTime();
1587             
1588              G4int nbin = GetDecayTimeBin(theDecayTime);
1589             
1590              // claculate the first part of the weight function
1591             
1592              G4double weight1 =1./DProfile[nbin-1] 
1593                *(DBin[nbin]-DBin[nbin-1])
1594                /NSplit;
1595              if (nbin > 1) {
1596                weight1 = 1./(DProfile[nbin]-DProfile[nbin-2])
1597                  *(DBin[nbin]-DBin[nbin-1])
1598                  /NSplit;}
1599              // it should be calculated in seconds
1600              weight1 /= s ;
1601             
1602              // a temprary products buffer and its contents is transfered to
1603              // the products at the end of the loop
1604              //
1605              G4DecayProducts *tempprods = 0;
1606             
1607              // calculate the decay rate of the isotope
1608              // one need to fold the the source bias function with the decaytime
1609              //
1610              decayRate = 0.;
1611              for ( j = 0; j < PT.size(); j++){
1612                taotime = GetTaoTime(theDecayTime,PT[j]);
1613                decayRate -= PR[j] * taotime;
1614              }
1615             
1616              // decayRatehe radioactivity of isotope (PZ,PA,PE) at the
1617              // time 'theDecayTime'
1618              // it will be used to calculate the statistical weight of the
1619              // decay products of this isotope
1620             
1621             
1622              //
1623              // now calculate the statistical weight
1624              //
1625             
1626              G4double weight = weight1*decayRate; 
1627              // decay the isotope
1628              theIonTable = (G4IonTable *)(G4ParticleTable::GetParticleTable()->GetIonTable());
1629              parentNucleus = theIonTable->GetIon(PZ,PA,PE);
1630             
1631              // decide whther to apply branching ratio bias or not
1632              //
1633              if (BRBias){
1634                G4DecayTable *theDecayTable = parentNucleus->GetDecayTable();
1635                ndecaych = G4int(theDecayTable->entries()*G4UniformRand());
1636                G4VDecayChannel *theDecayChannel = theDecayTable->GetDecayChannel(ndecaych);
1637                if (theDecayChannel == 0)
1638                  {
1639                    // Decay channel not found.
1640#ifdef G4VERBOSE
1641                    if (GetVerboseLevel()>0)
1642                      {
1643                        G4cerr <<"G4RadioactiveDecay::DoIt : can not determine decay channel";
1644                        G4cerr <<G4endl;
1645                        theDecayTable ->DumpInfo();
1646                      }
1647#endif
1648                  }
1649                else
1650                  {
1651                    // A decay channel has been identified, so execute the DecayIt.
1652                    G4double tempmass = parentNucleus->GetPDGMass();     
1653                    tempprods = theDecayChannel->DecayIt(tempmass);
1654                    weight *= (theDecayChannel->GetBR())*(theDecayTable->entries());
1655                  }
1656              }
1657              else {
1658                tempprods = DoDecay(*parentNucleus);
1659              }
1660              //
1661              // save the secondaries for buffers
1662              //
1663              numberOfSecondaries = tempprods->entries();
1664              currentTime = finalGlobalTime + theDecayTime;
1665              for (index=0; index < numberOfSecondaries; index++) 
1666                {
1667                  asecondaryparticle = tempprods->PopProducts();
1668                  if (asecondaryparticle->GetDefinition()->GetBaryonNumber() < 5){
1669                    pw.push_back(weight);
1670                    ptime.push_back(currentTime);
1671                    secondaryparticles.push_back(asecondaryparticle);
1672                  }
1673                }
1674              //
1675              delete tempprods;
1676             
1677              //end of i loop
1678            }
1679           
1680            // end of n loop
1681          } 
1682        // now deal with the secondaries in the two stl containers
1683        // and submmit them back to the tracking manager
1684        //
1685        totalNumberOfSecondaries = pw.size();
1686        fParticleChangeForRadDecay.SetNumberOfSecondaries(totalNumberOfSecondaries);
1687        for (index=0; index < totalNumberOfSecondaries; index++) 
1688          { 
1689            G4Track* secondary = new G4Track(
1690                                             secondaryparticles[index], ptime[index], currentPosition);
1691            secondary->SetGoodForTrackingFlag();           
1692                        secondary->SetTouchableHandle(theTrack.GetTouchableHandle());
1693            secondary->SetWeight(pw[index]);       
1694            fParticleChangeForRadDecay.AddSecondary(secondary); 
1695          }
1696        //
1697        // make sure the original track is set to stop and its kinematic energy collected
1698        //
1699        //theTrack.SetTrackStatus(fStopButAlive);
1700        //energyDeposit += theParticle->GetKineticEnergy();
1701       
1702      }
1703   
1704      //
1705      // Kill the parent particle.
1706      //
1707      fParticleChangeForRadDecay.ProposeTrackStatus( fStopAndKill ) ;
1708      fParticleChangeForRadDecay.ProposeLocalEnergyDeposit(energyDeposit);
1709      //
1710      fParticleChangeForRadDecay.ProposeGlobalTime( finalGlobalTime );
1711      //
1712      // Reset NumberOfInteractionLengthLeft.
1713      //
1714      ClearNumberOfInteractionLengthLeft();
1715     
1716      return &fParticleChangeForRadDecay ;
1717    }
1718} 
1719
1720////////////////////////////////////////////////////////////////////////////////
1721//
1722//
1723// DoDecay
1724//
1725G4DecayProducts* G4RadioactiveDecay::DoDecay(  G4ParticleDefinition& theParticleDef )
1726{
1727  G4DecayProducts *products = 0;
1728  //
1729  //
1730  // follow the decaytable and generate the secondaries...
1731  //
1732  //
1733#ifdef G4VERBOSE
1734  if (GetVerboseLevel()>0)
1735    {
1736      G4cout<<"Begin of DoDecay..."<<G4endl;
1737    }
1738#endif
1739  G4DecayTable *theDecayTable = theParticleDef.GetDecayTable();
1740  //
1741  // Choose a decay channel.
1742  //
1743#ifdef G4VERBOSE
1744  if (GetVerboseLevel()>0)
1745    {
1746      G4cout <<"Selecte a channel..."<<G4endl;
1747    }
1748#endif
1749  G4VDecayChannel *theDecayChannel = theDecayTable->SelectADecayChannel();
1750  if (theDecayChannel == 0)
1751    {
1752      // Decay channel not found.
1753      //
1754      G4cerr <<"G4RadioactiveDecay::DoIt : can not determine decay channel";
1755      G4cerr <<G4endl;
1756      theDecayTable ->DumpInfo();
1757    }
1758      else
1759    {
1760      //
1761      // A decay channel has been identified, so execute the DecayIt.
1762      //
1763#ifdef G4VERBOSE
1764      if (GetVerboseLevel()>1)
1765        {
1766          G4cerr <<"G4RadioactiveDecay::DoIt : selected decay channel  addr:";
1767          G4cerr <<theDecayChannel <<G4endl;
1768        }
1769#endif
1770     
1771      G4double tempmass = theParticleDef.GetPDGMass();
1772      //
1773     
1774      products = theDecayChannel->DecayIt(tempmass);
1775     
1776    }
1777  return products;
1778
1779}
1780
1781
1782
1783
1784
1785
1786
1787
1788
Note: See TracBrowser for help on using the repository browser.