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: G4NuElNucleusNcModel.cc 91806 2015-08- 26 // $Id: G4NuElNucleusNcModel.cc 91806 2015-08-06 12:20:45Z gcosmo $ 27 // 27 // 28 // Geant4 Header : G4NuElNucleusNcModel 28 // Geant4 Header : G4NuElNucleusNcModel 29 // 29 // 30 // Author : V.Grichine 12.2.19 30 // Author : V.Grichine 12.2.19 31 // 31 // 32 32 33 #include "G4NuElNucleusNcModel.hh" 33 #include "G4NuElNucleusNcModel.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 "G4NeutrinoE.hh" 55 #include "G4NeutrinoE.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 #ifdef G4MULTITHREADED 63 #ifdef G4MULTITHREADED 64 G4Mutex G4NuElNucleusNcModel::numuNucleusM 64 G4Mutex G4NuElNucleusNcModel::numuNucleusModel = G4MUTEX_INITIALIZER; 65 #endif 65 #endif 66 66 67 67 68 G4NuElNucleusNcModel::G4NuElNucleusNcModel(con 68 G4NuElNucleusNcModel::G4NuElNucleusNcModel(const G4String& name) 69 : G4NeutrinoNucleusModel(name) 69 : G4NeutrinoNucleusModel(name) 70 { 70 { 71 SetMinEnergy( 0.0*GeV ); 71 SetMinEnergy( 0.0*GeV ); 72 SetMaxEnergy( 100.*TeV ); 72 SetMaxEnergy( 100.*TeV ); 73 SetMinEnergy(1.e-6*eV); 73 SetMinEnergy(1.e-6*eV); 74 74 75 theNuE = G4NeutrinoE::NeutrinoE(); 75 theNuE = G4NeutrinoE::NeutrinoE(); 76 76 77 fMnumu = 0.; 77 fMnumu = 0.; 78 fData = fMaster = false; 78 fData = fMaster = false; 79 InitialiseModel(); 79 InitialiseModel(); 80 80 81 } 81 } 82 82 83 83 84 G4NuElNucleusNcModel::~G4NuElNucleusNcModel() 84 G4NuElNucleusNcModel::~G4NuElNucleusNcModel() 85 {} 85 {} 86 86 87 87 88 void G4NuElNucleusNcModel::ModelDescription(st 88 void G4NuElNucleusNcModel::ModelDescription(std::ostream& outFile) const 89 { 89 { 90 90 91 outFile << "G4NuElNucleusNcModel is a neut 91 outFile << "G4NuElNucleusNcModel is a neutrino-nucleus (neutral current) scattering\n" 92 << "model which uses the standard 92 << "model which uses the standard model \n" 93 << "transfer parameterization. Th 93 << "transfer parameterization. The model is fully relativistic\n"; 94 94 95 } 95 } 96 96 97 ////////////////////////////////////////////// 97 ///////////////////////////////////////////////////////// 98 // 98 // 99 // Read data from G4PARTICLEXSDATA (locally PA 99 // Read data from G4PARTICLEXSDATA (locally PARTICLEXSDATA) 100 100 101 void G4NuElNucleusNcModel::InitialiseModel() 101 void G4NuElNucleusNcModel::InitialiseModel() 102 { 102 { 103 G4String pName = "nu_e"; 103 G4String pName = "nu_e"; 104 104 105 G4int nSize(0), i(0), j(0), k(0); 105 G4int nSize(0), i(0), j(0), k(0); 106 106 107 if(!fData) 107 if(!fData) 108 { 108 { 109 #ifdef G4MULTITHREADED 109 #ifdef G4MULTITHREADED 110 G4MUTEXLOCK(&numuNucleusModel); 110 G4MUTEXLOCK(&numuNucleusModel); 111 if(!fData) 111 if(!fData) 112 { 112 { 113 #endif 113 #endif 114 fMaster = true; 114 fMaster = true; 115 #ifdef G4MULTITHREADED 115 #ifdef G4MULTITHREADED 116 } 116 } 117 G4MUTEXUNLOCK(&numuNucleusModel); 117 G4MUTEXUNLOCK(&numuNucleusModel); 118 #endif 118 #endif 119 } 119 } 120 120 121 if(fMaster) 121 if(fMaster) 122 { 122 { 123 const char* path = G4FindDataDir("G4PARTIC 123 const char* path = G4FindDataDir("G4PARTICLEXSDATA"); 124 std::ostringstream ost1, ost2, ost3, ost4; 124 std::ostringstream ost1, ost2, ost3, ost4; 125 ost1 << path << "/" << "neutrino" << "/" < 125 ost1 << path << "/" << "neutrino" << "/" << pName << "/xarraynckr"; 126 126 127 std::ifstream filein1( ost1.str().c_str() 127 std::ifstream filein1( ost1.str().c_str() ); 128 128 129 // filein.open("$PARTICLEXSDATA/"); 129 // filein.open("$PARTICLEXSDATA/"); 130 130 131 filein1>>nSize; 131 filein1>>nSize; 132 132 133 for( k = 0; k < fNbin; ++k ) 133 for( k = 0; k < fNbin; ++k ) 134 { 134 { 135 for( i = 0; i <= fNbin; ++i ) 135 for( i = 0; i <= fNbin; ++i ) 136 { 136 { 137 filein1 >> fNuMuXarrayKR[k][i]; 137 filein1 >> fNuMuXarrayKR[k][i]; 138 // G4cout<< fNuMuXarrayKR[k][i] << " 138 // G4cout<< fNuMuXarrayKR[k][i] << " "; 139 } 139 } 140 } 140 } 141 // G4cout<<G4endl<<G4endl; 141 // G4cout<<G4endl<<G4endl; 142 142 143 ost2 << path << "/" << "neutrino" << "/" < 143 ost2 << path << "/" << "neutrino" << "/" << pName << "/xdistrnckr"; 144 std::ifstream filein2( ost2.str().c_str() 144 std::ifstream filein2( ost2.str().c_str() ); 145 145 146 filein2>>nSize; 146 filein2>>nSize; 147 147 148 for( k = 0; k < fNbin; ++k ) 148 for( k = 0; k < fNbin; ++k ) 149 { 149 { 150 for( i = 0; i < fNbin; ++i ) 150 for( i = 0; i < fNbin; ++i ) 151 { 151 { 152 filein2 >> fNuMuXdistrKR[k][i]; 152 filein2 >> fNuMuXdistrKR[k][i]; 153 // G4cout<< fNuMuXdistrKR[k][i] << " 153 // G4cout<< fNuMuXdistrKR[k][i] << " "; 154 } 154 } 155 } 155 } 156 // G4cout<<G4endl<<G4endl; 156 // G4cout<<G4endl<<G4endl; 157 157 158 ost3 << path << "/" << "neutrino" << "/" < 158 ost3 << path << "/" << "neutrino" << "/" << pName << "/q2arraynckr"; 159 std::ifstream filein3( ost3.str().c_str() 159 std::ifstream filein3( ost3.str().c_str() ); 160 160 161 filein3>>nSize; 161 filein3>>nSize; 162 162 163 for( k = 0; k < fNbin; ++k ) 163 for( k = 0; k < fNbin; ++k ) 164 { 164 { 165 for( i = 0; i <= fNbin; ++i ) 165 for( i = 0; i <= fNbin; ++i ) 166 { 166 { 167 for( j = 0; j <= fNbin; ++j ) 167 for( j = 0; j <= fNbin; ++j ) 168 { 168 { 169 filein3 >> fNuMuQarrayKR[k][i][j]; 169 filein3 >> fNuMuQarrayKR[k][i][j]; 170 // G4cout<< fNuMuQarrayKR[k][i][j] < 170 // G4cout<< fNuMuQarrayKR[k][i][j] << " "; 171 } 171 } 172 } 172 } 173 } 173 } 174 // G4cout<<G4endl<<G4endl; 174 // G4cout<<G4endl<<G4endl; 175 175 176 ost4 << path << "/" << "neutrino" << "/" < 176 ost4 << path << "/" << "neutrino" << "/" << pName << "/q2distrnckr"; 177 std::ifstream filein4( ost4.str().c_str() 177 std::ifstream filein4( ost4.str().c_str() ); 178 178 179 filein4>>nSize; 179 filein4>>nSize; 180 180 181 for( k = 0; k < fNbin; ++k ) 181 for( k = 0; k < fNbin; ++k ) 182 { 182 { 183 for( i = 0; i <= fNbin; ++i ) 183 for( i = 0; i <= fNbin; ++i ) 184 { 184 { 185 for( j = 0; j < fNbin; ++j ) 185 for( j = 0; j < fNbin; ++j ) 186 { 186 { 187 filein4 >> fNuMuQdistrKR[k][i][j]; 187 filein4 >> fNuMuQdistrKR[k][i][j]; 188 // G4cout<< fNuMuQdistrKR[k][i][j] < 188 // G4cout<< fNuMuQdistrKR[k][i][j] << " "; 189 } 189 } 190 } 190 } 191 } 191 } 192 fData = true; 192 fData = true; 193 } 193 } 194 } 194 } 195 195 196 ////////////////////////////////////////////// 196 ///////////////////////////////////////////////////////// 197 197 198 G4bool G4NuElNucleusNcModel::IsApplicable(cons 198 G4bool G4NuElNucleusNcModel::IsApplicable(const G4HadProjectile & aPart, 199 G4Nucleus & ) 199 G4Nucleus & ) 200 { 200 { 201 G4bool result = false; 201 G4bool result = false; 202 G4String pName = aPart.GetDefinition()->GetP 202 G4String pName = aPart.GetDefinition()->GetParticleName(); 203 G4double energy = aPart.GetTotalEnergy(); 203 G4double energy = aPart.GetTotalEnergy(); 204 fMinNuEnergy = GetMinNuElEnergy(); 204 fMinNuEnergy = GetMinNuElEnergy(); 205 205 206 if( pName == "nu_e" 206 if( pName == "nu_e" 207 && 207 && 208 energy > fMinNuEnergy 208 energy > fMinNuEnergy ) 209 { 209 { 210 result = true; 210 result = true; 211 } 211 } 212 212 213 return result; 213 return result; 214 } 214 } 215 215 216 /////////////////////////////////////////// Cl 216 /////////////////////////////////////////// ClusterDecay //////////////////////////////////////////////////////////// 217 // 217 // 218 // 218 // 219 219 220 G4HadFinalState* G4NuElNucleusNcModel::ApplyYo 220 G4HadFinalState* G4NuElNucleusNcModel::ApplyYourself( 221 const G4HadProjectile& aTrack, G4Nucleus& 221 const G4HadProjectile& aTrack, G4Nucleus& targetNucleus) 222 { 222 { 223 theParticleChange.Clear(); 223 theParticleChange.Clear(); 224 fProton = f2p2h = fBreak = false; 224 fProton = f2p2h = fBreak = false; 225 const G4HadProjectile* aParticle = &aTrack; 225 const G4HadProjectile* aParticle = &aTrack; 226 G4double energy = aParticle->GetTotalEnergy( 226 G4double energy = aParticle->GetTotalEnergy(); 227 227 228 G4String pName = aParticle->GetDefinition() 228 G4String pName = aParticle->GetDefinition()->GetParticleName(); 229 229 230 if( energy < fMinNuEnergy ) 230 if( energy < fMinNuEnergy ) 231 { 231 { 232 theParticleChange.SetEnergyChange(energy); 232 theParticleChange.SetEnergyChange(energy); 233 theParticleChange.SetMomentumChange(aTrack 233 theParticleChange.SetMomentumChange(aTrack.Get4Momentum().vect().unit()); 234 return &theParticleChange; 234 return &theParticleChange; 235 } 235 } 236 SampleLVkr( aTrack, targetNucleus); 236 SampleLVkr( aTrack, targetNucleus); 237 237 238 if( fBreak == true || fEmu < fMnumu ) // ~5* 238 if( fBreak == true || fEmu < fMnumu ) // ~5*10^-6 239 { 239 { 240 // G4cout<<"ni, "; 240 // G4cout<<"ni, "; 241 theParticleChange.SetEnergyChange(energy); 241 theParticleChange.SetEnergyChange(energy); 242 theParticleChange.SetMomentumChange(aTrack 242 theParticleChange.SetMomentumChange(aTrack.Get4Momentum().vect().unit()); 243 return &theParticleChange; 243 return &theParticleChange; 244 } 244 } 245 245 246 // LVs of initial state 246 // LVs of initial state 247 247 248 G4LorentzVector lvp1 = aParticle->Get4Moment 248 G4LorentzVector lvp1 = aParticle->Get4Momentum(); 249 G4LorentzVector lvt1( 0., 0., 0., fM1 ); 249 G4LorentzVector lvt1( 0., 0., 0., fM1 ); 250 G4double mPip = G4ParticleTable::GetParticle 250 G4double mPip = G4ParticleTable::GetParticleTable()->FindParticle(211)->GetPDGMass(); 251 251 252 // 1-pi by fQtransfer && nu-energy 252 // 1-pi by fQtransfer && nu-energy 253 G4LorentzVector lvpip1( 0., 0., 0., mPip ); 253 G4LorentzVector lvpip1( 0., 0., 0., mPip ); 254 G4LorentzVector lvsum, lv2, lvX; 254 G4LorentzVector lvsum, lv2, lvX; 255 G4ThreeVector eP; 255 G4ThreeVector eP; 256 G4double cost(1.), sint(0.), phi(0.), muMom( 256 G4double cost(1.), sint(0.), phi(0.), muMom(0.), massX2(0.); 257 G4DynamicParticle* aLept = nullptr; // lepto 257 G4DynamicParticle* aLept = nullptr; // lepton lv 258 258 259 G4int Z = targetNucleus.GetZ_asInt(); 259 G4int Z = targetNucleus.GetZ_asInt(); 260 G4int A = targetNucleus.GetA_asInt(); 260 G4int A = targetNucleus.GetA_asInt(); 261 G4double mTarg = targetNucleus.AtomicMass(A 261 G4double mTarg = targetNucleus.AtomicMass(A,Z); 262 G4int pdgP(0), qB(0); 262 G4int pdgP(0), qB(0); 263 // G4double mSum = G4ParticleTable::GetParti 263 // G4double mSum = G4ParticleTable::GetParticleTable()->FindParticle(2212)->GetPDGMass() + mPip; 264 264 265 G4int iPi = GetOnePionIndex(energy); 265 G4int iPi = GetOnePionIndex(energy); 266 G4double p1pi = GetNuMuOnePionProb( iPi, ene 266 G4double p1pi = GetNuMuOnePionProb( iPi, energy); 267 267 268 if( p1pi > G4UniformRand() && fCosTheta > 0. 268 if( p1pi > G4UniformRand() && fCosTheta > 0.9 ) // && fQtransfer < 0.95*GeV ) // mu- & coherent pion + nucleus 269 { 269 { 270 // lvsum = lvp1 + lvpip1; 270 // lvsum = lvp1 + lvpip1; 271 lvsum = lvp1 + lvt1; 271 lvsum = lvp1 + lvt1; 272 // cost = fCosThetaPi; 272 // cost = fCosThetaPi; 273 cost = fCosTheta; 273 cost = fCosTheta; 274 sint = std::sqrt( (1.0 - cost)*(1.0 + cost 274 sint = std::sqrt( (1.0 - cost)*(1.0 + cost) ); 275 phi = G4UniformRand()*CLHEP::twopi; 275 phi = G4UniformRand()*CLHEP::twopi; 276 eP = G4ThreeVector( sint*std::cos(phi), 276 eP = G4ThreeVector( sint*std::cos(phi), sint*std::sin(phi), cost ); 277 277 278 // muMom = sqrt(fEmuPi*fEmuPi-fMnumu*fMnum 278 // muMom = sqrt(fEmuPi*fEmuPi-fMnumu*fMnumu); 279 muMom = sqrt(fEmu*fEmu-fMnumu*fMnumu); 279 muMom = sqrt(fEmu*fEmu-fMnumu*fMnumu); 280 280 281 eP *= muMom; 281 eP *= muMom; 282 282 283 // lv2 = G4LorentzVector( eP, fEmuPi ); 283 // lv2 = G4LorentzVector( eP, fEmuPi ); 284 lv2 = G4LorentzVector( eP, fEmu ); 284 lv2 = G4LorentzVector( eP, fEmu ); 285 lv2 = fLVl; 285 lv2 = fLVl; 286 286 287 lvX = lvsum - lv2; 287 lvX = lvsum - lv2; 288 lvX = fLVh; 288 lvX = fLVh; 289 massX2 = lvX.m2(); 289 massX2 = lvX.m2(); 290 G4double massX = lvX.m(); 290 G4double massX = lvX.m(); 291 G4double massR = fLVt.m(); 291 G4double massR = fLVt.m(); 292 292 293 // if ( massX2 <= 0. ) // vmg: very rarely 293 // 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 294 if ( massX2 <= fM1*fM1 ) // 9-3-20 vmg: very rarely ~ (1-4)e-6 due to big Q2/x, to be improved 295 if ( lvX.e() <= fM1 ) // 9-3-20 vmg: ver 295 if ( lvX.e() <= fM1 ) // 9-3-20 vmg: very rarely ~ (1-4)e-6 due to big Q2/x, to be improved 296 { 296 { 297 theParticleChange.SetEnergyChange(energy 297 theParticleChange.SetEnergyChange(energy); 298 theParticleChange.SetMomentumChange(aTra 298 theParticleChange.SetMomentumChange(aTrack.Get4Momentum().vect().unit()); 299 return &theParticleChange; 299 return &theParticleChange; 300 } 300 } 301 fW2 = massX2; 301 fW2 = massX2; 302 302 303 if( pName == "nu_e" ) aLept = new 303 if( pName == "nu_e" ) aLept = new G4DynamicParticle( theNuE, lv2 ); 304 // else if( pName == "anti_nu_mu") aLept = 304 // else if( pName == "anti_nu_mu") aLept = new G4DynamicParticle( theANuMu, lv2 ); 305 else 305 else 306 { 306 { 307 theParticleChange.SetEnergyChange(energy 307 theParticleChange.SetEnergyChange(energy); 308 theParticleChange.SetMomentumChange(aTra 308 theParticleChange.SetMomentumChange(aTrack.Get4Momentum().vect().unit()); 309 return &theParticleChange; 309 return &theParticleChange; 310 } 310 } 311 311 312 pdgP = 111; 312 pdgP = 111; 313 313 314 G4double eCut; // = fMpi + 0.5*(fMpi*fMpi 314 G4double eCut; // = fMpi + 0.5*(fMpi*fMpi - massX2)/mTarg; // massX -> fMpi 315 315 316 if( A > 1 ) 316 if( A > 1 ) 317 { 317 { 318 eCut = (fMpi + mTarg)*(fMpi + mTarg) - ( 318 eCut = (fMpi + mTarg)*(fMpi + mTarg) - (massX + massR)*(massX + massR); 319 eCut /= 2.*massR; 319 eCut /= 2.*massR; 320 eCut += massX; 320 eCut += massX; 321 } 321 } 322 else eCut = fM1 + fMpi; 322 else eCut = fM1 + fMpi; 323 323 324 if ( lvX.e() > eCut ) // && sqrt( GetW2() 324 if ( lvX.e() > eCut ) // && sqrt( GetW2() ) < 1.4*GeV ) // 325 { 325 { 326 CoherentPion( lvX, pdgP, targetNucleus); 326 CoherentPion( lvX, pdgP, targetNucleus); 327 } 327 } 328 else 328 else 329 { 329 { 330 theParticleChange.SetEnergyChange(energy 330 theParticleChange.SetEnergyChange(energy); 331 theParticleChange.SetMomentumChange(aTra 331 theParticleChange.SetMomentumChange(aTrack.Get4Momentum().vect().unit()); 332 return &theParticleChange; 332 return &theParticleChange; 333 } 333 } 334 theParticleChange.AddSecondary( aLept, fSe 334 theParticleChange.AddSecondary( aLept, fSecID ); 335 335 336 return &theParticleChange; 336 return &theParticleChange; 337 } 337 } 338 else // lepton part in lab 338 else // lepton part in lab 339 { 339 { 340 lvsum = lvp1 + lvt1; 340 lvsum = lvp1 + lvt1; 341 cost = fCosTheta; 341 cost = fCosTheta; 342 sint = std::sqrt( (1.0 - cost)*(1.0 + cost 342 sint = std::sqrt( (1.0 - cost)*(1.0 + cost) ); 343 phi = G4UniformRand()*CLHEP::twopi; 343 phi = G4UniformRand()*CLHEP::twopi; 344 eP = G4ThreeVector( sint*std::cos(phi), 344 eP = G4ThreeVector( sint*std::cos(phi), sint*std::sin(phi), cost ); 345 345 346 muMom = sqrt(fEmu*fEmu-fMnumu*fMnumu); 346 muMom = sqrt(fEmu*fEmu-fMnumu*fMnumu); 347 347 348 eP *= muMom; 348 eP *= muMom; 349 349 350 lv2 = G4LorentzVector( eP, fEmu ); 350 lv2 = G4LorentzVector( eP, fEmu ); 351 351 352 lvX = lvsum - lv2; 352 lvX = lvsum - lv2; 353 353 354 massX2 = lvX.m2(); 354 massX2 = lvX.m2(); 355 355 356 if ( massX2 <= 0. ) // vmg: very rarely ~ 356 if ( massX2 <= 0. ) // vmg: very rarely ~ (1-4)e-6 due to big Q2/x, to be improved 357 { 357 { 358 theParticleChange.SetEnergyChange(energy 358 theParticleChange.SetEnergyChange(energy); 359 theParticleChange.SetMomentumChange(aTra 359 theParticleChange.SetMomentumChange(aTrack.Get4Momentum().vect().unit()); 360 return &theParticleChange; 360 return &theParticleChange; 361 } 361 } 362 fW2 = massX2; 362 fW2 = massX2; 363 363 364 aLept = new G4DynamicParticle( theNuE, lv2 364 aLept = new G4DynamicParticle( theNuE, lv2 ); 365 365 366 theParticleChange.AddSecondary( aLept, fSe 366 theParticleChange.AddSecondary( aLept, fSecID ); 367 } 367 } 368 368 369 // hadron part 369 // hadron part 370 370 371 fRecoil = nullptr; 371 fRecoil = nullptr; 372 fCascade = false; 372 fCascade = false; 373 fString = false; 373 fString = false; 374 374 375 if( A == 1 ) 375 if( A == 1 ) 376 { 376 { 377 qB = 1; 377 qB = 1; 378 378 379 // if( G4UniformRand() > 0.1 ) // > 0.999 379 // if( G4UniformRand() > 0.1 ) // > 0.9999 ) // > 0.0001 ) // 380 { 380 { 381 ClusterDecay( lvX, qB ); 381 ClusterDecay( lvX, qB ); 382 } 382 } 383 return &theParticleChange; 383 return &theParticleChange; 384 } 384 } 385 G4Nucleus recoil; 385 G4Nucleus recoil; 386 G4double rM(0.), ratio = G4double(Z)/G4doubl 386 G4double rM(0.), ratio = G4double(Z)/G4double(A); 387 387 388 if( ratio > G4UniformRand() ) // proton is e 388 if( ratio > G4UniformRand() ) // proton is excited 389 { 389 { 390 fProton = true; 390 fProton = true; 391 recoil = G4Nucleus(A-1,Z-1); 391 recoil = G4Nucleus(A-1,Z-1); 392 fRecoil = &recoil; 392 fRecoil = &recoil; 393 rM = recoil.AtomicMass(A-1,Z-1); 393 rM = recoil.AtomicMass(A-1,Z-1); 394 394 395 fMt = G4ParticleTable::GetParticleTable()- 395 fMt = G4ParticleTable::GetParticleTable()->FindParticle(2212)->GetPDGMass() 396 + G4ParticleTable::GetParticleTable( 396 + G4ParticleTable::GetParticleTable()->FindParticle(111)->GetPDGMass(); 397 } 397 } 398 else // excited neutron 398 else // excited neutron 399 { 399 { 400 fProton = false; 400 fProton = false; 401 recoil = G4Nucleus(A-1,Z); 401 recoil = G4Nucleus(A-1,Z); 402 fRecoil = &recoil; 402 fRecoil = &recoil; 403 rM = recoil.AtomicMass(A-1,Z); 403 rM = recoil.AtomicMass(A-1,Z); 404 404 405 fMt = G4ParticleTable::GetParticleTable()- 405 fMt = G4ParticleTable::GetParticleTable()->FindParticle(2112)->GetPDGMass() 406 + G4ParticleTable::GetParticleTable( 406 + G4ParticleTable::GetParticleTable()->FindParticle(111)->GetPDGMass(); 407 } 407 } 408 // G4int index = GetEnergyIndex(energy 408 // G4int index = GetEnergyIndex(energy); 409 G4int nepdg = aParticle->GetDefinition()->Ge 409 G4int nepdg = aParticle->GetDefinition()->GetPDGEncoding(); 410 G4double qeTotRat; // = GetNuMuQeTotRat(inde 410 G4double qeTotRat; // = GetNuMuQeTotRat(index, energy); 411 qeTotRat = CalculateQEratioA( Z, A, energy, 411 qeTotRat = CalculateQEratioA( Z, A, energy, nepdg); 412 412 413 G4ThreeVector dX = (lvX.vect()).unit(); 413 G4ThreeVector dX = (lvX.vect()).unit(); 414 G4double eX = lvX.e(); // excited nucleon 414 G4double eX = lvX.e(); // excited nucleon 415 G4double mX = sqrt(massX2); 415 G4double mX = sqrt(massX2); 416 416 417 if( qeTotRat > G4UniformRand() || mX <= fMt 417 if( qeTotRat > G4UniformRand() || mX <= fMt ) // || eX <= 1232.*MeV) // QE 418 { 418 { 419 fString = false; 419 fString = false; 420 420 421 if( fProton ) 421 if( fProton ) 422 { 422 { 423 fPDGencoding = 2212; 423 fPDGencoding = 2212; 424 fMr = proton_mass_c2; 424 fMr = proton_mass_c2; 425 recoil = G4Nucleus(A-1,Z-1); 425 recoil = G4Nucleus(A-1,Z-1); 426 fRecoil = &recoil; 426 fRecoil = &recoil; 427 rM = recoil.AtomicMass(A-1,Z-1); 427 rM = recoil.AtomicMass(A-1,Z-1); 428 } 428 } 429 else 429 else 430 { 430 { 431 fPDGencoding = 2112; 431 fPDGencoding = 2112; 432 fMr = G4ParticleTable::GetParticleTabl 432 fMr = G4ParticleTable::GetParticleTable()-> 433 FindParticle(fPDGencoding)->GetPDGMass(); // 433 FindParticle(fPDGencoding)->GetPDGMass(); // 939.5654133*MeV; 434 recoil = G4Nucleus(A-1,Z); 434 recoil = G4Nucleus(A-1,Z); 435 fRecoil = &recoil; 435 fRecoil = &recoil; 436 rM = recoil.AtomicMass(A-1,Z); 436 rM = recoil.AtomicMass(A-1,Z); 437 } 437 } 438 G4double eTh = fMr+0.5*(fMr*fMr-mX*mX)/rM; 438 G4double eTh = fMr+0.5*(fMr*fMr-mX*mX)/rM; 439 439 440 if(eX <= eTh) // vmg, very rarely out of k 440 if(eX <= eTh) // vmg, very rarely out of kinematics 441 { 441 { 442 theParticleChange.SetEnergyChange(energy 442 theParticleChange.SetEnergyChange(energy); 443 theParticleChange.SetMomentumChange(aTra 443 theParticleChange.SetMomentumChange(aTrack.Get4Momentum().vect().unit()); 444 return &theParticleChange; 444 return &theParticleChange; 445 } 445 } 446 FinalBarion( lvX, 0, fPDGencoding ); // p( 446 FinalBarion( lvX, 0, fPDGencoding ); // p(n)+deexcited recoil 447 } 447 } 448 else // if ( eX < 9500000.*GeV ) // < 25.*Ge 448 else // if ( eX < 9500000.*GeV ) // < 25.*GeV) // < 95.*GeV ) // < 2.5*GeV ) //cluster decay 449 { 449 { 450 if ( fProton && pName == "nu_e" ) 450 if ( fProton && pName == "nu_e" ) qB = 1; 451 else if( !fProton && pName == "nu_e" ) 451 else if( !fProton && pName == "nu_e" ) qB = 0; 452 452 453 ClusterDecay( lvX, qB ); 453 ClusterDecay( lvX, qB ); 454 } 454 } 455 return &theParticleChange; 455 return &theParticleChange; 456 } 456 } 457 457 458 458 459 ////////////////////////////////////////////// 459 ///////////////////////////////////////////////////////////////////// 460 ////////////////////////////////////////////// 460 //////////////////////////////////////////////////////////////////// 461 ////////////////////////////////////////////// 461 /////////////////////////////////////////////////////////////////// 462 462 463 ////////////////////////////////////////////// 463 ///////////////////////////////////////////////// 464 // 464 // 465 // sample x, then Q2 465 // sample x, then Q2 466 466 467 void G4NuElNucleusNcModel::SampleLVkr(const G4 467 void G4NuElNucleusNcModel::SampleLVkr(const G4HadProjectile & aTrack, G4Nucleus& targetNucleus) 468 { 468 { 469 fBreak = false; 469 fBreak = false; 470 G4int A = targetNucleus.GetA_asInt(), iTer(0 470 G4int A = targetNucleus.GetA_asInt(), iTer(0), iTerMax(100); 471 G4int Z = targetNucleus.GetZ_asInt(); 471 G4int Z = targetNucleus.GetZ_asInt(); 472 G4double e3(0.), pMu2(0.), pX2(0.), nMom(0.) 472 G4double e3(0.), pMu2(0.), pX2(0.), nMom(0.), rM(0.), hM(0.), tM = targetNucleus.AtomicMass(A,Z); 473 G4double cost(1.), sint(0.), phi(0.), muMom( 473 G4double cost(1.), sint(0.), phi(0.), muMom(0.); 474 G4ThreeVector eP, bst; 474 G4ThreeVector eP, bst; 475 const G4HadProjectile* aParticle = &aTrack; 475 const G4HadProjectile* aParticle = &aTrack; 476 G4LorentzVector lvp1 = aParticle->Get4Moment 476 G4LorentzVector lvp1 = aParticle->Get4Momentum(); 477 nMom = NucleonMomentum( targetNucleus ); 477 nMom = NucleonMomentum( targetNucleus ); 478 478 479 if( A == 1 || nMom == 0. ) // hydrogen, no F 479 if( A == 1 || nMom == 0. ) // hydrogen, no Fermi motion ??? 480 { 480 { 481 fNuEnergy = aParticle->GetTotalEnergy(); 481 fNuEnergy = aParticle->GetTotalEnergy(); 482 iTer = 0; 482 iTer = 0; 483 483 484 do 484 do 485 { 485 { 486 fXsample = SampleXkr(fNuEnergy); 486 fXsample = SampleXkr(fNuEnergy); 487 fQtransfer = SampleQkr(fNuEnergy, fXsamp 487 fQtransfer = SampleQkr(fNuEnergy, fXsample); 488 fQ2 = fQtransfer*fQtransfer; 488 fQ2 = fQtransfer*fQtransfer; 489 489 490 if( fXsample > 0. ) 490 if( fXsample > 0. ) 491 { 491 { 492 fW2 = fM1*fM1 - fQ2 + fQ2/fXsample; // 492 fW2 = fM1*fM1 - fQ2 + fQ2/fXsample; // sample excited hadron mass 493 fEmu = fNuEnergy - fQ2/2./fM1/fXsample 493 fEmu = fNuEnergy - fQ2/2./fM1/fXsample; 494 } 494 } 495 else 495 else 496 { 496 { 497 fW2 = fM1*fM1; 497 fW2 = fM1*fM1; 498 fEmu = fNuEnergy; 498 fEmu = fNuEnergy; 499 } 499 } 500 e3 = fNuEnergy + fM1 - fEmu; 500 e3 = fNuEnergy + fM1 - fEmu; 501 501 502 // if( e3 < sqrt(fW2) ) G4cout<<"energy 502 // if( e3 < sqrt(fW2) ) G4cout<<"energyX = "<<e3/GeV<<", fW = "<<sqrt(fW2)/GeV<<G4endl; // vmg ~10^-5 for NC 503 503 504 pMu2 = fEmu*fEmu - fMnumu*fMnumu; 504 pMu2 = fEmu*fEmu - fMnumu*fMnumu; 505 pX2 = e3*e3 - fW2; 505 pX2 = e3*e3 - fW2; 506 506 507 fCosTheta = fNuEnergy*fNuEnergy + pMu2 507 fCosTheta = fNuEnergy*fNuEnergy + pMu2 - pX2; 508 fCosTheta /= 2.*fNuEnergy*sqrt(pMu2); 508 fCosTheta /= 2.*fNuEnergy*sqrt(pMu2); 509 iTer++; 509 iTer++; 510 } 510 } 511 while( ( abs(fCosTheta) > 1. || fEmu < fMn 511 while( ( abs(fCosTheta) > 1. || fEmu < fMnumu ) && iTer < iTerMax ); 512 512 513 if( iTer >= iTerMax ) { fBreak = true; ret 513 if( iTer >= iTerMax ) { fBreak = true; return; } 514 514 515 if( abs(fCosTheta) > 1.) // vmg: due to bi 515 if( abs(fCosTheta) > 1.) // vmg: due to big Q2/x values. To be improved ... 516 { 516 { 517 G4cout<<"H2: fCosTheta = "<<fCosTheta<<" 517 G4cout<<"H2: fCosTheta = "<<fCosTheta<<", fEmu = "<<fEmu<<G4endl; 518 // fCosTheta = -1. + 2.*G4UniformRand(); 518 // fCosTheta = -1. + 2.*G4UniformRand(); 519 if(fCosTheta < -1.) fCosTheta = -1.; 519 if(fCosTheta < -1.) fCosTheta = -1.; 520 if(fCosTheta > 1.) fCosTheta = 1.; 520 if(fCosTheta > 1.) fCosTheta = 1.; 521 } 521 } 522 // LVs 522 // LVs 523 523 524 G4LorentzVector lvt1 = G4LorentzVector( 0 524 G4LorentzVector lvt1 = G4LorentzVector( 0., 0., 0., fM1 ); 525 G4LorentzVector lvsum = lvp1 + lvt1; 525 G4LorentzVector lvsum = lvp1 + lvt1; 526 526 527 cost = fCosTheta; 527 cost = fCosTheta; 528 sint = std::sqrt( (1.0 - cost)*(1.0 + cost 528 sint = std::sqrt( (1.0 - cost)*(1.0 + cost) ); 529 phi = G4UniformRand()*CLHEP::twopi; 529 phi = G4UniformRand()*CLHEP::twopi; 530 eP = G4ThreeVector( sint*std::cos(phi), 530 eP = G4ThreeVector( sint*std::cos(phi), sint*std::sin(phi), cost ); 531 muMom = sqrt(fEmu*fEmu-fMnumu*fMnumu); 531 muMom = sqrt(fEmu*fEmu-fMnumu*fMnumu); 532 eP *= muMom; 532 eP *= muMom; 533 fLVl = G4LorentzVector( eP, fEmu ); 533 fLVl = G4LorentzVector( eP, fEmu ); 534 534 535 fLVh = lvsum - fLVl; 535 fLVh = lvsum - fLVl; 536 fLVt = G4LorentzVector( 0., 0., 0., 0. ); 536 fLVt = G4LorentzVector( 0., 0., 0., 0. ); // no recoil 537 } 537 } 538 else // Fermi motion, Q2 in nucleon rest fra 538 else // Fermi motion, Q2 in nucleon rest frame 539 { 539 { 540 G4ThreeVector nMomDir = nMom*G4RandomDirec 540 G4ThreeVector nMomDir = nMom*G4RandomDirection(); 541 541 542 if( !f2p2h ) // 1p1h 542 if( !f2p2h ) // 1p1h 543 { 543 { 544 G4Nucleus recoil(A-1,Z); 544 G4Nucleus recoil(A-1,Z); 545 rM = sqrt( recoil.AtomicMass(A-1,Z)*reco 545 rM = sqrt( recoil.AtomicMass(A-1,Z)*recoil.AtomicMass(A-1,Z) + nMom*nMom ); 546 hM = tM - rM; 546 hM = tM - rM; 547 547 548 fLVt = G4LorentzVector( nMomDir, sqrt( r 548 fLVt = G4LorentzVector( nMomDir, sqrt( rM*rM+nMom*nMom ) ); 549 fLVh = G4LorentzVector(-nMomDir, sqrt( h 549 fLVh = G4LorentzVector(-nMomDir, sqrt( hM*hM+nMom*nMom ) ); 550 } 550 } 551 else // 2p2h 551 else // 2p2h 552 { 552 { 553 G4Nucleus recoil(A-2,Z-1); 553 G4Nucleus recoil(A-2,Z-1); 554 rM = recoil.AtomicMass(A-2,Z-1)+sqrt(nMo 554 rM = recoil.AtomicMass(A-2,Z-1)+sqrt(nMom*nMom+fM1*fM1); 555 hM = tM - rM; 555 hM = tM - rM; 556 556 557 fLVt = G4LorentzVector( nMomDir, sqrt( r 557 fLVt = G4LorentzVector( nMomDir, sqrt( rM*rM+nMom*nMom ) ); 558 fLVh = G4LorentzVector(-nMomDir, sqrt( h 558 fLVh = G4LorentzVector(-nMomDir, sqrt( hM*hM+nMom*nMom ) ); 559 } 559 } 560 // G4cout<<hM<<", "; 560 // G4cout<<hM<<", "; 561 // bst = fLVh.boostVector(); // 9-3-20 561 // bst = fLVh.boostVector(); // 9-3-20 562 562 563 // lvp1.boost(-bst); // 9-3-20 -> nucleon 563 // lvp1.boost(-bst); // 9-3-20 -> nucleon rest system, where Q2 transfer is ??? 564 564 565 fNuEnergy = lvp1.e(); 565 fNuEnergy = lvp1.e(); 566 iTer = 0; 566 iTer = 0; 567 567 568 do 568 do 569 { 569 { 570 fXsample = SampleXkr(fNuEnergy); 570 fXsample = SampleXkr(fNuEnergy); 571 fQtransfer = SampleQkr(fNuEnergy, fXsamp 571 fQtransfer = SampleQkr(fNuEnergy, fXsample); 572 fQ2 = fQtransfer*fQtransfer; 572 fQ2 = fQtransfer*fQtransfer; 573 573 574 if( fXsample > 0. ) 574 if( fXsample > 0. ) 575 { 575 { 576 fW2 = fM1*fM1 - fQ2 + fQ2/fXsample; // 576 fW2 = fM1*fM1 - fQ2 + fQ2/fXsample; // sample excited hadron mass 577 fEmu = fNuEnergy - fQ2/2./fM1/fXsample 577 fEmu = fNuEnergy - fQ2/2./fM1/fXsample; 578 } 578 } 579 else 579 else 580 { 580 { 581 fW2 = fM1*fM1; 581 fW2 = fM1*fM1; 582 fEmu = fNuEnergy; 582 fEmu = fNuEnergy; 583 } 583 } 584 584 585 // if(fEmu < 0.) G4cout<<"fEmu = "<<fEmu 585 // if(fEmu < 0.) G4cout<<"fEmu = "<<fEmu<<" hM = "<<hM<<G4endl; 586 586 587 e3 = fNuEnergy + fM1 - fEmu; 587 e3 = fNuEnergy + fM1 - fEmu; 588 588 589 // if( e3 < sqrt(fW2) ) G4cout<<"energy 589 // if( e3 < sqrt(fW2) ) G4cout<<"energyX = "<<e3/GeV<<", fW = "<<sqrt(fW2)/GeV<<G4endl; 590 590 591 pMu2 = fEmu*fEmu - fMnumu*fMnumu; 591 pMu2 = fEmu*fEmu - fMnumu*fMnumu; 592 pX2 = e3*e3 - fW2; 592 pX2 = e3*e3 - fW2; 593 593 594 fCosTheta = fNuEnergy*fNuEnergy + pMu2 594 fCosTheta = fNuEnergy*fNuEnergy + pMu2 - pX2; 595 fCosTheta /= 2.*fNuEnergy*sqrt(pMu2); 595 fCosTheta /= 2.*fNuEnergy*sqrt(pMu2); 596 iTer++; 596 iTer++; 597 } 597 } 598 while( ( abs(fCosTheta) > 1. || fEmu < fMn 598 while( ( abs(fCosTheta) > 1. || fEmu < fMnumu ) && iTer < iTerMax ); 599 599 600 if( iTer >= iTerMax ) { fBreak = true; ret 600 if( iTer >= iTerMax ) { fBreak = true; return; } 601 601 602 if( abs(fCosTheta) > 1.) // vmg: due to bi 602 if( abs(fCosTheta) > 1.) // vmg: due to big Q2/x values. To be improved ... 603 { 603 { 604 G4cout<<"FM: fCosTheta = "<<fCosTheta<<" 604 G4cout<<"FM: fCosTheta = "<<fCosTheta<<", fEmu = "<<fEmu<<G4endl; 605 // fCosTheta = -1. + 2.*G4UniformRand(); 605 // fCosTheta = -1. + 2.*G4UniformRand(); 606 if(fCosTheta < -1.) fCosTheta = -1.; 606 if(fCosTheta < -1.) fCosTheta = -1.; 607 if(fCosTheta > 1.) fCosTheta = 1.; 607 if(fCosTheta > 1.) fCosTheta = 1.; 608 } 608 } 609 // LVs 609 // LVs 610 G4LorentzVector lvt1 = G4LorentzVector( 0 610 G4LorentzVector lvt1 = G4LorentzVector( 0., 0., 0., fM1 ); 611 G4LorentzVector lvsum = lvp1 + lvt1; 611 G4LorentzVector lvsum = lvp1 + lvt1; 612 612 613 cost = fCosTheta; 613 cost = fCosTheta; 614 sint = std::sqrt( (1.0 - cost)*(1.0 + cost 614 sint = std::sqrt( (1.0 - cost)*(1.0 + cost) ); 615 phi = G4UniformRand()*CLHEP::twopi; 615 phi = G4UniformRand()*CLHEP::twopi; 616 eP = G4ThreeVector( sint*std::cos(phi), 616 eP = G4ThreeVector( sint*std::cos(phi), sint*std::sin(phi), cost ); 617 muMom = sqrt(fEmu*fEmu-fMnumu*fMnumu); 617 muMom = sqrt(fEmu*fEmu-fMnumu*fMnumu); 618 eP *= muMom; 618 eP *= muMom; 619 fLVl = G4LorentzVector( eP, fEmu ); 619 fLVl = G4LorentzVector( eP, fEmu ); 620 fLVh = lvsum - fLVl; 620 fLVh = lvsum - fLVl; 621 // back to lab system 621 // back to lab system 622 // fLVl.boost(bst); // 9-3-20 622 // fLVl.boost(bst); // 9-3-20 623 // fLVh.boost(bst); // 9-3-20 623 // fLVh.boost(bst); // 9-3-20 624 } 624 } 625 //G4cout<<iTer<<", "<<fBreak<<"; "; 625 //G4cout<<iTer<<", "<<fBreak<<"; "; 626 } 626 } 627 627 628 // 628 // 629 // 629 // 630 /////////////////////////// 630 /////////////////////////// 631 631