94 const G4double timeThresholdForRadioactiveDecays)
99 G4cout <<
"G4Radioactivation constructor: processName = " << processName
119 theRadioactivityTables.push_back(rTable);
123 halflifethreshold = 1000.*nanosecond;
128 outFile <<
"The G4Radioactivation process performs radioactive decay of\n"
129 <<
"nuclides (G4GenericIon) in biased mode which includes nucleus\n"
130 <<
"duplication, branching ratio biasing, source time convolution\n"
131 <<
"and detector time convolution. It is designed for use in\n"
132 <<
"activation physics.\n"
133 <<
"The required half-lives and decay schemes are retrieved from\n"
134 <<
"the RadioactiveDecay database which was derived from ENSDF.\n";
140 delete theRadioactivationMessenger;
149 for (std::size_t i = 0; i < theParentChainTable.size(); ++i) {
150 if (theParentChainTable[i].GetIonName() == aParticleName)
return true;
161 for (std::size_t i = 0; i < theParentChainTable.size(); ++i) {
162 if (theParentChainTable[i].GetIonName() == aParticleName) {
163 theDecayRateVector = theParentChainTable[i].GetItsRates();
168 G4cout <<
"The DecayRate Table for " << aParticleName <<
" is selected."
185 if ( t > SBin[NSourceBin]) {
191 while (t > SBin[nbin]) {
194 G4Exception(
"G4Radioactivation::ConvolveSourceTimeProfile()",
195 "HAD_RDM_100",
JustWarning,
"While loop count exceeded");
207 for (
G4int i = 0; i < nbin; ++i) {
208 earg = (SBin[i+1] - SBin[i])/tau;
210 convolvedTime += SProfile[i] * std::exp((SBin[i] - t)/tau) *
213 convolvedTime += SProfile[i] *
214 (std::exp(-(t-SBin[i+1])/tau)-std::exp(-(t-SBin[i])/tau));
218 convolvedTime -= SProfile[nbin] * std::expm1((SBin[nbin] - t)/tau);
221 if (convolvedTime < 0.) {
222 G4cout <<
" Convolved time =: " << convolvedTime <<
" reset to zero! " <<
G4endl;
229 G4cout <<
" Convolved time: " << convolvedTime <<
G4endl;
231 return convolvedTime;
250 while (DProfile[i] < rand) {
256 G4Exception(
"G4Radioactivation::GetDecayTime()",
"HAD_RDM_100",
263 decaytime = DBin[i] + rand*(DBin[i+1]-DBin[i]);
266 G4cout <<
" Decay time: " <<decaytime/s <<
"[s]" <<
G4endl;
277 while (aDecayTime > DBin[i] ) {
281 G4Exception(
"G4Radioactivation::GetDecayTimeBin()",
"HAD_RDM_100",
310 G4int theG, std::vector<G4double>& theCoefficients,
311 std::vector<G4double>& theTaos)
315 ratesToDaughter.
SetZ(theZ);
316 ratesToDaughter.
SetA(theA);
317 ratesToDaughter.
SetE(theE);
320 ratesToDaughter.
SetTaos(theTaos);
334 theDecayRateVector.clear();
336 G4int nGeneration = 0;
338 std::vector<G4double> taos;
341 std::vector<G4double> Acoeffs;
344 Acoeffs.push_back(-1.);
346 const G4Ions* ion =
static_cast<const G4Ions*
>(&theParentNucleus);
351 if (tao < 0.) tao = 1e-100;
360 theDecayRateVector.push_back(ratesToDaughter);
385 std::vector<G4double> TP;
386 std::vector<G4double> RP;
390 G4int nearestLevelIndex = 0;
407 G4Exception(
"G4Radioactivation::CalculateChainsFromParent()",
"HAD_RDM_100",
412 for (j = nS; j < nT; ++j) {
414 ZP = theDecayRateVector[j].GetZ();
415 AP = theDecayRateVector[j].GetA();
416 EP = theDecayRateVector[j].GetE();
417 RP = theDecayRateVector[j].GetDecayRateC();
418 TP = theDecayRateVector[j].GetTaos();
420 G4cout <<
"G4RadioactiveDecay::CalculateChainsFromParent: daughters of ("
421 << ZP <<
", " << AP <<
", " << EP
422 <<
") are being calculated, generation = " << nGeneration
429 aParentNucleus = theIonTable->
GetIon(ZP,AP,EP);
431 if (
nullptr == parentDecayTable) {
continue; }
443 for (
G4int k = 0; k < nMode; ++k) brs[k] = 0.0;
446 for (
G4int i = 0; i < parentDecayTable->
entries(); ++i) {
448 theNuclearDecayChannel =
static_cast<G4NuclearDecay*
>(theChannel);
453 ZD = ((
const G4Ions*)(theDaughterNucleus))->GetAtomicNumber();
462 if ((std::abs(daughterExcitation - nearestEnergy) <
levelTolerance) && (std::abs(daughterExcitation - nearestEnergy) >
DBL_EPSILON)) {
466 if (levelManager->
LifeTime(nearestLevelIndex)*ns >= halflifethreshold){
468 summedDecayTable->
Insert(theChannel);
470 brs[theDecayMode] += theChannel->
GetBR();
473 brs[theDecayMode] += theChannel->
GetBR();
476 brs[theDecayMode] += theChannel->
GetBR();
483 for (
G4int i = 0; i < nMode; ++i) {
488 theITChannel =
new G4ITDecay(aParentNucleus, brs[
IT], 0.0, 0.0);
490 summedDecayTable->
Insert(theITChannel);
498 summedDecayTable->
Insert(theBetaMinusChannel);
506 summedDecayTable->
Insert(theBetaPlusChannel);
513 summedDecayTable->
Insert(theAlphaChannel);
520 summedDecayTable->
Insert(theProtonChannel);
527 summedDecayTable->
Insert(theNeutronChannel);
534 summedDecayTable->
Insert(theFissionChannel);
565 summedDecayTable->
Insert(theTritonChannel);
576 for (
G4int i = 0; i < summedDecayTable->
entries(); ++i){
578 theNuclearDecayChannel =
static_cast<G4NuclearDecay*
>(theChannel);
579 theBR = theChannel->
GetBR();
584 if (theNuclearDecayChannel->
GetDecayMode() ==
IT && nGeneration == 1) {
586 A = ((
const G4Ions*)(theDaughterNucleus))->GetAtomicMass();
587 Z = ((
const G4Ions*)(theDaughterNucleus))->GetAtomicNumber();
588 theDaughterNucleus=theIonTable->
GetIon(Z,
A,0.);
591 aParentNucleus != theDaughterNucleus) {
594 if (
nullptr != parentDecayTable && parentDecayTable->
entries() > 0) {
595 A = ((
const G4Ions*)(theDaughterNucleus))->GetAtomicMass();
596 Z = ((
const G4Ions*)(theDaughterNucleus))->GetAtomicNumber();
597 E = ((
const G4Ions*)(theDaughterNucleus))->GetExcitationEnergy();
600 if (TaoPlus <= 0.) TaoPlus = 1e-100;
610 taos.push_back(TaoPlus);
617 ta2 = (
long double)TaoPlus;
618 for (k = 0; k < RP.size(); ++k){
619 ta1 = (
long double)TP[k];
623 theRate = ta1/(ta1-ta2);
625 theRate = theRate * theBR * RP[k];
626 Acoeffs.push_back(theRate);
633 long double aRate, aRate1;
635 for (k = 0; k < RP.size(); ++k){
636 ta1 = (
long double)TP[k];
640 aRate = ta2/(ta1-ta2);
642 aRate = aRate * (
long double)(theBR * RP[k]);
646 Acoeffs.push_back(theRate);
648 theDecayRateVector.push_back(ratesToDaughter);
654 delete summedDecayTable;
659 if (nS == nT) stable =
true;
674 theParentChainTable.push_back(chainsFromParent);
686 std::ifstream infile ( filename, std::ios::in );
689 ed <<
" Could not open file " << filename <<
G4endl;
690 G4Exception(
"G4Radioactivation::SetSourceTimeProfile()",
"HAD_RDM_001",
698 while (infile >> bin >> flux) {
701 G4Exception(
"G4Radioactivation::SetSourceTimeProfile()",
"HAD_RDM_100",
707 if (NSourceBin > 99) {
708 G4Exception(
"G4Radioactivation::SetSourceTimeProfile()",
"HAD_RDM_002",
712 SBin[NSourceBin] = bin * s;
713 SProfile[NSourceBin] = flux;
722 G4cout <<
" Source Timeprofile Nbin = " << NSourceBin <<
G4endl;
735 std::ifstream infile(filename, std::ios::in);
736 if (!infile)
G4Exception(
"G4Radioactivation::SetDecayBias()",
"HAD_RDM_001",
743 theRadioactivityTables.clear();
748 while (infile >> bin >> flux ) {
752 G4Exception(
"G4Radioactivation::SetDecayBias()",
"HAD_RDM_100",
757 if (NDecayBin > 99) {
758 G4Exception(
"G4Radioactivation::SetDecayBias()",
"HAD_RDM_002",
761 DBin[NDecayBin] = bin * s;
762 DProfile[NDecayBin] = flux;
764 decayWindows[NDecayBin] = dWindows;
767 theRadioactivityTables.push_back(rTable);
771 for ( i = 1; i<= NDecayBin; ++i) DProfile[i] += DProfile[i-1];
772 for ( i = 0; i<= NDecayBin; ++i) DProfile[i] /= DProfile[NDecayBin];
781 G4cout <<
" Decay Bias Profile Nbin = " << NDecayBin <<
G4endl;
806 G4cout <<
"G4RadioactiveDecay::DecayIt : "
808 <<
" is not selected for the RDM"<<
G4endl;
830 G4cout <<
"G4RadioactiveDecay::DecayIt : "
832 <<
" is not an ion or is outside (Z,A) limits set for the decay. "
833 <<
" Set particle change accordingly. "
848 if (theDecayTable ==
nullptr || theDecayTable->
entries() == 0) {
853 G4cout <<
"G4RadioactiveDecay::DecayIt : "
854 <<
"decay table not defined for "
856 <<
". Set particle change accordingly. "
895 std::vector<G4double> PT;
896 std::vector<G4double> PR;
898 long double decayRate;
901 G4int numberOfSecondaries;
902 G4int totalNumberOfSecondaries = 0;
906 std::vector<G4DynamicParticle*> secondaryparticles;
907 std::vector<G4double> pw;
908 std::vector<G4double> ptime;
913 for (
G4int n = 0; n < NSplit; ++n) {
922 weight1 = 1./DProfile[nbin-1]
923 *(DBin[nbin]-DBin[nbin-1])/NSplit;
924 }
else if (nbin > 1) {
926 weight1 = 1./(DProfile[nbin]-DProfile[nbin-2])
927 *(DBin[nbin]-DBin[nbin-1])/NSplit;
935 for (i = 0; i < theDecayRateVector.size(); ++i) {
936 PZ = theDecayRateVector[i].GetZ();
937 PA = theDecayRateVector[i].GetA();
938 PE = theDecayRateVector[i].GetE();
939 PT = theDecayRateVector[i].GetTaos();
940 PR = theDecayRateVector[i].GetDecayRateC();
988 for (
G4int j = 0; j <
G4int(PT.size() ); ++j) {
990 decayRate -= PR[j] * (
long double)taotime;
1002 if (decayRate < 0.0) decayRate = 0.0;
1011 theRadioactivityTables[decayWindows[nbin-1]]
1012 ->AddIsotope(PZ,PA,PE,weight1*decayRate,theTrack.
GetWeight());
1021 parentNucleus = theIonTable->
GetIon(PZ,PA,PE);
1031 if (
nullptr != decayTable) {
1036 if (theDecayChannel ==
nullptr) {
1040 G4cout <<
" G4RadioactiveDecay::DoIt : cannot determine decay channel ";
1041 G4cout <<
" for this nucleus; decay as if no biasing active. ";
1043 if (
nullptr != decayTable) { decayTable ->
DumpInfo(); }
1046 tempprods =
DoDecay(*parentNucleus, theDecayTable);
1050 tempprods = theDecayChannel->
DecayIt(tempmass);
1051 weight *= (theDecayChannel->
GetBR())*(decayTable->
entries());
1054 tempprods =
DoDecay(*parentNucleus, theDecayTable);
1058 numberOfSecondaries = tempprods->
entries();
1059 currentTime = finalGlobalTime + theDecayTime;
1060 for (index = 0; index < numberOfSecondaries; ++index) {
1063 pw.push_back(weight);
1064 ptime.push_back(currentTime);
1065 secondaryparticles.push_back(asecondaryparticle);
1069 ->GetExcitationEnergy() > 0. && weight > 0.) {
1072 ptime,secondaryparticles);
1082 totalNumberOfSecondaries = (
G4int)pw.size();
1084 for (index=0; index < totalNumberOfSecondaries; ++index) {
1086 ptime[index], currentPosition);
1110 std::vector<double>& weights_v,
1111 std::vector<double>& times_v,
1112 std::vector<G4DynamicParticle*>& secondaries_v)
1114 G4double elevel=((
const G4Ions*)(apartDef))->GetExcitationEnergy();
1118 while (life_time < halflifethreshold && elevel > 0.) {
1125 for (
G4int ind = 0; ind < nb_pevapSecondaries; ind++) {
1130 elevel = ((
const G4Ions*)(secDef))->GetExcitationEnergy();
1134 weights_v.push_back(weight);
1135 times_v.push_back(currentTime);
1136 secondaries_v.push_back(a_pevap_secondary);
1139 weights_v.push_back(weight);
1140 times_v.push_back(currentTime);
1141 secondaries_v.push_back(a_pevap_secondary);
1146 delete pevap_products;
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
@ G4RadioactiveDecayModeSize
G4GLOB_DLL std::ostream G4cout
G4DynamicParticle * PopProducts()
G4VDecayChannel * GetDecayChannel(G4int index) const
void Insert(G4VDecayChannel *aChannel)
G4ParticleDefinition * GetDefinition() const
void SetupDecay(const G4ParticleDefinition *)
G4DecayProducts * DecayIt(G4double) override
G4ParticleDefinition * GetIon(G4int Z, G4int A, G4int lvl=0)
G4double GetExcitationEnergy() const
std::size_t NearestLevelIndex(const G4double energy, const std::size_t index=0) const
std::size_t NumberOfTransitions() const
G4double LifeTime(const std::size_t i) const
G4double NearestLevelEnergy(const G4double energy, const std::size_t index=0) const
const G4String & GetName() const
G4RadioactiveDecayMode GetDecayMode() const
G4double GetDaughterExcitation() const
G4ParticleDefinition * GetDaughterNucleus()
const G4LevelManager * GetLevelManager(G4int Z, G4int A)
static G4NuclearLevelData * GetInstance()
void Initialize(const G4Track &) final
void ProposeLocalTime(G4double t)
G4bool GetPDGStable() const
G4int GetAtomicNumber() const
G4double GetPDGMass() const
G4int GetAtomicMass() const
G4int GetBaryonNumber() const
G4double GetPDGLifeTime() const
const G4String & GetParticleName() const
G4IonTable * GetIonTable() const
static G4ParticleTable * GetParticleTable()
G4int GetDecayTimeBin(const G4double aDecayTime)
void AddDeexcitationSpectrumForBiasMode(G4ParticleDefinition *apartDef, G4double weight, G4double currenTime, std::vector< double > &weights_v, std::vector< double > ×_v, std::vector< G4DynamicParticle * > &secondaries_v)
G4bool IsRateTableReady(const G4ParticleDefinition &)
void SetDecayBias(const G4String &filename)
G4double GetMeanLifeTime(const G4Track &theTrack, G4ForceCondition *condition) override
G4double ConvolveSourceTimeProfile(const G4double, const G4double)
void CalculateChainsFromParent(const G4ParticleDefinition &)
~G4Radioactivation() override
G4VParticleChange * DecayIt(const G4Track &theTrack, const G4Step &theStep) override
G4Radioactivation(const G4String &processName="Radioactivation", const G4double timeThresholdForRadioactiveDecays=-1.0)
void SetDecayRate(G4int, G4int, G4double, G4int, std::vector< G4double > &, std::vector< G4double > &)
void ProcessDescription(std::ostream &outFile) const override
void SetSourceTimeProfile(const G4String &filename)
void GetChainsFromParent(const G4ParticleDefinition &)
void SetIonName(G4String name)
void SetItsRates(G4RadioactiveDecayRates arate)
void SetE(G4double value)
void SetTaos(std::vector< G4double > value)
void SetDecayRateC(std::vector< G4double > value)
void SetGeneration(G4int value)
G4bool IsApplicable(const G4ParticleDefinition &) override
std::vector< G4String > ValidVolumes
G4DecayProducts * DoDecay(const G4ParticleDefinition &, G4DecayTable *)
void DecayAnalog(const G4Track &theTrack, G4DecayTable *)
G4DecayTable * GetDecayTable(const G4ParticleDefinition *)
static const G4double levelTolerance
G4ParticleChangeForRadDecay fParticleChangeForRadDecay
G4double GetMeanLifeTime(const G4Track &theTrack, G4ForceCondition *condition) override
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
const G4DynamicParticle * GetDynamicParticle() const
const G4TouchableHandle & GetTouchableHandle() const
void SetGoodForTrackingFlag(G4bool value=true)
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()