151 using namespace CLHEP;
156 #ifdef G4MULTITHREADED
161 G4int& G4RadioactiveDecay::NumberOfInstances()
163 static G4int numberOfInstances = 0;
164 return numberOfInstances;
170 forceDecayDirection(0.,0.,0.), forceDecayHalfAngle(0.*
deg), dirPath(
""),
175 G4cout <<
"G4RadioactiveDecay constructor: processName = " << processName
180 G4cout <<
" G4RadioactiveDecay is deprecated and will be removed in Geant4 version 11. " <<
G4endl;
181 G4cout <<
" Please replace it with G4RadioactiveDecayBase if you want the unbiased radioactive deacy process." <<
G4endl;
182 G4cout <<
" If you want the general process, with optional biasing, use G4Radioactivation. " <<
G4endl;
196 char* path_var = std::getenv(
"G4RADIOACTIVEDATA");
199 "Environment variable G4RADIOACTIVEDATA is not set");
202 std::ostringstream os;
204 std::ifstream testFile;
205 testFile.open(os.str() );
206 if (!testFile.is_open() )
208 "Environment variable G4RADIOACTIVEDATA is set, but does not point to correct directory");
215 #ifdef G4MULTITHREADED
216 G4AutoLock lk(&G4RadioactiveDecay::radioactiveDecayMutex);
217 NumberOfInstances()++;
253 outFile <<
"The radioactive decay process (G4RadioactiveDecay) handles the\n"
254 <<
"alpha, beta+, beta-, electron capture and isomeric transition\n"
255 <<
"decays of nuclei (G4GenericIon) with masses A > 4.\n"
256 <<
"The required half-lives and decay schemes are retrieved from\n"
257 <<
"the RadioactiveDecay database which was derived from ENSDF.\n";
265 for (DecayTableMap::iterator i =
dkmap->begin(); i !=
dkmap->end(); i++) {
270 #ifdef G4MULTITHREADED
271 G4AutoLock lk(&G4RadioactiveDecay::radioactiveDecayMutex);
272 --NumberOfInstances();
273 if(NumberOfInstances()==0)
275 for (DecayTableMap::iterator i = master_dkmap->begin(); i != master_dkmap->end(); i++) {
278 master_dkmap->clear();
288 if (((
const G4Ions*)(&aParticle))->GetExcitationEnergy() > 0.) {
301 G4int A = ((
const G4Ions*) (&aParticle))->GetAtomicMass();
302 G4int Z = ((
const G4Ions*) (&aParticle))->GetAtomicNumber();
314 DecayTableMap::iterator table_ptr =
dkmap->find(key);
317 if (table_ptr ==
dkmap->end() ) {
319 if(theDecayTable) (*dkmap)[key] = theDecayTable;
321 theDecayTable = table_ptr->second;
324 return theDecayTable;
333 for (
size_t i = 0; i < theLogicalVolumes->size(); i++) {
334 volume=(*theLogicalVolumes)[i];
335 if (volume->
GetName() == aVolume) {
343 }
else if(i == theLogicalVolumes->size()) {
345 ed << aVolume <<
" is not a valid logical volume name. Decay not activated for it."
347 G4Exception(
"G4RadioactiveDecayBase::SelectAVolume()",
"HAD_RDM_300",
359 for (
size_t i = 0; i < theLogicalVolumes->size(); i++){
360 volume=(*theLogicalVolumes)[i];
361 if (volume->
GetName() == aVolume) {
362 std::vector<G4String>::iterator location;
370 ed << aVolume <<
" is not in the list " <<
G4endl;
371 G4Exception(
"G4RadioactiveDecayBase::DeselectAVolume()",
"HAD_RDM_300",
376 G4cout <<
" DeselectVolume: " << aVolume <<
" is removed from list "
379 }
else if (i == theLogicalVolumes->size()) {
381 ed << aVolume <<
" is not a valid logical volume name " <<
G4endl;
382 G4Exception(
"G4RadioactiveDecayBase::SelectAVolume()",
"HAD_RDM_300",
399 for (
size_t i = 0; i < theLogicalVolumes->size(); i++){
400 volume = (*theLogicalVolumes)[i];
448 G4cout <<
"The DecayRate Table for " << aParticleName <<
" is selected."
529 while (t >
SBin[nbin]) {
532 G4Exception(
"G4RadioactiveDecay::ConvolveSourceTimeProfile()",
533 "HAD_RDM_100",
JustWarning,
"While loop count exceeded");
545 for (
G4int i = 0; i < nbin; i++) {
548 convolvedTime +=
SProfile[i] * std::exp((
SBin[i] - t)/tau) *
552 (std::exp(-(t-
SBin[i+1])/tau)-std::exp(-(t-
SBin[i])/tau));
556 convolvedTime -=
SProfile[nbin] * std::expm1((
SBin[nbin] - t)/tau);
559 if (convolvedTime < 0.) {
560 G4cout <<
" Convolved time =: " << convolvedTime <<
" reset to zero! " <<
G4endl;
567 G4cout <<
" Convolved time: " << convolvedTime <<
G4endl;
569 return convolvedTime;
592 G4Exception(
"G4RadioactiveDecay::GetDecayTime()",
"HAD_RDM_100",
613 while ( aDecayTime >
DBin[i] ) {
617 G4Exception(
"G4RadioactiveDecay::GetDecayTimeBin()",
"HAD_RDM_100",
646 G4cout <<
"G4RadioactiveDecay::GetMeanLifeTime() " <<
G4endl;
648 <<
" GeV, Mass: " << theParticle->
GetMass()/
GeV
649 <<
" GeV, Life time: " << theLife/
ns <<
" ns " <<
G4endl;
653 else if (theLife < 0.0) {meanlife =
DBL_MAX;}
654 else {meanlife = theLife;}
657 if (((
const G4Ions*)(theParticleDef))->GetExcitationEnergy() > 0. &&
658 meanlife ==
DBL_MAX) {meanlife = 0.;}
662 G4cout <<
" mean life time: " << meanlife/
s <<
" s " <<
G4endl;
684 G4cout <<
"G4RadioactiveDecay::GetMeanFreePath() " <<
G4endl;
686 <<
" GeV, Mass: " << aMass/
GeV <<
" GeV, tau: " << tau <<
" ns "
697 }
else if (tau < 0.0) {
700 ed <<
"Ion has negative lifetime " << tau
701 <<
" but is not stable. Setting mean free path to DBL_MAX" <<
G4endl;
702 G4Exception(
"G4RadioactiveDecay::GetMeanFreePath()",
"HAD_RDM_011",
709 pathlength =
c_light*tau*betaGamma;
715 G4cout <<
"G4Decay::GetMeanFreePath: "
717 <<
" stops, kinetic energy = "
727 G4cout <<
"mean free path: "<< pathlength/
m <<
" m" <<
G4endl;
764 os <<
"======================================================================="
766 os <<
"====== Radioactive Decay Physics Parameters ========"
768 os <<
"======================================================================="
770 os <<
"Max life time "
772 os <<
"Internal e- conversion flag "
774 os <<
"Stored internal conversion coefficients "
776 os <<
"Enable correlated gamma emission "
778 os <<
"Max 2J for sampling of angular correlations "
780 os <<
"Atomic de-excitation enabled "
781 << emparam->
Fluo() << endline;
782 os <<
"Auger electron emission enabled "
783 << emparam->
Auger() << endline;
784 os <<
"Auger cascade enabled "
786 os <<
"Check EM cuts disabled for atomic de-excitation "
788 os <<
"Use Bearden atomic level energies "
790 os <<
"======================================================================="
807 G4int A = ((
const G4Ions*)(&theParentNucleus))->GetAtomicMass();
808 G4int Z = ((
const G4Ions*)(&theParentNucleus))->GetAtomicNumber();
810 G4double levelEnergy = ((
const G4Ions*)(&theParentNucleus))->GetExcitationEnergy();
812 ((
const G4Ions*)(&theParentNucleus))->GetFloatLevelBase();
814 #ifdef G4MULTITHREADED
815 G4AutoLock lk(&G4RadioactiveDecay::radioactiveDecayMutex);
818 DecayTableMap::iterator master_table_ptr = master_dkmap->find(key);
820 if (master_table_ptr != master_dkmap->end() ) {
821 return master_table_ptr->second;
829 std::ostringstream os;
830 os <<
dirPath <<
"/z" << Z <<
".a" << A <<
'\0';
837 std::ifstream DecaySchemeFile;
838 DecaySchemeFile.open(file);
840 if (DecaySchemeFile.good()) {
843 const G4int nMode = 12;
844 G4double modeTotalBR[nMode] = {0.0};
846 for (
G4int i = 0; i < nMode; i++) {
850 char inputChars[120]={
' '};
871 while (!complete && !DecaySchemeFile.getline(inputChars, 120).eof()) {
874 G4Exception(
"G4RadioactiveDecay::LoadDecayTable()",
"HAD_RDM_100",
879 inputLine = inputChars;
880 inputLine = inputLine.
strip(1);
881 if (inputChars[0] !=
'#' && inputLine.length() != 0) {
882 std::istringstream tmpStream(inputLine);
884 if (inputChars[0] ==
'P') {
887 tmpStream >> recordType >> parentExcitation >> floatingFlag >> dummy;
896 if (floatingLevel !=
noFloat) {
899 if (!floatMatch) found =
false;
908 if (inputLine.length() < 72) {
909 tmpStream >> theDecayMode >> dummy >> decayModeTotal;
910 switch (theDecayMode) {
917 theDecayTable->
Insert(anITChannel);
922 modeTotalBR[1] = decayModeTotal;
break;
924 modeTotalBR[2] = decayModeTotal;
break;
926 modeTotalBR[3] = decayModeTotal;
break;
928 modeTotalBR[4] = decayModeTotal;
break;
930 modeTotalBR[5] = decayModeTotal;
break;
932 modeTotalBR[6] = decayModeTotal;
break;
934 modeTotalBR[7] = decayModeTotal;
break;
936 modeTotalBR[8] = decayModeTotal;
break;
938 modeTotalBR[9] = decayModeTotal;
break;
952 modeTotalBR[10] = decayModeTotal;
break;
954 modeTotalBR[11] = decayModeTotal;
break;
958 G4Exception(
"G4RadioactiveDecay::LoadDecayTable()",
"HAD_RDM_000",
963 if (inputLine.length() < 84) {
964 tmpStream >> theDecayMode >> a >> daughterFloatFlag >> b >>
c;
967 tmpStream >> theDecayMode >> a >> daughterFloatFlag >> b >> c >> betaType;
977 switch (theDecayMode) {
982 daughterFloatLevel, betaType);
985 theDecayTable->
Insert(aBetaMinusChannel);
994 daughterFloatLevel, betaType);
997 theDecayTable->
Insert(aBetaPlusChannel);
1010 theDecayTable->
Insert(aKECChannel);
1023 theDecayTable->
Insert(aLECChannel);
1036 theDecayTable->
Insert(aMECChannel);
1049 theDecayTable->
Insert(aNECChannel);
1058 daughterFloatLevel);
1061 theDecayTable->
Insert(anAlphaChannel);
1070 daughterFloatLevel);
1073 theDecayTable->
Insert(aProtonChannel);
1082 daughterFloatLevel);
1085 theDecayTable->
Insert(aNeutronChannel);
1119 daughterFloatLevel);
1120 theDecayTable->
Insert(aSpontFissChannel);
1128 daughterFloatLevel);
1131 theDecayTable->
Insert(aTritonChannel);
1139 G4Exception(
"G4RadioactiveDecay::LoadDecayTable()",
"HAD_RDM_000",
1157 theNuclearDecayChannel =
static_cast<G4NuclearDecay*
>(theChannel);
1160 if (theDecayMode !=
IT) {
1161 theBR = theChannel->
GetBR();
1162 theChannel->
SetBR(theBR*modeTotalBR[theDecayMode]/modeSumBR[theDecayMode]);
1167 DecaySchemeFile.close();
1169 if (!found && levelEnergy > 0) {
1176 theDecayTable->
Insert(anITChannel);
1183 #ifdef G4MULTITHREADED
1186 return theDecayTable;
1192 if (Z < 1 || A < 2)
G4cout <<
"Z and A not valid!" <<
G4endl;
1194 std::ifstream DecaySchemeFile(filename);
1195 if (DecaySchemeFile) {
1196 G4int ID_ion = A*1000 +
Z;
1199 G4cout <<
"The file " << filename <<
" does not exist!" <<
G4endl;
1206 G4int theG, std::vector<G4double> theCoefficients,
1207 std::vector<G4double> theTaos)
1232 G4int nGeneration = 0;
1234 std::vector<G4double> taos;
1237 std::vector<G4double> Acoeffs;
1240 Acoeffs.push_back(-1.);
1242 G4int A = ((
const G4Ions*)(&theParentNucleus))->GetAtomicMass();
1243 G4int Z = ((
const G4Ions*)(&theParentNucleus))->GetAtomicNumber();
1244 G4double E = ((
const G4Ions*)(&theParentNucleus))->GetExcitationEnergy();
1246 if (tao < 0.) tao = 1
e-100;
1247 taos.push_back(tao);
1281 std::vector<G4double> TP;
1282 std::vector<G4double> RP;
1286 G4int nearestLevelIndex = 0;
1294 const G4int nMode = 12;
1306 G4Exception(
"G4RadioactiveDecay::CalculateChainsFromParent()",
"HAD_RDM_100",
1311 for (j = nS; j < nT; j++) {
1319 G4cout <<
"G4RadioactiveDecay::CalculateChainsFromParent: daughters of ("
1320 << ZP <<
", " << AP <<
", " << EP
1321 <<
") are being calculated, generation = " << nGeneration
1328 aParentNucleus = theIonTable->
GetIon(ZP,AP,EP);
1341 for (
G4int k = 0;
k < nMode;
k++) brs[
k] = 0.0;
1344 for (i = 0; i < parentDecayTable->
entries(); i++) {
1346 theNuclearDecayChannel =
static_cast<G4NuclearDecay*
>(theChannel);
1351 AD = ((
const G4Ions*)(theDaughterNucleus))->GetAtomicMass();
1352 ZD = ((
const G4Ions*)(theDaughterNucleus))->GetAtomicNumber();
1364 summedDecayTable->
Insert(theChannel);
1366 brs[theDecayMode] += theChannel->
GetBR();
1369 brs[theDecayMode] += theChannel->
GetBR();
1372 brs[theDecayMode] += theChannel->
GetBR();
1376 brs[2] = brs[2]+brs[3]+brs[4]+brs[5]+brs[6];
1377 brs[3] = brs[4] = brs[5] = brs[6] = 0.0;
1378 for (i = 0; i < nMode; i++) {
1383 theITChannel =
new G4ITDecay(aParentNucleus, brs[0], 0.0, 0.0,
1386 summedDecayTable->
Insert(theITChannel);
1394 summedDecayTable->
Insert(theBetaMinusChannel);
1402 summedDecayTable->
Insert(theBetaPlusChannel);
1409 summedDecayTable->
Insert(theAlphaChannel);
1416 summedDecayTable->
Insert(theProtonChannel);
1423 summedDecayTable->
Insert(theNeutronChannel);
1428 theFissionChannel =
new G4SFDecay(aParentNucleus, brs[10], 0.*
MeV,
1430 summedDecayTable->
Insert(theFissionChannel);
1436 summedDecayTable->
Insert(theTritonChannel);
1446 for (i = 0; i < summedDecayTable->
entries(); i++){
1448 theNuclearDecayChannel =
static_cast<G4NuclearDecay*
>(theChannel);
1449 theBR = theChannel->
GetBR();
1454 if (theNuclearDecayChannel->
GetDecayMode() ==
IT && nGeneration == 1) {
1456 A = ((
const G4Ions*)(theDaughterNucleus))->GetAtomicMass();
1457 Z = ((
const G4Ions*)(theDaughterNucleus))->GetAtomicNumber();
1458 theDaughterNucleus=theIonTable->
GetIon(Z,A,0.);
1461 aParentNucleus != theDaughterNucleus) {
1465 if (parentDecayTable->
entries() ) {
1466 A = ((
const G4Ions*)(theDaughterNucleus))->GetAtomicMass();
1467 Z = ((
const G4Ions*)(theDaughterNucleus))->GetAtomicNumber();
1468 E = ((
const G4Ions*)(theDaughterNucleus))->GetExcitationEnergy();
1471 if (TaoPlus <= 0.) TaoPlus = 1
e-100;
1481 taos.push_back(TaoPlus);
1487 long double ta1,ta2;
1488 ta2 = (
long double)TaoPlus;
1489 for (k = 0; k < RP.size(); k++){
1490 ta1 = (
long double)TP[k];
1494 theRate = ta1/(ta1-ta2);
1496 theRate = theRate * theBR * RP[
k];
1497 Acoeffs.push_back(theRate);
1504 long double aRate, aRate1;
1506 for (k = 0; k < RP.size(); k++){
1507 ta1 = (
long double)TP[k];
1511 aRate = ta2/(ta1-ta2);
1513 aRate = aRate * (
long double)(theBR * RP[k]);
1517 Acoeffs.push_back(theRate);
1525 delete summedDecayTable;
1530 if (nS == nT) stable =
true;
1560 ed <<
" Could not open file " << filename <<
G4endl;
1561 G4Exception(
"G4RadioactiveDecay::SetSourceTimeProfile()",
"HAD_RDM_001",
1569 while (infile >> bin >> flux) {
1572 G4Exception(
"G4RadioactiveDecay::SetSourceTimeProfile()",
"HAD_RDM_100",
1579 G4Exception(
"G4RadioactiveDecay::SetSourceTimeProfile()",
"HAD_RDM_002",
1607 if (!infile)
G4Exception(
"G4RadioactiveDecay::SetDecayBias()",
"HAD_RDM_003",
1619 while (infile >> bin >> flux ) {
1623 G4Exception(
"G4RadioactiveDecay::SetDecayBias()",
"HAD_RDM_100",
1629 G4Exception(
"G4RadioactiveDecay::SetDecayBias()",
"HAD_RDM_004",
1677 G4cout <<
"G4RadioactiveDecay::DecayIt : "
1679 <<
" is not selected for the RDM"<<
G4endl;
1701 G4cout <<
" G4RadioactiveDecay::DecayIt : "
1703 <<
" is not a valid nucleus for the RDM. "<<
G4endl;
1704 G4cout <<
" Set particle change accordingly. " <<
G4endl;
1717 if (theDecayTable == 0 || theDecayTable->
entries() == 0) {
1722 G4cout <<
" G4RadioactiveDecay::DecayIt : decay table not defined for ";
1724 G4cout <<
" Set particle change to indicate this. " <<
G4endl;
1755 if ( products->
entries() == 1) {
1784 if (temptime < 0.) temptime = 0.;
1785 finalGlobalTime += temptime;
1786 finalLocalTime += temptime;
1789 products->
Boost(ParentEnergy, ParentDirection);
1796 G4cout <<
"G4RadioactiveDecay::DecayIt : Decay vertex :";
1797 G4cout <<
" Time: " <<finalGlobalTime/
ns <<
"[ns]";
1802 G4cout <<
"G4Decay::DecayIt : decay products in Lab. Frame" <<
G4endl;
1807 for (index=0; index < numberOfSecondaries; index++) {
1809 finalGlobalTime, currentPosition);
1818 && index <numberOfSecondaries-1){
1832 G4cout <<
"DecayIt: Variance Reduction version " <<
G4endl;
1845 std::vector<G4double> PT;
1846 std::vector<G4double> PR;
1848 long double decayRate;
1852 G4int numberOfSecondaries;
1853 G4int totalNumberOfSecondaries = 0;
1857 std::vector<G4DynamicParticle*> secondaryparticles;
1858 std::vector<G4double> pw;
1859 std::vector<G4double> ptime;
1875 }
else if (nbin > 1) {
1938 for (
G4int j = 0; j <
G4int(PT.size()); j++) {
1941 decayRate -= PR[j] * (
long double)tauprob;
1953 if (decayRate < 0.0) decayRate = 0.0;
1978 ->AddIsotope(PZ,PA,PE,weight1*decayRate,theTrack.
GetWeight());
1987 parentNucleus = theIonTable->
GetIon(PZ,PA,PE);
1999 if (theDecayChannel == 0) {
2003 G4cout <<
" G4RadioactiveDecay::DoIt : cannot determine decay ";
2004 G4cout <<
" channel for this nucleus; decay as if no biasing active ";
2009 tempprods =
DoDecay(*parentNucleus);
2014 tempprods = theDecayChannel->DecayIt(tempmass);
2015 weight *= (theDecayChannel->GetBR())*(decayTable->
entries());
2018 tempprods =
DoDecay(*parentNucleus);
2022 numberOfSecondaries = tempprods->
entries();
2023 currentTime = finalGlobalTime + theDecayTime;
2024 for (index = 0; index < numberOfSecondaries; index++) {
2027 pw.push_back(weight);
2028 ptime.push_back(currentTime);
2029 secondaryparticles.push_back(asecondaryparticle);
2030 }
else if (((
const G4Ions*)(asecondaryparticle->
GetDefinition()))->GetExcitationEnergy() > 0.
2045 totalNumberOfSecondaries = pw.size();
2047 for (index=0; index < totalNumberOfSecondaries; index++) {
2049 ptime[index], currentPosition);
2086 if (theDecayChannel == 0) {
2090 G4Exception(
"G4RadioactiveDecay::DoDecay",
"HAD_RDM_013",
2096 G4cout <<
"G4RadioactiveDecay::DoIt : selected decay channel address:";
2116 if (0 == products || 0 == products->
entries())
return;
2136 if (daughterType == electron || daughterType == positron ||
2137 daughterType == neutron || daughterType == gamma ||
2138 daughterType == alpha || daughterType == triton || daughterType == proton)
CollimateDecayProduct(daughter);
2145 G4cout <<
"CollimateDecayProduct for daughter "
2176 G4cout <<
" ChooseCollimationDirection returns " << dir <<
G4endl;
2186 std::vector<double>& weights_v,
2187 std::vector<double>& times_v,
2188 std::vector<G4DynamicParticle*>& secondaries_v)
2190 G4double elevel = ((
const G4Ions*)(apartDef))->GetExcitationEnergy();
2194 while (life_time < halflifethreshold && elevel > 0.) {
2201 for (
G4int ind = 0; ind < nb_pevapSecondaries; ind++) {
2202 a_pevap_secondary = pevap_products->
PopProducts();
2206 elevel = ((
const G4Ions*)(secDef))->GetExcitationEnergy();
2210 weights_v.push_back(weight);
2211 times_v.push_back(currentTime);
2212 secondaries_v.push_back(a_pevap_secondary);
2215 weights_v.push_back(weight);
2216 times_v.push_back(currentTime);
2217 secondaries_v.push_back(a_pevap_secondary);