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

Last change on this file since 1036 was 962, checked in by garnier, 17 years ago

update processes

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