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 // $Id: G4NuMuNucleusNcModel.cc 91806 2015-08- 26 // $Id: G4NuMuNucleusNcModel.cc 91806 2015-08-06 12:20:45Z gcosmo $ 27 // 27 // 28 // Geant4 Header : G4NuMuNucleusNcModel 28 // Geant4 Header : G4NuMuNucleusNcModel 29 // 29 // 30 // Author : V.Grichine 12.2.19 30 // Author : V.Grichine 12.2.19 31 // 31 // 32 32 33 #include "G4NuMuNucleusNcModel.hh" 33 #include "G4NuMuNucleusNcModel.hh" 34 #include "G4NeutrinoNucleusModel.hh" 34 #include "G4NeutrinoNucleusModel.hh" 35 35 36 // #include "G4NuMuResQX.hh" 36 // #include "G4NuMuResQX.hh" 37 37 38 #include "G4SystemOfUnits.hh" 38 #include "G4SystemOfUnits.hh" 39 #include "G4ParticleTable.hh" 39 #include "G4ParticleTable.hh" 40 #include "G4ParticleDefinition.hh" 40 #include "G4ParticleDefinition.hh" 41 #include "G4IonTable.hh" 41 #include "G4IonTable.hh" 42 #include "Randomize.hh" 42 #include "Randomize.hh" 43 #include "G4RandomDirection.hh" 43 #include "G4RandomDirection.hh" 44 44 45 // #include "G4Integrator.hh" 45 // #include "G4Integrator.hh" 46 #include "G4DataVector.hh" 46 #include "G4DataVector.hh" 47 #include "G4PhysicsTable.hh" 47 #include "G4PhysicsTable.hh" 48 #include "G4KineticTrack.hh" 48 #include "G4KineticTrack.hh" 49 #include "G4DecayKineticTracks.hh" 49 #include "G4DecayKineticTracks.hh" 50 #include "G4KineticTrackVector.hh" 50 #include "G4KineticTrackVector.hh" 51 #include "G4Fragment.hh" 51 #include "G4Fragment.hh" 52 #include "G4ReactionProductVector.hh" 52 #include "G4ReactionProductVector.hh" 53 53 54 54 55 #include "G4NeutrinoMu.hh" 55 #include "G4NeutrinoMu.hh" 56 #include "G4AntiNeutrinoMu.hh" 56 #include "G4AntiNeutrinoMu.hh" 57 #include "G4Nucleus.hh" 57 #include "G4Nucleus.hh" 58 #include "G4LorentzVector.hh" 58 #include "G4LorentzVector.hh" 59 59 60 using namespace std; 60 using namespace std; 61 using namespace CLHEP; 61 using namespace CLHEP; 62 62 >> 63 const G4int G4NuMuNucleusNcModel::fResNumber = 6; >> 64 >> 65 const G4double G4NuMuNucleusNcModel::fResMass[6] = // [fResNumber] = >> 66 {2190., 1920., 1700., 1600., 1440., 1232. }; >> 67 >> 68 const G4int G4NuMuNucleusNcModel::fClustNumber = 4; >> 69 >> 70 const G4double G4NuMuNucleusNcModel::fMesMass[4] = {1260., 980., 770., 139.57}; >> 71 const G4int G4NuMuNucleusNcModel::fMesPDG[4] = {20213, 9000211, 213, 211}; >> 72 >> 73 // const G4double G4NuMuNucleusNcModel::fBarMass[4] = {1905., 1600., 1232., 939.57}; >> 74 // const G4int G4NuMuNucleusNcModel::fBarPDG[4] = {2226, 32224, 2224, 2212}; >> 75 >> 76 const G4double G4NuMuNucleusNcModel::fBarMass[4] = {1700., 1600., 1232., 939.57}; >> 77 const G4int G4NuMuNucleusNcModel::fBarPDG[4] = {12224, 32224, 2224, 2212}; >> 78 >> 79 const G4double G4NuMuNucleusNcModel::fNuMuEnergyLogVector[50] = { >> 80 115.603, 133.424, 153.991, 177.729, 205.126, 236.746, 273.24, 315.361, 363.973, 420.08, 484.836, 559.573, 645.832, >> 81 745.387, 860.289, 992.903, 1145.96, 1322.61, 1526.49, 1761.8, 2033.38, 2346.83, 2708.59, 3126.12, 3608.02, 4164.19, >> 82 4806.1, 5546.97, 6402.04, 7388.91, 8527.92, 9842.5, 11359.7, 13110.8, 15131.9, 17464.5, 20156.6, 23263.8, 26849.9, >> 83 30988.8, 35765.7, 41279, 47642.2, 54986.3, 63462.4, 73245.2, 84536, 97567.2, 112607, 129966 }; >> 84 >> 85 G4double G4NuMuNucleusNcModel::fNuMuXarrayKR[50][51] = {{1.0}}; >> 86 G4double G4NuMuNucleusNcModel::fNuMuXdistrKR[50][50] = {{1.0}}; >> 87 G4double G4NuMuNucleusNcModel::fNuMuQarrayKR[50][51][51] = {{{1.0}}}; >> 88 G4double G4NuMuNucleusNcModel::fNuMuQdistrKR[50][51][50] = {{{1.0}}}; >> 89 63 #ifdef G4MULTITHREADED 90 #ifdef G4MULTITHREADED 64 G4Mutex G4NuMuNucleusNcModel::numuNucleusM 91 G4Mutex G4NuMuNucleusNcModel::numuNucleusModel = G4MUTEX_INITIALIZER; 65 #endif 92 #endif 66 93 67 94 68 G4NuMuNucleusNcModel::G4NuMuNucleusNcModel(con 95 G4NuMuNucleusNcModel::G4NuMuNucleusNcModel(const G4String& name) 69 : G4NeutrinoNucleusModel(name) 96 : G4NeutrinoNucleusModel(name) 70 { 97 { 71 SetMinEnergy( 0.0*GeV ); 98 SetMinEnergy( 0.0*GeV ); 72 SetMaxEnergy( 100.*TeV ); 99 SetMaxEnergy( 100.*TeV ); 73 SetMinEnergy(1.e-6*eV); << 100 SetMinEnergy(1.e-6*eV); 74 << 75 theNuMu = G4NeutrinoMu::NeutrinoMu(); << 76 theANuMu = G4AntiNeutrinoMu::AntiNeutrinoMu << 77 101 78 fMnumu = 0.; 102 fMnumu = 0.; 79 fData = fMaster = false; 103 fData = fMaster = false; 80 InitialiseModel(); 104 InitialiseModel(); 81 105 82 } 106 } 83 107 84 108 85 G4NuMuNucleusNcModel::~G4NuMuNucleusNcModel() 109 G4NuMuNucleusNcModel::~G4NuMuNucleusNcModel() 86 {} 110 {} 87 111 88 112 89 void G4NuMuNucleusNcModel::ModelDescription(st 113 void G4NuMuNucleusNcModel::ModelDescription(std::ostream& outFile) const 90 { 114 { 91 115 92 outFile << "G4NuMuNucleusNcModel is a neut 116 outFile << "G4NuMuNucleusNcModel is a neutrino-nucleus (neutral current) scattering\n" 93 << "model which uses the standard 117 << "model which uses the standard model \n" 94 << "transfer parameterization. Th 118 << "transfer parameterization. The model is fully relativistic\n"; 95 119 96 } 120 } 97 121 98 ////////////////////////////////////////////// 122 ///////////////////////////////////////////////////////// 99 // 123 // 100 // Read data from G4PARTICLEXSDATA (locally PA 124 // Read data from G4PARTICLEXSDATA (locally PARTICLEXSDATA) 101 125 102 void G4NuMuNucleusNcModel::InitialiseModel() 126 void G4NuMuNucleusNcModel::InitialiseModel() 103 { 127 { 104 G4String pName = "nu_mu"; 128 G4String pName = "nu_mu"; 105 129 106 G4int nSize(0), i(0), j(0), k(0); 130 G4int nSize(0), i(0), j(0), k(0); 107 131 108 if(!fData) 132 if(!fData) 109 { 133 { 110 #ifdef G4MULTITHREADED 134 #ifdef G4MULTITHREADED 111 G4MUTEXLOCK(&numuNucleusModel); 135 G4MUTEXLOCK(&numuNucleusModel); 112 if(!fData) 136 if(!fData) 113 { 137 { 114 #endif 138 #endif 115 fMaster = true; 139 fMaster = true; 116 #ifdef G4MULTITHREADED 140 #ifdef G4MULTITHREADED 117 } 141 } 118 G4MUTEXUNLOCK(&numuNucleusModel); 142 G4MUTEXUNLOCK(&numuNucleusModel); 119 #endif 143 #endif 120 } 144 } 121 145 122 if(fMaster) 146 if(fMaster) 123 { 147 { 124 const char* path = G4FindDataDir("G4PARTIC << 148 char* path = getenv("G4PARTICLEXSDATA"); 125 std::ostringstream ost1, ost2, ost3, ost4; 149 std::ostringstream ost1, ost2, ost3, ost4; 126 ost1 << path << "/" << "neutrino" << "/" < 150 ost1 << path << "/" << "neutrino" << "/" << pName << "/xarraynckr"; 127 151 128 std::ifstream filein1( ost1.str().c_str() 152 std::ifstream filein1( ost1.str().c_str() ); 129 153 130 // filein.open("$PARTICLEXSDATA/"); 154 // filein.open("$PARTICLEXSDATA/"); 131 155 132 filein1>>nSize; 156 filein1>>nSize; 133 157 134 for( k = 0; k < fNbin; ++k ) 158 for( k = 0; k < fNbin; ++k ) 135 { 159 { 136 for( i = 0; i <= fNbin; ++i ) 160 for( i = 0; i <= fNbin; ++i ) 137 { 161 { 138 filein1 >> fNuMuXarrayKR[k][i]; 162 filein1 >> fNuMuXarrayKR[k][i]; 139 // G4cout<< fNuMuXarrayKR[k][i] << " 163 // G4cout<< fNuMuXarrayKR[k][i] << " "; 140 } 164 } 141 } 165 } 142 // G4cout<<G4endl<<G4endl; 166 // G4cout<<G4endl<<G4endl; 143 167 144 ost2 << path << "/" << "neutrino" << "/" < 168 ost2 << path << "/" << "neutrino" << "/" << pName << "/xdistrnckr"; 145 std::ifstream filein2( ost2.str().c_str() 169 std::ifstream filein2( ost2.str().c_str() ); 146 170 147 filein2>>nSize; 171 filein2>>nSize; 148 172 149 for( k = 0; k < fNbin; ++k ) 173 for( k = 0; k < fNbin; ++k ) 150 { 174 { 151 for( i = 0; i < fNbin; ++i ) 175 for( i = 0; i < fNbin; ++i ) 152 { 176 { 153 filein2 >> fNuMuXdistrKR[k][i]; 177 filein2 >> fNuMuXdistrKR[k][i]; 154 // G4cout<< fNuMuXdistrKR[k][i] << " 178 // G4cout<< fNuMuXdistrKR[k][i] << " "; 155 } 179 } 156 } 180 } 157 // G4cout<<G4endl<<G4endl; 181 // G4cout<<G4endl<<G4endl; 158 182 159 ost3 << path << "/" << "neutrino" << "/" < 183 ost3 << path << "/" << "neutrino" << "/" << pName << "/q2arraynckr"; 160 std::ifstream filein3( ost3.str().c_str() 184 std::ifstream filein3( ost3.str().c_str() ); 161 185 162 filein3>>nSize; 186 filein3>>nSize; 163 187 164 for( k = 0; k < fNbin; ++k ) 188 for( k = 0; k < fNbin; ++k ) 165 { 189 { 166 for( i = 0; i <= fNbin; ++i ) 190 for( i = 0; i <= fNbin; ++i ) 167 { 191 { 168 for( j = 0; j <= fNbin; ++j ) 192 for( j = 0; j <= fNbin; ++j ) 169 { 193 { 170 filein3 >> fNuMuQarrayKR[k][i][j]; 194 filein3 >> fNuMuQarrayKR[k][i][j]; 171 // G4cout<< fNuMuQarrayKR[k][i][j] < 195 // G4cout<< fNuMuQarrayKR[k][i][j] << " "; 172 } 196 } 173 } 197 } 174 } 198 } 175 // G4cout<<G4endl<<G4endl; 199 // G4cout<<G4endl<<G4endl; 176 200 177 ost4 << path << "/" << "neutrino" << "/" < 201 ost4 << path << "/" << "neutrino" << "/" << pName << "/q2distrnckr"; 178 std::ifstream filein4( ost4.str().c_str() 202 std::ifstream filein4( ost4.str().c_str() ); 179 203 180 filein4>>nSize; 204 filein4>>nSize; 181 205 182 for( k = 0; k < fNbin; ++k ) 206 for( k = 0; k < fNbin; ++k ) 183 { 207 { 184 for( i = 0; i <= fNbin; ++i ) 208 for( i = 0; i <= fNbin; ++i ) 185 { 209 { 186 for( j = 0; j < fNbin; ++j ) 210 for( j = 0; j < fNbin; ++j ) 187 { 211 { 188 filein4 >> fNuMuQdistrKR[k][i][j]; 212 filein4 >> fNuMuQdistrKR[k][i][j]; 189 // G4cout<< fNuMuQdistrKR[k][i][j] < 213 // G4cout<< fNuMuQdistrKR[k][i][j] << " "; 190 } 214 } 191 } 215 } 192 } 216 } 193 fData = true; 217 fData = true; 194 } 218 } 195 } 219 } 196 220 197 ////////////////////////////////////////////// 221 ///////////////////////////////////////////////////////// 198 222 199 G4bool G4NuMuNucleusNcModel::IsApplicable(cons 223 G4bool G4NuMuNucleusNcModel::IsApplicable(const G4HadProjectile & aPart, 200 G4Nucleus & ) << 224 G4Nucleus & targetNucleus) 201 { 225 { 202 G4bool result = false; 226 G4bool result = false; 203 G4String pName = aPart.GetDefinition()->GetP 227 G4String pName = aPart.GetDefinition()->GetParticleName(); 204 G4double energy = aPart.GetTotalEnergy(); 228 G4double energy = aPart.GetTotalEnergy(); 205 229 206 if( pName == "nu_mu" // || pName == "anti_n 230 if( pName == "nu_mu" // || pName == "anti_nu_mu" ) 207 && 231 && 208 energy > fMinNuEnergy 232 energy > fMinNuEnergy ) 209 { 233 { 210 result = true; 234 result = true; 211 } 235 } >> 236 G4int Z = targetNucleus.GetZ_asInt(); >> 237 Z *= 1; 212 238 213 return result; 239 return result; 214 } 240 } 215 241 216 /////////////////////////////////////////// Cl 242 /////////////////////////////////////////// ClusterDecay //////////////////////////////////////////////////////////// 217 // 243 // 218 // 244 // 219 245 220 G4HadFinalState* G4NuMuNucleusNcModel::ApplyYo 246 G4HadFinalState* G4NuMuNucleusNcModel::ApplyYourself( 221 const G4HadProjectile& aTrack, G4Nucleus& 247 const G4HadProjectile& aTrack, G4Nucleus& targetNucleus) 222 { 248 { 223 theParticleChange.Clear(); 249 theParticleChange.Clear(); 224 fProton = f2p2h = fBreak = false; 250 fProton = f2p2h = fBreak = false; 225 const G4HadProjectile* aParticle = &aTrack; 251 const G4HadProjectile* aParticle = &aTrack; 226 G4double energy = aParticle->GetTotalEnergy( 252 G4double energy = aParticle->GetTotalEnergy(); 227 253 228 G4String pName = aParticle->GetDefinition() 254 G4String pName = aParticle->GetDefinition()->GetParticleName(); 229 255 230 if( energy < fMinNuEnergy ) 256 if( energy < fMinNuEnergy ) 231 { 257 { 232 theParticleChange.SetEnergyChange(energy); 258 theParticleChange.SetEnergyChange(energy); 233 theParticleChange.SetMomentumChange(aTrack 259 theParticleChange.SetMomentumChange(aTrack.Get4Momentum().vect().unit()); 234 return &theParticleChange; 260 return &theParticleChange; 235 } 261 } 236 SampleLVkr( aTrack, targetNucleus); 262 SampleLVkr( aTrack, targetNucleus); 237 263 238 if( fBreak == true || fEmu < fMnumu ) // ~5* 264 if( fBreak == true || fEmu < fMnumu ) // ~5*10^-6 239 { 265 { 240 // G4cout<<"ni, "; 266 // G4cout<<"ni, "; 241 theParticleChange.SetEnergyChange(energy); 267 theParticleChange.SetEnergyChange(energy); 242 theParticleChange.SetMomentumChange(aTrack 268 theParticleChange.SetMomentumChange(aTrack.Get4Momentum().vect().unit()); 243 return &theParticleChange; 269 return &theParticleChange; 244 } 270 } 245 271 246 // LVs of initial state 272 // LVs of initial state 247 273 248 G4LorentzVector lvp1 = aParticle->Get4Moment 274 G4LorentzVector lvp1 = aParticle->Get4Momentum(); 249 G4LorentzVector lvt1( 0., 0., 0., fM1 ); 275 G4LorentzVector lvt1( 0., 0., 0., fM1 ); 250 G4double mPip = G4ParticleTable::GetParticle 276 G4double mPip = G4ParticleTable::GetParticleTable()->FindParticle(211)->GetPDGMass(); 251 277 252 // 1-pi by fQtransfer && nu-energy 278 // 1-pi by fQtransfer && nu-energy 253 G4LorentzVector lvpip1( 0., 0., 0., mPip ); 279 G4LorentzVector lvpip1( 0., 0., 0., mPip ); 254 G4LorentzVector lvsum, lv2, lvX; 280 G4LorentzVector lvsum, lv2, lvX; 255 G4ThreeVector eP; 281 G4ThreeVector eP; 256 G4double cost(1.), sint(0.), phi(0.), muMom( 282 G4double cost(1.), sint(0.), phi(0.), muMom(0.), massX2(0.); 257 G4DynamicParticle* aLept = nullptr; // lepto 283 G4DynamicParticle* aLept = nullptr; // lepton lv 258 284 259 G4int Z = targetNucleus.GetZ_asInt(); 285 G4int Z = targetNucleus.GetZ_asInt(); 260 G4int A = targetNucleus.GetA_asInt(); 286 G4int A = targetNucleus.GetA_asInt(); 261 G4double mTarg = targetNucleus.AtomicMass(A 287 G4double mTarg = targetNucleus.AtomicMass(A,Z); 262 G4int pdgP(0), qB(0); 288 G4int pdgP(0), qB(0); 263 // G4double mSum = G4ParticleTable::GetParti 289 // G4double mSum = G4ParticleTable::GetParticleTable()->FindParticle(2212)->GetPDGMass() + mPip; 264 290 265 G4int iPi = GetOnePionIndex(energy); 291 G4int iPi = GetOnePionIndex(energy); 266 G4double p1pi = GetNuMuOnePionProb( iPi, ene 292 G4double p1pi = GetNuMuOnePionProb( iPi, energy); 267 293 268 if( p1pi > G4UniformRand() && fCosTheta > 0. << 294 if( p1pi > G4UniformRand() ) // && fQtransfer < 0.95*GeV ) // mu- & coherent pion + nucleus 269 { 295 { 270 // lvsum = lvp1 + lvpip1; 296 // lvsum = lvp1 + lvpip1; 271 lvsum = lvp1 + lvt1; 297 lvsum = lvp1 + lvt1; 272 // cost = fCosThetaPi; 298 // cost = fCosThetaPi; 273 cost = fCosTheta; 299 cost = fCosTheta; 274 sint = std::sqrt( (1.0 - cost)*(1.0 + cost 300 sint = std::sqrt( (1.0 - cost)*(1.0 + cost) ); 275 phi = G4UniformRand()*CLHEP::twopi; 301 phi = G4UniformRand()*CLHEP::twopi; 276 eP = G4ThreeVector( sint*std::cos(phi), 302 eP = G4ThreeVector( sint*std::cos(phi), sint*std::sin(phi), cost ); 277 303 278 // muMom = sqrt(fEmuPi*fEmuPi-fMnumu*fMnum 304 // muMom = sqrt(fEmuPi*fEmuPi-fMnumu*fMnumu); 279 muMom = sqrt(fEmu*fEmu-fMnumu*fMnumu); 305 muMom = sqrt(fEmu*fEmu-fMnumu*fMnumu); 280 306 281 eP *= muMom; 307 eP *= muMom; 282 308 283 // lv2 = G4LorentzVector( eP, fEmuPi ); 309 // lv2 = G4LorentzVector( eP, fEmuPi ); 284 lv2 = G4LorentzVector( eP, fEmu ); 310 lv2 = G4LorentzVector( eP, fEmu ); 285 lv2 = fLVl; 311 lv2 = fLVl; 286 312 287 lvX = lvsum - lv2; 313 lvX = lvsum - lv2; 288 lvX = fLVh; 314 lvX = fLVh; 289 massX2 = lvX.m2(); 315 massX2 = lvX.m2(); 290 G4double massX = lvX.m(); << 291 G4double massR = fLVt.m(); << 292 316 293 // if ( massX2 <= 0. ) // vmg: very rarely << 317 if ( massX2 <= 0. ) // vmg: very rarely ~ (1-4)e-6 due to big Q2/x, to be improved 294 if ( massX2 <= fM1*fM1 ) // 9-3-20 vmg: ve << 295 if ( lvX.e() <= fM1 ) // 9-3-20 vmg: ver << 296 { 318 { 297 theParticleChange.SetEnergyChange(energy 319 theParticleChange.SetEnergyChange(energy); 298 theParticleChange.SetMomentumChange(aTra 320 theParticleChange.SetMomentumChange(aTrack.Get4Momentum().vect().unit()); 299 return &theParticleChange; 321 return &theParticleChange; 300 } 322 } 301 fW2 = massX2; 323 fW2 = massX2; 302 324 303 if( pName == "nu_mu" ) aLept = ne 325 if( pName == "nu_mu" ) aLept = new G4DynamicParticle( theNuMu, lv2 ); 304 else if( pName == "anti_nu_mu") aLept = ne 326 else if( pName == "anti_nu_mu") aLept = new G4DynamicParticle( theANuMu, lv2 ); 305 else 327 else 306 { 328 { 307 theParticleChange.SetEnergyChange(energy 329 theParticleChange.SetEnergyChange(energy); 308 theParticleChange.SetMomentumChange(aTra 330 theParticleChange.SetMomentumChange(aTrack.Get4Momentum().vect().unit()); 309 return &theParticleChange; 331 return &theParticleChange; 310 } 332 } 311 333 312 pdgP = 111; 334 pdgP = 111; 313 335 314 G4double eCut; // = fMpi + 0.5*(fMpi*fMpi << 336 G4double eCut = fMpi + 0.5*(fMpi*fMpi - massX2)/mTarg; // massX -> fMpi 315 << 316 if( A > 1 ) << 317 { << 318 eCut = (fMpi + mTarg)*(fMpi + mTarg) - ( << 319 eCut /= 2.*massR; << 320 eCut += massX; << 321 } << 322 else eCut = fM1 + fMpi; << 323 337 324 if ( lvX.e() > eCut ) // && sqrt( GetW2() 338 if ( lvX.e() > eCut ) // && sqrt( GetW2() ) < 1.4*GeV ) // 325 { 339 { 326 CoherentPion( lvX, pdgP, targetNucleus); 340 CoherentPion( lvX, pdgP, targetNucleus); 327 } 341 } 328 else 342 else 329 { 343 { 330 theParticleChange.SetEnergyChange(energy 344 theParticleChange.SetEnergyChange(energy); 331 theParticleChange.SetMomentumChange(aTra 345 theParticleChange.SetMomentumChange(aTrack.Get4Momentum().vect().unit()); 332 return &theParticleChange; 346 return &theParticleChange; 333 } 347 } 334 theParticleChange.AddSecondary( aLept, fSe << 348 theParticleChange.AddSecondary( aLept ); 335 349 336 return &theParticleChange; 350 return &theParticleChange; 337 } 351 } 338 else // lepton part in lab 352 else // lepton part in lab 339 { 353 { 340 lvsum = lvp1 + lvt1; 354 lvsum = lvp1 + lvt1; 341 cost = fCosTheta; 355 cost = fCosTheta; 342 sint = std::sqrt( (1.0 - cost)*(1.0 + cost 356 sint = std::sqrt( (1.0 - cost)*(1.0 + cost) ); 343 phi = G4UniformRand()*CLHEP::twopi; 357 phi = G4UniformRand()*CLHEP::twopi; 344 eP = G4ThreeVector( sint*std::cos(phi), 358 eP = G4ThreeVector( sint*std::cos(phi), sint*std::sin(phi), cost ); 345 359 346 muMom = sqrt(fEmu*fEmu-fMnumu*fMnumu); 360 muMom = sqrt(fEmu*fEmu-fMnumu*fMnumu); 347 361 348 eP *= muMom; 362 eP *= muMom; 349 363 350 lv2 = G4LorentzVector( eP, fEmu ); 364 lv2 = G4LorentzVector( eP, fEmu ); 351 365 352 lvX = lvsum - lv2; 366 lvX = lvsum - lv2; 353 367 354 massX2 = lvX.m2(); 368 massX2 = lvX.m2(); 355 369 356 if ( massX2 <= 0. ) // vmg: very rarely ~ 370 if ( massX2 <= 0. ) // vmg: very rarely ~ (1-4)e-6 due to big Q2/x, to be improved 357 { 371 { 358 theParticleChange.SetEnergyChange(energy 372 theParticleChange.SetEnergyChange(energy); 359 theParticleChange.SetMomentumChange(aTra 373 theParticleChange.SetMomentumChange(aTrack.Get4Momentum().vect().unit()); 360 return &theParticleChange; 374 return &theParticleChange; 361 } 375 } 362 fW2 = massX2; 376 fW2 = massX2; 363 377 364 aLept = new G4DynamicParticle( theNuMu, lv << 378 if( pName == "nu_mu" ) aLept = new G4DynamicParticle( theNuMu, lv2 ); 365 << 379 else if( pName == "anti_nu_mu") aLept = new G4DynamicParticle( theANuMu, lv2 ); 366 theParticleChange.AddSecondary( aLept, fSe << 380 >> 381 theParticleChange.AddSecondary( aLept ); 367 } 382 } 368 383 369 // hadron part 384 // hadron part 370 385 371 fRecoil = nullptr; 386 fRecoil = nullptr; 372 fCascade = false; 387 fCascade = false; 373 fString = false; 388 fString = false; 374 389 375 if( A == 1 ) 390 if( A == 1 ) 376 { 391 { 377 qB = 1; 392 qB = 1; 378 393 379 // if( G4UniformRand() > 0.1 ) // > 0.999 394 // if( G4UniformRand() > 0.1 ) // > 0.9999 ) // > 0.0001 ) // 380 { 395 { 381 ClusterDecay( lvX, qB ); 396 ClusterDecay( lvX, qB ); 382 } 397 } 383 return &theParticleChange; 398 return &theParticleChange; 384 } 399 } 385 G4Nucleus recoil; 400 G4Nucleus recoil; 386 G4double rM(0.), ratio = G4double(Z)/G4doubl 401 G4double rM(0.), ratio = G4double(Z)/G4double(A); 387 402 388 if( ratio > G4UniformRand() ) // proton is e 403 if( ratio > G4UniformRand() ) // proton is excited 389 { 404 { 390 fProton = true; 405 fProton = true; 391 recoil = G4Nucleus(A-1,Z-1); 406 recoil = G4Nucleus(A-1,Z-1); 392 fRecoil = &recoil; 407 fRecoil = &recoil; 393 rM = recoil.AtomicMass(A-1,Z-1); 408 rM = recoil.AtomicMass(A-1,Z-1); 394 409 395 fMt = G4ParticleTable::GetParticleTable()- 410 fMt = G4ParticleTable::GetParticleTable()->FindParticle(2212)->GetPDGMass() 396 + G4ParticleTable::GetParticleTable( 411 + G4ParticleTable::GetParticleTable()->FindParticle(111)->GetPDGMass(); 397 } 412 } 398 else // excited neutron 413 else // excited neutron 399 { 414 { 400 fProton = false; 415 fProton = false; 401 recoil = G4Nucleus(A-1,Z); 416 recoil = G4Nucleus(A-1,Z); 402 fRecoil = &recoil; 417 fRecoil = &recoil; 403 rM = recoil.AtomicMass(A-1,Z); 418 rM = recoil.AtomicMass(A-1,Z); 404 419 405 fMt = G4ParticleTable::GetParticleTable()- 420 fMt = G4ParticleTable::GetParticleTable()->FindParticle(2112)->GetPDGMass() 406 + G4ParticleTable::GetParticleTable( 421 + G4ParticleTable::GetParticleTable()->FindParticle(111)->GetPDGMass(); 407 } 422 } 408 // G4int index = GetEnergyIndex(energy << 423 G4int index = GetEnergyIndex(energy); 409 G4int nepdg = aParticle->GetDefinition()->Ge << 424 G4double qeTotRat = GetNuMuQeTotRat(index, energy); 410 << 411 G4double qeTotRat; // = GetNuMuQeTotRat(ind << 412 qeTotRat = CalculateQEratioA( Z, A, energy, << 413 425 414 G4ThreeVector dX = (lvX.vect()).unit(); 426 G4ThreeVector dX = (lvX.vect()).unit(); 415 G4double eX = lvX.e(); // excited nucleon 427 G4double eX = lvX.e(); // excited nucleon 416 G4double mX = sqrt(massX2); 428 G4double mX = sqrt(massX2); >> 429 G4double dP(0.), pX = sqrt( eX*eX - mX*mX ); >> 430 G4double sumE = eX + rM; >> 431 G4double a(0.), b(0.), c(0.), B(0.); 417 432 418 if( qeTotRat > G4UniformRand() || mX <= fMt 433 if( qeTotRat > G4UniformRand() || mX <= fMt ) // || eX <= 1232.*MeV) // QE 419 { 434 { 420 fString = false; 435 fString = false; 421 436 422 if( fProton ) << 437 if( fProton ) // pName == "nu_mu" ) 423 { 438 { 424 fPDGencoding = 2212; 439 fPDGencoding = 2212; 425 fMr = proton_mass_c2; 440 fMr = proton_mass_c2; 426 recoil = G4Nucleus(A-1,Z-1); 441 recoil = G4Nucleus(A-1,Z-1); 427 fRecoil = &recoil; 442 fRecoil = &recoil; 428 rM = recoil.AtomicMass(A-1,Z-1); 443 rM = recoil.AtomicMass(A-1,Z-1); 429 } 444 } 430 else << 445 else // if( pName == "anti_nu_mu" ) 431 { 446 { 432 fPDGencoding = 2112; 447 fPDGencoding = 2112; 433 fMr = G4ParticleTable::GetParticleTabl 448 fMr = G4ParticleTable::GetParticleTable()-> 434 FindParticle(fPDGencoding)->GetPDGMass(); // 449 FindParticle(fPDGencoding)->GetPDGMass(); // 939.5654133*MeV; 435 recoil = G4Nucleus(A-1,Z); 450 recoil = G4Nucleus(A-1,Z); 436 fRecoil = &recoil; 451 fRecoil = &recoil; 437 rM = recoil.AtomicMass(A-1,Z); 452 rM = recoil.AtomicMass(A-1,Z); 438 } 453 } >> 454 sumE = eX + rM; 439 G4double eTh = fMr+0.5*(fMr*fMr-mX*mX)/rM; 455 G4double eTh = fMr+0.5*(fMr*fMr-mX*mX)/rM; 440 456 441 if(eX <= eTh) // vmg, very rarely out of k 457 if(eX <= eTh) // vmg, very rarely out of kinematics 442 { 458 { 443 theParticleChange.SetEnergyChange(energy 459 theParticleChange.SetEnergyChange(energy); 444 theParticleChange.SetMomentumChange(aTra 460 theParticleChange.SetMomentumChange(aTrack.Get4Momentum().vect().unit()); 445 return &theParticleChange; 461 return &theParticleChange; 446 } 462 } 447 FinalBarion( lvX, 0, fPDGencoding ); // p( << 463 B = sumE*sumE + rM*rM - fMr*fMr - pX*pX; >> 464 a = 4.*(sumE*sumE - pX*pX); >> 465 b = -4.*B*pX; >> 466 c = 4.*sumE*sumE*rM*rM - B*B; >> 467 G4double det2 = b*b-4.*a*c; >> 468 if( det2 < 0.) det2 = 0.; >> 469 dP = 0.5*(-b - sqrt(det2) )/a; >> 470 pX -= dP; >> 471 eX = sqrt( pX*pX + fMr*fMr ); >> 472 G4LorentzVector qeLV( pX*dX, eX ); >> 473 >> 474 G4ParticleDefinition* qePart = G4ParticleTable::GetParticleTable()-> >> 475 FindParticle(fPDGencoding); >> 476 >> 477 G4DynamicParticle* qeDyn = new G4DynamicParticle( qePart, qeLV); >> 478 theParticleChange.AddSecondary(qeDyn); >> 479 >> 480 G4double eRecoil = sqrt(rM*rM + dP*dP); >> 481 G4ThreeVector vRecoil(dP*dX); >> 482 G4LorentzVector lvTarg(vRecoil, eRecoil); >> 483 >> 484 if( eRecoil > 100.*MeV ) // add recoil nucleus >> 485 { >> 486 G4ParticleDefinition * recoilDef = 0; >> 487 G4int Zr = recoil.GetZ_asInt(); >> 488 G4int Ar = recoil.GetA_asInt(); >> 489 >> 490 if ( Zr == 1 && Ar == 1 ) { recoilDef = G4Proton::Proton(); } >> 491 else if ( Zr == 0 && Ar == 1 ) { recoilDef = G4Neutron::Neutron(); } >> 492 else if ( Zr == 1 && Ar == 2 ) { recoilDef = G4Deuteron::Deuteron(); } >> 493 else if ( Zr == 1 && Ar == 3 ) { recoilDef = G4Triton::Triton(); } >> 494 else if ( Zr == 2 && Ar == 3 ) { recoilDef = G4He3::He3(); } >> 495 else if ( Zr == 2 && Ar == 4 ) { recoilDef = G4Alpha::Alpha(); } >> 496 else >> 497 { >> 498 recoilDef = >> 499 G4ParticleTable::GetParticleTable()->GetIonTable()->GetIon( Zr, Ar, 0.0 ); >> 500 } >> 501 G4DynamicParticle * aSec = new G4DynamicParticle( recoilDef, lvTarg); >> 502 theParticleChange.AddSecondary(aSec); >> 503 } >> 504 else if( eRecoil > 0.0 ) >> 505 { >> 506 theParticleChange.SetLocalEnergyDeposit( eRecoil ); >> 507 } 448 } 508 } 449 else // if ( eX < 9500000.*GeV ) // < 25.*Ge << 509 else if ( eX < 95000.*GeV ) // < 25.*GeV) // < 95.*GeV ) // < 2.5*GeV ) //cluster decay 450 { 510 { 451 if ( fProton && pName == "nu_mu" ) 511 if ( fProton && pName == "nu_mu" ) qB = 1; >> 512 else if( fProton && pName == "anti_nu_mu" ) qB = 1; 452 else if( !fProton && pName == "nu_mu" ) 513 else if( !fProton && pName == "nu_mu" ) qB = 0; >> 514 else if( !fProton && pName == "anti_nu_mu" ) qB = 0; 453 515 454 ClusterDecay( lvX, qB ); << 516 // if( G4UniformRand() > 0.1 ) >> 517 { >> 518 ClusterDecay( lvX, qB ); >> 519 } >> 520 // else >> 521 { >> 522 pdgP = 111; >> 523 >> 524 if ( fQtransfer < 0.95*GeV ) // < 0.99*GeV ) // >> 525 { >> 526 // if( lvX.m() > mSum ) CoherentPion( lvX, pdgP, targetNucleus); >> 527 } >> 528 } 455 } 529 } >> 530 else // string >> 531 { >> 532 return &theParticleChange; >> 533 >> 534 } 456 return &theParticleChange; 535 return &theParticleChange; 457 } 536 } 458 537 459 538 460 ////////////////////////////////////////////// 539 ///////////////////////////////////////////////////////////////////// 461 ////////////////////////////////////////////// 540 //////////////////////////////////////////////////////////////////// 462 ////////////////////////////////////////////// 541 /////////////////////////////////////////////////////////////////// 463 542 464 ////////////////////////////////////////////// 543 ///////////////////////////////////////////////// 465 // 544 // 466 // sample x, then Q2 545 // sample x, then Q2 467 546 468 void G4NuMuNucleusNcModel::SampleLVkr(const G4 547 void G4NuMuNucleusNcModel::SampleLVkr(const G4HadProjectile & aTrack, G4Nucleus& targetNucleus) 469 { 548 { 470 fBreak = false; 549 fBreak = false; 471 G4int A = targetNucleus.GetA_asInt(), iTer(0 550 G4int A = targetNucleus.GetA_asInt(), iTer(0), iTerMax(100); 472 G4int Z = targetNucleus.GetZ_asInt(); 551 G4int Z = targetNucleus.GetZ_asInt(); 473 G4double e3(0.), pMu2(0.), pX2(0.), nMom(0.) 552 G4double e3(0.), pMu2(0.), pX2(0.), nMom(0.), rM(0.), hM(0.), tM = targetNucleus.AtomicMass(A,Z); 474 G4double cost(1.), sint(0.), phi(0.), muMom( 553 G4double cost(1.), sint(0.), phi(0.), muMom(0.); 475 G4ThreeVector eP, bst; 554 G4ThreeVector eP, bst; 476 const G4HadProjectile* aParticle = &aTrack; 555 const G4HadProjectile* aParticle = &aTrack; 477 G4LorentzVector lvp1 = aParticle->Get4Moment 556 G4LorentzVector lvp1 = aParticle->Get4Momentum(); 478 nMom = NucleonMomentum( targetNucleus ); 557 nMom = NucleonMomentum( targetNucleus ); 479 558 480 if( A == 1 || nMom == 0. ) // hydrogen, no F 559 if( A == 1 || nMom == 0. ) // hydrogen, no Fermi motion ??? 481 { 560 { 482 fNuEnergy = aParticle->GetTotalEnergy(); 561 fNuEnergy = aParticle->GetTotalEnergy(); 483 iTer = 0; 562 iTer = 0; 484 563 485 do 564 do 486 { 565 { 487 fXsample = SampleXkr(fNuEnergy); 566 fXsample = SampleXkr(fNuEnergy); 488 fQtransfer = SampleQkr(fNuEnergy, fXsamp 567 fQtransfer = SampleQkr(fNuEnergy, fXsample); 489 fQ2 = fQtransfer*fQtransfer; 568 fQ2 = fQtransfer*fQtransfer; 490 569 491 if( fXsample > 0. ) 570 if( fXsample > 0. ) 492 { 571 { 493 fW2 = fM1*fM1 - fQ2 + fQ2/fXsample; // 572 fW2 = fM1*fM1 - fQ2 + fQ2/fXsample; // sample excited hadron mass 494 fEmu = fNuEnergy - fQ2/2./fM1/fXsample 573 fEmu = fNuEnergy - fQ2/2./fM1/fXsample; 495 } 574 } 496 else 575 else 497 { 576 { 498 fW2 = fM1*fM1; 577 fW2 = fM1*fM1; 499 fEmu = fNuEnergy; 578 fEmu = fNuEnergy; 500 } 579 } 501 e3 = fNuEnergy + fM1 - fEmu; 580 e3 = fNuEnergy + fM1 - fEmu; 502 581 503 // if( e3 < sqrt(fW2) ) G4cout<<"energy 582 // if( e3 < sqrt(fW2) ) G4cout<<"energyX = "<<e3/GeV<<", fW = "<<sqrt(fW2)/GeV<<G4endl; // vmg ~10^-5 for NC 504 583 505 pMu2 = fEmu*fEmu - fMnumu*fMnumu; 584 pMu2 = fEmu*fEmu - fMnumu*fMnumu; 506 pX2 = e3*e3 - fW2; 585 pX2 = e3*e3 - fW2; 507 586 508 fCosTheta = fNuEnergy*fNuEnergy + pMu2 587 fCosTheta = fNuEnergy*fNuEnergy + pMu2 - pX2; 509 fCosTheta /= 2.*fNuEnergy*sqrt(pMu2); 588 fCosTheta /= 2.*fNuEnergy*sqrt(pMu2); 510 iTer++; 589 iTer++; 511 } 590 } 512 while( ( abs(fCosTheta) > 1. || fEmu < fMn 591 while( ( abs(fCosTheta) > 1. || fEmu < fMnumu ) && iTer < iTerMax ); 513 592 514 if( iTer >= iTerMax ) { fBreak = true; ret 593 if( iTer >= iTerMax ) { fBreak = true; return; } 515 594 516 if( abs(fCosTheta) > 1.) // vmg: due to bi 595 if( abs(fCosTheta) > 1.) // vmg: due to big Q2/x values. To be improved ... 517 { 596 { 518 G4cout<<"H2: fCosTheta = "<<fCosTheta<<" 597 G4cout<<"H2: fCosTheta = "<<fCosTheta<<", fEmu = "<<fEmu<<G4endl; 519 // fCosTheta = -1. + 2.*G4UniformRand(); 598 // fCosTheta = -1. + 2.*G4UniformRand(); 520 if(fCosTheta < -1.) fCosTheta = -1.; 599 if(fCosTheta < -1.) fCosTheta = -1.; 521 if(fCosTheta > 1.) fCosTheta = 1.; 600 if(fCosTheta > 1.) fCosTheta = 1.; 522 } 601 } 523 // LVs 602 // LVs 524 603 525 G4LorentzVector lvt1 = G4LorentzVector( 0 604 G4LorentzVector lvt1 = G4LorentzVector( 0., 0., 0., fM1 ); 526 G4LorentzVector lvsum = lvp1 + lvt1; 605 G4LorentzVector lvsum = lvp1 + lvt1; 527 606 528 cost = fCosTheta; 607 cost = fCosTheta; 529 sint = std::sqrt( (1.0 - cost)*(1.0 + cost 608 sint = std::sqrt( (1.0 - cost)*(1.0 + cost) ); 530 phi = G4UniformRand()*CLHEP::twopi; 609 phi = G4UniformRand()*CLHEP::twopi; 531 eP = G4ThreeVector( sint*std::cos(phi), 610 eP = G4ThreeVector( sint*std::cos(phi), sint*std::sin(phi), cost ); 532 muMom = sqrt(fEmu*fEmu-fMnumu*fMnumu); 611 muMom = sqrt(fEmu*fEmu-fMnumu*fMnumu); 533 eP *= muMom; 612 eP *= muMom; 534 fLVl = G4LorentzVector( eP, fEmu ); 613 fLVl = G4LorentzVector( eP, fEmu ); 535 614 536 fLVh = lvsum - fLVl; 615 fLVh = lvsum - fLVl; 537 fLVt = G4LorentzVector( 0., 0., 0., 0. ); 616 fLVt = G4LorentzVector( 0., 0., 0., 0. ); // no recoil 538 } 617 } 539 else // Fermi motion, Q2 in nucleon rest fra 618 else // Fermi motion, Q2 in nucleon rest frame 540 { 619 { 541 G4ThreeVector nMomDir = nMom*G4RandomDirec 620 G4ThreeVector nMomDir = nMom*G4RandomDirection(); 542 621 543 if( !f2p2h ) // 1p1h 622 if( !f2p2h ) // 1p1h 544 { 623 { 545 G4Nucleus recoil(A-1,Z); 624 G4Nucleus recoil(A-1,Z); 546 rM = sqrt( recoil.AtomicMass(A-1,Z)*reco 625 rM = sqrt( recoil.AtomicMass(A-1,Z)*recoil.AtomicMass(A-1,Z) + nMom*nMom ); 547 hM = tM - rM; 626 hM = tM - rM; 548 627 549 fLVt = G4LorentzVector( nMomDir, sqrt( r 628 fLVt = G4LorentzVector( nMomDir, sqrt( rM*rM+nMom*nMom ) ); 550 fLVh = G4LorentzVector(-nMomDir, sqrt( h 629 fLVh = G4LorentzVector(-nMomDir, sqrt( hM*hM+nMom*nMom ) ); 551 } 630 } 552 else // 2p2h 631 else // 2p2h 553 { 632 { 554 G4Nucleus recoil(A-2,Z-1); 633 G4Nucleus recoil(A-2,Z-1); 555 rM = recoil.AtomicMass(A-2,Z-1)+sqrt(nMo 634 rM = recoil.AtomicMass(A-2,Z-1)+sqrt(nMom*nMom+fM1*fM1); 556 hM = tM - rM; 635 hM = tM - rM; 557 636 558 fLVt = G4LorentzVector( nMomDir, sqrt( r 637 fLVt = G4LorentzVector( nMomDir, sqrt( rM*rM+nMom*nMom ) ); 559 fLVh = G4LorentzVector(-nMomDir, sqrt( h 638 fLVh = G4LorentzVector(-nMomDir, sqrt( hM*hM+nMom*nMom ) ); 560 } 639 } 561 // G4cout<<hM<<", "; 640 // G4cout<<hM<<", "; 562 // bst = fLVh.boostVector(); // 9-3-20 << 641 bst = fLVh.boostVector(); 563 642 564 // lvp1.boost(-bst); // 9-3-20 -> nucleon << 643 lvp1.boost(-bst); // -> nucleon rest system, where Q2 transfer is ??? 565 644 566 fNuEnergy = lvp1.e(); 645 fNuEnergy = lvp1.e(); 567 iTer = 0; 646 iTer = 0; 568 647 569 do 648 do 570 { 649 { 571 fXsample = SampleXkr(fNuEnergy); 650 fXsample = SampleXkr(fNuEnergy); 572 fQtransfer = SampleQkr(fNuEnergy, fXsamp 651 fQtransfer = SampleQkr(fNuEnergy, fXsample); 573 fQ2 = fQtransfer*fQtransfer; 652 fQ2 = fQtransfer*fQtransfer; 574 653 575 if( fXsample > 0. ) 654 if( fXsample > 0. ) 576 { 655 { 577 fW2 = fM1*fM1 - fQ2 + fQ2/fXsample; // 656 fW2 = fM1*fM1 - fQ2 + fQ2/fXsample; // sample excited hadron mass 578 fEmu = fNuEnergy - fQ2/2./fM1/fXsample 657 fEmu = fNuEnergy - fQ2/2./fM1/fXsample; 579 } 658 } 580 else 659 else 581 { 660 { 582 fW2 = fM1*fM1; 661 fW2 = fM1*fM1; 583 fEmu = fNuEnergy; 662 fEmu = fNuEnergy; 584 } 663 } 585 664 586 // if(fEmu < 0.) G4cout<<"fEmu = "<<fEmu 665 // if(fEmu < 0.) G4cout<<"fEmu = "<<fEmu<<" hM = "<<hM<<G4endl; 587 666 588 e3 = fNuEnergy + fM1 - fEmu; 667 e3 = fNuEnergy + fM1 - fEmu; 589 668 590 // if( e3 < sqrt(fW2) ) G4cout<<"energy 669 // if( e3 < sqrt(fW2) ) G4cout<<"energyX = "<<e3/GeV<<", fW = "<<sqrt(fW2)/GeV<<G4endl; 591 670 592 pMu2 = fEmu*fEmu - fMnumu*fMnumu; 671 pMu2 = fEmu*fEmu - fMnumu*fMnumu; 593 pX2 = e3*e3 - fW2; 672 pX2 = e3*e3 - fW2; 594 673 595 fCosTheta = fNuEnergy*fNuEnergy + pMu2 674 fCosTheta = fNuEnergy*fNuEnergy + pMu2 - pX2; 596 fCosTheta /= 2.*fNuEnergy*sqrt(pMu2); 675 fCosTheta /= 2.*fNuEnergy*sqrt(pMu2); 597 iTer++; 676 iTer++; 598 } 677 } 599 while( ( abs(fCosTheta) > 1. || fEmu < fMn 678 while( ( abs(fCosTheta) > 1. || fEmu < fMnumu ) && iTer < iTerMax ); 600 679 601 if( iTer >= iTerMax ) { fBreak = true; ret 680 if( iTer >= iTerMax ) { fBreak = true; return; } 602 681 603 if( abs(fCosTheta) > 1.) // vmg: due to bi 682 if( abs(fCosTheta) > 1.) // vmg: due to big Q2/x values. To be improved ... 604 { 683 { 605 G4cout<<"FM: fCosTheta = "<<fCosTheta<<" 684 G4cout<<"FM: fCosTheta = "<<fCosTheta<<", fEmu = "<<fEmu<<G4endl; 606 // fCosTheta = -1. + 2.*G4UniformRand(); 685 // fCosTheta = -1. + 2.*G4UniformRand(); 607 if(fCosTheta < -1.) fCosTheta = -1.; 686 if(fCosTheta < -1.) fCosTheta = -1.; 608 if(fCosTheta > 1.) fCosTheta = 1.; 687 if(fCosTheta > 1.) fCosTheta = 1.; 609 } 688 } 610 // LVs 689 // LVs 611 G4LorentzVector lvt1 = G4LorentzVector( 0 690 G4LorentzVector lvt1 = G4LorentzVector( 0., 0., 0., fM1 ); 612 G4LorentzVector lvsum = lvp1 + lvt1; 691 G4LorentzVector lvsum = lvp1 + lvt1; 613 692 614 cost = fCosTheta; 693 cost = fCosTheta; 615 sint = std::sqrt( (1.0 - cost)*(1.0 + cost 694 sint = std::sqrt( (1.0 - cost)*(1.0 + cost) ); 616 phi = G4UniformRand()*CLHEP::twopi; 695 phi = G4UniformRand()*CLHEP::twopi; 617 eP = G4ThreeVector( sint*std::cos(phi), 696 eP = G4ThreeVector( sint*std::cos(phi), sint*std::sin(phi), cost ); 618 muMom = sqrt(fEmu*fEmu-fMnumu*fMnumu); 697 muMom = sqrt(fEmu*fEmu-fMnumu*fMnumu); 619 eP *= muMom; 698 eP *= muMom; 620 fLVl = G4LorentzVector( eP, fEmu ); 699 fLVl = G4LorentzVector( eP, fEmu ); 621 fLVh = lvsum - fLVl; 700 fLVh = lvsum - fLVl; 622 // back to lab system 701 // back to lab system 623 // fLVl.boost(bst); // 9-3-20 << 702 fLVl.boost(bst); 624 // fLVh.boost(bst); // 9-3-20 << 703 fLVh.boost(bst); 625 } 704 } 626 //G4cout<<iTer<<", "<<fBreak<<"; "; 705 //G4cout<<iTer<<", "<<fBreak<<"; "; >> 706 } >> 707 >> 708 ////////////////////////////////////// >> 709 >> 710 G4double G4NuMuNucleusNcModel::SampleXkr(G4double energy) >> 711 { >> 712 G4int i(0), nBin(50); >> 713 G4double xx(0.), prob = G4UniformRand(); >> 714 >> 715 for( i = 0; i < nBin; ++i ) >> 716 { >> 717 if( energy <= fNuMuEnergyLogVector[i] ) break; >> 718 } >> 719 if( i <= 0) // E-edge >> 720 { >> 721 fEindex = 0; >> 722 xx = GetXkr( 0, prob); >> 723 } >> 724 else if ( i >= nBin-1) >> 725 { >> 726 fEindex = nBin-1; >> 727 xx = GetXkr( nBin-1, prob); >> 728 } >> 729 else >> 730 { >> 731 fEindex = i; >> 732 G4double x1 = GetXkr(i-1,prob); >> 733 G4double x2 = GetXkr(i,prob); >> 734 >> 735 G4double e1 = G4Log(fNuMuEnergyLogVector[i-1]); >> 736 G4double e2 = G4Log(fNuMuEnergyLogVector[i]); >> 737 G4double e = G4Log(energy); >> 738 >> 739 if( e2 <= e1) xx = x1 + G4UniformRand()*(x2-x1); >> 740 else xx = x1 + (e-e1)*(x2-x1)/(e2-e1); // lin in energy log-scale >> 741 } >> 742 return xx; >> 743 } >> 744 >> 745 ////////////////////////////////////////////// >> 746 // >> 747 // sample X according to prob (xmin,1) at a given energy index iEnergy >> 748 >> 749 G4double G4NuMuNucleusNcModel::GetXkr(G4int iEnergy, G4double prob) >> 750 { >> 751 G4int i(0), nBin=50; >> 752 G4double xx(0.); >> 753 >> 754 for( i = 0; i < nBin; ++i ) >> 755 { >> 756 if( prob <= fNuMuXdistrKR[iEnergy][i] ) >> 757 break; >> 758 } >> 759 if(i <= 0 ) // X-edge >> 760 { >> 761 fXindex = 0; >> 762 xx = fNuMuXarrayKR[iEnergy][0]; >> 763 } >> 764 if ( i >= nBin ) >> 765 { >> 766 fXindex = nBin; >> 767 xx = fNuMuXarrayKR[iEnergy][nBin]; >> 768 } >> 769 else >> 770 { >> 771 fXindex = i; >> 772 G4double x1 = fNuMuXarrayKR[iEnergy][i]; >> 773 G4double x2 = fNuMuXarrayKR[iEnergy][i+1]; >> 774 >> 775 G4double p1 = 0.; >> 776 >> 777 if( i > 0 ) p1 = fNuMuXdistrKR[iEnergy][i-1]; >> 778 >> 779 G4double p2 = fNuMuXdistrKR[iEnergy][i]; >> 780 >> 781 if( p2 <= p1 ) xx = x1 + G4UniformRand()*(x2-x1); >> 782 else xx = x1 + (prob-p1)*(x2-x1)/(p2-p1); >> 783 } >> 784 return xx; >> 785 } >> 786 >> 787 ////////////////////////////////////// >> 788 // >> 789 // Sample fQtransfer at a given Enu and fX >> 790 >> 791 G4double G4NuMuNucleusNcModel::SampleQkr( G4double energy, G4double xx) >> 792 { >> 793 G4int nBin(50), iE=fEindex, jX=fXindex; >> 794 G4double qq(0.), qq1(0.), qq2(0.); >> 795 G4double prob = G4UniformRand(); >> 796 >> 797 // first E >> 798 >> 799 if( iE <= 0 ) >> 800 { >> 801 qq1 = GetQkr( 0, jX, prob); >> 802 } >> 803 else if ( iE >= nBin-1) >> 804 { >> 805 qq1 = GetQkr( nBin-1, jX, prob); >> 806 } >> 807 else >> 808 { >> 809 G4double q1 = GetQkr(iE-1,jX, prob); >> 810 G4double q2 = GetQkr(iE,jX, prob); >> 811 >> 812 G4double e1 = G4Log(fNuMuEnergyLogVector[iE-1]); >> 813 G4double e2 = G4Log(fNuMuEnergyLogVector[iE]); >> 814 G4double e = G4Log(energy); >> 815 >> 816 if( e2 <= e1) qq1 = q1 + G4UniformRand()*(q2-q1); >> 817 else qq1 = q1 + (e-e1)*(q2-q1)/(e2-e1); // lin in energy log-scale >> 818 } >> 819 >> 820 // then X >> 821 >> 822 if( jX <= 0 ) >> 823 { >> 824 qq2 = GetQkr( iE, 0, prob); >> 825 } >> 826 else if ( jX >= nBin) >> 827 { >> 828 qq2 = GetQkr( iE, nBin, prob); >> 829 } >> 830 else >> 831 { >> 832 G4double q1 = GetQkr(iE,jX-1, prob); >> 833 G4double q2 = GetQkr(iE,jX, prob); >> 834 >> 835 G4double e1 = G4Log(fNuMuXarrayKR[iE][jX-1]); >> 836 G4double e2 = G4Log(fNuMuXarrayKR[iE][jX]); >> 837 G4double e = G4Log(xx); >> 838 >> 839 if( e2 <= e1) qq2 = q1 + G4UniformRand()*(q2-q1); >> 840 else qq2 = q1 + (e-e1)*(q2-q1)/(e2-e1); // lin in energy log-scale >> 841 } >> 842 qq = 0.5*(qq1+qq2); >> 843 >> 844 return qq; >> 845 } >> 846 >> 847 ////////////////////////////////////////////// >> 848 // >> 849 // sample Q according to prob (qmin,qmax) at a given energy index iE and X index jX >> 850 >> 851 G4double G4NuMuNucleusNcModel::GetQkr( G4int iE, G4int jX, G4double prob ) >> 852 { >> 853 G4int i(0), nBin=50; >> 854 G4double qq(0.); >> 855 >> 856 for( i = 0; i < nBin; ++i ) >> 857 { >> 858 if( prob <= fNuMuQdistrKR[iE][jX][i] ) >> 859 break; >> 860 } >> 861 if(i <= 0 ) // Q-edge >> 862 { >> 863 fQindex = 0; >> 864 qq = fNuMuQarrayKR[iE][jX][0]; >> 865 } >> 866 if ( i >= nBin ) >> 867 { >> 868 fQindex = nBin; >> 869 qq = fNuMuQarrayKR[iE][jX][nBin]; >> 870 } >> 871 else >> 872 { >> 873 fQindex = i; >> 874 G4double q1 = fNuMuQarrayKR[iE][jX][i]; >> 875 G4double q2 = fNuMuQarrayKR[iE][jX][i+1]; >> 876 >> 877 G4double p1 = 0.; >> 878 >> 879 if( i > 0 ) p1 = fNuMuQdistrKR[iE][jX][i-1]; >> 880 >> 881 G4double p2 = fNuMuQdistrKR[iE][jX][i]; >> 882 >> 883 if( p2 <= p1 ) qq = q1 + G4UniformRand()*(q2-q1); >> 884 else qq = q1 + (prob-p1)*(q2-q1)/(p2-p1); >> 885 } >> 886 return qq; 627 } 887 } 628 888 629 // 889 // 630 // 890 // 631 /////////////////////////// 891 /////////////////////////// 632 892