Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4QIonIonElastic.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// ---------------- G4QIonIonElastic class -----------------
29// by Mikhail Kossov, December 2006.
30// G4QIonIonElastic 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: a simple process for the Ion-Ion elastic scattering.
36// For heavy by heavy ions it can reach 50% of the total cross-section.
37// -----------------------------------------------------------------------
38
39//#define debug
40//#define pdebug
41//#define tdebug
42//#define nandebug
43//#define ppdebug
44
45#include "G4QIonIonElastic.hh"
46#include "G4SystemOfUnits.hh"
48
49
50// Initialization of static vectors
51//G4int G4QIonIonElastic::nPartCWorld=152; // The#of particles initialized in CHIPS World
52//G4int G4QIonIonElastic::nPartCWorld=122; // The#of particles initialized in CHIPS World
53G4int G4QIonIonElastic::nPartCWorld=85; // The#of particles initialized in CHIPS World Red.
54std::vector<G4int> G4QIonIonElastic::ElementZ; // Z of the element(i) in theLastCalc
55std::vector<G4double> G4QIonIonElastic::ElProbInMat; // SumProbabilityElements in Material
56std::vector<std::vector<G4int>*> G4QIonIonElastic::ElIsoN; // N of isotope(j) of Element(i)
57std::vector<std::vector<G4double>*>G4QIonIonElastic::IsoProbInEl;//SumProbabIsotopes in ElI
58
59// Constructor
61 G4VDiscreteProcess(processName, fHadronic)
62{
63 G4HadronicDeprecate("G4QIonIonElastic");
64
65#ifdef debug
66 G4cout<<"G4QIonIonElastic::Constructor is called processName="<<processName<<G4endl;
67#endif
68 if (verboseLevel>0) G4cout << GetProcessName() << " process is created "<< G4endl;
69 //G4QCHIPSWorld::Get()->GetParticles(nPartCWorld); // Create CHIPS World (234 part. max)
70}
71
72// Destructor
74
75// output of the function must be in units of length! L=1/sig_V,sig_V=SUM(n(j,i)*sig(j,i)),
76// where n(i,j) is a number of nuclei of the isotop j of the element i in V=1(lengtUnit^3)
77// ********** All CHIPS cross sections are calculated in the surface units ************
80{
81 static const G4double mProt = G4QPDGCode(2212).GetMass()/MeV;// CHIPS proton Mass in MeV
82 *Fc = NotForced;
83 const G4DynamicParticle* incidentParticle = aTrack.GetDynamicParticle();
84 G4ParticleDefinition* incidentParticleDefinition=incidentParticle->GetDefinition();
85 if( !IsApplicable(*incidentParticleDefinition))
86 G4cout<<"-Warning-G4QIonIonElastic::GetMeanFreePath: notImplementedParticle"<<G4endl;
87 // Calculate the mean Cross Section for the set of Elements(*Isotopes) in the Material
88 G4double Momentum = incidentParticle->GetTotalMomentum(); // 3-momentum of the Particle
89#ifdef debug
90 G4double KinEn = incidentParticle->GetKineticEnergy();
91 G4cout<<"G4QIonIonElastic::GetMeanFreePath: kinE="<<KinEn<<",Mom="<<Momentum<<G4endl;
92#endif
93 const G4Material* material = aTrack.GetMaterial(); // Get the current material
94 const G4double* NOfNucPerVolume = material->GetVecNbOfAtomsPerVolume();
95 const G4ElementVector* theElementVector = material->GetElementVector();
96 G4int nE=material->GetNumberOfElements();
97#ifdef debug
98 G4cout<<"G4QIonIonElastic::GetMeanFreePath:"<<nE<<" Elem's in theMaterial"<<G4endl;
99#endif
102 G4int pPDG=0;
103 // Probably enough: pPDG=incidentParticleDefinition->GetPDGEncoding();
104 G4int pZ=static_cast<G4int>(incidentParticleDefinition->GetPDGCharge());
105 G4int pA=incidentParticleDefinition->GetBaryonNumber();
106 if (incidentParticleDefinition == G4Deuteron::Deuteron() ) pPDG = 1000010020;
107 else if (incidentParticleDefinition == G4Alpha::Alpha() ) pPDG = 1000020040;
108 else if (incidentParticleDefinition == G4Triton::Triton() ) pPDG = 1000010030;
109 else if (incidentParticleDefinition == G4He3::He3() ) pPDG = 1000020030;
110 else if (incidentParticleDefinition == G4GenericIon::GenericIon() || (pZ > 0 && pA > 0))
111 {
112 pPDG=incidentParticleDefinition->GetPDGEncoding();
113#ifdef debug
114 G4int prPDG=1000000000+10000*pZ+10*pA;
115 G4cout<<"G4QIonIonElastic::GetMeanFreePath: PDG="<<prPDG<<"="<<pPDG<<G4endl;
116#endif
117 }
118 else G4cout<<"-Warning-G4QIonIonElastic::GetMeanFreePath:Unknown projectile Ion"<<G4endl;
119 Momentum/=incidentParticleDefinition->GetBaryonNumber(); // Divide Mom by projectile A
120 G4QIsotope* Isotopes = G4QIsotope::Get(); // Pointer to the G4QIsotopes singleton
121 G4double sigma=0.; // Sums over elements for the material
122 G4int IPIE=IsoProbInEl.size(); // How many old elements?
123 if(IPIE) for(G4int ip=0; ip<IPIE; ++ip) // Clean up the SumProb's of Isotopes (SPI)
124 {
125 std::vector<G4double>* SPI=IsoProbInEl[ip]; // Pointer to the SPI vector
126 SPI->clear();
127 delete SPI;
128 std::vector<G4int>* IsN=ElIsoN[ip]; // Pointer to the N vector
129 IsN->clear();
130 delete IsN;
131 }
132 ElProbInMat.clear(); // Clean up the SumProb's of Elements (SPE)
133 ElementZ.clear(); // Clear the body vector for Z of Elements
134 IsoProbInEl.clear(); // Clear the body vector for SPI
135 ElIsoN.clear(); // Clear the body vector for N of Isotopes
136 for(G4int i=0; i<nE; ++i)
137 {
138 G4Element* pElement=(*theElementVector)[i]; // Pointer to the current element
139 G4int Z = static_cast<G4int>(pElement->GetZ()); // Z of the Element
140 ElementZ.push_back(Z); // Remember Z of the Element
141 G4int isoSize=0; // The default for the isoVectorLength is 0
142 G4int indEl=0; // Index of non-natural element or 0(default)
143 G4IsotopeVector* isoVector=pElement->GetIsotopeVector(); // Get the predefined IsoVect
144 if(isoVector) isoSize=isoVector->size();// Get size of the existing isotopeVector
145#ifdef debug
146 G4cout<<"G4QIonIonElastic::GetMeanFreePath: isovectorLength="<<isoSize<<G4endl;
147#endif
148 if(isoSize) // The Element has non-trivial abundance set
149 {
150 indEl=pElement->GetIndex()+1; // Index of the non-trivial element is an order
151#ifdef debug
152 G4cout<<"G4QIIEl::GetMFP:iE="<<indEl<<", def="<<Isotopes->IsDefined(Z,indEl)<<G4endl;
153#endif
154 if(!Isotopes->IsDefined(Z,indEl)) // This index is not defined for this Z: define
155 {
156 std::vector<std::pair<G4int,G4double>*>* newAbund =
157 new std::vector<std::pair<G4int,G4double>*>;
158 G4double* abuVector=pElement->GetRelativeAbundanceVector();
159 for(G4int j=0; j<isoSize; j++) // Calculation of abundance vector for isotopes
160 {
161 G4int N=pElement->GetIsotope(j)->GetN()-Z; // N means A=N+Z !
162 if(pElement->GetIsotope(j)->GetZ()!=Z) G4cerr<<"G4QIonIonEl::GetMeanFreePath Z="
163 <<pElement->GetIsotope(j)->GetZ()<<"#"<<Z<<G4endl;
164 G4double abund=abuVector[j];
165 std::pair<G4int,G4double>* pr= new std::pair<G4int,G4double>(N,abund);
166#ifdef debug
167 G4cout<<"G4QIonIonElastic::GetMeanFP:pair#="<<j<<",N="<<N<<",ab="<<abund<<G4endl;
168#endif
169 newAbund->push_back(pr);
170 }
171#ifdef debug
172 G4cout<<"G4QIonIonElastic::GetMeanFP: pairVectorLength="<<newAbund->size()<<G4endl;
173#endif
174 indEl=G4QIsotope::Get()->InitElement(Z,indEl,newAbund); // definition of the newInd
175 for(G4int k=0; k<isoSize; k++) delete (*newAbund)[k]; // Cleaning temporary
176 delete newAbund; // Was "new" in the beginning of the name space
177 }
178 }
179 std::vector<std::pair<G4int,G4double>*>* cs= Isotopes->GetCSVector(Z,indEl);//CSPointer
180 std::vector<G4double>* SPI = new std::vector<G4double>; // Pointer to the SPI vector
181 IsoProbInEl.push_back(SPI);
182 std::vector<G4int>* IsN = new std::vector<G4int>; // Pointer to the N vector
183 ElIsoN.push_back(IsN);
184 G4int nIs=cs->size(); // A#Of Isotopes in the Element
185#ifdef debug
186 G4cout<<"G4QIonIonEl::GetMFP:=***=> #isot="<<nIs<<", Z="<<Z<<", indEl="<<indEl<<G4endl;
187#endif
188 G4double susi=0.; // sum of CS over isotopes
189 if(nIs) for(G4int j=0; j<nIs; j++) // Calculate CS for eachIsotope of El
190 {
191 std::pair<G4int,G4double>* curIs=(*cs)[j]; // A pointer, which is used twice
192 G4int N=curIs->first; // #of Neuterons in the isotope j of El i
193 IsN->push_back(N); // Remember Min N for the Element
194#ifdef debug
195 G4cout<<"G4QIIE::GMFP:true,P="<<Momentum<<",Z="<<Z<<",N="<<N<<",pPDG="<<pPDG<<G4endl;
196#endif
197 G4bool ccsf=false; // Extract elastic Ion-Ion cross-section
198#ifdef debug
199 G4cout<<"G4QIonIonElastic::GMFP: GetCS #1 j="<<j<<G4endl;
200#endif
201 G4double CSI=0.;
202 if(Z==1 && !N) // Proton target. Reversed kinematics.
203 {
204 G4double projM=G4QPDGCode(2212).GetNuclMass(pZ,pA-pZ,0); // Mass of the projNucleus
205 CSI=PCSmanager->GetCrossSection(true, Momentum*mProt/projM, Z, N, 2212); // Ap CS
206 }
207 else CSI=CSmanager->GetCrossSection(ccsf,Momentum,Z,N,pPDG); // CS(j,i) for isotope
208#ifdef debug
209 G4cout<<"G4QIonIonElastic::GMFP: jI="<<j<<", Zt="<<Z<<", Nt="<<N<<", Mom="<<Momentum
210 <<", XSec="<<CSI/millibarn<<G4endl;
211#endif
212 curIs->second = CSI;
213 susi+=CSI; // Make a sum per isotopes
214 SPI->push_back(susi); // Remember summed cross-section
215 } // End of temporary initialization of the cross sections in the G4QIsotope singeltone
216 sigma+=Isotopes->GetMeanCrossSection(Z,indEl)*NOfNucPerVolume[i];//SUM(MeanCS*NOfNperV)
217#ifdef debug
218 G4cout<<"G4QIonIonEl::GMFP:<S>="<<Isotopes->GetMeanCrossSection(Z,indEl)<<",AddToSig="
219 <<Isotopes->GetMeanCrossSection(Z,indEl)*NOfNucPerVolume[i]<<G4endl;
220#endif
221 ElProbInMat.push_back(sigma);
222 } // End of LOOP over Elements
223 // Check that cross section is not zero and return the mean free path
224#ifdef debug
225 G4cout<<"G4QIonIonElastic::GetMeanFreePath: MeanFreePath="<<1./sigma<<G4endl;
226#endif
227 if(sigma > 0.00000000001) return 1./sigma; // Mean path [distance]
228 return DBL_MAX;
229}
230
231
233{
234 G4int Z=static_cast<G4int>(particle.GetPDGCharge());
235 G4int A=particle.GetBaryonNumber();
236 if (particle == *( G4Deuteron::Deuteron() )) return true;
237 else if (particle == *( G4Alpha::Alpha() )) return true;
238 else if (particle == *( G4Triton::Triton() )) return true;
239 else if (particle == *( G4He3::He3() )) return true;
240 else if (particle == *( G4GenericIon::GenericIon() )) return true;
241 else if (Z > 0 && A > 0) return true;
242#ifdef debug
243 G4cout<<"***>>G4QIonIonElastic::IsApplicable: PDG="<<particle.GetPDGEncoding()<<", A="
244 <<A<<", Z="<<Z<<G4endl;
245#endif
246 return false;
247}
248
250{
251 static const G4double mProt= G4QPDGCode(2212).GetMass(); // CHIPS proton mass in MeV
252 static const G4double fm2MeV2 = 3*38938./1.09; // (3/1.09)*(hc)^2 in fm^2*MeV^2
253 static G4bool CWinit = true; // CHIPS Warld needs to be initted
254 if(CWinit)
255 {
256 CWinit=false;
257 G4QCHIPSWorld::Get()->GetParticles(nPartCWorld); // Create CHIPS World (234 part.max)
258 }
259 //-------------------------------------------------------------------------------------
260 const G4DynamicParticle* projHadron = track.GetDynamicParticle();
261 const G4ParticleDefinition* particle=projHadron->GetDefinition();
262#ifdef debug
263 G4cout<<"G4QIonIonElastic::PostStepDoIt: Before the GetMeanFreePath is called In4M="
264 <<projHadron->Get4Momentum()<<" of PDG="<<particle->GetPDGEncoding()<<", Type="
265 <<particle->GetParticleType()<<", Subtp="<<particle->GetParticleSubType()<<G4endl;
266#endif
267 G4LorentzVector proj4M=(projHadron->Get4Momentum())/MeV; // Convert to MeV!
268 G4double momentum = projHadron->GetTotalMomentum()/MeV; // 3-momentum of the Proj in MeV
269 G4double Momentum = proj4M.rho(); // @@ Just for the test purposes
270 if(std::fabs(Momentum-momentum)>.000001)
271 G4cerr<<"-Warn-G4QIonIonElastic::PostStepDoIt:P(IU)="<<Momentum<<"#"<<momentum<<G4endl;
272 G4double pM2=proj4M.m2(); // in MeV^2
273 G4double pM=std::sqrt(pM2); // in MeV
274#ifdef pdebug
275 G4cout<<"G4QIonIonEl::PostStepDoIt: pP(IU)="<<Momentum<<"="<<momentum<<",pM="<<pM<<G4endl;
276#endif
277 if (!IsApplicable(*particle)) // Check applicability
278 {
279 G4cerr<<"G4QIonIonElastic::PostStepDoIt: Only NA elastic is implemented."<<G4endl;
280 return 0;
281 }
282 const G4Material* material = track.GetMaterial(); // Get the current material
283 const G4ElementVector* theElementVector = material->GetElementVector();
284 G4int nE=material->GetNumberOfElements();
285#ifdef debug
286 G4cout<<"G4QIonIonElastic::PostStepDoIt: "<<nE<<" elements in the material."<<G4endl;
287#endif
288 // Probably enough: projPDG=particle->GetPDGEncoding();
289 G4int projPDG=0; // CHIPS PDG Code for the captured hadron
290 G4int pZ=static_cast<G4int>(particle->GetPDGCharge());
291 G4int pA=particle->GetBaryonNumber();
292 if (particle == G4Deuteron::Deuteron() ) projPDG= 1000010020;
293 else if (particle == G4Alpha::Alpha() ) projPDG= 1000020040;
294 else if (particle == G4Triton::Triton() ) projPDG= 1000010030;
295 else if (particle == G4He3::He3() ) projPDG= 1000020030;
296 else if (particle == G4GenericIon::GenericIon() || (pZ > 0 && pA > 0))
297 {
298 projPDG=particle->GetPDGEncoding();
299#ifdef debug
300 G4int prPDG=1000000000+10000*pZ+10*pA;
301 G4cout<<"G4QIonIonElastic::PostStepDoIt: PDG="<<prPDG<<"="<<projPDG<<G4endl;
302#endif
303 }
304 else G4cout<<"-Warning-G4QIonIonElastic::PostStepDoIt:Unknown projectile Ion"<<G4endl;
305#ifdef debug
306 G4int prPDG=particle->GetPDGEncoding();
307 G4cout<<"G4QIonIonElastic::PostStepDoIt: projPDG="<<projPDG<<", stPDG="<<prPDG<<G4endl;
308#endif
309 if(!projPDG)
310 {
311 G4cerr<<"-Warning-G4QIonIonElastic::PostStepDoIt:Undefined interactingNucleus"<<G4endl;
312 return 0;
313 }
314 G4int pN=pA-pZ; // Projectile N
315 G4int EPIM=ElProbInMat.size();
316#ifdef debug
317 G4cout<<"G4QIonIonElastic::PSDI:m="<<EPIM<<",n="<<nE<<",T="<<ElProbInMat[EPIM-1]<<G4endl;
318#endif
319 G4int i=0;
320 if(EPIM>1)
321 {
322 G4double rnd = ElProbInMat[EPIM-1]*G4UniformRand();
323 for(i=0; i<nE; ++i)
324 {
325#ifdef debug
326 G4cout<<"G4QIonIonElastic::PSDI: EPM["<<i<<"]="<<ElProbInMat[i]<<", r="<<rnd<<G4endl;
327#endif
328 if (rnd<ElProbInMat[i]) break;
329 }
330 if(i>=nE) i=nE-1; // Top limit for the Element
331 }
332 G4Element* pElement=(*theElementVector)[i];
333 G4int tZ=static_cast<G4int>(pElement->GetZ());
334#ifdef debug
335 G4cout<<"G4QIonIonElastic::PostStepDoIt: i="<<i<<", Z(element)="<<tZ<<G4endl;
336#endif
337 if(tZ<=0)
338 {
339 G4cerr<<"---Warning---G4QIonIonElastic::PostStepDoIt: Element with Z="<<tZ<<G4endl;
340 if(tZ<0) return 0;
341 }
342 std::vector<G4double>* SPI = IsoProbInEl[i];// Vector of summedProbabilities for isotopes
343 std::vector<G4int>* IsN = ElIsoN[i]; // Vector of "#of neutrons" in the isotope El[i]
344 G4int nofIsot=SPI->size(); // #of isotopes in the element i
345#ifdef debug
346 G4cout<<"G4QIonIonElastic::PosStDoIt: nI="<<nofIsot<<",T="<<(*SPI)[nofIsot-1]<<G4endl;
347#endif
348 G4int j=0;
349 if(nofIsot>1)
350 {
351 G4double rndI=(*SPI)[nofIsot-1]*G4UniformRand(); // Randomize the isotop of the Element
352 for(j=0; j<nofIsot; ++j)
353 {
354#ifdef debug
355 G4cout<<"G4QIonIonElastic::PostStDI: SP["<<j<<"]="<<(*SPI)[j]<<", r="<<rndI<<G4endl;
356#endif
357 if(rndI < (*SPI)[j]) break;
358 }
359 if(j>=nofIsot) j=nofIsot-1; // Top limit for the isotope
360 }
361 G4int tN =(*IsN)[j]; ; // Randomized number of neutrons
362#ifdef debug
363 G4cout<<"G4QIonIonElastic::PostStepDoIt:j="<<i<<",N(isotope)="<<tN<<",MeV="<<MeV<<G4endl;
364#endif
365 if(tN<0)
366 {
367 G4cerr<<"-Warning-G4QIonIonElastic::PostStepDoIt:IsotopeZ="<<tZ<<" & 0>N="<<tN<<G4endl;
368 return 0;
369 }
370 nOfNeutrons=tN; // Remember it for the energy-momentum check
371#ifdef debug
372 G4cout<<"G4QIonIonElastic::PostStepDoIt: N="<<tN<<" for element with Z="<<tZ<<G4endl;
373#endif
375#ifdef debug
376 G4cout<<"G4QIonIonElastic::PostStepDoIt: track is initialized"<<G4endl;
377#endif
378 G4double weight = track.GetWeight();
379 G4double localtime = track.GetGlobalTime();
381#ifdef debug
382 G4cout<<"G4QIonIonElastic::PostStepDoIt: before Touchable extraction"<<G4endl;
383#endif
384 G4TouchableHandle trTouchable = track.GetTouchableHandle();
385#ifdef debug
386 G4cout<<"G4QIonIonElastic::PostStepDoIt: Touchable is extracted"<<G4endl;
387#endif
388 // Definitions for do nothing
389 G4double kinEnergy= projHadron->GetKineticEnergy()*MeV; // Kin energy in MeV (Is *MeV n?)
390 G4ParticleMomentum dir = projHadron->GetMomentumDirection();// It is a unit three-vector
391 // !! Exception for the proton target !!
392 G4bool revkin=false;
393 G4ThreeVector bvel(0.,0.,0.);
394 G4int tA=tZ+tN;
395 G4int targPDG=90000000+tZ*1000+tN; // CHIPS PDG Code of the target nucleus
396 G4QPDGCode targQPDG(targPDG); // @@ one can use G4Ion & get rid of CHIPS World
397 G4double tM=targQPDG.GetMass(); // CHIPS target mass in MeV
398 G4LorentzVector targ4M(0.,0.,0.,tM);
399 if(tZ==1 && !tN) // Update parameters in DB and trans to Antilab
400 {
402 GetMeanFreePath(track, -27., &cond); // @@ ?? jus to update parameters?
403#ifdef debug
404 G4cout<<"G4QIonIonElastic::PostStepDoIt: After the GetMeanFreePath is called"<<G4endl;
405#endif
406 revkin=true;
407 tZ=pZ;
408 tN=pN;
409 tA=tZ+tN;
410 tM=pM;
411 pZ=1; // @@ Is that necessary ??
412 pN=0; // @@ Is that necessary ??
413 pA=1; // @@ Is that necessary ??
414 pM=mProt;
415 bvel=proj4M.vect()/proj4M.e(); // Lab->Antilab transition boost velocity
416 proj4M=targ4M.boost(-bvel); // Proton 4-mom in Antilab
417 targ4M=G4LorentzVector(0.,0.,0.,tM); // Projectile nucleus 4-mom in Antilab
418 Momentum = proj4M.rho(); // Recalculate Momentum in Antilab
419 }
420 G4LorentzVector tot4M=proj4M+targ4M; // Total 4-mom of the reaction
421#ifdef debug
422 G4cout<<"G4QIonIonElastic::PostStDI: tM="<<tM<<", p4M="<<proj4M<<", t4M="<<tot4M<<G4endl;
423#endif
424 EnMomConservation=tot4M; // Total 4-mom of reaction for E/M conservation
428 // @@ Probably this is not necessary any more
429#ifdef debug
430 G4cout<<"G4QIIEl::PSDI:f, P="<<Momentum<<",Z="<<tZ<<",N="<<tN<<",tPDG="<<projPDG<<G4endl;
431#endif
432 // false means elastic cross-section
433 G4double xSec=0.; // Proto of Recalculated Cross Section
434 if(revkin) xSec=PELmanager->GetCrossSection(false, Momentum, tZ, tN, 2212);
435 else xSec=CSmanager->GetCrossSection(false, Momentum, tZ, tN, projPDG);
436#ifdef debug
437 G4cout<<"G4QIIEl::PSDI: pPDG="<<projPDG<<",P="<<Momentum<<",CS="<<xSec/millibarn<<G4endl;
438#endif
439#ifdef nandebug
440 if(xSec>0. || xSec<0. || xSec==0);
441 else G4cout<<"-NaN-Warning-G4QIonIonElastic::PostStDoIt: xSec="<<xSec/millibarn<<G4endl;
442#endif
443 // @@ check a possibility to separate p, n, or alpha (!)
444 if(xSec <= 0.) // The cross-section iz 0 -> Do Nothing
445 {
446#ifdef pdebug
447 G4cerr<<"-Warning-G4QIonIonElastic::PostStDoIt: *Zero cross-section* PDG="<<projPDG
448 <<",tPDG="<<targPDG<<",P="<<Momentum<<G4endl;
449#endif
450 //Do Nothing Action insead of the reaction
454 return G4VDiscreteProcess::PostStepDoIt(track,step);
455 }
456 G4double mint=0;
457 G4double maxt=0;
458 G4double dtM=tM+tM;
459 if(revkin)
460 {
461 mint=PELmanager->GetExchangeT(tZ,tN,2212); // functional randomized -t in MeV^2
462 maxt=PELmanager->GetHMaxT();
463 }
464 else
465 {
466 G4double PA=Momentum*pA;
467 G4double PA2=PA*PA;
468 maxt=dtM*PA2/(std::sqrt(PA2+pM2)+tM/2+pM2/dtM);
469#ifdef pdebug
470 G4cout<<"G4QIonIonElastic::PostStDoIt:pPDG="<<projPDG<<",tPDG="<<targPDG<<",P="
471 <<Momentum<<",CS="<<xSec<<",maxt="<<maxt<<G4endl;
472#endif
473 xSec=PELmanager->GetCrossSection(false, Momentum, 1, 0, 2212);// pp=nn
474 G4double B1=PELmanager->GetSlope(1,0,2212); // slope for pp=nn
475 xSec=NELmanager->GetCrossSection(false, Momentum, 1, 0, 2112);// np=pn
476 G4double B2 =NELmanager->GetSlope(1,0,2112); // slope for np=pn
477 G4double mB =((pZ*tZ+pN*tN)*B1+(pZ*tN+pN*tZ)*B2)/(pA+tA);
478 G4double pR2=std::pow(pA+4.,.305)/fm2MeV2;
479 G4double tR2=std::pow(tA+4.,.305)/fm2MeV2;
480 G4double eB =mB+pR2+tR2;
481 mint=-std::log(1.-G4UniformRand()*(1.-std::exp(-eB*maxt)))/eB;
482 mint+=mint;
483#ifdef pdebug
484 G4cout<<"G4QIonIonElastic::PostStDoIt:B1="<<B1<<",B2="<<B2<<",mB="<<mB
485 <<",pR2="<<pR2<<",tR2="<<tR2<<",eB="<<eB<<",mint="<<mint<<G4endl;
486#endif
487 }
488#ifdef nandebug
489 if(mint>-.0000001);
490 else G4cout<<"-Warning-G4QIonIonElastic::PostStDoIt:-t="<<mint<<G4endl;
491#endif
492 G4double cost=1.-mint/maxt; // cos(theta) in CMS
493 //
494#ifdef ppdebug
495 G4cout<<"G4QIonIonElastic::PoStDoI:t="<<mint<<",dpcm2="<<CSmanager->GetHMaxT()<<",Ek="
496 <<kinEnergy<<",tM="<<tM<<",pM="<<pM<<",cost="<<cost<<G4endl;
497#endif
498 if(cost>1. || cost<-1. || !(cost>-1. || cost<1.))
499 {
500 if(cost>1.000001 || cost<-1.000001 || !(cost>-1. || cost<1.))
501 {
502 G4double tM2=tM*tM; // Squared target mass
503 G4double pEn=pM+kinEnergy; // tot projectile Energy in MeV
504 G4double sM=dtM*pEn+tM2+pM2; // Mondelstam s
505 G4double twop2cm=(tM2+tM2)*(pEn*pEn-pM2)/sM;// Max_t/2 (2*p^2_cm)
506 G4cout<<"-Warning-G4QIonIonElastic::PoStDI:cos="<<cost<<",t="<<mint<<",T="<<kinEnergy
507 <<",tM="<<tM<<",tmax="<<2*kinEnergy*tM<<",p="<<projPDG<<",t="<<targPDG<<G4endl;
508 G4cout<<"G4QIonIonElastic::PSDI:dpcm2="<<twop2cm<<"="<<CSmanager->GetHMaxT()<<G4endl;
509 }
510 if (cost>1.) cost=1.;
511 else if(cost<-1.) cost=-1.;
512 }
513 G4LorentzVector scat4M(0.,0.,0.,pM); // 4-mom of the scattered projectile
514 G4LorentzVector reco4M(0.,0.,0.,tM); // 4-mom of the recoil target
515 G4LorentzVector dir4M=tot4M-G4LorentzVector(0.,0.,0.,(tot4M.e()-tM-pM)*.01);
516 if(!G4QHadron(tot4M).RelDecayIn2(scat4M, reco4M, dir4M, cost, cost))
517 {
518 G4cout<<"-Warning-G4QIonIonE::PSDI:t4M="<<tot4M<<",pM="<<pM<<",tM="<<tM<<",cost="
519 <<cost<<G4endl;
520 }
521 if(revkin)
522 {
523 G4LorentzVector tmpLV=scat4M.boost(bvel); // Recoil target Back to LS
524 scat4M=reco4M.boost(bvel); // Scattered Progectile Back to LS
525 reco4M=tmpLV;
526 pM=tM;
527 tM=mProt;
528 }
529#ifdef debug
530 G4cout<<"G4QIonIonElast::PSDI:s4M="<<scat4M<<"+r4M="<<reco4M<<"="<<scat4M+reco4M<<G4endl;
531 G4cout<<"G4QIonIonElastic::PSDI:scatE="<<scat4M.e()-pM<<",recoE="<<reco4M.e()-tM<<",d4M="
532 <<tot4M-scat4M-reco4M<<G4endl;
533#endif
534 // Update G4VParticleChange for the scattered projectile
535 G4double finE=scat4M.e()-pM; // Final kinetic energy of the scattered proton
536 if(finE>0.0) aParticleChange.ProposeEnergy(finE);
537 else
538 {
539 if(finE<-1.e-8 || !(finE>-1.||finE<1.)) // NAN or negative
540 G4cerr<<"*Warning*G4QIonIonElastic::PostStDoIt: Zero or negative scattered E="<<finE
541 <<", s4M="<<scat4M<<", r4M="<<reco4M<<", d4M="<<tot4M-scat4M-reco4M<<G4endl;
544 }
545 G4ThreeVector findir=scat4M.vect()/scat4M.rho(); // Unit vector in new direction
546 aParticleChange.ProposeMomentumDirection(findir); // new direction for the scattered part
547 EnMomConservation-=scat4M; // It must be initialized by (pE+tM,pP)
548 // This is how in general the secondary should be identified
549 G4DynamicParticle* theSec = new G4DynamicParticle; // A secondary for the recoil hadron
550#ifdef pdebug
551 G4cout<<"G4QIonIonElastic::PostStepDoIt: Ion tZ="<<tZ<<", tA="<<tA<<G4endl;
552#endif
553 G4ParticleDefinition* theDefinition=0;
554 if(revkin) theDefinition = G4Proton::Proton();
555 else theDefinition = G4ParticleTable::GetParticleTable()->FindIon(tZ,tA,0,tZ);
556 if(!theDefinition)G4cout<<"-Warning-G4QIonIonElastic::PoStDI:drop PDG="<<targPDG<<G4endl;
557#ifdef pdebug
558 G4cout<<"G4QIonIonElastic::PoStDI:RecoilName="<<theDefinition->GetParticleName()<<G4endl;
559#endif
560 theSec->SetDefinition(theDefinition);
561 EnMomConservation-=reco4M;
562#ifdef tdebug
563 G4cout<<"G4QIonIonElastic::PSD:"<<targPDG<<reco4M<<reco4M.m()<<EnMomConservation<<G4endl;
564#endif
565 theSec->Set4Momentum(reco4M);
566#ifdef debug
567 G4ThreeVector curD=theSec->GetMomentumDirection();
568 G4double curM=theSec->GetMass();
569 G4double curE=theSec->GetKineticEnergy()+curM;
570 G4cout<<"G4QIonIonElastic::PSDI: p="<<curD<<curD.mag()<<",e="<<curE<<",m="<<curM<<G4endl;
571#endif
572 // Make a recoil nucleus
573 G4Track* aNewTrack = new G4Track(theSec, localtime, position );
574 aNewTrack->SetWeight(weight); // weighted
575 aNewTrack->SetTouchableHandle(trTouchable);
576 aParticleChange.AddSecondary( aNewTrack );
577#ifdef debug
578 G4cout<<"G4QIonIonElastic::PostStepDoIt: **** PostStepDoIt is done ****"<<G4endl;
579#endif
580 return G4VDiscreteProcess::PostStepDoIt(track, step);
581}
std::vector< G4Element * > G4ElementVector
G4ForceCondition
@ NotForced
#define G4HadronicDeprecate(name)
std::vector< G4Isotope * > G4IsotopeVector
CLHEP::HepLorentzVector G4LorentzVector
@ fHadronic
@ fStopButAlive
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
HepLorentzVector & boost(double, double, double)
Hep3Vector vect() const
static G4Alpha * Alpha()
Definition: G4Alpha.cc:89
static G4Deuteron * Deuteron()
Definition: G4Deuteron.cc:94
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
static G4GenericIon * GenericIon()
Definition: G4GenericIon.cc:92
static G4He3 * He3()
Definition: G4He3.cc:94
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
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
G4double GetPDGCharge() 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)
static G4VQCrossSection * GetPointer()
G4QIonIonElastic(const G4String &processName="CHIPS_IonIonElasticScattering")
G4bool IsApplicable(const G4ParticleDefinition &particle)
G4VParticleChange * PostStepDoIt(const G4Track &aTrack, const G4Step &aStep)
G4double GetMeanFreePath(const G4Track &aTrack, G4double previousStepSize, G4ForceCondition *condition)
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
G4double GetNuclMass(G4int Z, G4int N, G4int S)
Definition: G4QPDGCode.cc:766
static G4VQCrossSection * 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
static G4Triton * Triton()
Definition: G4Triton.cc:95
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 GetSlope(G4int tZ, G4int tN, G4int pPDG)
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