Geant4 Cross Reference |
1 // 2 // ******************************************************************** 3 // * License and Disclaimer * 4 // * * 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. * 10 // * * 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitation of liability. * 17 // * * 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************************************** 25 // 26 // 27 // Geant4 Header : G4NeutrinoElectronCcModel 28 // 29 // Author : V.Grichine 26.4.17 30 // 31 32 #include "G4NeutrinoElectronCcModel.hh" 33 #include "G4SystemOfUnits.hh" 34 #include "G4ParticleTable.hh" 35 #include "G4ParticleDefinition.hh" 36 #include "G4IonTable.hh" 37 #include "Randomize.hh" 38 #include "G4NeutrinoE.hh" 39 #include "G4AntiNeutrinoE.hh" 40 41 #include "G4NeutrinoMu.hh" 42 #include "G4AntiNeutrinoMu.hh" 43 #include "G4NeutrinoTau.hh" 44 #include "G4AntiNeutrinoTau.hh" 45 #include "G4MuonMinus.hh" 46 #include "G4TauMinus.hh" 47 #include "G4HadronicParameters.hh" 48 #include "G4PhysicsModelCatalog.hh" 49 50 using namespace std; 51 using namespace CLHEP; 52 53 G4NeutrinoElectronCcModel::G4NeutrinoElectronCcModel(const G4String& name) 54 : G4HadronicInteraction(name) 55 { 56 SetMinEnergy( 0.0*GeV ); 57 SetMaxEnergy( G4HadronicParameters::Instance()->GetMaxEnergy() ); 58 SetMinEnergy(1.e-6*eV); 59 60 theNeutrinoE = G4NeutrinoE::NeutrinoE(); 61 theAntiNeutrinoE = G4AntiNeutrinoE::AntiNeutrinoE(); 62 63 theNeutrinoMu = G4NeutrinoMu::NeutrinoMu(); 64 theAntiNeutrinoMu = G4AntiNeutrinoMu::AntiNeutrinoMu(); 65 66 theNeutrinoTau = G4NeutrinoTau::NeutrinoTau(); 67 theAntiNeutrinoTau = G4AntiNeutrinoTau::AntiNeutrinoTau(); 68 69 theMuonMinus = G4MuonMinus::MuonMinus(); 70 theTauMinus = G4TauMinus::TauMinus(); 71 72 // PDG2016: sin^2 theta Weinberg 73 74 fSin2tW = 0.23129; // 0.2312; 75 76 fCutEnergy = 0.; // default value 77 78 // Creator model ID 79 secID = G4PhysicsModelCatalog::GetModelID( "model_" + GetModelName() ); 80 } 81 82 83 G4NeutrinoElectronCcModel::~G4NeutrinoElectronCcModel() 84 {} 85 86 87 void G4NeutrinoElectronCcModel::ModelDescription(std::ostream& outFile) const 88 { 89 90 outFile << "G4NeutrinoElectronCcModel is a neutrino-electron (neutral current) elastic scattering\n" 91 << "model which uses the standard model \n" 92 << "transfer parameterization. The model is fully relativistic\n"; 93 94 } 95 96 ///////////////////////////////////////////////////////// 97 98 G4bool G4NeutrinoElectronCcModel::IsApplicable(const G4HadProjectile & aPart, 99 G4Nucleus & ) 100 { 101 G4bool result = false; 102 G4String pName = aPart.GetDefinition()->GetParticleName(); 103 if(pName == "anti_nu_mu" || pName == "anti_nu_tau") return result; // no cc for anti_nu_(mu,tau) 104 G4double minEnergy = 0., energy = aPart.GetTotalEnergy(); 105 G4double fmass, emass = electron_mass_c2; 106 107 if( pName == "nu_mu" ) fmass = theMuonMinus->GetPDGMass(); 108 else if( pName == "nu_tau" ) fmass = theTauMinus->GetPDGMass(); 109 else fmass = emass; 110 111 minEnergy = (fmass-emass)*(fmass+emass)/emass; 112 SetMinEnergy( minEnergy ); 113 114 if( ( pName == "nu_mu" || pName == "nu_tau" || pName == "anti_nu_e" ) && energy > minEnergy ) 115 { 116 result = true; 117 } 118 119 return result; 120 } 121 122 //////////////////////////////////////////////// 123 // 124 // 125 126 G4HadFinalState* G4NeutrinoElectronCcModel::ApplyYourself( 127 const G4HadProjectile& aTrack, G4Nucleus& ) 128 { 129 theParticleChange.Clear(); 130 131 const G4HadProjectile* aParticle = &aTrack; 132 G4double energy = aParticle->GetTotalEnergy(); 133 134 G4String pName = aParticle->GetDefinition()->GetParticleName(); 135 G4double minEnergy(0.), fmass(0.), emass = electron_mass_c2; 136 137 if( pName == "nu_mu" ) fmass = theMuonMinus->GetPDGMass(); 138 else if( pName == "nu_tau" ) fmass = theTauMinus->GetPDGMass(); 139 else fmass = emass; 140 141 minEnergy = (fmass-emass)*(fmass+emass)/emass; 142 143 if( energy <= minEnergy ) 144 { 145 theParticleChange.SetEnergyChange(energy); 146 theParticleChange.SetMomentumChange(aTrack.Get4Momentum().vect().unit()); 147 return &theParticleChange; 148 } 149 G4double massf(0.), massf2(0.); // , emass = electron_mass_c2; 150 G4double sTot = 2.*energy*emass + emass*emass; 151 152 G4LorentzVector lvp1 = aParticle->Get4Momentum(); 153 G4LorentzVector lvt1(0.,0.,0.,electron_mass_c2); 154 G4LorentzVector lvsum = lvp1+lvt1; 155 G4ThreeVector bst = lvsum.boostVector(); 156 157 // sample and make final state in CMS frame 158 159 G4double cost = SampleCosCMS( aParticle ); 160 G4double sint = std::sqrt( (1.0 - cost)*(1.0 + cost) ); 161 G4double phi = G4UniformRand()*CLHEP::twopi; 162 163 G4ThreeVector eP( sint*std::cos(phi), sint*std::sin(phi), cost ); 164 165 if( pName == "nu_mu" ) massf = theMuonMinus->GetPDGMass(); 166 else if( pName == "nu_tau" ) massf = theTauMinus->GetPDGMass(); 167 168 massf2 = massf*massf; 169 170 G4double epf = 0.5*(sTot - massf2)/sqrt(sTot); 171 // G4double etf = epf*(sTot + massf2)/(sTot - massf2); 172 173 eP *= epf; 174 G4LorentzVector lvp2( eP, epf ); 175 lvp2.boost(bst); // back to lab frame 176 177 G4LorentzVector lvt2 = lvsum - lvp2; // ? 178 179 G4DynamicParticle* aNu = nullptr; 180 G4DynamicParticle* aLept = nullptr; 181 182 if( pName == "nu_mu" || pName == "nu_tau") 183 { 184 aNu = new G4DynamicParticle( theNeutrinoE, lvp2 ); 185 } 186 else if( pName == "anti_nu_e" ) aNu = new G4DynamicParticle( theAntiNeutrinoMu, lvp2 ); // s-channel for mu (tau later) 187 188 if( pName == "nu_mu" || pName == "anti_nu_e") 189 { 190 aLept = new G4DynamicParticle( theMuonMinus, lvt2 ); 191 } 192 else if( pName == "nu_tau" ) // || pName == "anti_nu_tau") 193 { 194 aLept = new G4DynamicParticle( theTauMinus, lvt2 ); 195 } 196 if(aNu) { theParticleChange.AddSecondary( aNu, secID ); } 197 if(aLept) { theParticleChange.AddSecondary( aLept, secID ); } 198 199 return &theParticleChange; 200 } 201 202 ////////////////////////////////////////////////////// 203 // 204 // sample recoil electron energy in lab frame 205 206 G4double G4NeutrinoElectronCcModel::SampleCosCMS(const G4HadProjectile* aParticle) 207 { 208 G4double result = 0., cofL, cofR, cofLR, massf2, sTot, emass = electron_mass_c2, emass2; 209 210 G4double energy = aParticle->GetTotalEnergy(); 211 212 if( energy == 0.) return result; // vmg: < th?? as in xsc 213 214 G4String pName = aParticle->GetDefinition()->GetParticleName(); 215 216 if( pName == "nu_mu" || pName == "nu_tau") 217 { 218 return 2.*G4UniformRand()-1.; // uniform scattering cos in CMS 219 } 220 else if( pName == "anti_nu_mu" || pName == "anti_nu_tau") 221 { 222 emass2 = emass*emass; 223 sTot = 2.*energy*emass + emass2; 224 225 cofL = (sTot-emass2)/(sTot+emass2); 226 227 if(pName == "anti_nu_mu") massf2 = theMuonMinus->GetPDGMass()*theMuonMinus->GetPDGMass(); 228 else massf2 = theTauMinus->GetPDGMass()*theTauMinus->GetPDGMass(); 229 230 cofR = (sTot-massf2)/(sTot+massf2); 231 232 cofLR = cofL*cofR/3.; 233 234 // cofs of cos 3rd equation 235 236 G4double a = cofLR; 237 G4double b = 0.5*(cofR+cofL); 238 G4double c = 1.; 239 240 G4double d = -G4UniformRand()*2.*(1.+ cofLR); 241 d += c - b + a; 242 243 // G4cout<<a<<" "<<b<<" "<<c<<" "<<d<<G4endl<<G4endl; 244 245 // cofs of the incomplete 3rd equation 246 247 G4double p = c/a; 248 p -= b*b/a/a/3.; 249 250 G4double q = d/a; 251 q -= b*c/a/a/3.; 252 q += 2*b*b*b/a/a/a/27.; 253 254 255 // cofs for the incomplete colutions 256 257 G4double D = p*p*p/3./3./3.; 258 D += q*q/2./2.; 259 260 // G4cout<<"D = "<<D<<G4endl; 261 if(D < 0.) D = -D; 262 // G4complex A1 = G4complex(- q/2., std::sqrt(-D) ); 263 // G4complex A = std::pow(A1,1./3.); 264 265 // G4complex B1 = G4complex(- q/2., -std::sqrt(-D) ); 266 // G4complex B = std::pow(B1,1./3.); 267 268 G4double A, B; 269 270 G4double A1 = - q/2. + std::sqrt(D); 271 if (A1 < 0.) A1 = -A1; 272 A = std::pow(A1,1./3.); 273 if (A1 < 0.) A = -A; 274 275 G4double B1 = - q/2. - std::sqrt(D); 276 // G4double B = std::pow(-B1,1./3.); 277 if(B1 < 0.) B1 = -B1; 278 B = std::pow(B1,1./3.); 279 if(B1 < 0.) B = -B; 280 // G4cout<<"A1 = "<<A1<<"; A = "<<A<<"; B1 = "<<B1<<"; B = "<<B<<G4endl; 281 // roots of the incomplete 3rd equation 282 283 G4complex y1 = A + B; 284 // G4complex y2 = -0.5*(A + B) + 0.5*std::sqrt(3.)*(A - B)*G4complex(0.,1.); 285 // G4complex y3 = -0.5*(A + B) - 0.5*std::sqrt(3.)*(A - B)*G4complex(0.,1.); 286 287 G4complex x1 = y1 - b/a/3.; 288 // G4complex x2 = y2 - b/a/3.; 289 // G4complex x3 = y3 - b/a/3.; 290 // G4cout<<"re_x1 = "<<real(x1)<<" + i*"<<imag(x1)<<G4endl; 291 // G4cout<<"re_x1 = "<<real(x1)<<"; re_x2 = "<<real(x2)<<"; re_x3 = "<<real(x3)<<G4endl; 292 // G4cout<<"im_x1 = "<<imag(x1)<<"; im_x2 = "<<imag(x2)<<"; im_x3 = "<<imag(x3)<<G4endl<<G4endl; 293 294 result = real(x1); 295 } 296 else 297 { 298 return result; 299 } 300 return result; 301 } 302 303 // 304 // 305 /////////////////////////// 306