Geant4  10.01.p01
G4INCLCrossSectionsMultiPions.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 // INCL++ intra-nuclear cascade model
27 // Alain Boudard, CEA-Saclay, France
28 // Joseph Cugnon, University of Liege, Belgium
29 // Jean-Christophe David, CEA-Saclay, France
30 // Pekka Kaitaniemi, CEA-Saclay, France, and Helsinki Institute of Physics, Finland
31 // Sylvie Leray, CEA-Saclay, France
32 // Davide Mancusi, CEA-Saclay, France
33 //
34 #define INCLXX_IN_GEANT4_MODE 1
35 
36 #include "globals.hh"
37 
39 #include "G4INCLKinematicsUtils.hh"
40 #include "G4INCLParticleTable.hh"
41 #include "G4INCLLogger.hh"
42 // #include <cassert>
43 
44 namespace G4INCL {
45 
46  template<G4int N>
48  static G4double eval(const G4double pLab, const G4double oneOverThreshold, HornerCoefficients<N> const &coeffs) {
49  const G4double pMeV = pLab*1E3;
51  const G4double xrat=ekin*oneOverThreshold;
52  const G4double x=std::log(xrat);
53  return HornerEvaluator<N>::eval(x, coeffs) * x * std::exp(-0.5*x);
54  }
55  };
56 
57  const G4double CrossSectionsMultiPions::s11pzOOT = 0.0035761542037692665889;
58  const G4double CrossSectionsMultiPions::s01ppOOT = 0.003421025623481919853;
59  const G4double CrossSectionsMultiPions::s01pzOOT = 0.0035739814152966403123;
60  const G4double CrossSectionsMultiPions::s11pmOOT = 0.0034855350296270480281;
61  const G4double CrossSectionsMultiPions::s12pmOOT = 0.0016672224074691565119;
62  const G4double CrossSectionsMultiPions::s12ppOOT = 0.0016507643038726931312;
63  const G4double CrossSectionsMultiPions::s12zzOOT = 0.0011111111111111111111;
65  const G4double CrossSectionsMultiPions::s02pmOOT = 0.0016661112962345883443;
66  const G4double CrossSectionsMultiPions::s12mzOOT = 0.0017047391749062392793;
67 
69  s11pzHC(-2.228000000000294018,8.7560000000005723725,-0.61000000000023239325,-5.4139999999999780324,3.3338333333333348023,-0.75835000000000022049,0.060623611111111114688),
70  s01ppHC(2.0570000000126518344,-6.029000000012135826,36.768500000002462784,-45.275666666666553533,25.112666666666611953,-7.2174166666666639187,1.0478875000000000275,-0.060804365079365080846),
71  s01pzHC(0.18030000000000441851,7.8700999999999953598,-4.0548999999999990425,0.555199999999999959),
72  s11pmHC(0.20590000000000031866,3.3450999999999993936,-1.4401999999999997825,0.17076666666666664973),
73  s12pmHC(-0.77235999999999901328,4.2626599999999991117,-1.9008899999999997323,0.30192266666666663379,-0.012270833333333331986),
74  s12ppHC(-0.75724999999999975664,2.0934399999999998565,-0.3803099999999999814),
75  s12zzHC(-0.89599999999996965072,7.882999999999978632,-7.1049999999999961928,1.884333333333333089),
76  s02pzHC(-1.0579999999999967036,11.113999999999994089,-8.5259999999999990196,2.0051666666666666525),
77  s02pmHC(2.4009000000012553286,-7.7680000000013376183,20.619000000000433505,-16.429666666666723928,5.2525708333333363472,-0.58969166666666670206),
78  s12mzHC(-0.21858699999999976269,1.9148999999999999722,-0.31727500000000001065,-0.027695000000000000486)
79  {
80  }
81 
82  G4double CrossSectionsMultiPions::NNElastic(Particle const * const part1, Particle const * const part2) {
83 
84  /* The NN cross section is parametrised as a function of the lab momentum
85  * of one of the nucleons. For NDelta or DeltaDelta, the physical
86  * assumption is that the cross section is the same as NN *for the same
87  * total CM energy*. Thus, we calculate s from the particles involved, and
88  * we convert this value to the lab momentum of a nucleon *as if this were
89  * an NN collision*.
90  */
92 
93  if(part1->isNucleon() && part2->isNucleon()) { // NN
94  const G4int i = ParticleTable::getIsospin(part1->getType())
96  return NNElasticFixed(s, i);
97  }
98  else { // Nucleon-Delta and Delta-Delta
100  if (plab < 0.440) {
101  return 34.*std::pow(plab/0.4, (-2.104));
102  }
103  else if (plab < 0.800) {
104  return 23.5+1000.*std::pow(plab-0.7, 4);
105  }
106  else if (plab <= 2.0) {
107  return 1250./(50.+plab)-4.*std::pow(plab-1.3, 2);
108  }
109  else {
110  return 77./(plab+1.5);
111  }
112  }
113  }
114 
116 
117  /* From NNElastic, with isospin fixed and for NN only.
118  */
119 
121 
122  if (i == 0) { // pn
123  if (plab < 0.446) {
124  G4double alp=std::log(plab);
125  return 6.3555*std::exp(-3.2481*alp-0.377*alp*alp);
126  }
127  else if (plab < 0.851) {
128  return 33.+196.*std::pow(std::fabs(plab-0.95),2.5);
129  }
130  else if (plab <= 2.0) {
131  return 31./std::sqrt(plab);
132  }
133  else {
134  return 77./(plab+1.5);
135  }
136  }
137  else { // pp and nn
138  if (plab < 0.440) {
139  return 34.*std::pow(plab/0.4, (-2.104));
140  }
141  else if (plab < 0.8067) {
142  return 23.5+1000.*std::pow(plab-0.7, 4);
143  }
144  else if (plab <= 2.0) {
145  return 1250./(50.+plab)-4.*std::pow(plab-1.3, 2);
146  }
147  else if (plab <= 3.0956) {
148  return 77./(plab+1.5);
149  }
150  else {
151  G4double alp=std::log(plab);
152  return 11.2+25.5*std::pow(plab, -1.12)+0.151*std::pow(alp, 2)-1.62*alp;
153  }
154  }
155  }
156 
157  G4double CrossSectionsMultiPions::NNTot(Particle const * const part1, Particle const * const part2) {
158 
161 
162  if(part1->isNucleon() && part2->isNucleon()) { // NN
163  const G4double s = KinematicsUtils::squareTotalEnergyInCM(part1, part2);
164  return NNTotFixed(s, i);
165  }
166  else if (part1->isDelta() && part2->isDelta()) { // Delta-Delta
167  return elastic(part1, part2);
168  }
169  else { // Nucleon-Delta
170  return NDeltaToNN(part1, part2) + elastic(part1, part2);
171  }
172  }
173 
175 
176  /* From NNTot, with isospin fixed and for NN only.
177  */
178 
180 
181  if (i == 0) { // pn
182  if (plab < 0.446) {
183  G4double alp=std::log(plab);
184  return 6.3555*std::exp(-3.2481*alp-0.377*std::pow(alp, 2));
185  }
186  else if (plab < 1.0) {
187  return 33.+196.*std::sqrt(std::pow(std::fabs(plab-0.95),5));
188  }
189  else if (plab < 1.924) {
190  return 24.2+8.9*plab;
191  }
192  else {
193  G4double alp=std::log(plab);
194  return 48.9-33.7*std::pow(plab, -3.08)+0.619*std::pow(alp, 2)-5.12*alp;
195  }
196  }
197  else { // pp and nn
198  if (plab < 0.440) {
199  return 34.*std::pow(plab/0.4, (-2.104));
200  }
201  else if (plab < 0.8734) {
202  return 23.5+1000.*std::pow(plab-0.7, 4);
203  }
204  else if (plab < 1.5) {
205  return 23.5+24.6/(1.+std::exp(-10.*(plab-1.2)));
206  }
207  else if (plab < 3.0044) {
208  return 41.+60.*(plab-0.9)*std::exp(-1.2*plab);
209  }
210  else {
211  G4double alp=std::log(plab);
212  return 45.6+219.*std::pow(plab, -4.23)+0.41*std::pow(alp, 2)-3.41*alp;
213  }
214  }
215  }
216 
218 
219  const G4double s = ener*ener;
220  G4double sincl;
221 
222  if (iso != 0) {
223  if(s>=4074595.287720512986) { // plab>800 MeV/c
224  sincl = NNTotFixed(s, 2)-NNElasticFixed(s, 2);
225  }
226  else {
227  sincl = 0. ;
228  }
229  } else {
230  if(s>=4074595.287720512986) { // plab>800 MeV/c
231  sincl = 2*(NNTotFixed(s, 0)-NNElasticFixed(s, 0))-(NNTotFixed(s, 2)-NNElasticFixed(s, 2));
232  }
233  else {
234  return 0. ;
235  }
236  }
237  if (sincl < 0.) sincl = 0.;
238  return sincl;
239  }
240 
242 
243  /* Article J. Physique 48 (1987)1901-1924 "Energy dependence of
244  nucleon-cucleon inelastic total cross-sections."
245  J. Bystricky, P. La France, F. Lehar, F. Perrot, T. Siemiarczuk & P. Winternitz
246  S11PZ= section pp->pp pi0
247  S01PP= section pp->pn pi+
248  S01PZ= section pn->pn pi0
249  S11PM= section pn->pp pi-
250  S= X-Section, 1st number : 1 if pp and 0 if pn
251  2nd number = number of pions, PP= pi+; PZ= pi0 ; PM= pi-
252  */
253 
254  const G4double s = ener*ener;
256 
257  G4double snnpit1=0.;
258  G4double snnpit=0.;
259  G4double s11pz=0.;
260  G4double s01pp=0.;
261  G4double s01pz=0.;
262  G4double s11pm=0.;
263 
264  if ((iso != 0) && (plab < 2.1989)) {
265  snnpit = xsiso - NNTwoPi(ener, iso, xsiso);
266  if (snnpit < 1.e-8) snnpit=0.;
267  return snnpit;
268  }
269  else if ((iso == 0) && (plab < 1.7369)) {
270  snnpit = xsiso;
271  if (snnpit < 1.e-8) snnpit=0.;
272  return snnpit;
273  }
274 
275 //s11pz
276  if (plab > 18.) {
277  s11pz=55.185/std::pow((0.1412*plab+5),2);
278  }
279  else if (plab > 13.9) {
280  G4double alp=std::log(plab);
281  s11pz=6.67-13.3*std::pow(plab, -6.18)+0.456*alp*alp-3.29*alp;
282  }
283  else if (plab >= 0.7765) {
285  s11pz=b*b;
286  }
287 //s01pp
288  if (plab >= 0.79624) {
290  s01pp=b*b;
291  }
292 
293 // channel T=1
294  snnpit1=s11pz+s01pp;
295  if (snnpit1 < 1.e-8) snnpit1=0.;
296  if (iso != 0) {
297  return snnpit1;
298  }
299 
300 //s01pz
301  if (plab > 4.5) {
302  s01pz=15289.4/std::pow((11.573*plab+5),2);
303  }
304  else if (plab >= 0.777) {
306  s01pz=b*b;
307  }
308 //s11pm
309  if (plab > 14.) {
310  s11pm=46.68/std::pow((0.2231*plab+5),2);
311  }
312  else if (plab >= 0.788) {
314  s11pm=b*b;
315  }
316 
317 // channel T=0
318  snnpit=2*(s01pz+2*s11pm)-snnpit1;
319  if (snnpit < 1.e-8) snnpit=0.;
320  return snnpit;
321  }
322 
323  G4double CrossSectionsMultiPions::NNTwoPi(const G4double ener, const G4int iso, const G4double xsiso) {
324 
325  /* Article J. Physique 48 (1987)1901-1924 "Energy dependence of nucleon-cucleon inelastic total cross-sections."
326  J. Bystricky, P. La France, F. Lehar, F. Perrot, T. Siemiarczuk & P. Winternitz
327  S12PM : pp -> pp Pi+ Pi-
328  S12ZZ : pp -> pp Pi0 Pi0
329  S12PP : pp -> nn Pi+ Pi+
330  S02PZ : pp -> pn Pi+ Pi0
331  S02PM : pn -> pn Pi+ Pi-
332  S12MZ : pn -> pp Pi- Pi0
333  */
334 
335  const G4double s = ener*ener;
337 
338  G4double snn2pit=0.;
339  G4double s12pm=0.;
340  G4double s12pp=0.;
341  G4double s12zz=0.;
342  G4double s02pz=0.;
343  G4double s02pm=0.;
344  G4double s12mz=0.;
345 
346  if (iso==0 && plab<3.3) {
347  snn2pit = xsiso - NNOnePiOrDelta(ener, iso, xsiso);
348  if (snn2pit < 1.e-8) snn2pit=0.;
349  return snn2pit;
350  }
351 
352  if (iso != 0) {
353 //s12pm
354  if (plab > 15.) {
355  s12pm=25.977/plab;
356  }
357  else if (plab >= 1.3817) {
359  s12pm=b*b;
360  }
361 //s12pp
362  if (plab > 10.) {
363  s12pp=141.505/std::pow((-0.1016*plab-7),2);
364  }
365  else if (plab >= 1.5739) {
367  s12pp=b*b;
368  }
369  }
370 //s12zz
371  if (plab > 4.) {
372  s12zz=97.355/std::pow((1.1579*plab+5),2);
373  }
374  else if (plab >= 1.72207) {
376  s12zz=b*b;
377  }
378 //s02pz
379  if (plab > 4.5) {
380  s02pz=178.082/std::pow((0.2014*plab+5),2);
381  }
382  else if (plab >= 1.5656) {
384  s02pz=b*b;
385  }
386 
387 // channel T=1
388  if (iso != 0) {
389  snn2pit=s12pm+s12pp+s12zz+s02pz;
390  if (snn2pit < 1.e-8) snn2pit=0.;
391  return snn2pit;
392  }
393 
394 //s02pm
395  if (plab > 5.) {
396  s02pm=135.826/std::pow(plab,2);
397  }
398  else if (plab >= 1.21925) {
400  s02pm=b*b;
401  }
402 //s12mz
403  if (plab >= 1.29269) {
405  s12mz=b*b;
406  }
407 
408 // channel T=0
409  snn2pit=3*(s02pm+0.5*s12mz-0.5*s02pz-s12zz);
410  if (snn2pit < 1.e-8) snn2pit=0.;
411  return snn2pit;
412  }
413 
414  G4double CrossSectionsMultiPions::NNThreePi(const G4double ener, const G4int iso, const G4double xsiso, const G4double xs1pi, const G4double xs2pi) {
415 
416  const G4double s = ener*ener;
418 
419  G4double snn3pit=0.;
420 
421  if (iso == 0) {
422 // channel T=0
423  if (plab > 7.2355) {
424  return 46.72/std::pow((plab - 5.8821),2);
425  }
426  else {
427  snn3pit=xsiso-xs1pi-xs2pi;
428  if (snn3pit < 1.e-8) snn3pit=0.;
429  return snn3pit;
430  }
431  }
432  else {
433 // channel T=1
434  if (plab > 7.206) {
435  return 5592.92/std::pow((plab+14.9764),2);
436  }
437  else if (plab > 2.1989){
438  snn3pit=xsiso-xs1pi-xs2pi;
439  if (snn3pit < 1.e-8) snn3pit=0.;
440  return snn3pit;
441  }
442  else return snn3pit;
443  }
444  }
445 
446  G4double CrossSectionsMultiPions::NNOnePi(Particle const * const particle1, Particle const * const particle2) {
447  // Cross section for nucleon-nucleon directly producing one pion
448 
449  const G4int iso=ParticleTable::getIsospin(particle1->getType()) + ParticleTable::getIsospin(particle2->getType());
450  if (iso!=0)
451  return 0.;
452 
453  const G4double ener=KinematicsUtils::totalEnergyInCM(particle1, particle2);
454 
455  const G4double xsiso2=NNInelasticIso(ener, 2);
456  const G4double xsiso0=NNInelasticIso(ener, 0);
457  return 0.25*(NNOnePiOrDelta(ener, 0, xsiso0)+ NNOnePiOrDelta(ener, 2, xsiso2));
458  }
459 
460  G4double CrossSectionsMultiPions::NNOnePiOrDelta(Particle const * const particle1, Particle const * const particle2) {
461  // Cross section for nucleon-nucleon directly producing one pion or producing a nucleon-delta pair
462  const G4double ener=KinematicsUtils::totalEnergyInCM(particle1, particle2);
463  const G4int iso=ParticleTable::getIsospin(particle1->getType()) + ParticleTable::getIsospin(particle2->getType());
464 
465  const G4double xsiso2=NNInelasticIso(ener, 2);
466  if (iso != 0)
467  return NNOnePiOrDelta(ener, iso, xsiso2);
468  else {
469  const G4double xsiso0=NNInelasticIso(ener, 0);
470  return 0.5*(NNOnePiOrDelta(ener, 0, xsiso0)+ NNOnePiOrDelta(ener, 2, xsiso2));
471  }
472  }
473 
474  G4double CrossSectionsMultiPions::NNTwoPi(Particle const * const particle1, Particle const * const particle2) {
475  //
476  // Nucleon-Nucleon producing one pion cross sections
477  //
478  const G4double ener=KinematicsUtils::totalEnergyInCM(particle1, particle2);
479  const G4int iso=ParticleTable::getIsospin(particle1->getType()) + ParticleTable::getIsospin(particle2->getType());
480 
481 
482  const G4double xsiso2=NNInelasticIso(ener, 2);
483  if (iso != 0) {
484  return NNTwoPi(ener, 2, xsiso2);
485  }
486  else {
487  const G4double xsiso0=NNInelasticIso(ener, 0);
488  return 0.5*(NNTwoPi(ener, 0, xsiso0)+ NNTwoPi(ener, 2, xsiso2));
489  }
490  return 0.0; // Should never reach this point
491  }
492 
493  G4double CrossSectionsMultiPions::NNThreePi(Particle const * const particle1, Particle const * const particle2) {
494  //
495  // Nucleon-Nucleon producing one pion cross sections
496  //
497 
498  const G4double ener=KinematicsUtils::totalEnergyInCM(particle1, particle2);
499  const G4int iso=ParticleTable::getIsospin(particle1->getType()) + ParticleTable::getIsospin(particle2->getType());
500 
501 
502  const G4double xsiso2=NNInelasticIso(ener, 2);
503  const G4double xs1pi2=NNOnePiOrDelta(ener, 2, xsiso2);
504  const G4double xs2pi2=NNTwoPi(ener, 2, xsiso2);
505  if (iso != 0)
506  return NNThreePi(ener, 2, xsiso2, xs1pi2, xs2pi2);
507  else {
508  const G4double xsiso0=NNInelasticIso(ener, 0);
509  const G4double xs1pi0=NNOnePiOrDelta(ener, 0, xsiso0);
510  const G4double xs2pi0=NNTwoPi(ener, 0, xsiso0);
511  return 0.5*(NNThreePi(ener, 0, xsiso0, xs1pi0, xs2pi0)+ NNThreePi(ener, 2, xsiso2, xs1pi2, xs2pi2));
512  }
513  }
514 
515  G4double CrossSectionsMultiPions::NNFourPi(Particle const * const particle1, Particle const * const particle2) {
516  const G4double s = KinematicsUtils::squareTotalEnergyInCM(particle1, particle2);
517  if(s<6.25E6)
518  return 0.;
519  const G4double sigma = NNTot(particle1, particle2) - NNElastic(particle1, particle2) - NNOnePiOrDelta(particle1, particle2) - NNTwoPi(particle1, particle2) - NNThreePi(particle1, particle2);
520  return ((sigma>0.) ? sigma : 0.);
521  }
522 
523  G4double CrossSectionsMultiPions::NNToxPiNN(const G4int xpi, Particle const * const particle1, Particle const * const particle2) {
524  //
525  // Nucleon-Nucleon producing xpi pions cross sections
526  //
527 // assert(xpi>0 && xpi<5);
528 // assert(particle1->isNucleon() && particle2->isNucleon());
529 
530  if (xpi == 1)
531  return NNOnePi(particle1, particle2);
532  else if (xpi == 2)
533  return NNTwoPi(particle1, particle2);
534  else if (xpi == 3)
535  return NNThreePi(particle1, particle2);
536  else // if (xpi == 4)
537  return NNFourPi(particle1, particle2);
538  }
539 
540 
542  // HE and LE pi- p and pi+ n
543  G4double ramass = 0.0;
544 
545  if(x <= 1306.0) {
546  G4double y = x*x;
547  G4double q2;
548  q2=(y-std::pow(1076.0, 2))*(y-std::pow(800.0, 2))/(4.0*y);
549  if (q2 > 0.) {
550  G4double q3=std::pow(q2, 3./2.);
551  G4double f3=q3/(q3+std::pow(180.0, 3));
552  G4double sdel;
553  sdel=326.5/(std::pow((x-1215.0-ramass)*2.0/110.0,2)+1.0);
554  return sdel*f3*(1.0-5.0*ramass/1215.0);
555  }
556  else {
557  return 0;
558  }
559  }
560  if(x <= 1754.0) {
561  return -2.33730e-06*std::pow(x, 3)+1.13819e-02*std::pow(x,2)
562  -1.83993e+01*x+9893.4;
563  } else if (x <= 2150.0) {
564  return 1.13531e-06*std::pow(x, 3)-6.91694e-03*std::pow(x, 2)
565  +1.39907e+01*x-9360.76;
566  } else {
567  return -3.18087*std::log(x)+52.9784;
568  }
569  }
570 
572  // HE pi- p and pi+ n
573  G4double ramass = 0.0;
574 
575  if(x <= 1275.8) {
576  G4double y = x*x;
577  G4double q2;
578  q2=(y-std::pow(1076.0, 2))*(y-std::pow(800.0, 2))/(4.0*y);
579  if (q2 > 0.) {
580  G4double q3=std::pow(q2, 3./2.);
581  G4double f3=q3/(q3+std::pow(180.0, 3));
582  G4double sdel;
583  sdel=326.5/(std::pow((x-1215.0-ramass)*2.0/110.0,2)+1.0);
584  return sdel*f3*(1.0-5.0*ramass/1215.0)/3.;
585  }
586  else {
587  return 0;
588  }
589  }
590  if(x <= 1495.0) {
591  return 0.00120683*(x-1372.52)*(x-1372.52)+26.2058;
592  } else if(x <= 1578.0) {
593  return 1.15873e-05*x*x+49965.6/((x-1519.59)*(x-1519.59)+2372.55);
594  } else if(x <= 2028.4) {
595  return 34.0248+43262.2/((x-1681.65)*(x-1681.65)+1689.35);
596  } else if(x <= 7500.0) {
597  return 3.3e-7*(x-7500.0)*(x-7500.0)+24.5;
598  } else {
599  return 24.5;
600  }
601  }
602 
603  G4double CrossSectionsMultiPions::total(Particle const * const p1, Particle const * const p2) {
604  G4double inelastic;
605  if(p1->isNucleon() && p2->isNucleon()) {
606  return NNTot(p1, p2);
607  } else if((p1->isNucleon() && p2->isDelta()) ||
608  (p1->isDelta() && p2->isNucleon())) {
609  inelastic = NDeltaToNN(p1, p2);
610  } else if((p1->isNucleon() && p2->isPion()) ||
611  (p1->isPion() && p2->isNucleon())) {
612  return piNTot(p1,p2);
613  } else {
614  inelastic = 0.;
615  }
616 
617  return inelastic + elastic(p1, p2);
618  }
619 
620 
621  G4double CrossSectionsMultiPions::piNIne(Particle const * const particle1, Particle const * const particle2) {
622  // piN inelastic cross section (Delta excluded)
623 
624  const Particle *pion;
625  const Particle *nucleon;
626  if(particle1->isNucleon()) {
627  nucleon = particle1;
628  pion = particle2;
629  } else {
630  pion = particle1;
631  nucleon = particle2;
632  }
633 // assert(pion->isPion());
634 
635  const G4double pLab = KinematicsUtils::momentumInLab(pion, nucleon);
636 
637  // these limits correspond to sqrt(s)=1230 and 20000 MeV
638  if(pLab>212677. || pLab<296.367)
639  return 0.0;
640 
641  const G4int ipit3 = ParticleTable::getIsospin(pion->getType());
642  const G4int ind2t3 = ParticleTable::getIsospin(nucleon->getType());
643  const G4int cg = 4 + ind2t3*ipit3;
644 // assert(cg==2 || cg==4 || cg==6);
645 
646  const G4double p1=1e-3*pLab;
647  const G4double p2=std::log(p1);
648  G4double xpipp = 0.0;
649  G4double xpimp = 0.0;
650 
651  if(cg!=2) {
652  // x-section pi+ p inelastique :
653  if(p1<=0.75)
654  xpipp=17.965*std::pow(p1, 5.4606);
655  else
656  xpipp=24.3-12.3*std::pow(p1, -1.91)+0.324*p2*p2-2.44*p2;
657  if(cg==6)
658  // cas pi+ p et pi- n
659  return xpipp;
660  }
661 
662  // x-section pi- p inelastique :
663  if(p1 <= 0.4731)
664  xpimp=0;
665  else
666  xpimp=26.6-7.18*std::pow(p1, -1.86)+0.327*p2*p2-2.81*p2;
667  if(xpimp<0.)
668  xpimp=0;
669 
670  if(cg==2) // cas pi- p et pi+ n
671  return xpimp;
672  else // cas pi0 p et pi0 n
673  return 0.5*(xpipp+xpimp);
674  }
675 
676  G4double CrossSectionsMultiPions::piNToDelta(Particle const * const particle1, Particle const * const particle2) {
677  // piN Delta production
678 
679  G4double x = KinematicsUtils::totalEnergyInCM(particle1, particle2);
680  if(x>20000.) return 0.0; // no cross section above this value
681 
682  G4int ipit3 = 0;
683  G4int ind2t3 = 0;
684  const G4double ramass = 0.0;
685 
686  if(particle1->isPion()) {
687  ipit3 = ParticleTable::getIsospin(particle1->getType());
688  ind2t3 = ParticleTable::getIsospin(particle2->getType());
689  } else if(particle2->isPion()) {
690  ipit3 = ParticleTable::getIsospin(particle2->getType());
691  ind2t3 = ParticleTable::getIsospin(particle1->getType());
692  }
693 
694  const G4double y=x*x;
695  const G4double q2=(y-1076.0*1076.0)*(y-800.0*800.0)/y/4.0;
696  if (q2 <= 0.) {
697  return 0.0;
698  }
699  const G4double q3 = std::pow(std::sqrt(q2),3);
700  const G4double f3 = q3/(q3 + 5832000.); // 5832000 = 180^3
701  G4double sdelResult = 326.5/(std::pow((x-1215.0-ramass)*2.0/(110.0-ramass), 2)+1.0);
702  sdelResult = sdelResult*(1.0-5.0*ramass/1215.0);
703  const G4int cg = 4 + ind2t3*ipit3;
704  sdelResult = sdelResult*f3*cg/6.0;
705 
706  return sdelResult;
707  }
708 
709  G4double CrossSectionsMultiPions::piNTot(Particle const * const particle1, Particle const * const particle2) {
710  // FUNCTION SPN(X,IND2T3,IPIT3,f17)
711  // SIGMA(PI+ + P) IN THE (3,3) REGION
712  // NEW FIT BY J.VANDERMEULEN + FIT BY Th AOUST ABOVE (3,3) RES
713  // CONST AT LOW AND VERY HIGH ENERGY
714  // COMMON/BL8/RATHR,RAMASS REL21800
715  // integer f17
716  // RATHR and RAMASS are always 0.0!!!
717 
718  G4double x = KinematicsUtils::totalEnergyInCM(particle1, particle2);
719 
720  G4int ipit3 = 0;
721  G4int ind2t3 = 0;
722 
723  if(particle1->isPion()) {
724  ipit3 = ParticleTable::getIsospin(particle1->getType());
725  ind2t3 = ParticleTable::getIsospin(particle2->getType());
726  } else if(particle2->isPion()) {
727  ipit3 = ParticleTable::getIsospin(particle2->getType());
728  ind2t3 = ParticleTable::getIsospin(particle1->getType());
729  }
730 
731  G4double spnResult=0.0;
732 
733  // HE pi+ p and pi- n
734  if((ind2t3 == 1 && ipit3 == 2) || (ind2t3 == -1 && ipit3 == -2))
735  spnResult=spnPiPlusPHE(x);
736  else if((ind2t3 == 1 && ipit3 == -2) || (ind2t3 == -1 && ipit3 == 2))
737  spnResult=spnPiMinusPHE(x);
738  else if(ipit3 == 0) spnResult = (spnPiPlusPHE(x) + spnPiMinusPHE(x))/2.0; // (spnpipphe(x)+spnpimphe(x))/2.0
739  else {
740  INCL_ERROR("Unknown configuration!\n" << particle1->print() << particle2->print() << '\n');
741  }
742 
743  return spnResult;
744  }
745 
746  G4double CrossSectionsMultiPions::NDeltaToNN(Particle const * const p1, Particle const * const p2) {
748  if(isospin==4 || isospin==-4) return 0.0;
749 
751  G4double Ecm = std::sqrt(s);
752  G4int deltaIsospin;
753  G4double deltaMass;
754  if(p1->isDelta()) {
755  deltaIsospin = ParticleTable::getIsospin(p1->getType());
756  deltaMass = p1->getMass();
757  } else {
758  deltaIsospin = ParticleTable::getIsospin(p2->getType());
759  deltaMass = p2->getMass();
760  }
761 
762  if(Ecm <= 938.3 + deltaMass) {
763  return 0.0;
764  }
765 
766  if(Ecm < 938.3 + deltaMass + 2.0) {
767  Ecm = 938.3 + deltaMass + 2.0;
768  s = Ecm*Ecm;
769  }
770 
772  (s - std::pow(ParticleTable::effectiveNucleonMass + deltaMass, 2));
773  const G4double y = s/(s - std::pow(deltaMass - ParticleTable::effectiveNucleonMass, 2));
774  /* Concerning the way we calculate the lab momentum, see the considerations
775  * in CrossSections::elasticNNLegacy().
776  */
777  G4double sDelta;
778  const G4double xsiso2=NNInelasticIso(Ecm, 2);
779  if (isospin != 0)
780  sDelta = NNOnePiOrDelta(Ecm, isospin, xsiso2);
781  else {
782  const G4double xsiso0=NNInelasticIso(Ecm, 0);
783  sDelta = 0.25*(NNOnePiOrDelta(Ecm, 0, xsiso0)+ NNOnePiOrDelta(Ecm, 2, xsiso2));
784  }
785  G4double result = 0.5 * x * y * sDelta;
786  /* modification for pion-induced cascade (see JC and MC LEMAIRE,NPA489(88)781
787  * result=3.*result
788  * pi absorption increased also for internal pions (7/3/01)
789  */
790  result *= 3.*(32.0 + isospin * isospin * (deltaIsospin * deltaIsospin - 5))/64.0;
791  result /= 1.0 + 0.25 * (isospin * isospin);
792  return result;
793  }
794 
795  G4double CrossSectionsMultiPions::NNToNDelta(Particle const * const p1, Particle const * const p2) {
796 // assert(p1->isNucleon() && p2->isNucleon());
798  G4double sigma = NNOnePiOrDelta(p1, p2);
799  if(isospin==0)
800  sigma *= 0.5;
801  return sigma;
802  }
803 
804  G4double CrossSectionsMultiPions::elastic(Particle const * const p1, Particle const * const p2) {
805  if(!p1->isPion() && !p2->isPion()){
806  return NNElastic(p1, p2);
807  }
808  else if (p1->isNucleon() || p2->isNucleon()){
809  G4double pielas = piNTot(p1,p2) - piNIne(p1,p2) - piNToDelta(p1,p2);
810  if (pielas < 0.){
811  pielas = 0.;
812  }
813 // return piNTot(p1,p2) - piNIne(p1,p2) - piNToDelta(p1,p2);
814  return pielas;
815  }
816  else {
817  return 0.0;
818  }
819  }
820 
822  G4double x = 0.001 * pl; // Change to GeV
823  if(iso != 0) {
824  if(pl <= 2000.0) {
825  x = std::pow(x, 8);
826  return 5.5e-6 * x/(7.7 + x);
827  } else {
828  return (5.34 + 0.67*(x - 2.0)) * 1.0e-6;
829  }
830  } else {
831  if(pl < 800.0) {
832  G4double b = (7.16 - 1.63*x) * 1.0e-6;
833  return b/(1.0 + std::exp(-(x - 0.45)/0.05));
834  } else if(pl < 1100.0) {
835  return (9.87 - 4.88 * x) * 1.0e-6;
836  } else {
837  return (3.68 + 0.76*x) * 1.0e-6;
838  }
839  }
840  return 0.0; // Should never reach this point
841  }
842 
843 
844  G4double CrossSectionsMultiPions::piNToxPiN(const G4int xpi, Particle const * const particle1, Particle const * const particle2) {
845  //
846  // pion-Nucleon producing xpi pions cross sections
847  //
848 // assert(xpi>1 && xpi<5);
849  if (xpi == 2)
850  return piNOnePi(particle1,particle2);
851  else if (xpi == 3)
852  return piNTwoPi(particle1,particle2);
853  else if (xpi == 4) {
854  const G4double piNThreePi = piNIne(particle1,particle2) - piNOnePi(particle1,particle2) - piNTwoPi(particle1,particle2);
855  return piNThreePi;
856  }
857  return 0.0; // Should never reach this point
858  }
859 
860  G4double CrossSectionsMultiPions::piNOnePi(Particle const * const particle1, Particle const * const particle2) {
861  const Particle *pion;
862  const Particle *nucleon;
863  if(particle1->isNucleon()) {
864  nucleon = particle1;
865  pion = particle2;
866  } else {
867  pion = particle1;
868  nucleon = particle2;
869  }
870 // assert(pion->isPion());
871 
872  const G4double pLab = KinematicsUtils::momentumInLab(pion, nucleon);
873 
874  // this limit corresponds to sqrt(s)=1230 MeV
875  if(pLab<296.367)
876  return 0.0;
877 
878  const G4int ipi = ParticleTable::getIsospin(pion->getType());
879  const G4int ind2 = ParticleTable::getIsospin(nucleon->getType());
880  const G4int cg = 4 + ind2*ipi;
881 // assert(cg==2 || cg==4 || cg==6);
882 
883  const G4double p1=1e-3*pLab;
884  G4double tamp6=0.;
885  G4double tamp2=0.;
886 
887  // X-SECTION PI+ P INELASTIQUE :
888  if(cg != 2) {
889  if(pLab < 1532.52) // corresponds to sqrt(s)=1946 MeV
890  tamp6=piNIne(particle1, particle2);
891  else
892  tamp6=0.204+18.2*std::pow(p1, -1.72)+6.33*std::pow(p1, -1.13);
893  if (cg == 6) // CAS PI+ P ET PI- N
894  return tamp6;
895  }
896 
897  // X-SECTION PI- P INELASTIQUE :
898  if (pLab < 1228.06) // corresponds to sqrt(s)=1794 MeV
899  tamp2=piNIne(particle1, particle2);
900  else
901  tamp2=9.04*std::pow(p1, -1.17)+18.*std::pow(p1, -1.21); // tamp2=9.04*std::pow(p1, -1.17)+(13.5*std::pow(p1, -1.21))*4./3.;
902  if (tamp2 < 0.0) tamp2=0;
903 
904  if (cg == 2) // CAS PI- P ET PI+ N
905  return tamp2;
906  else {
907  // CAS PI0 P ET PI0 N
908  G4double s1pin = 0.5*(tamp6+tamp2);
909  const G4double inelastic = piNIne(particle1, particle2);
910  if (s1pin > inelastic)
911  s1pin = inelastic;
912  return s1pin;
913  }
914  }
915 
916  G4double CrossSectionsMultiPions::piNTwoPi(Particle const * const particle1, Particle const * const particle2) {
917  //
918  // pion-nucleon interaction, producing 2 pions
919  // fit from Landolt-Bornstein multiplied by factor determined with evaluation of total xs
920  //
921 
922  const Particle *pion;
923  const Particle *nucleon;
924  if(particle1->isNucleon()) {
925  nucleon = particle1;
926  pion = particle2;
927  } else {
928  pion = particle1;
929  nucleon = particle2;
930  }
931 // assert(pion->isPion());
932 
933  const G4double pLab = KinematicsUtils::momentumInLab(pion, nucleon);
934 
935  // this limit corresponds to sqrt(s)=1230 MeV
936  if(pLab<296.367)
937  return 0.0;
938 
939  const G4int ipi = ParticleTable::getIsospin(pion->getType());
940  const G4int ind2 = ParticleTable::getIsospin(nucleon->getType());
941  const G4int cg = 4 + ind2*ipi;
942 // assert(cg==2 || cg==4 || cg==6);
943 
944  const G4double p1=1e-3*pLab;
945  G4double tamp6=0.;
946  G4double tamp2=0.;
947 
948  // X-SECTION PI+ P INELASTIQUE :
949  if(cg!=2) {
950  if(pLab < 2444.7) // corresponds to sqrt(s)=2344 MeV
951  tamp6=piNIne(particle1, particle2)-piNOnePi(particle1, particle2);
952  else
953  tamp6=1.59+25.5*std::pow(p1, -1.04); // tamp6=(0.636+10.2*std::pow(p1, -1.04))*15./6.;
954 
955  if(cg==6) // CAS PI+ P ET PI- N
956  return tamp6;
957  }
958 
959  // X-SECTION PI- P INELASTIQUE :
960  if(pLab<2083.63) // corresponds to sqrt(s)=2195 MeV
961  tamp2=piNIne(particle1, particle2)-piNOnePi(particle1, particle2);
962  else
963  tamp2=2.457794117647+18.066176470588*std::pow(p1, -0.92); // tamp2=(0.619+4.55*std::pow(p1, -0.92))*135./34.;
964 
965  if(cg==2) // CAS PI- P ET PI+ N
966  return tamp2;
967  else {
968  // CAS PI0 P ET PI0 N
969  const G4double s2pin=0.5*(tamp6+tamp2);
970  return s2pin;
971  }
972  }
973 
974 } // namespace G4INCL
975 
virtual G4double NNToxPiNN(const G4int xpi, Particle const *const p1, Particle const *const p2)
Cross section for X pion production - NN Channel.
static const G4double s01pzOOT
One over threshold for s01pz.
virtual G4double NNToNDelta(Particle const *const p1, Particle const *const p2)
Cross section for Delta production - NN Channel.
virtual G4double NNOnePiOrDelta(const G4double ener, const G4int iso, const G4double xsiso)
Cross section for direct 1-pion production + delta production - NN entrance channel.
G4double getMass() const
Get the cached particle mass.
G4double NNInelasticIso(const G4double ener, const G4int iso)
Internal implementation of the isospin dependent NN reaction cross section.
static const G4double s12mzOOT
One over threshold for s12mz.
G4bool pion(G4int ityp)
G4double piNIne(Particle const *const p1, Particle const *const p2)
virtual G4double NNTwoPi(const G4double ener, const G4int iso, const G4double xsiso)
Cross section for direct 2-pion production - NN entrance channel.
static const G4double s12ppOOT
One over threshold for s12pp.
G4double squareTotalEnergyInCM(Particle const *const p1, Particle const *const p2)
virtual G4double piNToDelta(Particle const *const p1, Particle const *const p2)
Cross section for Delta production - piN Channel.
G4double NNElasticFixed(const G4double s, const G4int i)
Internal implementation of the NN elastic cross section with fixed isospin.
const HornerC4 s12zzHC
Horner coefficients for s12zz.
#define INCL_ERROR(x)
G4bool isDelta() const
Is it a Delta?
std::string print() const
virtual G4double piNToxPiN(const G4int xpi, Particle const *const p1, Particle const *const p2)
Cross section for X pion production - piN Channel.
G4double spnPiPlusPHE(const G4double x)
Internal function for pion cross sections.
const HornerC4 s02pzHC
Horner coefficients for s02pz.
int G4int
Definition: G4Types.hh:78
virtual G4double NNThreePi(const G4double ener, const G4int iso, const G4double xsiso, const G4double xs1pi, const G4double xs2pi)
Cross section for direct 3-pion production - NN entrance channel.
G4double NNElastic(Particle const *const part1, Particle const *const part2)
Internal implementation of the NN elastic cross section.
const HornerC8 s01ppHC
Horner coefficients for s01pp.
virtual G4double NNOnePi(Particle const *const part1, Particle const *const part2)
Cross section for direct 1-pion production - NN entrance channel.
static const G4double s01ppOOT
One over threshold for s01pp.
G4double NNTot(Particle const *const part1, Particle const *const part2)
Internal implementation of the NN total cross section.
virtual G4double piNTwoPi(Particle const *const p1, Particle const *const p2)
Cross section for Two (more) pion production - piN entrance channel.
static const double s
Definition: G4SIunits.hh:150
const HornerC4 s01pzHC
Horner coefficients for s01pz.
G4bool nucleon(G4int ityp)
G4double piNTot(Particle const *const p1, Particle const *const p2)
virtual G4double elastic(Particle const *const p1, Particle const *const p2)
Elastic particle-particle cross section.
const HornerC3 s12ppHC
Horner coefficients for s12pp.
static const G4double s11pmOOT
One over threshold for s11pm.
virtual G4double NNFourPi(Particle const *const part1, Particle const *const part2)
Cross section for direct 4-pion production - NN entrance channel.
virtual G4double NDeltaToNN(Particle const *const p1, Particle const *const p2)
Cross section for NDelta->NN.
static const G4double f3
const HornerC7 s11pzHC
Horner coefficients for s11pz.
G4int getIsospin(const ParticleType t)
Get the isospin of a particle.
const G4double effectiveNucleonMass2
static const G4double s02pzOOT
One over threshold for s02pz.
G4INCL::ParticleType getType() const
Get the particle type.
static G4double eval(const G4double pLab, const G4double oneOverThreshold, HornerCoefficients< N > const &coeffs)
static const G4double s12pmOOT
One over threshold for s12pm.
static const G4double s12zzOOT
One over threshold for s12zz.
G4double NNTotFixed(const G4double s, const G4int i)
Internal implementation of the NN total cross section with fixed isospin.
static const G4double s11pzOOT
One over threshold for s11pz.
G4bool isNucleon() const
Is this a nucleon?
const HornerC4 s12mzHC
Horner coefficients for s12mz.
static const G4double s02pmOOT
One over threshold for s02pm.
G4double momentumInLab(Particle const *const p1, Particle const *const p2)
gives the momentum in the lab frame of two particles.
virtual G4double calculateNNAngularSlope(G4double energyCM, G4int iso)
Calculate the slope of the NN DDXS.
double G4double
Definition: G4Types.hh:76
G4double totalEnergyInCM(Particle const *const p1, Particle const *const p2)
const HornerC4 s11pmHC
Horner coefficients for s11pm.
G4bool isPion() const
Is this a pion?
G4double spnPiMinusPHE(const G4double x)
Internal function for pion cross sections.
static G4double eval(const G4double x, HornerCoefficients< N > const &coeffs)
virtual G4double total(Particle const *const p1, Particle const *const p2)
Total (elastic+inelastic) particle-particle cross section.
const G4double effectiveNucleonMass
virtual G4double piNOnePi(Particle const *const p1, Particle const *const p2)
Cross section for One (more) pion production - piN entrance channel.
Cross sections used in INCL Multipions.
const HornerC6 s02pmHC
Horner coefficients for s02pm.
const HornerC5 s12pmHC
Horner coefficients for s12pm.