100 if (density < universe_mean_density)
102 G4cout <<
" G4Material WARNING:"
103 <<
" define a material with density=0 is not allowed. \n"
104 <<
" The material " << name <<
" will be constructed with the"
105 <<
" default minimal density: " << universe_mean_density/(g/cm3)
107 density = universe_mean_density;
113 fPressure = pressure;
117 fNbComponents = fNumberOfElements = 1;
126 elm =
new G4Element(
"ELM_" + name, name, z, a);
128 theElementVector->push_back(elm);
130 fMassFractionVector =
new G4double[1];
131 fMassFractionVector[0] = 1.;
132 fMassOfMolecule = a/CLHEP::Avogadro;
136 if (fDensity > kGasThreshold) { fState =
kStateSolid; }
140 ComputeDerivedQuantities();
153 InitializePointers();
155 if (density < universe_mean_density)
157 G4cout <<
"--- Warning from G4Material::G4Material()"
158 <<
" define a material with density=0 is not allowed. \n"
159 <<
" The material " << name <<
" will be constructed with the"
160 <<
" default minimal density: " << universe_mean_density/(g/cm3)
162 density = universe_mean_density;
168 fPressure = pressure;
170 fNbComponents = nComponents;
171 fMassFraction =
true;
175 if (fDensity > kGasThreshold) { fState =
kStateSolid; }
189 InitializePointers();
191 if (density < universe_mean_density)
193 G4cout <<
"--- Warning from G4Material::G4Material()"
194 <<
" define a material with density=0 is not allowed. \n"
195 <<
" The material " << name <<
" will be constructed with the"
196 <<
" default minimal density: " << universe_mean_density/(g/cm3)
198 density = universe_mean_density;
204 fPressure = pressure;
206 fBaseMaterial = bmat;
211 if(
nullptr == ptr) {
break; }
212 else { fBaseMaterial = ptr; }
220 fNbComponents = fNumberOfElements;
222 CopyPointersOfBaseMaterial();
233 InitializePointers();
241 if(fBaseMaterial ==
nullptr) {
242 delete theElementVector;
244 delete [] fMassFractionVector;
245 delete [] fAtomsVector;
248 delete [] fVecNbOfAtomsPerVolume;
252 theMaterialTable[fIndexInTable] =
nullptr;
257void G4Material::InitializePointers()
259 fBaseMaterial =
nullptr;
260 fMaterialPropertiesTable =
nullptr;
261 theElementVector =
nullptr;
262 fAtomsVector =
nullptr;
263 fMassFractionVector =
nullptr;
264 fVecNbOfAtomsPerVolume =
nullptr;
266 fIonisation =
nullptr;
267 fSandiaTable =
nullptr;
269 fDensity = fFreeElecDensity = fTemp = fPressure = 0.0;
270 fTotNbOfAtomsPerVolume = 0.0;
271 fTotNbOfElectPerVolume = 0.0;
272 fRadlen = fNuclInterLen = fMassOfMolecule = 0.0;
275 fNumberOfElements = fNbComponents = fIdxComponent = 0;
276 fMassFraction =
true;
277 fChemicalFormula =
"";
280 fIndexInTable = theMaterialTable.size();
281 for(
size_t i=0; i<fIndexInTable; ++i) {
282 if(theMaterialTable[i]->
GetName() == fName) {
283 G4cout <<
"G4Material WARNING: duplicate name of material "
288 theMaterialTable.push_back(
this);
293void G4Material::ComputeDerivedQuantities()
299 fTotNbOfAtomsPerVolume = 0.;
300 delete[] fVecNbOfAtomsPerVolume;
301 fVecNbOfAtomsPerVolume =
new G4double[fNumberOfElements];
302 fTotNbOfElectPerVolume = 0.;
303 fFreeElecDensity = 0.;
304 const G4double elecTh = 15.*CLHEP::eV;
305 for (
G4int i=0; i<fNumberOfElements; ++i) {
306 Zi = (*theElementVector)[i]->GetZ();
307 Ai = (*theElementVector)[i]->GetA();
308 fVecNbOfAtomsPerVolume[i] = Avogadro*fDensity*fMassFractionVector[i]/Ai;
309 fTotNbOfAtomsPerVolume += fVecNbOfAtomsPerVolume[i];
310 fTotNbOfElectPerVolume += fVecNbOfAtomsPerVolume[i]*Zi;
312 fFreeElecDensity += fVecNbOfAtomsPerVolume[i]*
317 ComputeRadiationLength();
318 ComputeNuclearInterLength();
320 if(fIonisation ==
nullptr)
324 if(fSandiaTable ==
nullptr)
332void G4Material::CopyPointersOfBaseMaterial()
343 fMassFractionVector =
348 delete[] fVecNbOfAtomsPerVolume;
349 fVecNbOfAtomsPerVolume =
new G4double[fNumberOfElements];
350 for (
G4int i=0; i<fNumberOfElements; ++i) {
351 fVecNbOfAtomsPerVolume[i] = factor*v[i];
353 fRadlen = fBaseMaterial->
GetRadlen()/factor;
356 if(fIonisation ==
nullptr)
376 if(0 == fIdxComponent) {
377 fMassFraction =
false;
378 fAtoms =
new std::vector<G4int>;
379 fElm =
new std::vector<const G4Element*>;
381 if(fIdxComponent >= fNbComponents) {
383 ed <<
"For material " << fName <<
" and added element "
384 << elm->
GetName() <<
" with Natoms=" << nAtoms
385 <<
" wrong attempt to add more than the declared number of elements "
386 << fIdxComponent <<
" >= " << fNbComponents;
387 G4Exception (
"G4Material::AddElementByNumberOfAtoms()",
"mat031",
392 ed <<
"For material " << fName <<
" and added element "
393 << elm->
GetName() <<
" with Natoms=" << nAtoms
394 <<
" problem: cannot add by number of atoms after "
395 <<
"addition of elements by mass fraction";
396 G4Exception (
"G4Material::AddElementByNumberOfAtoms()",
"mat031",
401 ed <<
"For material " << fName <<
" and added element "
402 << elm->
GetName() <<
" with Natoms=" << nAtoms
403 <<
" problem: number of atoms should be above zero";
404 G4Exception (
"G4Material::AddElementByNumberOfAtoms()",
"mat031",
411 for (
G4int i=0; i<fNumberOfElements; ++i) {
412 if ( elm == (*fElm)[i] ) {
413 (*fAtoms)[i] += nAtoms;
420 fElm->push_back(elm);
421 fAtoms->push_back(nAtoms);
427 if (fIdxComponent == fNbComponents) {
429 theElementVector->reserve(fNumberOfElements);
430 fAtomsVector =
new G4int[fNumberOfElements];
431 fMassFractionVector =
new G4double[fNumberOfElements];
434 for (
G4int i=0; i<fNumberOfElements; ++i) {
435 theElementVector->push_back((*fElm)[i]);
436 fAtomsVector[i] = (*fAtoms)[i];
437 G4double w = fAtomsVector[i]*(*fElm)[i]->GetA();
439 fMassFractionVector[i] = w;
441 for (
G4int i=0; i<fNumberOfElements; ++i) {
442 fMassFractionVector[i] /= Amol;
446 fMassOfMolecule = Amol/CLHEP::Avogadro;
447 ComputeDerivedQuantities();
457 if(fraction < 0.0 || fraction > 1.0) {
459 ed <<
"For material " << fName <<
" and added element "
460 << elm->
GetName() <<
" massFraction= " << fraction
462 G4Exception (
"G4Material::AddElementByMassFraction()",
"mat031",
467 ed <<
"For material " << fName <<
" and added element "
468 << elm->
GetName() <<
", massFraction= " << fraction
469 <<
", fIdxComponent=" << fIdxComponent
470 <<
" problem: cannot add by mass fraction after "
471 <<
"addition of elements by number of atoms";
472 G4Exception (
"G4Material::AddElementByMassFraction()",
"mat031",
475 if(fIdxComponent >= fNbComponents) {
477 ed <<
"For material " << fName <<
" and added element "
478 << elm->
GetName() <<
", massFraction= " << fraction
479 <<
", fIdxComponent=" << fIdxComponent
480 <<
"; attempt to add more than the declared number of components "
481 << fIdxComponent <<
" >= " << fNbComponents;
482 G4Exception (
"G4Material::AddElementByMassFraction()",
"mat031",
485 if(0 == fIdxComponent) {
486 fElmFrac =
new std::vector<G4double>;
487 fElm =
new std::vector<const G4Element*>;
493 for (
G4int i=0; i<fNumberOfElements; ++i) {
494 if ( elm == (*fElm)[i] ) {
495 (*fElmFrac)[i] += fraction;
502 fElm->push_back(elm);
503 fElmFrac->push_back(fraction);
509 if(fIdxComponent == fNbComponents) { FillVectors(); }
517 if(fraction < 0.0 || fraction > 1.0) {
519 ed <<
"For material " << fName <<
" and added material "
520 << material->
GetName() <<
", massFraction= " << fraction
527 ed <<
"For material " << fName <<
" and added material "
528 << material->
GetName() <<
", massFraction= " << fraction
529 <<
", fIdxComponent=" << fIdxComponent
530 <<
" problem: cannot add by mass fraction after "
531 <<
"addition of elements by number of atoms";
535 if(fIdxComponent >= fNbComponents) {
537 ed <<
"For material " << fName <<
" and added material "
538 << material->
GetName() <<
", massFraction= " << fraction
539 <<
"; attempt to add more than the declared number of components "
540 << fIdxComponent <<
" >= " << fNbComponents;
544 if(0 == fIdxComponent) {
545 fElmFrac =
new std::vector<G4double>;
546 fElm =
new std::vector<const G4Element*>;
551 for(
G4int j=0; j<nelm; ++j) {
556 for (
G4int i=0; i<fNumberOfElements; ++i) {
557 if ( elm == (*fElm)[i] ) {
558 (*fElmFrac)[i] += fraction*frac[j];
565 fElm->push_back(elm);
566 fElmFrac->push_back(fraction*frac[j]);
571 fMatComponents[material] = fraction;
575 if(fIdxComponent == fNbComponents) { FillVectors(); }
580void G4Material::FillVectors()
584 theElementVector->reserve(fNumberOfElements);
585 fAtomsVector =
new G4int[fNumberOfElements];
586 fMassFractionVector =
new G4double[fNumberOfElements];
589 for (
G4int i=0; i<fNumberOfElements; ++i) {
590 theElementVector->push_back((*fElm)[i]);
591 fMassFractionVector[i] = (*fElmFrac)[i];
592 wtSum += fMassFractionVector[i];
598 if (std::abs(1.-wtSum) > perThousand) {
600 ed <<
"For material " << fName <<
" sum of fractional masses "
601 << wtSum <<
" is not 1 - results may be wrong";
605 G4double coeff = (wtSum > 0.0) ? 1./wtSum : 1.0;
607 for (
G4int i=0; i<fNumberOfElements; ++i) {
608 fMassFractionVector[i] *= coeff;
609 Amol += fMassFractionVector[i]*(*theElementVector)[i]->GetA();
611 for (
G4int i=0; i<fNumberOfElements; ++i) {
613 G4lrint(fMassFractionVector[i]*Amol/(*theElementVector)[i]->
GetA());
615 ComputeDerivedQuantities();
620void G4Material::ComputeRadiationLength()
623 for (
G4int i=0; i<fNumberOfElements; ++i) {
624 radinv += fVecNbOfAtomsPerVolume[i]*((*theElementVector)[i]->GetfRadTsai());
626 fRadlen = (radinv <= 0.0 ?
DBL_MAX : 1./radinv);
631void G4Material::ComputeNuclearInterLength()
633 const G4double lambda0 = 35*CLHEP::g/CLHEP::cm2;
636 for (
G4int i=0; i<fNumberOfElements; ++i) {
637 G4int Z = (*theElementVector)[i]->GetZasInt();
638 G4double A = (*theElementVector)[i]->GetN();
640 NILinv += fVecNbOfAtomsPerVolume[i]*
A;
642 NILinv += fVecNbOfAtomsPerVolume[i]*
G4Exp(twothird*
G4Log(
A));
645 NILinv *= amu/lambda0;
646 fNuclInterLen = (NILinv <= 0.0 ?
DBL_MAX : 1./NILinv);
653 if(!IsLocked()) { fChemicalFormula = chF; }
660 if(val >= 0. && !IsLocked()) { fFreeElecDensity = val; }
668 if (
nullptr == fIonisation) {
679 return &theMaterialTable;
686 return theMaterialTable.size();
694 for(
auto& j : theMaterialTable)
696 if(j->GetName() == materialName)
704 G4cout <<
"G4Material::GetMaterial() WARNING: The material: "
706 <<
" does not exist in the table. Return NULL pointer."
717 for(
auto mat : theMaterialTable)
719 if(1 == mat->GetNumberOfElements() && z == mat->GetZ() &&
720 a == mat->GetA() && dens == mat->GetDensity())
733 for(
auto mat : theMaterialTable)
735 if(nComp == mat->GetNumberOfElements() && dens == mat->GetDensity())
747 if (fNumberOfElements > 1) {
749 ed <<
"For material " << fName <<
" ERROR in GetZ() - Nelm="
750 << fNumberOfElements <<
" > 1, which is not allowed";
754 return (*theElementVector)[0]->GetZ();
761 if (fNumberOfElements > 1) {
763 ed <<
"For material " << fName <<
" ERROR in GetA() - Nelm="
764 << fNumberOfElements <<
" > 1, which is not allowed";
768 return (*theElementVector)[0]->GetA();
775 std::ios::fmtflags mode = flux.flags();
776 flux.setf(std::ios::fixed,std::ios::floatfield);
777 G4long prec = flux.precision(3);
780 <<
" Material: " << std::setw(8) << material->fName
781 <<
" " << material->fChemicalFormula <<
" "
782 <<
" density: " << std::setw(6) << std::setprecision(3)
783 <<
G4BestUnit(material->fDensity,
"Volumic Mass")
784 <<
" RadL: " << std::setw(7) << std::setprecision(3)
786 <<
" Nucl.Int.Length: " << std::setw(7) << std::setprecision(3)
787 <<
G4BestUnit(material->fNuclInterLen,
"Length")
788 <<
"\n" << std::setw(30)
789 <<
" Imean: " << std::setw(7) << std::setprecision(3)
791 <<
" temperature: " << std::setw(6) << std::setprecision(2)
792 << (material->fTemp)/CLHEP::kelvin <<
" K"
793 <<
" pressure: " << std::setw(6) << std::setprecision(2)
794 << (material->fPressure)/CLHEP::atmosphere <<
" atm" <<
"\n";
796 for (
G4int i=0; i<material->fNumberOfElements; i++) {
798 <<
"\n ---> " << (*(material->theElementVector))[i]
799 <<
"\n ElmMassFraction: "
800 << std::setw(6)<< std::setprecision(2)
801 << (material->fMassFractionVector[i])/perCent <<
" %"
802 <<
" ElmAbundance " << std::setw(6)<< std::setprecision(2)
803 << 100*(material->fVecNbOfAtomsPerVolume[i])
804 /(material->fTotNbOfAtomsPerVolume)
807 flux.precision(prec);
808 flux.setf(mode,std::ios::floatfield);
829 flux <<
"\n***** Table : Nb of materials = " << MaterialTable.size()
832 for(
auto i : MaterialTable)
851 if(fMaterialPropertiesTable != anMPT && !IsLocked()) {
852 delete fMaterialPropertiesTable;
853 fMaterialPropertiesTable = anMPT;
859G4bool G4Material::IsLocked()
std::vector< const G4Element * > G4ElementVector
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
G4double G4Log(G4double x)
std::vector< G4Material * > G4MaterialTable
std::ostream & operator<<(std::ostream &flux, const G4Material *material)
G4GLOB_DLL std::ostream G4cout
static G4int GetNumberOfFreeElectrons(G4int Z, G4double th)
const G4String & GetName() const
G4DensityEffectCalculator * GetDensityEffectCalculator() const
G4double GetMeanExcitationEnergy() const
void ComputeDensityEffectOnFly(G4bool)
void SetMeanExcitationEnergy(G4double value)
G4double GetDensity() const
const G4String & GetChemicalFormula() const
const G4ElementVector * GetElementVector() const
const G4Material * GetBaseMaterial() const
G4MaterialPropertiesTable * GetMaterialPropertiesTable() const
G4double GetTotNbOfAtomsPerVolume() const
static size_t GetNumberOfMaterials()
const G4Element * GetElement(G4int iel) const
virtual G4bool IsExtended() const
const G4double * GetFractionVector() const
G4double GetTotNbOfElectPerVolume() const
G4IonisParamMat * GetIonisation() const
G4double GetFreeElectronDensity() const
size_t GetNumberOfElements() const
void SetChemicalFormula(const G4String &chF)
const G4int * GetAtomsVector() const
G4SandiaTable * GetSandiaTable() const
void AddElementByNumberOfAtoms(const G4Element *elm, G4int nAtoms)
G4double GetRadlen() const
G4double GetMassOfMolecule() const
const G4double * GetVecNbOfAtomsPerVolume() const
G4Material(const G4String &name, G4double z, G4double a, G4double density, G4State state=kStateUndefined, G4double temp=NTP_Temperature, G4double pressure=CLHEP::STP_Pressure)
static G4MaterialTable * GetMaterialTable()
void AddMaterial(G4Material *material, G4double fraction)
const G4String & GetName() const
void SetMaterialPropertiesTable(G4MaterialPropertiesTable *anMPT)
void SetFreeElectronDensity(G4double val)
void AddElementByMassFraction(const G4Element *elm, G4double fraction)
static G4Material * GetMaterial(const G4String &name, G4bool warning=true)
void ComputeDensityEffectOnFly(G4bool)
G4double GetNuclearInterLength() const
static G4NistManager * Instance()
G4Element * FindOrBuildElement(G4int Z, G4bool isotopes=true)
const G4ApplicationState & GetCurrentState() const
static G4StateManager * GetStateManager()