ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4NeutrinoNucleusModel.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4NeutrinoNucleusModel.cc
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: G4NeutrinoNucleusModel.cc 91806 2015-08-06 12:20:45Z gcosmo $
27 //
28 // Geant4 Header : G4NeutrinoNucleusModel
29 //
30 // Author : V.Grichine 12.2.19
31 //
32 
34 
35 #include "G4SystemOfUnits.hh"
36 #include "G4ParticleTable.hh"
37 #include "G4ParticleDefinition.hh"
38 #include "G4IonTable.hh"
39 #include "Randomize.hh"
40 #include "G4RandomDirection.hh"
41 
42 //#include "G4Integrator.hh"
43 #include "G4DataVector.hh"
44 #include "G4PhysicsTable.hh"
45 
46 #include "G4CascadeInterface.hh"
47 // #include "G4BinaryCascade.hh"
48 #include "G4TheoFSGenerator.hh"
50 #include "G4ExcitationHandler.hh"
51 #include "G4PreCompoundModel.hh"
53 #include "G4ExcitedStringDecay.hh"
54 #include "G4FTFModel.hh"
55 // #include "G4BinaryCascade.hh"
56 #include "G4HadFinalState.hh"
57 #include "G4HadSecondary.hh"
59 // #include "G4INCLXXInterface.hh"
60 #include "G4KineticTrack.hh"
61 #include "G4DecayKineticTracks.hh"
62 #include "G4KineticTrackVector.hh"
63 #include "G4Fragment.hh"
65 
66 // #include "G4QGSModel.hh"
67 // #include "G4QGSMFragmentation.hh"
68 // #include "G4QGSParticipants.hh"
69 
70 
71 #include "G4MuonMinus.hh"
72 #include "G4MuonPlus.hh"
73 #include "G4Nucleus.hh"
74 #include "G4LorentzVector.hh"
75 
76 using namespace std;
77 using namespace CLHEP;
78 
80 
81 const G4double G4NeutrinoNucleusModel::fResMass[6] = // [fResNumber] =
82  {2190., 1920., 1700., 1600., 1440., 1232. };
83 
85 
86 const G4double G4NeutrinoNucleusModel::fMesMass[4] = {1260., 980., 770., 139.57};
87 const G4int G4NeutrinoNucleusModel::fMesPDG[4] = {20213, 9000211, 213, 211};
88 
89 // const G4double G4NeutrinoNucleusModel::fBarMass[4] = {1905., 1600., 1232., 939.57};
90 // const G4int G4NeutrinoNucleusModel::fBarPDG[4] = {2226, 32224, 2224, 2212};
91 
92 const G4double G4NeutrinoNucleusModel::fBarMass[4] = {1700., 1600., 1232., 939.57};
93 const G4int G4NeutrinoNucleusModel::fBarPDG[4] = {12224, 32224, 2224, 2212};
94 
95 
97  : G4HadronicInteraction(name)
98 {
99  SetMinEnergy( 0.0*GeV );
100  SetMaxEnergy( 100.*TeV );
101  SetMinEnergy(1.e-6*eV);
102 
103  fNbin = 50;
104  fEindex = fXindex = fQindex = 0;
105  fOnePionIndex = 58;
106  fIndex = 50;
107  fCascade = fString = fProton = f2p2h = fBreak = false;
108 
109  fNuEnergy = fQ2 = fQtransfer = fXsample = fDp = fTr = 0.;
110  fCosTheta = fCosThetaPi = 1.;
111  fEmuPi = fW2 = fW2pi = 0.;
112 
113  fMu = 105.6583745*MeV;
114  fMpi = 139.57018*MeV;
115  fM1 = 939.5654133*MeV; // for nu_mu -> mu-, and n -> p
116  fM2 = 938.2720813*MeV;
117 
118  fEmu = fMu;
119  fEx = fM1;
120  fMr = 1232.*MeV;
121  fMt = fM2; // threshold for N*-diffraction
122 
124 
125  fLVh = G4LorentzVector(0.,0.,0.,0.);
126  fLVl = G4LorentzVector(0.,0.,0.,0.);
127  fLVt = G4LorentzVector(0.,0.,0.,0.);
128  fLVcpi = G4LorentzVector(0.,0.,0.,0.);
129 
132 
133  // PDG2016: sin^2 theta Weinberg
134 
135  fSin2tW = 0.23129; // 0.2312;
136 
137  fCutEnergy = 0.; // default value
138 
139 
140  /*
141  // G4VPreCompoundModel* ptr;
142  // reuse existing pre-compound model as in binary cascade
143 
144  fPrecoInterface = new G4GeneratorPrecompoundInterface ;
145 
146  if( !fPreCompound )
147  {
148  G4HadronicInteraction* p =
149  G4HadronicInteractionRegistry::Instance()->FindModel("PRECO");
150  G4VPreCompoundModel* fPreCompound = static_cast<G4VPreCompoundModel*>(p);
151 
152  if(!fPreCompound)
153  {
154  fPreCompound = new G4PreCompoundModel();
155  }
156  fPrecoInterface->SetDeExcitation(fPreCompound);
157  }
158  fDeExcitation = GetDeExcitation()->GetExcitationHandler();
159  */
160 
165 
166  fPDGencoding = 0; // unphysical as default
167  fRecoil = nullptr;
168 
169 }
170 
171 
173 {
174  if(fPrecoInterface) delete fPrecoInterface;
175 }
176 
177 
178 void G4NeutrinoNucleusModel::ModelDescription(std::ostream& outFile) const
179 {
180 
181  outFile << "G4NeutrinoNucleusModel is a neutrino-nucleus general\n"
182  << "model which uses the standard model \n"
183  << "transfer parameterization. The model is fully relativistic\n";
184 
185 }
186 
188 
190  G4Nucleus & targetNucleus)
191 {
192  G4bool result = false;
193  G4String pName = aPart.GetDefinition()->GetParticleName();
194  G4double energy = aPart.GetTotalEnergy();
195 
196  if( pName == "nu_mu" // || pName == "anti_nu_mu" )
197  &&
198  energy > fMinNuEnergy )
199  {
200  result = true;
201  }
202  G4int Z = targetNucleus.GetZ_asInt();
203  Z *= 1;
204 
205  return result;
206 }
207 
208 
210 //
211 // Final meson to theParticleChange
212 
214 {
215  G4int pdg = pdgM;
216  // if ( qM == 0 ) pdg = pdgM - 100;
217  // else if ( qM == -1 ) pdg = -pdgM;
218 
219  if( pdg == 211 || pdg == -211 || pdg == 111) // pions
220  {
222  G4DynamicParticle* dp2 = new G4DynamicParticle( pd2, lvM);
224  }
225  else // meson resonances
226  {
228  FindParticle(pdg);
229  G4KineticTrack ddkt( rePart, 0., G4ThreeVector(0.,0.,0.), lvM);
230  G4KineticTrackVector* ddktv = ddkt.Decay();
231 
232  G4DecayKineticTracks decay( ddktv );
233 
234  for( unsigned int i = 0; i < ddktv->size(); i++ ) // add products to partchange
235  {
236  G4DynamicParticle * aNew =
237  new G4DynamicParticle( ddktv->operator[](i)->GetDefinition(),
238  ddktv->operator[](i)->Get4Momentum());
239 
240  // G4cout<<" "<<i<<", "<<aNew->GetDefinition()->GetParticleName()<<", "<<aNew->Get4Momentum()<<G4endl;
241 
243  delete ddktv->operator[](i);
244  }
245  delete ddktv;
246  }
247 }
248 
250 //
251 // Final barion to theParticleChange, and recoil nucleus treatment
252 
254 {
255  G4int A(0), Z(0), pdg = pdgB;
256  // G4bool FiNucleon(false);
257 
258  // if ( qB == 1 ) pdg = pdgB - 10;
259  // else if ( qB == 0 ) pdg = pdgB - 110;
260  // else if ( qB == -1 ) pdg = pdgB - 1110;
261 
262  if( pdg == 2212 || pdg == 2112)
263  {
265  // FiNucleon = true;
266  }
267  else fMr = lvB.m();
268 
270  lvB.boost(-bst); // in fLVt rest system
271 
272  G4double eX = lvB.e();
273  G4double det(0.), det2(0.), rM(0.), mX = lvB.m();
274  G4ThreeVector dX = (lvB.vect()).unit();
275  G4double pX = sqrt(eX*eX-mX*mX);
276 
277  if( fRecoil )
278  {
279  Z = fRecoil->GetZ_asInt();
280  A = fRecoil->GetA_asInt();
281  rM = fRecoil->AtomicMass(A,Z); //->AtomicMass(); //
282  rM = fLVt.m();
283  }
284  else // A=0 nu+p
285  {
286  A = 0;
287  Z = 1;
288  rM = electron_mass_c2;
289  }
290  // G4cout<<A<<", ";
291 
292  G4double sumE = eX + rM;
293  G4double B = sumE*sumE + rM*rM - fMr*fMr - pX*pX;
294  G4double a = 4.*(sumE*sumE - pX*pX);
295  G4double b = -4.*B*pX;
296  G4double c = 4.*sumE*sumE*rM*rM - B*B;
297  det2 = b*b-4.*a*c;
298  if( det2 <= 0. ) det = 0.;
299  else det = sqrt(det2);
300  G4double dP = 0.5*(-b - det )/a;
301 
302  fDp = dP;
303 
304  pX -= dP;
305 
306  if(pX < 0.) pX = 0.;
307 
308  // if( A == 0 ) G4cout<<pX/MeV<<", ";
309 
310  eX = sqrt( pX*pX + fMr*fMr );
311  G4LorentzVector lvN( pX*dX, eX );
312  lvN.boost(bst); // back to lab
313 
314  if( pdg == 2212 || pdg == 2112) // nucleons mX >= fMr, dP >= 0
315  {
317  G4DynamicParticle* dp2 = new G4DynamicParticle( pd2, lvN);
319 
320  }
321  else // delta resonances
322  {
324  G4KineticTrack ddkt( rePart, 0., G4ThreeVector( 0., 0., 0.), lvN);
325  G4KineticTrackVector* ddktv = ddkt.Decay();
326 
327  G4DecayKineticTracks decay( ddktv );
328 
329  for( unsigned int i = 0; i < ddktv->size(); i++ ) // add products to partchange
330  {
331  G4DynamicParticle * aNew =
332  new G4DynamicParticle( ddktv->operator[](i)->GetDefinition(),
333  ddktv->operator[](i)->Get4Momentum() );
334 
335  // G4cout<<" "<<i<<", "<<aNew->GetDefinition()->GetParticleName()<<", "<<aNew->Get4Momentum()<<G4endl;
336 
338  delete ddktv->operator[](i);
339  }
340  delete ddktv;
341  }
342  // recoil nucleus
343 
344  G4double eRecoil = sqrt( rM*rM + dP*dP );
345  fTr = eRecoil - rM;
346  G4ThreeVector vRecoil(dP*dX);
347  // dP += G4UniformRand()*10.*MeV;
348  G4LorentzVector rec4v(vRecoil, 0.);
349  rec4v.boost(bst); // back to lab
350  fLVt += rec4v;
351  const G4LorentzVector lvTarg = fLVt; // (vRecoil, eRecoil);
352 
353 
354  if( fRecoil ) // proton*?
355  {
357  G4double exE = fLVt.m() - grM;
358  if( exE < 5.*MeV ) exE = 5.*MeV + G4UniformRand()*10.*MeV;
359 
360  const G4LorentzVector in4v( G4ThreeVector( 0., 0., 0.), grM );
361  G4Fragment fragment( A, Z, in4v); // lvTarg );
362  fragment.SetNumberOfHoles(1);
363  fragment.SetExcEnergyAndMomentum( exE, lvTarg );
364 
365  RecoilDeexcitation(fragment);
366  }
367  else // momentum?
368  {
370  }
371 }
372 
373 
375 
377 {
378  G4ReactionProductVector* products = fPreCompound->DeExcite(fragment);
379 
380  if( products != NULL )
381  {
382  G4ReactionProductVector::iterator iter;
383 
384  for( iter = products->begin(); iter != products->end(); ++iter )
385  {
386  G4DynamicParticle * aNewDP =
387  new G4DynamicParticle((*iter)->GetDefinition(),
388  (*iter)->GetTotalEnergy(),
389  (*iter)->GetMomentum());
390  /*
391  // G4HadSecondary aNew = G4HadSecondary(aNewDP);
392 
393  G4double time=(*iter)->GetFormationTime();
394 
395  if( time < 0.0) { time = 0.0; }
396 
397  aNew.SetTime(time);// (timePrimary + time);
398  aNew.SetCreatorModelType((*iter)->GetCreatorModel());
399 */
400  // G4cout<<aNewDP->GetDefinition()->GetParticleName()<<", "<<aNewDP->Get4Momentum()<<G4endl;
401 
403  }
404  }
405  return;
406 }
407 
408 
410 //
411 // Fragmentation of lvX directly to pion and recoil nucleus (A,Z): fLVh + fLVt -> pi + A*
412 
414 {
415  G4int A(0), Z(0), pdg = pdgP;
416  fLVcpi = G4LorentzVector(0.,0.,0.,0.);
417 
418  G4double rM(0.), mN(938.), mI(0.), det(0.), det2(0.);
419 
420  mN = G4ParticleTable::GetParticleTable()->FindParticle(2212)->GetPDGMass(); // *0.85; // *0.9; //
421 
422  // mN = 1.*139.57 + G4UniformRand()*(938. - 1.*139.57);
423 
424  G4ThreeVector vN = lvP.boostVector(), bst(0.,0.,0.);
425  // G4double gN = lvP.e()/lvP.m();
426  // G4LorentzVector lvNu(vN*gN*mN, mN*gN);
427  G4LorentzVector lvNu(bst, mN);
428 
429  // lvP = lvP - lvNu; // already 1pi
430 
431  // G4cout<<vN-lvP.boostVector()<<", ";
432 
433  Z = targetNucleus.GetZ_asInt();
434  A = targetNucleus.GetA_asInt();
435  rM = targetNucleus.AtomicMass(A,Z); //->AtomicMass(); //
436 
437  // G4cout<<rM<<", ";
438  // G4cout<<A<<", ";
439 
440  if( A == 1 )
441  {
442  // bst = lvNu.boostVector();
443  mI = 0.;
444  }
445  else
446  {
447  G4Nucleus targ(A-1,Z);
448  mI = targ.AtomicMass(A-1,Z);
449  G4LorentzVector lvTar(bst,rM);
450  lvNu = lvNu + lvTar;
451  // bst = lvNu.boostVector();
452  bst = fLVt.boostVector(); // to recoil rest frame
453  lvP.boost(-bst);
454  }
456  G4double eX = lvP.e();
457  G4double mX = lvP.m();
458  // G4cout<<mX-fMr<<", ";
459  G4ThreeVector dX = (lvP.vect()).unit();
460  // G4cout<<dX<<", ";
461  G4double pX = sqrt(eX*eX-mX*mX);
462  // G4cout<<pX<<", ";
463  G4double sumE = eX + rM;
464  G4double B = sumE*sumE + rM*rM - fMr*fMr - pX*pX;
465  G4double a = 4.*(sumE*sumE - pX*pX);
466  G4double b = -4.*B*pX;
467  G4double c = 4.*sumE*sumE*rM*rM - B*B;
468  det2 = b*b-4.*a*c;
469  if(det2 > 0.) det = sqrt(det2);
470  G4double dP = 0.5*(-b - det )/a;
471 
472  dP = FinalMomentum( mI, rM, fMr, lvP);
473 
474  // G4cout<<dP<<", ";
475  pX -= dP;
476  if( pX < 0. ) pX = 0.;
477 
478  eX = sqrt( dP*dP + fMr*fMr );
479  G4LorentzVector lvN( dP*dX, eX );
480 
481  if( A > 1 ) lvN.boost(bst); // back to lab
482 
483  fLVcpi = lvN;
484 
486  G4DynamicParticle* dp2 = new G4DynamicParticle( pd2, lvN);
487  theParticleChange.AddSecondary( dp2 ); // coherent pion
488 
489  // recoil nucleus
490 
491  G4double eRecoil = sqrt( rM*rM + pX*pX );
492  G4ThreeVector vRecoil(pX*dX);
493  G4LorentzVector lvTarg1( vRecoil, eRecoil);
494  lvTarg1.boost(bst);
495 
496  const G4LorentzVector lvTarg = lvTarg1;
497 
498  if( A > 1 ) // recoil target nucleus*
499  {
501  G4double exE = fLVt.m() - grM;
502 
503  if( exE < 5.*MeV ) exE = 5.*MeV + G4UniformRand()*10.*MeV; // vmg???
504 
505  const G4LorentzVector in4v( G4ThreeVector( 0., 0., 0.), grM );
506  G4Fragment fragment( A, Z, in4v); // lvTarg );
507  fragment.SetNumberOfHoles(1);
508  fragment.SetExcEnergyAndMomentum( exE, lvTarg );
509 
510  RecoilDeexcitation(fragment);
511  }
512  else // recoil target proton
513  {
514  G4double eTkin = eRecoil - rM;
515  G4double eTh = 0.01*MeV; // 10.*MeV;
516 
517  if( eTkin > eTh )
518  {
519  G4DynamicParticle * aSec = new G4DynamicParticle( G4Proton::Proton(), lvTarg);
521  }
523  }
524  return;
525 }
526 
527 
529 //
530 // Excited barion decay to meson and barion,
531 // mass distributions and charge exchange are free parameters
532 
534 {
535  G4bool finB = false;
536  G4int pdgB(0), i(0), qM(0), qB(0); // pdgM(0),
537  G4double mM(0.), mB(0.), eM(0.), eB(0.), pM(0.), pB(0.);
538  G4double mm1(0.), mm22(0.), M1(0.), M2(0.), mX(0.);
539 
540  mX = lvX.m();
541 
544 
545  // G4double deltaM = 1.*MeV; // 30.*MeV; // 10.*MeV; // 100.*MeV; // 20.*MeV; //
546  G4double deltaMr[4] = { 0.*MeV, 0.*MeV, 100.*MeV, 0.*MeV};
547 
548  G4ThreeVector dir(0.,0.,0.);
549  G4ThreeVector bst(0.,0.,0.);
550  G4LorentzVector lvM(0.,0.,0.,0.);
551  G4LorentzVector lvB(0.,0.,0.,0.);
552 
553  for( i = 0; i < fClustNumber; ++i) // check resonance
554  {
555  if( mX >= fBarMass[i] )
556  {
557  pdgB = fBarPDG[i];
558  // mB = G4ParticleTable::GetParticleTable()->FindParticle(pdgB)->GetPDGMass();
559  break;
560  }
561  }
562  if( i == fClustNumber || i == fClustNumber-1 ) // low mass, p || n
563  {
564  if ( qX == 2 || qX == 0) { pdgB = 2212; qB = 1;} // p for 2, 0
565 
566  else if( qX == 1 || qX == -1) { pdgB = 2112; qB = 0;} // n for 1, -1
567 
568  return FinalBarion( lvX, qB, pdgB);
569  }
570  else if( mX < fBarMass[i] + deltaMr[i] || mX < mN + mPi )
571  {
572  finB = true; // final barion -> out
573 
574  if ( qX == 1 && pdgB != 2212) pdgB = pdgB - 10;
575  else if( qX == 0 && pdgB != 2212) pdgB = pdgB - 110;
576  else if( qX == 0 && pdgB == 2212) pdgB = pdgB - 100;
577 
578  if( finB ) return FinalBarion( lvX, qX, pdgB ); // out
579  }
580  // no barion resonance, try 1->2 decay in COM frame
581 
582  // try meson mass
583 
584  mm1 = mPi + 1.*MeV; // pi+
585  mm22 = mX - mN; // mX-n
586 
587  if( mm22 <= mm1 ) // out with p or n
588  {
589  if( qX == 2 || qX == 0) { pdgB = 2212; qB = 1;} // p
590  else if( qX == 1 || qX == -1) { pdgB = 2112; qB = 0;} // n
591 
592  return FinalBarion(lvX, qB, pdgB);
593  }
594  else // try decay -> meson(cluster) + barion(cluster)
595  {
596  // G4double sigmaM = 50.*MeV; // 100.*MeV; // 200.*MeV; // 400.*MeV; // 800.*MeV; //
597  G4double rand = G4UniformRand();
598 
599  // mM = mm1*mm22/( mm1 + rand*(mm22 - mm1) );
600  // mM = mm1*mm22/sqrt( mm1*mm1 + rand*(mm22*mm22 - mm1*mm1) );
601  // mM = -sigmaM*log( (1.- rand)*exp(-mm22/sigmaM) + rand*exp(-mm1/sigmaM) );
602  mM = mm1 + rand*(mm22-mm1);
603 
604 
605  for( i = 0; i < fClustNumber; ++i)
606  {
607  if( mM >= fMesMass[i] )
608  {
609  // pdgM = fMesPDG[i];
610  // mM = G4ParticleTable::GetParticleTable()->FindParticle(pdgM)->GetPDGMass();
611  break;
612  }
613  }
615  M2 = mX - mM;
616 
617  if( M2 <= M1 ) //
618  {
619  if ( qX == 2 || qX == 0) { pdgB = 2212; qB = 1;} // p
620  else if( qX == 1 || qX == -1) { pdgB = 2112; qB = 0;} // n
621 
622  return FinalBarion(lvX, qB, pdgB);
623  }
624  mB = M1 + G4UniformRand()*(M2-M1);
625  // mB = -sigmaM*log( (1.- rand)*exp(-M2/sigmaM) + rand*exp(-M1/sigmaM) );
626 
627 
628  dir = G4RandomDirection(); // ???
629  bst = lvX.boostVector();
630 
631  eM = 0.5*(mX*mX + mM*mM - mB*mB)/mX;
632  pM = sqrt(eM*eM - mM*mM);
633  lvM = G4LorentzVector( pM*dir, eM);
634  lvM.boost(bst);
635 
636  eB = 0.5*(mX*mX + mB*mB - mM*mM)/mX;
637  pB = sqrt(eB*eB - mB*mB);
638  lvB = G4LorentzVector(-pB*dir, eB);
639  lvB.boost(bst);
640 
641  // G4cout<<mM<<"/"<<mB<<", ";
642 
643  // charge exchange
644 
645  if ( qX == 2 ) { qM = 1; qB = 1;}
646  else if( qX == 1 ) { qM = 0; qB = 1;}
647  else if( qX == 0 ) { qM = 0; qB = 0;}
648  else if( qX == -1 ) { qM = -1; qB = 0;}
649 
650  // if ( qM == 0 ) pdgM = pdgM - 100;
651  // else if( qM == -1 ) pdgM = -pdgM;
652 
653  MesonDecay( lvM, qM); // pdgM ); //
654 
655  // else
656  ClusterDecay( lvB, qB ); // continue
657  }
658 }
659 
660 
662 //
663 // Excited barion decay to meson and barion,
664 // mass distributions and charge exchange are free parameters
665 
667 {
668  G4bool finB = false;
669  G4int pdgM(0), pdgB(0), i(0), qM(0), qB(0);
670  G4double mM(0.), mB(0.), eM(0.), eB(0.), pM(0.), pB(0.);
671  G4double mm1(0.), mm22(0.), M1(0.), M2(0.), mX(0.);
672 
673  mX = lvX.m();
674 
676 
677  G4double deltaMr[4] = { 0.*MeV, 0.*MeV, 100.*MeV, 0.*MeV};
678 
679  G4ThreeVector dir(0.,0.,0.);
680  G4ThreeVector bst(0.,0.,0.);
681  G4LorentzVector lvM(0.,0.,0.,0.);
682  G4LorentzVector lvB(0.,0.,0.,0.);
683 
684  for( i = 0; i < fClustNumber; ++i) // check resonance
685  {
686  if( mX >= fMesMass[i] )
687  {
688  pdgB = fMesPDG[i];
689  // mB = G4ParticleTable::GetParticleTable()->FindParticle(pdgB)->GetPDGMass();
690  break;
691  }
692  }
693  if( i == fClustNumber ) // || i == fClustNumber-1 ) // low mass, p || n
694  {
695  if ( qX == 1) { pdgB = 211; qB = 1;} // pi+
696  else if( qX == 0 ) { pdgB = 111; qB = 0;} // pi0
697  else if( qX == -1) { pdgB = -211; qB = -1;} // pi-
698 
699  return FinalMeson( lvX, qB, pdgB);
700  }
701  else if( mX < fMesMass[i] + deltaMr[i] ) // || mX < mPi + mPi ) //
702  {
703  finB = true; // final barion -> out
704  pdgB = fMesPDG[i];
705 
706  // if ( qX == 1 && pdgB != 2212) pdgB = pdgB - 10;
707 
708  if( qX == 0 ) pdgB = pdgB - 100;
709  else if( qX == -1 ) pdgB = -pdgB;
710 
711  if( finB ) return FinalMeson( lvX, qX, pdgB ); // out
712  }
713  // no resonance, try 1->2 decay in COM frame
714 
715  // try meson
716 
717  mm1 = mPi + 1.*MeV; // pi+
718  mm22 = mX - mPi - 1.*MeV; // mX-n
719 
720  if( mm22 <= mm1 ) // out
721  {
722  if ( qX == 1) { pdgB = 211; qB = 1;} // pi+
723  else if( qX == 0 ) { pdgB = 111; qB = 0;} // pi0
724  else if( qX == -1) { pdgB = -211; qB = -1;} // pi-
725 
726  return FinalMeson(lvX, qB, pdgB);
727  }
728  else // try decay -> pion + meson(cluster)
729  {
730  // G4double sigmaM = 50.*MeV; // 100.*MeV; // 200.*MeV; // 400.*MeV; // 800.*MeV; //
731  G4double rand = G4UniformRand();
732 
733  if ( qX == 1 ) { qM = 1; qB = 0;}
734  else if( qX == 0 ) { qM = -1; qB = 1;} // { qM = 0; qB = 0;} //
735  else if( qX == -1 ) { qM = -1; qB = 0;}
736  /*
737  mM = mPi;
738  if(qM == 0) mM = G4ParticleTable::GetParticleTable()->FindParticle(111)->GetPDGMass(); //pi0
739  pdgM = fMesPDG[fClustNumber-1];
740  */
741  // mm1*mm22/( mm1 + rand*(mm22 - mm1) );
742  // mM = mm1*mm22/sqrt( mm1*mm1 + rand*(mm22*mm22 - mm1*mm1) );
743  // mM = -sigmaM*log( (1.- rand)*exp(-mm22/sigmaM) + rand*exp(-mm1/sigmaM) );
744  mM = mm1 + rand*(mm22-mm1);
745  // mM = mm1 + 0.9*(mm22-mm1);
746 
747 
748  for( i = 0; i < fClustNumber; ++i)
749  {
750  if( mM >= fMesMass[i] )
751  {
752  pdgM = fMesPDG[i];
753  // mM = G4ParticleTable::GetParticleTable()->FindParticle(pdgM)->GetPDGMass();
754  break;
755  }
756  }
757  if( i == fClustNumber || i == fClustNumber-1 ) // low mass, p || n
758  {
759  if ( qX == 1) { pdgB = 211; qB = 1;} // pi+
760  else if( qX == 0 ) { pdgB = 111; qB = 0;} // pi0
761  else if( qX == -1) { pdgB = -211; qB = -1;} // pi-
762 
763  return FinalMeson( lvX, qB, pdgB);
764  }
765  else if( mX < fMesMass[i] + deltaMr[i] ) // || mX < mPi + mPi ) //
766  {
767  finB = true; // final barion -> out
768  pdgB = fMesPDG[i];
769 
770  // if ( qX == 1 && pdgB != 2212) pdgB = pdgB - 10;
771 
772  if( qX == 0 ) pdgB = pdgB - 100;
773  else if( qX == -1 ) pdgB = -pdgB;
774 
775  if( finB ) return FinalMeson( lvX, qX, pdgB ); // out
776  }
777 
779  M2 = mX - mM;
780 
781  if( M2 <= M1 ) //
782  {
783  if ( qX == 1) { pdgB = 211; qB = 1;} // pi+
784  else if( qX == 0 ) { pdgB = 111; qB = 0;} // pi0
785  else if( qX == -1) { pdgB = -211; qB = -1;} // pi-
786 
787  return FinalMeson(lvX, qB, pdgB);
788  }
789  mB = M1 + G4UniformRand()*(M2-M1);
790  // mB = -sigmaM*log( (1.- rand)*exp(-M2/sigmaM) + rand*exp(-M1/sigmaM) );
791  // mB = M1 + 0.9*(M2-M1);
792 
793  dir = G4RandomDirection();
794  bst = lvX.boostVector();
795 
796  eM = 0.5*(mX*mX + mM*mM - mB*mB)/mX;
797  pM = sqrt(eM*eM - mM*mM);
798  lvM = G4LorentzVector( pM*dir, eM);
799  lvM.boost(bst);
800 
801  eB = 0.5*(mX*mX + mB*mB - mM*mM)/mX;
802  pB = sqrt(eB*eB - mB*mB);
803  lvB = G4LorentzVector(-pB*dir, eB);
804  lvB.boost(bst);
805 
806  // G4cout<<mM<<"/"<<mB<<", ";
807 
808  // charge exchange
809 
810  // if ( qX == 2 ) { qM = 1; qB = 1;}
811 
812  if ( qM == 0 ) pdgM = pdgM - 100;
813  else if( qM == -1 ) pdgM = -pdgM;
814 
815  MesonDecay( lvM, qM ); //
816 
817  MesonDecay( lvB, qB ); // continue
818  }
819 }
820 
822 //
823 // return final momentum x in the reaction lvX + mI -> mF + mP with momenta p-x, x
824 
826 {
827  G4double result(0.), delta(0.);
828  // G4double mI2 = mI*mI;
829  G4double mF2 = mF*mF;
830  G4double mP2 = mP*mP;
831  G4double eX = lvX.e();
832  // G4double mX = lvX.m();
833  G4double pX = lvX.vect().mag();
834  G4double pX2 = pX*pX;
835  G4double sI = eX + mI;
836  G4double sI2 = sI*sI;
837  G4double B = sI2 - mF2 -pX2 + mP2;
838  G4double B2 = B*B;
839  G4double a = 4.*(sI2-pX2);
840  G4double b = -4.*B*pX;
841  G4double c = 4.*sI2*mP2 - B2;
842  G4double delta2 = b*b -4.*a*c;
843 
844  if( delta2 >= 0. ) delta = sqrt(delta2);
845 
846  result = 0.5*(-b-delta)/a;
847  // result = 0.5*(-b+delta)/a;
848 
849  return result;
850 }
851 
853 //
854 //
855 
857 {
858  G4int Z = targetNucleus.GetZ_asInt();
859  G4int A = targetNucleus.GetA_asInt();
860 
861  G4double kF(250.*MeV);
862  G4double kp = 365.*MeV;
863  G4double kn = 231.*MeV;
864  G4double t1 = 0.479;
865  G4double t2 = 0.526;
866  G4double ZpA = G4double(Z)/G4double(A);
867  G4double NpA = 1. - ZpA;
868 
869  if ( Z == 1 && A == 1 ) { kF = 0.; } // hydrogen ???
870  else if ( Z == 1 && A == 2 ) { kF = 87.*MeV; }
871  else if ( Z == 2 && A == 3 ) { kF = 134.*MeV; }
872  else if ( Z == 6 && A == 12 ) { kF = 221.*MeV; }
873  else if ( Z == 14 && A == 28 ) { kF = 239.*MeV; }
874  else if ( Z == 26 && A == 56 ) { kF = 257.*MeV; }
875  else if ( Z == 82 && A == 208 ) { kF = 265.*MeV; }
876  else
877  {
878  kF = kp*ZpA*( 1 - pow( G4double(A), -t1 ) ) + kn*NpA*( 1 - pow( G4double(A), -t2 ) );
879  }
880  return kF;
881 }
882 
884 //
885 // sample nucleon momentum of Fermi motion for 1p1h and 2p2h modes
886 
888 {
889  G4int A = targetNucleus.GetA_asInt();
890  G4double kF = FermiMomentum( targetNucleus);
891  G4double mom(0.), kCut = 0.5*GeV; // kCut = 1.*GeV; // kCut = 2.*GeV; // kCut = 4.*GeV; //
892  // G4double cof = 2./GeV;
893  // G4double ksi = kF*kF*cof*cof/pi/pi;
894  G4double th = 1.; // 1. - 6.*ksi; //
895 
896  if( G4UniformRand() < th || A < 3 ) // 1p1h
897  {
898  mom = kF*pow( G4UniformRand(), 1./3.);
899  }
900  else // 2p2h
901  {
902  mom = kF*kCut;
903  mom /= kCut - G4UniformRand()*(kCut - kF);
904  f2p2h = true;
905  }
906  return mom;
907 }
908 
909 
911 //
912 // Excitation energy according Bodek
913 
915 {
916  G4double eX(10.*MeV), a1(0.), a2(0.), e1(0.), e2(0.), aa = G4double(A);
917  G4int i(0);
918  const G4int maxBin = 12;
919 
920  G4double refA[maxBin] = { 2., 6., 12., 16., 27., 28., 40., 50., 56., 58., 197., 208. };
921 
922  G4double pEx[maxBin] = { 0., 12.2, 10.1, 10.9, 21.6, 12.4, 17.8, 17., 19., 16.8, 19.5, 14.7 };
923 
924  G4double nEx[maxBin] = { 0., 12.2, 10., 10.2, 21.6, 12.4, 21.8, 17., 19., 16.8, 19.5, 16.9 };
925 
926  G4DataVector dE(12,0.);
927 
928  if(fP) for( i = 0; i < maxBin; ++i ) dE[i] = pEx[i];
929  else dE[i] = nEx[i];
930 
931  for( i = 0; i < maxBin; ++i )
932  {
933  if( aa <= refA[i] ) break;
934  }
935  if( i >= maxBin ) eX = dE[maxBin-1];
936  else if( i <= 0 ) eX = dE[0];
937  else
938  {
939  a1 = refA[i-1];
940  a2 = refA[i];
941  e1 = dE[i-1];
942  e2 = dE[i];
943  if (a1 == a2 || e1 == e2 ) eX = dE[i];
944  else eX = e1 + (e2-e1)*(aa-a1)/(a2-a1);
945  }
946  return eX;
947 }
948 
949 
950 
952 //
953 // Two G-function sampling for the nucleon momentum
954 
956 {
957  f2p2h = false;
958  G4double /* distr(0.), tail(0.), */ shift(1.), xx(1.), mom(0.), th(0.1);
959  G4double kF = FermiMomentum( nucl);
960  G4double momMax = 2.*kF; // 1.*GeV; // 1.*GeV; //
961  G4double aa = 5.5;
962  G4double ll = 6.0; // 6.5; //
963 
964  G4int A = nucl.GetA_asInt();
965 
966  if( A <= 12) th = 0.1;
967  else
968  {
969  // th = 0.1/(1.+log(G4double(A)/12.));
970  th = 1.2/( G4double(A) + 1.35*log(G4double(A)/12.) );
971  }
972  shift = 0.99; // 0.95; //
973  xx = mom/shift/kF;
974 
975  G4double rr = G4UniformRand();
976 
977  if( rr > th )
978  {
979  aa = 5.5;
980 
981  if( A <= 12 ) ll = 6.0;
982  else
983  {
984  ll = 6.0 + 1.35*log(G4double(A)/12.);
985  }
986  xx = RandGamma::shoot(aa,ll);
987  shift = 0.99;
988  mom = xx*shift*kF;
989  }
990  else
991  {
992  f2p2h = true;
993  aa = 6.5;
994  ll = 6.5;
995  xx = RandGamma::shoot(aa,ll);
996  shift = 2.5;
997  mom = xx*shift*kF;
998  }
999  if( mom > momMax ) mom = G4UniformRand()*momMax;
1000  if( mom > 2.*kF ) f2p2h = true;
1001 
1002  // mom = 0.;
1003 
1004  return mom;
1005 }
1006 
1007 
1009 //
1010 // Return index of nu/anu energy array corresponding to the neutrino energy
1011 
1013 {
1014  G4int i, eIndex = 0;
1015 
1016  for( i = 0; i < fIndex; i++)
1017  {
1018  if( energy <= fNuMuEnergy[i]*GeV )
1019  {
1020  eIndex = i;
1021  break;
1022  }
1023  }
1024  if( i >= fIndex ) eIndex = fIndex;
1025  // G4cout<<"eIndex = "<<eIndex<<G4endl;
1026  return eIndex;
1027 }
1028 
1030 //
1031 // nu_mu QE/Tot ratio for index-1, index linear over energy
1032 
1034 {
1035  G4double ratio(0.);
1036  // GetMinNuMuEnergy()
1037  if( index <= 0 || energy < fNuMuEnergy[0] ) ratio = 0.;
1038  else if (index >= fIndex) ratio = fNuMuQeTotRat[fIndex-1]*fOnePionEnergy[fIndex-1]*GeV/energy;
1039  else
1040  {
1041  G4double x1 = fNuMuEnergy[index-1]*GeV;
1042  G4double x2 = fNuMuEnergy[index]*GeV;
1043  G4double y1 = fNuMuQeTotRat[index-1];
1044  G4double y2 = fNuMuQeTotRat[index];
1045 
1046  if(x1 >= x2) return fNuMuQeTotRat[index];
1047  else
1048  {
1049  G4double angle = (y2-y1)/(x2-x1);
1050  ratio = y1 + (energy-x1)*angle;
1051  }
1052  }
1053  return ratio;
1054 }
1055 
1057 
1059 {
1060  0.112103, 0.117359, 0.123119, 0.129443, 0.136404,
1061  0.144084, 0.152576, 0.161991, 0.172458, 0.184126,
1062  0.197171, 0.211801, 0.228261, 0.24684, 0.267887,
1063  0.291816, 0.319125, 0.350417, 0.386422, 0.428032,
1064  0.47634, 0.532692, 0.598756, 0.676612, 0.768868,
1065  0.878812, 1.01062, 1.16963, 1.36271, 1.59876,
1066  1.88943, 2.25002, 2.70086, 3.26916, 3.99166,
1067  4.91843, 6.11836, 7.6872, 9.75942, 12.5259,
1068  16.2605, 21.3615, 28.4141, 38.2903, 52.3062,
1069  72.4763, 101.93, 145.6, 211.39, 312.172
1070 };
1071 
1073 
1075 {
1076  // 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1077  // 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1078  // 1., 1., 1., 0.982311,
1079  0.98, 0.98, 0.98, 0.98, 0.98, 0.98, 0.98, 0.98, 0.98, 0.98,
1080  0.98, 0.98, 0.98, 0.98, 0.98, 0.98, 0.98, 0.98, 0.98, 0.98,
1081  0.97, 0.96, 0.95, 0.93,
1082  0.917794, 0.850239, 0.780412, 0.709339, 0.638134, 0.568165,
1083  0.500236, 0.435528, 0.375015, 0.319157, 0.268463, 0.2232, 0.183284,
1084  0.148627, 0.119008, 0.0940699, 0.0733255, 0.0563819, 0.0427312, 0.0319274,
1085  0.0235026, 0.0170486, 0.0122149, 0.00857825, 0.00594018, 0.00405037
1086 };
1087 
1089 //
1090 // Return index of one pion array corresponding to the neutrino energy
1091 
1093 {
1094  G4int i, eIndex = 0;
1095 
1096  for( i = 0; i < fOnePionIndex; i++)
1097  {
1098  if( energy <= fOnePionEnergy[i]*GeV )
1099  {
1100  eIndex = i;
1101  break;
1102  }
1103  }
1104  if( i >= fOnePionIndex ) eIndex = fOnePionIndex;
1105  // G4cout<<"eIndex = "<<eIndex<<G4endl;
1106  return eIndex;
1107 }
1108 
1110 //
1111 // nu_mu 1pi/Tot ratio for index-1, index linear over energy
1112 
1114 {
1115  G4double ratio(0.);
1116 
1117  if( index <= 0 || energy < fOnePionEnergy[0] ) ratio = 0.;
1118  else if ( index >= fOnePionIndex ) ratio = fOnePionProb[fOnePionIndex-1]*fOnePionEnergy[fOnePionIndex-1]*GeV/energy;
1119  else
1120  {
1121  G4double x1 = fOnePionEnergy[index-1]*GeV;
1122  G4double x2 = fOnePionEnergy[index]*GeV;
1123  G4double y1 = fOnePionProb[index-1];
1124  G4double y2 = fOnePionProb[index];
1125 
1126  if( x1 >= x2) return fOnePionProb[index];
1127  else
1128  {
1129  G4double angle = (y2-y1)/(x2-x1);
1130  ratio = y1 + (energy-x1)*angle;
1131  }
1132  }
1133  return ratio;
1134 }
1135 
1137 
1139 {
1140 
1141  0.275314, 0.293652, 0.31729, 0.33409, 0.351746, 0.365629, 0.380041, 0.400165, 0.437941, 0.479237,
1142  0.504391, 0.537803, 0.588487, 0.627532, 0.686839, 0.791905, 0.878332, 0.987405, 1.08162, 1.16971,
1143  1.2982, 1.40393, 1.49854, 1.64168, 1.7524, 1.87058, 2.02273, 2.15894, 2.3654, 2.55792, 2.73017,
1144  3.03005, 3.40733, 3.88128, 4.53725, 5.16786, 5.73439, 6.53106, 7.43879, 8.36214, 9.39965, 10.296,
1145  11.5735, 13.1801, 15.2052, 17.5414, 19.7178, 22.7462, 25.9026, 29.4955, 33.5867, 39.2516, 46.4716,
1146  53.6065, 63.4668, 73.2147, 85.5593, 99.9854
1147 };
1148 
1149 
1151 
1153 {
1154  0.0019357, 0.0189361, 0.0378722, 0.0502758, 0.0662559, 0.0754581, 0.0865008, 0.0987275, 0.124112,
1155  0.153787, 0.18308, 0.213996, 0.245358, 0.274425, 0.301536, 0.326612, 0.338208, 0.337806, 0.335948,
1156  0.328092, 0.313557, 0.304965, 0.292169, 0.28481, 0.269474, 0.254138, 0.247499, 0.236249, 0.221654,
1157  0.205492, 0.198781, 0.182216, 0.162251, 0.142878, 0.128631, 0.116001, 0.108435, 0.0974843, 0.082092,
1158  0.0755204, 0.0703121, 0.0607066, 0.0554278, 0.0480401, 0.0427023, 0.0377123, 0.0323248, 0.0298584,
1159  0.0244296, 0.0218526, 0.019121, 0.016477, 0.0137309, 0.0137963, 0.0110371, 0.00834028, 0.00686127, 0.00538226
1160 };
1161 
1162 //
1163 //