94 if (density < universe_mean_density) {
95 G4cout <<
" G4Material WARNING:"
96 <<
" define a material with density=0 is not allowed. \n"
97 <<
" The material " << name <<
" will be constructed with the"
98 <<
" default minimal density: " << universe_mean_density / (g / cm3) <<
"g/cm3"
100 density = universe_mean_density;
106 fPressure = pressure;
110 fNbComponents = fNumberOfElements = 1;
117 if (elm ==
nullptr) {
118 elm =
new G4Element(
"ELM_" + name, name, z, a);
120 theElementVector->push_back(elm);
122 fMassFractionVector =
new G4double[1];
123 fMassFractionVector[0] = 1.;
124 fMassOfMolecule = a / CLHEP::Avogadro;
127 if (fDensity > kGasThreshold) {
135 ComputeDerivedQuantities();
147 InitializePointers();
149 if (density < universe_mean_density) {
150 G4cout <<
"--- Warning from G4Material::G4Material()"
151 <<
" define a material with density=0 is not allowed. \n"
152 <<
" The material " << name <<
" will be constructed with the"
153 <<
" default minimal density: " << universe_mean_density / (g / cm3) <<
"g/cm3"
155 density = universe_mean_density;
161 fPressure = pressure;
163 fNbComponents = nComponents;
164 fMassFraction =
true;
167 if (fDensity > kGasThreshold) {
184 InitializePointers();
186 if (density < universe_mean_density) {
187 G4cout <<
"--- Warning from G4Material::G4Material()"
188 <<
" define a material with density=0 is not allowed. \n"
189 <<
" The material " << name <<
" will be constructed with the"
190 <<
" default minimal density: " << universe_mean_density / (g / cm3) <<
"g/cm3"
192 density = universe_mean_density;
198 fPressure = pressure;
200 fBaseMaterial = bmat;
202 if (
nullptr != ptr) {
204 ptr = ptr->GetBaseMaterial();
205 if (
nullptr == ptr) {
216 fNbComponents = fNumberOfElements;
218 CopyPointersOfBaseMaterial();
225 if (fBaseMaterial ==
nullptr) {
226 delete theElementVector;
228 delete[] fMassFractionVector;
229 delete[] fAtomsVector;
232 delete[] fVecNbOfAtomsPerVolume;
236 theMaterialTable[fIndexInTable] =
nullptr;
241void G4Material::InitializePointers()
243 fBaseMaterial =
nullptr;
244 fMaterialPropertiesTable =
nullptr;
245 theElementVector =
nullptr;
246 fAtomsVector =
nullptr;
247 fMassFractionVector =
nullptr;
248 fVecNbOfAtomsPerVolume =
nullptr;
250 fIonisation =
nullptr;
251 fSandiaTable =
nullptr;
253 fDensity = fFreeElecDensity = fTemp = fPressure = 0.0;
254 fTotNbOfAtomsPerVolume = 0.0;
255 fTotNbOfElectPerVolume = 0.0;
256 fRadlen = fNuclInterLen = fMassOfMolecule = 0.0;
259 fNumberOfElements = fNbComponents = fIdxComponent = 0;
260 fMassFraction =
true;
261 fChemicalFormula =
"";
264 fIndexInTable = theMaterialTable.size();
265 for (std::size_t i = 0; i < fIndexInTable; ++i) {
266 if (theMaterialTable[i]->
GetName() == fName) {
267 G4cout <<
"G4Material WARNING: duplicate name of material " << fName <<
G4endl;
271 theMaterialTable.push_back(
this);
276void G4Material::ComputeDerivedQuantities()
282 fTotNbOfAtomsPerVolume = 0.;
283 delete[] fVecNbOfAtomsPerVolume;
284 fVecNbOfAtomsPerVolume =
new G4double[fNumberOfElements];
285 fTotNbOfElectPerVolume = 0.;
286 fFreeElecDensity = 0.;
287 const G4double elecTh = 15. * CLHEP::eV;
288 for (
G4int i = 0; i < fNumberOfElements; ++i) {
289 Zi = (*theElementVector)[i]->GetZ();
290 Ai = (*theElementVector)[i]->GetA();
291 fVecNbOfAtomsPerVolume[i] = Avogadro * fDensity * fMassFractionVector[i] / Ai;
292 fTotNbOfAtomsPerVolume += fVecNbOfAtomsPerVolume[i];
293 fTotNbOfElectPerVolume += fVecNbOfAtomsPerVolume[i] * Zi;
300 ComputeRadiationLength();
301 ComputeNuclearInterLength();
303 if (fIonisation ==
nullptr) {
306 if (fSandiaTable ==
nullptr) {
313void G4Material::CopyPointersOfBaseMaterial()
329 delete[] fVecNbOfAtomsPerVolume;
330 fVecNbOfAtomsPerVolume =
new G4double[fNumberOfElements];
331 for (
G4int i = 0; i < fNumberOfElements; ++i) {
332 fVecNbOfAtomsPerVolume[i] = factor * v[i];
334 fRadlen = fBaseMaterial->
GetRadlen() / factor;
337 if (fIonisation ==
nullptr) {
354 if (0 == fIdxComponent) {
355 fMassFraction =
false;
356 fAtoms =
new std::vector<G4int>;
357 fElm =
new std::vector<const G4Element*>;
359 if (fIdxComponent >= fNbComponents) {
361 ed <<
"For material " << fName <<
" and added element " << elm->
GetName()
362 <<
" with Natoms=" << nAtoms
363 <<
" wrong attempt to add more than the declared number of elements " << fIdxComponent
364 <<
" >= " << fNbComponents;
369 ed <<
"For material " << fName <<
" and added element " << elm->
GetName()
370 <<
" with Natoms=" << nAtoms <<
" problem: cannot add by number of atoms after "
371 <<
"addition of elements by mass fraction";
376 ed <<
"For material " << fName <<
" and added element " << elm->
GetName()
377 <<
" with Natoms=" << nAtoms <<
" problem: number of atoms should be above zero";
383 if (! fElm->empty()) {
384 for (
G4int i = 0; i < fNumberOfElements; ++i) {
385 if (elm == (*fElm)[i]) {
386 (*fAtoms)[i] += nAtoms;
393 fElm->push_back(elm);
394 fAtoms->push_back(nAtoms);
400 if (fIdxComponent == fNbComponents) {
402 theElementVector->reserve(fNumberOfElements);
403 fAtomsVector =
new G4int[fNumberOfElements];
404 fMassFractionVector =
new G4double[fNumberOfElements];
407 for (
G4int i = 0; i < fNumberOfElements; ++i) {
408 theElementVector->push_back((*fElm)[i]);
409 fAtomsVector[i] = (*fAtoms)[i];
410 G4double w = fAtomsVector[i] * (*fElm)[i]->GetA();
412 fMassFractionVector[i] = w;
414 for (
G4int i = 0; i < fNumberOfElements; ++i) {
415 fMassFractionVector[i] /= Amol;
419 fMassOfMolecule = Amol / CLHEP::Avogadro;
420 ComputeDerivedQuantities();
429 if (fraction < 0.0 || fraction > 1.0) {
431 ed <<
"For material " << fName <<
" and added element " << elm->
GetName()
432 <<
" massFraction= " << fraction <<
" is wrong ";
435 if (! fMassFraction) {
437 ed <<
"For material " << fName <<
" and added element " << elm->
GetName()
438 <<
", massFraction= " << fraction <<
", fIdxComponent=" << fIdxComponent
439 <<
" problem: cannot add by mass fraction after "
440 <<
"addition of elements by number of atoms";
443 if (fIdxComponent >= fNbComponents) {
445 ed <<
"For material " << fName <<
" and added element " << elm->
GetName()
446 <<
", massFraction= " << fraction <<
", fIdxComponent=" << fIdxComponent
447 <<
"; attempt to add more than the declared number of components " << fIdxComponent
448 <<
" >= " << fNbComponents;
451 if (0 == fIdxComponent) {
452 fElmFrac =
new std::vector<G4double>;
453 fElm =
new std::vector<const G4Element*>;
458 if (! fElm->empty()) {
459 for (
G4int i = 0; i < fNumberOfElements; ++i) {
460 if (elm == (*fElm)[i]) {
461 (*fElmFrac)[i] += fraction;
468 fElm->push_back(elm);
469 fElmFrac->push_back(fraction);
475 if (fIdxComponent == fNbComponents) {
485 if (fraction < 0.0 || fraction > 1.0) {
487 ed <<
"For material " << fName <<
" and added material " << material->
GetName()
488 <<
", massFraction= " << fraction <<
" is wrong ";
491 if (! fMassFraction) {
493 ed <<
"For material " << fName <<
" and added material " << material->
GetName()
494 <<
", massFraction= " << fraction <<
", fIdxComponent=" << fIdxComponent
495 <<
" problem: cannot add by mass fraction after "
496 <<
"addition of elements by number of atoms";
499 if (fIdxComponent >= fNbComponents) {
501 ed <<
"For material " << fName <<
" and added material " << material->
GetName()
502 <<
", massFraction= " << fraction
503 <<
"; attempt to add more than the declared number of components " << fIdxComponent
504 <<
" >= " << fNbComponents;
507 if (0 == fIdxComponent) {
508 fElmFrac =
new std::vector<G4double>;
509 fElm =
new std::vector<const G4Element*>;
514 for (
G4int j = 0; j < nelm; ++j) {
518 if (! fElm->empty()) {
519 for (
G4int i = 0; i < fNumberOfElements; ++i) {
520 if (elm == (*fElm)[i]) {
521 (*fElmFrac)[i] += fraction * frac[j];
528 fElm->push_back(elm);
529 fElmFrac->push_back(fraction * frac[j]);
534 fMatComponents[material] = fraction;
538 if (fIdxComponent == fNbComponents) {
545void G4Material::FillVectors()
549 theElementVector->reserve(fNumberOfElements);
550 fAtomsVector =
new G4int[fNumberOfElements];
551 fMassFractionVector =
new G4double[fNumberOfElements];
554 for (
G4int i = 0; i < fNumberOfElements; ++i) {
555 theElementVector->push_back((*fElm)[i]);
556 fMassFractionVector[i] = (*fElmFrac)[i];
557 wtSum += fMassFractionVector[i];
563 if (std::abs(1. - wtSum) > perThousand) {
565 ed <<
"For material " << fName <<
" sum of fractional masses " << wtSum
566 <<
" is not 1 - results may be wrong";
571 for (
G4int i = 0; i < fNumberOfElements; ++i) {
572 fMassFractionVector[i] *=
coeff;
573 Amol += fMassFractionVector[i] * (*theElementVector)[i]->GetA();
575 for (
G4int i = 0; i < fNumberOfElements; ++i) {
576 fAtomsVector[i] =
G4lrint(fMassFractionVector[i] * Amol / (*theElementVector)[i]->
GetA());
578 ComputeDerivedQuantities();
583void G4Material::ComputeRadiationLength()
586 for (
G4int i = 0; i < fNumberOfElements; ++i) {
587 radinv += fVecNbOfAtomsPerVolume[i] * ((*theElementVector)[i]->GetfRadTsai());
589 fRadlen = (radinv <= 0.0 ?
DBL_MAX : 1. / radinv);
594void G4Material::ComputeNuclearInterLength()
596 const G4double lambda0 = 35 * CLHEP::g / CLHEP::cm2;
597 const G4double twothird = 2.0 / 3.0;
599 for (
G4int i = 0; i < fNumberOfElements; ++i) {
600 G4int Z = (*theElementVector)[i]->GetZasInt();
601 G4double A = (*theElementVector)[i]->GetN();
603 NILinv += fVecNbOfAtomsPerVolume[i] *
A;
606 NILinv += fVecNbOfAtomsPerVolume[i] *
G4Exp(twothird *
G4Log(
A));
609 NILinv *= amu / lambda0;
610 fNuclInterLen = (NILinv <= 0.0 ?
DBL_MAX : 1. / NILinv);
618 fChemicalFormula = chF;
626 if (val >= 0. && ! IsLocked()) {
627 fFreeElecDensity = val;
636 if (
nullptr == fIonisation) {
656 for (
auto const & j : theMaterialTable) {
657 if (j->GetName() == materialName) {
664 G4cout <<
"G4Material::GetMaterial() WARNING: The material: " << materialName
665 <<
" does not exist in the table. Return NULL pointer." <<
G4endl;
675 for (
auto const & mat : theMaterialTable) {
676 if (1 == mat->GetNumberOfElements() && z == mat->GetZ() && a == mat->GetA() &&
677 dens == mat->GetDensity())
690 for (
auto const & mat : theMaterialTable) {
691 if (nComp == mat->GetNumberOfElements() && dens == mat->GetDensity()) {
702 if (fNumberOfElements > 1) {
704 ed <<
"For material " << fName <<
" ERROR in GetZ() - Nelm=" << fNumberOfElements
705 <<
" > 1, which is not allowed";
708 return (*theElementVector)[0]->
GetZ();
715 if (fNumberOfElements > 1) {
717 ed <<
"For material " << fName <<
" ERROR in GetA() - Nelm=" << fNumberOfElements
718 <<
" > 1, which is not allowed";
721 return (*theElementVector)[0]->GetA();
728 std::ios::fmtflags mode = flux.flags();
729 flux.setf(std::ios::fixed, std::ios::floatfield);
730 G4long prec = flux.precision(3);
732 flux <<
" Material: " << std::setw(8) << material->fName <<
" " << material->fChemicalFormula
734 <<
" density: " << std::setw(6) << std::setprecision(3)
735 <<
G4BestUnit(material->fDensity,
"Volumic Mass") <<
" RadL: " << std::setw(7)
736 << std::setprecision(3) <<
G4BestUnit(material->fRadlen,
"Length")
737 <<
" Nucl.Int.Length: " << std::setw(7) << std::setprecision(3)
738 <<
G4BestUnit(material->fNuclInterLen,
"Length") <<
"\n"
739 << std::setw(30) <<
" Imean: " << std::setw(7) << std::setprecision(3)
741 <<
" temperature: " << std::setw(6) << std::setprecision(2)
742 << (material->fTemp) / CLHEP::kelvin <<
" K"
743 <<
" pressure: " << std::setw(6) << std::setprecision(2)
744 << (material->fPressure) / CLHEP::atmosphere <<
" atm"
747 for (
G4int i = 0; i < material->fNumberOfElements; i++) {
748 flux <<
"\n ---> " << (*(material->theElementVector))[i]
749 <<
"\n ElmMassFraction: " << std::setw(6) << std::setprecision(2)
750 << (material->fMassFractionVector[i]) / perCent <<
" %"
751 <<
" ElmAbundance " << std::setw(6) << std::setprecision(2)
752 << 100 * (material->fVecNbOfAtomsPerVolume[i]) / (material->fTotNbOfAtomsPerVolume)
755 flux.precision(prec);
756 flux.setf(mode, std::ios::floatfield);
778 flux <<
"\n***** Table : Nb of materials = " << MaterialTable.size() <<
" *****\n" <<
G4endl;
780 for (
auto i : MaterialTable) {
795 if (fMaterialPropertiesTable != anMPT && ! IsLocked()) {
796 delete fMaterialPropertiesTable;
797 fMaterialPropertiesTable = anMPT;
803G4bool 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
void ComputeDensityEffectOnFly(G4bool val)
const G4String & GetChemicalFormula() const
const G4ElementVector * GetElementVector() const
G4MaterialPropertiesTable * GetMaterialPropertiesTable() const
G4double GetTotNbOfAtomsPerVolume() const
const G4Element * GetElement(G4int iel) const
virtual G4bool IsExtended() const
const G4double * GetFractionVector() const
G4double GetTotNbOfElectPerVolume() const
G4IonisParamMat * GetIonisation() const
G4double GetFreeElectronDensity() const
void SetChemicalFormula(const G4String &chF)
const G4int * GetAtomsVector() const
G4SandiaTable * GetSandiaTable() const
void AddElementByNumberOfAtoms(const G4Element *elm, G4int nAtoms)
static std::size_t GetNumberOfMaterials()
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)
std::size_t GetNumberOfElements() const
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)
G4double GetNuclearInterLength() const
static G4NistManager * Instance()
G4Element * FindOrBuildElement(G4int Z, G4bool isotopes=true)
const G4ApplicationState & GetCurrentState() const
static G4StateManager * GetStateManager()