Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TGeoElement.cxx
Go to the documentation of this file.
1// @(#)root/geom:$Id$
2// Author: Andrei Gheata 17/06/04
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/** \class TGeoElement
13\ingroup Materials_classes
14Base class for chemical elements
15*/
16
17/** \class TGeoElementRN
18\ingroup Geometry_classes
19Class representing a radionuclidevoid TGeoManager::SetDefaultRootUnits()
20{
21 if ( fgDefaultUnits == kRootUnits ) {
22 return;
23 }
24 else if ( gGeometryLocked ) {
25 TError::Fatal("TGeoManager","The system of units may only be changed once BEFORE any elements and materials are created!");
26 }
27 fgDefaultUnits = kRootUnits;
28}
29
30*/
31
32/** \class TGeoElemIter
33\ingroup Geometry_classes
34Iterator for decay branches
35*/
36
37/** \class TGeoDecayChannel
38\ingroup Geometry_classes
39A decay channel for a radionuclide
40*/
41
42/** \class TGeoElementTable
43\ingroup Geometry_classes
44Table of elements
45*/
46
47#include "RConfigure.h"
48
49#include <fstream>
50#include <iomanip>
51
52#include "TSystem.h"
53#include "TROOT.h"
54#include "TObjArray.h"
55#include "TVirtualGeoPainter.h"
56#include "TGeoManager.h"
57#include "TGeoElement.h"
58#include "TMath.h"
61
62// statics and globals
63static const Int_t gMaxElem = 110;
64static const Int_t gMaxLevel = 8;
65static const Int_t gMaxDecay = 15;
66
67static const char gElName[gMaxElem][3] = {
68 "H ","He","Li","Be","B ","C ","N ","O ","F ","Ne","Na","Mg",
69 "Al","Si","P ","S ","Cl","Ar","K ","Ca","Sc","Ti","V ","Cr",
70 "Mn","Fe","Co","Ni","Cu","Zn","Ga","Ge","As","Se","Br","Kr",
71 "Rb","Sr","Y ","Zr","Nb","Mo","Tc","Ru","Rh","Pd","Ag","Cd",
72 "In","Sn","Sb","Te","I ","Xe","Cs","Ba","La","Ce","Pr","Nd",
73 "Pm","Sm","Eu","Gd","Tb","Dy","Ho","Er","Tm","Yb","Lu","Hf",
74 "Ta","W ","Re","Os","Ir","Pt","Au","Hg","Tl","Pb","Bi","Po",
75 "At","Rn","Fr","Ra","Ac","Th","Pa","U ","Np","Pu","Am","Cm",
76 "Bk","Cf","Es","Fm","Md","No","Lr","Rf","Db","Sg","Bh","Hs",
77 "Mt","Ds" };
78
79static const char *gDecayName[gMaxDecay+1] = {
80 "2BetaMinus", "BetaMinus", "NeutronEm", "ProtonEm", "Alpha", "ECF",
81 "ElecCapt", "IsoTrans", "I", "SpontFiss", "2ProtonEm", "2NeutronEm",
82 "2Alpha", "Carbon12", "Carbon14", "Stable" };
83
84static const Int_t gDecayDeltaA[gMaxDecay] = {
85 0, 0, -1, -1, -4,
86 -99, 0, 0, -99, -99,
87 -2, -2, -8, -12, -14 };
88
89static const Int_t gDecayDeltaZ[gMaxDecay] = {
90 2, 1, 0, -1, -2,
91 -99, -1, 0, -99, -99,
92 -2, 0, -4, -6, -6 };
93static const char gLevName[gMaxLevel]=" mnpqrs";
94
96
97////////////////////////////////////////////////////////////////////////////////
98/// Default constructor
99
101{
102 TGeoManager::SetDefaultUnits(TGeoManager::GetDefaultUnits()); // Ensure nobody changes the units afterwards
105 fZ = 0;
106 fN = 0;
107 fNisotopes = 0;
108 fA = 0.0;
109 fIsotopes = nullptr;
110 fAbundances = nullptr;
111}
112
113////////////////////////////////////////////////////////////////////////////////
114/// Obsolete constructor
115
116TGeoElement::TGeoElement(const char *name, const char *title, Int_t z, Double_t a)
117 :TNamed(name, title)
118{
119 TGeoManager::SetDefaultUnits(TGeoManager::GetDefaultUnits()); // Ensure nobody changes the units afterwards
122 fZ = z;
123 fN = Int_t(a);
124 fNisotopes = 0;
125 fA = a;
126 fIsotopes = nullptr;
127 fAbundances = nullptr;
129}
130
131////////////////////////////////////////////////////////////////////////////////
132/// Element having isotopes.
133
134TGeoElement::TGeoElement(const char *name, const char *title, Int_t nisotopes)
135 :TNamed(name, title)
136{
137 TGeoManager::SetDefaultUnits(TGeoManager::GetDefaultUnits()); // Ensure nobody changes the units afterwards
140 fZ = 0;
141 fN = 0;
142 fNisotopes = nisotopes;
143 fA = 0.0;
144 fIsotopes = new TObjArray(nisotopes);
145 fAbundances = new Double_t[nisotopes];
146}
147
148////////////////////////////////////////////////////////////////////////////////
149/// Constructor
150
151TGeoElement::TGeoElement(const char *name, const char *title, Int_t z, Int_t n, Double_t a)
152 :TNamed(name, title)
153{
154 TGeoManager::SetDefaultUnits(TGeoManager::GetDefaultUnits()); // Ensure nobody changes the units afterwards
157 fZ = z;
158 fN = n;
159 fNisotopes = 0;
160 fA = a;
161 fIsotopes = nullptr;
162 fAbundances = nullptr;
164}
165
166////////////////////////////////////////////////////////////////////////////////
167/// destructor
168
170{
171 delete fIsotopes;
172 delete [] fAbundances;
173}
174
175
176////////////////////////////////////////////////////////////////////////////////
177/// Calculate properties for an atomic number
178
180{
181 // Radiation Length
184}
185////////////////////////////////////////////////////////////////////////////////
186/// Compute Coulomb correction factor (Phys Rev. D50 3-1 (1994) page 1254)
187
189{
190 static constexpr Double_t k1 = 0.0083 , k2 = 0.20206 ,k3 = 0.0020 , k4 = 0.0369;
193 Double_t az2 = (fsc*fZ)*(fsc*fZ);
194 Double_t az4 = az2 * az2;
195
196 fCoulomb = (k1*az4 + k2 + 1./(1.+az2))*az2 - (k3*az4 + k4)*az4;
197}
198////////////////////////////////////////////////////////////////////////////////
199/// Compute Tsai's Expression for the Radiation Length (Phys Rev. D50 3-1 (1994) page 1254)
200
202{
203 static constexpr Double_t Lrad_light[] = {5.31 , 4.79 , 4.74 , 4.71} ;
204 static constexpr Double_t Lprad_light[] = {6.144 , 5.621 , 5.805 , 5.924} ;
205
206 fRadTsai = 0.0;
207 if (fZ == 0) return;
208 const Double_t logZ3 = TMath::Log(fZ)/3.;
209
210 Double_t Lrad, Lprad;
213 Int_t iz = static_cast<Int_t>(fZ+0.5) - 1 ; // The static cast comes from G4lrint
214 static const Double_t log184 = TMath::Log(184.15);
215 static const Double_t log1194 = TMath::Log(1194.);
216 if (iz <= 3) { Lrad = Lrad_light[iz] ; Lprad = Lprad_light[iz] ; }
217 else { Lrad = log184 - logZ3 ; Lprad = log1194 - 2*logZ3;}
218
219 fRadTsai = 4*alpha_rcl2*fZ*(fZ*(Lrad-fCoulomb) + Lprad);
220}
221////////////////////////////////////////////////////////////////////////////////
222/// Print this isotope
223
225{
226 printf("Element: %s Z=%d N=%f A=%f [g/mole]\n", GetName(), fZ,Neff(),fA);
227 if (HasIsotopes()) {
228 for (Int_t i=0; i<fNisotopes; i++) {
229 TGeoIsotope *iso = GetIsotope(i);
230 printf("=>Isotope %s, abundance=%f :\n", iso->GetName(), fAbundances[i]);
231 iso->Print(option);
232 }
233 }
234}
235
236////////////////////////////////////////////////////////////////////////////////
237/// Returns pointer to the table.
238
240{
241 if (!gGeoManager) {
242 ::Error("TGeoElementTable::GetElementTable", "Create a geometry manager first");
243 return nullptr;
244 }
246}
247
248////////////////////////////////////////////////////////////////////////////////
249/// Add an isotope for this element. All isotopes have to be isotopes of the same element.
250
251void TGeoElement::AddIsotope(TGeoIsotope *isotope, Double_t relativeAbundance)
252{
253 if (!fIsotopes) {
254 fNisotopes = 1;
255 fIsotopes = new TObjArray();
256 fAbundances = new Double_t[1];
257 }
258 Int_t ncurrent = 0;
259 TGeoIsotope *isocrt;
260 for (ncurrent=0; ncurrent<fNisotopes; ncurrent++)
261 if (!fIsotopes->At(ncurrent)) break;
262 if (ncurrent==fNisotopes) {
263 // User requested overwriting a standard element - we need to extend dynamically the support arrays
264 Double_t *abundances = new Double_t[fNisotopes + 1];
265 memcpy(abundances, fAbundances, fNisotopes * sizeof(Double_t));
266 delete[] fAbundances;
267 fAbundances = abundances;
268 fNisotopes++;
269 }
270 // Check Z of the new isotope
271 if ((fZ!=0) && (isotope->GetZ()!=fZ)) {
272 Fatal("AddIsotope", "Trying to add isotope %s with different Z to the same element %s",
273 isotope->GetName(), GetName());
274 return;
275 } else {
276 fZ = isotope->GetZ();
277 }
278 fIsotopes->Add(isotope);
279 fAbundances[ncurrent] = relativeAbundance;
280 if (ncurrent==fNisotopes-1) {
281 Double_t weight = 0.0;
282 Double_t aeff = 0.0;
283 Double_t neff = 0.0;
284 for (Int_t i=0; i<fNisotopes; i++) {
285 isocrt = (TGeoIsotope*)fIsotopes->At(i);
286 aeff += fAbundances[i]*isocrt->GetA();
287 neff += fAbundances[i]*isocrt->GetN();
288 weight += fAbundances[i];
289 }
290 aeff /= weight;
291 neff /= weight;
292 fN = (Int_t)neff;
293 fA = aeff;
294 }
296}
297
298////////////////////////////////////////////////////////////////////////////////
299/// Returns effective number of nucleons.
300
302{
303 if (!fNisotopes) return fN;
304 TGeoIsotope *isocrt;
305 Double_t weight = 0.0;
306 Double_t neff = 0.0;
307 for (Int_t i=0; i<fNisotopes; i++) {
308 isocrt = (TGeoIsotope*)fIsotopes->At(i);
309 neff += fAbundances[i]*isocrt->GetN();
310 weight += fAbundances[i];
311 }
312 neff /= weight;
313 return neff;
314}
315
316////////////////////////////////////////////////////////////////////////////////
317/// Return i-th isotope in the element.
318
320{
321 if (i>=0 && i<fNisotopes) {
322 return (TGeoIsotope*)fIsotopes->At(i);
323 }
324 return nullptr;
325}
326
327////////////////////////////////////////////////////////////////////////////////
328/// Return relative abundance of i-th isotope in this element.
329
331{
332 if (i>=0 && i<fNisotopes) return fAbundances[i];
333 return 0.0;
334}
335
337
338////////////////////////////////////////////////////////////////////////////////
339/// Dummy I/O constructor
340
342 :TNamed(),
343 fZ(0),
344 fN(0),
345 fA(0)
346{
347}
348
349////////////////////////////////////////////////////////////////////////////////
350/// Constructor
351
353 :TNamed(name,""),
354 fZ(z),
355 fN(n),
356 fA(a)
357{
358 if (z<1) Fatal("ctor", "Not allowed Z=%d (<1) for isotope: %s", z,name);
359 if (n<z) Fatal("ctor", "Not allowed Z=%d < N=%d for isotope: %s", z,n,name);
361}
362
363////////////////////////////////////////////////////////////////////////////////
364/// Find existing isotope by name.
365
367{
369 if (!elTable) return 0;
370 return elTable->FindIsotope(name);
371}
372
373////////////////////////////////////////////////////////////////////////////////
374/// Print this isotope
375
377{
378 printf("Isotope: %s Z=%d N=%d A=%f [g/mole]\n", GetName(), fZ,fN,fA);
379}
380
382
383////////////////////////////////////////////////////////////////////////////////
384/// Default constructor
385
387{
389 fENDFcode = 0;
390 fIso = 0;
391 fLevel = 0;
392 fDeltaM = 0;
393 fHalfLife = 0;
394 fNatAbun = 0;
395 fTH_F = 0;
396 fTG_F = 0;
397 fTH_S = 0;
398 fTG_S = 0;
399 fStatus = 0;
400 fRatio = 0;
401 fDecays = 0;
402}
403
404////////////////////////////////////////////////////////////////////////////////
405/// Constructor.
406
408 Double_t deltaM, Double_t halfLife, const char* JP,
409 Double_t natAbun, Double_t th_f, Double_t tg_f, Double_t th_s,
410 Double_t tg_s, Int_t status)
411 :TGeoElement("", JP, zz, aa)
412{
414 fENDFcode = ENDF(aa,zz,iso);
415 fIso = iso;
416 fLevel = level;
417 fDeltaM = deltaM;
418 fHalfLife = halfLife;
419 fTitle = JP;
420 if (!fTitle.Length()) fTitle = "?";
421 fNatAbun = natAbun;
422 fTH_F = th_f;
423 fTG_F = tg_f;
424 fTH_S = th_s;
425 fTG_S = tg_s;
426 fStatus = status;
427 fDecays = 0;
428 fRatio = 0;
429 MakeName(aa,zz,iso);
430 if ((TMath::Abs(fHalfLife)<1.e-30) || fHalfLife<-1) Warning("ctor","Element %s has T1/2=%g [s]", fName.Data(), fHalfLife);
431}
432
433////////////////////////////////////////////////////////////////////////////////
434/// Destructor.
435
437{
438 if (fDecays) {
439 fDecays->Delete();
440 delete fDecays;
441 }
442 if (fRatio) delete fRatio;
443}
444
445////////////////////////////////////////////////////////////////////////////////
446/// Adds a decay mode for this element.
447
448void TGeoElementRN::AddDecay(Int_t decay, Int_t diso, Double_t branchingRatio, Double_t qValue)
449{
450 if (branchingRatio<1E-20) {
451 TString decayName;
452 TGeoDecayChannel::DecayName(decay, decayName);
453 Warning("AddDecay", "Decay %s of %s has BR=0. Not added.", decayName.Data(),fName.Data());
454 return;
455 }
456 TGeoDecayChannel *dc = new TGeoDecayChannel(decay,diso,branchingRatio, qValue);
457 dc->SetParent(this);
458 if (!fDecays) fDecays = new TObjArray(5);
459 fDecays->Add(dc);
460}
461
462////////////////////////////////////////////////////////////////////////////////
463/// Adds a decay channel to the list of decays.
464
466{
467 dc->SetParent(this);
468 if (!fDecays) fDecays = new TObjArray(5);
469 fDecays->Add(dc);
470}
471
472////////////////////////////////////////////////////////////////////////////////
473/// Get number of decay channels of this element.
474
476{
477 if (!fDecays) return 0;
478 return fDecays->GetEntriesFast();
479}
480
481////////////////////////////////////////////////////////////////////////////////
482/// Get the activity in Bq of a gram of material made from this element.
483
485{
486 static const Double_t ln2 = TMath::Log(2.);
487 Double_t sa = (fHalfLife>0 && fA>0)?(ln2*TMath::Na()/fHalfLife/fA):0.;
488 return sa;
489}
490
491////////////////////////////////////////////////////////////////////////////////
492/// Check if all decay chain of the element is OK.
493
495{
497 TObject *oelem = (TObject*)this;
499 TGeoElementRN *elem;
501 TString decayName;
502 if (!table) {
503 Error("CheckDecays", "Element table not present");
504 return kFALSE;
505 }
506 Bool_t resultOK = kTRUE;
507 if (!fDecays) {
509 return resultOK;
510 }
511 Double_t br = 0.;
512 Int_t decayResult = 0;
513 TIter next(fDecays);
514 while ((dc=(TGeoDecayChannel*)next())) {
515 br += dc->BranchingRatio();
516 decayResult = DecayResult(dc);
517 if (decayResult) {
518 elem = table->GetElementRN(decayResult);
519 if (!elem) {
520 TGeoDecayChannel::DecayName(dc->Decay(),decayName);
521 Error("CheckDecays", "Element after decay %s of %s not found in DB", decayName.Data(),fName.Data());
522 return kFALSE;
523 }
524 dc->SetDaughter(elem);
525 resultOK = elem->CheckDecays();
526 }
527 }
528 if (TMath::Abs(br-100) > 1.E-3) {
529 Warning("CheckDecays", "BR for decays of element %s sum-up = %f", fName.Data(), br);
530 resultOK = kFALSE;
531 }
533 return resultOK;
534}
535
536////////////////////////////////////////////////////////////////////////////////
537/// Returns ENDF code of decay result.
538
540{
541 Int_t da, dz, diso;
542 dc->DecayShift(da, dz, diso);
543 if (da == -99 || dz == -99) return 0;
544 return ENDF(Int_t(fA)+da,fZ+dz,fIso+diso);
545}
546
547////////////////////////////////////////////////////////////////////////////////
548/// Fills the input array with the set of RN elements resulting from the decay of
549/// this one. All element in the list will contain the time evolution of their
550/// proportion by number with respect to this element. The proportion can be
551/// retrieved via the method TGeoElementRN::Ratio().
552/// The precision represent the minimum cumulative branching ratio for
553/// which decay products are still taken into account.
554
555void TGeoElementRN::FillPopulation(TObjArray *population, Double_t precision, Double_t factor)
556{
557 TGeoElementRN *elem;
558 TGeoElemIter next(this, precision);
559 TGeoBatemanSol s(this);
560 s.Normalize(factor);
561 AddRatio(s);
562 if (!population->FindObject(this)) population->Add(this);
563 while ((elem=next())) {
564 TGeoBatemanSol ratio(next.GetBranch());
565 ratio.Normalize(factor);
566 elem->AddRatio(ratio);
567 if (!population->FindObject(elem)) population->Add(elem);
568 }
569}
570
571////////////////////////////////////////////////////////////////////////////////
572/// Generate a default name for the element.
573
575{
576 fName = "";
577 if (z==0 && a==1) {
578 fName = "neutron";
579 return;
580 }
581 if (z>=1 && z<= gMaxElem) fName += TString::Format("%3d-%s-",z,gElName[z-1]);
582 else fName = "?? -?? -";
583 if (a>=1 && a<=999) fName += TString::Format("%3.3d",a);
584 else fName += "??";
585 if (iso>0 && iso<gMaxLevel) fName += TString::Format("%c", gLevName[iso]);
586 fName.ReplaceAll(" ","");
587}
588
589////////////////////////////////////////////////////////////////////////////////
590/// Print info about the element;
591
593{
594 printf("\n%-12s ",fName.Data());
595 printf("ENDF=%d; ",fENDFcode);
596 printf("A=%d; ",(Int_t)fA);
597 printf("Z=%d; ",fZ);
598 printf("Iso=%d; ",fIso);
599 printf("Level=%g[MeV]; ",fLevel);
600 printf("Dmass=%g[MeV]; ",fDeltaM);
601 if (fHalfLife>0) printf("Hlife=%g[s]\n",fHalfLife);
602 else printf("Hlife=INF\n");
603 printf("%13s"," ");
604 printf("J/P=%s; ",fTitle.Data());
605 printf("Abund=%g; ",fNatAbun);
606 printf("Htox=%g; ",fTH_F);
607 printf("Itox=%g; ",fTG_F);
608 printf("Stat=%d\n",fStatus);
609 if(!fDecays) return;
610 printf("Decay modes:\n");
611 TIter next(fDecays);
613 while ((dc=(TGeoDecayChannel*)next())) dc->Print(option);
614}
615
616////////////////////////////////////////////////////////////////////////////////
617/// Create element from line record.
618
620{
621 Int_t a,z,iso,status;
622 Double_t level, deltaM, halfLife, natAbun, th_f, tg_f, th_s, tg_s;
623 char name[20],jp[20];
624 sscanf(&line[0], "%s%d%d%d%lg%lg%lg%s%lg%lg%lg%lg%lg%d%d", name,&a,&z,&iso,&level,&deltaM,
625 &halfLife,jp,&natAbun,&th_f,&tg_f,&th_s,&tg_s,&status,&ndecays);
626 TGeoElementRN *elem = new TGeoElementRN(a,z,iso,level,deltaM,halfLife,
627 jp,natAbun,th_f,tg_f,th_s,tg_s,status);
628 return elem;
629}
630
631////////////////////////////////////////////////////////////////////////////////
632/// Save primitive for RN elements.
633
635{
636 if (!strcmp(option,"h")) {
637 // print a header if requested
638 out << "#====================================================================================================================================" << std::endl;
639 out << "# Name A Z ISO LEV[MeV] DM[MeV] T1/2[s] J/P ABUND[%] HTOX ITOX HTOX ITOX STAT NDCY" << std::endl;
640 out << "#====================================================================================================================================" << std::endl;
641 }
642 out << std::setw(11) << fName.Data();
643 out << std::setw(5) << (Int_t)fA;
644 out << std::setw(5) << fZ;
645 out << std::setw(5) << fIso;
646 out << std::setw(10) << std::setiosflags(std::ios::fixed) << std::setprecision(5) << fLevel;
647 out << std::setw(10) << std::setiosflags(std::ios::fixed) << std::setprecision(5) << fDeltaM;
648 out << std::setw(10) << std::setiosflags(std::ios::scientific) << std::setprecision(3) << fHalfLife;
649 out << std::setw(13) << fTitle.Data();
650 out << std::setw(10) << std::setiosflags(std::ios::fixed) << std::setprecision(5) << fNatAbun;
651 out << std::setw(10) << std::setiosflags(std::ios::fixed) << std::setprecision(5) << fTH_F;
652 out << std::setw(10) << std::setiosflags(std::ios::fixed) << std::setprecision(5) << fTG_F;
653 out << std::setw(10) << std::setiosflags(std::ios::fixed) << std::setprecision(5) << fTH_S;
654 out << std::setw(10) << std::setiosflags(std::ios::fixed) << std::setprecision(5) << fTG_S;
655 out << std::setw(5) << fStatus;
656 Int_t ndecays = 0;
657 if (fDecays) ndecays = fDecays->GetEntries();
658 out << std::setw(5) << ndecays;
659 out << std::endl;
660 if (fDecays) {
661 TIter next(fDecays);
663 while ((dc=(TGeoDecayChannel*)next())) dc->SavePrimitive(out);
664 }
665}
666
667////////////////////////////////////////////////////////////////////////////////
668/// Adds a proportion ratio to the existing one.
669
671{
672 if (!fRatio) fRatio = new TGeoBatemanSol(ratio);
673 else *fRatio += ratio;
674}
675
676////////////////////////////////////////////////////////////////////////////////
677/// Clears the existing ratio.
678
680{
681 if (fRatio) {
682 delete fRatio;
683 fRatio = 0;
684 }
685}
686
688
689////////////////////////////////////////////////////////////////////////////////
690/// Assignment.
691///assignment operator
692
694{
695 if(this!=&dc) {
697 fDecay = dc.fDecay;
698 fDiso = dc.fDiso;
700 fQvalue = dc.fQvalue;
701 fParent = dc.fParent;
702 fDaughter = dc.fDaughter;
703 }
704 return *this;
705}
706
707////////////////////////////////////////////////////////////////////////////////
708/// Returns name of decay.
709
710const char *TGeoDecayChannel::GetName() const
711{
712 static TString name = "";
713 name = "";
714 if (!fDecay) return gDecayName[gMaxDecay];
715 for (Int_t i=0; i<gMaxDecay; i++) {
716 if (1<<i & fDecay) {
717 if (name.Length()) name += "+";
718 name += gDecayName[i];
719 }
720 }
721 return name.Data();
722}
723
724////////////////////////////////////////////////////////////////////////////////
725/// Returns decay name.
726
728{
729 if (!decay) {
731 return;
732 }
733 name = "";
734 for (Int_t i=0; i<gMaxDecay; i++) {
735 if (1<<i & decay) {
736 if (name.Length()) name += "+";
737 name += gDecayName[i];
738 }
739 }
740}
741
742////////////////////////////////////////////////////////////////////////////////
743/// Get index of this channel in the list of decays of the parent nuclide.
744
746{
747 return fParent->Decays()->IndexOf(this);
748}
749
750////////////////////////////////////////////////////////////////////////////////
751/// Prints decay info.
752
754{
757 printf("%-20s Diso: %3d BR: %9.3f%% Qval: %g\n", name.Data(),fDiso,fBranchingRatio,fQvalue);
758}
759
760////////////////////////////////////////////////////////////////////////////////
761/// Create element from line record.
762
764{
765 char name[80];
766 Int_t decay,diso;
767 Double_t branchingRatio, qValue;
768 sscanf(&line[0], "%s%d%d%lg%lg", name,&decay,&diso,&branchingRatio,&qValue);
769 TGeoDecayChannel *dc = new TGeoDecayChannel(decay,diso,branchingRatio,qValue);
770 return dc;
771}
772
773////////////////////////////////////////////////////////////////////////////////
774/// Save primitive for decays.
775
777{
778 TString decayName;
779 DecayName(fDecay, decayName);
780 out << std::setw(50) << decayName.Data();
781 out << std::setw(10) << fDecay;
782 out << std::setw(10) << fDiso;
783 out << std::setw(12) << std::setiosflags(std::ios::fixed) << std::setprecision(6) << fBranchingRatio;
784 out << std::setw(12) << std::setiosflags(std::ios::fixed) << std::setprecision(6) << fQvalue;
785 out << std::endl;
786}
787
788////////////////////////////////////////////////////////////////////////////////
789/// Returns variation in A, Z and Iso after decay.
790
792{
793 dA=dZ=0;
794 dI=fDiso;
795 for(Int_t i=0; i<gMaxDecay; ++i) {
796 if(1<<i & fDecay) {
797 if(gDecayDeltaA[i] == -99 || gDecayDeltaZ[i] == -99 ) {
798 dA=dZ=-99;
799 return;
800 }
801 dA += gDecayDeltaA[i];
802 dZ += gDecayDeltaZ[i];
803 }
804 }
805}
806
808
809////////////////////////////////////////////////////////////////////////////////
810/// Default constructor.
811
813 : fTop(top), fElem(top), fBranch(0), fLevel(0), fLimitRatio(limit), fRatio(1.)
814{
815 fBranch = new TObjArray(10);
816}
817
818////////////////////////////////////////////////////////////////////////////////
819/// Copy ctor.
820
822 :fTop(iter.fTop),
823 fElem(iter.fElem),
824 fBranch(0),
825 fLevel(iter.fLevel),
826 fLimitRatio(iter.fLimitRatio),
827 fRatio(iter.fRatio)
828{
829 if (iter.fBranch) {
830 fBranch = new TObjArray(10);
831 for (Int_t i=0; i<fLevel; i++) fBranch->Add(iter.fBranch->At(i));
832 }
833}
834
835////////////////////////////////////////////////////////////////////////////////
836/// Destructor.
837
839{
840 if (fBranch) delete fBranch;
841}
842
843////////////////////////////////////////////////////////////////////////////////
844/// Assignment.
845
847{
848 if (&iter == this) return *this;
849 fTop = iter.fTop;
850 fElem = iter.fElem;
851 fLevel = iter.fLevel;
852 if (iter.fBranch) {
853 fBranch = new TObjArray(10);
854 for (Int_t i=0; i<fLevel; i++) fBranch->Add(iter.fBranch->At(i));
855 }
857 fRatio = iter.fRatio;
858 return *this;
859}
860
861////////////////////////////////////////////////////////////////////////////////
862/// () operator.
863
865{
866 return Next();
867}
868
869////////////////////////////////////////////////////////////////////////////////
870/// Go upwards from the current location until the next branching, then down.
871
873{
875 Int_t ind, nd;
876 while (fLevel) {
877 // Current decay channel
879 ind = dc->GetIndex();
880 nd = dc->Parent()->GetNdecays();
881 fRatio /= 0.01*dc->BranchingRatio();
882 fElem = dc->Parent();
884 ind++;
885 while (ind<nd) {
886 if (Down(ind++)) return (TGeoElementRN*)fElem;
887 }
888 }
889 fElem = nullptr;
890 return nullptr;
891}
892
893////////////////////////////////////////////////////////////////////////////////
894/// Go downwards from current level via ibranch as low in the tree as possible.
895/// Return value flags if the operation was successful.
896
898{
899 if (!fElem) return nullptr;
900 TGeoDecayChannel *dc = (TGeoDecayChannel*)fElem->Decays()->At(ibranch);
901 if (!dc->Daughter()) return nullptr;
902 Double_t br = 0.01*fRatio*dc->BranchingRatio();
903 if (br < fLimitRatio) return nullptr;
904 fLevel++;
905 fRatio = br;
906 fBranch->Add(dc);
907 fElem = dc->Daughter();
908 return (TGeoElementRN*)fElem;
909}
910
911////////////////////////////////////////////////////////////////////////////////
912/// Return next element.
913
915{
916 if (!fElem) return nullptr;
917 // Check if this is the first iteration.
918 Int_t nd = fElem->GetNdecays();
919 for (Int_t i=0; i<nd; i++) if (Down(i)) return (TGeoElementRN*)fElem;
920 return Up();
921}
922
923////////////////////////////////////////////////////////////////////////////////
924/// Print info about the current decay branch.
925
926void TGeoElemIter::Print(Option_t * /*option*/) const
927{
928 TGeoElementRN *elem;
930 TString indent = "";
931 printf("=== Chain with %g %%\n", 100*fRatio);
932 for (Int_t i=0; i<fLevel; i++) {
933 dc = (TGeoDecayChannel*)fBranch->At(i);
934 elem = dc->Parent();
935 printf("%s%s (%g%% %s) T1/2=%g\n", indent.Data(), elem->GetName(),dc->BranchingRatio(),dc->GetName(),elem->HalfLife());
936 indent += " ";
937 if (i==fLevel-1) {
938 elem = dc->Daughter();
939 printf("%s%s\n", indent.Data(), elem->GetName());
940 }
941 }
942}
943
945
946////////////////////////////////////////////////////////////////////////////////
947/// default constructor
948
950{
951 fNelements = 0;
952 fNelementsRN = 0;
953 fNisotopes = 0;
954 fList = 0;
955 fListRN = 0;
956 fIsotopes = 0;
957}
958
959////////////////////////////////////////////////////////////////////////////////
960/// constructor
961
963{
964 fNelements = 0;
965 fNelementsRN = 0;
966 fNisotopes = 0;
967 fList = new TObjArray(128);
968 fListRN = 0;
969 fIsotopes = 0;
971// BuildElementsRN();
972}
973
974////////////////////////////////////////////////////////////////////////////////
975///copy constructor
976
978 TObject(get),
979 fNelements(get.fNelements),
980 fNelementsRN(get.fNelementsRN),
981 fNisotopes(get.fNisotopes),
982 fList(get.fList),
983 fListRN(get.fListRN),
984 fIsotopes(0)
985{
986}
987
988////////////////////////////////////////////////////////////////////////////////
989///assignment operator
990
992{
993 if(this!=&get) {
998 fList=get.fList;
999 fListRN=get.fListRN;
1000 fIsotopes = 0;
1001 }
1002 return *this;
1003}
1004
1005////////////////////////////////////////////////////////////////////////////////
1006/// destructor
1007
1009{
1010 if (fList) {
1011 fList->Delete();
1012 delete fList;
1013 }
1014 if (fListRN) {
1015 fListRN->Delete();
1016 delete fListRN;
1017 }
1018 if (fIsotopes) {
1019 fIsotopes->Delete();
1020 delete fIsotopes;
1021 }
1022}
1023
1024////////////////////////////////////////////////////////////////////////////////
1025/// Add an element to the table. Obsolete.
1026
1027void TGeoElementTable::AddElement(const char *name, const char *title, Int_t z, Double_t a)
1028{
1029 if (!fList) fList = new TObjArray(128);
1030 fList->AddAtAndExpand(new TGeoElement(name,title,z,a), fNelements++);
1031}
1032
1033////////////////////////////////////////////////////////////////////////////////
1034/// Add an element to the table.
1035
1036void TGeoElementTable::AddElement(const char *name, const char *title, Int_t z, Int_t n, Double_t a)
1037{
1038 if (!fList) fList = new TObjArray(128);
1039 fList->AddAtAndExpand(new TGeoElement(name,title,z,n,a), fNelements++);
1040}
1041
1042////////////////////////////////////////////////////////////////////////////////
1043/// Add a custom element to the table.
1044
1046{
1047 if (!fList) fList = new TObjArray(128);
1048 TGeoElement *orig = FindElement(elem->GetName());
1049 if (orig) {
1050 Error("AddElement", "Found element with same name: %s (%s). Cannot add to table.",
1051 orig->GetName(), orig->GetTitle());
1052 return;
1053 }
1055}
1056
1057////////////////////////////////////////////////////////////////////////////////
1058/// Add a radionuclide to the table and map it.
1059
1061{
1062 if (!fListRN) fListRN = new TObjArray(3600);
1063 if (HasRNElements() && GetElementRN(elem->ENDFCode())) return;
1064// elem->Print();
1065 fListRN->Add(elem);
1066 fNelementsRN++;
1067 fElementsRN.insert(ElementRNMap_t::value_type(elem->ENDFCode(), elem));
1068}
1069
1070////////////////////////////////////////////////////////////////////////////////
1071/// Add isotope to the table.
1072
1074{
1075 if (FindIsotope(isotope->GetName())) {
1076 Error("AddIsotope", "Isotope with the same name: %s already in table. Not adding.",isotope->GetName());
1077 return;
1078 }
1079 if (!fIsotopes) fIsotopes = new TObjArray();
1080 fIsotopes->Add(isotope);
1081}
1082
1083////////////////////////////////////////////////////////////////////////////////
1084/// Creates the default element table
1085
1087{
1088 if (HasDefaultElements()) return;
1089 AddElement("VACUUM","VACUUM" ,0, 0, 0.0);
1090 AddElement("H" ,"HYDROGEN" ,1, 1, 1.00794);
1091 AddElement("HE" ,"HELIUM" ,2, 4, 4.002602);
1092 AddElement("LI" ,"LITHIUM" ,3, 7, 6.941);
1093 AddElement("BE" ,"BERYLLIUM" ,4, 9, 9.01218);
1094 AddElement("B" ,"BORON" ,5, 11, 10.811);
1095 AddElement("C" ,"CARBON" ,6, 12, 12.0107);
1096 AddElement("N" ,"NITROGEN" ,7, 14, 14.00674);
1097 AddElement("O" ,"OXYGEN" ,8, 16, 15.9994);
1098 AddElement("F" ,"FLUORINE" ,9, 19, 18.9984032);
1099 AddElement("NE" ,"NEON" ,10, 20, 20.1797);
1100 AddElement("NA" ,"SODIUM" ,11, 23, 22.989770);
1101 AddElement("MG" ,"MAGNESIUM" ,12, 24, 24.3050);
1102 AddElement("AL" ,"ALUMINIUM" ,13, 27, 26.981538);
1103 AddElement("SI" ,"SILICON" ,14, 28, 28.0855);
1104 AddElement("P" ,"PHOSPHORUS" ,15, 31, 30.973761);
1105 AddElement("S" ,"SULFUR" ,16, 32, 32.066);
1106 AddElement("CL" ,"CHLORINE" ,17, 35, 35.4527);
1107 AddElement("AR" ,"ARGON" ,18, 40, 39.948);
1108 AddElement("K" ,"POTASSIUM" ,19, 39, 39.0983);
1109 AddElement("CA" ,"CALCIUM" ,20, 40, 40.078);
1110 AddElement("SC" ,"SCANDIUM" ,21, 45, 44.955910);
1111 AddElement("TI" ,"TITANIUM" ,22, 48, 47.867);
1112 AddElement("V" ,"VANADIUM" ,23, 51, 50.9415);
1113 AddElement("CR" ,"CHROMIUM" ,24, 52, 51.9961);
1114 AddElement("MN" ,"MANGANESE" ,25, 55, 54.938049);
1115 AddElement("FE" ,"IRON" ,26, 56, 55.845);
1116 AddElement("CO" ,"COBALT" ,27, 59, 58.933200);
1117 AddElement("NI" ,"NICKEL" ,28, 59, 58.6934);
1118 AddElement("CU" ,"COPPER" ,29, 64, 63.546);
1119 AddElement("ZN" ,"ZINC" ,30, 65, 65.39);
1120 AddElement("GA" ,"GALLIUM" ,31, 70, 69.723);
1121 AddElement("GE" ,"GERMANIUM" ,32, 73, 72.61);
1122 AddElement("AS" ,"ARSENIC" ,33, 75, 74.92160);
1123 AddElement("SE" ,"SELENIUM" ,34, 79, 78.96);
1124 AddElement("BR" ,"BROMINE" ,35, 80, 79.904);
1125 AddElement("KR" ,"KRYPTON" ,36, 84, 83.80);
1126 AddElement("RB" ,"RUBIDIUM" ,37, 85, 85.4678);
1127 AddElement("SR" ,"STRONTIUM" ,38, 88, 87.62);
1128 AddElement("Y" ,"YTTRIUM" ,39, 89, 88.90585);
1129 AddElement("ZR" ,"ZIRCONIUM" ,40, 91, 91.224);
1130 AddElement("NB" ,"NIOBIUM" ,41, 93, 92.90638);
1131 AddElement("MO" ,"MOLYBDENUM" ,42, 96, 95.94);
1132 AddElement("TC" ,"TECHNETIUM" ,43, 98, 98.0);
1133 AddElement("RU" ,"RUTHENIUM" ,44, 101, 101.07);
1134 AddElement("RH" ,"RHODIUM" ,45, 103, 102.90550);
1135 AddElement("PD" ,"PALLADIUM" ,46, 106, 106.42);
1136 AddElement("AG" ,"SILVER" ,47, 108, 107.8682);
1137 AddElement("CD" ,"CADMIUM" ,48, 112, 112.411);
1138 AddElement("IN" ,"INDIUM" ,49, 115, 114.818);
1139 AddElement("SN" ,"TIN" ,50, 119, 118.710);
1140 AddElement("SB" ,"ANTIMONY" ,51, 122, 121.760);
1141 AddElement("TE" ,"TELLURIUM" ,52, 128, 127.60);
1142 AddElement("I" ,"IODINE" ,53, 127, 126.90447);
1143 AddElement("XE" ,"XENON" ,54, 131, 131.29);
1144 AddElement("CS" ,"CESIUM" ,55, 133, 132.90545);
1145 AddElement("BA" ,"BARIUM" ,56, 137, 137.327);
1146 AddElement("LA" ,"LANTHANUM" ,57, 139, 138.9055);
1147 AddElement("CE" ,"CERIUM" ,58, 140, 140.116);
1148 AddElement("PR" ,"PRASEODYMIUM" ,59, 141, 140.90765);
1149 AddElement("ND" ,"NEODYMIUM" ,60, 144, 144.24);
1150 AddElement("PM" ,"PROMETHIUM" ,61, 145, 145.0);
1151 AddElement("SM" ,"SAMARIUM" ,62, 150, 150.36);
1152 AddElement("EU" ,"EUROPIUM" ,63, 152, 151.964);
1153 AddElement("GD" ,"GADOLINIUM" ,64, 157, 157.25);
1154 AddElement("TB" ,"TERBIUM" ,65, 159, 158.92534);
1155 AddElement("DY" ,"DYSPROSIUM" ,66, 162, 162.50);
1156 AddElement("HO" ,"HOLMIUM" ,67, 165, 164.93032);
1157 AddElement("ER" ,"ERBIUM" ,68, 167, 167.26);
1158 AddElement("TM" ,"THULIUM" ,69, 169, 168.93421);
1159 AddElement("YB" ,"YTTERBIUM" ,70, 173, 173.04);
1160 AddElement("LU" ,"LUTETIUM" ,71, 175, 174.967);
1161 AddElement("HF" ,"HAFNIUM" ,72, 178, 178.49);
1162 AddElement("TA" ,"TANTALUM" ,73, 181, 180.9479);
1163 AddElement("W" ,"TUNGSTEN" ,74, 184, 183.84);
1164 AddElement("RE" ,"RHENIUM" ,75, 186, 186.207);
1165 AddElement("OS" ,"OSMIUM" ,76, 190, 190.23);
1166 AddElement("IR" ,"IRIDIUM" ,77, 192, 192.217);
1167 AddElement("PT" ,"PLATINUM" ,78, 195, 195.078);
1168 AddElement("AU" ,"GOLD" ,79, 197, 196.96655);
1169 AddElement("HG" ,"MERCURY" ,80, 200, 200.59);
1170 AddElement("TL" ,"THALLIUM" ,81, 204, 204.3833);
1171 AddElement("PB" ,"LEAD" ,82, 207, 207.2);
1172 AddElement("BI" ,"BISMUTH" ,83, 209, 208.98038);
1173 AddElement("PO" ,"POLONIUM" ,84, 209, 209.0);
1174 AddElement("AT" ,"ASTATINE" ,85, 210, 210.0);
1175 AddElement("RN" ,"RADON" ,86, 222, 222.0);
1176 AddElement("FR" ,"FRANCIUM" ,87, 223, 223.0);
1177 AddElement("RA" ,"RADIUM" ,88, 226, 226.0);
1178 AddElement("AC" ,"ACTINIUM" ,89, 227, 227.0);
1179 AddElement("TH" ,"THORIUM" ,90, 232, 232.0381);
1180 AddElement("PA" ,"PROTACTINIUM" ,91, 231, 231.03588);
1181 AddElement("U" ,"URANIUM" ,92, 238, 238.0289);
1182 AddElement("NP" ,"NEPTUNIUM" ,93, 237, 237.0);
1183 AddElement("PU" ,"PLUTONIUM" ,94, 244, 244.0);
1184 AddElement("AM" ,"AMERICIUM" ,95, 243, 243.0);
1185 AddElement("CM" ,"CURIUM" ,96, 247, 247.0);
1186 AddElement("BK" ,"BERKELIUM" ,97, 247, 247.0);
1187 AddElement("CF" ,"CALIFORNIUM",98, 251, 251.0);
1188 AddElement("ES" ,"EINSTEINIUM",99, 252, 252.0);
1189 AddElement("FM" ,"FERMIUM" ,100, 257, 257.0);
1190 AddElement("MD" ,"MENDELEVIUM",101, 258, 258.0);
1191 AddElement("NO" ,"NOBELIUM" ,102, 259, 259.0);
1192 AddElement("LR" ,"LAWRENCIUM" ,103, 262, 262.0);
1193 AddElement("RF" ,"RUTHERFORDIUM",104, 261, 261.0);
1194 AddElement("DB" ,"DUBNIUM" ,105, 262, 262.0);
1195 AddElement("SG" ,"SEABORGIUM" ,106, 263, 263.0);
1196 AddElement("BH" ,"BOHRIUM" ,107, 262, 262.0);
1197 AddElement("HS" ,"HASSIUM" ,108, 265, 265.0);
1198 AddElement("MT" ,"MEITNERIUM" ,109, 266, 266.0);
1199 AddElement("UUN" ,"UNUNNILIUM" ,110, 269, 269.0);
1200 AddElement("UUU" ,"UNUNUNIUM" ,111, 272, 272.0);
1201 AddElement("UUB" ,"UNUNBIUM" ,112, 277, 277.0);
1202
1204}
1205
1206////////////////////////////////////////////////////////////////////////////////
1207/// Creates the list of radionuclides.
1208
1210{
1211 if (HasRNElements()) return;
1212 TGeoElementRN *elem;
1213 TString rnf = "RadioNuclides.txt";
1215 FILE *fp = fopen(rnf, "r");
1216 if (!fp) {
1217 Error("ImportElementsRN","File RadioNuclides.txt not found");
1218 return;
1219 }
1220 char line[150];
1221 Int_t ndecays = 0;
1222 Int_t i;
1223 while (fgets(&line[0],140,fp)) {
1224 if (line[0]=='#') continue;
1225 elem = TGeoElementRN::ReadElementRN(line, ndecays);
1226 for (i=0; i<ndecays; i++) {
1227 if (!fgets(&line[0],140,fp)) {
1228 Error("ImportElementsRN", "Error parsing RadioNuclides.txt file");
1229 fclose(fp);
1230 return;
1231 }
1233 elem->AddDecay(dc);
1234 }
1235 AddElementRN(elem);
1236// elem->Print();
1237 }
1239 CheckTable();
1240 fclose(fp);
1241}
1242
1243////////////////////////////////////////////////////////////////////////////////
1244/// Checks status of element table.
1245
1247{
1248 if (!HasRNElements()) return HasDefaultElements();
1249 TGeoElementRN *elem;
1251 TIter next(fListRN);
1252 while ((elem=(TGeoElementRN*)next())) {
1253 if (!elem->CheckDecays()) result = kFALSE;
1254 }
1255 return result;
1256}
1257
1258////////////////////////////////////////////////////////////////////////////////
1259/// Export radionuclides in a file.
1260
1262{
1263 if (!HasRNElements()) return;
1264 TString sname = filename;
1265 if (!sname.Length()) sname = "RadioNuclides.txt";
1266 std::ofstream out;
1267 out.open(sname.Data(), std::ios::out);
1268 if (!out.good()) {
1269 Error("ExportElementsRN", "Cannot open file %s", sname.Data());
1270 return;
1271 }
1272
1273 TGeoElementRN *elem;
1274 TIter next(fListRN);
1275 Int_t i=0;
1276 while ((elem=(TGeoElementRN*)next())) {
1277 if ((i%48)==0) elem->SavePrimitive(out,"h");
1278 else elem->SavePrimitive(out);
1279 i++;
1280 }
1281 out.close();
1282}
1283
1284////////////////////////////////////////////////////////////////////////////////
1285/// Search an element by symbol or full name
1286/// Exact matching
1287
1289{
1290 TGeoElement *elem;
1291 elem = (TGeoElement*)fList->FindObject(name);
1292 if (elem) return elem;
1293 // Search case insensitive by element name
1294 TString s(name);
1295 s.ToUpper();
1296 elem = (TGeoElement*)fList->FindObject(s.Data());
1297 if (elem) return elem;
1298 // Search by full name
1299 TIter next(fList);
1300 while ((elem=(TGeoElement*)next())) {
1301 if (s == elem->GetTitle()) return elem;
1302 }
1303 return 0;
1304}
1305
1306////////////////////////////////////////////////////////////////////////////////
1307/// Find existing isotope by name. Not optimized for a big number of isotopes.
1308
1310{
1311 if (!fIsotopes) return nullptr;
1313}
1314
1315////////////////////////////////////////////////////////////////////////////////
1316/// Retrieve a radionuclide by ENDF code.
1317
1319{
1320 if (!HasRNElements()) {
1321 TGeoElementTable *table = (TGeoElementTable*)this;
1322 table->ImportElementsRN();
1323 if (!fListRN) return 0;
1324 }
1325 ElementRNMap_t::const_iterator it = fElementsRN.find(ENDFcode);
1326 if (it != fElementsRN.end()) return it->second;
1327 return 0;
1328}
1329
1330////////////////////////////////////////////////////////////////////////////////
1331/// Retrieve a radionuclide by a, z, and isomeric state.
1332
1334{
1335 return GetElementRN(TGeoElementRN::ENDF(a,z,iso));
1336}
1337
1338////////////////////////////////////////////////////////////////////////////////
1339/// Print table of elements. The accepted options are:
1340/// "" - prints everything by default
1341/// "D" - prints default elements only
1342/// "I" - prints isotopes
1343/// "R" - prints radio-nuclides only if imported
1344/// "U" - prints user-defined elements only
1345
1347{
1348 TString opt(option);
1349 opt.ToUpper();
1350 Int_t induser = HasDefaultElements() ? 113 : 0;
1351 // Default elements
1352 if (opt=="" || opt=="D") {
1353 if (induser) printf("================\nDefault elements\n================\n");
1354 for (Int_t iel=0; iel<induser; ++iel) fList->At(iel)->Print();
1355 }
1356 // Isotopes
1357 if (opt=="" || opt=="I") {
1358 if (fIsotopes) {
1359 printf("================\nIsotopes\n================\n");
1360 fIsotopes->Print();
1361 }
1362 }
1363 // Radio-nuclides
1364 if (opt=="" || opt=="R") {
1365 if (HasRNElements()) {
1366 printf("================\nRadio-nuclides\n================\n");
1367 fListRN->Print();
1368 }
1369 }
1370 // User-defined elements
1371 if (opt=="" || opt=="U") {
1372 if (fNelements>induser) printf("================\nUser elements\n================\n");
1373 for (Int_t iel=induser; iel<fNelements; ++iel) fList->At(iel)->Print();
1374 }
1375}
1376
1378
1379////////////////////////////////////////////////////////////////////////////////
1380/// Default ctor.
1381
1383 :TObject(), TAttLine(), TAttFill(), TAttMarker(),
1384 fElem(elem),
1385 fElemTop(elem),
1386 fCsize(10),
1387 fNcoeff(0),
1388 fFactor(1.),
1389 fTmin(0.),
1390 fTmax(0.),
1391 fCoeff(nullptr)
1392{
1393 fCoeff = new BtCoef_t[fCsize];
1394 fNcoeff = 1;
1395 fCoeff[0].cn = 1.;
1396 Double_t t12 = elem->HalfLife();
1397 if (t12 == 0.) t12 = 1.e-30;
1398 if (elem->Stable()) fCoeff[0].lambda = 0.;
1399 else fCoeff[0].lambda = TMath::Log(2.)/t12;
1400}
1401
1402////////////////////////////////////////////////////////////////////////////////
1403/// Default ctor.
1404
1406 :TObject(), TAttLine(), TAttFill(), TAttMarker(),
1407 fElem(nullptr),
1408 fElemTop(nullptr),
1409 fCsize(0),
1410 fNcoeff(0),
1411 fFactor(1.),
1412 fTmin(0.),
1413 fTmax(0.),
1414 fCoeff(nullptr)
1415{
1416 TGeoDecayChannel *dc = (TGeoDecayChannel*)chain->At(0);
1417 if (dc) fElemTop = dc->Parent();
1418 dc = (TGeoDecayChannel*)chain->At(chain->GetEntriesFast()-1);
1419 if (dc) {
1420 fElem = dc->Daughter();
1421 fCsize = chain->GetEntriesFast()+1;
1422 fCoeff = new BtCoef_t[fCsize];
1423 FindSolution(chain);
1424 }
1425}
1426
1427////////////////////////////////////////////////////////////////////////////////
1428/// Copy constructor.
1429
1431 :TObject(other), TAttLine(other), TAttFill(other), TAttMarker(other),
1432 fElem(other.fElem),
1433 fElemTop(other.fElemTop),
1434 fCsize(other.fCsize),
1435 fNcoeff(other.fNcoeff),
1436 fFactor(other.fFactor),
1437 fTmin(other.fTmin),
1438 fTmax(other.fTmax),
1439 fCoeff(nullptr)
1440{
1441 if (fCsize) {
1442 fCoeff = new BtCoef_t[fCsize];
1443 for (Int_t i=0; i<fNcoeff; i++) {
1444 fCoeff[i].cn = other.fCoeff[i].cn;
1445 fCoeff[i].lambda = other.fCoeff[i].lambda;
1446 }
1447 }
1448}
1449
1450////////////////////////////////////////////////////////////////////////////////
1451/// Destructor.
1452
1454{
1455 if (fCoeff) delete [] fCoeff;
1456}
1457
1458////////////////////////////////////////////////////////////////////////////////
1459/// Assignment.
1460
1462{
1463 if (this == &other) return *this;
1464 TObject::operator=(other);
1465 TAttLine::operator=(other);
1466 TAttFill::operator=(other);
1467 TAttMarker::operator=(other);
1468 fElem = other.fElem;
1469 fElemTop = other.fElemTop;
1470 if (fCoeff) delete [] fCoeff;
1471 fCoeff = 0;
1472 fCsize = other.fCsize;
1473 fNcoeff = other.fNcoeff;
1474 fFactor = other.fFactor;
1475 fTmin = other.fTmin;
1476 fTmax = other.fTmax;
1477 if (fCsize) {
1478 fCoeff = new BtCoef_t[fCsize];
1479 for (Int_t i=0; i<fNcoeff; i++) {
1480 fCoeff[i].cn = other.fCoeff[i].cn;
1481 fCoeff[i].lambda = other.fCoeff[i].lambda;
1482 }
1483 }
1484 return *this;
1485}
1486
1487////////////////////////////////////////////////////////////////////////////////
1488/// Addition of other solution.
1489
1491{
1492 if (other.GetElement() != fElem) {
1493 Error("operator+=", "Cannot add 2 solutions for different elements");
1494 return *this;
1495 }
1496 Int_t i,j;
1497 BtCoef_t *coeff = fCoeff;
1498 Int_t ncoeff = fNcoeff + other.fNcoeff;
1499 if (ncoeff > fCsize) {
1500 fCsize = ncoeff;
1501 coeff = new BtCoef_t[ncoeff];
1502 for (i=0; i<fNcoeff; i++) {
1503 coeff[i].cn = fCoeff[i].cn;
1504 coeff[i].lambda = fCoeff[i].lambda;
1505 }
1506 delete [] fCoeff;
1507 fCoeff = coeff;
1508 }
1509 ncoeff = fNcoeff;
1510 for (j=0; j<other.fNcoeff; j++) {
1511 for (i=0; i<fNcoeff; i++) {
1512 if (coeff[i].lambda == other.fCoeff[j].lambda) {
1513 coeff[i].cn += fFactor * other.fCoeff[j].cn;
1514 break;
1515 }
1516 }
1517 if (i == fNcoeff) {
1518 coeff[ncoeff].cn = fFactor * other.fCoeff[j].cn;
1519 coeff[ncoeff].lambda = other.fCoeff[j].lambda;
1520 ncoeff++;
1521 }
1522 }
1523 fNcoeff = ncoeff;
1524 return *this;
1525}
1526////////////////////////////////////////////////////////////////////////////////
1527/// Find concentration of the element at a given time.
1528
1530{
1531 Double_t conc = 0.;
1532 for (Int_t i=0; i<fNcoeff; i++)
1533 conc += fCoeff[i].cn * TMath::Exp(-fCoeff[i].lambda * time);
1534 return conc;
1535}
1536
1537////////////////////////////////////////////////////////////////////////////////
1538/// Draw the solution of Bateman equation versus time.
1539
1541{
1542 if (!gGeoManager) return;
1544}
1545
1546////////////////////////////////////////////////////////////////////////////////
1547/// Find the solution for the Bateman equations corresponding to the decay
1548/// chain described by an array ending with element X.
1549/// A->B->...->X
1550/// Cn = SUM [Ain * exp(-LMBDi*t)];
1551/// Cn - concentration Nx/Na
1552/// n - order of X in chain (A->B->X => n=3)
1553/// LMBDi - decay constant for element of order i in the chain
1554/// Ain = LMBD1*...*LMBD(n-1) * br1*...*br(n-1)/(LMBD1-LMBDi)...(LMBDn-LMBDi)
1555/// bri - branching ratio for decay Ei->Ei+1
1556
1558{
1559 fNcoeff = 0;
1560 if (!array || !array->GetEntriesFast()) return;
1561 Int_t n = array->GetEntriesFast();
1562 TGeoDecayChannel *dc = (TGeoDecayChannel*)array->At(n-1);
1563 TGeoElementRN *elem = dc->Daughter();
1564 if (elem != fElem) {
1565 Error("FindSolution", "Last element in the list must be %s\n", fElem->GetName());
1566 return;
1567 }
1568 Int_t i,j;
1569 Int_t order = n+1;
1570 if (!fCoeff) {
1571 fCsize = order;
1572 fCoeff = new BtCoef_t[fCsize];
1573 }
1574 if (fCsize < order) {
1575 delete [] fCoeff;
1576 fCsize = order;
1577 fCoeff = new BtCoef_t[fCsize];
1578 }
1579
1580 Double_t *lambda = new Double_t[order];
1581 Double_t *br = new Double_t[n];
1582 Double_t halflife;
1583 for (i=0; i<n; i++) {
1584 dc = (TGeoDecayChannel*)array->At(i);
1585 elem = dc->Parent();
1586 br[i] = 0.01 * dc->BranchingRatio();
1587 halflife = elem->HalfLife();
1588 if (halflife==0.) halflife = 1.e-30;
1589 if (elem->Stable()) lambda[i] = 0.;
1590 else lambda[i] = TMath::Log(2.)/halflife;
1591 if (i==n-1) {
1592 elem = dc->Daughter();
1593 halflife = elem->HalfLife();
1594 if (halflife==0.) halflife = 1.e-30;
1595 if (elem->Stable()) lambda[n] = 0.;
1596 else lambda[n] = TMath::Log(2.)/halflife;
1597 }
1598 }
1599 // Check if we have equal lambdas
1600 for (i=0; i<order-1; i++) {
1601 for (j=i+1; j<order; j++) {
1602 if (lambda[j] == lambda[i]) lambda[j] += 0.001*lambda[j];
1603 }
1604 }
1605 Double_t ain;
1606 Double_t pdlambda, plambdabr=1.;
1607 for (j=0; j<n; j++) plambdabr *= lambda[j]*br[j];
1608 for (i=0; i<order; i++) {
1609 pdlambda = 1.;
1610 for (j=0; j<n+1; j++) {
1611 if (j == i) continue;
1612 pdlambda *= lambda[j] - lambda[i];
1613 }
1614 if (pdlambda == 0.) {
1615 Error("FindSolution", "pdlambda=0 !!!");
1616 delete [] lambda;
1617 delete [] br;
1618 return;
1619 }
1620 ain = plambdabr/pdlambda;
1621 fCoeff[i].cn = ain;
1622 fCoeff[i].lambda = lambda[i];
1623 }
1624 fNcoeff = order;
1626 delete [] lambda;
1627 delete [] br;
1628}
1629
1630////////////////////////////////////////////////////////////////////////////////
1631/// Normalize all coefficients with a given factor.
1632
1634{
1635 for (Int_t i=0; i<fNcoeff; i++) fCoeff[i].cn *= factor;
1636}
1637
1638////////////////////////////////////////////////////////////////////////////////
1639/// Print concentration evolution.
1640
1641void TGeoBatemanSol::Print(Option_t * /*option*/) const
1642{
1643 TString formula;
1644 formula.Form("N[%s]/N[%s] = ", fElem->GetName(), fElemTop->GetName());
1645 for (Int_t i=0; i<fNcoeff; i++) {
1646 if (i == fNcoeff-1) formula += TString::Format("%g*exp(-%g*t)", fCoeff[i].cn, fCoeff[i].lambda);
1647 else formula += TString::Format("%g*exp(-%g*t) + ", fCoeff[i].cn, fCoeff[i].lambda);
1648 }
1649 printf("%s\n", formula.Data());
1650}
1651
#define a(i)
Definition RSha256.hxx:99
int Int_t
Definition RtypesCore.h:45
constexpr Bool_t kFALSE
Definition RtypesCore.h:101
constexpr Bool_t kTRUE
Definition RtypesCore.h:100
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:377
static void indent(ostringstream &buf, int indent_level)
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
char name[80]
Definition TGX11.cxx:110
static const char gLevName[gMaxLevel]
static const Int_t gDecayDeltaZ[gMaxDecay]
static const Int_t gMaxDecay
static const char * gDecayName[gMaxDecay+1]
static const Int_t gDecayDeltaA[gMaxDecay]
static const char gElName[gMaxElem][3]
static const Int_t gMaxLevel
static const Int_t gMaxElem
R__EXTERN TGeoManager * gGeoManager
R__EXTERN TSystem * gSystem
Definition TSystem.h:560
Fill Area Attributes class.
Definition TAttFill.h:19
Line Attributes class.
Definition TAttLine.h:18
Marker Attributes class.
Definition TAttMarker.h:19
void Print(Option_t *option="") const override
Default print for collections, calls Print(option, 1).
Double_t Concentration(Double_t time) const
Find concentration of the element at a given time.
~TGeoBatemanSol()
Destructor.
Double_t fFactor
BtCoef_t * fCoeff
virtual void Draw(Option_t *option="")
Draw the solution of Bateman equation versus time.
void FindSolution(const TObjArray *array)
Find the solution for the Bateman equations corresponding to the decay chain described by an array en...
TGeoElementRN * fElem
virtual void Print(Option_t *option="") const
Print concentration evolution.
TGeoElementRN * fElemTop
TGeoBatemanSol & operator=(const TGeoBatemanSol &other)
Assignment.
void Normalize(Double_t factor)
Normalize all coefficients with a given factor.
TGeoElementRN * GetElement() const
TGeoBatemanSol & operator+=(const TGeoBatemanSol &other)
Addition of other solution.
A decay channel for a radionuclide.
void SetParent(TGeoElementRN *parent)
virtual const char * GetName() const
Returns name of decay.
TGeoElementRN * fParent
TGeoElementRN * Daughter() const
UInt_t Decay() const
virtual void Print(Option_t *opt=" ") const
Prints decay info.
static TGeoDecayChannel * ReadDecay(const char *record)
Create element from line record.
TGeoElementRN * Parent() const
TGeoElementRN * fDaughter
Double_t BranchingRatio() const
Double_t fBranchingRatio
void SetDaughter(TGeoElementRN *daughter)
TGeoDecayChannel & operator=(const TGeoDecayChannel &dc)
Assignment.
static void DecayName(UInt_t decay, TString &name)
Returns decay name.
virtual void DecayShift(Int_t &dA, Int_t &dZ, Int_t &dI) const
Returns variation in A, Z and Iso after decay.
Int_t GetIndex() const
Get index of this channel in the list of decays of the parent nuclide.
virtual void SavePrimitive(std::ostream &out, Option_t *option="")
Save primitive for decays.
Iterator for decay branches.
virtual void Print(Option_t *option="") const
Print info about the current decay branch.
Double_t fRatio
TObjArray * GetBranch() const
const TGeoElementRN * fElem
TObjArray * fBranch
TGeoElementRN * Next()
Return next element.
TGeoElemIter & operator=(const TGeoElemIter &iter)
Assignment.
virtual ~TGeoElemIter()
Destructor.
TGeoElementRN * operator()()
() operator.
const TGeoElementRN * fTop
Double_t fLimitRatio
TGeoElementRN * Up()
Go upwards from the current location until the next branching, then down.
TGeoElementRN * Down(Int_t ibranch)
Go downwards from current level via ibranch as low in the tree as possible.
Class representing a radionuclidevoid TGeoManager::SetDefaultRootUnits() { if ( fgDefaultUnits == kRo...
Double_t fNatAbun
void AddRatio(TGeoBatemanSol &ratio)
Adds a proportion ratio to the existing one.
void FillPopulation(TObjArray *population, Double_t precision=0.001, Double_t factor=1.)
Fills the input array with the set of RN elements resulting from the decay of this one.
void AddDecay(Int_t decay, Int_t diso, Double_t branchingRatio, Double_t qValue)
Adds a decay mode for this element.
Double_t fHalfLife
TObjArray * fDecays
Double_t fTH_S
virtual Int_t ENDFCode() const
Double_t fLevel
TGeoBatemanSol * fRatio
virtual void SavePrimitive(std::ostream &out, Option_t *option="")
Save primitive for RN elements.
Double_t HalfLife() const
Double_t fDeltaM
virtual Double_t GetSpecificActivity() const
Get the activity in Bq of a gram of material made from this element.
Int_t DecayResult(TGeoDecayChannel *dc) const
Returns ENDF code of decay result.
TObjArray * Decays() const
Bool_t Stable() const
Int_t GetNdecays() const
Get number of decay channels of this element.
void MakeName(Int_t a, Int_t z, Int_t iso)
Generate a default name for the element.
TGeoElementRN()
Default constructor.
Bool_t CheckDecays() const
Check if all decay chain of the element is OK.
static TGeoElementRN * ReadElementRN(const char *record, Int_t &ndecays)
Create element from line record.
virtual ~TGeoElementRN()
Destructor.
Double_t fTG_F
Double_t fTH_F
static Int_t ENDF(Int_t a, Int_t z, Int_t iso)
void ResetRatio()
Clears the existing ratio.
Double_t fTG_S
virtual void Print(Option_t *option="") const
Print info about the element;.
Table of elements.
TGeoElementTable & operator=(const TGeoElementTable &)
assignment operator
Bool_t HasRNElements() const
void ExportElementsRN(const char *filename="")
Export radionuclides in a file.
TObjArray * fListRN
virtual ~TGeoElementTable()
destructor
void AddIsotope(TGeoIsotope *isotope)
Add isotope to the table.
ElementRNMap_t fElementsRN
TGeoElementRN * GetElementRN(Int_t ENDFcode) const
Retrieve a radionuclide by ENDF code.
void AddElementRN(TGeoElementRN *elem)
Add a radionuclide to the table and map it.
Bool_t HasDefaultElements() const
TObjArray * fList
TObjArray * fIsotopes
Bool_t CheckTable() const
Checks status of element table.
void ImportElementsRN()
Creates the list of radionuclides.
void AddElement(const char *name, const char *title, Int_t z, Double_t a)
Add an element to the table. Obsolete.
virtual void Print(Option_t *option="") const
Print table of elements.
TGeoIsotope * FindIsotope(const char *name) const
Find existing isotope by name. Not optimized for a big number of isotopes.
void BuildDefaultElements()
Creates the default element table.
TGeoElementTable()
default constructor
TGeoElement * FindElement(const char *name) const
Search an element by symbol or full name Exact matching.
Base class for chemical elements.
Definition TGeoElement.h:37
Double_t fA
Definition TGeoElement.h:48
Int_t fNisotopes
Definition TGeoElement.h:47
Double_t fRadTsai
Definition TGeoElement.h:52
TGeoElement()
Default constructor.
void SetDefined(Bool_t flag=kTRUE)
Definition TGeoElement.h:90
void ComputeDerivedQuantities()
Calculate properties for an atomic number.
Double_t Neff() const
Returns effective number of nucleons.
void ComputeCoulombFactor()
Compute Coulomb correction factor (Phys Rev. D50 3-1 (1994) page 1254)
Double_t fCoulomb
Definition TGeoElement.h:51
void AddIsotope(TGeoIsotope *isotope, Double_t relativeAbundance)
Add an isotope for this element. All isotopes have to be isotopes of the same element.
TObjArray * fIsotopes
Definition TGeoElement.h:49
virtual void Print(Option_t *option="") const
Print this isotope.
static TGeoElementTable * GetElementTable()
Returns pointer to the table.
void ComputeLradTsaiFactor()
Compute Tsai's Expression for the Radiation Length (Phys Rev. D50 3-1 (1994) page 1254)
Double_t * fAbundances
Definition TGeoElement.h:50
virtual ~TGeoElement()
destructor
Bool_t HasIsotopes() const
Definition TGeoElement.h:85
Double_t GetRelativeAbundance(Int_t i) const
Return relative abundance of i-th isotope in this element.
void SetUsed(Bool_t flag=kTRUE)
Definition TGeoElement.h:91
TGeoIsotope * GetIsotope(Int_t i) const
Return i-th isotope in the element.
Double_t fA
TGeoIsotope()
Dummy I/O constructor.
Int_t GetZ() const
virtual void Print(Option_t *option="") const
Print this isotope.
Int_t GetN() const
Double_t GetA() const
static TGeoIsotope * FindIsotope(const char *name)
Find existing isotope by name.
static EDefaultUnits GetDefaultUnits()
TGeoElementTable * GetElementTable()
Returns material table. Creates it if not existing.
TVirtualGeoPainter * GetGeomPainter()
Make a default painter if none present. Returns pointer to it.
static void SetDefaultUnits(EDefaultUnits new_value)
The TNamed class is the base class for all named ROOT classes.
Definition TNamed.h:29
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:48
TString fTitle
Definition TNamed.h:33
TString fName
Definition TNamed.h:32
An array of TObjects.
Definition TObjArray.h:31
Int_t GetEntriesFast() const
Definition TObjArray.h:58
Int_t IndexOf(const TObject *obj) const override
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
Int_t GetEntries() const override
Return the number of objects in array (i.e.
void Delete(Option_t *option="") override
Remove all objects from the array AND delete all heap based objects.
TObject * At(Int_t idx) const override
Definition TObjArray.h:164
TObject * RemoveAt(Int_t idx) override
Remove object at index idx.
TObject * FindObject(const char *name) const override
Find an object in this collection using its name.
void Add(TObject *obj) override
Definition TObjArray.h:68
Mother of all ROOT objects.
Definition TObject.h:41
TObject & operator=(const TObject &rhs)
TObject assignment operator.
Definition TObject.h:298
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:201
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:956
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:774
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:970
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:998
virtual void Print(Option_t *option="") const
This method must be overridden when a class wants to print itself.
Definition TObject.cxx:630
static const TString & GetEtcDir()
Get the sysconfig directory in the installation. Static utility function.
Definition TROOT.cxx:2984
Basic string class.
Definition TString.h:139
Ssiz_t Length() const
Definition TString.h:421
const char * Data() const
Definition TString.h:380
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:704
void ToUpper()
Change string to upper case.
Definition TString.cxx:1183
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2356
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2334
virtual const char * PrependPathName(const char *dir, TString &name)
Concatenate a directory and a file name.
Definition TSystem.cxx:1084
virtual void DrawBatemanSol(TGeoBatemanSol *sol, Option_t *option="")=0
TLine * line
const Int_t n
Definition legend1.C:16
static constexpr double alpha_rcl2
static constexpr double fine_structure_const
static constexpr double fine_structure_const
static constexpr double alpha_rcl2
Double_t Exp(Double_t x)
Returns the base-e exponential function of x, which is e raised to the power x.
Definition TMath.h:707
Double_t Log(Double_t x)
Returns the natural logarithm of x.
Definition TMath.h:754
constexpr Double_t Na()
Avogadro constant (Avogadro's Number) in .
Definition TMath.h:284
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:123