34 ClassImp(TGeoMaterial);
39 TGeoMaterial::TGeoMaterial()
40 :TNamed(), TAttFill(),
49 fState(kMatStateUndefined),
56 TGeoUnit::setUnitType(TGeoUnit::unitType());
59 fTemperature = STP_temperature;
60 fPressure = STP_pressure;
61 fState = kMatStateUndefined;
67 TGeoMaterial::TGeoMaterial(
const char *name)
68 :TNamed(name,
""), TAttFill(),
77 fState(kMatStateUndefined),
84 TGeoUnit::setUnitType(TGeoUnit::unitType());
85 fName = fName.Strip();
88 fTemperature = STP_temperature;
89 fPressure = STP_pressure;
90 fState = kMatStateUndefined;
93 gGeoManager =
new TGeoManager(
"Geometry",
"default geometry");
95 gGeoManager->AddMaterial(
this);
101 TGeoMaterial::TGeoMaterial(
const char *name, Double_t a, Double_t z,
102 Double_t rho, Double_t radlen, Double_t intlen)
103 :TNamed(name,
""), TAttFill(),
112 fState(kMatStateUndefined),
119 TGeoUnit::setUnitType(TGeoUnit::unitType());
120 fName = fName.Strip();
126 fTemperature = STP_temperature;
127 fPressure = STP_pressure;
128 fState = kMatStateUndefined;
129 SetRadLen(radlen, intlen);
131 gGeoManager =
new TGeoManager(
"Geometry",
"default geometry");
133 if (fZ - Int_t(fZ) > 1E-3)
134 Warning(
"ctor",
"Material %s defined with fractional Z=%f", GetName(), fZ);
135 if (GetElement()) GetElement()->SetUsed();
136 gGeoManager->AddMaterial(
this);
142 TGeoMaterial::TGeoMaterial(
const char *name, Double_t a, Double_t z, Double_t rho,
143 EGeoMaterialState state, Double_t temperature, Double_t pressure)
144 :TNamed(name,
""), TAttFill(),
151 fTemperature(temperature),
160 TGeoUnit::setUnitType(TGeoUnit::unitType());
161 fName = fName.Strip();
166 gGeoManager =
new TGeoManager(
"Geometry",
"default geometry");
168 if (fZ - Int_t(fZ) > 1E-3)
169 Warning(
"ctor",
"Material %s defined with fractional Z=%f", GetName(), fZ);
170 if (GetElement()) GetElement()->SetUsed();
171 gGeoManager->AddMaterial(
this);
177 TGeoMaterial::TGeoMaterial(
const char *name, TGeoElement *elem, Double_t rho)
178 :TNamed(name,
""), TAttFill(),
187 fState(kMatStateUndefined),
194 TGeoUnit::setUnitType(TGeoUnit::unitType());
195 fName = fName.Strip();
201 fTemperature = STP_temperature;
202 fPressure = STP_pressure;
203 fState = kMatStateUndefined;
205 gGeoManager =
new TGeoManager(
"Geometry",
"default geometry");
207 if (fZ - Int_t(fZ) > 1E-3)
208 Warning(
"ctor",
"Material %s defined with fractional Z=%f", GetName(), fZ);
209 if (GetElement()) GetElement()->SetUsed();
210 gGeoManager->AddMaterial(
this);
215 TGeoMaterial::TGeoMaterial(
const TGeoMaterial& gm) :
221 fDensity(gm.fDensity),
224 fTemperature(gm.fTemperature),
225 fPressure(gm.fPressure),
228 fCerenkov(gm.fCerenkov),
229 fElement(gm.fElement),
230 fUserExtension(gm.fUserExtension->Grab()),
231 fFWExtension(gm.fFWExtension->Grab())
235 TGeoUnit::setUnitType(TGeoUnit::unitType());
236 fProperties.SetOwner();
237 TIter next(&fProperties);
239 while ((property = (TNamed*)next())) fProperties.Add(
new TNamed(*property));
245 TGeoMaterial& TGeoMaterial::operator=(
const TGeoMaterial& gm)
248 TNamed::operator=(gm);
249 TAttFill::operator=(gm);
253 fDensity=gm.fDensity;
256 fTemperature=gm.fTemperature;
257 fPressure=gm.fPressure;
260 fCerenkov=gm.fCerenkov;
261 fElement=gm.fElement;
262 fUserExtension = gm.fUserExtension->Grab();
263 fFWExtension = gm.fFWExtension->Grab();
264 fProperties.SetOwner();
265 TIter next(&fProperties);
267 while ((property = (TNamed*)next())) fProperties.Add(
new TNamed(*property));
275 TGeoMaterial::~TGeoMaterial()
277 if (fUserExtension) {fUserExtension->Release(); fUserExtension=0;}
278 if (fFWExtension) {fFWExtension->Release(); fFWExtension=0;}
289 void TGeoMaterial::SetUserExtension(TGeoExtension *ext)
291 if (fUserExtension) fUserExtension->Release();
293 if (ext) fUserExtension = ext->Grab();
297 const char *TGeoMaterial::GetPropertyRef(
const char *property)
const
300 TNamed *prop = (TNamed*)fProperties.FindObject(property);
301 return (prop) ? prop->GetTitle() :
nullptr;
305 TGDMLMatrix *TGeoMaterial::GetProperty(
const char *property)
const
308 TNamed *prop = (TNamed*)fProperties.FindObject(property);
309 if ( !prop )
return nullptr;
310 return gGeoManager->GetGDMLMatrix(prop->GetTitle());
314 TGDMLMatrix *TGeoMaterial::GetProperty(Int_t i)
const
317 TNamed *prop = (TNamed*)fProperties.At(i);
318 if ( !prop )
return nullptr;
319 return gGeoManager->GetGDMLMatrix(prop->GetTitle());
323 const char *TGeoMaterial::GetConstPropertyRef(
const char *property)
const
326 TNamed *prop = (TNamed*)fConstProperties.FindObject(property);
327 return (prop) ? prop->GetTitle() :
nullptr;
331 Double_t TGeoMaterial::GetConstProperty(
const char *property, Bool_t *err)
const
334 TNamed *prop = (TNamed*)fConstProperties.FindObject(property);
336 if (err) *err = kTRUE;
339 return gGeoManager->GetProperty(prop->GetTitle(), err);
343 Double_t TGeoMaterial::GetConstProperty(Int_t i, Bool_t *err)
const
346 TNamed *prop = (TNamed*)fConstProperties.At(i);
348 if (err) *err = kTRUE;
351 return gGeoManager->GetProperty(prop->GetTitle(), err);
355 bool TGeoMaterial::AddProperty(
const char *property,
const char *ref)
357 fProperties.SetOwner();
358 if (GetPropertyRef(property)) {
359 Error(
"AddProperty",
"Property %s already added to material %s",
360 property, GetName());
363 fProperties.Add(
new TNamed(property, ref));
368 bool TGeoMaterial::AddConstProperty(
const char *property,
const char *ref)
370 fConstProperties.SetOwner();
371 if (GetConstPropertyRef(property)) {
372 Error(
"AddConstProperty",
"Constant property %s already added to material %s",
373 property, GetName());
376 fConstProperties.Add(
new TNamed(property, ref));
388 void TGeoMaterial::SetFWExtension(TGeoExtension *ext)
390 if (fFWExtension) fFWExtension->Release();
392 if (ext) fFWExtension = ext->Grab();
400 TGeoExtension *TGeoMaterial::GrabUserExtension()
const
402 if (fUserExtension)
return fUserExtension->Grab();
411 TGeoExtension *TGeoMaterial::GrabFWExtension()
const
413 if (fFWExtension)
return fFWExtension->Grab();
420 char *TGeoMaterial::GetPointerName()
const
423 name = TString::Format(
"pMat%d", GetUniqueID());
424 return (
char*)name.Data();
431 void TGeoMaterial::SetRadLen(Double_t radlen, Double_t intlen)
433 fRadLen = TMath::Abs(radlen);
434 fIntLen = TMath::Abs(intlen);
436 if (fA<0.9 || fZ<0.9) {
437 if (radlen<-1e5 || intlen<-1e-5) {
438 Error(
"SetRadLen",
"Material %s: user values taken for vacuum: radlen=%g or intlen=%g - too small", GetName(),fRadLen, fIntLen);
442 if (radlen>=0) fRadLen = 1.E30;
443 if (intlen>=0) fIntLen = 1.E30;
446 TGeoUnit::UnitType typ = TGeoUnit::unitType();
448 if ( typ == TGeoUnit::kTGeoUnits && radlen>=0 ) {
450 constexpr Double_t alr2av = 1.39621E-03*TGeoUnit::cm2;
451 constexpr Double_t al183 = 5.20948;
452 fRadLen = fA/(alr2av*fDensity*fZ*(fZ +TGeoMaterial::ScreenFactor(fZ))*
453 (al183-TMath::Log(fZ)/3-TGeoMaterial::Coulomb(fZ)));
454 fRadLen *= TGeoUnit::cm;
456 else if ( typ == TGeoUnit::kTGeant4Units && radlen>=0 ) {
458 constexpr Double_t alr2av = 1.39621E-03*TGeant4Unit::cm2;
459 constexpr Double_t al183 = 5.20948;
460 fRadLen = fA/(alr2av*fDensity*fZ*(fZ +TGeoMaterial::ScreenFactor(fZ))*
461 (al183-TMath::Log(fZ)/3-TGeoMaterial::Coulomb(fZ)));
462 fRadLen *= TGeant4Unit::cm;
465 if ( typ == TGeoUnit::kTGeoUnits && intlen>=0 ) {
466 constexpr Double_t lambda0 = 35.*TGeoUnit::g/TGeoUnit::cm2;
467 Double_t nilinv = 0.0;
468 TGeoElement *elem = GetElement();
470 Fatal(
"SetRadLen",
"Element not found for material %s", GetName());
473 Double_t nbAtomsPerVolume = TGeoUnit::Avogadro*fDensity/elem->A();
474 nilinv += nbAtomsPerVolume*TMath::Power(elem->Neff(), 0.6666667);
475 nilinv *= TGeoUnit::amu/lambda0;
476 fIntLen = (nilinv<=0) ? TGeoShape::Big() : (TGeoUnit::cm/nilinv);
478 else if ( typ == TGeoUnit::kTGeant4Units && intlen>=0 ) {
479 constexpr Double_t lambda0 = 35.*TGeant4Unit::g/TGeant4Unit::cm2;
480 Double_t nilinv = 0.0;
481 TGeoElement *elem = GetElement();
483 Fatal(
"SetRadLen",
"Element not found for material %s", GetName());
486 Double_t nbAtomsPerVolume = TGeant4Unit::Avogadro*fDensity/elem->A();
487 nilinv += nbAtomsPerVolume*TMath::Power(elem->Neff(), 0.6666667);
488 nilinv *= TGeant4Unit::amu/lambda0;
489 fIntLen = (nilinv<=0) ? TGeoShape::Big() : (TGeant4Unit::cm/nilinv);
499 Double_t TGeoMaterial::Coulomb(Double_t z)
501 Double_t az = TGeoUnit::unitType() == TGeoUnit::kTGeoUnits
502 ? TGeoUnit::fine_structure_const*z : TGeant4Unit::fine_structure_const*z;
503 Double_t az2 = az*az;
504 Double_t az4 = az2 * az2;
505 Double_t fp = ( 0.0083*az4 + 0.20206 + 1./(1.+az2) ) * az2;
506 Double_t fm = ( 0.0020*az4 + 0.0369 ) * az4;
513 Bool_t TGeoMaterial::IsEq(
const TGeoMaterial *other)
const
515 if (other==
this)
return kTRUE;
516 if (other->IsMixture())
return kFALSE;
517 if (TMath::Abs(fA-other->GetA())>1E-3)
return kFALSE;
518 if (TMath::Abs(fZ-other->GetZ())>1E-3)
return kFALSE;
519 if (TMath::Abs(fDensity-other->GetDensity())>1E-6)
return kFALSE;
520 if (GetCerenkovProperties() != other->GetCerenkovProperties())
return kFALSE;
529 void TGeoMaterial::Print(
const Option_t * )
const
531 printf(
"Material %s %s A=%g Z=%g rho=%g radlen=%g intlen=%g index=%i\n", GetName(), GetTitle(),
532 fA,fZ,fDensity, fRadLen, fIntLen, fIndex);
538 void TGeoMaterial::SavePrimitive(std::ostream &out, Option_t * )
540 if (TestBit(TGeoMaterial::kMatSavePrimitive))
return;
541 char *name = GetPointerName();
542 out <<
"// Material: " << GetName() << std::endl;
543 out <<
" a = " << fA <<
";" << std::endl;
544 out <<
" z = " << fZ <<
";" << std::endl;
545 out <<
" density = " << fDensity <<
";" << std::endl;
546 out <<
" radl = " << fRadLen <<
";" << std::endl;
547 out <<
" absl = " << fIntLen <<
";" << std::endl;
549 out <<
" " << name <<
" = new TGeoMaterial(\"" << GetName() <<
"\", a,z,density,radl,absl);" << std::endl;
550 out <<
" " << name <<
"->SetIndex(" << GetIndex() <<
");" << std::endl;
551 SetBit(TGeoMaterial::kMatSavePrimitive);
557 Int_t TGeoMaterial::GetDefaultColor()
const
559 Int_t
id = 1+ gGeoManager->GetListOfMaterials()->IndexOf(
this);
566 TGeoElement *TGeoMaterial::GetElement(Int_t)
const
568 if (fElement)
return fElement;
569 TGeoElementTable *table = gGeoManager->GetElementTable();
570 return table->GetElement(Int_t(fZ));
575 void TGeoMaterial::GetElementProp(Double_t &a, Double_t &z, Double_t &w, Int_t)
585 Int_t TGeoMaterial::GetIndex()
587 if (fIndex>=0)
return fIndex;
588 TList *matlist = gGeoManager->GetListOfMaterials();
589 fIndex = matlist->IndexOf(
this);
598 TGeoMaterial *TGeoMaterial::DecayMaterial(Double_t time, Double_t precision)
600 TObjArray *pop =
new TObjArray();
601 if (!fElement || !fElement->IsRadioNuclide())
return this;
602 FillMaterialEvolution(pop, precision);
603 Int_t ncomp = pop->GetEntriesFast();
604 if (!ncomp)
return this;
606 Double_t *weight =
new Double_t[ncomp];
609 for (i=0; i<ncomp; i++) {
610 el = (TGeoElementRN *)pop->At(i);
611 weight[i] = el->Ratio()->Concentration(time) * el->A();
614 Double_t rho = fDensity*amed/fA;
615 TGeoMixture *mix = 0;
616 Int_t ncomp1 = ncomp;
617 for (i=0; i<ncomp; i++) {
618 if ((weight[i]/amed)<precision) {
624 el = (TGeoElementRN *)pop->At(0);
627 if (ncomp1==1)
return new TGeoMaterial(TString::Format(
"%s-evol",GetName()), el, rho);
630 mix =
new TGeoMixture(TString::Format(
"%s-evol",GetName()), ncomp, rho);
631 for (i=0; i<ncomp; i++) {
633 if (weight[i]<precision)
continue;
634 el = (TGeoElementRN *)pop->At(i);
635 mix->AddElement(el, weight[i]);
665 void TGeoMaterial::FillMaterialEvolution(TObjArray *population, Double_t precision)
667 if (population->GetEntriesFast()) {
668 Error(
"FillMaterialEvolution",
"Provide an empty array !");
671 TGeoElementTable *table = gGeoManager->GetElementTable();
673 TGeoElementRN *elemrn;
674 TIter next(table->GetElementsRN());
675 while ((elemrn=(TGeoElementRN*)next())) elemrn->ResetRatio();
678 Fatal(
"FillMaterialEvolution",
"Element not found for material %s", GetName());
681 if (!elem->IsRadioNuclide()) {
682 population->Add(elem);
685 elemrn = (TGeoElementRN*)elem;
686 elemrn->FillPopulation(population, precision);
696 ClassImp(TGeoMixture);
701 TGeoMixture::TGeoMixture()
708 fVecNbOfAtomsPerVolume = 0;
715 TGeoMixture::TGeoMixture(
const char *name, Int_t , Double_t rho)
723 fVecNbOfAtomsPerVolume = 0;
726 if (fDensity < 0) fDensity = 0.001;
732 TGeoMixture::TGeoMixture(
const TGeoMixture& gm) :
734 fNelements(gm.fNelements),
735 fZmixture(gm.fZmixture),
736 fAmixture(gm.fAmixture),
737 fWeights(gm.fWeights),
739 fVecNbOfAtomsPerVolume(gm.fVecNbOfAtomsPerVolume),
740 fElements(gm.fElements)
747 TGeoMixture& TGeoMixture::operator=(
const TGeoMixture& gm)
750 TGeoMaterial::operator=(gm);
751 fNelements=gm.fNelements;
752 fZmixture=gm.fZmixture;
753 fAmixture=gm.fAmixture;
754 fWeights=gm.fWeights;
755 fNatoms = gm.fNatoms;
756 fVecNbOfAtomsPerVolume = gm.fVecNbOfAtomsPerVolume;
757 fElements = gm.fElements;
765 TGeoMixture::~TGeoMixture()
767 if (fZmixture)
delete[] fZmixture;
768 if (fAmixture)
delete[] fAmixture;
769 if (fWeights)
delete[] fWeights;
770 if (fNatoms)
delete[] fNatoms;
771 if (fVecNbOfAtomsPerVolume)
delete[] fVecNbOfAtomsPerVolume;
772 if (fElements)
delete fElements;
778 void TGeoMixture::AverageProperties()
780 TGeoUnit::UnitType typ = TGeoUnit::unitType();
781 const Double_t cm = (typ==TGeoUnit::kTGeoUnits) ? TGeoUnit::cm : TGeant4Unit::cm;
782 const Double_t cm2 = (typ==TGeoUnit::kTGeoUnits) ? TGeoUnit::cm2 : TGeant4Unit::cm2;
783 const Double_t amu = (typ==TGeoUnit::kTGeoUnits) ? TGeoUnit::amu : TGeant4Unit::amu;
784 const Double_t gram = (typ==TGeoUnit::kTGeoUnits) ? TGeoUnit::gram : TGeant4Unit::gram;
785 const Double_t na = (typ==TGeoUnit::kTGeoUnits) ? TGeoUnit::Avogadro : TGeant4Unit::Avogadro;
786 const Double_t alr2av = 1.39621E-03 * cm2;
787 const Double_t al183 = 5.20948;
788 const Double_t lambda0 = 35.*gram/cm2;
789 Double_t radinv = 0.0;
790 Double_t nilinv = 0.0;
791 Double_t nbAtomsPerVolume;
794 for (Int_t j=0;j<fNelements;j++) {
795 if (fWeights[j] <= 0)
continue;
796 fA += fWeights[j]*fAmixture[j];
797 fZ += fWeights[j]*fZmixture[j];
798 nbAtomsPerVolume = na*fDensity*fWeights[j]/GetElement(j)->A();
799 nilinv += nbAtomsPerVolume*TMath::Power(GetElement(j)->Neff(), 0.6666667);
800 Double_t zc = fZmixture[j];
801 Double_t alz = TMath::Log(zc)/3.;
802 Double_t xinv = zc*(zc+TGeoMaterial::ScreenFactor(zc))*
803 (al183-alz-TGeoMaterial::Coulomb(zc))/fAmixture[j];
804 radinv += xinv*fWeights[j];
806 radinv *= alr2av*fDensity;
807 if (radinv > 0) fRadLen = cm/radinv;
809 nilinv *= amu/lambda0;
810 fIntLen = (nilinv<=0) ? TGeoShape::Big() : (cm/nilinv);
817 void TGeoMixture::AddElement(Double_t a, Double_t z, Double_t weight)
819 TGeoElementTable *table = gGeoManager->GetElementTable();
820 if (z<1 || z>table->GetNelements()-1)
821 Fatal(
"AddElement",
"Cannot add element having Z=%d to mixture %s", (Int_t)z, GetName());
823 for (i=0; i<fNelements; i++) {
824 if (TMath::Abs(z-fZmixture[i])<1.e-6 && TMath::Abs(a-fAmixture[i])<1.e-6) {
825 fWeights[i] += weight;
831 fZmixture =
new Double_t[1];
832 fAmixture =
new Double_t[1];
833 fWeights =
new Double_t[1];
835 Int_t nelements = fNelements+1;
836 Double_t *zmixture =
new Double_t[nelements];
837 Double_t *amixture =
new Double_t[nelements];
838 Double_t *weights =
new Double_t[nelements];
839 for (Int_t j=0; j<fNelements; j++) {
840 zmixture[j] = fZmixture[j];
841 amixture[j] = fAmixture[j];
842 weights[j] = fWeights[j];
847 fZmixture = zmixture;
848 fAmixture = amixture;
856 fWeights[i] = weight;
857 if (z - Int_t(z) > 1E-3)
858 Warning(
"DefineElement",
"Mixture %s has element defined with fractional Z=%f", GetName(), z);
859 GetElement(i)->SetDefined();
860 table->GetElement((Int_t)z)->SetDefined();
869 void TGeoMixture::AddElement(TGeoMaterial *mat, Double_t weight)
871 TGeoElement *elnew, *elem;
873 if (!mat->IsMixture()) {
874 elem = mat->GetBaseElement();
876 AddElement(elem, weight);
880 AddElement(a, z, weight);
885 TGeoMixture *mix = (TGeoMixture*)mat;
887 Int_t nelem = mix->GetNelements();
891 for (i=0; i<nelem; i++) {
893 elnew = mix->GetElement(i);
894 if (!elnew)
continue;
896 for (j=0; j<fNelements; j++) {
897 if (fWeights[j]<=0)
continue;
898 elem = GetElement(j);
901 fWeights[j] += weight * (mix->GetWmixt())[i];
906 if (elfound)
continue;
908 wnew = weight * (mix->GetWmixt())[i];
909 AddElement(elnew, wnew);
916 void TGeoMixture::AddElement(TGeoElement *elem, Double_t weight)
918 TGeoElement *elemold;
919 TGeoElementTable *table = gGeoManager->GetElementTable();
920 if (!fElements) fElements =
new TObjArray(128);
921 Bool_t exist = kFALSE;
923 for (Int_t i=0; i<fNelements; i++) {
924 elemold = (TGeoElement*)fElements->At(i);
925 if (!elemold) fElements->AddAt(elemold = table->GetElement((Int_t)fZmixture[i]), i);
926 if (elemold == elem) exist = kTRUE;
928 if (!exist) fElements->AddAtAndExpand(elem, fNelements);
929 AddElement(elem->A(), elem->Z(), weight);
935 void TGeoMixture::AddElement(TGeoElement *elem, Int_t natoms)
939 TGeoElement *elemold;
940 TGeoElementTable *table = gGeoManager->GetElementTable();
941 if (!fElements) fElements =
new TObjArray(128);
943 for (i=0; i<fNelements; i++) {
944 elemold = (TGeoElement*)fElements->At(i);
945 if (!elemold) fElements->AddAt(table->GetElement((Int_t)fZmixture[i]), i);
946 else if (elemold != elem)
continue;
947 if ((elem==elemold) ||
948 (TMath::Abs(elem->Z()-fZmixture[i])<1.e-6 && TMath::Abs(elem->A()-fAmixture[i])<1.e-6)) {
949 fNatoms[i] += natoms;
951 for (j=0; j<fNelements; j++) amol += fAmixture[j]*fNatoms[j];
952 for (j=0; j<fNelements; j++) fWeights[j] = fNatoms[j]*fAmixture[j]/amol;
959 fZmixture =
new Double_t[1];
960 fAmixture =
new Double_t[1];
961 fWeights =
new Double_t[1];
962 fNatoms =
new Int_t[1];
965 Fatal(
"AddElement",
"Cannot add element by natoms in mixture %s after defining elements by weight",
969 Int_t nelements = fNelements+1;
970 Double_t *zmixture =
new Double_t[nelements];
971 Double_t *amixture =
new Double_t[nelements];
972 Double_t *weights =
new Double_t[nelements];
973 Int_t *nnatoms =
new Int_t[nelements];
974 for (j=0; j<fNelements; j++) {
975 zmixture[j] = fZmixture[j];
976 amixture[j] = fAmixture[j];
977 weights[j] = fWeights[j];
978 nnatoms[j] = fNatoms[j];
984 fZmixture = zmixture;
985 fAmixture = amixture;
990 Int_t iel = fNelements-1;
991 fZmixture[iel] = elem->Z();
992 fAmixture[iel] = elem->A();
993 fNatoms[iel] = natoms;
994 fElements->AddAtAndExpand(elem, iel);
996 for (i=0; i<fNelements; i++) {
997 if (fNatoms[i]<=0)
return;
998 amol += fAmixture[i]*fNatoms[i];
1000 for (i=0; i<fNelements; i++) fWeights[i] = fNatoms[i]*fAmixture[i]/amol;
1001 table->GetElement(elem->Z())->SetDefined();
1002 AverageProperties();
1008 void TGeoMixture::DefineElement(Int_t , Int_t z, Int_t natoms)
1010 TGeoElementTable *table = gGeoManager->GetElementTable();
1011 TGeoElement *elem = table->GetElement(z);
1013 Fatal(
"DefineElement",
"In mixture %s, element with Z=%i not found",GetName(),z);
1016 AddElement(elem, natoms);
1022 TGeoElement *TGeoMixture::GetElement(Int_t i)
const
1024 if (i<0 || i>=fNelements) {
1025 Error(
"GetElement",
"Mixture %s has only %d elements", GetName(), fNelements);
1028 TGeoElement *elem = 0;
1029 if (fElements) elem = (TGeoElement*)fElements->At(i);
1030 if (elem)
return elem;
1031 TGeoElementTable *table = gGeoManager->GetElementTable();
1032 return table->GetElement(Int_t(fZmixture[i]));
1039 Double_t TGeoMixture::GetSpecificActivity(Int_t i)
const
1041 if (i>=0 && i<fNelements)
return fWeights[i]*GetElement(i)->GetSpecificActivity();
1043 for (Int_t iel=0; iel<fNelements; iel++) {
1044 sa += fWeights[iel]*GetElement(iel)->GetSpecificActivity();
1052 Bool_t TGeoMixture::IsEq(
const TGeoMaterial *other)
const
1054 if (other->IsEqual(
this))
return kTRUE;
1055 if (!other->IsMixture())
return kFALSE;
1056 TGeoMixture *mix = (TGeoMixture*)other;
1057 if (!mix)
return kFALSE;
1058 if (fNelements != mix->GetNelements())
return kFALSE;
1059 if (TMath::Abs(fA-other->GetA())>1E-3)
return kFALSE;
1060 if (TMath::Abs(fZ-other->GetZ())>1E-3)
return kFALSE;
1061 if (TMath::Abs(fDensity-other->GetDensity())>1E-6)
return kFALSE;
1062 if (GetCerenkovProperties() != other->GetCerenkovProperties())
return kFALSE;
1065 for (Int_t i=0; i<fNelements; i++) {
1066 if (TMath::Abs(fZmixture[i]-(mix->GetZmixt())[i])>1E-3)
return kFALSE;
1067 if (TMath::Abs(fAmixture[i]-(mix->GetAmixt())[i])>1E-3)
return kFALSE;
1068 if (TMath::Abs(fWeights[i]-(mix->GetWmixt())[i])>1E-3)
return kFALSE;
1076 void TGeoMixture::Print(
const Option_t * )
const
1078 printf(
"Mixture %s %s Aeff=%g Zeff=%g rho=%g radlen=%g intlen=%g index=%i\n", GetName(), GetTitle(),
1079 fA,fZ,fDensity, fRadLen, fIntLen, fIndex);
1080 for (Int_t i=0; i<fNelements; i++) {
1081 if (fNatoms) printf(
" Element #%i : %s Z=%6.2f A=%6.2f w=%6.3f natoms=%d\n", i, GetElement(i)->GetName(),fZmixture[i],
1082 fAmixture[i], fWeights[i], fNatoms[i]);
1083 else printf(
" Element #%i : %s Z=%6.2f A=%6.2f w=%6.3f\n", i, GetElement(i)->GetName(),fZmixture[i],
1084 fAmixture[i], fWeights[i]);
1091 void TGeoMixture::SavePrimitive(std::ostream &out, Option_t * )
1093 if (TestBit(TGeoMaterial::kMatSavePrimitive))
return;
1094 char *name = GetPointerName();
1095 out <<
"// Mixture: " << GetName() << std::endl;
1096 out <<
" nel = " << fNelements <<
";" << std::endl;
1097 out <<
" density = " << fDensity <<
";" << std::endl;
1098 out <<
" " << name <<
" = new TGeoMixture(\"" << GetName() <<
"\", nel,density);" << std::endl;
1099 for (Int_t i=0; i<fNelements; i++) {
1100 TGeoElement *el = GetElement(i);
1101 out <<
" a = " << fAmixture[i] <<
"; z = "<< fZmixture[i] <<
"; w = " << fWeights[i] <<
"; // " << el->GetName() << std::endl;
1102 out <<
" " << name <<
"->DefineElement(" << i <<
",a,z,w);" << std::endl;
1104 out <<
" " << name <<
"->SetIndex(" << GetIndex() <<
");" << std::endl;
1105 SetBit(TGeoMaterial::kMatSavePrimitive);
1113 TGeoMaterial *TGeoMixture::DecayMaterial(Double_t time, Double_t precision)
1115 TObjArray *pop =
new TObjArray();
1116 FillMaterialEvolution(pop, precision);
1117 Int_t ncomp = pop->GetEntriesFast();
1118 if (!ncomp)
return this;
1121 Double_t *weight =
new Double_t[ncomp];
1124 for (i=0; i<ncomp; i++) {
1125 elem = (TGeoElement *)pop->At(i);
1126 if (!elem->IsRadioNuclide()) {
1127 j = fElements->IndexOf(elem);
1128 weight[i] = fWeights[j]*fAmixture[0]/fWeights[0];
1130 el = (TGeoElementRN*)elem;
1131 weight[i] = el->Ratio()->Concentration(time) * el->A();
1135 Double_t rho = fDensity * fWeights[0] * amed/fAmixture[0];
1136 TGeoMixture *mix = 0;
1137 Int_t ncomp1 = ncomp;
1138 for (i=0; i<ncomp; i++) {
1139 if ((weight[i]/amed)<precision) {
1145 el = (TGeoElementRN *)pop->At(0);
1148 if (ncomp1==1)
return new TGeoMaterial(TString::Format(
"%s-evol",GetName()), el, rho);
1151 mix =
new TGeoMixture(TString::Format(
"%s-evol",GetName()), ncomp, rho);
1152 for (i=0; i<ncomp; i++) {
1154 if (weight[i]<precision)
continue;
1155 el = (TGeoElementRN *)pop->At(i);
1156 mix->AddElement(el, weight[i]);
1186 void TGeoMixture::FillMaterialEvolution(TObjArray *population, Double_t precision)
1188 if (population->GetEntriesFast()) {
1189 Error(
"FillMaterialEvolution",
"Provide an empty array !");
1192 TGeoElementTable *table = gGeoManager->GetElementTable();
1194 TGeoElementRN *elemrn;
1195 TIter next(table->GetElementsRN());
1196 while ((elemrn=(TGeoElementRN*)next())) elemrn->ResetRatio();
1198 for (Int_t i=0; i<fNelements; i++) {
1199 elem = GetElement(i);
1200 if (!elem->IsRadioNuclide()) {
1201 population->Add(elem);
1204 elemrn = (TGeoElementRN*)elem;
1205 factor = fWeights[i]*fAmixture[0]/(fWeights[0]*fAmixture[i]);
1206 elemrn->FillPopulation(population, precision, factor);
1216 Double_t TGeoMaterial::ScreenFactor(Double_t z)
1218 const Double_t al183= 5.20948 , al1440 = 7.27239;
1219 Double_t alz = TMath::Log(z)/3.;
1220 Double_t factor = (al1440 - 2*alz) / (al183 - alz - TGeoMaterial::Coulomb(z));
1227 void TGeoMixture::ComputeDerivedQuantities()
1229 const Double_t Na = (TGeoUnit::unitType()==TGeoUnit::kTGeoUnits)
1230 ? TGeoUnit::Avogadro : TGeant4Unit::Avogadro;
1232 if ( fVecNbOfAtomsPerVolume )
delete [] fVecNbOfAtomsPerVolume;
1234 fVecNbOfAtomsPerVolume =
new Double_t[fNelements];
1237 for (Int_t i=0; i<fNelements; ++i) {
1238 fVecNbOfAtomsPerVolume[i] = Na*fDensity*fWeights[i]/((TGeoElement*)fElements->At(i))->A();
1240 ComputeRadiationLength();
1241 ComputeNuclearInterLength();
1248 void TGeoMixture::ComputeRadiationLength()
1251 const Double_t cm = (TGeoUnit::unitType()==TGeoUnit::kTGeoUnits) ? TGeoUnit::cm : TGeant4Unit::cm;
1252 Double_t radinv = 0.0 ;
1253 for (Int_t i=0;i<fNelements;++i) {
1254 radinv += fVecNbOfAtomsPerVolume[i]*((TGeoElement*)fElements->At(i))->GetfRadTsai();
1256 fRadLen = (radinv <= 0.0 ? DBL_MAX : cm/radinv);
1261 void TGeoMixture::ComputeNuclearInterLength()
1264 TGeoUnit::UnitType typ = TGeoUnit::unitType();
1265 const Double_t g = (typ==TGeoUnit::kTGeoUnits) ? TGeoUnit::g : TGeant4Unit::g;
1266 const Double_t cm = (typ==TGeoUnit::kTGeoUnits) ? TGeoUnit::cm : TGeant4Unit::cm;
1267 const Double_t amu = (typ==TGeoUnit::kTGeoUnits) ? TGeoUnit::amu : TGeant4Unit::amu;
1268 const Double_t lambda0 = 35*g/(cm*cm);
1269 const Double_t twothird = 2.0/3.0;
1270 Double_t NILinv = 0.0;
1271 for (Int_t i=0; i<fNelements; ++i) {
1272 Int_t Z =
static_cast<Int_t
>(((TGeoElement*)fElements->At(i))->Z()+0.5);
1273 Double_t A = ((TGeoElement*)fElements->At(i))->Neff();
1275 NILinv += fVecNbOfAtomsPerVolume[i]*A;
1277 NILinv += fVecNbOfAtomsPerVolume[i]*TMath::Exp(twothird*TMath::Log(A));
1280 NILinv *= amu/lambda0;
1281 fIntLen = (NILinv <= 0.0 ? DBL_MAX : cm/NILinv);