Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer 3 // * License and Disclaimer * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/ 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. 9 // * include a list of copyright holders. * 10 // * 10 // * * 11 // * Neither the authors of this software syst 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitatio 16 // * for the full disclaimer and the limitation of liability. * 17 // * 17 // * * 18 // * This code implementation is the result 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboratio 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distri 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you ag 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publicati 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Sof 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************* 24 // ******************************************************************** 25 // 25 // 26 // 26 // 27 // Author: D.H. Wright 27 // Author: D.H. Wright 28 // Date: 2 February 2011 28 // Date: 2 February 2011 29 // 29 // 30 // Description: model of muon nuclear interact 30 // Description: model of muon nuclear interaction in which a gamma from 31 // the virtual photon spectrum in 31 // the virtual photon spectrum interacts in the nucleus as 32 // a real gamma at low energies a 32 // a real gamma at low energies and as a pi0 at high energies. 33 // Kokoulin's muon cross section 33 // Kokoulin's muon cross section and equivalent gamma spectrum 34 // are used. 34 // are used. 35 // 35 // 36 36 37 #include "G4MuonVDNuclearModel.hh" 37 #include "G4MuonVDNuclearModel.hh" 38 38 39 #include "Randomize.hh" 39 #include "Randomize.hh" 40 #include "G4Log.hh" 40 #include "G4Log.hh" 41 #include "G4PhysicalConstants.hh" 41 #include "G4PhysicalConstants.hh" 42 #include "G4SystemOfUnits.hh" 42 #include "G4SystemOfUnits.hh" 43 #include "G4CascadeInterface.hh" 43 #include "G4CascadeInterface.hh" 44 #include "G4TheoFSGenerator.hh" 44 #include "G4TheoFSGenerator.hh" 45 #include "G4GeneratorPrecompoundInterface.hh" 45 #include "G4GeneratorPrecompoundInterface.hh" 46 #include "G4PreCompoundModel.hh" 46 #include "G4PreCompoundModel.hh" 47 #include "G4LundStringFragmentation.hh" 47 #include "G4LundStringFragmentation.hh" 48 #include "G4ExcitedStringDecay.hh" 48 #include "G4ExcitedStringDecay.hh" 49 #include "G4FTFModel.hh" 49 #include "G4FTFModel.hh" 50 #include "G4HadronicInteractionRegistry.hh" 50 #include "G4HadronicInteractionRegistry.hh" 51 #include "G4KokoulinMuonNuclearXS.hh" 51 #include "G4KokoulinMuonNuclearXS.hh" 52 #include "G4CrossSectionDataSetRegistry.hh" 52 #include "G4CrossSectionDataSetRegistry.hh" 53 #include "G4ElementData.hh" 53 #include "G4ElementData.hh" 54 #include "G4Physics2DVector.hh" 54 #include "G4Physics2DVector.hh" 55 #include "G4Pow.hh" 55 #include "G4Pow.hh" 56 #include "G4PhysicsModelCatalog.hh" 56 #include "G4PhysicsModelCatalog.hh" 57 57 58 const G4int G4MuonVDNuclearModel::zdat[] = {1, 58 const G4int G4MuonVDNuclearModel::zdat[] = {1, 4, 13, 29, 92}; 59 const G4double G4MuonVDNuclearModel::adat[] = 59 const G4double G4MuonVDNuclearModel::adat[] = {1.01,9.01,26.98,63.55,238.03}; 60 const G4double G4MuonVDNuclearModel::tdat[] = 60 const G4double G4MuonVDNuclearModel::tdat[] = { 61 1.e3,2.e3,3.e3,4.e3,5.e3,6.e3,7.e3,8.e3,9.e3 61 1.e3,2.e3,3.e3,4.e3,5.e3,6.e3,7.e3,8.e3,9.e3, 62 1.e4,2.e4,3.e4,4.e4,5.e4,6.e4,7.e4,8.e4,9.e4 62 1.e4,2.e4,3.e4,4.e4,5.e4,6.e4,7.e4,8.e4,9.e4, 63 1.e5,2.e5,3.e5,4.e5,5.e5,6.e5,7.e5,8.e5,9.e5 63 1.e5,2.e5,3.e5,4.e5,5.e5,6.e5,7.e5,8.e5,9.e5, 64 1.e6,2.e6,3.e6,4.e6,5.e6,6.e6,7.e6,8.e6,9.e6 64 1.e6,2.e6,3.e6,4.e6,5.e6,6.e6,7.e6,8.e6,9.e6, 65 1.e7,2.e7,3.e7,4.e7,5.e7,6.e7,7.e7,8.e7,9.e7 65 1.e7,2.e7,3.e7,4.e7,5.e7,6.e7,7.e7,8.e7,9.e7, 66 1.e8,2.e8,3.e8,4.e8,5.e8,6.e8,7.e8,8.e8,9.e8 66 1.e8,2.e8,3.e8,4.e8,5.e8,6.e8,7.e8,8.e8,9.e8, 67 1.e9,2.e9,3.e9,4.e9,5.e9,6.e9,7.e9,8.e9,9.e9 67 1.e9,2.e9,3.e9,4.e9,5.e9,6.e9,7.e9,8.e9,9.e9, 68 1.e10,2.e10,3.e10,4.e10,5.e10,6.e10,7.e10,8. 68 1.e10,2.e10,3.e10,4.e10,5.e10,6.e10,7.e10,8.e10,9.e10,1.e11}; 69 69 70 G4ElementData* G4MuonVDNuclearModel::fElementD 70 G4ElementData* G4MuonVDNuclearModel::fElementData = nullptr; 71 71 72 G4MuonVDNuclearModel::G4MuonVDNuclearModel() 72 G4MuonVDNuclearModel::G4MuonVDNuclearModel() 73 : G4HadronicInteraction("G4MuonVDNuclearMode 73 : G4HadronicInteraction("G4MuonVDNuclearModel") 74 { 74 { 75 muNucXS = (G4KokoulinMuonNuclearXS*)G4CrossS 75 muNucXS = (G4KokoulinMuonNuclearXS*)G4CrossSectionDataSetRegistry::Instance()-> 76 GetCrossSectionDataSet(G4KokoulinMuonNucle 76 GetCrossSectionDataSet(G4KokoulinMuonNuclearXS::Default_Name()); 77 77 78 SetMinEnergy(0.0); 78 SetMinEnergy(0.0); 79 SetMaxEnergy(1*CLHEP::PeV); 79 SetMaxEnergy(1*CLHEP::PeV); 80 CutFixed = 0.2*CLHEP::GeV; 80 CutFixed = 0.2*CLHEP::GeV; 81 81 82 if (nullptr == fElementData) { 82 if (nullptr == fElementData) { 83 fElementData = new G4ElementData(93); 83 fElementData = new G4ElementData(93); 84 MakeSamplingTable(); 84 MakeSamplingTable(); 85 } 85 } 86 86 87 // reuse existing pre-compound model 87 // reuse existing pre-compound model 88 G4GeneratorPrecompoundInterface* precoInterf 88 G4GeneratorPrecompoundInterface* precoInterface 89 = new G4GeneratorPrecompoundInterface(); 89 = new G4GeneratorPrecompoundInterface(); 90 G4HadronicInteraction* p = 90 G4HadronicInteraction* p = 91 G4HadronicInteractionRegistry::Instance()- 91 G4HadronicInteractionRegistry::Instance()->FindModel("PRECO"); 92 G4VPreCompoundModel* pre = static_cast<G4VPr 92 G4VPreCompoundModel* pre = static_cast<G4VPreCompoundModel*>(p); 93 if(nullptr == pre) { pre = new G4PreCompound 93 if(nullptr == pre) { pre = new G4PreCompoundModel(); } 94 precoInterface->SetDeExcitation(pre); 94 precoInterface->SetDeExcitation(pre); 95 95 96 // Build FTFP model 96 // Build FTFP model 97 ftfp = new G4TheoFSGenerator(); 97 ftfp = new G4TheoFSGenerator(); 98 ftfp->SetTransport(precoInterface); 98 ftfp->SetTransport(precoInterface); 99 theFragmentation = new G4LundStringFragmenta 99 theFragmentation = new G4LundStringFragmentation(); 100 theStringDecay = new G4ExcitedStringDecay(th 100 theStringDecay = new G4ExcitedStringDecay(theFragmentation); 101 G4FTFModel* theStringModel = new G4FTFModel; 101 G4FTFModel* theStringModel = new G4FTFModel; 102 theStringModel->SetFragmentationModel(theStr 102 theStringModel->SetFragmentationModel(theStringDecay); 103 ftfp->SetHighEnergyGenerator(theStringModel) 103 ftfp->SetHighEnergyGenerator(theStringModel); 104 104 105 // Build Bertini cascade 105 // Build Bertini cascade 106 bert = new G4CascadeInterface(); 106 bert = new G4CascadeInterface(); 107 107 108 // Creator model ID 108 // Creator model ID 109 secID = G4PhysicsModelCatalog::GetModelID( " 109 secID = G4PhysicsModelCatalog::GetModelID( "model_" + GetModelName() ); 110 } 110 } 111 111 112 G4MuonVDNuclearModel::~G4MuonVDNuclearModel() 112 G4MuonVDNuclearModel::~G4MuonVDNuclearModel() 113 { 113 { 114 delete theFragmentation; 114 delete theFragmentation; 115 delete theStringDecay; 115 delete theStringDecay; 116 } 116 } 117 117 118 G4HadFinalState* 118 G4HadFinalState* 119 G4MuonVDNuclearModel::ApplyYourself(const G4Ha 119 G4MuonVDNuclearModel::ApplyYourself(const G4HadProjectile& aTrack, 120 G4Nucleus& 120 G4Nucleus& targetNucleus) 121 { 121 { 122 theParticleChange.Clear(); 122 theParticleChange.Clear(); 123 123 124 // For very low energy, return initial track 124 // For very low energy, return initial track 125 G4double epmax = aTrack.GetTotalEnergy() - 0 125 G4double epmax = aTrack.GetTotalEnergy() - 0.5*proton_mass_c2; 126 if (epmax <= CutFixed) { 126 if (epmax <= CutFixed) { 127 theParticleChange.SetStatusChange(isAlive) 127 theParticleChange.SetStatusChange(isAlive); 128 theParticleChange.SetEnergyChange(aTrack.G 128 theParticleChange.SetEnergyChange(aTrack.GetKineticEnergy()); 129 theParticleChange.SetMomentumChange(aTrack 129 theParticleChange.SetMomentumChange(aTrack.Get4Momentum().vect().unit()); 130 return &theParticleChange; 130 return &theParticleChange; 131 } 131 } 132 132 133 // Produce recoil muon and transferred photo 133 // Produce recoil muon and transferred photon 134 G4DynamicParticle* transferredPhoton = Calcu 134 G4DynamicParticle* transferredPhoton = CalculateEMVertex(aTrack, targetNucleus); 135 135 136 // Interact the gamma with the nucleus 136 // Interact the gamma with the nucleus 137 CalculateHadronicVertex(transferredPhoton, t 137 CalculateHadronicVertex(transferredPhoton, targetNucleus); 138 return &theParticleChange; 138 return &theParticleChange; 139 } 139 } 140 140 141 G4DynamicParticle* 141 G4DynamicParticle* 142 G4MuonVDNuclearModel::CalculateEMVertex(const 142 G4MuonVDNuclearModel::CalculateEMVertex(const G4HadProjectile& aTrack, 143 G4Nucl 143 G4Nucleus& targetNucleus) 144 { 144 { 145 // Select sampling table 145 // Select sampling table 146 G4double KineticEnergy = aTrack.GetKineticEn 146 G4double KineticEnergy = aTrack.GetKineticEnergy(); 147 G4double TotalEnergy = aTrack.GetTotalEnergy 147 G4double TotalEnergy = aTrack.GetTotalEnergy(); 148 G4double Mass = G4MuonMinus::MuonMinus()->Ge 148 G4double Mass = G4MuonMinus::MuonMinus()->GetPDGMass(); 149 G4Pow* g4calc = G4Pow::GetInstance(); 149 G4Pow* g4calc = G4Pow::GetInstance(); 150 G4double lnZ = g4calc->logZ(targetNucleus.Ge 150 G4double lnZ = g4calc->logZ(targetNucleus.GetZ_asInt()); 151 151 152 G4double epmin = CutFixed; 152 G4double epmin = CutFixed; 153 G4double epmax = TotalEnergy - 0.5*proton_ma 153 G4double epmax = TotalEnergy - 0.5*proton_mass_c2; 154 G4double m0 = CutFixed; 154 G4double m0 = CutFixed; 155 155 156 G4double delmin = 1.e10; 156 G4double delmin = 1.e10; 157 G4double del; 157 G4double del; 158 G4int izz = 0; 158 G4int izz = 0; 159 G4int itt = 0; 159 G4int itt = 0; 160 160 161 for (G4int iz = 0; iz < nzdat; ++iz) { 161 for (G4int iz = 0; iz < nzdat; ++iz) { 162 del = std::abs(lnZ - g4calc->logZ(zdat[iz] 162 del = std::abs(lnZ - g4calc->logZ(zdat[iz])); 163 if (del < delmin) { 163 if (del < delmin) { 164 delmin = del; 164 delmin = del; 165 izz = iz; 165 izz = iz; 166 } 166 } 167 } 167 } 168 168 169 delmin = 1.e10; 169 delmin = 1.e10; 170 for (G4int it = 0; it < ntdat; ++it) { 170 for (G4int it = 0; it < ntdat; ++it) { 171 del = std::abs(G4Log(KineticEnergy)-G4Log( 171 del = std::abs(G4Log(KineticEnergy)-G4Log(tdat[it]) ); 172 if (del < delmin) { 172 if (del < delmin) { 173 delmin = del; 173 delmin = del; 174 itt = it; 174 itt = it; 175 } 175 } 176 } 176 } 177 177 178 // Sample the energy transfer according to t 178 // Sample the energy transfer according to the probability table 179 G4double r = G4UniformRand(); 179 G4double r = G4UniformRand(); 180 180 181 G4int iy; 181 G4int iy; 182 182 183 G4int Z = zdat[izz]; 183 G4int Z = zdat[izz]; 184 184 185 for(iy = 0; iy<NBIN; ++iy) { 185 for(iy = 0; iy<NBIN; ++iy) { 186 186 187 G4double pvv = fElementData->GetElement2DD 187 G4double pvv = fElementData->GetElement2DData(Z)->GetValue(iy, itt); 188 if(pvv >= r) { break; } 188 if(pvv >= r) { break; } 189 } 189 } 190 190 191 // Sampling is done uniformly in y in the bi 191 // Sampling is done uniformly in y in the bin 192 G4double pvx = fElementData->GetElement2DDat 192 G4double pvx = fElementData->GetElement2DData(Z)->GetX(iy); 193 G4double pvx1 = fElementData->GetElement2DDa 193 G4double pvx1 = fElementData->GetElement2DData(Z)->GetX(iy+1); 194 G4double y = pvx + G4UniformRand() * (pvx1 - 194 G4double y = pvx + G4UniformRand() * (pvx1 - pvx); 195 195 196 G4double x = G4Exp(y); 196 G4double x = G4Exp(y); 197 G4double ep = epmin*G4Exp(x*G4Log(epmax/epmi 197 G4double ep = epmin*G4Exp(x*G4Log(epmax/epmin) ); 198 198 199 // Sample scattering angle of mu, but first 199 // Sample scattering angle of mu, but first t should be sampled. 200 G4double yy = ep/TotalEnergy; 200 G4double yy = ep/TotalEnergy; 201 G4double tmin = Mass*Mass*yy*yy/(1.-yy); 201 G4double tmin = Mass*Mass*yy*yy/(1.-yy); 202 G4double tmax = 2.*proton_mass_c2*ep; 202 G4double tmax = 2.*proton_mass_c2*ep; 203 G4double t1; 203 G4double t1; 204 G4double t2; 204 G4double t2; 205 if (m0 < ep) { 205 if (m0 < ep) { 206 t1 = m0*m0; 206 t1 = m0*m0; 207 t2 = ep*ep; 207 t2 = ep*ep; 208 } else { 208 } else { 209 t1 = ep*ep; 209 t1 = ep*ep; 210 t2 = m0*m0; 210 t2 = m0*m0; 211 } 211 } 212 212 213 G4double w1 = tmax*t1; 213 G4double w1 = tmax*t1; 214 G4double w2 = tmax+t1; 214 G4double w2 = tmax+t1; 215 G4double w3 = tmax*(tmin+t1)/(tmin*w2); 215 G4double w3 = tmax*(tmin+t1)/(tmin*w2); 216 G4double y1 = 1.-yy; 216 G4double y1 = 1.-yy; 217 G4double y2 = 0.5*yy*yy; 217 G4double y2 = 0.5*yy*yy; 218 G4double y3 = y1+y2; 218 G4double y3 = y1+y2; 219 219 220 G4double t = 0.0; 220 G4double t = 0.0; 221 G4double rej = 0.0; 221 G4double rej = 0.0; 222 222 223 // Now sample t 223 // Now sample t 224 G4int ntry = 0; 224 G4int ntry = 0; 225 do 225 do 226 { 226 { 227 ntry += 1; 227 ntry += 1; 228 if (ntry > 10000) { 228 if (ntry > 10000) { 229 G4ExceptionDescription eda; 229 G4ExceptionDescription eda; 230 eda << " While count exceeded " << G4end 230 eda << " While count exceeded " << G4endl; 231 G4Exception("G4MuonVDNuclearModel::Calcu 231 G4Exception("G4MuonVDNuclearModel::CalculateEMVertex()", "HAD_RPG_100", JustWarning, eda); 232 break; 232 break; 233 } 233 } 234 234 235 t = w1/(w2*G4Exp(G4UniformRand()*G4Log(w3) 235 t = w1/(w2*G4Exp(G4UniformRand()*G4Log(w3))-tmax); 236 rej = (1.-t/tmax)*(y1*(1.-tmin/t)+y2)/(y3* 236 rej = (1.-t/tmax)*(y1*(1.-tmin/t)+y2)/(y3*(1.-t/t2)); 237 } while (G4UniformRand() > rej) ; /* Loop 237 } while (G4UniformRand() > rej) ; /* Loop checking, 01.09.2015, D.Wright */ 238 238 239 // compute angle from t 239 // compute angle from t 240 G4double sinth2 = 240 G4double sinth2 = 241 0.5*(t-tmin)/(2.*(TotalEnergy*(To 241 0.5*(t-tmin)/(2.*(TotalEnergy*(TotalEnergy-ep)-Mass*Mass)-tmin); 242 G4double theta = std::acos(1. - 2.*sinth2); 242 G4double theta = std::acos(1. - 2.*sinth2); 243 243 244 G4double phi = twopi*G4UniformRand(); 244 G4double phi = twopi*G4UniformRand(); 245 G4double sinth = std::sin(theta); 245 G4double sinth = std::sin(theta); 246 G4double dirx = sinth*std::cos(phi); 246 G4double dirx = sinth*std::cos(phi); 247 G4double diry = sinth*std::sin(phi); 247 G4double diry = sinth*std::sin(phi); 248 G4double dirz = std::cos(theta); 248 G4double dirz = std::cos(theta); 249 G4ThreeVector finalDirection(dirx,diry,dirz) 249 G4ThreeVector finalDirection(dirx,diry,dirz); 250 G4ThreeVector ParticleDirection(aTrack.Get4M 250 G4ThreeVector ParticleDirection(aTrack.Get4Momentum().vect().unit() ); 251 finalDirection.rotateUz(ParticleDirection); 251 finalDirection.rotateUz(ParticleDirection); 252 252 253 G4double NewKinEnergy = KineticEnergy - ep; 253 G4double NewKinEnergy = KineticEnergy - ep; 254 G4double finalMomentum = std::sqrt(NewKinEne 254 G4double finalMomentum = std::sqrt(NewKinEnergy*(NewKinEnergy+2.*Mass) ); 255 G4double Ef = NewKinEnergy + Mass; 255 G4double Ef = NewKinEnergy + Mass; 256 G4double initMomentum = std::sqrt(KineticEne 256 G4double initMomentum = std::sqrt(KineticEnergy*(TotalEnergy+Mass) ); 257 257 258 // Set energy and direction of scattered pri 258 // Set energy and direction of scattered primary in theParticleChange 259 theParticleChange.SetStatusChange(isAlive); 259 theParticleChange.SetStatusChange(isAlive); 260 theParticleChange.SetEnergyChange(NewKinEner 260 theParticleChange.SetEnergyChange(NewKinEnergy); 261 theParticleChange.SetMomentumChange(finalDir 261 theParticleChange.SetMomentumChange(finalDirection); 262 262 263 // Now create the emitted gamma 263 // Now create the emitted gamma 264 G4LorentzVector primaryMomentum(initMomentum 264 G4LorentzVector primaryMomentum(initMomentum*ParticleDirection, TotalEnergy); 265 G4LorentzVector fsMomentum(finalMomentum*fin 265 G4LorentzVector fsMomentum(finalMomentum*finalDirection, Ef); 266 G4LorentzVector momentumTransfer = primaryMo 266 G4LorentzVector momentumTransfer = primaryMomentum - fsMomentum; 267 267 268 G4DynamicParticle* gamma = 268 G4DynamicParticle* gamma = 269 new G4DynamicParticle(G4Gamma::Gamm 269 new G4DynamicParticle(G4Gamma::Gamma(), momentumTransfer); 270 270 271 return gamma; 271 return gamma; 272 } 272 } 273 273 274 void 274 void 275 G4MuonVDNuclearModel::CalculateHadronicVertex( 275 G4MuonVDNuclearModel::CalculateHadronicVertex(G4DynamicParticle* incident, 276 276 G4Nucleus& target) 277 { 277 { 278 G4HadFinalState* hfs = 0; 278 G4HadFinalState* hfs = 0; 279 G4double gammaE = incident->GetTotalEnergy() 279 G4double gammaE = incident->GetTotalEnergy(); 280 280 281 if (gammaE < 10*GeV) { 281 if (gammaE < 10*GeV) { 282 G4HadProjectile projectile(*incident); 282 G4HadProjectile projectile(*incident); 283 hfs = bert->ApplyYourself(projectile, targ 283 hfs = bert->ApplyYourself(projectile, target); 284 } else { 284 } else { 285 // convert incident gamma to a pi0 285 // convert incident gamma to a pi0 286 G4double piMass = G4PionZero::PionZero()-> 286 G4double piMass = G4PionZero::PionZero()->GetPDGMass(); 287 G4double piKE = incident->GetTotalEnergy() 287 G4double piKE = incident->GetTotalEnergy() - piMass; 288 G4double piMom = std::sqrt(piKE*(piKE + 2* 288 G4double piMom = std::sqrt(piKE*(piKE + 2*piMass) ); 289 G4ThreeVector piMomentum(incident->GetMome 289 G4ThreeVector piMomentum(incident->GetMomentumDirection() ); 290 piMomentum *= piMom; 290 piMomentum *= piMom; 291 G4DynamicParticle theHadron(G4PionZero::Pi 291 G4DynamicParticle theHadron(G4PionZero::PionZero(), piMomentum); 292 G4HadProjectile projectile(theHadron); 292 G4HadProjectile projectile(theHadron); 293 hfs = ftfp->ApplyYourself(projectile, targ 293 hfs = ftfp->ApplyYourself(projectile, target); 294 } 294 } 295 295 296 delete incident; 296 delete incident; 297 297 298 // Assign the creator model ID to the second 298 // Assign the creator model ID to the secondaries 299 for ( size_t i = 0; i < hfs->GetNumberOfSeco 299 for ( size_t i = 0; i < hfs->GetNumberOfSecondaries(); ++i ) { 300 hfs->GetSecondary( i )->SetCreatorModelID( 300 hfs->GetSecondary( i )->SetCreatorModelID( secID ); 301 } 301 } 302 302 303 // Copy secondaries from sub-model to model 303 // Copy secondaries from sub-model to model 304 theParticleChange.AddSecondaries(hfs); 304 theParticleChange.AddSecondaries(hfs); 305 } 305 } 306 306 307 307 308 void G4MuonVDNuclearModel::MakeSamplingTable() 308 void G4MuonVDNuclearModel::MakeSamplingTable() 309 { 309 { 310 G4int nbin; 310 G4int nbin; 311 G4double KineticEnergy; 311 G4double KineticEnergy; 312 G4double TotalEnergy; 312 G4double TotalEnergy; 313 G4double Maxep; 313 G4double Maxep; 314 G4double CrossSection; 314 G4double CrossSection; 315 315 316 G4double c; 316 G4double c; 317 G4double y; 317 G4double y; 318 G4double ymin,ymax; 318 G4double ymin,ymax; 319 G4double dy,yy; 319 G4double dy,yy; 320 G4double dx,x; 320 G4double dx,x; 321 G4double ep; 321 G4double ep; 322 322 323 G4double AtomicNumber; 323 G4double AtomicNumber; 324 G4double AtomicWeight; 324 G4double AtomicWeight; 325 325 326 G4double mumass = G4MuonMinus::MuonMinus()-> 326 G4double mumass = G4MuonMinus::MuonMinus()->GetPDGMass(); 327 327 328 for (G4int iz = 0; iz < nzdat; ++iz) { 328 for (G4int iz = 0; iz < nzdat; ++iz) { 329 AtomicNumber = zdat[iz]; 329 AtomicNumber = zdat[iz]; 330 AtomicWeight = adat[iz]*(g/mole); 330 AtomicWeight = adat[iz]*(g/mole); 331 331 332 G4Physics2DVector* pv = new G4Physics2DVec 332 G4Physics2DVector* pv = new G4Physics2DVector(NBIN+1,ntdat+1); 333 G4double pvv; 333 G4double pvv; 334 334 335 for (G4int it = 0; it < ntdat; ++it) { 335 for (G4int it = 0; it < ntdat; ++it) { 336 KineticEnergy = tdat[it]; 336 KineticEnergy = tdat[it]; 337 TotalEnergy = KineticEnergy + mumass; 337 TotalEnergy = KineticEnergy + mumass; 338 Maxep = TotalEnergy - 0.5*proton_mass_c2 338 Maxep = TotalEnergy - 0.5*proton_mass_c2; 339 339 340 CrossSection = 0.0; 340 CrossSection = 0.0; 341 341 342 // Calculate the differential cross sect 342 // Calculate the differential cross section 343 // numerical integration in log ........ 343 // numerical integration in log ......... 344 c = G4Log(Maxep/CutFixed); 344 c = G4Log(Maxep/CutFixed); 345 ymin = -5.0; 345 ymin = -5.0; 346 ymax = 0.0; 346 ymax = 0.0; 347 dy = (ymax-ymin)/NBIN; 347 dy = (ymax-ymin)/NBIN; 348 348 349 nbin=-1; 349 nbin=-1; 350 350 351 y = ymin - 0.5*dy; 351 y = ymin - 0.5*dy; 352 yy = ymin - dy; 352 yy = ymin - dy; 353 for (G4int i = 0; i < NBIN; ++i) { 353 for (G4int i = 0; i < NBIN; ++i) { 354 y += dy; 354 y += dy; 355 x = G4Exp(y); 355 x = G4Exp(y); 356 yy += dy; 356 yy += dy; 357 dx = G4Exp(yy+dy)-G4Exp(yy); 357 dx = G4Exp(yy+dy)-G4Exp(yy); 358 358 359 ep = CutFixed*G4Exp(c*x); 359 ep = CutFixed*G4Exp(c*x); 360 360 361 CrossSection += 361 CrossSection += 362 ep*dx*muNucXS->ComputeDDMicroscopic 362 ep*dx*muNucXS->ComputeDDMicroscopicCrossSection(KineticEnergy, 363 AtomicNumber, 363 AtomicNumber, 364 AtomicWeight, ep); 364 AtomicWeight, ep); 365 if (nbin < NBIN) { 365 if (nbin < NBIN) { 366 ++nbin; 366 ++nbin; 367 pv->PutValue(nbin, it, CrossSection) 367 pv->PutValue(nbin, it, CrossSection); 368 pv->PutX(nbin, y); 368 pv->PutX(nbin, y); 369 } 369 } 370 } 370 } 371 pv->PutX(NBIN, 0.); 371 pv->PutX(NBIN, 0.); 372 372 373 if (CrossSection > 0.0) { 373 if (CrossSection > 0.0) { 374 for (G4int ib = 0; ib <= nbin; ++ib) { 374 for (G4int ib = 0; ib <= nbin; ++ib) { 375 pvv = pv->GetValue(ib, it); 375 pvv = pv->GetValue(ib, it); 376 pvv = pvv/CrossSection; 376 pvv = pvv/CrossSection; 377 pv->PutValue(ib, it, pvv); 377 pv->PutValue(ib, it, pvv); 378 } 378 } 379 } 379 } 380 } // loop on it 380 } // loop on it 381 381 382 fElementData->InitialiseForElement(zdat[iz 382 fElementData->InitialiseForElement(zdat[iz], pv); 383 } // loop on iz 383 } // loop on iz 384 384 385 // G4cout << " Kokoulin XS = " 385 // G4cout << " Kokoulin XS = " 386 // << muNucXS->ComputeDDMicroscopicCro 386 // << muNucXS->ComputeDDMicroscopicCrossSection(1*GeV, 20.0, 387 // 40.0*g/mole, 0.3*GeV)/millibarn 387 // 40.0*g/mole, 0.3*GeV)/millibarn 388 // << G4endl; 388 // << G4endl; 389 } 389 } 390 390 391 void G4MuonVDNuclearModel::ModelDescription(st 391 void G4MuonVDNuclearModel::ModelDescription(std::ostream& outFile) const 392 { 392 { 393 outFile << "G4MuonVDNuclearModel handles the 393 outFile << "G4MuonVDNuclearModel handles the inelastic scattering\n" 394 << "of mu- and mu+ from nuclei using 394 << "of mu- and mu+ from nuclei using the equivalent photon\n" 395 << "approximation in which the incom 395 << "approximation in which the incoming lepton generates a\n" 396 << "virtual photon at the electromag 396 << "virtual photon at the electromagnetic vertex, and the\n" 397 << "virtual photon is converted to a 397 << "virtual photon is converted to a real photon. At low\n" 398 << "energies, the photon interacts d 398 << "energies, the photon interacts directly with the nucleus\n" 399 << "using the Bertini cascade. At h 399 << "using the Bertini cascade. At high energies the photon\n" 400 << "is converted to a pi0 which inte 400 << "is converted to a pi0 which interacts using the FTFP\n" 401 << "model. The muon-nuclear cross s 401 << "model. The muon-nuclear cross sections of R. Kokoulin \n" 402 << "are used to generate the virtual 402 << "are used to generate the virtual photon spectrum\n"; 403 } 403 } 404 404 405 405