// // ******************************************************************** // * License and Disclaimer * // * * // * The Geant4 software is copyright of the Copyright Holders of * // * the Geant4 Collaboration. It is provided under the terms and * // * conditions of the Geant4 Software License, included in the file * // * LICENSE and available at http://cern.ch/geant4/license . These * // * include a list of copyright holders. * // * * // * Neither the authors of this software system, nor their employing * // * institutes,nor the agencies providing financial support for this * // * work make any representation or warranty, express or implied, * // * regarding this software system or assume any liability for its * // * use. Please see the license in the file LICENSE and URL above * // * for the full disclaimer and the limitation of liability. * // * * // * This code implementation is the result of the scientific and * // * technical work of the GEANT4 collaboration. * // * By using, copying, modifying or distributing the software (or * // * any work based on the software) you agree to acknowledge its * // * use in resulting scientific publications, and indicate your * // * acceptance of all terms of the Geant4 Software license. * // ******************************************************************** // // $Id: G4NuMuNucleusNcModel.cc 91806 2015-08-06 12:20:45Z gcosmo $ // // Geant4 Header : G4NuMuNucleusNcModel // // Author : V.Grichine 12.2.19 // #include "G4NuMuNucleusNcModel.hh" #include "G4NeutrinoNucleusModel.hh" // #include "G4NuMuResQX.hh" #include "G4SystemOfUnits.hh" #include "G4ParticleTable.hh" #include "G4ParticleDefinition.hh" #include "G4IonTable.hh" #include "Randomize.hh" #include "G4RandomDirection.hh" // #include "G4Integrator.hh" #include "G4DataVector.hh" #include "G4PhysicsTable.hh" #include "G4KineticTrack.hh" #include "G4DecayKineticTracks.hh" #include "G4KineticTrackVector.hh" #include "G4Fragment.hh" #include "G4ReactionProductVector.hh" #include "G4NeutrinoMu.hh" #include "G4AntiNeutrinoMu.hh" #include "G4Nucleus.hh" #include "G4LorentzVector.hh" using namespace std; using namespace CLHEP; #ifdef G4MULTITHREADED G4Mutex G4NuMuNucleusNcModel::numuNucleusModel = G4MUTEX_INITIALIZER; #endif G4NuMuNucleusNcModel::G4NuMuNucleusNcModel(const G4String& name) : G4NeutrinoNucleusModel(name) { SetMinEnergy( 0.0*GeV ); SetMaxEnergy( 100.*TeV ); SetMinEnergy(1.e-6*eV); theNuMu = G4NeutrinoMu::NeutrinoMu(); theANuMu = G4AntiNeutrinoMu::AntiNeutrinoMu(); fMnumu = 0.; fData = fMaster = false; InitialiseModel(); } G4NuMuNucleusNcModel::~G4NuMuNucleusNcModel() {} void G4NuMuNucleusNcModel::ModelDescription(std::ostream& outFile) const { outFile << "G4NuMuNucleusNcModel is a neutrino-nucleus (neutral current) scattering\n" << "model which uses the standard model \n" << "transfer parameterization. The model is fully relativistic\n"; } ///////////////////////////////////////////////////////// // // Read data from G4PARTICLEXSDATA (locally PARTICLEXSDATA) void G4NuMuNucleusNcModel::InitialiseModel() { G4String pName = "nu_mu"; G4int nSize(0), i(0), j(0), k(0); if(!fData) { #ifdef G4MULTITHREADED G4MUTEXLOCK(&numuNucleusModel); if(!fData) { #endif fMaster = true; #ifdef G4MULTITHREADED } G4MUTEXUNLOCK(&numuNucleusModel); #endif } if(fMaster) { const char* path = G4FindDataDir("G4PARTICLEXSDATA"); std::ostringstream ost1, ost2, ost3, ost4; ost1 << path << "/" << "neutrino" << "/" << pName << "/xarraynckr"; std::ifstream filein1( ost1.str().c_str() ); // filein.open("$PARTICLEXSDATA/"); filein1>>nSize; for( k = 0; k < fNbin; ++k ) { for( i = 0; i <= fNbin; ++i ) { filein1 >> fNuMuXarrayKR[k][i]; // G4cout<< fNuMuXarrayKR[k][i] << " "; } } // G4cout<>nSize; for( k = 0; k < fNbin; ++k ) { for( i = 0; i < fNbin; ++i ) { filein2 >> fNuMuXdistrKR[k][i]; // G4cout<< fNuMuXdistrKR[k][i] << " "; } } // G4cout<>nSize; for( k = 0; k < fNbin; ++k ) { for( i = 0; i <= fNbin; ++i ) { for( j = 0; j <= fNbin; ++j ) { filein3 >> fNuMuQarrayKR[k][i][j]; // G4cout<< fNuMuQarrayKR[k][i][j] << " "; } } } // G4cout<>nSize; for( k = 0; k < fNbin; ++k ) { for( i = 0; i <= fNbin; ++i ) { for( j = 0; j < fNbin; ++j ) { filein4 >> fNuMuQdistrKR[k][i][j]; // G4cout<< fNuMuQdistrKR[k][i][j] << " "; } } } fData = true; } } ///////////////////////////////////////////////////////// G4bool G4NuMuNucleusNcModel::IsApplicable(const G4HadProjectile & aPart, G4Nucleus & ) { G4bool result = false; G4String pName = aPart.GetDefinition()->GetParticleName(); G4double energy = aPart.GetTotalEnergy(); if( pName == "nu_mu" // || pName == "anti_nu_mu" ) && energy > fMinNuEnergy ) { result = true; } return result; } /////////////////////////////////////////// ClusterDecay //////////////////////////////////////////////////////////// // // G4HadFinalState* G4NuMuNucleusNcModel::ApplyYourself( const G4HadProjectile& aTrack, G4Nucleus& targetNucleus) { theParticleChange.Clear(); fProton = f2p2h = fBreak = false; const G4HadProjectile* aParticle = &aTrack; G4double energy = aParticle->GetTotalEnergy(); G4String pName = aParticle->GetDefinition()->GetParticleName(); if( energy < fMinNuEnergy ) { theParticleChange.SetEnergyChange(energy); theParticleChange.SetMomentumChange(aTrack.Get4Momentum().vect().unit()); return &theParticleChange; } SampleLVkr( aTrack, targetNucleus); if( fBreak == true || fEmu < fMnumu ) // ~5*10^-6 { // G4cout<<"ni, "; theParticleChange.SetEnergyChange(energy); theParticleChange.SetMomentumChange(aTrack.Get4Momentum().vect().unit()); return &theParticleChange; } // LVs of initial state G4LorentzVector lvp1 = aParticle->Get4Momentum(); G4LorentzVector lvt1( 0., 0., 0., fM1 ); G4double mPip = G4ParticleTable::GetParticleTable()->FindParticle(211)->GetPDGMass(); // 1-pi by fQtransfer && nu-energy G4LorentzVector lvpip1( 0., 0., 0., mPip ); G4LorentzVector lvsum, lv2, lvX; G4ThreeVector eP; G4double cost(1.), sint(0.), phi(0.), muMom(0.), massX2(0.); G4DynamicParticle* aLept = nullptr; // lepton lv G4int Z = targetNucleus.GetZ_asInt(); G4int A = targetNucleus.GetA_asInt(); G4double mTarg = targetNucleus.AtomicMass(A,Z); G4int pdgP(0), qB(0); // G4double mSum = G4ParticleTable::GetParticleTable()->FindParticle(2212)->GetPDGMass() + mPip; G4int iPi = GetOnePionIndex(energy); G4double p1pi = GetNuMuOnePionProb( iPi, energy); if( p1pi > G4UniformRand() && fCosTheta > 0.9 ) // && fQtransfer < 0.95*GeV ) // mu- & coherent pion + nucleus { // lvsum = lvp1 + lvpip1; lvsum = lvp1 + lvt1; // cost = fCosThetaPi; cost = fCosTheta; sint = std::sqrt( (1.0 - cost)*(1.0 + cost) ); phi = G4UniformRand()*CLHEP::twopi; eP = G4ThreeVector( sint*std::cos(phi), sint*std::sin(phi), cost ); // muMom = sqrt(fEmuPi*fEmuPi-fMnumu*fMnumu); muMom = sqrt(fEmu*fEmu-fMnumu*fMnumu); eP *= muMom; // lv2 = G4LorentzVector( eP, fEmuPi ); lv2 = G4LorentzVector( eP, fEmu ); lv2 = fLVl; lvX = lvsum - lv2; lvX = fLVh; massX2 = lvX.m2(); G4double massX = lvX.m(); G4double massR = fLVt.m(); // if ( massX2 <= 0. ) // vmg: very rarely ~ (1-4)e-6 due to big Q2/x, to be improved if ( massX2 <= fM1*fM1 ) // 9-3-20 vmg: very rarely ~ (1-4)e-6 due to big Q2/x, to be improved if ( lvX.e() <= fM1 ) // 9-3-20 vmg: very rarely ~ (1-4)e-6 due to big Q2/x, to be improved { theParticleChange.SetEnergyChange(energy); theParticleChange.SetMomentumChange(aTrack.Get4Momentum().vect().unit()); return &theParticleChange; } fW2 = massX2; if( pName == "nu_mu" ) aLept = new G4DynamicParticle( theNuMu, lv2 ); else if( pName == "anti_nu_mu") aLept = new G4DynamicParticle( theANuMu, lv2 ); else { theParticleChange.SetEnergyChange(energy); theParticleChange.SetMomentumChange(aTrack.Get4Momentum().vect().unit()); return &theParticleChange; } pdgP = 111; G4double eCut; // = fMpi + 0.5*(fMpi*fMpi - massX2)/mTarg; // massX -> fMpi if( A > 1 ) { eCut = (fMpi + mTarg)*(fMpi + mTarg) - (massX + massR)*(massX + massR); eCut /= 2.*massR; eCut += massX; } else eCut = fM1 + fMpi; if ( lvX.e() > eCut ) // && sqrt( GetW2() ) < 1.4*GeV ) // { CoherentPion( lvX, pdgP, targetNucleus); } else { theParticleChange.SetEnergyChange(energy); theParticleChange.SetMomentumChange(aTrack.Get4Momentum().vect().unit()); return &theParticleChange; } theParticleChange.AddSecondary( aLept, fSecID ); return &theParticleChange; } else // lepton part in lab { lvsum = lvp1 + lvt1; cost = fCosTheta; sint = std::sqrt( (1.0 - cost)*(1.0 + cost) ); phi = G4UniformRand()*CLHEP::twopi; eP = G4ThreeVector( sint*std::cos(phi), sint*std::sin(phi), cost ); muMom = sqrt(fEmu*fEmu-fMnumu*fMnumu); eP *= muMom; lv2 = G4LorentzVector( eP, fEmu ); lvX = lvsum - lv2; massX2 = lvX.m2(); if ( massX2 <= 0. ) // vmg: very rarely ~ (1-4)e-6 due to big Q2/x, to be improved { theParticleChange.SetEnergyChange(energy); theParticleChange.SetMomentumChange(aTrack.Get4Momentum().vect().unit()); return &theParticleChange; } fW2 = massX2; aLept = new G4DynamicParticle( theNuMu, lv2 ); theParticleChange.AddSecondary( aLept, fSecID ); } // hadron part fRecoil = nullptr; fCascade = false; fString = false; if( A == 1 ) { qB = 1; // if( G4UniformRand() > 0.1 ) // > 0.9999 ) // > 0.0001 ) // { ClusterDecay( lvX, qB ); } return &theParticleChange; } G4Nucleus recoil; G4double rM(0.), ratio = G4double(Z)/G4double(A); if( ratio > G4UniformRand() ) // proton is excited { fProton = true; recoil = G4Nucleus(A-1,Z-1); fRecoil = &recoil; rM = recoil.AtomicMass(A-1,Z-1); fMt = G4ParticleTable::GetParticleTable()->FindParticle(2212)->GetPDGMass() + G4ParticleTable::GetParticleTable()->FindParticle(111)->GetPDGMass(); } else // excited neutron { fProton = false; recoil = G4Nucleus(A-1,Z); fRecoil = &recoil; rM = recoil.AtomicMass(A-1,Z); fMt = G4ParticleTable::GetParticleTable()->FindParticle(2112)->GetPDGMass() + G4ParticleTable::GetParticleTable()->FindParticle(111)->GetPDGMass(); } // G4int index = GetEnergyIndex(energy); G4int nepdg = aParticle->GetDefinition()->GetPDGEncoding(); G4double qeTotRat; // = GetNuMuQeTotRat(index, energy); qeTotRat = CalculateQEratioA( Z, A, energy, nepdg); G4ThreeVector dX = (lvX.vect()).unit(); G4double eX = lvX.e(); // excited nucleon G4double mX = sqrt(massX2); if( qeTotRat > G4UniformRand() || mX <= fMt ) // || eX <= 1232.*MeV) // QE { fString = false; if( fProton ) { fPDGencoding = 2212; fMr = proton_mass_c2; recoil = G4Nucleus(A-1,Z-1); fRecoil = &recoil; rM = recoil.AtomicMass(A-1,Z-1); } else { fPDGencoding = 2112; fMr = G4ParticleTable::GetParticleTable()-> FindParticle(fPDGencoding)->GetPDGMass(); // 939.5654133*MeV; recoil = G4Nucleus(A-1,Z); fRecoil = &recoil; rM = recoil.AtomicMass(A-1,Z); } G4double eTh = fMr+0.5*(fMr*fMr-mX*mX)/rM; if(eX <= eTh) // vmg, very rarely out of kinematics { theParticleChange.SetEnergyChange(energy); theParticleChange.SetMomentumChange(aTrack.Get4Momentum().vect().unit()); return &theParticleChange; } FinalBarion( lvX, 0, fPDGencoding ); // p(n)+deexcited recoil } else // if ( eX < 9500000.*GeV ) // < 25.*GeV) // < 95.*GeV ) // < 2.5*GeV ) //cluster decay { if ( fProton && pName == "nu_mu" ) qB = 1; else if( !fProton && pName == "nu_mu" ) qB = 0; ClusterDecay( lvX, qB ); } return &theParticleChange; } ///////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////// // // sample x, then Q2 void G4NuMuNucleusNcModel::SampleLVkr(const G4HadProjectile & aTrack, G4Nucleus& targetNucleus) { fBreak = false; G4int A = targetNucleus.GetA_asInt(), iTer(0), iTerMax(100); G4int Z = targetNucleus.GetZ_asInt(); G4double e3(0.), pMu2(0.), pX2(0.), nMom(0.), rM(0.), hM(0.), tM = targetNucleus.AtomicMass(A,Z); G4double cost(1.), sint(0.), phi(0.), muMom(0.); G4ThreeVector eP, bst; const G4HadProjectile* aParticle = &aTrack; G4LorentzVector lvp1 = aParticle->Get4Momentum(); nMom = NucleonMomentum( targetNucleus ); if( A == 1 || nMom == 0. ) // hydrogen, no Fermi motion ??? { fNuEnergy = aParticle->GetTotalEnergy(); iTer = 0; do { fXsample = SampleXkr(fNuEnergy); fQtransfer = SampleQkr(fNuEnergy, fXsample); fQ2 = fQtransfer*fQtransfer; if( fXsample > 0. ) { fW2 = fM1*fM1 - fQ2 + fQ2/fXsample; // sample excited hadron mass fEmu = fNuEnergy - fQ2/2./fM1/fXsample; } else { fW2 = fM1*fM1; fEmu = fNuEnergy; } e3 = fNuEnergy + fM1 - fEmu; // if( e3 < sqrt(fW2) ) G4cout<<"energyX = "< nucleon rest system, where Q2 transfer is ??? fNuEnergy = lvp1.e(); iTer = 0; do { fXsample = SampleXkr(fNuEnergy); fQtransfer = SampleQkr(fNuEnergy, fXsample); fQ2 = fQtransfer*fQtransfer; if( fXsample > 0. ) { fW2 = fM1*fM1 - fQ2 + fQ2/fXsample; // sample excited hadron mass fEmu = fNuEnergy - fQ2/2./fM1/fXsample; } else { fW2 = fM1*fM1; fEmu = fNuEnergy; } // if(fEmu < 0.) G4cout<<"fEmu = "<