// // ******************************************************************** // * License and Disclaimer * // * * // * The Geant4 software is copyright of the Copyright Holders of * // * the Geant4 Collaboration. It is provided under the terms and * // * conditions of the Geant4 Software License, included in the file * // * LICENSE and available at http://cern.ch/geant4/license . These * // * include a list of copyright holders. * // * * // * Neither the authors of this software system, nor their employing * // * institutes,nor the agencies providing financial support for this * // * work make any representation or warranty, express or implied, * // * regarding this software system or assume any liability for its * // * use. Please see the license in the file LICENSE and URL above * // * for the full disclaimer and the limitation of liability. * // * * // * This code implementation is the result of the scientific and * // * technical work of the GEANT4 collaboration. * // * By using, copying, modifying or distributing the software (or * // * any work based on the software) you agree to acknowledge its * // * use in resulting scientific publications, and indicate your * // * acceptance of all terms of the Geant4 Software license. * // ******************************************************************** // // // $Id: G4SandiaTable.cc,v 1.34 2007/10/02 10:13:33 vnivanch Exp $ // GEANT4 tag $Name: geant4-09-02-ref-02 $ // //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo.... // // 10.06.97 created. V. Grichine // 18.11.98 simplified public interface; new methods for materials. mma // 31.01.01 redesign of ComputeMatSandiaMatrix(). mma // 16.02.01 adapted for STL. mma // 22.02.01 GetsandiaCofForMaterial(energy) return 0 below lowest interval mma // 03.04.01 fnulcof returned if energy < emin // 10.07.01 Migration to STL. M. Verderi. // 03.02.04 Update distructor V.Ivanchenko // 05.03.04 New methods for old sorting algorithm for PAI model. V.Grichine // //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo.... #include "G4SandiaTable.hh" #include "G4StaticSandiaData.hh" #include "G4Material.hh" #include "G4MaterialTable.hh" G4int G4SandiaTable::fCumulInterval[101]; G4double G4SandiaTable::fSandiaCofPerAtom[4]; G4double const G4SandiaTable::funitc[4] = {cm2*keV/g, cm2*keV*keV/g, cm2*keV*keV*keV/g, cm2*keV*keV*keV*keV/g}; //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo.... G4SandiaTable::G4SandiaTable(G4Material* material) : fMaterial(material) { fMatSandiaMatrix = 0; fMatSandiaMatrixPAI = 0; fPhotoAbsorptionCof = 0; //build the CumulInterval array fCumulInterval[0] = 1; for (G4int Z=1; Z<101; Z++) { fCumulInterval[Z] = fCumulInterval[Z-1] + fNbOfIntervals[Z]; } //compute macroscopic Sandia coefs for a material ComputeMatSandiaMatrix(); //initialisation of fnulcof fnulcof[0] = fnulcof[1] = fnulcof[2] = fnulcof[3] = 0.; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo.... // Fake default constructor - sets only member data and allocates memory // for usage restricted to object persistency G4SandiaTable::G4SandiaTable(__void__&) : fMaterial(0), fMatSandiaMatrix(0), fPhotoAbsorptionCof(0) { } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo.... G4SandiaTable::~G4SandiaTable() { if(fMatSandiaMatrix) { fMatSandiaMatrix->clearAndDestroy(); delete fMatSandiaMatrix; } if(fMatSandiaMatrixPAI) { fMatSandiaMatrixPAI->clearAndDestroy(); delete fMatSandiaMatrixPAI; } if(fPhotoAbsorptionCof) { delete [] fPhotoAbsorptionCof ; } } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo.... G4double G4SandiaTable::GetZtoA(G4int Z) { return fZtoAratio[Z]; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo.... G4double* G4SandiaTable::GetSandiaCofPerAtom(G4int Z, G4double energy) { assert (Z > 0 && Z < 101); G4double Emin = fSandiaTable[fCumulInterval[Z-1]][0]*keV; G4double Iopot = fIonizationPotentials[Z]*eV; if (Iopot > Emin) Emin = Iopot; G4int interval = fNbOfIntervals[Z] - 1; G4int row = fCumulInterval[Z-1] + interval; while ((interval>0) && (energy= Emin) { G4double AoverAvo = Z*amu/fZtoAratio[Z]; fSandiaCofPerAtom[0]=AoverAvo*funitc[0]*fSandiaTable[row][1]; fSandiaCofPerAtom[1]=AoverAvo*funitc[1]*fSandiaTable[row][2]; fSandiaCofPerAtom[2]=AoverAvo*funitc[2]*fSandiaTable[row][3]; fSandiaCofPerAtom[3]=AoverAvo*funitc[3]*fSandiaTable[row][4]; } else { fSandiaCofPerAtom[0] = fSandiaCofPerAtom[1] = fSandiaCofPerAtom[2] = fSandiaCofPerAtom[3] = 0.; } return fSandiaCofPerAtom; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo.... void G4SandiaTable::ComputeMatSandiaMatrix() { //get list of elements const G4int NbElm = fMaterial->GetNumberOfElements(); const G4ElementVector* ElementVector = fMaterial->GetElementVector(); G4int* Z = new G4int[NbElm]; //Atomic number // //determine the maximum number of energy-intervals for this material // G4int MaxIntervals = 0; G4int elm; for (elm=0; elmGetZ(); MaxIntervals += fNbOfIntervals[Z[elm]]; } // //copy the Energy bins in a tmp1 array //(take care of the Ionization Potential of each element) // G4double* tmp1 = new G4double[MaxIntervals]; G4double IonizationPot; G4int interval1=0; for (elm=0; elmpush_back(new G4DataVector(5,0.)); } // //ready to compute the Sandia coefs for the material // const G4double* NbOfAtomsPerVolume = fMaterial->GetVecNbOfAtomsPerVolume(); const G4double prec = 1.e-03*eV; G4double coef, oldsum(0.), newsum(0.); fMatNbOfIntervals = 0; for (interval=0; intervalGetNumberOfElements(); const G4ElementVector* ElementVector = fMaterial->GetElementVector(); G4int* Z = new G4int[noElm]; //Atomic number for (elm = 0; elmGetZ(); MaxIntervals += fNbOfIntervals[Z[elm]]; } fMaxInterval = MaxIntervals + 2; // G4cout<<"fMaxInterval = "< fSandiaTable[k1][0]) { continue ; // no ionization for energies smaller than I1 (first } // ionisation potential) break ; } G4int flag = 0 ; for(c1 = 1 ; c1 < c ; c1++) { if(fPhotoAbsorptionCof0[c1] == I1) // this value already has existed { flag = 1 ; break ; } } if(flag == 0) { fPhotoAbsorptionCof0[c] = I1 ; c++ ; } for(k2 = k1 ; k2 < n2 ; k2++) { flag = 0 ; for(c1 = 1 ; c1 < c ; c1++) { if(fPhotoAbsorptionCof0[c1] == fSandiaTable[k2][0]) { flag = 1 ; break ; } } if(flag == 0) { fPhotoAbsorptionCof0[c] = fSandiaTable[k2][0] ; c++ ; } } } // end for(i) // sort out for(i = 1; i < c ; i++ ) { for(j = i + 1 ; j < c; j++ ) { if(fPhotoAbsorptionCof0[i] > fPhotoAbsorptionCof0[j]) { G4double tmp = fPhotoAbsorptionCof0[i]; fPhotoAbsorptionCof0[i] = fPhotoAbsorptionCof0[j]; fPhotoAbsorptionCof0[j] = tmp ; } } } fMaxInterval = c ; const G4double* fractionW = fMaterial->GetFractionVector(); for(i = 0 ; i < noElm; i++) { n1 = 1 ; G4double I1 = fIonizationPotentials[Z[i]]*keV ; for(j = 1 ; j < Z[i] ; j++) { n1 += fNbOfIntervals[j] ; } G4int n2 = n1 + fNbOfIntervals[Z[i]] - 1 ; for(k = n1 ; k < n2 ; k++) { G4double B1 = fSandiaTable[k][0]; G4double B2 = fSandiaTable[k+1][0]; for(G4int c = 1 ; c < fMaxInterval-1 ; c++) { G4double E1 = fPhotoAbsorptionCof0[c]; G4double E2 = fPhotoAbsorptionCof0[c+1]; if(B1 > E1 || B2 < E2 || E1 < I1) { continue ; } fPhotoAbsorptionCof1[c] += fSandiaTable[k][1]*fractionW[i] ; fPhotoAbsorptionCof2[c] += fSandiaTable[k][2]*fractionW[i] ; fPhotoAbsorptionCof3[c] += fSandiaTable[k][3]*fractionW[i] ; fPhotoAbsorptionCof4[c] += fSandiaTable[k][4]*fractionW[i] ; } } // Last interval fPhotoAbsorptionCof1[fMaxInterval-1] += fSandiaTable[k][1]*fractionW[i] ; fPhotoAbsorptionCof2[fMaxInterval-1] += fSandiaTable[k][2]*fractionW[i] ; fPhotoAbsorptionCof3[fMaxInterval-1] += fSandiaTable[k][3]*fractionW[i] ; fPhotoAbsorptionCof4[fMaxInterval-1] += fSandiaTable[k][4]*fractionW[i] ; } // for(i) c = 0 ; // Deleting of first intervals where all coefficients = 0 do { c++ ; if( fPhotoAbsorptionCof1[c] != 0.0 || fPhotoAbsorptionCof2[c] != 0.0 || fPhotoAbsorptionCof3[c] != 0.0 || fPhotoAbsorptionCof4[c] != 0.0 ) continue ; for(jj = 2 ; jj < fMaxInterval ; jj++) { fPhotoAbsorptionCof0[jj-1] = fPhotoAbsorptionCof0[jj]; fPhotoAbsorptionCof1[jj-1] = fPhotoAbsorptionCof1[jj]; fPhotoAbsorptionCof2[jj-1] = fPhotoAbsorptionCof2[jj]; fPhotoAbsorptionCof3[jj-1] = fPhotoAbsorptionCof3[jj]; fPhotoAbsorptionCof4[jj-1] = fPhotoAbsorptionCof4[jj]; } fMaxInterval-- ; c-- ; } while(c < fMaxInterval - 1) ; // create the sandia matrix for this material fMatSandiaMatrixPAI = new G4OrderedTable(); G4double density = fMaterial->GetDensity(); for (i = 0; i < fMaxInterval; i++) { fMatSandiaMatrixPAI->push_back(new G4DataVector(5,0.)); } for (i = 0; i < fMaxInterval; i++) { (*(*fMatSandiaMatrixPAI)[i])[0] = fPhotoAbsorptionCof0[i+1]; (*(*fMatSandiaMatrixPAI)[i])[1] = fPhotoAbsorptionCof1[i+1]*density; (*(*fMatSandiaMatrixPAI)[i])[2] = fPhotoAbsorptionCof2[i+1]*density; (*(*fMatSandiaMatrixPAI)[i])[3] = fPhotoAbsorptionCof3[i+1]*density; (*(*fMatSandiaMatrixPAI)[i])[4] = fPhotoAbsorptionCof4[i+1]*density; } delete [] Z; delete [] fPhotoAbsorptionCof0; delete [] fPhotoAbsorptionCof1; delete [] fPhotoAbsorptionCof2; delete [] fPhotoAbsorptionCof3; delete [] fPhotoAbsorptionCof4; return; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo.... //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// // // Methods for PAI model //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo.... G4SandiaTable::G4SandiaTable(G4int matIndex) { fMatSandiaMatrix = 0 ; fMatSandiaMatrixPAI = 0; fPhotoAbsorptionCof = 0 ; const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable(); size_t numberOfMat = G4Material::GetNumberOfMaterials(); if ( matIndex >= 0 && matIndex < G4int(numberOfMat) ) { fMaterial = (*theMaterialTable)[matIndex]; } else { G4Exception("G4SandiaTable::G4SandiaTable(G4int matIndex): wrong matIndex "); } ComputeMatTable(); } /////////////////////////////////////////////////////////////////////// // // Bubble sorting of left energy interval in SandiaTable in ascening order // void G4SandiaTable::SandiaSort(G4double** da , G4int sz ) { for(G4int i = 1 ;i < sz ; i++ ) { for(G4int j = i + 1 ;j < sz ; j++ ) { if(da[i][0] > da[j][0]) { SandiaSwap(da,i,j) ; } } } } //////////////////////////////////////////////////////////////////////////// // // SandiaIntervals // G4int G4SandiaTable::SandiaIntervals(G4int Z[], G4int el ) { G4int c,i ; fMaxInterval = 0 ; for(i=0;i