37 #include "RConfigure.h"
52 static const Int_t gMaxElem = 110;
53 static const Int_t gMaxLevel = 8;
54 static const Int_t gMaxDecay = 15;
56 static const char gElName[gMaxElem][3] = {
57 "H ",
"He",
"Li",
"Be",
"B ",
"C ",
"N ",
"O ",
"F ",
"Ne",
"Na",
"Mg",
58 "Al",
"Si",
"P ",
"S ",
"Cl",
"Ar",
"K ",
"Ca",
"Sc",
"Ti",
"V ",
"Cr",
59 "Mn",
"Fe",
"Co",
"Ni",
"Cu",
"Zn",
"Ga",
"Ge",
"As",
"Se",
"Br",
"Kr",
60 "Rb",
"Sr",
"Y ",
"Zr",
"Nb",
"Mo",
"Tc",
"Ru",
"Rh",
"Pd",
"Ag",
"Cd",
61 "In",
"Sn",
"Sb",
"Te",
"I ",
"Xe",
"Cs",
"Ba",
"La",
"Ce",
"Pr",
"Nd",
62 "Pm",
"Sm",
"Eu",
"Gd",
"Tb",
"Dy",
"Ho",
"Er",
"Tm",
"Yb",
"Lu",
"Hf",
63 "Ta",
"W ",
"Re",
"Os",
"Ir",
"Pt",
"Au",
"Hg",
"Tl",
"Pb",
"Bi",
"Po",
64 "At",
"Rn",
"Fr",
"Ra",
"Ac",
"Th",
"Pa",
"U ",
"Np",
"Pu",
"Am",
"Cm",
65 "Bk",
"Cf",
"Es",
"Fm",
"Md",
"No",
"Lr",
"Rf",
"Db",
"Sg",
"Bh",
"Hs",
68 static const char *gDecayName[gMaxDecay+1] = {
69 "2BetaMinus",
"BetaMinus",
"NeutronEm",
"ProtonEm",
"Alpha",
"ECF",
70 "ElecCapt",
"IsoTrans",
"I",
"SpontFiss",
"2ProtonEm",
"2NeutronEm",
71 "2Alpha",
"Carbon12",
"Carbon14",
"Stable" };
73 static const Int_t gDecayDeltaA[gMaxDecay] = {
76 -2, -2, -8, -12, -14 };
78 static const Int_t gDecayDeltaZ[gMaxDecay] = {
82 static const char gLevName[gMaxLevel]=
" mnpqrs";
84 ClassImp(TGeoElement);
89 TGeoElement::TGeoElement()
91 TGeoUnit::setUnitType(TGeoUnit::unitType());
105 TGeoElement::TGeoElement(
const char *name,
const char *title, Int_t z, Double_t a)
108 TGeoUnit::setUnitType(TGeoUnit::unitType());
117 ComputeDerivedQuantities();
123 TGeoElement::TGeoElement(
const char *name,
const char *title, Int_t nisotopes)
126 TGeoUnit::setUnitType(TGeoUnit::unitType());
131 fNisotopes = nisotopes;
133 fIsotopes =
new TObjArray(nisotopes);
134 fAbundances =
new Double_t[nisotopes];
140 TGeoElement::TGeoElement(
const char *name,
const char *title, Int_t z, Int_t n, Double_t a)
143 TGeoUnit::setUnitType(TGeoUnit::unitType());
152 ComputeDerivedQuantities();
157 void TGeoElement::ComputeDerivedQuantities()
160 ComputeCoulombFactor();
161 ComputeLradTsaiFactor();
166 void TGeoElement::ComputeCoulombFactor()
168 static constexpr Double_t k1 = 0.0083 , k2 = 0.20206 ,k3 = 0.0020 , k4 = 0.0369;
169 Double_t fsc = TGeoUnit::unitType() == TGeoUnit::kTGeoUnits
170 ? TGeoUnit::fine_structure_const : TGeant4Unit::fine_structure_const;
171 Double_t az2 = (fsc*fZ)*(fsc*fZ);
172 Double_t az4 = az2 * az2;
174 fCoulomb = (k1*az4 + k2 + 1./(1.+az2))*az2 - (k3*az4 + k4)*az4;
179 void TGeoElement::ComputeLradTsaiFactor()
181 static constexpr Double_t Lrad_light[] = {5.31 , 4.79 , 4.74 , 4.71} ;
182 static constexpr Double_t Lprad_light[] = {6.144 , 5.621 , 5.805 , 5.924} ;
186 const Double_t logZ3 = TMath::Log(fZ)/3.;
188 Double_t Lrad, Lprad;
189 Double_t alpha_rcl2 = TGeoUnit::unitType() == TGeoUnit::kTGeoUnits
190 ? TGeoUnit::alpha_rcl2 : TGeant4Unit::alpha_rcl2;
191 Int_t iz =
static_cast<Int_t
>(fZ+0.5) - 1 ;
192 static const Double_t log184 = TMath::Log(184.15);
193 static const Double_t log1194 = TMath::Log(1194.);
194 if (iz <= 3) { Lrad = Lrad_light[iz] ; Lprad = Lprad_light[iz] ; }
195 else { Lrad = log184 - logZ3 ; Lprad = log1194 - 2*logZ3;}
197 fRadTsai = 4*alpha_rcl2*fZ*(fZ*(Lrad-fCoulomb) + Lprad);
202 void TGeoElement::Print(Option_t *option)
const
204 printf(
"Element: %s Z=%d N=%f A=%f [g/mole]\n", GetName(), fZ,Neff(),fA);
206 for (Int_t i=0; i<fNisotopes; i++) {
207 TGeoIsotope *iso = GetIsotope(i);
208 printf(
"=>Isotope %s, abundance=%f :\n", iso->GetName(), fAbundances[i]);
217 TGeoElementTable *TGeoElement::GetElementTable()
220 ::Error(
"TGeoElementTable::GetElementTable",
"Create a geometry manager first");
223 return gGeoManager->GetElementTable();
229 void TGeoElement::AddIsotope(TGeoIsotope *isotope, Double_t relativeAbundance)
232 Fatal(
"AddIsotope",
"Cannot add isotopes to normal elements. Use constructor with number of isotopes.");
237 for (ncurrent=0; ncurrent<fNisotopes; ncurrent++)
238 if (!fIsotopes->At(ncurrent))
break;
239 if (ncurrent==fNisotopes) {
240 Error(
"AddIsotope",
"All %d isotopes of element %s already defined", fNisotopes, GetName());
244 if ((fZ!=0) && (isotope->GetZ()!=fZ)) {
245 Fatal(
"AddIsotope",
"Trying to add isotope %s with different Z to the same element %s",
246 isotope->GetName(), GetName());
249 fZ = isotope->GetZ();
251 fIsotopes->Add(isotope);
252 fAbundances[ncurrent] = relativeAbundance;
253 if (ncurrent==fNisotopes-1) {
254 Double_t weight = 0.0;
257 for (Int_t i=0; i<fNisotopes; i++) {
258 isocrt = (TGeoIsotope*)fIsotopes->At(i);
259 aeff += fAbundances[i]*isocrt->GetA();
260 neff += fAbundances[i]*isocrt->GetN();
261 weight += fAbundances[i];
268 ComputeDerivedQuantities();
274 Double_t TGeoElement::Neff()
const
276 if (!fNisotopes)
return fN;
278 Double_t weight = 0.0;
280 for (Int_t i=0; i<fNisotopes; i++) {
281 isocrt = (TGeoIsotope*)fIsotopes->At(i);
282 neff += fAbundances[i]*isocrt->GetN();
283 weight += fAbundances[i];
292 TGeoIsotope *TGeoElement::GetIsotope(Int_t i)
const
294 if (i>=0 && i<fNisotopes) {
295 return (TGeoIsotope*)fIsotopes->At(i);
303 Double_t TGeoElement::GetRelativeAbundance(Int_t i)
const
305 if (i>=0 && i<fNisotopes)
return fAbundances[i];
309 ClassImp(TGeoIsotope);
314 TGeoIsotope::TGeoIsotope()
325 TGeoIsotope::TGeoIsotope(
const char *name, Int_t z, Int_t n, Double_t a)
331 if (z<1) Fatal(
"ctor",
"Not allowed Z=%d (<1) for isotope: %s", z,name);
332 if (n<z) Fatal(
"ctor",
"Not allowed Z=%d < N=%d for isotope: %s", z,n,name);
333 TGeoElement::GetElementTable()->AddIsotope(
this);
339 TGeoIsotope *TGeoIsotope::FindIsotope(
const char *name)
341 TGeoElementTable *elTable = TGeoElement::GetElementTable();
342 if (!elTable)
return 0;
343 return elTable->FindIsotope(name);
349 void TGeoIsotope::Print(Option_t *)
const
351 printf(
"Isotope: %s Z=%d N=%d A=%f [g/mole]\n", GetName(), fZ,fN,fA);
354 ClassImp(TGeoElementRN);
359 TGeoElementRN::TGeoElementRN()
361 TObject::SetBit(kElementChecked,kFALSE);
380 TGeoElementRN::TGeoElementRN(Int_t aa, Int_t zz, Int_t iso, Double_t level,
381 Double_t deltaM, Double_t halfLife,
const char* JP,
382 Double_t natAbun, Double_t th_f, Double_t tg_f, Double_t th_s,
383 Double_t tg_s, Int_t status)
384 :TGeoElement(
"", JP, zz, aa)
386 TObject::SetBit(kElementChecked,kFALSE);
387 fENDFcode = ENDF(aa,zz,iso);
391 fHalfLife = halfLife;
393 if (!fTitle.Length()) fTitle =
"?";
403 if ((TMath::Abs(fHalfLife)<1.e-30) || fHalfLife<-1) Warning(
"ctor",
"Element %s has T1/2=%g [s]", fName.Data(), fHalfLife);
409 TGeoElementRN::~TGeoElementRN()
415 if (fRatio)
delete fRatio;
421 void TGeoElementRN::AddDecay(Int_t decay, Int_t diso, Double_t branchingRatio, Double_t qValue)
423 if (branchingRatio<1E-20) {
425 TGeoDecayChannel::DecayName(decay, decayName);
426 Warning(
"AddDecay",
"Decay %s of %s has BR=0. Not added.", decayName.Data(),fName.Data());
429 TGeoDecayChannel *dc =
new TGeoDecayChannel(decay,diso,branchingRatio, qValue);
431 if (!fDecays) fDecays =
new TObjArray(5);
438 void TGeoElementRN::AddDecay(TGeoDecayChannel *dc)
441 if (!fDecays) fDecays =
new TObjArray(5);
448 Int_t TGeoElementRN::GetNdecays()
const
450 if (!fDecays)
return 0;
451 return fDecays->GetEntriesFast();
457 Double_t TGeoElementRN::GetSpecificActivity()
const
459 static const Double_t ln2 = TMath::Log(2.);
460 Double_t sa = (fHalfLife>0 && fA>0)?(ln2*TMath::Na()/fHalfLife/fA):0.;
467 Bool_t TGeoElementRN::CheckDecays()
const
469 if (TObject::TestBit(kElementChecked))
return kTRUE;
470 TObject *oelem = (TObject*)
this;
471 TGeoDecayChannel *dc;
473 TGeoElementTable *table = GetElementTable();
476 Error(
"CheckDecays",
"Element table not present");
479 Bool_t resultOK = kTRUE;
481 oelem->SetBit(kElementChecked,kTRUE);
485 Int_t decayResult = 0;
487 while ((dc=(TGeoDecayChannel*)next())) {
488 br += dc->BranchingRatio();
489 decayResult = DecayResult(dc);
491 elem = table->GetElementRN(decayResult);
493 TGeoDecayChannel::DecayName(dc->Decay(),decayName);
494 Error(
"CheckDecays",
"Element after decay %s of %s not found in DB", decayName.Data(),fName.Data());
497 dc->SetDaughter(elem);
498 resultOK = elem->CheckDecays();
501 if (TMath::Abs(br-100) > 1.E-3) {
502 Warning(
"CheckDecays",
"BR for decays of element %s sum-up = %f", fName.Data(), br);
505 oelem->SetBit(kElementChecked,kTRUE);
512 Int_t TGeoElementRN::DecayResult(TGeoDecayChannel *dc)
const
515 dc->DecayShift(da, dz, diso);
516 if (da == -99 || dz == -99)
return 0;
517 return ENDF(Int_t(fA)+da,fZ+dz,fIso+diso);
528 void TGeoElementRN::FillPopulation(TObjArray *population, Double_t precision, Double_t factor)
531 TGeoElemIter next(
this, precision);
532 TGeoBatemanSol s(
this);
535 if (!population->FindObject(
this)) population->Add(
this);
536 while ((elem=next())) {
537 TGeoBatemanSol ratio(next.GetBranch());
538 ratio.Normalize(factor);
539 elem->AddRatio(ratio);
540 if (!population->FindObject(elem)) population->Add(elem);
547 void TGeoElementRN::MakeName(Int_t a, Int_t z, Int_t iso)
554 if (z>=1 && z<= gMaxElem) fName += TString::Format(
"%3d-%s-",z,gElName[z-1]);
555 else fName =
"?? -?? -";
556 if (a>=1 && a<=999) fName += TString::Format(
"%3.3d",a);
558 if (iso>0 && iso<gMaxLevel) fName += TString::Format(
"%c", gLevName[iso]);
559 fName.ReplaceAll(
" ",
"");
565 void TGeoElementRN::Print(Option_t *option)
const
567 printf(
"\n%-12s ",fName.Data());
568 printf(
"ENDF=%d; ",fENDFcode);
569 printf(
"A=%d; ",(Int_t)fA);
571 printf(
"Iso=%d; ",fIso);
572 printf(
"Level=%g[MeV]; ",fLevel);
573 printf(
"Dmass=%g[MeV]; ",fDeltaM);
574 if (fHalfLife>0) printf(
"Hlife=%g[s]\n",fHalfLife);
575 else printf(
"Hlife=INF\n");
577 printf(
"J/P=%s; ",fTitle.Data());
578 printf(
"Abund=%g; ",fNatAbun);
579 printf(
"Htox=%g; ",fTH_F);
580 printf(
"Itox=%g; ",fTG_F);
581 printf(
"Stat=%d\n",fStatus);
583 printf(
"Decay modes:\n");
585 TGeoDecayChannel *dc;
586 while ((dc=(TGeoDecayChannel*)next())) dc->Print(option);
592 TGeoElementRN *TGeoElementRN::ReadElementRN(
const char *line, Int_t &ndecays)
594 Int_t a,z,iso,status;
595 Double_t level, deltaM, halfLife, natAbun, th_f, tg_f, th_s, tg_s;
596 char name[20],jp[20];
597 sscanf(&line[0],
"%s%d%d%d%lg%lg%lg%s%lg%lg%lg%lg%lg%d%d", name,&a,&z,&iso,&level,&deltaM,
598 &halfLife,jp,&natAbun,&th_f,&tg_f,&th_s,&tg_s,&status,&ndecays);
599 TGeoElementRN *elem =
new TGeoElementRN(a,z,iso,level,deltaM,halfLife,
600 jp,natAbun,th_f,tg_f,th_s,tg_s,status);
607 void TGeoElementRN::SavePrimitive(std::ostream &out, Option_t *option)
609 if (!strcmp(option,
"h")) {
611 out <<
"#====================================================================================================================================" << std::endl;
612 out <<
"# Name A Z ISO LEV[MeV] DM[MeV] T1/2[s] J/P ABUND[%] HTOX ITOX HTOX ITOX STAT NDCY" << std::endl;
613 out <<
"#====================================================================================================================================" << std::endl;
615 out << std::setw(11) << fName.Data();
616 out << std::setw(5) << (Int_t)fA;
617 out << std::setw(5) << fZ;
618 out << std::setw(5) << fIso;
619 out << std::setw(10) << std::setiosflags(std::ios::fixed) << std::setprecision(5) << fLevel;
620 out << std::setw(10) << std::setiosflags(std::ios::fixed) << std::setprecision(5) << fDeltaM;
621 out << std::setw(10) << std::setiosflags(std::ios::scientific) << std::setprecision(3) << fHalfLife;
622 out << std::setw(13) << fTitle.Data();
623 out << std::setw(10) << std::setiosflags(std::ios::fixed) << std::setprecision(5) << fNatAbun;
624 out << std::setw(10) << std::setiosflags(std::ios::fixed) << std::setprecision(5) << fTH_F;
625 out << std::setw(10) << std::setiosflags(std::ios::fixed) << std::setprecision(5) << fTG_F;
626 out << std::setw(10) << std::setiosflags(std::ios::fixed) << std::setprecision(5) << fTH_S;
627 out << std::setw(10) << std::setiosflags(std::ios::fixed) << std::setprecision(5) << fTG_S;
628 out << std::setw(5) << fStatus;
630 if (fDecays) ndecays = fDecays->GetEntries();
631 out << std::setw(5) << ndecays;
635 TGeoDecayChannel *dc;
636 while ((dc=(TGeoDecayChannel*)next())) dc->SavePrimitive(out);
643 void TGeoElementRN::AddRatio(TGeoBatemanSol &ratio)
645 if (!fRatio) fRatio =
new TGeoBatemanSol(ratio);
646 else *fRatio += ratio;
652 void TGeoElementRN::ResetRatio()
660 ClassImp(TGeoDecayChannel);
666 TGeoDecayChannel& TGeoDecayChannel::operator=(
const TGeoDecayChannel& dc)
669 TObject::operator=(dc);
672 fBranchingRatio = dc.fBranchingRatio;
673 fQvalue = dc.fQvalue;
674 fParent = dc.fParent;
675 fDaughter = dc.fDaughter;
683 const char *TGeoDecayChannel::GetName()
const
685 static TString name =
"";
687 if (!fDecay)
return gDecayName[gMaxDecay];
688 for (Int_t i=0; i<gMaxDecay; i++) {
690 if (name.Length()) name +=
"+";
691 name += gDecayName[i];
700 void TGeoDecayChannel::DecayName(UInt_t decay, TString &name)
703 name = gDecayName[gMaxDecay];
707 for (Int_t i=0; i<gMaxDecay; i++) {
709 if (name.Length()) name +=
"+";
710 name += gDecayName[i];
718 Int_t TGeoDecayChannel::GetIndex()
const
720 return fParent->Decays()->IndexOf(
this);
726 void TGeoDecayChannel::Print(Option_t *)
const
729 DecayName(fDecay, name);
730 printf(
"%-20s Diso: %3d BR: %9.3f%% Qval: %g\n", name.Data(),fDiso,fBranchingRatio,fQvalue);
736 TGeoDecayChannel *TGeoDecayChannel::ReadDecay(
const char *line)
740 Double_t branchingRatio, qValue;
741 sscanf(&line[0],
"%s%d%d%lg%lg", name,&decay,&diso,&branchingRatio,&qValue);
742 TGeoDecayChannel *dc =
new TGeoDecayChannel(decay,diso,branchingRatio,qValue);
749 void TGeoDecayChannel::SavePrimitive(std::ostream &out, Option_t *)
752 DecayName(fDecay, decayName);
753 out << std::setw(50) << decayName.Data();
754 out << std::setw(10) << fDecay;
755 out << std::setw(10) << fDiso;
756 out << std::setw(12) << std::setiosflags(std::ios::fixed) << std::setprecision(6) << fBranchingRatio;
757 out << std::setw(12) << std::setiosflags(std::ios::fixed) << std::setprecision(6) << fQvalue;
764 void TGeoDecayChannel::DecayShift(Int_t &dA, Int_t &dZ, Int_t &dI)
const
768 for(Int_t i=0; i<gMaxDecay; ++i) {
770 if(gDecayDeltaA[i] == -99 || gDecayDeltaZ[i] == -99 ) {
774 dA += gDecayDeltaA[i];
775 dZ += gDecayDeltaZ[i];
780 ClassImp(TGeoElemIter);
785 TGeoElemIter::TGeoElemIter(TGeoElementRN *top, Double_t limit)
786 : fTop(top), fElem(top), fBranch(0), fLevel(0), fLimitRatio(limit), fRatio(1.)
788 fBranch =
new TObjArray(10);
794 TGeoElemIter::TGeoElemIter(
const TGeoElemIter &iter)
799 fLimitRatio(iter.fLimitRatio),
803 fBranch =
new TObjArray(10);
804 for (Int_t i=0; i<fLevel; i++) fBranch->Add(iter.fBranch->At(i));
811 TGeoElemIter::~TGeoElemIter()
813 if (fBranch)
delete fBranch;
819 TGeoElemIter &TGeoElemIter::operator=(
const TGeoElemIter &iter)
821 if (&iter ==
this)
return *
this;
824 fLevel = iter.fLevel;
826 fBranch =
new TObjArray(10);
827 for (Int_t i=0; i<fLevel; i++) fBranch->Add(iter.fBranch->At(i));
829 fLimitRatio = iter.fLimitRatio;
830 fRatio = iter.fRatio;
837 TGeoElementRN *TGeoElemIter::operator()()
845 TGeoElementRN *TGeoElemIter::Up()
847 TGeoDecayChannel *dc;
851 dc = (TGeoDecayChannel*)fBranch->At(fLevel-1);
852 ind = dc->GetIndex();
853 nd = dc->Parent()->GetNdecays();
854 fRatio /= 0.01*dc->BranchingRatio();
855 fElem = dc->Parent();
856 fBranch->RemoveAt(--fLevel);
859 if (Down(ind++))
return (TGeoElementRN*)fElem;
870 TGeoElementRN *TGeoElemIter::Down(Int_t ibranch)
872 TGeoDecayChannel *dc = (TGeoDecayChannel*)fElem->Decays()->At(ibranch);
873 if (!dc->Daughter())
return NULL;
874 Double_t br = 0.01*fRatio*dc->BranchingRatio();
875 if (br < fLimitRatio)
return NULL;
879 fElem = dc->Daughter();
880 return (TGeoElementRN*)fElem;
886 TGeoElementRN *TGeoElemIter::Next()
888 if (!fElem)
return NULL;
890 Int_t nd = fElem->GetNdecays();
891 for (Int_t i=0; i<nd; i++)
if (Down(i))
return (TGeoElementRN*)fElem;
898 void TGeoElemIter::Print(Option_t * )
const
901 TGeoDecayChannel *dc;
903 printf(
"=== Chain with %g %%\n", 100*fRatio);
904 for (Int_t i=0; i<fLevel; i++) {
905 dc = (TGeoDecayChannel*)fBranch->At(i);
907 printf(
"%s%s (%g%% %s) T1/2=%g\n", indent.Data(), elem->GetName(),dc->BranchingRatio(),dc->GetName(),elem->HalfLife());
910 elem = dc->Daughter();
911 printf(
"%s%s\n", indent.Data(), elem->GetName());
916 ClassImp(TGeoElementTable);
921 TGeoElementTable::TGeoElementTable()
934 TGeoElementTable::TGeoElementTable(Int_t )
939 fList =
new TObjArray(128);
942 BuildDefaultElements();
949 TGeoElementTable::TGeoElementTable(
const TGeoElementTable&
get) :
951 fNelements(get.fNelements),
952 fNelementsRN(get.fNelementsRN),
953 fNisotopes(get.fNisotopes),
955 fListRN(get.fListRN),
963 TGeoElementTable& TGeoElementTable::operator=(
const TGeoElementTable&
get)
966 TObject::operator=(
get);
967 fNelements=
get.fNelements;
968 fNelementsRN=
get.fNelementsRN;
969 fNisotopes=
get.fNisotopes;
980 TGeoElementTable::~TGeoElementTable()
999 void TGeoElementTable::AddElement(
const char *name,
const char *title, Int_t z, Double_t a)
1001 if (!fList) fList =
new TObjArray(128);
1002 fList->AddAtAndExpand(
new TGeoElement(name,title,z,a), fNelements++);
1008 void TGeoElementTable::AddElement(
const char *name,
const char *title, Int_t z, Int_t n, Double_t a)
1010 if (!fList) fList =
new TObjArray(128);
1011 fList->AddAtAndExpand(
new TGeoElement(name,title,z,n,a), fNelements++);
1017 void TGeoElementTable::AddElement(TGeoElement *elem)
1019 if (!fList) fList =
new TObjArray(128);
1020 TGeoElement *orig = FindElement(elem->GetName());
1022 Error(
"AddElement",
"Found element with same name: %s (%s). Cannot add to table.",
1023 orig->GetName(), orig->GetTitle());
1026 fList->AddAtAndExpand(elem, fNelements++);
1032 void TGeoElementTable::AddElementRN(TGeoElementRN *elem)
1034 if (!fListRN) fListRN =
new TObjArray(3600);
1035 if (HasRNElements() && GetElementRN(elem->ENDFCode()))
return;
1039 fElementsRN.insert(ElementRNMap_t::value_type(elem->ENDFCode(), elem));
1045 void TGeoElementTable::AddIsotope(TGeoIsotope *isotope)
1047 if (FindIsotope(isotope->GetName())) {
1048 Error(
"AddIsotope",
"Isotope with the same name: %s already in table. Not adding.",isotope->GetName());
1051 if (!fIsotopes) fIsotopes =
new TObjArray();
1052 fIsotopes->Add(isotope);
1058 void TGeoElementTable::BuildDefaultElements()
1060 if (HasDefaultElements())
return;
1061 AddElement(
"VACUUM",
"VACUUM" ,0, 0, 0.0);
1062 AddElement(
"H" ,
"HYDROGEN" ,1, 1, 1.00794);
1063 AddElement(
"HE" ,
"HELIUM" ,2, 4, 4.002602);
1064 AddElement(
"LI" ,
"LITHIUM" ,3, 7, 6.941);
1065 AddElement(
"BE" ,
"BERYLLIUM" ,4, 9, 9.01218);
1066 AddElement(
"B" ,
"BORON" ,5, 11, 10.811);
1067 AddElement(
"C" ,
"CARBON" ,6, 12, 12.0107);
1068 AddElement(
"N" ,
"NITROGEN" ,7, 14, 14.00674);
1069 AddElement(
"O" ,
"OXYGEN" ,8, 16, 15.9994);
1070 AddElement(
"F" ,
"FLUORINE" ,9, 19, 18.9984032);
1071 AddElement(
"NE" ,
"NEON" ,10, 20, 20.1797);
1072 AddElement(
"NA" ,
"SODIUM" ,11, 23, 22.989770);
1073 AddElement(
"MG" ,
"MAGNESIUM" ,12, 24, 24.3050);
1074 AddElement(
"AL" ,
"ALUMINIUM" ,13, 27, 26.981538);
1075 AddElement(
"SI" ,
"SILICON" ,14, 28, 28.0855);
1076 AddElement(
"P" ,
"PHOSPHORUS" ,15, 31, 30.973761);
1077 AddElement(
"S" ,
"SULFUR" ,16, 32, 32.066);
1078 AddElement(
"CL" ,
"CHLORINE" ,17, 35, 35.4527);
1079 AddElement(
"AR" ,
"ARGON" ,18, 40, 39.948);
1080 AddElement(
"K" ,
"POTASSIUM" ,19, 39, 39.0983);
1081 AddElement(
"CA" ,
"CALCIUM" ,20, 40, 40.078);
1082 AddElement(
"SC" ,
"SCANDIUM" ,21, 45, 44.955910);
1083 AddElement(
"TI" ,
"TITANIUM" ,22, 48, 47.867);
1084 AddElement(
"V" ,
"VANADIUM" ,23, 51, 50.9415);
1085 AddElement(
"CR" ,
"CHROMIUM" ,24, 52, 51.9961);
1086 AddElement(
"MN" ,
"MANGANESE" ,25, 55, 54.938049);
1087 AddElement(
"FE" ,
"IRON" ,26, 56, 55.845);
1088 AddElement(
"CO" ,
"COBALT" ,27, 59, 58.933200);
1089 AddElement(
"NI" ,
"NICKEL" ,28, 59, 58.6934);
1090 AddElement(
"CU" ,
"COPPER" ,29, 64, 63.546);
1091 AddElement(
"ZN" ,
"ZINC" ,30, 65, 65.39);
1092 AddElement(
"GA" ,
"GALLIUM" ,31, 70, 69.723);
1093 AddElement(
"GE" ,
"GERMANIUM" ,32, 73, 72.61);
1094 AddElement(
"AS" ,
"ARSENIC" ,33, 75, 74.92160);
1095 AddElement(
"SE" ,
"SELENIUM" ,34, 79, 78.96);
1096 AddElement(
"BR" ,
"BROMINE" ,35, 80, 79.904);
1097 AddElement(
"KR" ,
"KRYPTON" ,36, 84, 83.80);
1098 AddElement(
"RB" ,
"RUBIDIUM" ,37, 85, 85.4678);
1099 AddElement(
"SR" ,
"STRONTIUM" ,38, 88, 87.62);
1100 AddElement(
"Y" ,
"YTTRIUM" ,39, 89, 88.90585);
1101 AddElement(
"ZR" ,
"ZIRCONIUM" ,40, 91, 91.224);
1102 AddElement(
"NB" ,
"NIOBIUM" ,41, 93, 92.90638);
1103 AddElement(
"MO" ,
"MOLYBDENUM" ,42, 96, 95.94);
1104 AddElement(
"TC" ,
"TECHNETIUM" ,43, 98, 98.0);
1105 AddElement(
"RU" ,
"RUTHENIUM" ,44, 101, 101.07);
1106 AddElement(
"RH" ,
"RHODIUM" ,45, 103, 102.90550);
1107 AddElement(
"PD" ,
"PALLADIUM" ,46, 106, 106.42);
1108 AddElement(
"AG" ,
"SILVER" ,47, 108, 107.8682);
1109 AddElement(
"CD" ,
"CADMIUM" ,48, 112, 112.411);
1110 AddElement(
"IN" ,
"INDIUM" ,49, 115, 114.818);
1111 AddElement(
"SN" ,
"TIN" ,50, 119, 118.710);
1112 AddElement(
"SB" ,
"ANTIMONY" ,51, 122, 121.760);
1113 AddElement(
"TE" ,
"TELLURIUM" ,52, 128, 127.60);
1114 AddElement(
"I" ,
"IODINE" ,53, 127, 126.90447);
1115 AddElement(
"XE" ,
"XENON" ,54, 131, 131.29);
1116 AddElement(
"CS" ,
"CESIUM" ,55, 133, 132.90545);
1117 AddElement(
"BA" ,
"BARIUM" ,56, 137, 137.327);
1118 AddElement(
"LA" ,
"LANTHANUM" ,57, 139, 138.9055);
1119 AddElement(
"CE" ,
"CERIUM" ,58, 140, 140.116);
1120 AddElement(
"PR" ,
"PRASEODYMIUM" ,59, 141, 140.90765);
1121 AddElement(
"ND" ,
"NEODYMIUM" ,60, 144, 144.24);
1122 AddElement(
"PM" ,
"PROMETHIUM" ,61, 145, 145.0);
1123 AddElement(
"SM" ,
"SAMARIUM" ,62, 150, 150.36);
1124 AddElement(
"EU" ,
"EUROPIUM" ,63, 152, 151.964);
1125 AddElement(
"GD" ,
"GADOLINIUM" ,64, 157, 157.25);
1126 AddElement(
"TB" ,
"TERBIUM" ,65, 159, 158.92534);
1127 AddElement(
"DY" ,
"DYSPROSIUM" ,66, 162, 162.50);
1128 AddElement(
"HO" ,
"HOLMIUM" ,67, 165, 164.93032);
1129 AddElement(
"ER" ,
"ERBIUM" ,68, 167, 167.26);
1130 AddElement(
"TM" ,
"THULIUM" ,69, 169, 168.93421);
1131 AddElement(
"YB" ,
"YTTERBIUM" ,70, 173, 173.04);
1132 AddElement(
"LU" ,
"LUTETIUM" ,71, 175, 174.967);
1133 AddElement(
"HF" ,
"HAFNIUM" ,72, 178, 178.49);
1134 AddElement(
"TA" ,
"TANTALUM" ,73, 181, 180.9479);
1135 AddElement(
"W" ,
"TUNGSTEN" ,74, 184, 183.84);
1136 AddElement(
"RE" ,
"RHENIUM" ,75, 186, 186.207);
1137 AddElement(
"OS" ,
"OSMIUM" ,76, 190, 190.23);
1138 AddElement(
"IR" ,
"IRIDIUM" ,77, 192, 192.217);
1139 AddElement(
"PT" ,
"PLATINUM" ,78, 195, 195.078);
1140 AddElement(
"AU" ,
"GOLD" ,79, 197, 196.96655);
1141 AddElement(
"HG" ,
"MERCURY" ,80, 200, 200.59);
1142 AddElement(
"TL" ,
"THALLIUM" ,81, 204, 204.3833);
1143 AddElement(
"PB" ,
"LEAD" ,82, 207, 207.2);
1144 AddElement(
"BI" ,
"BISMUTH" ,83, 209, 208.98038);
1145 AddElement(
"PO" ,
"POLONIUM" ,84, 209, 209.0);
1146 AddElement(
"AT" ,
"ASTATINE" ,85, 210, 210.0);
1147 AddElement(
"RN" ,
"RADON" ,86, 222, 222.0);
1148 AddElement(
"FR" ,
"FRANCIUM" ,87, 223, 223.0);
1149 AddElement(
"RA" ,
"RADIUM" ,88, 226, 226.0);
1150 AddElement(
"AC" ,
"ACTINIUM" ,89, 227, 227.0);
1151 AddElement(
"TH" ,
"THORIUM" ,90, 232, 232.0381);
1152 AddElement(
"PA" ,
"PROTACTINIUM" ,91, 231, 231.03588);
1153 AddElement(
"U" ,
"URANIUM" ,92, 238, 238.0289);
1154 AddElement(
"NP" ,
"NEPTUNIUM" ,93, 237, 237.0);
1155 AddElement(
"PU" ,
"PLUTONIUM" ,94, 244, 244.0);
1156 AddElement(
"AM" ,
"AMERICIUM" ,95, 243, 243.0);
1157 AddElement(
"CM" ,
"CURIUM" ,96, 247, 247.0);
1158 AddElement(
"BK" ,
"BERKELIUM" ,97, 247, 247.0);
1159 AddElement(
"CF" ,
"CALIFORNIUM",98, 251, 251.0);
1160 AddElement(
"ES" ,
"EINSTEINIUM",99, 252, 252.0);
1161 AddElement(
"FM" ,
"FERMIUM" ,100, 257, 257.0);
1162 AddElement(
"MD" ,
"MENDELEVIUM",101, 258, 258.0);
1163 AddElement(
"NO" ,
"NOBELIUM" ,102, 259, 259.0);
1164 AddElement(
"LR" ,
"LAWRENCIUM" ,103, 262, 262.0);
1165 AddElement(
"RF" ,
"RUTHERFORDIUM",104, 261, 261.0);
1166 AddElement(
"DB" ,
"DUBNIUM" ,105, 262, 262.0);
1167 AddElement(
"SG" ,
"SEABORGIUM" ,106, 263, 263.0);
1168 AddElement(
"BH" ,
"BOHRIUM" ,107, 262, 262.0);
1169 AddElement(
"HS" ,
"HASSIUM" ,108, 265, 265.0);
1170 AddElement(
"MT" ,
"MEITNERIUM" ,109, 266, 266.0);
1171 AddElement(
"UUN" ,
"UNUNNILIUM" ,110, 269, 269.0);
1172 AddElement(
"UUU" ,
"UNUNUNIUM" ,111, 272, 272.0);
1173 AddElement(
"UUB" ,
"UNUNBIUM" ,112, 277, 277.0);
1175 TObject::SetBit(kETDefaultElements,kTRUE);
1181 void TGeoElementTable::ImportElementsRN()
1183 if (HasRNElements())
return;
1184 TGeoElementRN *elem;
1185 TString rnf =
"RadioNuclides.txt";
1186 gSystem->PrependPathName(TROOT::GetEtcDir(), rnf);
1187 FILE *fp = fopen(rnf,
"r");
1189 Error(
"ImportElementsRN",
"File RadioNuclides.txt not found");
1195 while (fgets(&line[0],140,fp)) {
1196 if (line[0]==
'#')
continue;
1197 elem = TGeoElementRN::ReadElementRN(line, ndecays);
1198 for (i=0; i<ndecays; i++) {
1199 if (!fgets(&line[0],140,fp)) {
1200 Error(
"ImportElementsRN",
"Error parsing RadioNuclides.txt file");
1204 TGeoDecayChannel *dc = TGeoDecayChannel::ReadDecay(line);
1210 TObject::SetBit(kETRNElements,kTRUE);
1218 Bool_t TGeoElementTable::CheckTable()
const
1220 if (!HasRNElements())
return HasDefaultElements();
1221 TGeoElementRN *elem;
1222 Bool_t result = kTRUE;
1223 TIter next(fListRN);
1224 while ((elem=(TGeoElementRN*)next())) {
1225 if (!elem->CheckDecays()) result = kFALSE;
1233 void TGeoElementTable::ExportElementsRN(
const char *filename)
1235 if (!HasRNElements())
return;
1236 TString sname = filename;
1237 if (!sname.Length()) sname =
"RadioNuclides.txt";
1239 out.open(sname.Data(), std::ios::out);
1241 Error(
"ExportElementsRN",
"Cannot open file %s", sname.Data());
1245 TGeoElementRN *elem;
1246 TIter next(fListRN);
1248 while ((elem=(TGeoElementRN*)next())) {
1249 if ((i%48)==0) elem->SavePrimitive(out,
"h");
1250 else elem->SavePrimitive(out);
1260 TGeoElement *TGeoElementTable::FindElement(
const char *name)
const
1263 elem = (TGeoElement*)fList->FindObject(name);
1264 if (elem)
return elem;
1268 elem = (TGeoElement*)fList->FindObject(s.Data());
1269 if (elem)
return elem;
1272 while ((elem=(TGeoElement*)next())) {
1273 if (s == elem->GetTitle())
return elem;
1281 TGeoIsotope *TGeoElementTable::FindIsotope(
const char *name)
const
1283 if (!fIsotopes)
return NULL;
1284 return (TGeoIsotope*)fIsotopes->FindObject(name);
1290 TGeoElementRN *TGeoElementTable::GetElementRN(Int_t ENDFcode)
const
1292 if (!HasRNElements()) {
1293 TGeoElementTable *table = (TGeoElementTable*)
this;
1294 table->ImportElementsRN();
1295 if (!fListRN)
return 0;
1297 ElementRNMap_t::const_iterator it = fElementsRN.find(ENDFcode);
1298 if (it != fElementsRN.end())
return it->second;
1305 TGeoElementRN *TGeoElementTable::GetElementRN(Int_t a, Int_t z, Int_t iso)
const
1307 return GetElementRN(TGeoElementRN::ENDF(a,z,iso));
1318 void TGeoElementTable::Print(Option_t *option)
const
1320 TString opt(option);
1322 Int_t induser = HasDefaultElements() ? 113 : 0;
1324 if (opt==
"" || opt==
"D") {
1325 if (induser) printf(
"================\nDefault elements\n================\n");
1326 for (Int_t iel=0; iel<induser; ++iel) fList->At(iel)->Print();
1329 if (opt==
"" || opt==
"I") {
1331 printf(
"================\nIsotopes\n================\n");
1336 if (opt==
"" || opt==
"R") {
1337 if (HasRNElements()) {
1338 printf(
"================\nRadio-nuclides\n================\n");
1343 if (opt==
"" || opt==
"U") {
1344 if (fNelements>induser) printf(
"================\nUser elements\n================\n");
1345 for (Int_t iel=induser; iel<fNelements; ++iel) fList->At(iel)->Print();
1349 ClassImp(TGeoBatemanSol);
1354 TGeoBatemanSol::TGeoBatemanSol(TGeoElementRN *elem)
1355 :TObject(), TAttLine(), TAttFill(), TAttMarker(),
1365 fCoeff =
new BtCoef_t[fCsize];
1368 Double_t t12 = elem->HalfLife();
1369 if (t12 == 0.) t12 = 1.e-30;
1370 if (elem->Stable()) fCoeff[0].lambda = 0.;
1371 else fCoeff[0].lambda = TMath::Log(2.)/t12;
1377 TGeoBatemanSol::TGeoBatemanSol(
const TObjArray *chain)
1378 :TObject(), TAttLine(), TAttFill(), TAttMarker(),
1388 TGeoDecayChannel *dc = (TGeoDecayChannel*)chain->At(0);
1389 if (dc) fElemTop = dc->Parent();
1390 dc = (TGeoDecayChannel*)chain->At(chain->GetEntriesFast()-1);
1392 fElem = dc->Daughter();
1393 fCsize = chain->GetEntriesFast()+1;
1394 fCoeff =
new BtCoef_t[fCsize];
1395 FindSolution(chain);
1402 TGeoBatemanSol::TGeoBatemanSol(
const TGeoBatemanSol& other)
1403 :TObject(other), TAttLine(other), TAttFill(other), TAttMarker(other),
1405 fElemTop(other.fElemTop),
1406 fCsize(other.fCsize),
1407 fNcoeff(other.fNcoeff),
1408 fFactor(other.fFactor),
1414 fCoeff =
new BtCoef_t[fCsize];
1415 for (Int_t i=0; i<fNcoeff; i++) {
1416 fCoeff[i].cn = other.fCoeff[i].cn;
1417 fCoeff[i].lambda = other.fCoeff[i].lambda;
1425 TGeoBatemanSol::~TGeoBatemanSol()
1427 if (fCoeff)
delete [] fCoeff;
1433 TGeoBatemanSol& TGeoBatemanSol::operator=(
const TGeoBatemanSol& other)
1435 if (
this == &other)
return *
this;
1436 TObject::operator=(other);
1437 TAttLine::operator=(other);
1438 TAttFill::operator=(other);
1439 TAttMarker::operator=(other);
1440 fElem = other.fElem;
1441 fElemTop = other.fElemTop;
1442 if (fCoeff)
delete [] fCoeff;
1444 fCsize = other.fCsize;
1445 fNcoeff = other.fNcoeff;
1446 fFactor = other.fFactor;
1447 fTmin = other.fTmin;
1448 fTmax = other.fTmax;
1450 fCoeff =
new BtCoef_t[fCsize];
1451 for (Int_t i=0; i<fNcoeff; i++) {
1452 fCoeff[i].cn = other.fCoeff[i].cn;
1453 fCoeff[i].lambda = other.fCoeff[i].lambda;
1462 TGeoBatemanSol& TGeoBatemanSol::operator+=(
const TGeoBatemanSol& other)
1464 if (other.GetElement() != fElem) {
1465 Error(
"operator+=",
"Cannot add 2 solutions for different elements");
1469 BtCoef_t *coeff = fCoeff;
1470 Int_t ncoeff = fNcoeff + other.fNcoeff;
1471 if (ncoeff > fCsize) {
1473 coeff =
new BtCoef_t[ncoeff];
1474 for (i=0; i<fNcoeff; i++) {
1475 coeff[i].cn = fCoeff[i].cn;
1476 coeff[i].lambda = fCoeff[i].lambda;
1482 for (j=0; j<other.fNcoeff; j++) {
1483 for (i=0; i<fNcoeff; i++) {
1484 if (coeff[i].lambda == other.fCoeff[j].lambda) {
1485 coeff[i].cn += fFactor * other.fCoeff[j].cn;
1490 coeff[ncoeff].cn = fFactor * other.fCoeff[j].cn;
1491 coeff[ncoeff].lambda = other.fCoeff[j].lambda;
1501 Double_t TGeoBatemanSol::Concentration(Double_t time)
const
1504 for (Int_t i=0; i<fNcoeff; i++)
1505 conc += fCoeff[i].cn * TMath::Exp(-fCoeff[i].lambda * time);
1512 void TGeoBatemanSol::Draw(Option_t *option)
1514 if (!gGeoManager)
return;
1515 gGeoManager->GetGeomPainter()->DrawBatemanSol(
this, option);
1529 void TGeoBatemanSol::FindSolution(
const TObjArray *array)
1532 if (!array || !array->GetEntriesFast())
return;
1533 Int_t n = array->GetEntriesFast();
1534 TGeoDecayChannel *dc = (TGeoDecayChannel*)array->At(n-1);
1535 TGeoElementRN *elem = dc->Daughter();
1536 if (elem != fElem) {
1537 Error(
"FindSolution",
"Last element in the list must be %s\n", fElem->GetName());
1544 fCoeff =
new BtCoef_t[fCsize];
1546 if (fCsize < order) {
1549 fCoeff =
new BtCoef_t[fCsize];
1552 Double_t *lambda =
new Double_t[order];
1553 Double_t *br =
new Double_t[n];
1555 for (i=0; i<n; i++) {
1556 dc = (TGeoDecayChannel*)array->At(i);
1557 elem = dc->Parent();
1558 br[i] = 0.01 * dc->BranchingRatio();
1559 halflife = elem->HalfLife();
1560 if (halflife==0.) halflife = 1.e-30;
1561 if (elem->Stable()) lambda[i] = 0.;
1562 else lambda[i] = TMath::Log(2.)/halflife;
1564 elem = dc->Daughter();
1565 halflife = elem->HalfLife();
1566 if (halflife==0.) halflife = 1.e-30;
1567 if (elem->Stable()) lambda[n] = 0.;
1568 else lambda[n] = TMath::Log(2.)/halflife;
1572 for (i=0; i<order-1; i++) {
1573 for (j=i+1; j<order; j++) {
1574 if (lambda[j] == lambda[i]) lambda[j] += 0.001*lambda[j];
1578 Double_t pdlambda, plambdabr=1.;
1579 for (j=0; j<n; j++) plambdabr *= lambda[j]*br[j];
1580 for (i=0; i<order; i++) {
1582 for (j=0; j<n+1; j++) {
1583 if (j == i)
continue;
1584 pdlambda *= lambda[j] - lambda[i];
1586 if (pdlambda == 0.) {
1587 Error(
"FindSolution",
"pdlambda=0 !!!");
1592 ain = plambdabr/pdlambda;
1594 fCoeff[i].lambda = lambda[i];
1605 void TGeoBatemanSol::Normalize(Double_t factor)
1607 for (Int_t i=0; i<fNcoeff; i++) fCoeff[i].cn *= factor;
1613 void TGeoBatemanSol::Print(Option_t * )
const
1616 formula.Form(
"N[%s]/N[%s] = ", fElem->GetName(), fElemTop->GetName());
1617 for (Int_t i=0; i<fNcoeff; i++) {
1618 if (i == fNcoeff-1) formula += TString::Format(
"%g*exp(-%g*t)", fCoeff[i].cn, fCoeff[i].lambda);
1619 else formula += TString::Format(
"%g*exp(-%g*t) + ", fCoeff[i].cn, fCoeff[i].lambda);
1621 printf(
"%s\n", formula.Data());