// // ******************************************************************** // * 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: G4QCoherentChargeExchange.cc,v 1.8 2009/02/23 09:49:24 mkossov Exp $ // GEANT4 tag $Name: geant4-09-03-beta-cand-01 $ // // ---------------- G4QCoherentChargeExchange class ----------------- // by Mikhail Kossov, December 2003. // G4QCoherentChargeExchange class of the CHIPS Simulation Branch in GEANT4 // --------------------------------------------------------------- // **************************************************************************************** // ********** This CLASS is temporary moved from the photolepton_hadron directory ********* // **************************************************************************************** // Short description: This class resolves an ambiguity in the definition of the // "inelastic" cross section. As it was shown in Ph.D.Thesis (M.Kosov,ITEP,1979) // it is more reasonable to subdivide the total cross-section in the coherent & // incoherent parts, but the measuring method for the "inelastic" cross-sections // consideres the lack of the projectile within the narrow forward solid angle // with the consequent extrapolation of these partial cross-sections, corresponding // to the particular solid angle, to the zero solid angle. The low angle region // is shadowed by the elastic (coherent) scattering. BUT the coherent charge // exchange (e.g. conversion p->n) is included by this procedure as a constant term // in the extrapolation, so the "inelastic" cross-section differes from the // incoherent cross-section by the value of the coherent charge exchange cross // section. Fortunately, this cross-sectoion drops ruther fast with energy increasing. // All Geant4 inelastic hadronic models (including CHIPS) simulate the incoherent // reactions. So the incoherent (including quasielastic) cross-section must be used // instead of the inelastic cross-section. For that the "inelastic" cross-section // must be reduced by the value of the coherent charge-exchange cross-section, which // is estimated (it must be tuned!) in this CHIPS class. The angular distribution // is made (at present) identical to the corresponding coherent-elastic scattering // ----------------------------------------------------------------------------------- //#define debug //#define pdebug //#define tdebug //#define nandebug //#define ppdebug #include "G4QCoherentChargeExchange.hh" // Initialization of static vectors G4int G4QCoherentChargeExchange::nPartCWorld=152; // #of particles initialized in CHIPS std::vector G4QCoherentChargeExchange::ElementZ; // Z of element(i) in theLastCalc std::vector G4QCoherentChargeExchange::ElProbInMat; // SumProbOfElem in Material std::vector*> G4QCoherentChargeExchange::ElIsoN;// N of isotope(j), E(i) std::vector*>G4QCoherentChargeExchange::IsoProbInEl;//SumProbIsotE(i) // Constructor G4QCoherentChargeExchange::G4QCoherentChargeExchange(const G4String& processName) : G4VDiscreteProcess(processName, fHadronic) { #ifdef debug G4cout<<"G4QCohChargeEx::Constructor is called processName="<0) G4cout << GetProcessName() << " process is created "<< G4endl; SetProcessSubType(fChargeExchange); //G4QCHIPSWorld::Get()->GetParticles(nPartCWorld); // Create CHIPS World (234 part. max) } // Destructor G4QCoherentChargeExchange::~G4QCoherentChargeExchange() {} G4LorentzVector G4QCoherentChargeExchange::GetEnegryMomentumConservation() {return EnMomConservation;} G4int G4QCoherentChargeExchange::GetNumberOfNeutronsInTarget() {return nOfNeutrons;} // output of the function must be in units of length! L=1/sig_V,sig_V=SUM(n(j,i)*sig(j,i)), // where n(i,j) is a number of nuclei of the isotop j of the element i in V=1(lengtUnit^3) // ********** All CHIPS cross sections are calculated in the surface units ************ G4double G4QCoherentChargeExchange::GetMeanFreePath(const G4Track& aTrack,G4double Q, G4ForceCondition* Fc) { *Fc = NotForced; const G4DynamicParticle* incidentParticle = aTrack.GetDynamicParticle(); G4ParticleDefinition* incidentParticleDefinition=incidentParticle->GetDefinition(); if( !IsApplicable(*incidentParticleDefinition)) G4cout<<"*W*G4QCohChargeEx::GetMeanFreePath called for notImplementedParticle"<GetTotalMomentum(); // 3-momentum of the Particle #ifdef debug G4double KinEn = incidentParticle->GetKineticEnergy(); G4cout<<"G4QCohChEx::GetMeanFreePath: kinE="<GetVecNbOfAtomsPerVolume(); const G4ElementVector* theElementVector = material->GetElementVector(); G4int nE=material->GetNumberOfElements(); #ifdef debug G4cout<<"G4QCohChargeExchange::GetMeanFreePath:"<* SPI=IsoProbInEl[ip]; // Pointer to the SPI vector SPI->clear(); delete SPI; std::vector* IsN=ElIsoN[ip]; // Pointer to the N vector IsN->clear(); delete IsN; } ElProbInMat.clear(); // Clean up the SumProb's of Elements (SPE) ElementZ.clear(); // Clear the body vector for Z of Elements IsoProbInEl.clear(); // Clear the body vector for SPI ElIsoN.clear(); // Clear the body vector for N of Isotopes for(G4int i=0; i(pElement->GetZ()); // Z of the Element ElementZ.push_back(Z); // Remember Z of the Element G4int isoSize=0; // The default for the isoVectorLength is 0 G4int indEl=0; // Index of non-natural element or 0(default) G4IsotopeVector* isoVector=pElement->GetIsotopeVector(); // Get the predefined IsoVect if(isoVector) isoSize=isoVector->size();// Get size of the existing isotopeVector #ifdef debug G4cout<<"G4QCoherentChargeExchange::GetMeanFreePath:isovectorLength="<GetIndex()+1; // Index of the non-trivial element is an order #ifdef debug G4cout<<"G4QCCX::GetMFP: iE="<* pr= new std::pair(N,abund); #ifdef debug G4cout<<"G4QCohChEx::GetMeanFreePath:pair#="<push_back(pr); } #ifdef debug G4cout<<"G4QCohChEx::GetMeanFreePath: pairVectorLength="<size()<InitElement(Z,indEl,newAbund); // definition of the newInd for(G4int k=0; k*>* cs= Isotopes->GetCSVector(Z,indEl);//CSPointer std::vector* SPI = new std::vector; // Pointer to the SPI vector IsoProbInEl.push_back(SPI); std::vector* IsN = new std::vector; // Pointer to the N vector ElIsoN.push_back(IsN); G4int nIs=cs->size(); // A#Of Isotopes in the Element #ifdef debug G4cout<<"G4QCohChargEx::GMFP:=***=>,#isot="<="<GetMeanCrossSection(Z,indEl)<<",AddToSigma=" <GetMeanCrossSection(Z,indEl)*NOfNucPerVolume[i]<>G4QCoherChargeExch::IsApplicable: PDG="<GetParticles(nPartCWorld); // Create CHIPS World (234 part.max) } //------------------------------------------------------------------------------------- const G4DynamicParticle* projHadron = track.GetDynamicParticle(); const G4ParticleDefinition* particle=projHadron->GetDefinition(); #ifdef debug G4cout<<"G4QCohChargeExchange::PostStepDoIt: Before the GetMeanFreePath is called In4M=" <Get4Momentum()<<" of PDG="<GetPDGEncoding()<<", Type=" <GetParticleType()<<", Subtp="<GetParticleSubType()<Get4Momentum())/MeV; // Convert to MeV! G4double momentum = projHadron->GetTotalMomentum()/MeV; // 3-momentum of the Proj in MeV G4double Momentum = proj4M.rho(); // @@ Just for the test purposes if(std::fabs(Momentum-momentum)>.000001) G4cerr<<"*Warning*G4QCohChEx::PostStepDoIt:P(IU)="<GetElementVector(); G4int nE=material->GetNumberOfElements(); #ifdef debug G4cout<<"G4QCohChargeExchange::PostStepDoIt: "<GetPDGEncoding(); G4cout<<"G4QCohChrgExchange::PostStepDoIt: projPDG="<size(); // #of isotopes in the element i #ifdef debug G4cout<<"G4QCohChargeExchange::PosStDoIt:nI="<1) { G4double rndI=(*SPI)[nofIsot-1]*G4UniformRand(); // Randomize the isotop of the Element for(j=0; jN="<GetKineticEnergy()*MeV; // Kin energy in MeV (Is *MeV n?) G4ParticleMomentum dir = projHadron->GetMomentumDirection();// It is a unit three-vector G4LorentzVector tot4M=proj4M+G4LorentzVector(0.,0.,0.,tM); // Total 4-mom of the reaction #ifdef debug G4cout<<"G4QCohChrgEx::PostStepDoIt: tM="<1.) cost=1.; else if(cost<-1.) cost=-1.; } G4LorentzVector reco4M=G4LorentzVector(0.,0.,0.,tM); // 4mom of the recoil target G4LorentzVector scat4M=G4LorentzVector(0.,0.,0.,pM); // 4mom of the recoil target G4LorentzVector dir4M=tot4M-G4LorentzVector(0.,0.,0.,(tot4M.e()-tM-pM)*.01); if(!G4QHadron(tot4M).RelDecayIn2(scat4M, reco4M, dir4M, cost, cost)) { G4cerr<<"G4QCohChEx::PSDI:t4M="<Set4Momentum(reco4M); #ifdef debug G4ThreeVector curD=theSec->GetMomentumDirection(); G4double curM=theSec->GetMass(); G4double curE=theSec->GetKineticEnergy()+curM; G4cout<<"G4QCohChEx::PostStpDoIt:p="<SetWeight(weight); // weighted aNewTrack->SetTouchableHandle(trTouchable); aParticleChange.AddSecondary( aNewTrack ); #ifdef debug G4cout<<"G4QCoherentChargeExchange::PostStepDoIt:*** PostStepDoIt is done ***"<GetCrossSection(true, p, Z, N, pPDG); // XS for isotope res*=qfMan->ChExElCoef(p*MeV, Z, N, pPDG); } else if(!oxs && xst) // Calculate Cross-Section & prepare differential { res=CSmanager->GetCrossSection(false, p, Z, N, pPDG);// XS for isotope + init t-distr. res*=qfMan->ChExElCoef(p*MeV, Z, N, pPDG); // The XS for the nucleus must be calculated the last init=true; } else if(init) // Return t-value for scattering (=G4QElastic) { if(oxs) res=CSmanager->GetHMaxT(); // Calculate the max_t value else res=CSmanager->GetExchangeT(Z, N, pPDG); // fanctionally randomized -t in MeV^2 } else G4cout<<"*Warning*G4QCohChrgExchange::CalculateXSt: NotInitiatedScattering"<