// // ******************************************************************** // * 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: G4MuBremsstrahlungModel.cc,v 1.24 2007/11/08 11:48:28 vnivanch Exp $ // GEANT4 tag $Name: geant4-09-01-patch-02 $ // // ------------------------------------------------------------------- // // GEANT4 Class file // // // File name: G4MuBremsstrahlungModel // // Author: Vladimir Ivanchenko on base of Laszlo Urban code // // Creation date: 24.06.2002 // // Modifications: // // 04-12-02 Change G4DynamicParticle constructor in PostStepDoIt (V.Ivanchenko) // 23-12-02 Change interface in order to move to cut per region (V.Ivanchenko) // 24-01-03 Fix for compounds (V.Ivanchenko) // 27-01-03 Make models region aware (V.Ivanchenko) // 13-02-03 Add name (V.Ivanchenko) // 10-02-04 Add lowestKinEnergy (V.Ivanchenko) // 08-04-05 Major optimisation of internal interfaces (V.Ivantchenko) // 03-08-05 Angular correlations according to PRM (V.Ivantchenko) // 13-02-06 add ComputeCrossSectionPerAtom (mma) // 21-03-06 Fix problem of initialisation in case when cuts are not defined (VI) // 07-11-07 Improve sampling of final state (A.Bogdanov) // // // Class Description: // // // ------------------------------------------------------------------- // //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... #include "G4MuBremsstrahlungModel.hh" #include "G4Gamma.hh" #include "G4MuonMinus.hh" #include "G4MuonPlus.hh" #include "Randomize.hh" #include "G4Material.hh" #include "G4Element.hh" #include "G4ElementVector.hh" #include "G4ProductionCutsTable.hh" #include "G4ParticleChangeForLoss.hh" //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... // static members // G4double G4MuBremsstrahlungModel::zdat[]={1., 4., 13., 29., 92.}; G4double G4MuBremsstrahlungModel::adat[]={1.01, 9.01, 26.98, 63.55, 238.03}; G4double G4MuBremsstrahlungModel::tdat[]={1.e3, 1.e4, 1.e5, 1.e6, 1.e7, 1.e8, 1.e9, 1.e10}; //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... using namespace std; G4MuBremsstrahlungModel::G4MuBremsstrahlungModel(const G4ParticleDefinition* p, const G4String& nam) : G4VEmModel(nam), particle(0), lowestKinEnergy(1.0*GeV), minThreshold(1.0*keV), nzdat(5), ntdat(8), NBIN(1000), cutFixed(0.98*keV), ignoreCut(false), samplingTablesAreFilled(false) { theGamma = G4Gamma::Gamma(); if(p) SetParticle(p); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... G4MuBremsstrahlungModel::~G4MuBremsstrahlungModel() { size_t n = partialSumSigma.size(); if(n > 0) { for(size_t i=0; iGetPDGMass(); } } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void G4MuBremsstrahlungModel::Initialise(const G4ParticleDefinition* p, const G4DataVector& cuts) { if(p) SetParticle(p); highKinEnergy = HighEnergyLimit(); G4double fixedEnergy = 0.5*highKinEnergy; const G4ProductionCutsTable* theCoupleTable= G4ProductionCutsTable::GetProductionCutsTable(); if(theCoupleTable) { G4int numOfCouples = theCoupleTable->GetTableSize(); G4int nn = partialSumSigma.size(); G4int nc = cuts.size(); if(nn > 0) { for (G4int ii=0; ii0) { for (G4int i=0; iGetMaterialCutsCouple(i); const G4Material* material = couple->GetMaterial(); G4DataVector* dv = ComputePartialSumSigma(material,fixedEnergy,cute); partialSumSigma.push_back(dv); } } } if(!samplingTablesAreFilled) MakeSamplingTables(); if(pParticleChange) fParticleChange = reinterpret_cast(pParticleChange); else fParticleChange = new G4ParticleChangeForLoss(); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... G4double G4MuBremsstrahlungModel::ComputeDEDXPerVolume( const G4Material* material, const G4ParticleDefinition*, G4double kineticEnergy, G4double cutEnergy) { G4double dedx = 0.0; if (kineticEnergy <= lowestKinEnergy || ignoreCut) return dedx; G4double tmax = kineticEnergy; G4double cut = min(cutEnergy,tmax); if(cut < cutFixed) cut = cutFixed; const G4ElementVector* theElementVector = material->GetElementVector(); const G4double* theAtomicNumDensityVector = material->GetAtomicNumDensityVector(); // loop for elements in the material for (size_t i=0; iGetNumberOfElements(); i++) { G4double Z = (*theElementVector)[i]->GetZ(); G4double A = (*theElementVector)[i]->GetA()/(g/mole) ; G4double loss = ComputMuBremLoss(Z, A, kineticEnergy, cut); dedx += loss*theAtomicNumDensityVector[i]; } if(dedx < 0.) dedx = 0.; return dedx; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... G4double G4MuBremsstrahlungModel::ComputMuBremLoss(G4double Z, G4double A, G4double tkin, G4double cut) { G4double totalEnergy = mass + tkin; G4double ak1 = 0.05; G4int k2=5; G4double xgi[]={0.03377,0.16940,0.38069,0.61931,0.83060,0.96623}; G4double wgi[]={0.08566,0.18038,0.23396,0.23396,0.18038,0.08566}; G4double loss = 0.; G4double vcut = cut/totalEnergy; G4double vmax = tkin/totalEnergy; G4double aaa = 0.; G4double bbb = vcut; if(vcut>vmax) bbb=vmax ; G4int kkk = (G4int)((bbb-aaa)/ak1)+k2 ; G4double hhh=(bbb-aaa)/float(kkk) ; G4double aa = aaa; for(G4int l=0; l= tkin) return cross; G4double vcut = cut/totalEnergy; G4double vmax = tkin/totalEnergy; G4double aaa = log(vcut); G4double bbb = log(vmax); G4int kkk = (G4int)((bbb-aaa)/ak1)+k2 ; G4double hhh = (bbb-aaa)/float(kkk); G4double aa = aaa; for(G4int l=0; l tkin) return dxsection ; G4double E = tkin + mass ; G4double v = gammaEnergy/E ; G4double delta = 0.5*mass*mass*v/(E-gammaEnergy) ; G4double rab0=delta*sqrte ; G4double z13 = exp(-log(Z)/3.) ; G4double dn = 1.54*exp(0.27*log(A)) ; G4double b,b1,dnstar ; if(Z<1.5) { b=bh; b1=bh1; dnstar=dn ; } else { b=btf; b1=btf1; dnstar = exp((1.-1./Z)*log(dn)) ; } // nucleus contribution logarithm G4double rab1=b*z13; G4double fn=log(rab1/(dnstar*(electron_mass_c2+rab0*rab1))* (mass+delta*(dnstar*sqrte-2.))) ; if(fn <0.) fn = 0. ; // electron contribution logarithm G4double epmax1=E/(1.+0.5*mass*rmass/E) ; G4double fe=0.; if(gammaEnergy= maxEnergy || kineticEnergy <= lowestKinEnergy) return cross; G4double tmax = min(maxEnergy, kineticEnergy); G4double cut = min(cutEnergy, tmax); if(cut < cutFixed || ignoreCut) cut = cutFixed; const G4ElementVector* theElementVector = material->GetElementVector(); const G4double* theAtomNumDensityVector = material->GetAtomicNumDensityVector(); for (size_t i=0; iGetNumberOfElements(); i++) { G4double Z = (*theElementVector)[i]->GetZ(); G4double A = (*theElementVector)[i]->GetA()/(g/mole); G4double cr = ComputeMicroscopicCrossSection(kineticEnergy, Z, A, cut); if(tmax < kineticEnergy) { cr -= ComputeMicroscopicCrossSection(kineticEnergy, Z, A, tmax); } cross += theAtomNumDensityVector[i] * cr; } return cross; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... G4DataVector* G4MuBremsstrahlungModel::ComputePartialSumSigma( const G4Material* material, G4double kineticEnergy, G4double cut) // Build the table of cross section per element. The table is built for MATERIAL // This table is used by DoIt to select randomly an element in the material. { G4int nElements = material->GetNumberOfElements(); const G4ElementVector* theElementVector = material->GetElementVector(); const G4double* theAtomNumDensityVector = material->GetAtomicNumDensityVector(); G4DataVector* dv = new G4DataVector(); G4double cross = 0.0; for (G4int i=0; iGetZ(); G4double A = (*theElementVector)[i]->GetA()/(g/mole) ; cross += theAtomNumDensityVector[i] * ComputeMicroscopicCrossSection(kineticEnergy, Z, A, cut); dv->push_back(cross); } return dv; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void G4MuBremsstrahlungModel::MakeSamplingTables() { G4double AtomicNumber,AtomicWeight,KineticEnergy, TotalEnergy,Maxep; for (G4int iz=0; iz 0.) { for(G4int ib=0; ib<=NBIN; ib++) { proba[iz][it][ib] /= CrossSection ; } } } } samplingTablesAreFilled = true; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void G4MuBremsstrahlungModel::SampleSecondaries(std::vector* vdp, const G4MaterialCutsCouple* couple, const G4DynamicParticle* dp, G4double minEnergy, G4double maxEnergy) { G4double kineticEnergy = dp->GetKineticEnergy(); // check against insufficient energy G4double tmax = min(kineticEnergy, maxEnergy); G4double tmin = min(kineticEnergy, minEnergy); if(tmin < cutFixed || ignoreCut) tmin = cutFixed; if(tmin >= tmax) return; // ===== the begining of a new code ====== // ===== sampling of energy transfer ====== G4ParticleMomentum partDirection = dp->GetMomentumDirection(); // select randomly one element constituing the material const G4Element* anElement = SelectRandomAtom(couple); G4double totalEnergy = kineticEnergy + mass; G4double totalMomentum = sqrt(kineticEnergy*(kineticEnergy + 2.0*mass)); G4double AtomicNumber = anElement->GetZ(); G4double AtomicWeight = anElement->GetA()/(g/mole); G4double func1 = tmin*ComputeDMicroscopicCrossSection( kineticEnergy,AtomicNumber, AtomicWeight,tmin); G4double lnepksi, epksi; G4double func2; G4double ksi2; do { lnepksi = log(tmin) + G4UniformRand()*log(kineticEnergy/tmin); epksi = exp(lnepksi); func2 = epksi*ComputeDMicroscopicCrossSection( kineticEnergy,AtomicNumber, AtomicWeight,epksi); ksi2 = G4UniformRand(); } while(func2/func1 < ksi2); // ===== the end of a new code ===== // create G4DynamicParticle object for the Gamma G4double gEnergy = epksi; // sample angle G4double gam = totalEnergy/mass; G4double rmax = gam*min(1.0, totalEnergy/gEnergy - 1.0); rmax *= rmax; G4double x = G4UniformRand()*rmax/(1.0 + rmax); G4double theta = sqrt(x/(1.0 - x))/gam; G4double sint = sin(theta); G4double phi = twopi * G4UniformRand() ; G4double dirx = sint*cos(phi), diry = sint*sin(phi), dirz = cos(theta) ; G4ThreeVector gDirection(dirx, diry, dirz); gDirection.rotateUz(partDirection); partDirection *= totalMomentum; partDirection -= gEnergy*gDirection; partDirection = partDirection.unit(); // primary change kineticEnergy -= gEnergy; fParticleChange->SetProposedKineticEnergy(kineticEnergy); fParticleChange->SetProposedMomentumDirection(partDirection); // save secondary G4DynamicParticle* aGamma = new G4DynamicParticle(theGamma,gDirection,gEnergy); vdp->push_back(aGamma); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... const G4Element* G4MuBremsstrahlungModel::SelectRandomAtom( const G4MaterialCutsCouple* couple) const { // select randomly 1 element within the material const G4Material* material = couple->GetMaterial(); G4int nElements = material->GetNumberOfElements(); const G4ElementVector* theElementVector = material->GetElementVector(); if(1 == nElements) return (*theElementVector)[0]; else if(1 > nElements) return 0; G4DataVector* dv = partialSumSigma[couple->GetIndex()]; G4double rval = G4UniformRand()*((*dv)[nElements-1]); for (G4int i=0; i