// This code implementation is the intellectual property of // the RD44 GEANT4 collaboration. // // By copying, distributing or modifying the Program (or any work // based on the Program) you indicate your acceptance of this statement, // and all its terms. // // $Id: G4Material.cc,v 1.3 1999/04/14 12:49:03 maire Exp $ // GEANT4 tag $Name: geant4-00-01 $ // // // ---------- class G4Material ---------- // // Torre Wenaus, November 1995 // //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo.... // // 26-06-96, Code uses operators (+=, *=, ++, -> etc.) correctly, P. Urban // 10-07-96, new data members added by L.Urban // 12-12-96, new data members added by L.Urban // 20-01-97, aesthetic rearrangement. RadLength calculation modified. // Data members Zeff and Aeff REMOVED (i.e. passed to the Elements). // (local definition of Zeff in DensityEffect and FluctModel...) // Vacuum defined as a G4State. Mixture flag removed, M.Maire. // 29-01-97, State=Vacuum automatically set density=0 in the contructors. // Subsequent protections have been put in the calculation of // MeanExcEnergy, ShellCorrectionVector, DensityEffect, M.Maire. // 11-02-97, ComputeDensityEffect() rearranged, M.Maire. // 20-03-97, corrected initialization of pointers, M.Maire. // 28-05-98, the kState=kVacuum has been removed. // automatic check for a minimal density, M.Maire // 12-06-98, new method AddMaterial() allowing mixture of materials, M.Maire // 09-07-98, ionisation parameters removed from the class, M.Maire // 05-10-98, change names: NumDensity -> NbOfAtomsPerVolume // 18-11-98, new interface to SandiaTable // 19-01-99 enlarge tolerance on test of coherence of gas conditions //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo.... #include "G4Material.hh" #include "G4UnitsTable.hh" #include G4MaterialTable G4Material::theMaterialTable; //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo.... // Constructor to create a material from scratch G4Material::G4Material(const G4String& name, G4double z, G4double a, G4double density, G4State state, G4double temp, G4double pressure) :fName(name) { InitializePointers(); if (density < universe_mean_density) { G4cout << "--- Warning from G4Material::G4Material()" << " define a material with density=0 is not allowed. \n" << " The material " << name << " will be constructed with the" << " default minimal density: " << universe_mean_density/(g/cm3) << "g/cm3" << endl; density = universe_mean_density; } fDensity = density; fState = state; fTemp = temp; fPressure = pressure; // Initialize theElementVector allocating one // element corresponding to this material maxNbComponents = fNumberOfComponents = fNumberOfElements = 1; theElementVector = new G4ElementVector(1); theElementVector[0] = new G4Element(name, " ", z, a); fMassFractionVector = new G4double[1]; fMassFractionVector[0] = 1. ; if (fState == kStateUndefined) { if (fDensity > kGasThreshold) fState = kStateSolid; else fState = kStateGas; } ComputeDerivedQuantities(); // Store in the table of Materials theMaterialTable.insert(this); fIndexInTable = theMaterialTable.index(this); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo.... // Constructor to create a material from a List of constituents // (elements and/or materials) added with AddElement or AddMaterial G4Material::G4Material(const G4String& name, G4double density, G4int nComponents, G4State state, G4double temp, G4double pressure) :fName(name) { InitializePointers(); if (density < universe_mean_density) {G4cout << "--- Warning from G4Material::G4Material()" << " define a material with density=0 is not allowed. \n" << " The material " << name << " will be constructed with the" << " default minimal density: " << universe_mean_density/(g/cm3) << "g/cm3" << endl; density = universe_mean_density; } fDensity = density; fState = state; fTemp = temp; fPressure = pressure; maxNbComponents = nComponents; fNumberOfComponents = fNumberOfElements = 0; theElementVector = new G4ElementVector(maxNbComponents); if (fState == kStateUndefined) { if (fDensity > kGasThreshold) fState = kStateSolid; else fState = kStateGas; } } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo.... // AddElement -- composition by atom count void G4Material::AddElement(G4Element* element, G4int nAtoms) { // initialization if ( fNumberOfElements == 0 ) { fAtomsVector = new G4int [maxNbComponents]; fMassFractionVector = new G4double[maxNbComponents]; } // filling ... if ( fNumberOfElements < maxNbComponents ) { (*theElementVector)[fNumberOfElements] = element; fAtomsVector [fNumberOfElements] = nAtoms; fNumberOfComponents = ++fNumberOfElements; } else G4Exception ("ERROR!!! - Attempt to add more than the declared number of elements."); // filled. if ( fNumberOfElements == maxNbComponents ) { // compute proportion by mass G4int i=0; G4double Zmol(0.), Amol(0.); for (i=0;iGetZ(); Amol += fAtomsVector[i]*(*theElementVector)[i]->GetA(); } for (i=0;iGetA()/Amol; } ComputeDerivedQuantities(); // Store in the static Table of Materials theMaterialTable.insert(this); fIndexInTable = theMaterialTable.index(this); } } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo.... // AddElement -- composition by fraction of mass void G4Material::AddElement(G4Element* element, G4double fraction) { // if fAtomsVector is non-NULL, complain. Apples and oranges. $$$ if (fAtomsVector) { G4cerr << "This material is already being defined via elements by" << "atoms." << endl; G4Exception ("You are mixing apples and oranges ..."); } // initialization if (fNumberOfComponents == 0) { fMassFractionVector = new G4double[100]; } // filling ... if (fNumberOfComponents < maxNbComponents) { size_t el = 0; while ((el=theElementVector->length()) theElementVector->resize(el+1); (*theElementVector)[el] = element; fMassFractionVector[el] = fraction; fNumberOfElements ++; } fNumberOfComponents++; } else G4Exception ("ERROR!!! - Attempt to add more than the declared number of components."); // filled. if (fNumberOfComponents == maxNbComponents) { // check sum of weights -- OK? G4int i; G4double wtSum(0.0); for (i=0;i perThousand) { G4cerr << "WARNING !! - Fractional masses do not sum to 1 :the Delta is > 0.001" << "( the weights are NOT renormalized; the results may be wrong)" << endl; } ComputeDerivedQuantities(); // Store in the static Table of Materials theMaterialTable.insert(this); fIndexInTable = theMaterialTable.index(this); } } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo.... // AddMaterial -- composition by fraction of mass void G4Material::AddMaterial(G4Material* material, G4double fraction) { // if fAtomsVector is non-NULL, complain. Apples and oranges. $$$ if (fAtomsVector) { G4cerr << "This material is already being defined via elements by" << "atoms." << endl; G4Exception ("You are mixing apples and oranges ..."); } // initialization if (fNumberOfComponents == 0) { fMassFractionVector = new G4double[100]; } // filling ... if (fNumberOfComponents < maxNbComponents) { for (G4int elm=0; elm < material->GetNumberOfElements(); elm++) { G4Element* element = (*(material->GetElementVector()))[elm]; size_t el = 0; while ((elGetFractionVector())[elm]; else { if(el>=theElementVector->length()) theElementVector->resize(el+1); (*theElementVector)[el] = element; fMassFractionVector[el] = fraction*(material->GetFractionVector())[elm]; fNumberOfElements ++; } } fNumberOfComponents++; } else G4Exception ("ERROR!!! - Attempt to add more than the declared number of components."); // filled. if (fNumberOfComponents == maxNbComponents) { // check sum of weights -- OK? G4int i; G4double wtSum(0.0); for (i=0;i perThousand) { G4cerr << "WARNING !! - Fractional masses do not sum to 1 :the Delta is > 0.001" << "( the weights are NOT renormalized; the results may be wrong)" << endl; } ComputeDerivedQuantities(); // Store in the static Table of Materials theMaterialTable.insert(this); fIndexInTable = theMaterialTable.index(this); } } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo.... void G4Material::ComputeDerivedQuantities() { // Header routine to compute various properties of material. // // Atoms density vector, Electrons density G4double Zi, Ai; TotNbOfAtomsPerVolume = 0.; VecNbOfAtomsPerVolume = new G4double[fNumberOfElements]; TotNbOfElectPerVolume = 0.; for (G4int i=0;iGetZ(); Ai = (*theElementVector)[i]->GetA(); VecNbOfAtomsPerVolume[i] = Avogadro*fDensity*fMassFractionVector[i]/Ai; TotNbOfAtomsPerVolume += VecNbOfAtomsPerVolume[i]; TotNbOfElectPerVolume += VecNbOfAtomsPerVolume[i]*Zi; } //for gas, check coherence of the state conditions if (fState == kStateGas) { G4double ratio = TotNbOfAtomsPerVolume*k_Boltzmann*fTemp/fPressure; if ((ratio<0.1)||(ratio>10.)) { G4cout << "---warning from G4Material-- The state conditions of the gas: " << fName << " are not consistent." << "\n density = " << fDensity/(mg/cm3) << " mg/cm3" << "\t pressure = " << fPressure/atmosphere << " atmosphere" << "\t temperature = " << fTemp/kelvin << " kelvin" << "\n rho*(T/P) would be of the order of: " << (fDensity/(TotNbOfAtomsPerVolume*k_Boltzmann))/((mg/cm3)*(kelvin/atmosphere)) << " (mg/cm3)*(kelvin/atmosphere). The energy loss calculation maybe be affected \n"; } } ComputeRadiationLength(); fIonisation = new G4IonisParamMat(this); fSandiaTable = new G4SandiaTable(this); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo.... void G4Material::ComputeRadiationLength() { G4double radinv = 0.0 ; for (G4int i=0;iGetfRadTsai()); } fRadlen = (radinv <= 0.0 ? DBL_MAX : 1./radinv); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo.... void G4Material::InitializePointers() { theElementVector = NULL; fMassFractionVector = NULL; fAtomsVector = NULL; fMaterialPropertiesTable = NULL; VecNbOfAtomsPerVolume = NULL; fIonisation = NULL; fSandiaTable = NULL; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo.... G4Material::~G4Material() { if (theElementVector) delete theElementVector; if (fMassFractionVector) delete [] fMassFractionVector; if (fAtomsVector) delete [] fAtomsVector; if (VecNbOfAtomsPerVolume) delete [] VecNbOfAtomsPerVolume; if (fIonisation) delete fIonisation; if (fSandiaTable) delete fSandiaTable; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo.... G4Material::G4Material(const G4Material& right) { *this = right; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo.... const G4Material& G4Material::operator=(const G4Material& right) { if (this != &right) { fName = right.fName; fDensity = right.fDensity; fState = right.fState; fTemp = right.fTemp; fPressure = right.fPressure; maxNbComponents = right.maxNbComponents; fNumberOfComponents = right.fNumberOfComponents; fNumberOfElements = right.fNumberOfElements; theElementVector = right.theElementVector; fMassFractionVector = right.fMassFractionVector; fAtomsVector = right.fAtomsVector; fMaterialPropertiesTable = right.fMaterialPropertiesTable; fIndexInTable = right.fIndexInTable; VecNbOfAtomsPerVolume = right.VecNbOfAtomsPerVolume; TotNbOfAtomsPerVolume = right.TotNbOfAtomsPerVolume; TotNbOfElectPerVolume = right.TotNbOfElectPerVolume; fRadlen = right.fRadlen; fIonisation = right.fIonisation; fSandiaTable = right.fSandiaTable; } return *this; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo.... G4int G4Material::operator==(const G4Material& right) const { return (this == (G4Material *) &right); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo.... G4int G4Material::operator!=(const G4Material& right) const { return (this != (G4Material *) &right); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo.... ostream& operator<<(ostream& flux, G4Material* material) { long mode = flux.setf(ios::fixed,ios::floatfield); flux << " Material: " << setw(8) << material->fName << " density: " << setw(6) << setprecision(3) << G4BestUnit(material->fDensity,"Volumic Mass") << " temperature: " << setw(6) << setprecision(2) << (material->fTemp)/kelvin << " K" << " pressure: " << setw(6) << setprecision(2) << (material->fPressure)/atmosphere << " atm" << " RadLength: " << setw(7) << setprecision(3) << G4BestUnit(material->fRadlen,"Length"); for (G4int i=0; ifNumberOfElements; i++) flux << "\n ---> " << (*(material->theElementVector))[i] << " fractionMass: " << setw(6)<< setprecision(2) << (material->fMassFractionVector[i])/perCent << " %" << " Abundance " << setw(6)<< setprecision(2) << 100*(material->VecNbOfAtomsPerVolume[i])/ (material->TotNbOfAtomsPerVolume) << " %"; flux.setf(mode,ios::floatfield); return flux; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo.... ostream& operator<<(ostream& flux, G4Material& material) { flux << &material; return flux; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo.... ostream& operator<<(ostream& flux, G4MaterialTable MaterialTable) { //Dump info for all known materials flux << "\n***** Table : Nb of materials = " << MaterialTable.length() << " *****\n" << endl; for (G4int i=0; i