103std::map<G4int, G4String>* G4RadioactiveDecay::theUserRDataFiles =
nullptr;
104G4String G4RadioactiveDecay::dirPath =
"";
114 fThresholdForVeryLongDecayTime( 1.0*
CLHEP::year )
117 G4cout <<
"G4RadioactiveDecay constructor: processName = " << processName
127 if (dirPath.empty()) {
129 if (
nullptr == path_var) {
131 "Environment variable G4RADIOACTIVEDATA is not set");
134 std::ostringstream os;
135 os << dirPath <<
"/z1.a3";
136 std::ifstream testFile;
137 testFile.open(os.str() );
138 if ( !testFile.is_open() )
140 "Environment variable G4RADIOACTIVEDATA is set, but does not point to correct directory");
153 if (
nullptr == theUserRDataFiles) {
154 theUserRDataFiles =
new std::map<G4int, G4String>;
170 if ( timeThreshold > 0.0 || timeThresholdBis > 0.0 ) {
171 if ( timeThreshold > timeThresholdBis ) timeThresholdBis = timeThreshold;
172 fThresholdForVeryLongDecayTime = timeThresholdBis;
180 return DecayIt(theTrack, theStep);
187 return DecayIt(theTrack, theStep);
193 outFile <<
"The radioactive decay process (G4RadioactiveDecay) handles the\n"
194 <<
"alpha, beta+, beta-, electron capture and isomeric transition\n"
195 <<
"decays of nuclei (G4GenericIon) with masses A > 4.\n"
196 <<
"The required half-lives and decay schemes are retrieved from\n"
197 <<
"the RadioactiveDecay database which was derived from ENSDF.\n";
216 delete theUserRDataFiles;
217 theUserRDataFiles =
nullptr;
226 if (pname ==
"GenericIon" || pname ==
"triton") {
return true; }
228 const G4Ions* p =
dynamic_cast<const G4Ions*
>(&aParticle);
229 if (
nullptr == p) {
return false; }
236 if (lifeTime < 0.0 || lifeTime > fThresholdForVeryLongDecayTime) {
245 Z > theNucleusLimits.
GetZMax() || Z < theNucleusLimits.
GetZMin()) {
261 const G4Ions* ion =
dynamic_cast<const G4Ions*
>(aNucleus);
262 if (
nullptr != ion) {
266 theDecayTable = ptr->second;
268 return theDecayTable;
276 volume = theLogicalVolumes->
GetVolume(aVolume);
277 if (volume !=
nullptr)
284 G4cout <<
" Radioactive decay applied to " << aVolume <<
G4endl;
289 ed << aVolume <<
" is not a valid logical volume name."
290 <<
" Decay not activated for it."
292 G4Exception(
"G4RadioactiveDecay::SelectAVolume()",
"HAD_RDM_300",
302 volume = theLogicalVolumes->
GetVolume(aVolume);
303 if (volume !=
nullptr)
312 G4cout <<
" G4RadioactiveDecay::DeselectAVolume: " << aVolume
313 <<
" is removed from list " <<
G4endl;
318 ed << aVolume <<
" is not in the list. No action taken." <<
G4endl;
319 G4Exception(
"G4RadioactiveDecay::DeselectAVolume()",
"HAD_RDM_300",
326 ed << aVolume <<
" is not a valid logical volume name. No action taken."
328 G4Exception(
"G4RadioactiveDecay::DeselectAVolume()",
"HAD_RDM_300",
343 for (std::size_t i = 0; i < theLogicalVolumes->size(); ++i){
344 volume = (*theLogicalVolumes)[i];
378 if (!
IsApplicable(*theParticleDef)) {
return meanlife; }
382 G4cout <<
"G4RadioactiveDecay::GetMeanLifeTime() for "
385 <<
" Mass(GeV)=" << theParticleDef->
GetPDGMass()/CLHEP::GeV
386 <<
" LifeTime(ns)=" << theLife/CLHEP::ns <<
G4endl;
389 if (theLife >= 0.0 && theLife <= fThresholdForVeryLongDecayTime) {
394 const G4Ions* ion =
dynamic_cast<const G4Ions*
>(theParticleDef);
402 G4cout <<
"G4RadioactiveDecay::GetMeanLifeTime: "
403 << meanlife/CLHEP::s <<
" second " <<
G4endl;
421 if (lifeTime > 0.0 && lifeTime <
DBL_MAX) {
430 G4cout <<
"G4RadioactiveDecay::GetMeanFreePath() for "
433 <<
" lifeTime(ns)=" << lifeTime
434 <<
" mean free path(cm)=" << res/CLHEP::cm <<
G4endl;
448 if (isInitialised) {
return; }
449 isInitialised =
true;
477 G4long prec = os.precision(5);
478 os <<
"======================================================================"
480 os <<
"====== Radioactive Decay Physics Parameters ======="
482 os <<
"======================================================================"
484 os <<
"min MeanLife (from G4NuclideTable) "
485 <<
G4BestUnit(minMeanLife,
"Time") << endline;
486 os <<
"Max life time (from G4DeexPrecoParameters) "
488 os <<
"Internal e- conversion flag "
490 os <<
"Stored internal conversion coefficients "
492 os <<
"Enabled atomic relaxation mode "
493 << applyARM << endline;
494 os <<
"Enable correlated gamma emission "
496 os <<
"Max 2J for sampling of angular correlations "
498 os <<
"Atomic de-excitation enabled "
499 << emparam->
Fluo() << endline;
500 os <<
"Auger electron emission enabled "
501 << emparam->
Auger() << endline;
502 os <<
"Check EM cuts disabled for atomic de-excitation "
504 os <<
"Use Bearden atomic level energies "
506 os <<
"Use ANSTO fluorescence model "
508 os <<
"Threshold for very long decay time at rest "
509 <<
G4BestUnit(fThresholdForVeryLongDecayTime,
"Time") << endline;
510 os <<
"======================================================================"
530 return dtptr->second;
546 auto ptr = theUserRDataFiles->find(ke);
547 if (ptr != theUserRDataFiles->end()) {
550 std::ostringstream os;
551 os << dirPath <<
"/z" << Z <<
".a" <<
A <<
'\0';
558 std::ifstream DecaySchemeFile;
559 DecaySchemeFile.open(file);
561 if (DecaySchemeFile.good()) {
565 G4double modeTotalBR[nMode] = {0.0};
567 for (
G4int i = 0; i < nMode; ++i) {
571 char inputChars[120]={
' '};
593 while (!complete && !DecaySchemeFile.getline(inputChars, 120).eof()) {
596 G4Exception(
"G4RadioactiveDecay::LoadDecayTable()",
"HAD_RDM_100",
601 inputLine = inputChars;
602 G4StrUtil::rstrip(inputLine);
603 if (inputChars[0] !=
'#' && inputLine.length() != 0) {
604 std::istringstream tmpStream(inputLine);
606 if (inputChars[0] ==
'P') {
609 tmpStream >> recordType >> parentExcitation >> floatingFlag >> dummy;
617 found = (std::abs(parentExcitation*keV - levelEnergy) <
levelTolerance);
618 if (floatingLevel !=
noFloat) {
621 if (!floatMatch) found =
false;
630 if (inputLine.length() < 72) {
631 tmpStream >> theDecayMode >> dummy >> decayModeTotal;
633 switch (theDecayMode) {
637 theDecayTable->
Insert(anITChannel);
641 modeTotalBR[
BetaMinus] = decayModeTotal;
break;
643 modeTotalBR[
BetaPlus] = decayModeTotal;
break;
645 modeTotalBR[
KshellEC] = decayModeTotal;
break;
647 modeTotalBR[
LshellEC] = decayModeTotal;
break;
649 modeTotalBR[
MshellEC] = decayModeTotal;
break;
651 modeTotalBR[
NshellEC] = decayModeTotal;
break;
653 modeTotalBR[
Alpha] = decayModeTotal;
break;
655 modeTotalBR[
Proton] = decayModeTotal;
break;
657 modeTotalBR[
Neutron] = decayModeTotal;
break;
659 modeTotalBR[
SpFission] = decayModeTotal;
break;
673 modeTotalBR[
Triton] = decayModeTotal;
break;
677 G4Exception(
"G4RadioactiveDecay::LoadDecayTable()",
"HAD_RDM_000",
682 if (inputLine.length() < 84) {
683 tmpStream >> theDecayMode >> a >> daughterFloatFlag >> b >> c;
686 tmpStream >> theDecayMode >> a >> daughterFloatFlag >> b >> c >> betaType;
696 switch (theDecayMode) {
701 daughterFloatLevel, betaType);
703 theDecayTable->
Insert(aBetaMinusChannel);
712 daughterFloatLevel, betaType);
714 theDecayTable->
Insert(aBetaPlusChannel);
725 aKECChannel->
SetARM(applyARM);
726 theDecayTable->
Insert(aKECChannel);
737 aLECChannel->
SetARM(applyARM);
738 theDecayTable->
Insert(aLECChannel);
749 aMECChannel->
SetARM(applyARM);
750 theDecayTable->
Insert(aMECChannel);
761 aNECChannel->
SetARM(applyARM);
762 theDecayTable->
Insert(aNECChannel);
773 theDecayTable->
Insert(anAlphaChannel);
774 modeSumBR[
Alpha] += b;
784 theDecayTable->
Insert(aProtonChannel);
795 theDecayTable->
Insert(aNeutronChannel);
803 new G4SFDecay(theIon, b, c*MeV, a*MeV, daughterFloatLevel);
804 theDecayTable->
Insert(aSpontFissChannel);
842 new G4TritonDecay(theIon, b, c*MeV, a*MeV, daughterFloatLevel);
843 theDecayTable->
Insert(aTritonChannel);
851 G4Exception(
"G4RadioactiveDecay::LoadDecayTable()",
"HAD_RDM_000",
869 theNuclearDecayChannel =
static_cast<G4NuclearDecay*
>(theChannel);
872 if (theDecayMode !=
IT) {
873 theBR = theChannel->
GetBR();
874 theChannel->
SetBR(theBR*modeTotalBR[theDecayMode]/modeSumBR[theDecayMode]);
879 DecaySchemeFile.close();
881 if (!found && levelEnergy > 0) {
885 theDecayTable->
Insert(anITChannel);
895 return theDecayTable;
901 if (Z < 1 ||
A < 2)
G4cout <<
"Z and A not valid!" <<
G4endl;
903 std::ifstream DecaySchemeFile(filename);
904 if (DecaySchemeFile) {
905 G4int ID_ion =
A*1000 + Z;
906 (*theUserRDataFiles)[ID_ion] = filename;
909 ed << filename <<
" does not exist! " <<
G4endl;
910 G4Exception(
"G4RadioactiveDecay::AddUserDecayDataFile()",
"HAD_RDM_001",
936 G4cout <<
"G4RadioactiveDecay::DecayIt : "
938 <<
" is not selected for the RDM"<<
G4endl;
940 G4cout <<
" The Valid volumes are: ";
957 if ( theDecayTable ==
nullptr || theDecayTable->
entries() == 0) {
961 G4cout <<
"G4RadioactiveDecay::DecayIt : "
963 <<
" is outside (Z,A) limits set for the decay or has no decays."
994 if (
nullptr == products || products->
entries() == 1) {
1027 if (temptime < 0.) temptime = 0.;
1028 finalGlobalTime += temptime;
1029 finalLocalTime += temptime;
1042 if ( finalGlobalTime > fThresholdForVeryLongDecayTime ) {
1051 products->
Boost(ParentEnergy, ParentDirection);
1058 G4cout <<
"G4RadioactiveDecay::DecayAnalog: Decay vertex :";
1059 G4cout <<
" Time: " << finalGlobalTime/ns <<
"[ns]";
1064 G4cout <<
"G4Decay::DecayIt : decay products in Lab. Frame" <<
G4endl;
1070 G4int modelID = modelID_forIT + 10*theRadDecayMode;
1071 const G4int modelID_forAtomicRelaxation =
1073 for (
G4int index = 0; index < numberOfSecondaries; ++index ) {
1079 if ( theRadDecayMode ==
IT && index > 0 ) {
1080 if ( index == numberOfSecondaries-1 ) {
1086 index < numberOfSecondaries-1 ) {
1119 if (theDecayChannel ==
nullptr) {
1123 G4Exception(
"G4RadioactiveDecay::DoDecay",
"HAD_RDM_013",
1129 G4cout <<
"G4RadioactiveDecay::DoIt : selected decay channel addr: "
1130 << theDecayChannel <<
G4endl;
1133 theRadDecayMode =
static_cast<G4NuclearDecay*
>(theDecayChannel)->GetDecayMode();
1136 if (theRadDecayMode ==
IT) {
1155 if (origin == forceDecayDirection)
return;
1156 if (180.*deg == forceDecayHalfAngle)
return;
1157 if (0 == products || 0 == products->
entries())
return;
1177 if (daughterType == electron || daughterType == positron ||
1178 daughterType == neutron || daughterType == gamma ||
1179 daughterType == alpha || daughterType == triton || daughterType == proton) {
1188 G4cout <<
"CollimateDecayProduct for daughter "
1201 if (origin == forceDecayDirection)
return origin;
1202 if (forceDecayHalfAngle == 180.*deg)
return origin;
1207 if (forceDecayHalfAngle > 0.) {
1210 G4double cosMin = std::cos(forceDecayHalfAngle);
1219 G4cout <<
" ChooseCollimationDirection returns " << dir <<
G4endl;
const char * G4FindDataDir(const char *)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
std::map< G4String, G4DecayTable * > DecayTableMap
@ G4RadioactiveDecayModeSize
std::map< G4String, G4DecayTable * > DecayTableMap
#define G4MUTEX_INITIALIZER
G4GLOB_DLL std::ostream G4cout
static G4Alpha * Definition()
G4DynamicParticle * PopProducts()
void Boost(G4double totalEnergy, const G4ThreeVector &momentumDirection)
G4VDecayChannel * GetDecayChannel(G4int index) const
void Insert(G4VDecayChannel *aChannel)
G4VDecayChannel * SelectADecayChannel(G4double parentMass=-1.)
G4bool CorrelatedGamma() const
G4bool StoreICLevelData() const
G4double GetMaxLifeTime() const
G4bool GetInternalConversionFlag() const
void SetMomentumDirection(const G4ThreeVector &aDirection)
const G4ThreeVector & GetMomentumDirection() const
const G4ParticleDefinition * GetParticleDefinition() const
G4ParticleDefinition * GetDefinition() const
G4double GetKineticEnergy() const
G4double GetTotalEnergy() const
void SetARM(G4bool onoff)
static G4Electron * Definition()
static G4EmParameters * Instance()
G4bool DeexcitationIgnoreCut() const
static G4Gamma * Definition()
static G4HadronicParameters * Instance()
G4double GetTimeThresholdForRadioactiveDecay() const
void RegisterExtraProcess(G4VProcess *)
void RegisterParticleForExtraProcess(G4VProcess *, const G4ParticleDefinition *)
static G4HadronicProcessStore * Instance()
void PrintInfo(const G4ParticleDefinition *)
void SetupDecay(const G4ParticleDefinition *)
void SetARM(G4bool onoff)
G4DecayProducts * DecayIt(G4double) override
G4double GetExcitationEnergy() const
G4Ions::G4FloatLevelBase GetFloatLevelBase() const
static G4Ions::G4FloatLevelBase FloatLevelBase(char flbChar)
G4LogicalVolume * GetVolume(const G4String &name, G4bool verbose=true, G4bool reverseSearch=false) const
static G4LogicalVolumeStore * GetInstance()
const G4String & GetName() const
static G4Neutron * Definition()
G4RadioactiveDecayMode GetDecayMode() const
G4DeexPrecoParameters * GetParameters()
static G4NuclearLevelData * GetInstance()
G4double GetMeanLifeThreshold()
static G4NuclideTable * GetInstance()
void Initialize(const G4Track &) final
void ProposeLocalTime(G4double t)
G4int GetAtomicNumber() const
G4double GetPDGMass() const
G4int GetAtomicMass() const
G4double GetPDGLifeTime() const
const G4String & GetParticleName() const
void RDMForced(G4bool) override
void SetICM(G4bool) override
void Initialise() override
static G4int GetModelID(const G4int modelIndex)
static G4Positron * Definition()
static G4Proton * Definition()
G4DecayTable * LoadDecayTable(const G4Ions *)
G4double GetMeanFreePath(const G4Track &theTrack, G4double previousStepSize, G4ForceCondition *condition) override
void AddUserDecayDataFile(G4int Z, G4int A, const G4String &filename)
void SelectAVolume(const G4String &aVolume)
G4RadioactiveDecayMessenger * theRadioactiveDecayMessenger
void StreamInfo(std::ostream &os, const G4String &endline)
G4bool IsApplicable(const G4ParticleDefinition &) override
G4VParticleChange * AtRestDoIt(const G4Track &theTrack, const G4Step &theStep) override
static DecayTableMap * master_dkmap
std::vector< G4String > ValidVolumes
~G4RadioactiveDecay() override
void ProcessDescription(std::ostream &outFile) const override
G4VParticleChange * PostStepDoIt(const G4Track &theTrack, const G4Step &theStep) override
G4DecayProducts * DoDecay(const G4ParticleDefinition &, G4DecayTable *)
void CollimateDecayProduct(G4DynamicParticle *product)
void DecayAnalog(const G4Track &theTrack, G4DecayTable *)
G4DecayTable * GetDecayTable(const G4ParticleDefinition *)
static const G4double levelTolerance
G4ParticleChangeForRadDecay fParticleChangeForRadDecay
G4ThreeVector ChooseCollimationDirection() const
virtual G4VParticleChange * DecayIt(const G4Track &theTrack, const G4Step &theStep)
G4double GetMeanLifeTime(const G4Track &theTrack, G4ForceCondition *condition) override
void BuildPhysicsTable(const G4ParticleDefinition &) override
void DeselectAllVolumes()
void DeselectAVolume(const G4String &aVolume)
void CollimateDecay(G4DecayProducts *products)
G4PhotonEvaporation * photonEvaporation
G4RadioactiveDecay(const G4String &processName="RadioactiveDecay", const G4double timeThreshold=-1.0)
G4TrackStatus GetTrackStatus() const
G4double GetVelocity() const
const G4ParticleDefinition * GetParticleDefinition() const
G4VPhysicalVolume * GetVolume() const
G4double GetWeight() const
void SetWeight(G4double aValue)
const G4ThreeVector & GetPosition() const
void SetTouchableHandle(const G4TouchableHandle &apValue)
G4double GetGlobalTime() const
G4double GetLocalTime() const
G4ParticleDefinition * GetDefinition() const
const G4DynamicParticle * GetDynamicParticle() const
const G4TouchableHandle & GetTouchableHandle() const
G4double GetKineticEnergy() const
void SetCreatorModelID(const G4int id)
void SetGoodForTrackingFlag(G4bool value=true)
static G4Triton * Definition()
void SetBR(G4double value)
virtual G4DecayProducts * DecayIt(G4double parentMass=-1.0)=0
void ProposeTrackStatus(G4TrackStatus status)
void ProposeWeight(G4double finalWeight)
void AddSecondary(G4Track *aSecondary)
void ProposeLocalEnergyDeposit(G4double anEnergyPart)
void SetNumberOfSecondaries(G4int totSecondaries)
G4LogicalVolume * GetLogicalVolume() const
G4int GetVerboseLevel() const
void ClearNumberOfInteractionLengthLeft()
void SetProcessSubType(G4int)
G4VParticleChange * pParticleChange