Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
G4QuasiElRatios.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//
27//
28//
29// G4 Physics class: G4QuasiElRatios for N+A elastic cross sections
30// Created: M.V. Kossov, CERN/ITEP(Moscow), 10-OCT-01
31// The last update: M.V. Kossov, CERN/ITEP (Moscow) 15-Oct-06
32//
33// ----------------------------------------------------------------------
34// This class has been extracted from the CHIPS model.
35// All the dependencies on CHIPS classes have been removed.
36// Short description: Provides percentage of quasi-free and quasi-elastic
37// reactions in the inelastic reactions.
38// ----------------------------------------------------------------------
39
40
41#include "G4QuasiElRatios.hh"
43#include "G4SystemOfUnits.hh"
44#include "G4Proton.hh"
45#include "G4Neutron.hh"
46#include "G4Deuteron.hh"
47#include "G4Triton.hh"
48#include "G4He3.hh"
49#include "G4Alpha.hh"
50#include "G4ThreeVector.hh"
52#include "G4Pow.hh"
53#include "G4Log.hh"
54#include "G4Exp.hh"
55
56namespace {
57 const G4int nps=150; // Number of steps in the R(s) LinTable
58 const G4int mps=nps+1; // Number of elements in the R(s) LinTable
59 const G4double sma=150.; // The first LinTabEl(s=0)=1., s>sma -> logTab
60 const G4double ds=sma/nps; // Step of the linear Table
61 const G4int nls=100; // Number of steps in the R(lns) logTable
62 const G4int mls=nls+1; // Number of elements in the R(lns) logTable
63 const G4double lsi=5.; // The min ln(s) logTabEl(s=148.4 < sma=150.)
64 const G4double lsa=9.; // The max ln(s) logTabEl(s=148.4 - 8103. mb)
65 const G4double mi=G4Exp(lsi);// The min s of logTabEl(~ 148.4 mb)
66 const G4double min_s=G4Exp(lsa);// The max s of logTabEl(~ 8103. mb)
67 const G4double dls=(lsa-lsi)/nls;// Step of the logarithmic Table
68 const G4double edls=G4Exp(dls);// Multiplication step of the logarithmic Table
69 const G4double toler=.01; // The tolarence mb defining the same cross-section
70 const G4double C=1.246;
71 const G4double lmi=3.5; // min of (lnP-lmi)^2 parabola
72 const G4double pbe=.0557; // elastic (lnP-lmi)^2 parabola coefficient
73 const G4double pbt=.3; // total (lnP-lmi)^2 parabola coefficient
74 const G4double pmi=.1; // Below that fast LE calculation is made
75 const G4double pma=1000.; // Above that fast HE calculation is made
76 const G4int nlp=300; // Number of steps in the S(lnp) logTable(5% step)
77 const G4int mlp=nlp+1; // Number of elements in the S(lnp) logTable
78 const G4double lpi=-5.; // The min ln(p) logTabEl(p=6.7 MeV/c - 22. TeV/c)
79 const G4double lpa=10.; // The max ln(p) logTabEl(p=6.7 MeV/c - 22. TeV/c)
80 const G4double mip=G4Exp(lpi);// The min p of logTabEl(~ 6.7 MeV/c)
81 const G4double map=G4Exp(lpa);// The max p of logTabEl(~ 22. TeV)
82 const G4double dlp=(lpa-lpi)/nlp;// Step of the logarithmic Table
83 const G4double edlp=G4Exp(dlp);// Multiplication step of the logarithmic Table
84}
85
86
88{
89 vT = new std::vector<G4double*>;
90 vL = new std::vector<G4double*>;
91 vX = new std::vector<std::pair<G4double,G4double>*>;
92
93 lastSRatio=0.; // The last sigma value for which R was calculated
94 lastRRatio=0.; // The last ratio R which was calculated
95 lastARatio=0; // theLast of calculated A
96 lastHRatio=0.; // theLast of max s initialized in the LinTable
97 lastNRatio=0; // theLast of topBin number initialized in LinTable
98 lastMRatio=0.; // theLast of rel max ln(s) initialized in LogTable
99 lastKRatio=0; // theLast of topBin number initialized in LogTable
100 lastTRatio=0; // theLast of pointer to LinTable in the C++ heap
101 lastLRatio=0; // theLast of pointer to LogTable in the C++ heap
102 lastPtot=0.; // The last momentum for which XS was calculated
103 lastHtot=0; // The last projPDG for which XS was calculated
104 lastFtot=true; // The last nucleon for which XS was calculated
105 lastItot=0; // The Last index for which XS was calculated
106 lastMtot=0.; // The Last rel max ln(p) initialized in LogTable
107 lastKtot=0; // The Last topBin number initialized in LogTable
108 lastXtot = nullptr; // The Last ETPointers to LogTable in heap
109
111
113}
114
116{
117 std::vector<G4double*>::iterator pos;
118 for(pos=vT->begin(); pos<vT->end(); pos++)
119 { delete [] *pos; }
120 vT->clear();
121 delete vT;
122
123 for(pos=vL->begin(); pos<vL->end(); pos++)
124 { delete [] *pos; }
125 vL->clear();
126 delete vL;
127
128 std::vector<std::pair<G4double,G4double>*>::iterator pos2;
129 for(pos2=vX->begin(); pos2<vX->end(); pos2++)
130 { delete [] *pos2; }
131 vX->clear();
132 delete vX;
133}
134
135// Calculation of pair(QuasiFree/Inelastic,QuasiElastic/QuasiFree)
136std::pair<G4double,G4double> G4QuasiElRatios::GetRatios(G4double pIU, G4int pPDG,
137 G4int tgZ, G4int tgN)
138{
139 G4double R=0.;
140 G4double QF2In=1.; // Prototype of QuasiFree/Inel ratio for hN_tot
141 G4int tgA=tgZ+tgN;
142 if(tgA<2) return std::make_pair(QF2In,R); // No quasi-elastic on the only nucleon
143 std::pair<G4double,G4double> ElTot=GetElTot(pIU, pPDG, tgZ, tgN); // mean hN El&Tot(IU)
144 //if( ( (pPDG>999 && pIU<227.) || pIU<27.) && tgA>1) R=1.; // @@ TMP to accelerate @lowE
145 if(pPDG>999 && pIU<227. && tgZ+tgN>1) R=1.; // To accelerate @lowE
146 else if(ElTot.second>0.)
147 {
148 R=ElTot.first/ElTot.second; // El/Total ratio (does not depend on units
149 QF2In=GetQF2IN_Ratio(ElTot.second/millibarn, tgZ+tgN); // QuasiFree/Inelastic ratio
150 }
151 return std::make_pair(QF2In,R);
152}
153
154// Calculatio QasiFree/Inelastic Ratio as a function of total hN cross-section (mb) and A
155G4double G4QuasiElRatios::GetQF2IN_Ratio(G4double m_s, G4int A)
156{
157 // LogTable is created only if necessary. The ratio R(s>8100 mb) = 0 for any nuclei
158 if(m_s<toler || A<2) return 1.;
159 if(m_s>min_s) return 0.;
160
161 //if(A>238)
162 //{
163 // G4cout<<"-Warning-G4QuasiElRatio::GetQF2IN_Ratio:A="<<A<<">238, return zero"<<G4endl;
164 // return 0.;
165 //}
166 G4int nDB=(G4int)vARatio.size(); // A number of nuclei already initialized in AMDB
167 if(nDB && lastARatio==A && m_s==lastSRatio) return lastRRatio; // VI do not use tolerance
168 G4bool found=false;
169 G4int i=-1;
170 if(nDB) for (i=0; i<nDB; i++) if(A==vARatio[i]) // Search for this A in AMDB
171 {
172 found=true; // The A value is found
173 break;
174 }
175 if(!nDB || !found) // Create new line in the AMDB
176 {
177 lastARatio = A;
178 lastTRatio = new G4double[mps]; // Create the linear Table
179 lastNRatio = static_cast<int>(m_s/ds)+1; // MaxBin to be initialized
180 if(lastNRatio>nps)
181 {
182 lastNRatio=nps;
183 lastHRatio=sma;
184 }
185 else lastHRatio = lastNRatio*ds; // Calculate max initialized s for LinTab
186 G4double sv=0;
187 lastTRatio[0]=1.;
188 for(G4int j=1; j<=lastNRatio; j++) // Calculate LogTab values
189 {
190 sv+=ds;
191 lastTRatio[j]=CalcQF2IN_Ratio(sv,A);
192 }
193 lastLRatio=new G4double[mls]; // Create the logarithmic Table
194 // Initialize the logarithmic Table
195 for(G4int j=0; j<mls; ++j) lastLRatio[j]=0.0;
196 if(m_s>sma)
197 {
198 G4double ls=G4Log(m_s);
199 lastKRatio = static_cast<int>((ls-lsi)/dls)+1; // MaxBin to be initialized in LogTaB
200 if(lastKRatio>nls)
201 {
202 lastKRatio=nls;
203 lastMRatio=lsa-lsi;
204 }
205 else lastMRatio = lastKRatio*dls; // Calculate max initialized ln(s)-lsi for LogTab
206 sv=mi;
207 for(G4int j=0; j<=lastKRatio; j++) // Calculate LogTab values
208 {
209 lastLRatio[j]=CalcQF2IN_Ratio(sv,A);
210 if(j!=lastKRatio) sv*=edls;
211 }
212 }
213 else // LogTab is not initialized
214 {
215 lastKRatio = 0;
216 lastMRatio = 0.;
217 }
218 i++; // Make a new record to AMDB and position on it
219 vARatio.push_back(lastARatio);
220 vHRatio.push_back(lastHRatio);
221 vNRatio.push_back(lastNRatio);
222 vMRatio.push_back(lastMRatio);
223 vKRatio.push_back(lastKRatio);
224 vT->push_back(lastTRatio);
225 vL->push_back(lastLRatio);
226 }
227 else // The A value was found in AMDB
228 {
229 lastARatio=vARatio[i];
230 lastHRatio=vHRatio[i];
231 lastNRatio=vNRatio[i];
232 lastMRatio=vMRatio[i];
233 lastKRatio=vKRatio[i];
234 lastTRatio=(*vT)[i];
235 lastLRatio=(*vL)[i];
236 if(m_s>lastHRatio) // At least LinTab must be updated
237 {
238 G4int nextN=lastNRatio+1; // The next bin to be initialized
239 if(lastNRatio<nps)
240 {
241 G4double sv=lastHRatio; // bug fix by WP
242
243 lastNRatio = static_cast<int>(m_s/ds)+1;// MaxBin to be initialized
244 if(lastNRatio>nps)
245 {
246 lastNRatio=nps;
247 lastHRatio=sma;
248 }
249 else lastHRatio = lastNRatio*ds; // Calculate max initialized s for LinTab
250
251 for(G4int j=nextN; j<=lastNRatio; j++)// Calculate LogTab values
252 {
253 sv+=ds;
254 lastTRatio[j]=CalcQF2IN_Ratio(sv,A);
255 }
256 } // End of LinTab update
257 if(lastNRatio>=nextN)
258 {
259 vHRatio[i]=lastHRatio;
260 vNRatio[i]=lastNRatio;
261 }
262 G4int nextK=lastKRatio+1;
263 if(!lastKRatio) nextK=0;
264 if(m_s>sma && lastKRatio<nls) // LogTab must be updated
265 {
266 G4double sv=G4Exp(lastMRatio+lsi); // Define starting poit (lastM will be changed)
267 G4double ls=G4Log(m_s);
268 lastKRatio = static_cast<int>((ls-lsi)/dls)+1; // MaxBin to be initialized in LogTaB
269 if(lastKRatio>nls)
270 {
271 lastKRatio=nls;
272 lastMRatio=lsa-lsi;
273 }
274 else lastMRatio = lastKRatio*dls; // Calculate max initialized ln(s)-lsi for LogTab
275 for(G4int j=nextK; j<=lastKRatio; j++)// Calculate LogTab values
276 {
277 sv*=edls;
278 lastLRatio[j]=CalcQF2IN_Ratio(sv,A);
279 }
280 } // End of LogTab update
281 if(lastKRatio>=nextK)
282 {
283 vMRatio[i]=lastMRatio;
284 vKRatio[i]=lastKRatio;
285 }
286 }
287 }
288 // Now one can use tabeles to calculate the value
289 if(m_s<sma) // Use linear table
290 {
291 G4int n=static_cast<int>(m_s/ds); // Low edge number of the bin
292 G4double d=m_s-n*ds; // Linear shift
293 G4double v=lastTRatio[n]; // Base
294 lastRRatio=v+d*(lastTRatio[n+1]-v)/ds; // Result
295 }
296 else // Use log table
297 {
298 G4double ls=G4Log(m_s)-lsi; // ln(s)-l_min
299 G4int n=static_cast<int>(ls/dls); // Low edge number of the bin
300 G4double d=ls-n*dls; // Log shift
301 G4double v=lastLRatio[n]; // Base
302 lastRRatio=v+d*(lastLRatio[n+1]-v)/dls; // Result
303 }
304 if(lastRRatio<0.) lastRRatio=0.;
305 if(lastRRatio>1.) lastRRatio=1.;
306 return lastRRatio;
307} // End of CalcQF2IN_Ratio
308
309// Calculatio QasiFree/Inelastic Ratio as a function of total hN cross-section and A
310G4double G4QuasiElRatios::CalcQF2IN_Ratio(G4double m_s, G4int A)
311{
312 G4double s2=m_s*m_s;
313 G4double s4=s2*s2;
314 G4double ss=std::sqrt(std::sqrt(m_s));
315 G4double P=7.48e-5*s2/(1.+8.77e12/s4/s4/s2);
316 G4double E=.2644+.016/(1.+G4Exp((29.54-m_s)/2.49));
317 G4double F=ss*.1526*G4Exp(-s2*ss*.0000859);
318 return C*G4Exp(-E*G4Pow::GetInstance()->powA(G4double(A-1.),F))/G4Pow::GetInstance()->powA(G4double(A),P);
319} // End of CalcQF2IN_Ratio
320
321// Calculatio pair(hN_el,hN_tot) (mb): p in GeV/c, index(PDG,F) (see FetchElTot)
322std::pair<G4double,G4double> G4QuasiElRatios::CalcElTot(G4double p, G4int I)
323{
324 // ---------> Each parameter set can have not more than nPoints=128 parameters
325
326 G4double El=0.; // prototype of the elastic hN cross-section
327 G4double To=0.; // prototype of the total hN cross-section
328 if(p<=0.)
329 {
330 G4cout<<"-Warning-G4QuasiElRatios::CalcElTot: p="<<p<<" is zero or negative"<<G4endl;
331 return std::make_pair(El,To);
332 }
333 if (!I) // pp/nn
334 {
335 if(p<pmi)
336 {
337 G4double p2=p*p;
338 El=1./(.00012+p2*.2);
339 To=El;
340 }
341 else if(p>pma)
342 {
343 G4double lp=G4Log(p)-lmi;
344 G4double lp2=lp*lp;
345 El=pbe*lp2+6.72;
346 To=pbt*lp2+38.2;
347 }
348 else
349 {
350 G4double p2=p*p;
351 G4double LE=1./(.00012+p2*.2);
352 G4double lp=G4Log(p)-lmi;
353 G4double lp2=lp*lp;
354 G4double rp2=1./p2;
355 El=LE+(pbe*lp2+6.72+32.6/p)/(1.+rp2/p);
356 To=LE+(pbt*lp2+38.2+52.7*rp2)/(1.+2.72*rp2*rp2);
357 }
358 }
359 else if(I==1) // np/pn
360 {
361 if(p<pmi)
362 {
363 G4double p2=p*p;
364 El=1./(.00012+p2*(.051+.1*p2));
365 To=El;
366 }
367 else if(p>pma)
368 {
369 G4double lp=G4Log(p)-lmi;
370 G4double lp2=lp*lp;
371 El=pbe*lp2+6.72;
372 To=pbt*lp2+38.2;
373 }
374 else
375 {
376 G4double p2=p*p;
377 G4double LE=1./(.00012+p2*(.051+.1*p2));
378 G4double lp=G4Log(p)-lmi;
379 G4double lp2=lp*lp;
380 G4double rp2=1./p2;
381 El=LE+(pbe*lp2+6.72+30./p)/(1.+.49*rp2/p);
382 To=LE+(pbt*lp2+38.2)/(1.+.54*rp2*rp2);
383 }
384 }
385 else if(I==2) // pimp/pipn
386 {
387 G4double lp=G4Log(p);
388 if(p<pmi)
389 {
390 G4double lr=lp+1.27;
391 El=1.53/(lr*lr+.0676);
392 To=El*3;
393 }
394 else if(p>pma)
395 {
396 G4double ld=lp-lmi;
397 G4double ld2=ld*ld;
398 G4double sp=std::sqrt(p);
399 El=pbe*ld2+2.4+7./sp;
400 To=pbt*ld2+22.3+12./sp;
401 }
402 else
403 {
404 G4double lr=lp+1.27; // p1
405 G4double LE=1.53/(lr*lr+.0676); // p2, p3
406 G4double ld=lp-lmi; // p4 (lmi=3.5)
407 G4double ld2=ld*ld;
408 G4double p2=p*p;
409 G4double p4=p2*p2;
410 G4double sp=std::sqrt(p);
411 G4double lm=lp+.36; // p5
412 G4double md=lm*lm+.04; // p6
413 G4double lh=lp-.017; // p7
414 G4double hd=lh*lh+.0025; // p8
415 El=LE+(pbe*ld2+2.4+7./sp)/(1.+.7/p4)+.6/md+.05/hd;//p9(pbe=.0557),p10,p11,p12,p13,p14
416 To=LE*3+(pbt*ld2+22.3+12./sp)/(1.+.4/p4)+1./md+.06/hd;
417 }
418 }
419 else if(I==3) // pipp/pimn
420 {
421 G4double lp=G4Log(p);
422 if(p<pmi)
423 {
424 G4double lr=lp+1.27;
425 G4double lr2=lr*lr;
426 El=13./(lr2+lr2*lr2+.0676);
427 To=El;
428 }
429 else if(p>pma)
430 {
431 G4double ld=lp-lmi;
432 G4double ld2=ld*ld;
433 G4double sp=std::sqrt(p);
434 El=pbe*ld2+2.4+6./sp;
435 To=pbt*ld2+22.3+5./sp;
436 }
437 else
438 {
439 G4double lr=lp+1.27; // p1
440 G4double lr2=lr*lr;
441 G4double LE=13./(lr2+lr2*lr2+.0676); // p2, p3
442 G4double ld=lp-lmi; // p4 (lmi=3.5)
443 G4double ld2=ld*ld;
444 G4double p2=p*p;
445 G4double p4=p2*p2;
446 G4double sp=std::sqrt(p);
447 G4double lm=lp-.32; // p5
448 G4double md=lm*lm+.0576; // p6
449 El=LE+(pbe*ld2+2.4+6./sp)/(1.+3./p4)+.7/md; // p7(pbe=.0557), p8, p9, p10, p11
450 To=LE+(pbt*ld2+22.3+5./sp)/(1.+1./p4)+.8/md;
451 }
452 }
453 else if(I==4) // Kmp/Kmn/K0p/K0n
454 {
455
456 if(p<pmi)
457 {
458 G4double psp=p*std::sqrt(p);
459 El=5.2/psp;
460 To=14./psp;
461 }
462 else if(p>pma)
463 {
464 G4double ld=G4Log(p)-lmi;
465 G4double ld2=ld*ld;
466 El=pbe*ld2+2.23;
467 To=pbt*ld2+19.5;
468 }
469 else
470 {
471 G4double ld=G4Log(p)-lmi;
472 G4double ld2=ld*ld;
473 G4double sp=std::sqrt(p);
474 G4double psp=p*sp;
475 G4double p2=p*p;
476 G4double p4=p2*p2;
477 G4double lm=p-.39;
478 G4double md=lm*lm+.000156;
479 G4double lh=p-1.;
480 G4double hd=lh*lh+.0156;
481 El=5.2/psp+(pbe*ld2+2.23)/(1.-.7/sp+.075/p4)+.004/md+.15/hd;
482 To=14./psp+(pbt*ld2+19.5)/(1.-.21/sp+.52/p4)+.006/md+.30/hd;
483 }
484 }
485 else if(I==5) // Kpp/Kpn/aKp/aKn
486 {
487 if(p<pmi)
488 {
489 G4double lr=p-.38;
490 G4double lm=p-1.;
491 G4double md=lm*lm+.372;
492 El=.7/(lr*lr+.0676)+2./md;
493 To=El+.6/md;
494 }
495 else if(p>pma)
496 {
497 G4double ld=G4Log(p)-lmi;
498 G4double ld2=ld*ld;
499 El=pbe*ld2+2.23;
500 To=pbt*ld2+19.5;
501 }
502 else
503 {
504 G4double ld=G4Log(p)-lmi;
505 G4double ld2=ld*ld;
506 G4double lr=p-.38;
507 G4double LE=.7/(lr*lr+.0676);
508 G4double sp=std::sqrt(p);
509 G4double p2=p*p;
510 G4double p4=p2*p2;
511 G4double lm=p-1.;
512 G4double md=lm*lm+.372;
513 El=LE+(pbe*ld2+2.23)/(1.-.7/sp+.1/p4)+2./md;
514 To=LE+(pbt*ld2+19.5)/(1.+.46/sp+1.6/p4)+2.6/md;
515 }
516 }
517 else if(I==6) // hyperon-N
518 {
519 if(p<pmi)
520 {
521 G4double p2=p*p;
522 El=1./(.002+p2*(.12+p2));
523 To=El;
524 }
525 else if(p>pma)
526 {
527 G4double lp=G4Log(p)-lmi;
528 G4double lp2=lp*lp;
529 G4double sp=std::sqrt(p);
530 El=(pbe*lp2+6.72)/(1.+2./sp);
531 To=(pbt*lp2+38.2+900./sp)/(1.+27./sp);
532 }
533 else
534 {
535 G4double p2=p*p;
536 G4double LE=1./(.002+p2*(.12+p2));
537 G4double lp=G4Log(p)-lmi;
538 G4double lp2=lp*lp;
539 G4double p4=p2*p2;
540 G4double sp=std::sqrt(p);
541 El=LE+(pbe*lp2+6.72+99./p2)/(1.+2./sp+2./p4);
542 To=LE+(pbt*lp2+38.2+900./sp)/(1.+27./sp+3./p4);
543 }
544 }
545 else if(I==7) // antibaryon-N
546 {
547 if(p>pma)
548 {
549 G4double lp=G4Log(p)-lmi;
550 G4double lp2=lp*lp;
551 El=pbe*lp2+6.72;
552 To=pbt*lp2+38.2;
553 }
554 else
555 {
556 G4double ye=G4Pow::GetInstance()->powA(p,1.25);
557 G4double yt=G4Pow::GetInstance()->powA(p,.35);
558 G4double lp=G4Log(p)-lmi;
559 G4double lp2=lp*lp;
560 El=80./(ye+1.)+pbe*lp2+6.72;
561 To=(80./yt+.3)/yt+pbt*lp2+38.2;
562 }
563 }
564 else
565 {
566 G4cout<<"*Error*G4QuasiElRatios::CalcElTot:ind="<<I<<" is not defined (0-7)"<<G4endl;
567 G4Exception("G4QuasiElRatios::CalcElTot:","23",FatalException,"QEcrash");
568 }
569 if(El>To) El=To;
570 return std::make_pair(El,To);
571} // End of CalcElTot
572
573// For hadron PDG with momentum Mom (GeV/c) on N (p/n) calculate <sig_el,sig_tot> pair (mb)
574std::pair<G4double,G4double> G4QuasiElRatios::GetElTotXS(G4double p, G4int PDG, G4bool F)
575{
576 G4int ind=0; // Prototype of the reaction index
577 G4bool kfl=true; // Flag of K0/aK0 oscillation
578 G4bool kf=false;
579 if(PDG==130||PDG==310)
580 {
581 kf=true;
582 if(G4UniformRand()>.5) kfl=false;
583 }
584 if ( (PDG == 2212 && F) || (PDG == 2112 && !F) ) ind=0; // pp/nn
585 else if ( (PDG == 2112 && F) || (PDG == 2212 && !F) ) ind=1; // np/pn
586 else if ( (PDG == -211 && F) || (PDG == 211 && !F) ) ind=2; // pimp/pipn
587 else if ( (PDG == 211 && F) || (PDG == -211 && !F) ) ind=3; // pipp/pimn
588 //AR-Jul2020: Extended to charmed and bottom hadrons:
589 // - treat mesons with constituent c quark or b quark as a meson with s quark (e.g. K-);
590 // - treat mesons with constituent cbar antiquark or bbar antiquark as a meson with sbar antiquark (e.g. K+);
591 // - treat all heavy baryons (i.e. hyperons, charmed and bottom baryons) as lambda;
592 // - treat all heavy anti-baryons (i.e. anti-hyperons, charmed and bottom anti-baryons) as anti-p/anti-n.
593 else if ( PDG == -321 || PDG == -311 || (kf && !kfl) || // mesons with s quark
594 PDG == 411 || PDG == 421 || PDG == 431 || // mesons with c quark
595 PDG == -521 || PDG == -511 || PDG == -531 || PDG == -541 ) ind=4; // mesons with b quark
596 else if ( PDG == 321 || PDG == 311 || (kf && kfl) || // mesons with sbar antiquark
597 PDG == -411 || PDG == -421 || PDG == -431 || // mesons with cbar antiquark
598 PDG == 521 || PDG == 511 || PDG == 531 || PDG == 541 ) ind=5; // mesons with bbar antiquark
599 else if ( PDG > 3000 && PDG < 5333 ) ind=6; // @@ for all heavy baryons - take Lambda
600 else if ( PDG > -5333 && PDG < -2000 ) ind=7; // @@ for all anti-baryons (anti-p/anti-n)
601 else {
602 G4cout<<"*Error*G4QuasiElRatios::CalcElTotXS: PDG="<<PDG
603 <<", while it is defined only for p,n,hyperons,anti-baryons,pi,K/antiK"<<G4endl;
604 G4Exception("G4QuasiElRatio::CalcElTotXS:","22",FatalException,"QEcrash");
605 }
606 return CalcElTot(p,ind);
607}
608
609// Calculatio pair(hN_el,hN_tot)(mb): p in GeV/c, F=true -> N=proton, F=false -> N=neutron
610std::pair<G4double,G4double> G4QuasiElRatios::FetchElTot(G4double p, G4int PDG, G4bool F)
611{
612 // LogTable is created only if necessary. The ratio R(s>8100 mb) = 0 for any nuclei
613 G4int nDB=(G4int)vItot.size(); // A number of hadrons already initialized in AMDB
614 if(nDB && lastHtot==PDG && lastFtot==F && p>0. && p==lastPtot) return lastRtot;// VI don't use toler.
615 // if(nDB && lastH==PDG && lastF==F && p>0. && std::fabs(p-lastP)/p<toler) return lastR;
616 lastHtot=PDG;
617 lastFtot=F;
618 G4int ind=-1; // Prototipe of the index of the PDG/F combination
619 // i=0: pp(nn), i=1: np(pn), i=2: pimp(pipn), i=3: pipp(pimn), i=4: Kmp(Kmn,K0n,K0p),
620 // i=5: Kpp(Kpn,aK0n,aK0p), i=6: Hp(Hn), i=7: app(apn,ann,anp)
621 G4bool kfl=true; // Flag of K0/aK0 oscillation
622 G4bool kf=false;
623 if(PDG==130||PDG==310)
624 {
625 kf=true;
626 if(G4UniformRand()>.5) kfl=false;
627 }
628 if ( (PDG == 2212 && F) || (PDG == 2112 && !F) ) ind=0; // pp/nn
629 else if ( (PDG == 2112 && F) || (PDG == 2212 && !F) ) ind=1; // np/pn
630 else if ( (PDG == -211 && F) || (PDG == 211 && !F) ) ind=2; // pimp/pipn
631 else if ( (PDG == 211 && F) || (PDG == -211 && !F) ) ind=3; // pipp/pimn
632 //AR-Jul2020: Extended to charmed and bottom hadrons:
633 // - treat mesons with constituent c quark or b quark as a meson with s quark (e.g. K-);
634 // - treat mesons with constituent cbar antiquark or bbar antiquark as a meson with sbar antiquark (e.g. K+);
635 // - treat all heavy baryons (i.e. hyperons, charmed and bottom baryons) as lambda;
636 // - treat all heavy anti-baryons (i.e. anti-hyperons, charmed and bottom anti-baryons) as anti-p/anti-n.
637 else if ( PDG == -321 || PDG == -311 || (kf && !kfl) || // mesons with s quark
638 PDG == 411 || PDG == 421 || PDG == 431 || // mesons with c quark
639 PDG == -521 || PDG == -511 || PDG == -531 || PDG == -541 ) ind=4; // mesons with b quark
640 else if ( PDG == 321 || PDG == 311 || (kf && kfl) || // mesons with sbar antiquark
641 PDG == -411 || PDG == -421 || PDG == -431 || // mesons with cbar antiquark
642 PDG == 521 || PDG == 511 || PDG == 531 || PDG == 541 ) ind=5; // mesons with bbar antiquark
643 else if ( PDG > 3000 && PDG < 5333 ) ind=6; // @@ for all heavy baryons - take Lambda
644 else if ( PDG > -5333 && PDG < -2000 ) ind=7; // @@ for all anti-baryons (anti-p/anti-n)
645 else {
646 G4cout<<"*Error*G4QuasiElRatios::FetchElTot: PDG="<<PDG
647 <<", while it is defined only for p,n,hyperons,anti-baryons,pi,K/antiK"<<G4endl;
648 G4Exception("G4QuasiELRatio::FetchElTot:","22",FatalException,"QECrash");
649 }
650 if(nDB && lastItot==ind && p>0. && p==lastPtot) return lastRtot; // VI do not use toler
651 // if(nDB && lastI==ind && p>0. && std::fabs(p-lastP)/p<toler) return lastR;
652 if(p<=mip || p>=map) return CalcElTot(p,ind); // @@ Slow calculation ! (Warning?)
653 G4bool found=false;
654 G4int i=-1;
655 if(nDB) for (i=0; i<nDB; i++) if(ind==vItot[i]) // Sirch for this index in AMDB
656 {
657 found=true; // The index is found
658 break;
659 }
660 G4double lp=G4Log(p);
661 if(!nDB || !found) // Create new line in the AMDB
662 {
663 lastXtot = new std::pair<G4double,G4double>[mlp]; // Create logarithmic Table for ElTot
664 lastItot = ind; // Remember the initialized inex
665 lastKtot = static_cast<int>((lp-lpi)/dlp)+1; // MaxBin to be initialized in LogTaB
666 if(lastKtot>nlp)
667 {
668 lastKtot=nlp;
669 lastMtot=lpa-lpi;
670 }
671 else lastMtot = lastKtot*dlp; // Calculate max initialized ln(p)-lpi for LogTab
672 G4double pv=mip;
673 for(G4int j=0; j<=lastKtot; j++) // Calculate LogTab values
674 {
675 lastXtot[j]=CalcElTot(pv,ind);
676 if(j!=lastKtot) pv*=edlp;
677 }
678 i++; // Make a new record to AMDB and position on it
679 vItot.push_back(lastItot);
680 vMtot.push_back(lastMtot);
681 vKtot.push_back(lastKtot);
682 vX->push_back(lastXtot);
683 }
684 else // The A value was found in AMDB
685 {
686 lastItot=vItot[i];
687 lastMtot=vMtot[i];
688 lastKtot=vKtot[i];
689 lastXtot=(*vX)[i];
690 G4int nextK=lastKtot+1;
691 G4double lpM=lastMtot+lpi;
692 if(lp>lpM && lastKtot<nlp) // LogTab must be updated
693 {
694 lastKtot = static_cast<int>((lp-lpi)/dlp)+1; // MaxBin to be initialized in LogTab
695 if(lastKtot>nlp)
696 {
697 lastKtot=nlp;
698 lastMtot=lpa-lpi;
699 }
700 else lastMtot = lastKtot*dlp; // Calculate max initialized ln(p)-lpi for LogTab
701 G4double pv=G4Exp(lpM); // momentum of the last calculated beam
702 for(G4int j=nextK; j<=lastKtot; j++)// Calculate LogTab values
703 {
704 pv*=edlp;
705 lastXtot[j]=CalcElTot(pv,ind);
706 }
707 } // End of LogTab update
708 if(lastKtot>=nextK) // The AMDB was apdated
709 {
710 vMtot[i]=lastMtot;
711 vKtot[i]=lastKtot;
712 }
713 }
714 // Now one can use tabeles to calculate the value
715 G4double dlpp=lp-lpi; // Shifted log(p) value
716 G4int n=static_cast<int>(dlpp/dlp); // Low edge number of the bin
717 G4double d=dlpp-n*dlp; // Log shift
718 G4double e=lastXtot[n].first; // E-Base
719 lastRtot.first=e+d*(lastXtot[n+1].first-e)/dlp; // E-Result
720 if(lastRtot.first<0.) lastRtot.first = 0.;
721 G4double t=lastXtot[n].second; // T-Base
722 lastRtot.second=t+d*(lastXtot[n+1].second-t)/dlp; // T-Result
723 if(lastRtot.second<0.) lastRtot.second= 0.;
724 if(lastRtot.first>lastRtot.second) lastRtot.first = lastRtot.second;
725 return lastRtot;
726} // End of FetchElTot
727
728// (Mean Elastic and Mean Total) Cross-Sections (mb) for PDG+(Z,N) at P=p[GeV/c]
729std::pair<G4double,G4double> G4QuasiElRatios::GetElTot(G4double pIU, G4int hPDG,
730 G4int Z, G4int N)
731{
732 G4double pGeV=pIU/gigaelectronvolt;
733 if(Z<1 && N<1)
734 {
735 G4cout<<"-Warning-G4QuasiElRatio::GetElTot:Z="<<Z<<",N="<<N<<", return zero"<<G4endl;
736 return std::make_pair(0.,0.);
737 }
738 std::pair<G4double,G4double> hp=FetchElTot(pGeV, hPDG, true);
739 std::pair<G4double,G4double> hn=FetchElTot(pGeV, hPDG, false);
740 G4double A=(Z+N)/millibarn; // To make the result in independent units(IU)
741 return std::make_pair((Z*hp.first+N*hn.first)/A,(Z*hp.second+N*hn.second)/A);
742} // End of GetElTot
743
744// (Mean Elastic and Mean Total) Cross-Sections (mb) for PDG+(Z,N) at P=p[GeV/c]
745std::pair<G4double,G4double> G4QuasiElRatios::GetChExFactor(G4double pIU, G4int hPDG,
746 G4int Z, G4int N)
747{
748 G4double pGeV=pIU/gigaelectronvolt;
749 G4double resP=0.;
750 G4double resN=0.;
751 if(Z<1 && N<1)
752 {
753 G4cout<<"-Warning-G4QuasiElRatio::GetChExF:Z="<<Z<<",N="<<N<<", return zero"<<G4endl;
754 return std::make_pair(resP,resN);
755 }
756 G4double A=Z+N;
757 G4double pf=0.; // Possibility to interact with a proton
758 G4double nf=0.; // Possibility to interact with a neutron
759 if (hPDG==-211||hPDG==-321||hPDG==3112||hPDG==3212||hPDG==3312) pf=Z/(A+N);
760 else if(hPDG==211||hPDG==321||hPDG==3222||hPDG==3212||hPDG==3322) nf=N/(A+Z);
761 else if(hPDG==-311||hPDG==311||hPDG==130||hPDG==310)
762 {
763 G4double dA=A+A;
764 pf=Z/(dA+N+N);
765 nf=N/(dA+Z+Z);
766 }
767 G4double mult=1.; // Factor of increasing multiplicity ( ? @@)
768 if(pGeV>.5)
769 {
770 mult=1./(1.+G4Log(pGeV+pGeV))/pGeV;
771 if(mult>1.) mult=1.;
772 }
773 if(pf)
774 {
775 std::pair<G4double,G4double> hp=FetchElTot(pGeV, hPDG, true);
776 resP=pf*(hp.second/hp.first-1.)*mult;
777 }
778 if(nf)
779 {
780 std::pair<G4double,G4double> hn=FetchElTot(pGeV, hPDG, false);
781 resN=nf*(hn.second/hn.first-1.)*mult;
782 }
783 return std::make_pair(resP,resN);
784} // End of GetChExFactor
785
786// scatter (pPDG,p4M) on a virtual nucleon (NPDG,N4M), result: final pair(newN4M,newp4M)
787// if(newN4M.e()==0.) - below threshold, XS=0, no scattering of the progectile happened
788std::pair<G4LorentzVector,G4LorentzVector> G4QuasiElRatios::Scatter(G4int NPDG,
790{
791 static const G4double mNeut= G4Neutron::Neutron()->GetPDGMass();
792 static const G4double mProt= G4Proton::Proton()->GetPDGMass();
793 static const G4double mDeut= G4Deuteron::Deuteron()->GetPDGMass();
794 static const G4double mTrit= G4Triton::Triton()->GetPDGMass();
795 static const G4double mHel3= G4He3::He3()->GetPDGMass();
796 static const G4double mAlph= G4Alpha::Alpha()->GetPDGMass();
797
798 G4LorentzVector pr4M=p4M/megaelectronvolt; // Convert 4-momenta in MeV (keep p4M)
799 N4M/=megaelectronvolt;
800 G4LorentzVector tot4M=N4M+p4M;
801 G4double mT=mNeut;
802 G4int Z=0;
803 G4int N=1;
804 if(NPDG==2212||NPDG==90001000)
805 {
806 mT=mProt;
807 Z=1;
808 N=0;
809 }
810 else if(NPDG==90001001)
811 {
812 mT=mDeut;
813 Z=1;
814 N=1;
815 }
816 else if(NPDG==90002001)
817 {
818 mT=mHel3;
819 Z=2;
820 N=1;
821 }
822 else if(NPDG==90001002)
823 {
824 mT=mTrit;
825 Z=1;
826 N=2;
827 }
828 else if(NPDG==90002002)
829 {
830 mT=mAlph;
831 Z=2;
832 N=2;
833 }
834 else if(NPDG!=2112&&NPDG!=90000001)
835 {
836 G4cout<<"Error:G4QuasiElRatios::Scatter:NPDG="<<NPDG<<" is not 2212 or 2112"<<G4endl;
837 G4Exception("G4QuasiElRatios::Scatter:","21",FatalException,"QEcomplain");
838 //return std::make_pair(G4LorentzVector(0.,0.,0.,0.),p4M);// Use this if not exception
839 }
840 G4double mT2=mT*mT;
841 G4double mP2=pr4M.m2();
842 G4double E=(tot4M.m2()-mT2-mP2)/(mT+mT);
843 G4double E2=E*E;
844 if(E<0. || E2<mP2)
845 {
846 return std::make_pair(G4LorentzVector(0.,0.,0.,0.),p4M); // Do Nothing Action
847 }
848 G4double P=std::sqrt(E2-mP2); // Momentum in pseudo laboratory system
849 // @@ Temporary NN t-dependence for all hadrons
850 //if(pPDG>3400 || pPDG<-3400) G4cout<<"-Warning-G4QE::Scatter: pPDG="<<pPDG<<G4endl;
851 G4int PDG=2212; // *TMP* instead of pPDG
852 if(pPDG==2112||pPDG==-211||pPDG==-321) PDG=2112; // *TMP* instead of pPDG
853 if(!Z && N==1) // Change for Quasi-Elastic on neutron
854 {
855 Z=1;
856 N=0;
857 if (PDG==2212) PDG=2112;
858 else if(PDG==2112) PDG=2212;
859 }
860 G4double xSec=0.; // Prototype of Recalculated Cross Section *TMP*
861 if(PDG==2212) xSec=PCSmanager->GetChipsCrossSection(P, Z, N, PDG); // P CrossSect *TMP*
862 else xSec=NCSmanager->GetChipsCrossSection(P, Z, N, PDG); // N CrossSect *TMP*
863 // @@ check a possibility to separate p, n, or alpha (!)
864 if(xSec <= 0.) // The cross-section iz 0 -> Do Nothing
865 {
866 return std::make_pair(G4LorentzVector(0.,0.,0.,0.),p4M); //Do Nothing Action
867 }
868 G4double mint=0.; // Prototype of functional rand -t (MeV^2) *TMP*
869 if(PDG==2212) mint=PCSmanager->GetExchangeT(Z,N,PDG);// P functional rand -t(MeV^2) *TMP*
870 else mint=NCSmanager->GetExchangeT(Z,N,PDG);// N functional rand -t(MeV^2) *TMP*
871 G4double maxt=0.; // Prototype of max possible -t
872 if(PDG==2212) maxt=PCSmanager->GetHMaxT(); // max possible -t
873 else maxt=NCSmanager->GetHMaxT(); // max possible -t
874 G4double cost=1.-(mint+mint)/maxt; // cos(theta) in CMS
875 if(cost>1. || cost<-1. || !(cost>-1. || cost<=1.))
876 {
877 if (cost>1.) cost=1.;
878 else if(cost<-1.) cost=-1.;
879 else
880 {
881 G4double tm=0.;
882 if(PDG==2212) tm=PCSmanager->GetHMaxT();
883 else tm=NCSmanager->GetHMaxT();
884 G4cerr<<"G4QuasiFreeRatio::Scat:*NAN* cost="<<cost<<",-t="<<mint<<",tm="<<tm<<G4endl;
885 return std::make_pair(G4LorentzVector(0.,0.,0.,0.),p4M); // Do Nothing Action
886 }
887 }
888 G4LorentzVector reco4M=G4LorentzVector(0.,0.,0.,mT); // 4mom of the recoil nucleon
889 G4LorentzVector dir4M=tot4M-G4LorentzVector(0.,0.,0.,(tot4M.e()-mT)*.01);
890 if(!RelDecayIn2(tot4M, pr4M, reco4M, dir4M, cost, cost))
891 {
892 G4cerr<<"G4QFR::Scat:t="<<tot4M<<tot4M.m()<<",mT="<<mT<<",mP="<<std::sqrt(mP2)<<G4endl;
893 //G4Exception("G4QFR::Scat:","009",FatalException,"Decay of ElasticComp");
894 return std::make_pair(G4LorentzVector(0.,0.,0.,0.),p4M); // Do Nothing Action
895 }
896 return std::make_pair(reco4M*megaelectronvolt,pr4M*megaelectronvolt); // Result
897} // End of Scatter
898
899// scatter (pPDG,p4M) on a virtual nucleon (NPDG,N4M), result: final pair(newN4M,newp4M)
900// if(newN4M.e()==0.) - below threshold, XS=0, no scattering of the progectile happened
901// User should himself change the charge (PDG) (e.g. pn->np, pi+n->pi0p, pi-p->pi0n etc.)
902//AR-Jul2020: No need to change this method in order to extended quasi-elastic to
903// charmed and bottom mesons, because it is not used anywhere !
904std::pair<G4LorentzVector,G4LorentzVector> G4QuasiElRatios::ChExer(G4int NPDG,
906{
907 static const G4double mNeut= G4Neutron::Neutron()->GetPDGMass();
908 static const G4double mProt= G4Proton::Proton()->GetPDGMass();
909 G4LorentzVector pr4M=p4M/megaelectronvolt; // Convert 4-momenta in MeV(keep p4M)
910 N4M/=megaelectronvolt;
911 G4LorentzVector tot4M=N4M+p4M;
912 G4int Z=0;
913 G4int N=1;
914 G4int sPDG=0; // PDG code of the scattered hadron
915 G4double mS=0.; // proto of mass of scattered hadron
916 G4double mT=mProt; // mass of the recoil nucleon
917 if(NPDG==2212)
918 {
919 mT=mNeut;
920 Z=1;
921 N=0;
922 if(pPDG==-211) sPDG=111; // pi+ -> pi0
923 else if(pPDG==-321)
924 {
925 sPDG=310; // K+ -> K0S
926 if(G4UniformRand()>.5) sPDG=130; // K+ -> K0L
927 }
928 else if(pPDG==-311||pPDG==311||pPDG==130||pPDG==310) sPDG=321; // K0 -> K+ (?)
929 else if(pPDG==3112) sPDG=3212; // Sigma- -> Sigma0
930 else if(pPDG==3212) sPDG=3222; // Sigma0 -> Sigma+
931 else if(pPDG==3312) sPDG=3322; // Xi- -> Xi0
932 }
933 else if(NPDG==2112) // Default
934 {
935 if(pPDG==211) sPDG=111; // pi+ -> pi0
936 else if(pPDG==321)
937 {
938 sPDG=310; // K+ -> K0S
939 if(G4UniformRand()>.5) sPDG=130; // K+ -> K0L
940 }
941 else if(pPDG==-311||pPDG==311||pPDG==130||pPDG==310) sPDG=-321; // K0 -> K- (?)
942 else if(pPDG==3222) sPDG=3212; // Sigma+ -> Sigma0
943 else if(pPDG==3212) sPDG=3112; // Sigma0 -> Sigma-
944 else if(pPDG==3322) sPDG=3312; // Xi0 -> Xi-
945 }
946 else
947 {
948 G4cout<<"Error:G4QuasiElRatios::ChExer: NPDG="<<NPDG<<" is not 2212 or 2112"<<G4endl;
949 G4Exception("G4QuasiElRatios::ChExer:","21",FatalException,"QE complain");
950 //return std::make_pair(G4LorentzVector(0.,0.,0.,0.),p4M);// Use this if not exception
951 }
952 if(sPDG) mS=mNeut;
953 else
954 {
955 G4cout<<"Error:G4QuasiElRatios::ChExer: BAD pPDG="<<pPDG<<", NPDG="<<NPDG<<G4endl;
956 G4Exception("G4QuasiElRatios::ChExer:","21",FatalException,"QE complain");
957 //return std::make_pair(G4LorentzVector(0.,0.,0.,0.),p4M);// Use this if not exception
958 }
959 G4double mT2=mT*mT;
960 G4double mS2=mS*mS;
961 G4double E=(tot4M.m2()-mT2-mS2)/(mT+mT);
962 G4double E2=E*E;
963 if(E<0. || E2<mS2)
964 {
965 return std::make_pair(G4LorentzVector(0.,0.,0.,0.),p4M); // Do Nothing Action
966 }
967 G4double P=std::sqrt(E2-mS2); // Momentum in pseudo laboratory system
968 // @@ Temporary NN t-dependence for all hadrons
969 G4int PDG=2212; // *TMP* instead of pPDG
970 if(pPDG==2112||pPDG==-211||pPDG==-321) PDG=2112; // *TMP* instead of pPDG
971 if(!Z && N==1) // Change for Quasi-Elastic on neutron
972 {
973 Z=1;
974 N=0;
975 if (PDG==2212) PDG=2112;
976 else if(PDG==2112) PDG=2212;
977 }
978 G4double xSec=0.; // Prototype of Recalculated Cross Section *TMP*
979 if(PDG==2212) xSec=PCSmanager->GetChipsCrossSection(P, Z, N, PDG); // P CrossSect *TMP*
980 else xSec=NCSmanager->GetChipsCrossSection(P, Z, N, PDG); // N CrossSect *TMP*
981 // @@ check a possibility to separate p, n, or alpha (!)
982 if(xSec <= 0.) // The cross-section iz 0 -> Do Nothing
983 {
984 return std::make_pair(G4LorentzVector(0.,0.,0.,0.),p4M); //Do Nothing Action
985 }
986 G4double mint=0.; // Prototype of functional rand -t (MeV^2) *TMP*
987 if(PDG==2212) mint=PCSmanager->GetExchangeT(Z,N,PDG);// P functional rand -t(MeV^2) *TMP*
988 else mint=NCSmanager->GetExchangeT(Z,N,PDG);// N functional rand -t(MeV^2) *TMP*
989 G4double maxt=0.; // Prototype of max possible -t
990 if(PDG==2212) maxt=PCSmanager->GetHMaxT(); // max possible -t
991 else maxt=NCSmanager->GetHMaxT(); // max possible -t
992 G4double cost=1.-mint/maxt; // cos(theta) in CMS
993 if(cost>1. || cost<-1. || !(cost>-1. || cost<=1.))
994 {
995 if (cost>1.) cost=1.;
996 else if(cost<-1.) cost=-1.;
997 else
998 {
999 G4cerr<<"G4QuasiFreeRatio::ChExer:*NAN* c="<<cost<<",t="<<mint<<",tm="<<maxt<<G4endl;
1000 return std::make_pair(G4LorentzVector(0.,0.,0.,0.),p4M); // Do Nothing Action
1001 }
1002 }
1003 G4LorentzVector reco4M=G4LorentzVector(0.,0.,0.,mT); // 4mom of the recoil nucleon
1004 pr4M=G4LorentzVector(0.,0.,0.,mS); // 4mom of the scattered hadron
1005 G4LorentzVector dir4M=tot4M-G4LorentzVector(0.,0.,0.,(tot4M.e()-mT)*.01);
1006 if(!RelDecayIn2(tot4M, pr4M, reco4M, dir4M, cost, cost))
1007 {
1008 G4cerr<<"G4QFR::ChEx:t="<<tot4M<<tot4M.m()<<",mT="<<mT<<",mP="<<mS<<G4endl;
1009 //G4Exception("G4QFR::ChExer:","009",FatalException,"Decay of ElasticComp");
1010 return std::make_pair(G4LorentzVector(0.,0.,0.,0.),p4M); // Do Nothing Action
1011 }
1012 return std::make_pair(reco4M*megaelectronvolt,pr4M*megaelectronvolt); // Result
1013} // End of ChExer
1014
1015// Calculate ChEx/El ratio (p is in independent units, (Z,N) is target, pPDG is projectile)
1017{
1018
1019 p/=MeV; // Converted from independent units
1020 G4double A=Z+N;
1021 if(A<1.5) return 0.;
1022 G4double Cex=0.;
1023 if (pPDG==2212) Cex=N/(A+Z);
1024 else if(pPDG==2112) Cex=Z/(A+N);
1025 else G4cout<<"*Warning*G4CohChrgExchange::ChExElCoef: wrong PDG="<<pPDG<<G4endl;
1026 Cex*=Cex; // Coherent processes squares the amplitude
1027 // @@ This is true only for nucleons: other projectiles must be treated differently
1028 G4double sp=std::sqrt(p);
1029 G4double p2=p*p;
1030 G4double p4=p2*p2;
1031 G4double dl1=G4Log(p)-5.;
1032 G4double T=(6.75+.14*dl1*dl1+13./p)/(1.+.14/p4)+.6/(p4+.00013);
1033 G4double U=(6.25+8.33e-5/p4/p)*(p*sp+.34)/p2/p;
1034 G4double R=U/T;
1035 return Cex*R*R;
1036}
1037
1038// Decay of Hadron In2Particles f&s, f is in respect to the direction of HadronMomentumDir
1040 G4LorentzVector& dir, G4double maxCost, G4double minCost)
1041{
1042 G4double fM2 = f4Mom.m2();
1043 G4double fM = std::sqrt(fM2); // Mass of the 1st Hadron
1044 G4double sM2 = s4Mom.m2();
1045 G4double sM = std::sqrt(sM2); // Mass of the 2nd Hadron
1046 G4double iM2 = theMomentum.m2();
1047 G4double iM = std::sqrt(iM2); // Mass of the decaying hadron
1048 G4double vP = theMomentum.rho(); // Momentum of the decaying hadron
1049 G4double dE = theMomentum.e(); // Energy of the decaying hadron
1050 if(dE<vP)
1051 {
1052 G4cerr<<"***G4QHad::RelDecIn2: Tachionic 4-mom="<<theMomentum<<", E-p="<<dE-vP<<G4endl;
1053 G4double accuracy=.000001*vP;
1054 G4double emodif=std::fabs(dE-vP);
1055 //if(emodif<accuracy)
1056 //{
1057 G4cerr<<"G4QHadron::RelDecIn2: *Boost* E-p shift is corrected to "<<emodif<<G4endl;
1058 theMomentum.setE(vP+emodif+.01*accuracy);
1059 //}
1060 }
1061 G4ThreeVector ltb = theMomentum.boostVector();// Boost vector for backward Lorentz Trans.
1062 G4ThreeVector ltf = -ltb; // Boost vector for forward Lorentz Trans.
1063 G4LorentzVector cdir = dir; // A copy to make a transformation to CMS
1064 cdir.boost(ltf); // Direction transpormed to CMS of the Momentum
1065 G4ThreeVector vdir = cdir.vect(); // 3-Vector of the direction-particle
1066 G4ThreeVector vx(0.,0.,1.); // Ort in the direction of the reference particle
1067 G4ThreeVector vy(0.,1.,0.); // First ort orthogonal to the direction
1068 G4ThreeVector vz(1.,0.,0.); // Second ort orthoganal to the direction
1069 if(vdir.mag2() > 0.) // the refference particle isn't at rest in CMS
1070 {
1071 vx = vdir.unit(); // Ort in the direction of the reference particle
1072 G4ThreeVector vv= vx.orthogonal(); // Not normed orthogonal vector (!)
1073 vy = vv.unit(); // First ort orthogonal to the direction
1074 vz = vx.cross(vy); // Second ort orthoganal to the direction
1075 }
1076 if(maxCost> 1.) maxCost= 1.;
1077 if(minCost<-1.) minCost=-1.;
1078 if(maxCost<-1.) maxCost=-1.;
1079 if(minCost> 1.) minCost= 1.;
1080 if(minCost> maxCost) minCost=maxCost;
1081 if(std::fabs(iM-fM-sM)<.00000001)
1082 {
1083 G4double fR=fM/iM;
1084 G4double sR=sM/iM;
1085 f4Mom=fR*theMomentum;
1086 s4Mom=sR*theMomentum;
1087 return true;
1088 }
1089 else if (iM+.001<fM+sM || iM==0.)
1090 {//@@ Later on make a quark content check for the decay
1091 G4cerr<<"***G4QH::RelDecIn2: fM="<<fM<<"+sM="<<sM<<">iM="<<iM<<",d="<<iM-fM-sM<<G4endl;
1092 return false;
1093 }
1094 G4double d2 = iM2-fM2-sM2;
1095 G4double p2 = (d2*d2/4.-fM2*sM2)/iM2; // Decay momentum(^2) in CMS of Quasmon
1096 if(p2<0.)
1097 {
1098 p2=0.;
1099 }
1100 G4double p = std::sqrt(p2);
1101 G4double ct = maxCost;
1102 if(maxCost>minCost)
1103 {
1104 G4double dcost=maxCost-minCost;
1105 ct = minCost+dcost*G4UniformRand();
1106 }
1107 G4double phi= twopi*G4UniformRand(); // @@ Change 360.*deg to M_TWOPI (?)
1108 G4double pss=0.;
1109 if(std::fabs(ct)<1.) pss = p * std::sqrt(1.-ct*ct);
1110 else
1111 {
1112 if(ct>1.) ct=1.;
1113 if(ct<-1.) ct=-1.;
1114 }
1115 G4ThreeVector pVect=(pss*std::sin(phi))*vz+(pss*std::cos(phi))*vy+p*ct*vx;
1116
1117 f4Mom.setVect(pVect);
1118 f4Mom.setE(std::sqrt(fM2+p2));
1119 s4Mom.setVect((-1)*pVect);
1120 s4Mom.setE(std::sqrt(sM2+p2));
1121
1122 if(f4Mom.e()+.001<f4Mom.rho())G4cerr<<"*G4QH::RDIn2:*Boost* f4M="<<f4Mom<<",e-p="
1123 <<f4Mom.e()-f4Mom.rho()<<G4endl;
1124 f4Mom.boost(ltb); // Lor.Trans. of 1st hadron back to LS
1125 if(s4Mom.e()+.001<s4Mom.rho())G4cerr<<"*G4QH::RDIn2:*Boost* s4M="<<s4Mom<<",e-p="
1126 <<s4Mom.e()-s4Mom.rho()<<G4endl;
1127 s4Mom.boost(ltb); // Lor.Trans. of 2nd hadron back to LS
1128 return true;
1129} // End of "RelDecayIn2"
1130
1131
1132
1133
1134
1135
@ LE
Definition: Evaluator.cc:68
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:59
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
Definition: G4Exp.hh:180
G4double G4Log(G4double x)
Definition: G4Log.hh:227
CLHEP::HepLorentzVector G4LorentzVector
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
const G4int Z[17]
const G4double A[17]
G4GLOB_DLL std::ostream G4cerr
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
#define G4UniformRand()
Definition: Randomize.hh:52
Hep3Vector unit() const
Hep3Vector orthogonal() const
double mag2() const
Hep3Vector cross(const Hep3Vector &) const
Hep3Vector boostVector() const
HepLorentzVector & boost(double, double, double)
Hep3Vector vect() const
void setVect(const Hep3Vector &)
static G4Alpha * Alpha()
Definition: G4Alpha.cc:88
G4double GetExchangeT(G4int tZ, G4int tN, G4int pPDG)
static const char * Default_Name()
virtual G4double GetChipsCrossSection(G4double momentum, G4int Z, G4int N, G4int pdg)
G4double GetExchangeT(G4int tZ, G4int tN, G4int pPDG)
virtual G4double GetChipsCrossSection(G4double momentum, G4int Z, G4int N, G4int pdg)
static const char * Default_Name()
G4VCrossSectionDataSet * GetCrossSectionDataSet(const G4String &name, G4bool warning=false)
static G4CrossSectionDataSetRegistry * Instance()
static G4Deuteron * Deuteron()
Definition: G4Deuteron.cc:93
static G4He3 * He3()
Definition: G4He3.cc:93
static G4Neutron * Neutron()
Definition: G4Neutron.cc:103
static G4Pow * GetInstance()
Definition: G4Pow.cc:41
G4double powA(G4double A, G4double y) const
Definition: G4Pow.hh:230
static G4Proton * Proton()
Definition: G4Proton.cc:92
std::pair< G4double, G4double > GetChExFactor(G4double pIU, G4int pPDG, G4int Z, G4int N)
G4double ChExElCoef(G4double p, G4int Z, G4int N, G4int pPDG)
G4bool RelDecayIn2(G4LorentzVector &theMomentum, G4LorentzVector &f4Mom, G4LorentzVector &s4Mom, G4LorentzVector &dir, G4double maxCost=1., G4double minCost=-1.)
std::pair< G4double, G4double > FetchElTot(G4double pGeV, G4int PDG, G4bool F)
std::pair< G4LorentzVector, G4LorentzVector > ChExer(G4int NPDG, G4LorentzVector N4M, G4int pPDG, G4LorentzVector p4M)
std::pair< G4double, G4double > GetElTot(G4double pIU, G4int hPDG, G4int Z, G4int N)
std::pair< G4double, G4double > GetRatios(G4double pIU, G4int prPDG, G4int tgZ, G4int tgN)
std::pair< G4double, G4double > GetElTotXS(G4double Mom, G4int PDG, G4bool F)
std::pair< G4LorentzVector, G4LorentzVector > Scatter(G4int NPDG, G4LorentzVector N4M, G4int pPDG, G4LorentzVector p4M)
static G4Triton * Triton()
Definition: G4Triton.cc:93
#define N
Definition: crc32.c:56