Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4QCoherentChargeExchange.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26// $Id$
27//
28// ---------------- G4QCoherentChargeExchange class -----------------
29// by Mikhail Kossov, December 2003.
30// G4QCoherentChargeExchange class of the CHIPS Simulation Branch in GEANT4
31// ---------------------------------------------------------------
32// ****************************************************************************************
33// ********** This CLASS is temporary moved from the photolepton_hadron directory *********
34// ****************************************************************************************
35// Short description: This class resolves an ambiguity in the definition of the
36// "inelastic" cross section. As it was shown in Ph.D.Thesis (M.Kosov,ITEP,1979)
37// it is more reasonable to subdivide the total cross-section in the coherent &
38// incoherent parts, but the measuring method for the "inelastic" cross-sections
39// consideres the lack of the projectile within the narrow forward solid angle
40// with the consequent extrapolation of these partial cross-sections, corresponding
41// to the particular solid angle, to the zero solid angle. The low angle region
42// is shadowed by the elastic (coherent) scattering. BUT the coherent charge
43// exchange (e.g. conversion p->n) is included by this procedure as a constant term
44// in the extrapolation, so the "inelastic" cross-section differes from the
45// incoherent cross-section by the value of the coherent charge exchange cross
46// section. Fortunately, this cross-sectoion drops ruther fast with energy increasing.
47// All Geant4 inelastic hadronic models (including CHIPS) simulate the incoherent
48// reactions. So the incoherent (including quasielastic) cross-section must be used
49// instead of the inelastic cross-section. For that the "inelastic" cross-section
50// must be reduced by the value of the coherent charge-exchange cross-section, which
51// is estimated (it must be tuned!) in this CHIPS class. The angular distribution
52// is made (at present) identical to the corresponding coherent-elastic scattering
53// -----------------------------------------------------------------------------------
54//#define debug
55//#define pdebug
56//#define tdebug
57//#define nandebug
58//#define ppdebug
59
61#include "G4SystemOfUnits.hh"
63
64
65// Initialization of static vectors
66//G4int G4QCoherentChargeExchange::nPartCWorld=152;// #of particles initialized in CHIPS
67//G4int G4QCoherentChargeExchange::nPartCWorld=122;// #of particles initialized in CHIPS
68G4int G4QCoherentChargeExchange::nPartCWorld=85;// #of particles initialized in CHIPSRed
69std::vector<G4int> G4QCoherentChargeExchange::ElementZ; // Z of element(i) in theLastCalc
70std::vector<G4double> G4QCoherentChargeExchange::ElProbInMat; // SumProbOfElem in Material
71std::vector<std::vector<G4int>*> G4QCoherentChargeExchange::ElIsoN;// N of isotope(j), E(i)
72std::vector<std::vector<G4double>*>G4QCoherentChargeExchange::IsoProbInEl;//SumProbIsotE(i)
73
74// Constructor
76 : G4VDiscreteProcess(processName, fHadronic)
77{
78 G4HadronicDeprecate("G4QCoherentChargeExchange");
79
80#ifdef debug
81 G4cout<<"G4QCohChargeEx::Constructor is called processName="<<processName<<G4endl;
82#endif
83 if (verboseLevel>0) G4cout << GetProcessName() << " process is created "<< G4endl;
84 //G4QCHIPSWorld::Get()->GetParticles(nPartCWorld); // Create CHIPS World (234 part. max)
85}
86
87// Destructor
89
90
92 {return EnMomConservation;}
93
95
96// output of the function must be in units of length! L=1/sig_V,sig_V=SUM(n(j,i)*sig(j,i)),
97// where n(i,j) is a number of nuclei of the isotop j of the element i in V=1(lengtUnit^3)
98// ********** All CHIPS cross sections are calculated in the surface units ************
101{
102 *Fc = NotForced;
103 const G4DynamicParticle* incidentParticle = aTrack.GetDynamicParticle();
104 G4ParticleDefinition* incidentParticleDefinition=incidentParticle->GetDefinition();
105 if( !IsApplicable(*incidentParticleDefinition))
106 G4cout<<"*W*G4QCohChargeEx::GetMeanFreePath called for notImplementedParticle"<<G4endl;
107 // Calculate the mean Cross Section for the set of Elements(*Isotopes) in the Material
108 G4double Momentum = incidentParticle->GetTotalMomentum(); // 3-momentum of the Particle
109#ifdef debug
110 G4double KinEn = incidentParticle->GetKineticEnergy();
111 G4cout<<"G4QCohChEx::GetMeanFreePath: kinE="<<KinEn<<",Mom="<<Momentum<<G4endl; // Result
112#endif
113 const G4Material* material = aTrack.GetMaterial(); // Get the current material
114 const G4double* NOfNucPerVolume = material->GetVecNbOfAtomsPerVolume();
115 const G4ElementVector* theElementVector = material->GetElementVector();
116 G4int nE=material->GetNumberOfElements();
117#ifdef debug
118 G4cout<<"G4QCohChargeExchange::GetMeanFreePath:"<<nE<<" Elem's in theMaterial"<<G4endl;
119#endif
120 G4int pPDG=0;
121
122 if (incidentParticleDefinition == G4Proton::Proton() ) pPDG=2212;
123 else if(incidentParticleDefinition == G4Neutron::Neutron()) pPDG=2112;
124 else G4cout<<"G4QCohChargeEx::GetMeanFreePath: only nA & pA are implemented"<<G4endl;
125
126 G4QIsotope* Isotopes = G4QIsotope::Get(); // Pointer to the G4QIsotopes singleton
127 G4double sigma=0.; // Sums over elements for the material
128 G4int IPIE=IsoProbInEl.size(); // How many old elements?
129 if(IPIE) for(G4int ip=0; ip<IPIE; ++ip) // Clean up the SumProb's of Isotopes (SPI)
130 {
131 std::vector<G4double>* SPI=IsoProbInEl[ip]; // Pointer to the SPI vector
132 SPI->clear();
133 delete SPI;
134 std::vector<G4int>* IsN=ElIsoN[ip]; // Pointer to the N vector
135 IsN->clear();
136 delete IsN;
137 }
138 ElProbInMat.clear(); // Clean up the SumProb's of Elements (SPE)
139 ElementZ.clear(); // Clear the body vector for Z of Elements
140 IsoProbInEl.clear(); // Clear the body vector for SPI
141 ElIsoN.clear(); // Clear the body vector for N of Isotopes
142 for(G4int i=0; i<nE; ++i)
143 {
144 G4Element* pElement=(*theElementVector)[i]; // Pointer to the current element
145 G4int Z = static_cast<G4int>(pElement->GetZ()); // Z of the Element
146 ElementZ.push_back(Z); // Remember Z of the Element
147 G4int isoSize=0; // The default for the isoVectorLength is 0
148 G4int indEl=0; // Index of non-natural element or 0(default)
149 G4IsotopeVector* isoVector=pElement->GetIsotopeVector(); // Get the predefined IsoVect
150 if(isoVector) isoSize=isoVector->size();// Get size of the existing isotopeVector
151#ifdef debug
152 G4cout<<"G4QCoherentChargeExchange::GetMeanFreePath:isovectorLength="<<isoSize<<G4endl;
153#endif
154 if(isoSize) // The Element has non-trivial abundance set
155 {
156 indEl=pElement->GetIndex()+1; // Index of the non-trivial element is an order
157#ifdef debug
158 G4cout<<"G4QCCX::GetMFP: iE="<<indEl<<", def="<<Isotopes->IsDefined(Z,indEl)<<G4endl;
159#endif
160 if(!Isotopes->IsDefined(Z,indEl)) // This index is not defined for this Z: define
161 {
162 std::vector<std::pair<G4int,G4double>*>* newAbund =
163 new std::vector<std::pair<G4int,G4double>*>;
164 G4double* abuVector=pElement->GetRelativeAbundanceVector();
165 for(G4int j=0; j<isoSize; j++) // Calculation of abundance vector for isotopes
166 {
167 G4int N=pElement->GetIsotope(j)->GetN()-Z; // N means A=N+Z !
168 if(pElement->GetIsotope(j)->GetZ()!=Z)G4cerr<<"G4QCohChX::GetMeanFreePath: Z="
169 <<pElement->GetIsotope(j)->GetZ()<<"#"<<Z<<G4endl;
170 G4double abund=abuVector[j];
171 std::pair<G4int,G4double>* pr= new std::pair<G4int,G4double>(N,abund);
172#ifdef debug
173 G4cout<<"G4QCohChEx::GetMeanFreePath:pair#="<<j<<",N="<<N<<",ab="<<abund<<G4endl;
174#endif
175 newAbund->push_back(pr);
176 }
177#ifdef debug
178 G4cout<<"G4QCohChEx::GetMeanFreePath: pairVectorLength="<<newAbund->size()<<G4endl;
179#endif
180 indEl=G4QIsotope::Get()->InitElement(Z,indEl,newAbund); // definition of the newInd
181 for(G4int k=0; k<isoSize; k++) delete (*newAbund)[k]; // Cleaning temporary
182 delete newAbund; // Was "new" in the beginning of the name space
183 }
184 }
185 std::vector<std::pair<G4int,G4double>*>* cs= Isotopes->GetCSVector(Z,indEl);//CSPointer
186 std::vector<G4double>* SPI = new std::vector<G4double>; // Pointer to the SPI vector
187 IsoProbInEl.push_back(SPI);
188 std::vector<G4int>* IsN = new std::vector<G4int>; // Pointer to the N vector
189 ElIsoN.push_back(IsN);
190 G4int nIs=cs->size(); // A#Of Isotopes in the Element
191#ifdef debug
192 G4cout<<"G4QCohChargEx::GMFP:=***=>,#isot="<<nIs<<", Z="<<Z<<", indEl="<<indEl<<G4endl;
193#endif
194 G4double susi=0.; // sum of CS over isotopes
195 if(nIs) for(G4int j=0; j<nIs; j++) // Calculate CS for eachIsotope of El
196 {
197 std::pair<G4int,G4double>* curIs=(*cs)[j]; // A pointer, which is used twice
198 G4int N=curIs->first; // #of Neuterons in the isotope j of El i
199 IsN->push_back(N); // Remember Min N for the Element
200#ifdef debug
201 G4cout<<"G4QCCX::GMFP:true, P="<<Momentum<<",Z="<<Z<<",N="<<N<<",PDG="<<pPDG<<G4endl;
202#endif
203 G4bool ccsf=true;
204 if(Q==-27.) ccsf=false;
205#ifdef debug
206 G4cout<<"G4QCoherentChargeExchange::GMFP: GetCS #1 j="<<j<<G4endl;
207#endif
208 G4double CSI=CalculateXSt(ccsf, true, Momentum, Z, N, pPDG);// CS(j,i) for theIsotope
209
210#ifdef debug
211 G4cout<<"G4QCohChEx::GetMeanFreePath:jI="<<j<<",Zt="<<Z<<",Nt="<<N<<",Mom="<<Momentum
212 <<", XSec="<<CSI/millibarn<<G4endl;
213#endif
214 curIs->second = CSI;
215 susi+=CSI; // Make a sum per isotopes
216 SPI->push_back(susi); // Remember summed cross-section
217 } // End of temporary initialization of the cross sections in the G4QIsotope singeltone
218 sigma+=Isotopes->GetMeanCrossSection(Z,indEl)*NOfNucPerVolume[i];//SUM(MeanCS*NOfNperV)
219#ifdef debug
220 G4cout<<"G4QCohChEx::GMFP:<S>="<<Isotopes->GetMeanCrossSection(Z,indEl)<<",AddToSigma="
221 <<Isotopes->GetMeanCrossSection(Z,indEl)*NOfNucPerVolume[i]<<G4endl;
222#endif
223 ElProbInMat.push_back(sigma);
224 } // End of LOOP over Elements
225 // Check that cross section is not zero and return the mean free path
226#ifdef debug
227 G4cout<<"G4QCoherentChargeExchange::GetMeanFreePath: MeanFreePath="<<1./sigma<<G4endl;
228#endif
229 if(sigma > 0.) return 1./sigma; // Mean path [distance]
230 return DBL_MAX;
231}
232
234{
235 if (particle == *( G4Proton::Proton() )) return true;
236 else if (particle == *( G4Neutron::Neutron() )) return true;
237 //else if (particle == *( G4MuonMinus::MuonMinus() )) return true;
238 //else if (particle == *( G4TauPlus::TauPlus() )) return true;
239 //else if (particle == *( G4TauMinus::TauMinus() )) return true;
240 //else if (particle == *( G4Electron::Electron() )) return true;
241 //else if (particle == *( G4Positron::Positron() )) return true;
242 //else if (particle == *( G4Gamma::Gamma() )) return true;
243 //else if (particle == *( G4MuonPlus::MuonPlus() )) return true;
244 //else if (particle == *(G4AntiNeutrinoMu::AntiNeutrinoMu())) return true;
245 //else if (particle == *( G4NeutrinoMu::NeutrinoMu() )) return true;
246 //else if (particle == *( G4PionMinus::PionMinus() )) return true;
247 //else if (particle == *( G4PionPlus::PionPlus() )) return true;
248 //else if (particle == *( G4KaonPlus::KaonPlus() )) return true;
249 //else if (particle == *( G4KaonMinus::KaonMinus() )) return true;
250 //else if (particle == *( G4KaonZeroLong::KaonZeroLong() )) return true;
251 //else if (particle == *( G4KaonZeroShort::KaonZeroShort() )) return true;
252 //else if (particle == *( G4Lambda::Lambda() )) return true;
253 //else if (particle == *( G4SigmaPlus::SigmaPlus() )) return true;
254 //else if (particle == *( G4SigmaMinus::SigmaMinus() )) return true;
255 //else if (particle == *( G4SigmaZero::SigmaZero() )) return true;
256 //else if (particle == *( G4XiMinus::XiMinus() )) return true;
257 //else if (particle == *( G4XiZero::XiZero() )) return true;
258 //else if (particle == *( G4OmegaMinus::OmegaMinus() )) return true;
259 //else if (particle == *( G4AntiNeutron::AntiNeutron() )) return true;
260 //else if (particle == *( G4AntiProton::AntiProton() )) return true;
261#ifdef debug
262 G4cout<<"***>>G4QCoherChargeExch::IsApplicable: PDG="<<particle.GetPDGEncoding()<<G4endl;
263#endif
264 return false;
265}
266
268 const G4Step& step)
269{
270 static const G4double mProt= G4QPDGCode(2212).GetMass(); // CHIPS pMass in MeV
271 static const G4double mNeut= G4QPDGCode(2212).GetMass(); // CHIPS pMass in MeV
272 //
273 //-------------------------------------------------------------------------------------
274 static G4bool CWinit = true; // CHIPS Warld needs to be initted
275 if(CWinit)
276 {
277 CWinit=false;
278 G4QCHIPSWorld::Get()->GetParticles(nPartCWorld); // Create CHIPS World (234 part.max)
279 }
280 //-------------------------------------------------------------------------------------
281 const G4DynamicParticle* projHadron = track.GetDynamicParticle();
282 const G4ParticleDefinition* particle=projHadron->GetDefinition();
283#ifdef debug
284 G4cout<<"G4QCohChargeExchange::PostStepDoIt: Before the GetMeanFreePath is called In4M="
285 <<projHadron->Get4Momentum()<<" of PDG="<<particle->GetPDGEncoding()<<", Type="
286 <<particle->GetParticleType()<<", Subtp="<<particle->GetParticleSubType()<<G4endl;
287#endif
289 GetMeanFreePath(track, -27., &cond); // @@ ?? jus to update parameters?
290#ifdef debug
291 G4cout<<"G4QCohChargeExchange::PostStepDoIt: After GetMeanFreePath is called"<<G4endl;
292#endif
293 G4LorentzVector proj4M=(projHadron->Get4Momentum())/MeV; // Convert to MeV!
294 G4double momentum = projHadron->GetTotalMomentum()/MeV; // 3-momentum of the Proj in MeV
295 G4double Momentum = proj4M.rho(); // @@ Just for the test purposes
296 if(std::fabs(Momentum-momentum)>.000001)
297 G4cerr<<"*Warning*G4QCohChEx::PostStepDoIt:P(IU)="<<Momentum<<"#"<<momentum<<G4endl;
298#ifdef pdebug
299 G4cout<<"G4QCoherentChargeExchange::PostStepDoIt: pP(IU)="<<Momentum<<"="<<momentum
300 <<",pM="<<pM<<",proj4M="<<proj4M<<proj4M.m()<<G4endl;
301#endif
302 if (!IsApplicable(*particle)) // Check applicability
303 {
304 G4cerr<<"G4QCoherentChargeExchange::PostStepDoIt: Only NA is implemented."<<G4endl;
305 return 0;
306 }
307 const G4Material* material = track.GetMaterial(); // Get the current material
308 G4int Z=0;
309 const G4ElementVector* theElementVector = material->GetElementVector();
310 G4int nE=material->GetNumberOfElements();
311#ifdef debug
312 G4cout<<"G4QCohChargeExchange::PostStepDoIt: "<<nE<<" elements in the material."<<G4endl;
313#endif
314 G4int projPDG=0; // PDG Code prototype for the captured hadron
315 // Not all these particles are implemented yet (see Is Applicable)
316 if (particle == G4Proton::Proton() ) projPDG= 2212;
317 else if (particle == G4Neutron::Neutron() ) projPDG= 2112;
318 //else if (particle == G4PionMinus::PionMinus() ) projPDG= -211;
319 //else if (particle == G4PionPlus::PionPlus() ) projPDG= 211;
320 //else if (particle == G4KaonPlus::KaonPlus() ) projPDG= 2112;
321 //else if (particle == G4KaonMinus::KaonMinus() ) projPDG= -321;
322 //else if (particle == G4KaonZeroLong::KaonZeroLong() ) projPDG= 130;
323 //else if (particle == G4KaonZeroShort::KaonZeroShort() ) projPDG= 310;
324 //else if (particle == G4MuonPlus::MuonPlus() ) projPDG= -13;
325 //else if (particle == G4MuonMinus::MuonMinus() ) projPDG= 13;
326 //else if (particle == G4NeutrinoMu::NeutrinoMu() ) projPDG= 14;
327 //else if (particle == G4AntiNeutrinoMu::AntiNeutrinoMu() ) projPDG= -14;
328 //else if (particle == G4Electron::Electron() ) projPDG= 11;
329 //else if (particle == G4Positron::Positron() ) projPDG= -11;
330 //else if (particle == G4NeutrinoE::NeutrinoE() ) projPDG= 12;
331 //else if (particle == G4AntiNeutrinoE::AntiNeutrinoE() ) projPDG= -12;
332 //else if (particle == G4Gamma::Gamma() ) projPDG= 22;
333 //else if (particle == G4TauPlus::TauPlus() ) projPDG= -15;
334 //else if (particle == G4TauMinus::TauMinus() ) projPDG= 15;
335 //else if (particle == G4NeutrinoTau::NeutrinoTau() ) projPDG= 16;
336 //else if (particle == G4AntiNeutrinoTau::AntiNeutrinoTau()) projPDG= -16;
337 //else if (particle == G4Lambda::Lambda() ) projPDG= 3122;
338 //else if (particle == G4SigmaPlus::SigmaPlus() ) projPDG= 3222;
339 //else if (particle == G4SigmaMinus::SigmaMinus() ) projPDG= 3112;
340 //else if (particle == G4SigmaZero::SigmaZero() ) projPDG= 3212;
341 //else if (particle == G4XiMinus::XiMinus() ) projPDG= 3312;
342 //else if (particle == G4XiZero::XiZero() ) projPDG= 3322;
343 //else if (particle == G4OmegaMinus::OmegaMinus() ) projPDG= 3334;
344 //else if (particle == G4AntiNeutron::AntiNeutron() ) projPDG=-2112;
345 //else if (particle == G4AntiProton::AntiProton() ) projPDG=-2212;
346#ifdef debug
347 G4int prPDG=particle->GetPDGEncoding();
348 G4cout<<"G4QCohChrgExchange::PostStepDoIt: projPDG="<<projPDG<<", stPDG="<<prPDG<<G4endl;
349#endif
350 if(!projPDG)
351 {
352 G4cerr<<"*Warning*G4QCoherentChargeExchange::PostStepDoIt:UndefinedProjHadron"<<G4endl;
353 return 0;
354 }
355 //G4double pM2=proj4M.m2(); // in MeV^2
356 //G4double pM=std::sqrt(pM2); // in MeV
357 G4double pM=mNeut;
358 if(projPDG==2112) pM=mProt;
359 G4double pM2=pM*pM;
360 // Element treatment
361 G4int EPIM=ElProbInMat.size();
362#ifdef debug
363 G4cout<<"G4QCohChEx::PostStDoIt:m="<<EPIM<<",n="<<nE<<",T="<<ElProbInMat[EPIM-1]<<G4endl;
364#endif
365 G4int i=0;
366 if(EPIM>1)
367 {
368 G4double rnd = ElProbInMat[EPIM-1]*G4UniformRand();
369 for(i=0; i<nE; ++i)
370 {
371#ifdef debug
372 G4cout<<"G4QCohChEx::PostStepDoIt:EPM["<<i<<"]="<<ElProbInMat[i]<<",r="<<rnd<<G4endl;
373#endif
374 if (rnd<ElProbInMat[i]) break;
375 }
376 if(i>=nE) i=nE-1; // Top limit for the Element
377 }
378 G4Element* pElement=(*theElementVector)[i];
379 Z=static_cast<G4int>(pElement->GetZ());
380#ifdef debug
381 G4cout<<"G4QCoherentChargeExchange::PostStepDoIt: i="<<i<<", Z(element)="<<Z<<G4endl;
382#endif
383 if(Z<=0)
384 {
385 G4cerr<<"-Warning-G4QCoherentChargeExchange::PostStepDoIt: Element with Z="<<Z<<G4endl;
386 if(Z<0) return 0;
387 }
388 std::vector<G4double>* SPI = IsoProbInEl[i];// Vector of summedProbabilities for isotopes
389 std::vector<G4int>* IsN = ElIsoN[i]; // Vector of "#of neutrons" in the isotope El[i]
390 G4int nofIsot=SPI->size(); // #of isotopes in the element i
391#ifdef debug
392 G4cout<<"G4QCohChargeExchange::PosStDoIt:nI="<<nofIsot<<",T="<<(*SPI)[nofIsot-1]<<G4endl;
393#endif
394 G4int j=0;
395 if(nofIsot>1)
396 {
397 G4double rndI=(*SPI)[nofIsot-1]*G4UniformRand(); // Randomize the isotop of the Element
398 for(j=0; j<nofIsot; ++j)
399 {
400#ifdef debug
401 G4cout<<"G4QCohChargEx::PostStepDoIt: SP["<<j<<"]="<<(*SPI)[j]<<", r="<<rndI<<G4endl;
402#endif
403 if(rndI < (*SPI)[j]) break;
404 }
405 if(j>=nofIsot) j=nofIsot-1; // Top limit for the isotope
406 }
407 G4int N =(*IsN)[j]; ; // Randomized number of neutrons
408#ifdef debug
409 G4cout<<"G4QCohChargeEx::PostStepDoIt: j="<<i<<", N(isotope)="<<N<<", MeV="<<MeV<<G4endl;
410#endif
411 if(N<0)
412 {
413 G4cerr<<"*Warning*G4QCohChEx::PostStepDoIt: Isotope with Z="<<Z<<", 0>N="<<N<<G4endl;
414 return 0;
415 }
416 nOfNeutrons=N; // Remember it for the energy-momentum check
417#ifdef debug
418 G4cout<<"G4QCohChargeExchange::PostStepDoIt: N="<<N<<" for element with Z="<<Z<<G4endl;
419#endif
420 if(N<0)
421 {
422 G4cerr<<"*Warning*G4QCoherentChargeExchange::PostStepDoIt:Element with N="<<N<< G4endl;
423 return 0;
424 }
426#ifdef debug
427 G4cout<<"G4QCoherentChargeExchange::PostStepDoIt: track is initialized"<<G4endl;
428#endif
429 G4double weight = track.GetWeight();
430 G4double localtime = track.GetGlobalTime();
432#ifdef debug
433 G4cout<<"G4QCoherentChargeExchange::PostStepDoIt: before Touchable extraction"<<G4endl;
434#endif
435 G4TouchableHandle trTouchable = track.GetTouchableHandle();
436#ifdef debug
437 G4cout<<"G4QCoherentChargeExchange::PostStepDoIt: Touchable is extracted"<<G4endl;
438#endif
439 //
440 G4int targPDG=90000000+Z*1000+N; // CHIPS PDG Code of the target nucleus
441 if(projPDG==2212) targPDG+=999; // convert to final nucleus code
442 else if(projPDG==2112) targPDG-=999;
443 G4QPDGCode targQPDG(targPDG); // @@ use G4Ion and get rid of CHIPS World
444 G4double tM=targQPDG.GetMass(); // CHIPS final nucleus mass in MeV
445 G4double kinEnergy= projHadron->GetKineticEnergy()*MeV; // Kin energy in MeV (Is *MeV n?)
446 G4ParticleMomentum dir = projHadron->GetMomentumDirection();// It is a unit three-vector
447 G4LorentzVector tot4M=proj4M+G4LorentzVector(0.,0.,0.,tM); // Total 4-mom of the reaction
448#ifdef debug
449 G4cout<<"G4QCohChrgEx::PostStepDoIt: tM="<<tM<<", p4M="<<proj4M<<", t4M="<<tot4M<<G4endl;
450#endif
451 EnMomConservation=tot4M; // Total 4-mom of reaction for E/M conservation
452 // @@ Probably this is not necessary any more
453#ifdef debug
454 G4cout<<"G4QCCX::PSDI:false, P="<<Momentum<<",Z="<<Z<<",N="<<N<<",PDG="<<projPDG<<G4endl;
455#endif
456 G4double xSec=CalculateXSt(false, true, Momentum, Z, N, projPDG); // Recalc. CrossSection
457#ifdef debug
458 G4cout<<"G4QCoChEx::PSDI:PDG="<<projPDG<<",P="<<Momentum<<",CS="<<xSec/millibarn<<G4endl;
459#endif
460#ifdef nandebug
461 if(xSec>0. || xSec<0. || xSec==0);
462 else G4cout<<"*Warning*G4QCohChargeExchange::PSDI: xSec="<<xSec/millibarn<<G4endl;
463#endif
464 // @@ check a possibility to separate p, n, or alpha (!)
465 if(xSec <= 0.) // The cross-section iz 0 -> Do Nothing
466 {
467#ifdef pdebug
468 G4cerr<<"*Warning*G4QCoherentChargeExchange::PSDoIt:*Zero cross-section* PDG="<<projPDG
469 <<",tPDG="<<targPDG<<",P="<<Momentum<<G4endl;
470#endif
471 //Do Nothing Action insead of the reaction
475 return G4VDiscreteProcess::PostStepDoIt(track,step);
476 }
477 G4double mint=CalculateXSt(false, false, Momentum, Z, N, projPDG);// randomize t in MeV^2
478#ifdef pdebug
479 G4cout<<"G4QCohChEx::PoStDoIt:pPDG="<<projPDG<<",tPDG="<<targPDG<<",P="<<Momentum<<",CS="
480 <<xSec<<",-t="<<mint<<G4endl;
481#endif
482#ifdef nandebug
483 if(mint>-.0000001);
484 else G4cout<<"*Warning*G4QCoherentChargeExchange::PostStDoIt:-t="<<mint<<G4endl;
485#endif
486 G4double maxt=CalculateXSt(true, false, Momentum, Z, N, projPDG);
487 if(maxt<=0.) maxt=1.e-27;
488 G4double cost=1.-mint/maxt; // cos(theta) in CMS (@@ we neglect mass diff for ChEx)
489 //
490#ifdef ppdebug
491 G4cout<<"G4QCoherentChargeExchange::PoStDoIt:t="<<mint<<",dpcm2="<<maxt
492 <<",Ek="<<kinEnergy<<",tM="<<tM<<",pM="<<pM<<",cost="<<cost<<G4endl;
493#endif
494 if(cost>1. || cost<-1. || !(cost>-1. || cost<1.))
495 {
496 if(cost>1.000001 || cost<-1.000001 || !(cost>-1. || cost<1.))
497 {
498 G4double tM2=tM*tM; // Squared target mass
499 G4double pEn=pM+kinEnergy; // tot projectile Energy in MeV
500 G4double sM=(tM+tM)*pEn+tM2+pM2; // Mondelstam s
501 G4double twop2cm=(tM2+tM2)*(pEn*pEn-pM2)/sM;// Max_t/2 (2*p^2_cm)
502 G4cout<<"*Warning*G4QCohChEx::PostStepDoIt:cos="<<cost<<",t="<<mint<<",T="<<kinEnergy
503 <<",tM="<<tM<<",tmax="<<2*kinEnergy*tM<<",p="<<projPDG<<",t="<<targPDG<<G4endl;
504 G4cout<<"..G4QCohChEx::PoStDoI: dpcm2="<<twop2cm<<"="<<maxt<<G4endl;
505 }
506 if (cost>1.) cost=1.;
507 else if(cost<-1.) cost=-1.;
508 }
509 G4LorentzVector reco4M=G4LorentzVector(0.,0.,0.,tM); // 4mom of the recoil target
510 G4LorentzVector scat4M=G4LorentzVector(0.,0.,0.,pM); // 4mom of the recoil target
511 G4LorentzVector dir4M=tot4M-G4LorentzVector(0.,0.,0.,(tot4M.e()-tM-pM)*.01);
512 if(!G4QHadron(tot4M).RelDecayIn2(scat4M, reco4M, dir4M, cost, cost))
513 {
514 G4cerr<<"G4QCohChEx::PSDI:t4M="<<tot4M<<",pM="<<pM<<",tM="<<tM<<",cost="<<cost<<G4endl;
515 //G4Exception("G4QCoherentChargeExchange::PostStepDoIt:","009",FatalException,"Decay");
516 }
517#ifdef debug
518 G4cout<<"G4QCohChEx::PoStDoIt:s4M="<<scat4M<<"+r4M="<<reco4M<<"="<<scat4M+reco4M<<G4endl;
519 G4cout<<"G4QCohChEx::PoStDoIt: scatE="<<scat4M.e()-pM<<", recoE="<<reco4M.e()-tM<<",d4M="
520 <<tot4M-scat4M-reco4M<<G4endl;
521#endif
522 // Kill scattered hadron
524 // Definition of the scattered nucleon
525 G4DynamicParticle* theSec = new G4DynamicParticle; // A secondary for the recoil hadron
526 G4ParticleDefinition* theDefinition=G4Proton::Proton();
527 if(projPDG==2212) theDefinition=G4Neutron::Neutron();
528 theSec->SetDefinition(theDefinition);
529 EnMomConservation-=scat4M;
530 theSec->Set4Momentum(scat4M);
531 G4Track* aNewTrack = new G4Track(theSec, localtime, position );
532 aNewTrack->SetWeight(weight); // weighted
533 aNewTrack->SetTouchableHandle(trTouchable);
534 aParticleChange.AddSecondary( aNewTrack );
535 // Filling the recoil nucleus
536 theSec = new G4DynamicParticle; // A secondary for the recoil hadron
537 G4int aA = Z+N;
538#ifdef pdebug
539 G4cout<<"G4QCoherentChargeExchange::PostStepDoIt: Ion Z="<<Z<<", A="<<aA<<G4endl;
540#endif
541 theDefinition=G4ParticleTable::GetParticleTable()->FindIon(Z,aA,0,Z);
542 if(!theDefinition)G4cout<<"*Warning*G4QCohChEx::PostStepDoIt:drop PDG="<<targPDG<<G4endl;
543#ifdef pdebug
544 G4cout<<"G4QCohChEx::PostStepDoIt:RecoilName="<<theDefinition->GetParticleName()<<G4endl;
545#endif
546 theSec->SetDefinition(theDefinition);
547 EnMomConservation-=reco4M;
548#ifdef tdebug
549 G4cout<<"G4QCohChEx::PostSDoIt:"<<targPDG<<reco4M<<reco4M.m()<<EnMomConservation<<G4endl;
550#endif
551 theSec->Set4Momentum(reco4M);
552#ifdef debug
553 G4ThreeVector curD=theSec->GetMomentumDirection();
554 G4double curM=theSec->GetMass();
555 G4double curE=theSec->GetKineticEnergy()+curM;
556 G4cout<<"G4QCohChEx::PostStpDoIt:p="<<curD<<curD.mag()<<",e="<<curE<<",m="<<curM<<G4endl;
557#endif
558 // Make a recoil nucleus
559 aNewTrack = new G4Track(theSec, localtime, position );
560 aNewTrack->SetWeight(weight); // weighted
561 aNewTrack->SetTouchableHandle(trTouchable);
562 aParticleChange.AddSecondary( aNewTrack );
563#ifdef debug
564 G4cout<<"G4QCoherentChargeExchange::PostStepDoIt:*** PostStepDoIt is done ***"<<G4endl;
565#endif
566 return G4VDiscreteProcess::PostStepDoIt(track, step);
567}
568
569G4double G4QCoherentChargeExchange::CalculateXSt(G4bool oxs, G4bool xst, G4double p,
570 G4int Z, G4int N, G4int pPDG)
571{
572 static G4bool init=false;
573 static G4bool first=true;
574 static G4VQCrossSection* PCSmanager;
575 static G4VQCrossSection* NCSmanager;
577 if(first) // Connection with a singletone
578 {
581 first=false;
582 }
583 G4double res=0.;
584 if(oxs && xst) // Only the Cross-Section can be returened
585 {
586 if(pPDG==2212) res=PCSmanager->GetCrossSection(true, p, Z, N, pPDG); // XS for isotope
587 else res=NCSmanager->GetCrossSection(true, p, Z, N, pPDG); // XS for isotope
588 res*=qfMan->ChExElCoef(p*MeV, Z, N, pPDG);
589 }
590 else if(!oxs && xst) // Calculate CrossSection & prepare differentialCS
591 {
592 if(pPDG==2212) res=PCSmanager->GetCrossSection(false, p, Z, N, pPDG);// XS+init t-distr
593 else res=NCSmanager->GetCrossSection(false, p, Z, N, pPDG);// XS+init t-distr
594 res*=qfMan->ChExElCoef(p*MeV, Z, N, pPDG);
595 // The XS for the nucleus must be calculated the last
596 init=true;
597 }
598 else if(init) // Return t-value for scattering (=G4QElastic)
599 {
600 if(pPDG==2212) // ===> Protons
601 {
602 if(oxs) res=PCSmanager->GetHMaxT(); // Calculate the max_t value
603 else res=PCSmanager->GetExchangeT(Z, N, pPDG); // fanctionally randomized -t in MeV^2
604 }
605 else // ==> Neutrons
606 {
607 if(oxs) res=NCSmanager->GetHMaxT(); // Calculate the max_t value
608 else res=NCSmanager->GetExchangeT(Z, N, pPDG); // fanctionally randomized -t in MeV^2
609 }
610 }
611 else G4cout<<"*Warning*G4QCohChrgExchange::CalculateXSt: NotInitiatedScattering"<<G4endl;
612 return res;
613}
std::vector< G4Element * > G4ElementVector
G4ForceCondition
@ NotForced
#define G4HadronicDeprecate(name)
std::vector< G4Isotope * > G4IsotopeVector
CLHEP::HepLorentzVector G4LorentzVector
@ fHadronic
@ fStopAndKill
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
bool G4bool
Definition: G4Types.hh:67
#define G4endl
Definition: G4ios.hh:52
G4DLLIMPORT std::ostream G4cerr
G4DLLIMPORT std::ostream G4cout
#define G4UniformRand()
Definition: Randomize.hh:53
double mag() const
G4double GetMass() const
const G4ThreeVector & GetMomentumDirection() const
void SetDefinition(const G4ParticleDefinition *aParticleDefinition)
G4ParticleDefinition * GetDefinition() const
G4LorentzVector Get4Momentum() const
G4double GetKineticEnergy() const
void Set4Momentum(const G4LorentzVector &momentum)
G4double GetTotalMomentum() const
G4double * GetRelativeAbundanceVector() const
Definition: G4Element.hh:166
G4double GetZ() const
Definition: G4Element.hh:131
const G4Isotope * GetIsotope(G4int iso) const
Definition: G4Element.hh:169
size_t GetIndex() const
Definition: G4Element.hh:182
G4IsotopeVector * GetIsotopeVector() const
Definition: G4Element.hh:162
G4int GetZ() const
Definition: G4Isotope.hh:91
G4int GetN() const
Definition: G4Isotope.hh:94
const G4ElementVector * GetElementVector() const
Definition: G4Material.hh:189
size_t GetNumberOfElements() const
Definition: G4Material.hh:185
const G4double * GetVecNbOfAtomsPerVolume() const
Definition: G4Material.hh:205
static G4Neutron * Neutron()
Definition: G4Neutron.cc:104
void AddSecondary(G4Track *aSecondary)
void ProposeEnergy(G4double finalEnergy)
void ProposeMomentumDirection(G4double Px, G4double Py, G4double Pz)
virtual void Initialize(const G4Track &)
const G4String & GetParticleType() const
const G4String & GetParticleName() const
const G4String & GetParticleSubType() const
G4ParticleDefinition * FindIon(G4int atomicNumber, G4int atomicMass, G4double excitationEnergy)
static G4ParticleTable * GetParticleTable()
static G4Proton * Proton()
Definition: G4Proton.cc:93
static G4QCHIPSWorld * Get()
G4QParticleVector * GetParticles(G4int nOfParts=0)
G4double GetMeanFreePath(const G4Track &aTrack, G4double previousStepSize, G4ForceCondition *condition)
G4QCoherentChargeExchange(const G4String &processName="CHIPS_CoherChargeExScattering")
G4bool IsApplicable(const G4ParticleDefinition &particle)
G4VParticleChange * PostStepDoIt(const G4Track &aTrack, const G4Step &aStep)
G4LorentzVector GetEnegryMomentumConservation()
std::vector< std::pair< G4int, G4double > * > * GetCSVector(G4int Z, G4int index=0)
Definition: G4QIsotope.cc:1737
G4bool IsDefined(G4int Z, G4int Ind)
Definition: G4QIsotope.cc:1660
G4double GetMeanCrossSection(G4int Z, G4int index=0)
Definition: G4QIsotope.cc:1842
static G4QIsotope * Get()
Definition: G4QIsotope.cc:720
G4int InitElement(G4int Z, G4int index, std::vector< std::pair< G4int, G4double > * > *abund)
Definition: G4QIsotope.cc:1557
G4double GetMass()
Definition: G4QPDGCode.cc:693
static G4VQCrossSection * GetPointer()
G4double ChExElCoef(G4double p, G4int Z, G4int N, G4int pPDG)
static G4QuasiFreeRatios * GetPointer()
Definition: G4Step.hh:78
G4double GetWeight() const
void SetWeight(G4double aValue)
const G4ThreeVector & GetPosition() const
void SetTouchableHandle(const G4TouchableHandle &apValue)
G4double GetGlobalTime() const
G4Material * GetMaterial() const
const G4DynamicParticle * GetDynamicParticle() const
const G4TouchableHandle & GetTouchableHandle() const
virtual G4VParticleChange * PostStepDoIt(const G4Track &, const G4Step &)
void ProposeTrackStatus(G4TrackStatus status)
void ProposeLocalEnergyDeposit(G4double anEnergyPart)
G4ParticleChange aParticleChange
Definition: G4VProcess.hh:289
G4int verboseLevel
Definition: G4VProcess.hh:368
const G4String & GetProcessName() const
Definition: G4VProcess.hh:379
virtual G4double GetExchangeT(G4int tZ, G4int tN, G4int pPDG)
virtual G4double GetCrossSection(G4bool, G4double, G4int, G4int, G4int pPDG=0)
virtual G4double GetHMaxT()
#define DBL_MAX
Definition: templates.hh:83