Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4QInelastic.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26// $Id$
27//
28// ---------------- G4QInelastic class -----------------
29// by Mikhail Kossov, December 2003.
30// G4QInelastic class of the CHIPS Simulation Branch in GEANT4
31// ---------------------------------------------------------------
32// ****************************************************************************************
33// This Header is a part of the CHIPS physics package (author: M. Kosov)
34// ****************************************************************************************
35// Short description: This is a universal class for the incoherent (inelastic)
36// nuclear interactions in the CHIPS model.
37// ---------------------------------------------------------------------------
38//#define debug
39//#define pdebug
40//#define pickupd
41//#define ldebug
42//#define ppdebug
43//#define qedebug
44
45#include "G4QInelastic.hh"
47#include "G4SystemOfUnits.hh"
49
50
51// Initialization of static vectors
52std::vector<G4int> G4QInelastic::ElementZ; // Z of the element(i) in theLastCalc
53std::vector<G4double> G4QInelastic::ElProbInMat; // SumProbabilityElements in Material
54std::vector<std::vector<G4int>*> G4QInelastic::ElIsoN;// N of isotope(j) of Element(i)
55std::vector<std::vector<G4double>*>G4QInelastic::IsoProbInEl;//SumProbabIsotopes inElementI
56
58 G4VDiscreteProcess(processName, fHadronic)
59{
60 G4HadronicDeprecate("G4QInelastic");
61
62 EnMomConservation = G4LorentzVector(0.,0.,0.,0.);
63 nOfNeutrons = 0;
64#ifdef debug
65 G4cout<<"G4QInelastic::Constructor is called"<<G4endl;
66#endif
67 if (verboseLevel>0) G4cout << GetProcessName() << " process is created "<< G4endl;
68 //G4QCHIPSWorld::Get()->GetParticles(nPartCWorld); // Create CHIPSWorld (234 part.max)
69 G4QNucleus::SetParameters(freeNuc,freeDib,clustProb,mediRatio); // Clusterization param's
70 G4Quasmon::SetParameters(Temperature,SSin2Gluons,EtaEtaprime); // Hadronic parameters
71 G4QEnvironment::SetParameters(SolidAngle); // SolAngle of pbar-A secondary mesons capture
72 //@@ Initialize here the G4QuasmonString parameters
73}
74
75G4bool G4QInelastic::manualFlag=false; // If false then standard parameters are used
76G4double G4QInelastic::Temperature=140.; // Critical Temperature (sensitive at High En)
77G4double G4QInelastic::SSin2Gluons=0.3; // Supression of s-quarks (in respect to u&d)
78G4double G4QInelastic::EtaEtaprime=0.3; // Supression of eta mesons (gg->qq/3g->qq)
79G4double G4QInelastic::freeNuc=.04; // Percentage of free nucleons on the surface
80G4double G4QInelastic::freeDib=.08; // Percentage of free diBaryons on the surface
81G4double G4QInelastic::clustProb=4.; // Nuclear clusterization parameter
82G4double G4QInelastic::mediRatio=1.; // medium/vacuum hadronization ratio
83//G4int G4QInelastic::nPartCWorld=152;// The#of particles initialized in CHIPS World
84//G4int G4QInelastic::nPartCWorld=122;// The#of particles initialized in CHIPS World
85G4int G4QInelastic::nPartCWorld=85; // The#of particles initialized in CHIPS World Red
86G4double G4QInelastic::SolidAngle=0.5; // Part of Solid Angle to capture (@@A-dep.)
87G4bool G4QInelastic::EnergyFlux=false; // Flag for Energy Flux use (not MultyQuasmon)
88G4double G4QInelastic::PiPrThresh=141.4; // Pion Production Threshold for gammas
89G4double G4QInelastic::M2ShiftVir=20000.;// Shift for M2=-Q2=m_pi^2 of the virtualGamma
90G4double G4QInelastic::DiNuclMass=1870.; // DoubleNucleon Mass for VirtualNormalization
91G4double G4QInelastic::photNucBias=1.; // BiasingParameter for photo(e,mu,tau)Nuclear
92G4double G4QInelastic::weakNucBias=1.; // BiasingParameter for ChargedCurrents(nu,mu)
93
94void G4QInelastic::SetManual() {manualFlag=true;}
95void G4QInelastic::SetStandard() {manualFlag=false;}
96
97// Fill the private parameters
99 G4double fN, G4double fD, G4double cP, G4double mR,
100 G4int nParCW, G4double solAn, G4bool efFlag,
101 G4double piThresh, G4double mpisq, G4double dinum)
102{
103 Temperature=temper;
104 SSin2Gluons=ssin2g;
105 EtaEtaprime=etaetap;
106 freeNuc=fN;
107 freeDib=fD;
108 clustProb=cP;
109 mediRatio=mR;
110 nPartCWorld = nParCW;
111 EnergyFlux=efFlag;
112 SolidAngle=solAn;
113 PiPrThresh=piThresh;
114 M2ShiftVir=mpisq;
115 DiNuclMass=dinum;
116 G4QCHIPSWorld::Get()->GetParticles(nPartCWorld); // Create CHIPS World with 234 particles
117 G4QNucleus::SetParameters(freeNuc,freeDib,clustProb,mediRatio); // Clusterization param's
118 G4Quasmon::SetParameters(Temperature,SSin2Gluons,EtaEtaprime); // Hadronic parameters
119 G4QEnvironment::SetParameters(SolidAngle); // SolAngle of pbar-A secondary mesons capture
120}
121
122void G4QInelastic::SetPhotNucBias(G4double phnB) {photNucBias=phnB;}
123void G4QInelastic::SetWeakNucBias(G4double ccnB) {weakNucBias=ccnB;}
124
125// Destructor
126
128{
129 // The following is just a copy of what is done in PostStepDoIt every interaction !
130 // The correction is if(IPIE), so just for(...;ip<IPIE;...) does not work ! @@
131 G4int IPIE=IsoProbInEl.size(); // How many old elements?
132 if(IPIE) for(G4int ip=0; ip<IPIE; ++ip) // Clean up the SumProb's of Isotopes (SPI)
133 {
134 std::vector<G4double>* SPI=IsoProbInEl[ip]; // Pointer to the SPI vector
135 SPI->clear();
136 delete SPI;
137 std::vector<G4int>* IsN=ElIsoN[ip]; // Pointer to the N vector
138 IsN->clear();
139 delete IsN;
140 }
141 ElProbInMat.clear(); // Clean up the SumProb's of Elements (SPE)
142 ElementZ.clear(); // Clear the body vector for Z of Elements
143 IsoProbInEl.clear(); // Clear the body vector for SPI
144 ElIsoN.clear(); // Clear the body vector for N of Isotopes
145}
146
147
149{
150 return EnMomConservation;
151}
152
154{
155 return nOfNeutrons;
156}
157
158// output of the function must be in units of length! L=1/sig_V,sig_V=SUM(n(j,i)*sig(j,i)),
159// where n(i,j) is a number of nuclei of the isotop j of the element i in V=1(lengtUnit^3)
160// ********** All CHIPS cross sections are calculated in the surface units ************
162{
163#ifdef debug
164 G4cout<<"G4QInelastic::GetMeanFreePath: Called Fc="<<*Fc<<G4endl;
165#endif
166 *Fc = NotForced;
167#ifdef debug
168 G4cout<<"G4QInelastic::GetMeanFreePath: Before GetDynPart"<<G4endl;
169#endif
170 const G4DynamicParticle* incidentParticle = aTrack.GetDynamicParticle();
171#ifdef debug
172 G4cout<<"G4QInelastic::GetMeanFreePath: Before GetDef"<<G4endl;
173#endif
174 G4ParticleDefinition* incidentParticleDefinition=incidentParticle->GetDefinition();
175 if( !IsApplicable(*incidentParticleDefinition))
176 {
177 G4cout<<"-W-G4QInelastic::GetMeanFreePath called for not implemented particle"<<G4endl;
178 return DBL_MAX;
179 }
180 // Calculate the mean Cross Section for the set of Elements(*Isotopes) in the Material
181 G4double Momentum = incidentParticle->GetTotalMomentum(); // 3-momentum of the Particle
182#ifdef debug
183 G4cout<<"G4QInelastic::GetMeanFreePath: BeforeGetMaterial"<<G4endl;
184#endif
185 const G4Material* material = aTrack.GetMaterial(); // Get the current material
186 const G4double* NOfNucPerVolume = material->GetVecNbOfAtomsPerVolume();
187 const G4ElementVector* theElementVector = material->GetElementVector();
188 G4int nE=material->GetNumberOfElements();
189#ifdef debug
190 G4cout<<"G4QInelastic::GetMeanFreePath:"<<nE<<" Elem's in theMaterial"<<G4endl;
191#endif
192 //G4bool leptoNuc=false; // By default the reaction is not lepto-nuclear *Growing point*
193 G4VQCrossSection* CSmanager=0;
194 G4VQCrossSection* CSmanager2=0;
195 G4QNeutronCaptureRatio* capMan=0;
196 G4int pPDG=0;
197 G4int pZ = incidentParticleDefinition->GetAtomicNumber();
198 G4int pA = incidentParticleDefinition->GetAtomicMass();
199 if(incidentParticleDefinition == G4Neutron::Neutron())
200 {
203#ifdef debug
204 G4cout<<"G4QInelastic::GetMeanFreePath: CSmanager is defined for the neutron"<<G4endl;
205#endif
206 pPDG=2112;
207 }
208 else if(incidentParticleDefinition == G4Proton::Proton())
209 {
211 pPDG=2212;
212 }
213 else if(incidentParticleDefinition == G4PionMinus::PionMinus())
214 {
216 pPDG=-211;
217 }
218 else if(incidentParticleDefinition == G4PionPlus::PionPlus())
219 {
221 pPDG=211;
222 }
223 else if(incidentParticleDefinition == G4KaonMinus::KaonMinus())
224 {
226 pPDG=-321;
227 }
228 else if(incidentParticleDefinition == G4KaonPlus::KaonPlus())
229 {
231 pPDG=321;
232 }
233 else if(incidentParticleDefinition == G4KaonZeroLong::KaonZeroLong() ||
234 incidentParticleDefinition == G4KaonZeroShort::KaonZeroShort() ||
235 incidentParticleDefinition == G4KaonZero::KaonZero() ||
236 incidentParticleDefinition == G4AntiKaonZero::AntiKaonZero() )
237 {
239 if(G4UniformRand() > 0.5) pPDG= 311;
240 else pPDG=-311;
241 }
242 else if(incidentParticleDefinition == G4Lambda::Lambda())
243 {
245 pPDG=3122;
246 }
247 else if(pZ > 0 && pA > 1) // Ions (not implemented yet, should not be used)
248 {
249 G4cout<<"-Warning-G4QInelastic::GetMeanFreePath: G4QInelastic called for ions"<<G4endl;
251 pPDG=90000000+999*pZ+pA;
252 }
253 else if(incidentParticleDefinition == G4SigmaPlus::SigmaPlus())
254 {
256 pPDG=3222;
257 }
258 else if(incidentParticleDefinition == G4SigmaMinus::SigmaMinus())
259 {
261 pPDG=3112;
262 }
263 else if(incidentParticleDefinition == G4SigmaZero::SigmaZero())
264 {
266 pPDG=3212;
267 }
268 else if(incidentParticleDefinition == G4XiMinus::XiMinus())
269 {
271 pPDG=3312;
272 }
273 else if(incidentParticleDefinition == G4XiZero::XiZero())
274 {
276 pPDG=3322;
277 }
278 else if(incidentParticleDefinition == G4OmegaMinus::OmegaMinus())
279 {
281 pPDG=3334;
282 }
283 else if(incidentParticleDefinition == G4MuonPlus::MuonPlus() ||
284 incidentParticleDefinition == G4MuonMinus::MuonMinus())
285 {
287 //leptoNuc=true;
288 pPDG=13;
289 }
290 else if(incidentParticleDefinition == G4AntiNeutron::AntiNeutron())
291 {
293 pPDG=-2112;
294 }
295 else if(incidentParticleDefinition == G4AntiProton::AntiProton())
296 {
298 pPDG=-2212;
299 }
300 else if(incidentParticleDefinition == G4AntiLambda::AntiLambda())
301 {
303 pPDG=-3122;
304 }
305 else if(incidentParticleDefinition == G4AntiSigmaPlus::AntiSigmaPlus())
306 {
308 pPDG=-3222;
309 }
310 else if(incidentParticleDefinition == G4AntiSigmaMinus::AntiSigmaMinus())
311 {
313 pPDG=-3112;
314 }
315 else if(incidentParticleDefinition == G4AntiSigmaZero::AntiSigmaZero())
316 {
318 pPDG=-3212;
319 }
320 else if(incidentParticleDefinition == G4AntiXiMinus::AntiXiMinus())
321 {
323 pPDG=-3312;
324 }
325 else if(incidentParticleDefinition == G4AntiXiZero::AntiXiZero())
326 {
328 pPDG=-3322;
329 }
330 else if(incidentParticleDefinition == G4AntiOmegaMinus::AntiOmegaMinus())
331 {
333 pPDG=-3334;
334 }
335 else if(incidentParticleDefinition == G4Gamma::Gamma())
336 {
338 pPDG=22;
339 }
340 else if(incidentParticleDefinition == G4Electron::Electron() ||
341 incidentParticleDefinition == G4Positron::Positron())
342 {
344 //leptoNuc=true;
345 pPDG=11;
346 }
347 else if(incidentParticleDefinition == G4TauPlus::TauPlus() ||
348 incidentParticleDefinition == G4TauMinus::TauMinus())
349 {
351 //leptoNuc=true;
352 pPDG=15;
353 }
354 else if(incidentParticleDefinition == G4NeutrinoMu::NeutrinoMu() )
355 {
358 //leptoNuc=true;
359 pPDG=14;
360 }
361 else if(incidentParticleDefinition == G4AntiNeutrinoMu::AntiNeutrinoMu() )
362 {
365 //leptoNuc=true;
366 pPDG=-14;
367 }
368 else if(incidentParticleDefinition == G4NeutrinoE::NeutrinoE() )
369 {
372 //leptoNuc=true;
373 pPDG=12;
374 }
375 else if(incidentParticleDefinition == G4AntiNeutrinoE::AntiNeutrinoE() )
376 {
379 //leptoNuc=true;
380 pPDG=-12;
381 }
382 else
383 {
384 G4cout<<"-Warning-G4QInelastic::GetMeanFreePath:Particle "
385 <<incidentParticleDefinition->GetPDGEncoding()<<" isn't supported"<<G4endl;
386 return DBL_MAX;
387 }
388 G4QIsotope* Isotopes = G4QIsotope::Get(); // Pointer to the G4QIsotopes singleton
389 G4double sigma=0.; // Sums over elements for the material
390 G4int IPIE=IsoProbInEl.size(); // How many old elements?
391 if(IPIE) for(G4int ip=0; ip<IPIE; ++ip) // Clean up the SumProb's of Isotopes (SPI)
392 {
393 std::vector<G4double>* SPI=IsoProbInEl[ip]; // Pointer to the SPI vector
394 SPI->clear();
395 delete SPI;
396 std::vector<G4int>* IsN=ElIsoN[ip]; // Pointer to the N vector
397 IsN->clear();
398 delete IsN;
399 }
400 ElProbInMat.clear(); // Clean up the SumProb's of Elements (SPE)
401 ElementZ.clear(); // Clear the body vector for Z of Elements
402 IsoProbInEl.clear(); // Clear the body vector for SPI
403 ElIsoN.clear(); // Clear the body vector for N of Isotopes
404 for(G4int i=0; i<nE; ++i)
405 {
406 G4Element* pElement=(*theElementVector)[i]; // Pointer to the current element
407 G4int Z = static_cast<G4int>(pElement->GetZ()); // Z of the Element
408 ElementZ.push_back(Z); // Remember Z of the Element
409 G4int isoSize=0; // The default for the isoVectorLength is 0
410 G4int indEl=0; // Index of non-trivial element or 0(default)
411 G4IsotopeVector* isoVector=pElement->GetIsotopeVector(); // Get the predefined IsoVect
412 if(isoVector) isoSize=isoVector->size();// Get size of the existing isotopeVector
413#ifdef debug
414 G4cout<<"G4QInelastic::GetMeanFreePath: isovectorLength="<<isoSize<<G4endl; // Result
415#endif
416 if(isoSize) // The Element has non-trivial abundance set
417 {
418 indEl=pElement->GetIndex()+1; // Index of the non-trivial element
419 if(!Isotopes->IsDefined(Z,indEl)) // This index is not defined for this Z: define
420 {
421 std::vector<std::pair<G4int,G4double>*>* newAbund =
422 new std::vector<std::pair<G4int,G4double>*>;
423 G4double* abuVector=pElement->GetRelativeAbundanceVector();
424 for(G4int j=0; j<isoSize; j++) // Calculation of abundance vector for isotopes
425 {
426 G4int N=pElement->GetIsotope(j)->GetN()-Z; // N means A=N+Z !
427 if(pElement->GetIsotope(j)->GetZ()!=Z)G4cerr<<"G4QInelastic::GetMeanFreePath"
428 <<": Z="<<pElement->GetIsotope(j)->GetZ()<<"#"<<Z<<G4endl;
429 G4double abund=abuVector[j];
430 std::pair<G4int,G4double>* pr= new std::pair<G4int,G4double>(N,abund);
431#ifdef debug
432 G4cout<<"G4QInelastic::GetMeanFreePath: p#="<<j<<",N="<<N<<",ab="<<abund<<G4endl;
433#endif
434 newAbund->push_back(pr);
435 }
436#ifdef debug
437 G4cout<<"G4QInelastic::GetMeanFreePath: pairVectLength="<<newAbund->size()<<G4endl;
438#endif
439 indEl=G4QIsotope::Get()->InitElement(Z,indEl,newAbund); // definition of the newInd
440 for(G4int k=0; k<isoSize; k++) delete (*newAbund)[k]; // Cleaning temporary
441 delete newAbund; // Was "new" in the beginning of the name space
442 }
443 }
444 std::vector<std::pair<G4int,G4double>*>* cs= Isotopes->GetCSVector(Z,indEl);//CSPointer
445 std::vector<G4double>* SPI = new std::vector<G4double>; // Pointer to the SPI vector
446 IsoProbInEl.push_back(SPI);
447 std::vector<G4int>* IsN = new std::vector<G4int>; // Pointer to the N vector
448 ElIsoN.push_back(IsN);
449 G4int nIs=cs->size(); // A#Of Isotopes in the Element
450 G4double susi=0.; // sum of CS over isotopes
451#ifdef debug
452 G4cout<<"G4QInelastic::GetMeanFreePath: Before Loop nIs="<<nIs<<G4endl;
453#endif
454 if(nIs) for(G4int j=0; j<nIs; j++) // Calculate CS for eachIsotope of El
455 {
456 std::pair<G4int,G4double>* curIs=(*cs)[j]; // A pointer, which is used twice
457 G4int N=curIs->first; // #of Neuterons in the isotope j of El i
458 IsN->push_back(N); // Remember Min N for the Element
459#ifdef debug
460 G4cout<<"G4QInel::GetMeanFrP: Before CS, P="<<Momentum<<",Z="<<Z<<",N="<<N<<G4endl;
461#endif
462 if(!pPDG) G4cout<<"-Warning-G4QInelastic::GetMeanFrP: (1) projectile PDG=0"<<G4endl;
463 G4double CSI=CSmanager->GetCrossSection(true,Momentum,Z,N,pPDG);//CS(j,i) for isotope
464 if(CSmanager2)CSI+=CSmanager2->GetCrossSection(true,Momentum,Z,N,pPDG);//CS(j,i)nu,nu
465 if(capMan) CSI*=(1.-capMan->GetRatio(Momentum, Z, N));
466#ifdef debug
467 G4cout<<"GQC::GMF:X="<<CSI<<",M="<<Momentum<<",Z="<<Z<<",N="<<N<<",P="<<pPDG<<G4endl;
468#endif
469 curIs->second = CSI;
470 susi+=CSI; // Make a sum per isotopes
471 SPI->push_back(susi); // Remember summed cross-section
472 } // End of temporary initialization of the cross sections in the G4QIsotope singeltone
473 sigma+=Isotopes->GetMeanCrossSection(Z,indEl)*NOfNucPerVolume[i];//SUM(MeanCS*NOfNperV)
474 ElProbInMat.push_back(sigma);
475 } // End of LOOP over Elements
476#ifdef debug
477 G4cout<<"G4QInel::GetMeanFrPa:S="<<sigma<<",e="<<photNucBias<<",w="<<weakNucBias<<G4endl;
478#endif
479 // Check that cross section is not zero and return the mean free path
480 if(photNucBias!=1.) if(incidentParticleDefinition == G4Gamma::Gamma() ||
481 incidentParticleDefinition == G4MuonPlus::MuonPlus() ||
482 incidentParticleDefinition == G4MuonMinus::MuonMinus() ||
483 incidentParticleDefinition == G4Electron::Electron() ||
484 incidentParticleDefinition == G4Positron::Positron() ||
485 incidentParticleDefinition == G4TauMinus::TauMinus() ||
486 incidentParticleDefinition == G4TauPlus::TauPlus() )
487 sigma*=photNucBias;
488 if(weakNucBias!=1.) if(incidentParticleDefinition==G4NeutrinoE::NeutrinoE() ||
489 incidentParticleDefinition==G4AntiNeutrinoE::AntiNeutrinoE() ||
490 incidentParticleDefinition==G4NeutrinoTau::NeutrinoTau() ||
491 incidentParticleDefinition==G4AntiNeutrinoTau::AntiNeutrinoTau()||
492 incidentParticleDefinition==G4NeutrinoMu::NeutrinoMu() ||
493 incidentParticleDefinition==G4AntiNeutrinoMu::AntiNeutrinoMu() )
494 sigma*=weakNucBias;
495 if(sigma > 0.) return 1./sigma; // Mean path [distance]
496 return DBL_MAX;
497}
498
499
501{
502 G4int Z=particle.GetAtomicNumber();
503 G4int A=particle.GetAtomicMass();
504 if (particle == *( G4Neutron::Neutron() )) return true;
505 else if (particle == *( G4Proton::Proton() )) return true;
506 else if (particle == *( G4MuonPlus::MuonPlus() )) return true;
507 else if (particle == *( G4MuonMinus::MuonMinus() )) return true;
508 else if (particle == *( G4Gamma::Gamma() )) return true;
509 else if (particle == *( G4Electron::Electron() )) return true;
510 else if (particle == *( G4Positron::Positron() )) return true;
511 else if (particle == *( G4PionMinus::PionMinus() )) return true;
512 else if (particle == *( G4PionPlus::PionPlus() )) return true;
513 else if (particle == *( G4KaonPlus::KaonPlus() )) return true;
514 else if (particle == *( G4KaonMinus::KaonMinus() )) return true;
515 else if (particle == *( G4KaonZeroLong::KaonZeroLong() )) return true;
516 else if (particle == *( G4KaonZeroShort::KaonZeroShort() )) return true;
517 else if (particle == *( G4Lambda::Lambda() )) return true;
518 else if (particle == *( G4SigmaPlus::SigmaPlus() )) return true;
519 else if (particle == *( G4SigmaMinus::SigmaMinus() )) return true;
520 else if (particle == *( G4SigmaZero::SigmaZero() )) return true;
521 else if (particle == *( G4XiMinus::XiMinus() )) return true;
522 else if (particle == *( G4XiZero::XiZero() )) return true;
523 else if (particle == *( G4OmegaMinus::OmegaMinus() )) return true;
524 else if (particle == *(G4GenericIon::GenericIon()) || (Z > 0 && A > 1)) return true;
525 else if (particle == *( G4AntiNeutron::AntiNeutron() )) return true;
526 else if (particle == *( G4AntiProton::AntiProton() )) return true;
527 else if (particle == *( G4AntiLambda::AntiLambda() )) return true;
528 else if (particle == *( G4AntiSigmaPlus::AntiSigmaPlus() )) return true;
529 else if (particle == *(G4AntiSigmaMinus::AntiSigmaMinus())) return true;
530 else if (particle == *( G4AntiSigmaZero::AntiSigmaZero() )) return true;
531 else if (particle == *( G4AntiXiMinus::AntiXiMinus() )) return true;
532 else if (particle == *( G4AntiXiZero::AntiXiZero() )) return true;
533 else if (particle == *(G4AntiOmegaMinus::AntiOmegaMinus())) return true;
534 else if (particle == *( G4TauPlus::TauPlus() )) return true;
535 else if (particle == *( G4TauMinus::TauMinus() )) return true;
536 else if (particle == *( G4AntiNeutrinoE::AntiNeutrinoE() )) return true;
537 else if (particle == *( G4NeutrinoE::NeutrinoE() )) return true;
538 else if (particle == *(G4AntiNeutrinoMu::AntiNeutrinoMu())) return true;
539 else if (particle == *( G4NeutrinoMu::NeutrinoMu() )) return true;
540 //else if (particle == *(G4AntiNeutrinoTau::AntiNeutrinoTau())) return true;
541 //else if (particle == *( G4NeutrinoTau::NeutrinoTau() )) return true;
542#ifdef debug
543 G4cout<<"***G4QInelastic::IsApplicable: PDG="<<particle.GetPDGEncoding()<<G4endl;
544#endif
545 return false;
546}
547
549{
550 static const G4double third = 1./3.;
551 static const G4double me=G4Electron::Electron()->GetPDGMass(); // electron mass
552 static const G4double me2=me*me; // squared electron mass
553 static const G4double mu=G4MuonMinus::MuonMinus()->GetPDGMass(); // muon mass
554 static const G4double mu2=mu*mu; // squared muon mass
555 static const G4double mt=G4TauMinus::TauMinus()->GetPDGMass(); // tau mass
556 static const G4double mt2=mt*mt; // squared tau mass
557 //static const G4double dpi=M_PI+M_PI; // 2*pi (for Phi distr.) ***changed to twopi***
558 static const G4double mNeut= G4QPDGCode(2112).GetMass();
559 static const G4double mNeut2= mNeut*mNeut;
560 static const G4double mProt= G4QPDGCode(2212).GetMass();
561 static const G4double mProt2= mProt*mProt;
562 static const G4double dM=mProt+mNeut; // doubled nucleon mass
563 static const G4double hdM=dM/2.; // M of the "nucleon"
564 static const G4double hdM2=hdM*hdM; // M2 of the "nucleon"
565 static const G4double mLamb= G4QPDGCode(3122).GetMass(); // Mass of Lambda/antiL
566 static const G4double mPi0 = G4QPDGCode(111).GetMass();
567 static const G4double mPi0s= mPi0*mPi0;
568 static const G4double mDeut= G4QPDGCode(2112).GetNuclMass(1,1,0);// Mass of deuteron
569 //static const G4double mDeut2=mDeut*mDeut; // SquaredMassOfDeuteron
570 static const G4double mTrit= G4QPDGCode(2112).GetNuclMass(1,2,0);// Mass of tritium
571 static const G4double mHel3= G4QPDGCode(2112).GetNuclMass(2,1,0);// Mass of Helium3
572 static const G4double mAlph= G4QPDGCode(2112).GetNuclMass(2,2,0);// Mass of alpha
573 static const G4double mPi = G4QPDGCode(211).GetMass();
574 static const G4double tmPi = mPi+mPi; // Doubled mass of the charged pion
575 static const G4double stmPi= tmPi*tmPi; // Squared Doubled mass of the charged pion
576 static const G4double mPPi = mPi+mProt; // Delta threshold
577 static const G4double mPPi2= mPPi*mPPi; // Delta low threshold for W2
578 //static const G4double mDel2= 1400*1400; // Delta up threshold for W2 (in MeV^2)
579 // Static definitions for electrons (nu,e) -----------------------------------------
580 static const G4double meN = mNeut+me;
581 static const G4double meN2= meN*meN;
582 static const G4double fmeN= 4*mNeut2*me2;
583 static const G4double mesN= mNeut2+me2;
584 static const G4double meP = mProt+me;
585 static const G4double meP2= meP*meP;
586 static const G4double fmeP= 4*mProt2*me2;
587 static const G4double mesP= mProt2+me2;
588 static const G4double medM= me2/dM; // for x limit
589 static const G4double meD = mPPi+me; // Multiperipheral threshold
590 static const G4double meD2= meD*meD;
591 // Static definitions for muons (nu,mu) -----------------------------------------
592 static const G4double muN = mNeut+mu;
593 static const G4double muN2= muN*muN;
594 static const G4double fmuN= 4*mNeut2*mu2;
595 static const G4double musN= mNeut2+mu2;
596 static const G4double muP = mProt+mu;
597 static const G4double muP2= muP*muP; // +
598 static const G4double fmuP= 4*mProt2*mu2; // +
599 static const G4double musP= mProt2+mu2;
600 static const G4double mudM= mu2/dM; // for x limit
601 static const G4double muD = mPPi+mu; // Multiperipheral threshold
602 static const G4double muD2= muD*muD;
603 // Static definitions for muons (nu,nu) -----------------------------------------
604 //static const G4double nuN = mNeut;
605 //static const G4double nuN2= mNeut2;
606 //static const G4double fnuN= 0.;
607 //static const G4double nusN= mNeut2;
608 //static const G4double nuP = mProt;
609 //static const G4double nuP2= mProt2;
610 //static const G4double fnuP= 0.;
611 //static const G4double nusP= mProt2;
612 //static const G4double nudM= 0.; // for x limit
613 //static const G4double nuD = mPPi; // Multiperipheral threshold
614 //static const G4double nuD2= mPPi2;
615 static const G4LorentzVector vacuum4M(0.,0.,0.,0.);
616 //-------------------------------------------------------------------------------------
617 static G4bool CWinit = true; // CHIPS Warld needs to be initted
618 if(CWinit)
619 {
620 CWinit=false;
621 G4QCHIPSWorld::Get()->GetParticles(nPartCWorld); // Create CHIPS World (234 part.max)
622 }
623 //-------------------------------------------------------------------------------------
624 const G4DynamicParticle* projHadron = track.GetDynamicParticle();
625 const G4ParticleDefinition* particle=projHadron->GetDefinition();
626#ifdef debug
627 G4cout<<"G4QInelastic::PostStepDoIt: Before the GetMeanFreePath is called"<<G4endl;
628#endif
630 GetMeanFreePath(track, 1., &cond);
631#ifdef debug
632 G4cout<<"G4QInelastic::PostStepDoIt: After the GetMeanFreePath is called"<<G4endl;
633#endif
634 G4bool scat=false; // No CHEX in proj scattering
635 G4int scatPDG=0; // Must be filled if true (CHEX)
636 G4LorentzVector proj4M=projHadron->Get4Momentum(); // 4-momentum of the projectile (IU?)
637 G4LorentzVector scat4M=proj4M; // Must be filled if true
638 G4double momentum = projHadron->GetTotalMomentum(); // 3-momentum of the Particle
639 G4double Momentum=proj4M.rho();
640 if(std::fabs(Momentum-momentum)>.001)
641 G4cerr<<"*G4QInelastic::PostStepDoIt: P="<<Momentum<<"#"<<momentum<<G4endl;
642#ifdef debug
643 G4double mp=proj4M.m();
644 G4cout<<"-->G4QInel::PostStDoIt:*called*, 4M="<<proj4M<<", P="<<Momentum<<"="<<momentum
645 <<",m="<<mp<<G4endl;
646#endif
647 if (!IsApplicable(*particle)) // Check applicability
648 {
649 G4cerr<<"G4QInelastic::PostStepDoIt:Only gam,e+,e-,mu+,mu-,t+,t-,p are implemented."
650 <<G4endl;
651 return 0;
652 }
653 const G4Material* material = track.GetMaterial(); // Get the current material
654 G4int Z=0;
655 const G4ElementVector* theElementVector = material->GetElementVector();
656 G4int nE=material->GetNumberOfElements();
657#ifdef debug
658 G4cout<<"G4QInelastic::PostStepDoIt: "<<nE<<" elements in the material."<<G4endl;
659#endif
660 G4int projPDG=0; // PDG Code prototype for the captured hadron
661 G4int pZ=particle->GetAtomicNumber();
662 G4int pA=particle->GetAtomicMass();
663 if (particle == G4Neutron::Neutron() ) projPDG= 2112;
664 else if (particle == G4Proton::Proton() ) projPDG= 2212;
665 else if (particle == G4PionMinus::PionMinus() ) projPDG= -211;
666 else if (particle == G4PionPlus::PionPlus() ) projPDG= 211;
667 else if (particle == G4KaonPlus::KaonPlus() ) projPDG= 321;
668 else if (particle == G4KaonMinus::KaonMinus() ) projPDG= -321;
669 else if (particle == G4KaonZeroLong::KaonZeroLong() ||
670 particle == G4KaonZeroShort::KaonZeroShort() ||
671 particle == G4KaonZero::KaonZero() ||
672 particle == G4AntiKaonZero::AntiKaonZero() )
673 {
674 if(G4UniformRand() > 0.5) projPDG= 311;
675 else projPDG= -311;
676 }
677 else if ( pZ > 0 && pA > 1 ) projPDG = 90000000+999*pZ+pA;
678 else if (particle == G4Lambda::Lambda() ) projPDG= 3122;
679 else if (particle == G4SigmaPlus::SigmaPlus() ) projPDG= 3222;
680 else if (particle == G4SigmaMinus::SigmaMinus() ) projPDG= 3112;
681 else if (particle == G4SigmaZero::SigmaZero() ) projPDG= 3212;
682 else if (particle == G4XiMinus::XiMinus() ) projPDG= 3312;
683 else if (particle == G4XiZero::XiZero() ) projPDG= 3322;
684 else if (particle == G4OmegaMinus::OmegaMinus() ) projPDG= 3334;
685 else if (particle == G4AntiNeutron::AntiNeutron() ) projPDG=-2112;
686 else if (particle == G4AntiProton::AntiProton() ) projPDG=-2212;
687 else if (particle == G4MuonPlus::MuonPlus() ) projPDG= -13;
688 else if (particle == G4MuonMinus::MuonMinus() ) projPDG= 13;
689 else if (particle == G4Gamma::Gamma() ) projPDG= 22;
690 else if (particle == G4Electron::Electron() ) projPDG= 11;
691 else if (particle == G4Positron::Positron() ) projPDG= -11;
692 else if (particle == G4NeutrinoMu::NeutrinoMu() ) projPDG= 14;
693 else if (particle == G4AntiNeutrinoMu::AntiNeutrinoMu() ) projPDG= -14;
694 else if (particle == G4AntiLambda::AntiLambda() ) projPDG=-3122;
695 else if (particle == G4AntiSigmaPlus::AntiSigmaPlus() ) projPDG=-3222;
696 else if (particle == G4AntiSigmaMinus::AntiSigmaMinus() ) projPDG=-3112;
697 else if (particle == G4AntiSigmaZero::AntiSigmaZero() ) projPDG=-3212;
698 else if (particle == G4AntiXiMinus::AntiXiMinus() ) projPDG=-3312;
699 else if (particle == G4AntiXiZero::AntiXiZero() ) projPDG=-3322;
700 else if (particle == G4AntiOmegaMinus::AntiOmegaMinus() ) projPDG=-3334;
701 else if (particle == G4NeutrinoE::NeutrinoE() ) projPDG= 12;
702 else if (particle == G4AntiNeutrinoE::AntiNeutrinoE() ) projPDG= -12;
703 else if (particle == G4TauPlus::TauPlus() ) projPDG= -15;
704 else if (particle == G4TauMinus::TauMinus() ) projPDG= 15;
705 else if (particle == G4NeutrinoTau::NeutrinoTau() ) projPDG= 16;
706 else if (particle == G4AntiNeutrinoTau::AntiNeutrinoTau()) projPDG= -16;
707 G4int aProjPDG=std::abs(projPDG);
708#ifdef debug
709 G4int prPDG=particle->GetPDGEncoding();
710 G4cout<<"G4QInelastic::PostStepDoIt: projPDG="<<projPDG<<", stPDG="<<prPDG<<G4endl;
711#endif
712 if(!projPDG)
713 {
714 G4cerr<<"---Warning---G4QInelastic::PostStepDoIt:Undefined interacting hadron"<<G4endl;
715 return 0;
716 }
717 G4int EPIM=ElProbInMat.size();
718#ifdef debug
719 G4cout<<"G4QInel::PostStDoIt: m="<<EPIM<<",n="<<nE<<",T="<<ElProbInMat[EPIM-1]<<G4endl;
720#endif
721 G4int i=0;
722 if(EPIM>1)
723 {
724 G4double rnd = ElProbInMat[EPIM-1]*G4UniformRand();
725 for(i=0; i<nE; ++i)
726 {
727#ifdef debug
728 G4cout<<"G4QInelastic::PostStepDoIt:E["<<i<<"]="<<ElProbInMat[i]<<",r="<<rnd<<G4endl;
729#endif
730 if (rnd<ElProbInMat[i]) break;
731 }
732 if(i>=nE) i=nE-1; // Top limit for the Element
733 }
734 G4Element* pElement=(*theElementVector)[i];
735 Z=static_cast<G4int>(pElement->GetZ());
736#ifdef debug
737 G4cout<<"G4QInelastic::PostStepDoIt: i="<<i<<", Z(element)="<<Z<<G4endl;
738#endif
739 if(Z<=0)
740 {
741 G4cerr<<"---Warning---G4QInelastic::PostStepDoIt: Element with Z="<<Z<<G4endl;
742 if(Z<0) return 0;
743 }
744 std::vector<G4double>* SPI = IsoProbInEl[i];// Vector of summedProbabilities for isotopes
745 std::vector<G4int>* IsN = ElIsoN[i]; // Vector of "#of neutrons" in the isotope El[i]
746 G4int nofIsot=SPI->size(); // #of isotopes in the element i
747#ifdef debug
748 G4cout<<"G4QInel::PosStDoIt:n="<<nofIsot<<",T="<<(*SPI)[nofIsot-1]<<G4endl;
749#endif
750 G4int j=0;
751 if(nofIsot>1)
752 {
753 G4double rndI=(*SPI)[nofIsot-1]*G4UniformRand(); // Randomize the isotop of the Element
754 for(j=0; j<nofIsot; ++j)
755 {
756#ifdef debug
757 G4cout<<"G4QInelastic::PostStepDoIt: SP["<<j<<"]="<<(*SPI)[j]<<", r="<<rndI<<G4endl;
758#endif
759 if(rndI < (*SPI)[j]) break;
760 }
761 if(j>=nofIsot) j=nofIsot-1; // Top limit for the isotope
762 }
763 G4int N =(*IsN)[j]; ; // Randomized number of neutrons
764#ifdef debug
765 G4cout<<"G4QInelastic::PostStepDoIt: Z="<<Z<<", j="<<i<<", N(isotope)="<<N<<G4endl;
766#endif
767 G4double kinEnergy= projHadron->GetKineticEnergy();
768 G4ParticleMomentum dir = projHadron->GetMomentumDirection();
769 if(projPDG==22 && Z==1 && !N && Momentum<150.)
770 {
771#ifdef debug
772 G4cerr<<"---LowPHOTON---G4QInelastic::PSDoIt: Called for zero Cross-section"<<G4endl;
773#endif
774 //Do Nothing Action insead of the reaction
779 return G4VDiscreteProcess::PostStepDoIt(track,step);
780 }
781 if(N<0)
782 {
783 G4cerr<<"-Warning-G4QInelastic::PostStepDoIt: Isotope with Z="<<Z<<", 0>N="<<N<<G4endl;
784 return 0;
785 }
786 nOfNeutrons=N; // Remember it for the energy-momentum check
787 //G4double am=Z+N;
788 G4int am=Z+N;
789 //G4double dd=0.025;
790 //G4double sr=std::sqrt(am);
791 //G4double dsr=0.01*(sr+sr);
792 //if(dsr<dd)dsr=dd;
793 //G4double medRA=mediRatio*G4QThd(am);
794 G4double medRA=mediRatio;
795 if(manualFlag) G4QNucleus::SetParameters(freeNuc,freeDib,clustProb,medRA); // ManualP
796 //else if(projPDG==-2212)G4QNucleus::SetParameters(1.-dsr-dsr,dd+dd,5.,9.);//aP ClustPars
797 //else if(projPDG==-211) G4QNucleus::SetParameters(.67-dsr,.32-dsr,5.,9.); //Pi-ClustPars
798 //else if(projPDG ==-2212 || projPDG ==-2112)
799 // G4QNucleus::SetParameters(1.-dsr-dsr,dd+dd,5.,1.);//aP ClustPars
800 //else if(projPDG ==-211 ||projPDG == 211 )
801 // G4QNucleus::SetParameters(.67-dsr,.32-dsr,5.,1.); //Pi-ClustPars
802#ifdef debug
803 G4cout<<"G4QInelastic::PostStepDoIt: N="<<N<<" for element with Z="<<Z<<G4endl;
804#endif
806 G4double weight = track.GetWeight();
807#ifdef debug
808 G4cout<<"G4QInelastic::PostStepDoIt: weight="<<weight<<G4endl;
809#endif
810 if(photNucBias!=1.) weight/=photNucBias;
811 else if(weakNucBias!=1.) weight/=weakNucBias;
812 G4double localtime = track.GetGlobalTime();
813#ifdef debug
814 G4cout<<"G4QInelastic::PostStepDoIt: localtime="<<localtime<<G4endl;
815#endif
817 G4TouchableHandle trTouchable = track.GetTouchableHandle();
818#ifdef debug
819 G4cout<<"G4QInelastic::PostStepDoIt: position="<<position<<G4endl;
820#endif
821 //
822 G4int targPDG=90000000+Z*1000+N; // PDG Code of the target nucleus
823 G4QPDGCode targQPDG(targPDG);
824 G4double tgM=targQPDG.GetMass(); // Target mass
825 G4double tM=tgM; // Target mass (copy to be changed)
826 G4QHadronVector* output=new G4QHadronVector;// Prototype of Fragm Output G4QHadronVector
827 G4double absMom = 0.; // Prototype of absorbed by nucleus Moment
828 G4QHadronVector* leadhs=new G4QHadronVector;// Prototype of QuasmOutput G4QHadronVector
829 G4LorentzVector lead4M(0.,0.,0.,0.); // Prototype of LeadingQ 4-momentum
830#ifdef debug
831 G4cout<<"G4QInelastic::PostStepDoIt: projPDG="<<aProjPDG<<", targPDG="<<targPDG<<G4endl;
832#endif
833 //
834 // Leptons with photonuclear
835 // Lepto-nuclear case with the equivalent photon algorithm. @@InFuture + NC (?)
836 //
837 if (aProjPDG == 11 || aProjPDG == 13 || aProjPDG == 15)
838 {
839#ifdef debug
840 G4cout<<"G4QInelastic::PostStDoIt:startSt="<<aParticleChange.GetTrackStatus()<<G4endl;
841#endif
843 G4double ml=me;
844 G4double ml2=me2;
845 if(aProjPDG== 13)
846 {
848 ml=mu;
849 ml2=mu2;
850 }
851 if(aProjPDG== 15)
852 {
854 ml=mt;
855 ml2=mt2;
856 }
857 // @@ Probably this is not necessary any more (?)
858 if(!aProjPDG) G4cout<<"-Warning-G4QInelast::PostStepDoIt:(2) projectile PDG=0"<<G4endl;
859 G4double xSec=CSmanager->GetCrossSection(false,Momentum,Z,N,aProjPDG);// Recalculate XS
860 // @@ check a possibility to separate p, n, or alpha (!)
861 if(Z==1 && !N && Momentum<150.) xSec=0.;
862#ifdef debug
863 G4cout<<"-Forse-G4QInel::PStDoIt:P="<<Momentum<<",PDG="<<projPDG<<",xS="<<xSec<<G4endl;
864#endif
865 if(xSec <= 0.) // The cross-section is 0 -> Do Nothing
866 {
867#ifdef debug
868 G4cerr<<"---OUT---G4QInelastic::PSDoIt: Called for zero Cross-section"<<G4endl;
869#endif
870 //Do Nothing Action insead of the reaction
875 delete output;
876 return G4VDiscreteProcess::PostStepDoIt(track,step);
877 }
878 G4double photonEnergy = CSmanager->GetExchangeEnergy(); // Energy of EqivExchangePart
879#ifdef debug
880 G4cout<<"G4QInel::PStDoIt:kE="<<kinEnergy<<",dir="<<dir<<",phE="<<photonEnergy<<G4endl;
881#endif
882 if( kinEnergy < photonEnergy || photonEnergy < 0.)
883 {
884 //Do Nothing Action insead of the reaction
885 G4cerr<<"--G4QInelastic::PSDoIt: photE="<<photonEnergy<<">leptE="<<kinEnergy<<G4endl;
890 delete output;
891 return G4VDiscreteProcess::PostStepDoIt(track,step);
892 }
893 G4double photonQ2 = CSmanager->GetExchangeQ2(photonEnergy);// Q2(t) of EqivExchangePart
894 G4double W=photonEnergy-photonQ2/dM;// HadronicEnergyFlow (W-energy) for virtual photon
895 if(tM<999.) W-=mPi0+mPi0s/dM; // Pion production threshold for a nucleon target
896 if(W<0.)
897 {
898 //Do Nothing Action insead of the reaction
899#ifdef debug
900 G4cout<<"--G4QInelastic::PostStepDoIt:(lN) negative equivalent energy W="<<W<<G4endl;
901#endif
906 delete output;
907 return G4VDiscreteProcess::PostStepDoIt(track,step);
908 }
909 // Update G4VParticleChange for the scattered muon
911 G4double sigNu=thePhotonData->GetCrossSection(true,photonEnergy,Z,N,22);//Integrated XS
912 G4double sigK =thePhotonData->GetCrossSection(true, W, Z, N, 22); // Real XS
913 G4double rndFraction = CSmanager->GetVirtualFactor(photonEnergy, photonQ2);
914 if(sigNu*G4UniformRand()>sigK*rndFraction)
915 {
916 //NothingToDo Action insead of the reaction
917#ifdef debug
918 G4cout<<"-DoNoth-G4QInelastic::PostStepDoIt: probab. correction - DoNothing"<<G4endl;
919#endif
924 delete output;
925 return G4VDiscreteProcess::PostStepDoIt(track,step);
926 }
927 G4double iniE=kinEnergy+ml; // Initial total energy of the lepton
928 G4double finE=iniE-photonEnergy; // Final total energy of the lepton
929#ifdef pdebug
930 G4cout<<"G4QInelastic::PoStDoIt:E="<<iniE<<",lE="<<finE<<"-"<<ml<<"="<<finE-ml<<G4endl;
931#endif
933 if(finE<=ml) // Secondary lepton (e/mu/tau) at rest disappears
934 {
939 }
941 G4double iniP=std::sqrt(iniE*iniE-ml2); // Initial momentum of the electron
942 G4double finP=std::sqrt(finE*finE-ml2); // Final momentum of the electron
943 G4double cost=(iniE*finE-ml2-photonQ2/2)/iniP/finP; // cos(scat_ang_of_lepton)
944#ifdef pdebug
945 G4cout<<"G4QI::PSDoIt:Q2="<<photonQ2<<",ct="<<cost<<",Pi="<<iniP<<",Pf="<<finP<<G4endl;
946#endif
947 if(cost>1.) cost=1.; // To avoid the accuracy of calculation problem
948 if(cost<-1.) cost=-1.; // To avoid the accuracy of calculation problem
949 //
950 // Scatter the lepton ( @@ make the same thing for real photons)
951 // At this point we have photonEnergy and photonQ2 (with notDefinedPhi)->SelectProjPart
952 G4double absEn = G4QThd(am)*GeV; // @@(b) Mean Energy Absorbed by a Nucleus
953 //G4double absEn = std::pow(am,third)*GeV; // @@(b) Mean Energy Absorbed by a Nucleus
954 if(am>1 && absEn < photonEnergy) // --> the absorption of energy can happen
955 //if(absEn < photonEnergy) // --> the absorption of energy can happen
956 {
957 G4double abtEn = absEn+hdM; // @@(b) MeanEnergyAbsorbed by a nucleus (+M_N)
958 G4double abEn2 = abtEn*abtEn; // Squared absorbed Energy + MN
959 G4double abMo2 = abEn2-hdM2; // Squared absorbed Momentum of compound system
960 G4double phEn2 = photonEnergy*photonEnergy;
961 G4double phMo2 = phEn2+photonQ2; // Squared momentum of primary virtual photon
962 G4double phMo = std::sqrt(phMo2); // Momentum of the primary virtual photon
963 absMom = std::sqrt(abMo2); // Absorbed Momentum
964 if(absMom < phMo) // --> the absorption of momentum can happen
965 {
966 G4double dEn = photonEnergy - absEn; // Leading energy
967 G4double dMo = phMo - absMom; // Leading momentum
968 G4double sF = dEn*dEn - dMo*dMo;// s of leading particle
969#ifdef ppdebug
970 G4cout<<"-PhotoAbsorption-G4QIn::PStDoIt: sF="<<sF<<",phEn="<<photonEnergy<<G4endl;
971#endif
972 if(sF > stmPi) // --> Leading fragmentation is possible
973 {
974 photonEnergy = absEn; // New value of the photon energy
975 photonQ2=abMo2-absEn*absEn; // New value of the photon Q2
976 absEn = dEn; // Put energy of leading particle to absEn (!)
977 }
978 else absMom=0.; // Flag that nothing has happened
979 }
980 else absMom=0.; // Flag that nothing has happened
981 }
982 // ------------- End of ProjPart selection
983 //
984 // Scattering in respect to the derection of the incident muon is made impicitly:
985 G4ThreeVector ort=dir.orthogonal(); // Not normed orthogonal vector (!) (to dir)
986 G4ThreeVector ortx = ort.unit(); // First unit vector orthogonal to the direction
987 G4ThreeVector orty = dir.cross(ortx);// Second unit vector orthoganal to the direction
988 G4double sint=std::sqrt(1.-cost*cost); // Perpendicular component
989 G4double phi=twopi*G4UniformRand(); // phi of scattered electron
990 G4double sinx=sint*std::sin(phi); // x perpendicular component
991 G4double siny=sint*std::cos(phi); // y perpendicular component
992 G4ThreeVector findir=cost*dir+sinx*ortx+siny*orty;
993 aParticleChange.ProposeMomentumDirection(findir); // new direction for the lepton
994#ifdef pdebug
995 G4cout<<"G4QInelastic::PostStepDoIt: E="<<aParticleChange.GetEnergy()<<"="<<finE<<"-"
996 <<ml<<", d="<<*aParticleChange.GetMomentumDirection()<<","<<findir<<G4endl;
997#endif
998 G4ThreeVector photon3M=iniP*dir-finP*findir;// 3D total momentum of photon
999 if(absMom) // Photon must be reduced & LeadingSyst fragmented
1000 {
1001 G4double ptm=photon3M.mag(); // 3M of the virtual photon
1002#ifdef ppdebug
1003 G4cout<<"-Absorption-G4QInelastic::PostStepDoIt: ph3M="<<photon3M<<", eIn3M="
1004 <<iniP*dir<<", eFin3M="<<finP*findir<<", abs3M="<<absMom<<"<ptm="<<ptm<<G4endl;
1005#endif
1006 G4ThreeVector lead3M=photon3M*(ptm-absMom)/ptm; // Keep the direction for leading Q
1007 photon3M-=lead3M; // Reduced photon Momentum (photEn already = absEn)
1008 proj4M=G4LorentzVector(lead3M,absEn); // 4-momentum of leading System
1009#ifdef ppdebug
1010 G4cout<<"-->G4QI::PoStDoIt: new sF="<<proj4M.m2()<<", lead4M="<<proj4M<<G4endl;
1011#endif
1012 lead4M=proj4M; // Remember 4-mom for the total 4-momentum
1013 G4Quasmon* pan= new G4Quasmon(G4QContent(1,1,0,1,1,0),proj4M);// ---> DELETED -->---+
1014 try // |
1015 { // |
1016 if(leadhs) delete leadhs; // |
1017 G4QNucleus vac(90000000); // |
1018 leadhs=pan->Fragment(vac,1); // DELETED after it is copied to output vector |
1019 } // |
1020 catch (G4QException& error) // |
1021 { // |
1022 G4cerr<<"***G4QInelastic::PostStepDoIt: G4Quasmon Exception is catched"<<G4endl;//|
1023 // G4Exception("G4QInelastic::PostStepDoIt:","72",FatalException,"QuasmonCrash"); //|
1024 G4Exception("G4QInelastic::PostStepDoIt()","HAD_CHPS_0072",
1025 FatalException, "QuasmonCrash");
1026 } // |
1027 delete pan; // Delete the Nuclear Environment <----<---+
1028#ifdef ppdebug
1029 G4cout<<"G4QInel::PStDoIt: l4M="<<proj4M<<proj4M.m2()<<", N="<<leadhs->size()<<",pt="
1030 <<ptm<<",pa="<<absMom<<",El="<<absEn<<",Pl="<<ptm-absMom<<G4endl;
1031#endif
1032 }
1033 else
1034 {
1035 G4int qNH=0;
1036 if(leadhs) qNH=leadhs->size();
1037 if(qNH) for(G4int iq=0; iq<qNH; iq++) delete (*leadhs)[iq];
1038 if(leadhs) delete leadhs;
1039 leadhs=0;
1040 }
1041 projPDG=22;
1042 proj4M=G4LorentzVector(photon3M,photonEnergy);
1043#ifdef debug
1044 G4cout<<"G4QInelastic::PostStDoIt: St="<<aParticleChange.GetTrackStatus()<<", g4m="
1045 <<proj4M<<", lE="<<finE<<", lP="<<finP*findir<<", d="<<findir.mag2()<<G4endl;
1046#endif
1047
1048 //
1049 // neutrinoNuclear interactions (nu_e, nu_mu only)
1050 //
1051 }
1052 else if (aProjPDG == 12 || aProjPDG == 14)
1053 {
1054 kinEnergy= projHadron->GetKineticEnergy()/MeV; // Total energy of the neutrino
1055 G4double dKinE=kinEnergy+kinEnergy; // doubled energy for s calculation
1056#ifdef debug
1057 G4cout<<"G4QInelastic::PostStDoIt: 2*nuEnergy="<<dKinE<<"(MeV), PDG="<<projPDG<<G4endl;
1058#endif
1059 dir = projHadron->GetMomentumDirection(); // unit vector
1060 G4double ml = mu;
1061 G4double ml2 = mu2;
1062 //G4double mlN = muN;
1063 G4double mlN2= muN2;
1064 G4double fmlN= fmuN;
1065 G4double mlsN= musN;
1066 //G4double mlP = muP;
1067 G4double mlP2= muP2;
1068 G4double fmlP= fmuP;
1069 G4double mlsP= musP;
1070 G4double mldM= mudM;
1071 //G4double mlD = muD;
1072 G4double mlD2= muD2;
1073 if(aProjPDG==12)
1074 {
1075 ml = me;
1076 ml2 = me2;
1077 //mlN = meN;
1078 mlN2= meN2;
1079 fmlN= fmeN;
1080 mlsN= mesN;
1081 //mlP = meP;
1082 mlP2= meP2;
1083 fmlP= fmeP;
1084 mlsP= mesP;
1085 mldM= medM;
1086 //mlD = meD;
1087 mlD2= meD2;
1088 }
1091 proj4M=G4LorentzVector(dir*kinEnergy,kinEnergy); // temporary
1092 G4bool nuanu=true;
1093 scatPDG=13; // Prototype = secondary scattered mu-
1094 if(projPDG==-14)
1095 {
1096 nuanu=false; // Anti-neutrino
1097 CSmanager=G4QANuMuNuclearCrossSection::GetPointer(); // (anu,mu+) CC @@ open
1098 CSmanager=G4QANuANuNuclearCrossSection::GetPointer(); // (anu,anu) NC @@ open
1099 scatPDG=-13; // secondary scattered mu+
1100 }
1101 else if(projPDG==12)
1102 {
1103 CSmanager=G4QNuENuclearCrossSection::GetPointer(); // @@ open (only CC is changed)
1104 scatPDG=11; // secondary scattered e-
1105 }
1106 else if(projPDG==-12)
1107 {
1108 nuanu=false; // anti-neutrino
1109 CSmanager=G4QANuENuclearCrossSection::GetPointer(); // (anu,e+) CC @@ open
1110 CSmanager=G4QANuANuNuclearCrossSection::GetPointer(); // (anu,anu) NC @@ open
1111 scatPDG=-11; // secondary scattered e+
1112 }
1113 // @@ Probably this is not necessary any more
1114 if(!projPDG) G4cout<<"-Warning-G4QInelastic::PostStepDoIt:(3)projectile PDG=0"<<G4endl;
1115 G4double xSec1=CSmanager->GetCrossSection(false,Momentum,Z,N,projPDG); //Recalculate XS
1116 G4double xSec2=CSmanager2->GetCrossSection(false,Momentum,Z,N,projPDG);//Recalculate XS
1117 G4double xSec=xSec1+xSec2;
1118 // @@ check a possibility to separate p, n, or alpha (!)
1119 if(xSec <= 0.) // The cross-section = 0 -> Do Nothing
1120 {
1121 G4cerr<<"G4QInelastic::PSDoIt:nuE="<<kinEnergy<<",X1="<<xSec1<<",X2="<<xSec2<<G4endl;
1122 //Do Nothing Action insead of the reaction
1123 aParticleChange.ProposeEnergy(kinEnergy);
1127 delete output;
1128 return G4VDiscreteProcess::PostStepDoIt(track,step);
1129 }
1130 G4bool secnu=false;
1131 if(xSec*G4UniformRand()>xSec1) // recover neutrino/antineutrino
1132 {
1133 if(scatPDG>0) scatPDG++;
1134 else scatPDG--;
1135 secnu=true;
1136 }
1137 scat=true; // event with changed scattered projectile
1138 G4double totCS1 = CSmanager->GetLastTOTCS(); // the last total cross section1(isotope?)
1139 G4double totCS2 = CSmanager2->GetLastTOTCS();// the last total cross section2(isotope?)
1140 G4double totCS = totCS1+totCS2; // the last total cross section (isotope?)
1141 if(std::fabs(xSec-totCS*millibarn)/xSec>.0001)
1142 G4cout<<"-Warning-G4QInelastic::PostStepDoIt: xS="<<xSec<<"# CS="<<totCS<<G4endl;
1143 G4double qelCS1 = CSmanager->GetLastQELCS(); // the last quasi-elastic cross section1
1144 G4double qelCS2 = CSmanager2->GetLastQELCS();// the last quasi-elastic cross section2
1145 G4double qelCS = qelCS1+qelCS2; // the last quasi-elastic cross section
1146 if(totCS - qelCS < 0.) // only at low energies
1147 {
1148 totCS = qelCS;
1149 totCS1 = qelCS1;
1150 totCS2 = qelCS2;
1151 }
1152 // make different definitions for neutrino and antineutrino
1153 G4double mIN=mProt; // Just a prototype (for anu, Z=1, N=0)
1154 G4double mOT=mNeut;
1155 G4double OT=mlN2;
1156 //G4double mOT2=mNeut2; // Other formula: sd=s-mlsOT -Not used?-
1157 G4double mlOT=fmlN;
1158 G4double mlsOT=mlsN;
1159 if(secnu)
1160 {
1161 if(am*G4UniformRand()>Z) // Neutron target
1162 {
1163 targPDG-=1; // subtract neutron
1164 projPDG=2112; // neutron is going out
1165 mIN =mNeut;
1166 OT =mNeut2;
1167 //mOT2=mNeut2;
1168 mlOT=0.;
1169 mlsOT=mNeut2;
1170 }
1171 else
1172 {
1173 targPDG-=1000; // subtract neutron
1174 projPDG=2212; // neutron is going out
1175 mOT =mProt;
1176 OT =mProt2;
1177 //mOT2 =mProt2;
1178 mlOT =0.;
1179 mlsOT=mProt2;
1180 }
1181 ml=0.;
1182 ml2=0.;
1183 mldM=0.;
1184 mlD2=mPPi2;
1185 G4QPDGCode temporary_targQPDG(targPDG);
1186 targQPDG = temporary_targQPDG;
1187 G4double rM=targQPDG.GetMass();
1188 mIN=tM-rM; // bounded in-mass of the neutron
1189 tM=rM;
1190 }
1191 else if(nuanu)
1192 {
1193 targPDG-=1; // Neutrino -> subtract neutron
1194 G4QPDGCode temporary_targQPDG(targPDG);
1195 targQPDG = temporary_targQPDG;
1196 G4double rM=targQPDG.GetMass();
1197 mIN=tM-rM; // bounded in-mass of the neutron
1198 tM=rM;
1199 mOT=mProt;
1200 OT=mlP2;
1201 //mOT2=mProt2;
1202 mlOT=fmlP;
1203 mlsOT=mlsP;
1204 projPDG=2212; // proton is going out
1205 }
1206 else
1207 {
1208 if(Z>1||N>0) // Calculate the splitted mass
1209 {
1210 targPDG-=1000; // Anti-Neutrino -> subtract proton
1211 G4QPDGCode temporary_targQPDG(targPDG);
1212 targQPDG = temporary_targQPDG;
1213 G4double rM=targQPDG.GetMass();
1214 mIN=tM-rM; // bounded in-mass of the proton
1215 tM=rM;
1216 }
1217 else
1218 {
1219 targPDG=0;
1220 mIN=tM;
1221 tM=0.;
1222 }
1223 projPDG=2112; // neutron is going out
1224 }
1225 G4double s_value=mIN*(mIN+dKinE); // s_value=(M_cm)^2=m2+2mE (m=targetMass,E=E_nu)
1226#ifdef debug
1227 G4cout<<"G4QInelastic::PostStDoIt: s="<<s_value<<" >? OT="<<OT<<", mlD2="<<mlD2<<G4endl;
1228#endif
1229 if(s_value<=OT) // *** Do nothing solution ***
1230 {
1231 //Do NothingToDo Action insead of the reaction (@@ Can we make it common?)
1232 G4cout<<"G4QInelastic::PostStepDoIt: tooSmallFinalMassOfCompound: DoNothing"<<G4endl;
1233 aParticleChange.ProposeEnergy(kinEnergy);
1237 delete output;
1238 return G4VDiscreteProcess::PostStepDoIt(track,step);
1239 }
1240#ifdef debug
1241 G4cout<<"G4QInelastic::PostStDoIt: Stop and kill the projectile neutrino"<<G4endl;
1242#endif
1244 aParticleChange.ProposeTrackStatus(fStopAndKill); // the initial neutrino is killed
1245 // There is no way back from here !
1246 if ( ((secnu || !nuanu || N) && totCS*G4UniformRand() < qelCS) || s_value < mlD2 )
1247 { // Quasi-Elastic interaction
1248 G4double Q2=0.; // Simulate transferred momentum, in MeV^2
1249 if(secnu) Q2=CSmanager2->GetQEL_ExchangeQ2();
1250 else Q2=CSmanager->GetQEL_ExchangeQ2();
1251#ifdef debug
1252 G4cout<<"G4QInelastic::PostStDoIt:QuasiEl(nu="<<secnu<<"),s="<<s_value<<",Q2="<<Q2<<G4endl;
1253#endif
1254 //G4double ds=s_value+s_value; // doubled s_value
1255 G4double sqs=std::sqrt(s_value); // M_cm
1256 G4double dsqs=sqs+sqs; // 2*M_cm
1257 G4double p_init=(s_value-mIN*mIN)/dsqs; // initial momentum in CMS (checked MK)
1258 G4double dpi=p_init+p_init; // doubled initial momentum in CMS
1259 G4double sd=s_value-mlsOT; // s_value-ml2-mOT2 (mlsOT=m^2_neut+m^2_lept)
1260 G4double qo2=(sd*sd-mlOT)/dsqs; // squared momentum of secondaries in CMS
1261 G4double qo=std::sqrt(qo2); // momentum of secondaries in CMS
1262 G4double cost=(dpi*std::sqrt(qo2+ml2)-Q2-ml2)/dpi/qo; // cos(theta) in CMS (chck MK)
1263 G4LorentzVector t4M(0.,0.,0.,mIN); // 4mom of the effective target
1264 G4LorentzVector c4M=t4M+proj4M; // 4mom of the compound system
1265 t4M.setT(mOT); // now it is 4mom of the outgoing nucleon
1266 scat4M=G4LorentzVector(0.,0.,0.,ml); // 4mom of the scattered muon
1267 if(!G4QHadron(c4M).RelDecayIn2(scat4M, t4M, proj4M, cost, cost))
1268 {
1269 G4cerr<<"G4QIn::PStD:c4M="<<c4M<<sqs<<",mM="<<ml<<",tM="<<mOT<<",c="<<cost<<G4endl;
1270 // throw G4QException("G4QInelastic::HadronizeQuasm: Can't dec QE nu,lept Compound");
1271 G4Exception("G4QInelastic::PostStepDoIt()", "HAD_CHPS_0000",
1272 FatalException, "Hadronize quasmon: Can't dec QE nu,lept Compound");
1273 }
1274 proj4M=t4M; // 4mom of the new projectile nucleon
1275 }
1276 else // ***** Non Quasi Elastic interaction
1277 {
1278 // Recover the target PDG Code if the quasi-elastic scattering did not happened
1279 if ( (secnu && projPDG == 2212) || (!secnu && projPDG == 2112) ) targPDG+=1;
1280 else if ( (secnu && projPDG == 2112) || (!secnu && projPDG == 2212) ) targPDG+=1000;
1281 G4double Q2=0; // Simulate transferred momentum, in MeV^2
1282 if(secnu) Q2=CSmanager->GetNQE_ExchangeQ2();
1283 else Q2=CSmanager2->GetNQE_ExchangeQ2();
1284#ifdef debug
1285 G4cout<<"G4QInel::PStDoIt: MultiPeriferal s="<<s_value<<",Q2="<<Q2<<",T="<<targPDG<<G4endl;
1286#endif
1287 if(secnu) projPDG=CSmanager2->GetExchangePDGCode();// PDG Code of the effective gamma
1288 else projPDG=CSmanager->GetExchangePDGCode(); // PDG Code of the effective pion
1289 //@@ Temporary made only for direct interaction and for N=3 (good for small Q2)
1290 //@@ inFuture use N=GetNPartons and directFraction=GetDirectPart, @@ W2...
1292 G4double r1=0.5; // (1-x)
1293 if(r<0.5) r1=std::sqrt(r+r)*(.5+.1579*(r-.5));
1294 else if(r>0.5) r1=1.-std::sqrt(2.-r-r)*(.5+.1579*(.5-r));
1295 G4double xn=1.-mldM/Momentum; // Normalization of (1-x) [x>mldM/Mom]
1296 G4double x1=xn*r1; // (1-x)
1297 G4double x=1.-x1; // x=2k/M
1298 //G4double W2=(hdM2+Q2/x)*x1; // W2 candidate
1299 G4double mx=hdM*x; // Part of the target to interact with
1300 G4double we=Q2/(mx+mx); // transfered energy
1301 if(we>=kinEnergy-ml-.001) we=kinEnergy-ml-.0001; // safety to avoid nan=sqrt(neg)
1302 G4double pot=kinEnergy-we; // energy of the secondary lepton
1303 G4double mlQ2=ml2+Q2;
1304 G4double cost=(pot-mlQ2/dKinE)/std::sqrt(pot*pot-ml2); // LS cos(theta)
1305 if(std::fabs(cost)>1)
1306 {
1307#ifdef debug
1308 G4cout<<"*G4QInelastic::PostStDoIt: cost="<<cost<<", Q2="<<Q2<<", nu="<<we<<", mx="
1309 <<mx<<", pot="<<pot<<", 2KE="<<dKinE<<G4endl;
1310#endif
1311 if(cost>1.) cost=1.;
1312 else cost=-1.;
1313 pot=mlQ2/dKinE+dKinE*ml2/mlQ2; // extreme output momentum
1314 }
1315 G4double lEn=std::sqrt(pot*pot+ml2); // Lepton energy
1316 G4double lPl=pot*cost; // Lepton longitudinal momentum
1317 G4double lPt=pot*std::sqrt(1.-cost*cost); // Lepton transverse momentum
1318 std::pair<G4double,G4double> d2d=Random2DDirection(); // Randomize phi
1319 G4double lPx=lPt*d2d.first;
1320 G4double lPy=lPt*d2d.second;
1321 G4ThreeVector vdir=proj4M.vect(); // 3D momentum of the projectile
1322 G4ThreeVector vz= vdir.unit(); // Ort in the direction of the projectile
1323 G4ThreeVector vv= vz.orthogonal(); // Not normed orthogonal vector (!)
1324 G4ThreeVector vx= vv.unit(); // First ort orthogonal to the direction
1325 G4ThreeVector vy= vz.cross(vx); // Second ort orthoganal to the direction
1326 G4ThreeVector lP= lPl*vz+lPx*vx+lPy*vy; // 3D momentum of the scattered lepton
1327 scat4M=G4LorentzVector(lP,lEn); // 4mom of the scattered lepton
1328 proj4M-=scat4M; // 4mom of the W/Z (effective pion/gamma)
1329#ifdef debug
1330 G4cout<<"G4QInelastic::PostStDoIt: proj4M="<<proj4M<<", ml="<<ml<<G4endl;
1331#endif
1332 // Check that the en/mom transfer is possible, if not -> elastic
1333 G4int fintPDG=targPDG; // Prototype for the compound nucleus
1334 if(!secnu)
1335 {
1336 if(projPDG<0) fintPDG-= 999;
1337 else fintPDG+= 999;
1338 }
1339 G4double fM=G4QPDGCode(fintPDG).GetMass();// compound nucleus Mass (MeV)
1340 G4double fM2=fM*fM;
1341 G4LorentzVector tg4M=G4LorentzVector(0.,0.,0.,tgM);
1342 G4LorentzVector c4M=tg4M+proj4M;
1343#ifdef debug
1344 G4cout<<"G4QInelastic::PSDI:fM2="<<fM2<<"<? mc4M="<<c4M.m2()<<",dM="<<fM-tgM<<G4endl;
1345#endif
1346 if(fM2>=c4M.m2()) // Elastic scattering should be done
1347 {
1348 G4LorentzVector tot4M=tg4M+proj4M+scat4M; // recover the total 4-momentum
1349 s_value=tot4M.m2();
1350 G4double fs=s_value-fM2-ml2;
1351 G4double fMl=fM2*ml2;
1352 G4double hQ2max=(fs*fs/2-fMl-fMl)/s_value; // Maximum possible Q2/2
1353 cost=1.-Q2/hQ2max; // cos(theta) in CMS (use MultProd Q2)
1354#ifdef debug
1355 G4cout<<"G4QI::PSDI:ct="<<cost<<",Q2="<<Q2<<",hQ2="<<hQ2max<<",4M="<<tot4M<<G4endl;
1356#endif
1357 G4double acost=std::fabs(cost);
1358 if(acost>1.)
1359 {
1360 if(acost>1.001) G4cout<<"-Warning-G4QInelastic::PostStDoIt: cost="<<cost<<G4endl;
1361 if (cost> 1.) cost= 1.;
1362 else if(cost<-1.) cost=-1.;
1363 }
1364 G4LorentzVector reco4M=G4LorentzVector(0.,0.,0.,fM); // 4mom of the recoilNucleus
1365 scat4M=G4LorentzVector(0.,0.,0.,ml); // 4mom of the scatteredLepton
1366 G4LorentzVector dir4M=tot4M-G4LorentzVector(0.,0.,0.,(tot4M.e()-ml)*.01);
1367 if(!G4QHadron(tot4M).RelDecayIn2(scat4M, reco4M, dir4M, cost, cost))
1368 {
1369 G4cerr<<"G4QI::PSDI:t4M="<<tot4M<<",lM="<<ml<<",rM="<<fM<<",cost="<<cost<<G4endl;
1370 //G4Exception("G4QInelastic::PostStepDoIt:","027",FatalException,"ElasticDecay");
1371 }
1372#ifdef debug
1373 G4cout<<"G4QIn::PStDoI:l4M="<<scat4M<<"+r4M="<<reco4M<<"="<<scat4M+reco4M<<G4endl;
1374#endif
1375 // ----------------------------------------------------
1376 G4ParticleDefinition* theDefinition=0; // Prototype of a particle for E-Secondaries
1377 // Fill scattered lepton
1378 if (scatPDG==-11) theDefinition = G4Positron::Positron();
1379 else if(scatPDG== 11) theDefinition = G4Electron::Electron();
1380 else if(scatPDG== 13) theDefinition = G4MuonMinus::MuonMinus();
1381 else if(scatPDG==-13) theDefinition = G4MuonPlus::MuonPlus();
1382 //else if(scatPDG== 15) theDefinition = G4TauMinus::TauMinus();
1383 //else if(scatPDG==-15) theDefinition = G4TauPlus::TauPlus();
1384 if (scatPDG==-12) theDefinition = G4AntiNeutrinoE::AntiNeutrinoE();
1385 else if(scatPDG== 12) theDefinition = G4NeutrinoE::NeutrinoE();
1386 else if(scatPDG== 14) theDefinition = G4NeutrinoMu::NeutrinoMu();
1387 else if(scatPDG==-14) theDefinition = G4AntiNeutrinoMu::AntiNeutrinoMu();
1388 //else if(scatPDG== 16) theDefinition = G4NeutrinoTau::NeutrinoTau();
1389 //else if(scatPDG==-16) theDefinition = G4AntiNeutrinoTau::AntiNeutrinoTau();
1390 else G4cout<<"-Warning-G4QInelastic::PostStDoIt: UnknownLepton="<<scatPDG<<G4endl;
1391 G4DynamicParticle* theScL = new G4DynamicParticle(theDefinition,scat4M);
1392 G4Track* scatLep = new G4Track(theScL, localtime, position ); // scattered
1393 scatLep->SetWeight(weight); // weighted
1394 scatLep->SetTouchableHandle(trTouchable); // residual
1395 aParticleChange.AddSecondary(scatLep); // lepton
1396 // Fill residual nucleus
1397 if (fintPDG==90000001) theDefinition = G4Neutron::Neutron(); // neutron
1398 else if(fintPDG==90001000) theDefinition = G4Proton::Proton(); // proton
1399 else // ion
1400 {
1401 G4int fm=static_cast<G4int>(fintPDG/1000000); // Strange part
1402 G4int ZN=fintPDG-1000000*fm;
1403 G4int rZ=static_cast<G4int>(ZN/1000);
1404 G4int rA=ZN-999*rZ;
1405 theDefinition = G4ParticleTable::GetParticleTable()->FindIon(rZ,rA,0,rZ);
1406 }
1407 G4DynamicParticle* theReN = new G4DynamicParticle(theDefinition,reco4M);
1408 G4Track* scatReN = new G4Track(theReN, localtime, position ); // scattered
1409 scatReN->SetWeight(weight); // weighted
1410 scatReN->SetTouchableHandle(trTouchable); // residual
1411 aParticleChange.AddSecondary(scatReN); // nucleus
1412 delete output;
1413 return G4VDiscreteProcess::PostStepDoIt(track, step);
1414 }
1415 } // End of non-quasi-elastic interaction
1416 //
1417 // quasi-elastic (& pickup process) for p+A(Z,N)
1418 //
1419 }
1420 //else if ((projPDG == 2212 || projPDG == 2112) && Z > 0 && N > 0) // Never (in Fragm!)
1421 else if(2>3) // Possibility is closed as quasi-free scattering is made in fragmentation
1422 {
1423 if(momentum<500. && projPDG == 2112) // @@ It's reasonable to add proton capture too !
1424 {
1425 G4LorentzVector tot4M=G4LorentzVector(0.,0.,0.,tgM)+proj4M;
1426 G4double totM2=tot4M.m2();
1427 G4int tZ=Z;
1428 G4int tN=N;
1429 if(projPDG == 2212) tZ++;
1430 else tN++; // @@ Now a neutron is the only alternative
1431 if(momentum<100.) // Try the production threshold (@@ Why 5 MeV?)
1432 {
1433 G4QPDGCode FakeP(2112);
1434 //G4int m1p=tZ-1;
1435 G4int m2n=tN-2;
1436 // @@ For the secondary proton the Coulomb barrier should be taken into account
1437 //G4double mRP= FakeP.GetNuclMass(m1p,tN,0); // Residual to the secondary proton
1438 G4double mR2N= FakeP.GetNuclMass(tZ,m2n,0); // Residual to two secondary neutrons
1439 //G4double mRAl= FakeP.GetNuclMass(tZ-2,m2n,0); // Residual to the secondary alpha
1440 //G4double mR2N= FakeP.GetNuclMass(m1p,tN-1,0); // Residual to the p+n secondaries
1441 G4double minM=mR2N+mNeut+mNeut;
1442 // Compare with other possibilities (sciped for acceleration)
1443 if(totM2 < minM*minM) // DoNothing (under reasonable threshold)
1444 {
1445 aParticleChange.ProposeEnergy(kinEnergy);
1449 return G4VDiscreteProcess::PostStepDoIt(track,step);
1450 }
1451 }
1452 }
1453 // Now the quasi-free and PickUp processes should be done:
1455 std::pair<G4double,G4double> fief=qfMan->GetRatios(momentum, projPDG, Z, N);
1456 G4double qepart=fief.first*fief.second; // @@ charge exchange is not included @@
1457 // Keep QE part for the quasi-free nucleons
1458 const G4int lCl=3; // The last clProb[lCl]==1. by definition, MUST be increasing
1459 G4double clProb[lCl]={.65,.85,.95};// N/P,D,t/He3,He4, integroProbab for .65,.2,.1,.05
1460 if(qepart>0.45) qepart=.45; // Quasielastic part is too large - shrink
1461 //else qepart/=clProb[0]; // Add corresponding number of 2N, 3N, & 4N clusters
1462 qepart=qepart/clProb[0]-qepart;// Add QE for 2N, 3N, & 4N clusters (N is made in G4QF)
1463 G4double pickup=1.-qepart; // Estimate the rest of the cross-section
1464 G4double thresh=100.;
1465 //if(momentum >thresh) pickup*=50./momentum/std::pow(G4double(Z+N),third);// 50 is Par
1466 if(momentum > thresh) pickup*=50./momentum/G4QThd(Z+N);// 50 is Par
1467 // pickup = 0.; // To exclude the pickup process
1468 if (N) pickup+=qepart;
1469 else pickup =qepart;
1470 G4double rnd=G4UniformRand();
1471#ifdef ldebug
1472 G4cout<<"-->G4QInelastic::PSD:QE[p("<<proj4M<<")+(Z="<<Z<<",N="<<N<<")]="<<qepart
1473 <<", pickup="<<pickup<<G4endl;
1474#endif
1475 if(rnd<pickup) // Make a quasi free scattering (out:A-1,h,N) @@ KinLim,CoulBar,PauliBl
1476 {
1477 G4double dmom=91.; // Fermi momentum (proto default for a deuteron)
1478 G4double fmm=287.; // @@ Can be A-dependent
1479 if(Z>1||N>1) dmom=fmm*std::pow(-std::log(G4UniformRand()),third);
1480 // Values to be redefined for quasi-elastic
1481 G4LorentzVector r4M(0.,0.,0.,0.); // Prototype of 4mom of the residual nucleus
1482 G4LorentzVector n4M(0.,0.,0.,0.); // Prototype of 4mom of the quasi-cluster
1483 G4int nPDG=90000001; // Prototype for quasiCluster mass calculation
1484 G4int restPDG=targPDG; // Prototype should be reduced by quasiCluster
1485 G4int rA=Z+N-1; // Prototype for the residualNucl definition
1486 G4int rZ=Z; // residZ: OK for the quasi-free neutron
1487 G4int nA=1; // Prototype for the quasi-cluster definition
1488 G4int nZ=0; // nA=1,nZ=0: OK for the quasi-free neutron
1489 G4double qM=mNeut; // Free mass of the quasi-free cluster
1490 G4int A = Z + N; // Baryon number of the nucleus
1491 if(rnd<qepart)
1492 {
1493 // ===> First decay a nucleus in a nucleon and a residual (A-1) nucleus
1494 // Calculate clusterProbabilities (n,p,d,t,he3,he4 now only, can use UpdateClusters)
1495 G4double base=1.; // Base for randomization (can be reduced by totZ & totN)
1496 G4int max=lCl; // Number of boundaries (can be reduced by totZ & totN)
1497 // Take into account that at least one nucleon must be left !
1498 if(Z<2 || N<2 || A < 6) base = clProb[--max]; // Alpha cluster is impossible
1499 if((Z > 1 && N < 2) || (Z < 2 && N > 1)) base=(clProb[max]+clProb[max-1])/2;// t/He3
1500 if ( (Z < 2 && N < 2) || A < 5) base=clProb[--max];// He3&t clusters are impossible
1501 if(A<3) base=clProb[--max]; // Deuteron cluster is impossible
1502 //G4int cln=0; // Cluster#0 (Default for the selectedNucleon)
1503 G4int cln=1; // Cluster#1 (Default for the selectedDeutron)
1504 //if(max) // Not only nucleons are possible
1505 if(max>1) // Not only deuterons are possible
1506 {
1507 base-=clProb[0]; // Exclude scattering on QF Nucleon
1508 G4double ran=+clProb[0]+base*G4UniformRand(); // Base can be reduced
1509 G4int ic=1; // Start from the smallest cluster boundary
1510 if(max>1) while(ic<max) if(ran>clProb[ic++]) cln=ic;
1511 }
1512 G4ParticleDefinition* theDefinition=0;// Prototype for qfNucleon
1513 G4bool cp1 = cln+2==A; // A=ClusterBN+1 condition
1514 if(!cln || cp1) // Split in nucleon + (A-1) with Fermi momentum
1515 {
1516 G4int nln=0;
1517 if(cln==2) nln=1; // @@ only for cp1: t/He3 choice from A=4
1518 // mass(A)=tM. Calculate masses of A-1 (rM) and mN (mNeut or mProt bounded mass)
1519 if ( ((!cln || cln == 2) && G4UniformRand()*(A-cln) > (N-nln)) ||
1520 ((cln == 3 || cln == 1) && Z > N) )
1521 {
1522 nPDG=90001000; // Update quasi-free nucleon PDGCode to P
1523 nZ=1; // Change charge of the quasiFree nucleon
1524 qM=mProt; // Update quasi-free nucleon mass
1525 rZ--; // Reduce the residual Z
1526 restPDG-=1000; // Reduce the residual PDGCode
1527 }
1528 else restPDG--;
1529 G4LorentzVector t4M(0.,0.,0.,tM); // 4m of the target nucleus to be decayed
1530 G4double rM=G4QPDGCode(restPDG).GetMass();// Mass of the residual nucleus
1531 r4M=G4LorentzVector(0.,0.,0.,rM); // 4mom of the residual nucleus
1532 G4double rM2=rM*rM;
1533 G4double nM=std::sqrt(rM2+tM*tM-(tM+tM)*std::sqrt(rM2+dmom*dmom));// M of q-nucleon
1534 n4M=G4LorentzVector(0.,0.,0.,nM); // 4mom of the quasi-nucleon
1535#ifdef qedebug
1536 G4cout<<"G4QInel::PStDoIt:QE,p="<<dmom<<",tM="<<tM<<",R="<<rM<<",N="<<nM<<G4endl;
1537#endif
1538 if(!G4QHadron(t4M).DecayIn2(r4M, n4M))
1539 {
1540 //G4cerr<<"G4QInel::PostStDoIt:M="<<tM<<"<r="<<rM<<"+n="<<nM<<"="<<rM+nM<<G4endl;
1541 //G4Exception("G4QInelastic::PostStepDoIt()", "HAD_CHPS_0002",
1542 // FatalException,"Hadronize quasmon: Can't Dec totNuc->QENuc+ResNuc");
1543 G4cerr<<"-W-G4QInel::PoStDoI:M="<<tM<<"<rM="<<rM<<"+nM="<<nM<<"="<<rM+nM<<G4endl;
1544 aParticleChange.ProposeEnergy(kinEnergy);
1548 return G4VDiscreteProcess::PostStepDoIt(track,step);
1549 }
1550#ifdef qedebug
1551 G4cout<<"G4QIn::PStDoIt:QE-N, RA="<<r4M.rho()<<r4M<<",QN="<<n4M.rho()<<n4M<<G4endl;
1552#endif
1553 if(cp1 && cln) // Quasi-cluster case: swap the output
1554 {
1555 qM=rM; // Scattering will be made on a cluster
1556 nln=nPDG;
1557 nPDG=restPDG;
1558 restPDG=nln;
1559 t4M=n4M;
1560 n4M=r4M;
1561 r4M=t4M;
1562 nln=nZ;
1563 nZ=rZ;
1564 rZ=nln;
1565 nln=nA;
1566 nA=rA;
1567 rA=nln;
1568 }
1569 }
1570 else // Split the cluster (with or w/o "Fermi motion" and "Fermi decay")
1571 {
1572 if(cln==1)
1573 {
1574 nPDG=90001001; // Deuteron
1575 qM=mDeut;
1576 nA=2;
1577 nZ=1;
1578 restPDG-=1001;
1579 // Recalculate dmom
1580 G4ThreeVector sumv=G4ThreeVector(0.,0.,dmom) +
1581 fmm*std::pow(-std::log(G4UniformRand()),third)*G4RandomDirection();
1582 dmom=sumv.mag();
1583 }
1584 else if(cln==2)
1585 {
1586 nA=3;
1587 if(G4UniformRand()*(A-2)>(N-1)) // He3
1588 {
1589 nPDG=90002001;
1590 qM=mHel3;
1591 nZ=2;
1592 restPDG-=2001;
1593 }
1594 else // tritium
1595 {
1596 nPDG=90001002;
1597 qM=mTrit;
1598 nZ=1;
1599 restPDG-=1002;
1600 }
1601 // Recalculate dmom
1602 G4ThreeVector sumv=G4ThreeVector(0.,0.,dmom) +
1603 fmm*std::pow(-std::log(G4UniformRand()),third)*G4RandomDirection()+
1604 fmm*std::pow(-std::log(G4UniformRand()),third)*G4RandomDirection();
1605 dmom=sumv.mag();
1606 }
1607 else
1608 {
1609 nPDG=90002002; // Alpha
1610 qM=mAlph;
1611 nA=4;
1612 nZ=2;
1613 restPDG-=2002;
1614 G4ThreeVector sumv=G4ThreeVector(0.,0.,dmom) +
1615 fmm*std::pow(-std::log(G4UniformRand()),third)*G4RandomDirection()+
1616 fmm*std::pow(-std::log(G4UniformRand()),third)*G4RandomDirection()+
1617 fmm*std::pow(-std::log(G4UniformRand()),third)*G4RandomDirection();
1618 dmom=sumv.mag();
1619 }
1620 rA=A-nA;
1621 rZ=Z-nZ;
1622 // This is a simple case of cluster at rest
1623 //G4double rM=G4QPDGCode(restPDG).GetMass();// Mass of the residual nucleus
1624 //r4M=G4LorentzVector(0.,0.,0.,rM); // 4mom of the residual nucleus
1625 //n4M=G4LorentzVector(0.,0.,0.,tM-rM); // 4mom of the quasi-free cluster
1626 // --- End of the "simple case of cluster at rest"
1627 // Make a fake quasi-Fermi distribution for clusters (clusters are not at rest)
1628 G4LorentzVector t4M(0.,0.,0.,tM); // 4m of the target nucleus to be decayed
1629 G4double rM=G4QPDGCode(restPDG).GetMass();// Mass of the residual nucleus
1630 r4M=G4LorentzVector(0.,0.,0.,rM); // 4mom of the residual nucleus
1631 G4double rM2=rM*rM;
1632 G4double nM=std::sqrt(rM2+tM*tM-(tM+tM)*std::sqrt(rM2+dmom*dmom));// M of q-cluster
1633 n4M=G4LorentzVector(0.,0.,0.,nM); // 4mom of the quasi-nucleon
1634#ifdef qedebug
1635 G4cout<<"G4QInel::PStDoIt:QEC, p="<<dmom<<",T="<<tM<<",R="<<rM<<",N="<<nM<<G4endl;
1636#endif
1637 if(!G4QHadron(t4M).DecayIn2(r4M, n4M))
1638 {
1639 //G4cerr<<"G4QInel::PostStDoIt:M="<<tM<<"<r="<<rM<<"+c="<<nM<<"="<<rM+nM<<G4endl;
1640 //G4Exception("G4QInelastic::PostStepDoIt()", "HAD_CHPS_0003",
1641 // FatalException,"Hadronize quasmon: Can't Dec totNuc->QEClu+ResNuc");
1642 G4cerr<<"-W-G4QInel::PoStDoI:M="<<tM<<"<rM="<<rM<<"+cM="<<nM<<"="<<rM+nM<<G4endl;
1643 aParticleChange.ProposeEnergy(kinEnergy);
1647 return G4VDiscreteProcess::PostStepDoIt(track,step);
1648 }
1649 // --- End of the moving cluster implementation ---
1650#ifdef qedebug
1651 G4cout<<"G4QIn::PStDoIt:QEC, RN="<<r4M.rho()<<r4M<<",QCl="<<n4M.rho()<<n4M<<G4endl;
1652#endif
1653 }
1654 G4LorentzVector s4M=n4M+proj4M; // Tot 4-momentum for scattering
1655 G4double prjM2 = proj4M.m2(); // Squared mass of the projectile
1656 G4double prjM = std::sqrt(prjM2); // @@ Get from pPDG (?)
1657 G4double minM = prjM+qM; // Min mass sum for the final products
1658 G4double cmM2 =s4M.m2();
1659 if(cmM2>minM*minM)
1660 {
1661#ifdef qedebug
1662 G4cout<<"G4QInel::PStDoIt:***Enter***,cmM2="<<cmM2<<" > minM2="<<minM*minM<<G4endl;
1663#endif
1664 // Estimate and randomize charge-exchange with a quasi-free cluster
1665 G4bool chex=false; // Flag of the charge exchange scattering
1666 G4ParticleDefinition* projpt=G4Proton::Proton(); // Prototype, only for chex=true
1667 // This is reserved for the charge-exchange scattering (to help neutron spectras)
1668 //if(cln&&!cp1 &&(projPDG==2212&&rA>rZ || projPDG==2112&&rZ>1))// @@ Use proj chex
1669 if(2>3) // @@ charge exchange is not implemented yet @@
1670 {
1671#ifdef qedebug
1672 G4cout<<"G4QIn::PStDoIt:-Enter, P="<<projPDG<<",cln="<<cln<<",cp1="<<cp1<<G4endl;
1673#endif
1674 G4double tprM=mProt;
1675 G4double tprM2=mProt2;
1676 G4int tprPDG=2212;
1677 G4int tresPDG=restPDG+999;
1678 if(projPDG==2212)
1679 {
1680 projpt=G4Neutron::Neutron();
1681 tprM=mNeut;
1682 tprM2=mNeut2;
1683 tprPDG=2112;
1684 tresPDG=restPDG-999;
1685 }
1686 minM=tprM+qM;
1687 G4double efE=(cmM2-tprM2-qM*qM)/(qM+qM);
1688 G4double efP=std::sqrt(efE*efE-tprM2);
1689 G4double chl=qfMan->ChExElCoef(efP*MeV, nZ, nA-nZ, projPDG); // ChEx/Elast(pPDG!)
1690#ifdef qedebug
1691 G4cout<<"G4QInel::PStDoIt:chl="<<chl<<",P="<<efP<<",nZ="<<nZ<<",nA="<<nA<<G4endl;
1692#endif
1693 if(chl>0.&&cmM2>minM*minM&&G4UniformRand()<chl/(1.+chl)) // minM is redefined
1694 {
1695 projPDG=tprPDG;
1696 prjM=tprM;
1697 G4double rM=G4QPDGCode(tresPDG).GetMass();// Mass of the residual nucleus
1698 r4M=G4LorentzVector(0.,0.,0.,rM); // 4mom of the residual nucleus
1699 n4M=G4LorentzVector(0.,0.,0.,tM-rM); // 4mom of the quasi-free cluster
1700 chex=true; // Confirm charge exchange scattering
1701 }
1702 }
1703 //
1704 std::pair<G4LorentzVector,G4LorentzVector> sctout=qfMan->Scatter(nPDG, n4M,
1705 projPDG, proj4M);
1706#ifdef qedebug
1707 G4cout<<"G4QInelastic::PStDoIt:QElS,proj="<<prjM<<sctout.second<<",qfCl="<<qM
1708 <<sctout.first<<",chex="<<chex<<",nA="<<nA<<",nZ="<<nZ<<G4endl;
1709#endif
1710 aParticleChange.ProposeLocalEnergyDeposit(0.); // Everything is in particles
1711 // @@ @@ @@ Coulomb barriers must be checked !! @@ @@ @@ Skip if not
1712 if(chex) // ==> Projectile is changed: fill everything to secondaries
1713 {
1714 aParticleChange.ProposeEnergy(0.); // @@ ??
1715 aParticleChange.ProposeTrackStatus(fStopAndKill); // projectile nucleon is killed
1717 G4DynamicParticle* thePrH = new G4DynamicParticle(projpt,sctout.second);
1718 G4Track* scatPrH = new G4Track(thePrH, localtime, position ); // scattered & chex
1719 scatPrH->SetWeight(weight); // weighted
1720 scatPrH->SetTouchableHandle(trTouchable); // projectile
1721 aParticleChange.AddSecondary(scatPrH); // hadron
1722 }
1723 else // ==> The leading particle is filled to the updated projectilee
1724 {
1725 aParticleChange.SetNumberOfSecondaries(2); // @@ if proj=leading
1726 G4double ldT=(sctout.second).e()-prjM; // kin Energy of scat project.
1727 aParticleChange.ProposeEnergy(ldT); // Change the kin Energy
1728 G4ThreeVector ldV=(sctout.second).vect(); // Change momentum direction
1731 }
1732 // ---------------------------------------------------------
1733 // Fill scattered quasi-free nucleon/fragment
1734 if (nPDG==90000001) theDefinition = G4Neutron::Neutron();
1735 else if(nPDG==90001000) theDefinition = G4Proton::Proton();
1736 else if(nZ>0 && nA>1)
1737 theDefinition = G4ParticleTable::GetParticleTable()->FindIon(nZ,nA,0,nZ);
1738#ifdef debug
1739 else G4cout<<"-Warning_G4QIn::PSD:scatqfPDG="<<nPDG<<", Z="<<nZ<<",A="<<nA<<G4endl;
1740#endif
1741 if(nZ>0 && nA>0)
1742 {
1743 G4DynamicParticle* theQFN = new G4DynamicParticle(theDefinition,sctout.first);
1744 G4Track* scatQFN = new G4Track(theQFN, localtime, position ); // scattered
1745 scatQFN->SetWeight(weight); // weighted
1746 scatQFN->SetTouchableHandle(trTouchable); // quasi-free
1747 aParticleChange.AddSecondary(scatQFN); // nucleon/cluster
1748 }
1749 // ----------------------------------------------------
1750 // Fill residual nucleus
1751 if (restPDG==90000001) theDefinition = G4Neutron::Neutron();
1752 else if(restPDG==90001000) theDefinition = G4Proton::Proton();
1753 else if(rZ>0 && rA>1)
1754 theDefinition = G4ParticleTable::GetParticleTable()->FindIon(rZ,rA,0,rZ);
1755#ifdef debug
1756 else G4cout<<"-Warning_G4QIn::PSD: resPDG="<<restPDG<<",Z="<<rZ<<",A="<<rA<<G4endl;
1757#endif
1758 if(rZ>0 && rA>0)
1759 {
1760 G4DynamicParticle* theReN = new G4DynamicParticle(theDefinition,r4M);
1761 G4Track* scatReN = new G4Track(theReN, localtime, position ); // scattered
1762 scatReN->SetWeight(weight); // weighted
1763 scatReN->SetTouchableHandle(trTouchable); // residual
1764 aParticleChange.AddSecondary(scatReN); // nucleus
1765 }
1766 delete output;
1767 return G4VDiscreteProcess::PostStepDoIt(track, step);
1768 }
1769#ifdef qedebug
1770 else G4cout<<"G4QInel::PSD:OUT,M2="<<s4M.m2()<<"<"<<minM*minM<<", N="<<nPDG<<G4endl;
1771#endif
1772 } // end of proton quasi-elastic (including QE on NF)
1773 else // @@ make cost-condition @@ Pickup process (pickup 1 or 2 n and make d or t)
1774 {
1775 if(projPDG==2212) restPDG--; // Res. nucleus PDG is one neutron less than targ. PDG
1776 else
1777 {
1778 restPDG-=1000; // Res. nucleus PDG is one proton less than targ. PDG
1779 rZ--; // Reduce the charge of the residual nucleus
1780 }
1781 G4double mPUF=mDeut; // Prototype of the mass of the created pickup fragment
1782 G4ParticleDefinition* theDefinition = G4Deuteron::Deuteron(); // Default: make d
1783 //theDefinition = G4ParticleTable::GetParticleTable()->FindIon(nZ,nA,0,nZ);//ion
1784 G4bool din=false; // Flag of picking up 2 neutrons to create t (tritium)(p)
1785 G4bool dip=false; // Flag of picking up 2 protons to create t (tritium) (n)
1786 G4bool pin=false; // Flag of picking up 1 n + 1 p to create He3/t (p/n)
1787 G4bool hin=false; // Flag of PickUp creation of alpha (He4) (p/n)
1788 G4double frn=G4UniformRand();
1789 if(N>2 && frn > 0.95) // .95 is a parameter to pickup 2N (to cteate t or He3)
1790 {
1791 if(projPDG==2212)
1792 {
1793 if(N>1 && G4UniformRand()*(Z+.5*(N-1)) > Z)
1794 {
1795 theDefinition = G4Triton::Triton();
1796 mPUF=mTrit; // The mass of the created pickup fragment is triton
1797 restPDG--; // Res. nucleus PDG is two neutrons less than target PDG
1798 din=true;
1799 }
1800 else
1801 {
1802 theDefinition = G4He3::He3();
1803 mPUF=mHel3; // The mass of the created pickup fragment is Helium3
1804 restPDG-=1000; // Res. nucleus PDG is two neutrons less than target PDG
1805 rZ--; // Reduce the charge of the residual nucleus
1806 pin=true;
1807 }
1808 }
1809 else // Neutron projectile (2112)
1810 {
1811 if(Z>1 && G4UniformRand()*(N+.5*(Z-1)) > N)
1812 {
1813 theDefinition = G4He3::He3();
1814 mPUF=mHel3; // The mass of the created pickup fragment is Helium3
1815 restPDG-=1000; // Res. nucleus PDG is two neutrons less than target PDG
1816 rZ--; // Reduce the charge of the residual nucleus
1817 dip=true;
1818 }
1819 else
1820 {
1821 theDefinition = G4Triton::Triton();
1822 mPUF=mTrit; // The mass of the created pickup fragment is triton
1823 restPDG--; // Res. nucleus PDG is two neutrons less than target PDG
1824 pin=true;
1825 }
1826 }
1827 rA--; // Reduce the baryon number of the residual nucleus
1828 // Recalculate dmom
1829 G4ThreeVector sumv=G4ThreeVector(0.,0.,dmom) +
1830 fmm*std::pow(-std::log(G4UniformRand()),third)*G4RandomDirection();
1831 dmom=sumv.mag();
1832 if(Z>1 && frn > 0.99) // .99 is a parameter to pickup 2n1p || 1n2p & create alpha
1833 {
1834 theDefinition = G4Alpha::Alpha();
1835 if((din && projPDG==2212) || (pin && projPDG==2112))
1836 {
1837 restPDG-=1000; // Residual nucleus PDG is reduced to create alpha
1838 rZ--; // Reduce the charge of the residual nucleus
1839 }
1840 else if((pin && projPDG==2212) || (dip && projPDG==2112)) restPDG--;
1841 else G4cout<<"-Warning-G4QIn::PSD: PickUp logic error, proj="<<projPDG<<G4endl;
1842 hin=true;
1843 mPUF=mAlph; // The mass of the created pickup fragment (alpha)
1844 rA--; // Reduce the baryon number of the residual nucleus
1845 // Recalculate dmom
1846 sumv += fmm*std::pow(-std::log(G4UniformRand()),third)*G4RandomDirection();
1847 dmom=sumv.mag();
1848 }
1849 }
1850 G4double mPUF2=mPUF*mPUF;
1851 G4LorentzVector t4M(0.,0.,0.,tM); // 4m of the target nucleus to be decayed
1852 G4double rM=G4QPDGCode(restPDG).GetMass();// Mass of the residual nucleus
1853 G4double rM2=rM*rM; // Squared mass of the residual nucleus
1854 G4double nM2=rM2+tM*tM-(tM+tM)*std::sqrt(rM2+dmom*dmom);// M2 of boundQF-nucleon(2N)
1855 if(nM2 < 0) nM2=0.;
1856 G4double den2=(dmom*dmom+nM2); // squared energy of bQF-nucleon
1857 G4double den=std::sqrt(den2); // energy of bQF-nucleon
1858#ifdef qedebug
1859 G4double nM=std::sqrt(nM2); // M of bQF-nucleon
1860 G4cout<<"G4QInel::PStDoIt:PiU, p="<<dmom<<",tM="<<tM<<", R="<<rM<<",N="<<nM<<G4endl;
1861#endif
1862 G4double qp=momentum*dmom;
1863 G4double srm=proj4M.e()*den;
1864 G4double mNucl2=mProt2;
1865 if(projPDG == 2112) mNucl2=mNeut2;
1866 G4double cost=(nM2+mNucl2+srm+srm-mPUF2)/(qp+qp);
1867 G4int ict=0;
1868 while(std::fabs(cost)>1. && ict<3)
1869 {
1870 dmom=91.; // Fermi momentum (proDefault for a deuteron)
1871 if(Z>1||N>1) dmom=fmm*std::pow(-std::log(G4UniformRand()),third);
1872 if(din || pin || dip) // Recalculate dmom for the final t/He3
1873 {
1874 G4ThreeVector sumv=G4ThreeVector(0.,0.,dmom) +
1875 fmm*std::pow(-std::log(G4UniformRand()),third)*G4RandomDirection();
1876 if(hin)
1877 sumv+=fmm*std::pow(-std::log(G4UniformRand()),third)*G4RandomDirection();
1878 dmom=sumv.mag();
1879 }
1880 nM2=rM2+tM*tM-(tM+tM)*std::sqrt(rM2+dmom*dmom); // M2 of bQF-nucleon
1881 if(nM2 < 0) nM2=0.;
1882 //nM=std::sqrt(nM2); // M of bQF-nucleon --Not used?--
1883 den2=(dmom*dmom+nM2); // squared energy of bQF-nucleon
1884 den=std::sqrt(den2); // energy of bQF-nucleon
1885 qp=momentum*dmom;
1886 srm=proj4M.e()*den;
1887 cost=(nM2+mNucl2+srm+srm-mPUF2)/(qp+qp);
1888 ict++;
1889#ifdef ldebug
1890 if(ict>2)G4cout<<"G4QInelast::PStDoIt:i="<<ict<<",d="<<dmom<<",ct="<<cost<<G4endl;
1891#endif
1892 }
1893 if(std::fabs(cost)<=1.)
1894 {// ---- @@ From here can be a MF for QF nucleon extraction (if used by others)
1895 G4ThreeVector vdir = proj4M.vect(); // 3-Vector in the projectile direction
1896 G4ThreeVector vx(0.,0.,1.); // ProtoOrt in theDirection of the projectile
1897 G4ThreeVector vy(0.,1.,0.); // First ProtoOrt orthogonal to the direction
1898 G4ThreeVector vz(1.,0.,0.); // SecondProtoOrt orthoganal to the direction
1899 if(vdir.mag2() > 0.) // the projectile isn't at rest
1900 {
1901 vx = vdir.unit(); // Ort in the direction of the projectile
1902 G4ThreeVector vv= vx.orthogonal(); // Not normed orthogonal vector (!)
1903 vy = vv.unit(); // First ort orthogonal to the proj direction
1904 vz = vx.cross(vy); // Second ort orthoganal to the projDirection
1905 }
1906 // ---- @@ End of possible MF (Similar is in G4QEnvironment)
1907 G4double tdom=dmom*std::sqrt(1-cost*cost);// Transversal component of the Fermi-Mom
1908 G4double phi=twopi*G4UniformRand(); // Phi of the Fermi-Mom
1909 G4ThreeVector vedm=vx*dmom*cost+vy*tdom*std::sin(phi)+vz*tdom*std::cos(phi);// bQFN
1910 G4LorentzVector bqf(vedm,den); // 4-mom of the bQF nucleon
1911 r4M=t4M-bqf; // 4mom of the residual nucleus
1912#ifdef debug
1913 if(std::fabs(r4M.m()-rM)>.001) G4cout<<"G4QIn::PSD: rM="<<rM<<"#"<<r4M.m()<<G4endl;
1914#endif
1915 G4LorentzVector f4M=proj4M+bqf; // Prototype of 4-mom of Deuteron
1916#ifdef debug
1917 if(std::fabs(f4M.m()-mPUF)>.001)G4cout<<"G4QI::PSD:m="<<mPUF<<"#"<<f4M.m()<<G4endl;
1918#endif
1919 aParticleChange.ProposeEnergy(0.); // @@ ??
1920 aParticleChange.ProposeTrackStatus(fStopAndKill);// projectile nucleon is killed
1922 // Fill pickup hadron
1923 G4DynamicParticle* theQFN = new G4DynamicParticle(theDefinition,f4M);
1924 G4Track* scatQFN = new G4Track(theQFN, localtime, position ); // pickup
1925 scatQFN->SetWeight(weight); // weighted
1926 scatQFN->SetTouchableHandle(trTouchable); // nuclear
1927 aParticleChange.AddSecondary(scatQFN); // cluster
1928#ifdef pickupd
1929 G4cout<<"G4QInelastic::PStDoIt: f="<<theDefinition<<",f4M="<<f4M.m()<<f4M<<G4endl;
1930#endif
1931 // ----------------------------------------------------
1932 // Fill residual nucleus
1933 if (restPDG==90000001) theDefinition = G4Neutron::Neutron();
1934 else if(restPDG==90001000) theDefinition = G4Proton::Proton();
1935 else theDefinition = G4ParticleTable::GetParticleTable()->FindIon(rZ,rA,0,rZ);//ion
1936 G4DynamicParticle* theReN = new G4DynamicParticle(theDefinition,r4M);
1937 G4Track* scatReN = new G4Track(theReN, localtime, position ); // scattered
1938 scatReN->SetWeight(weight); // weighted
1939 scatReN->SetTouchableHandle(trTouchable); // residual
1940 aParticleChange.AddSecondary(scatReN); // nucleus
1941#ifdef pickupd
1942 G4cout<<"G4QInelastic::PStDoIt:rZ="<<rZ<<",rA="<<rA<<",r4M="<<r4M.m()<<r4M<<G4endl;
1943#endif
1944 delete output;
1945 return G4VDiscreteProcess::PostStepDoIt(track, step);
1946 }
1947 }
1948 } // end of the quasi-elastic decoupled process for the neucleon projectile
1949 } // end lepto-nuclear, neutrino-nuclear, proton/neutron decoupled processes
1950 EnMomConservation=proj4M+G4LorentzVector(0.,0.,0.,tM); // Total 4-mom of the reaction
1951 if(absMom) EnMomConservation+=lead4M; // Add E/M of leading System
1952#ifdef debug
1953 G4cout<<"G4QInelastic::PostStDoIt:before St="<<aParticleChange.GetTrackStatus()<<G4endl;
1954#endif
1955
1956 // @@@@@@@@@@@@@@ Temporary for the testing purposes --- Begin
1957 //G4bool elF=false; // Flag of the ellastic scattering is "false" by default
1958 //G4double eWei=1.;
1959 // @@@@@@@@@@@@@@ Temporary for the testing purposes --- End
1960#ifdef debug
1961 G4cout<<"^^G4QInelastic::PostStepDoIt: projPDG="<<projPDG<<", targPDG="<<targPDG<<G4endl;
1962#endif
1963 const G4QNucleus targNuc(Z,N); // Define the target nucleus
1964 if(projPDG>9000000)
1965 {
1966 delete output; // Before the output creation
1967 G4QNucleus projNuc(proj4M,projPDG); // Define the projectile nucleus
1968 G4QIonIonCollision IonIon(projNuc, targNuc); // Define deep-inelastic ion-ion reaction
1969#ifdef debug
1970 G4cout<<"G4QInel::PStDoIt: ProjNuc="<<projPDG<<proj4M<<", TargNuc="<<targPDG<<G4endl;
1971#endif
1972 try {output = IonIon.Fragment();} // DINR AA interaction products
1973 catch (G4QException& error)
1974 {
1975 G4cerr<<"***G4QInelastic::PostStepDoIt: G4QE Exception is catched in hA"<<G4endl;
1976 // G4Exception("G4QInelastic::PostStepDoIt:","27",FatalException,"CHIPS hA crash");
1977 G4Exception("G4QInelastic::PostStepDoIt()", "HAD_CHPS_0027",
1978 FatalException, "CHIPS hA crash");
1979 }
1980 }
1981 else // --> A projectile hadron
1982 {
1983 // *** Let to produce elastic final states for acceleration ***
1984#ifdef debug
1985 G4int maxCn=7;
1986#endif
1987 G4int atCn=0; // Attempts counter
1988 //G4bool inel=false;
1989 //while (inel==false && ++atCn <= maxCn) // To evoid elastic final state
1990 //{
1991#ifdef debug
1992 G4cout<<"G4QInelastic::PStDoIt: atCn="<<atCn<<" <= maxCn="<<maxCn<<G4endl;
1993#endif
1994 G4int outN=output->size();
1995 if(outN) // The output is not empty
1996 {
1997 std::for_each(output->begin(), output->end(), DeleteQHadron());
1998 output->clear();
1999 }
2000 delete output; // Before the new output creation
2001 const G4QHadron projH(projPDG,proj4M); // Define the projectile particle
2002#ifdef debug
2003 G4cout<<"G4QInelastic::PStDoIt: Before Fragmentation"<<G4endl;
2004#endif
2005 //if(aProjPDG==22 && projPDG==22 && proj4M.m2()<.01 && proj4M.e()<150.)
2006 //{
2007 // G4QHadron* tgH= new G4QHadron(targNuc.GetPDGCode(),targNuc.Get4Momentum());
2008 // G4QHadron* prH= new G4QHadron(projPDG,proj4M);
2009 // output = new G4QHadronVector();
2010 // output->push_back(prH);
2011 // output->push_back(tgH);
2012 //}
2013 //else
2014 //{
2015 G4QFragmentation DINR(targNuc, projH); // Define deep-inel. h-A reaction
2016#ifdef debug
2017 G4cout<<"G4QInelastic::PStDoIt:Proj="<<projPDG<<proj4M<<",TgNuc="<<targPDG<<G4endl;
2018#endif
2019 try {output = DINR.Fragment();} // DINR hA fragmentation
2020 catch (G4QException& error)
2021 {
2022 G4cerr<<"***G4QInelastic::PostStepDoIt: G4QE Exception is catched in hA"<<G4endl;
2023 // G4Exception("G4QInelastic::PostStepDoIt:","27",FatalException,"CHIPS hA crash");
2024 G4Exception("G4QInelastic::PostStepDoIt()", "HAD_CHPS_0027",
2025 FatalException, "CHIPS hA crash");
2026 }
2027 //}
2028 outN=output->size();
2029#ifdef debug
2030 G4cout<<"G4QInelastic::PostStepDoIt: At# "<<atCn<<", nSec="<<outN<<", fPDG="
2031 <<(*output)[0]->GetPDGCode()<<", pPDG="<< projPDG<<G4endl;
2032#endif
2033 //inel=true; // For while
2034 if(outN < 2)
2035 {
2036 G4cout<<"-Warning-G4QInelastic::PostStepDoIt: nSec="<<outN<<", At# "<<atCn<<G4endl;
2037 //inel=false; // For while
2038 }
2039 //else if(outN==2 && (*output)[0]->GetPDGCode() == projPDG) inel=false; // For while
2040#ifdef debug
2041 if(atCn==maxCn)G4cout<<"-Warning-G4QI::PostStDoIt:mAt="<<atCn<<" is reached"<<G4endl;
2042#endif
2043 //}
2044 }
2045 //
2046 // --- the scattered hadron with changed nature can be added here ---
2047 if(scat)
2048 {
2049 G4QHadron* scatHadron = new G4QHadron(scatPDG,scat4M);
2050 output->push_back(scatHadron);
2051 }
2052 G4int qNH=0;
2053 if(leadhs) qNH=leadhs->size();
2054 if(absMom)
2055 {
2056 if(qNH) for(G4int iq=0; iq<qNH; iq++)
2057 {
2058 G4QHadron* loh=(*leadhs)[iq]; // Pointer to the output hadron
2059 output->push_back(loh);
2060 }
2061 if(leadhs) delete leadhs;
2062 leadhs=0;
2063 }
2064 else
2065 {
2066 if(qNH) for(G4int iq=0; iq<qNH; iq++) delete (*leadhs)[iq];
2067 if(leadhs) delete leadhs;
2068 leadhs=0;
2069 }
2070 // ------------- From here the secondaries are filled -------------------------
2071 G4int tNH = output->size(); // A#of hadrons in the output
2072 aParticleChange.SetNumberOfSecondaries(tNH); // @@ tNH can be changed (drop/decay!)
2073 // Now add nuclear fragments
2074#ifdef debug
2075 G4cout<<"G4QInelastic::PostStepDoIt: "<<tNH<<" particles are generated"<<G4endl;
2076#endif
2077#ifdef ppdebug
2078 if(absMom)G4cout<<"G4QInelastic::PostStepDoIt: t="<<tNH<<", q="<<qNH<<G4endl;
2079#endif
2080 G4int nOut=output->size(); // Real length of the output @@ Temporary
2081 if(tNH==1 && !scat) // @@ Temporary. Find out why it happened!
2082 {
2083 G4cout<<"-Warning-G4QInelastic::PostStepDoIt: 1 secondary! absMom="<<absMom;
2084 if(absMom) G4cout<<", qNH="<<qNH;
2085 G4cout<<", PDG0="<<(*output)[0]->GetPDGCode();
2086 G4cout<<G4endl;
2087 tNH=0;
2088 delete output->operator[](0); // delete the creazy hadron
2089 output->pop_back(); // clean up the output vector
2090 }
2091 if(tNH==2&&2!=nOut) G4cout<<"--Warning--G4QInelastic::PostStepDoIt: 2 # "<<nOut<<G4endl;
2092 // Deal with ParticleChange final state interface to GEANT4 output of the process
2093 //if(tNH==2) for(i=0; i<tNH; i++) // @@ Temporary tNH==2 instead of just tNH
2094 if(tNH) for(i=0; i<tNH; i++) // @@ Temporary tNH==2 instead of just tNH
2095 {
2096 // Note that one still has to take care of Hypernuclei (with Lambda or Sigma inside)
2097 // Hypernucleus mass calculation and ion-table interface upgrade => work for Hisaya @@
2098 // The decau process for hypernuclei must be developed in GEANT4 (change CHIPS body)
2099 G4QHadron* hadr=(*output)[i]; // Pointer to the output hadron
2100 G4int PDGCode = hadr->GetPDGCode();
2101 G4int nFrag = hadr->GetNFragments();
2102#ifdef pdebug
2103 G4cout<<"G4QInelastic::PostStepDoIt: H#"<<i<<",PDG="<<PDGCode<<",nF="<<nFrag
2104 <<", 4Mom="<<hadr->Get4Momentum()<<G4endl;
2105#endif
2106 if(nFrag) // Skip intermediate (decayed) hadrons
2107 {
2108#ifdef debug
2109 G4cout<<"G4QInelastic::PostStepDoIt: Intermediate particle is found i="<<i<<G4endl;
2110#endif
2111 delete hadr;
2112 continue;
2113 }
2115 G4ParticleDefinition* theDefinition;
2116 if (PDGCode==90000001) theDefinition = G4Neutron::Neutron();
2117 else if(PDGCode==90001000) theDefinition = G4Proton::Proton();//While it can be in ions
2118 else if(PDGCode==91000000) theDefinition = G4Lambda::Lambda();
2119 else if(PDGCode==311 || PDGCode==-311)
2120 {
2121 if(G4UniformRand()>.5) theDefinition = G4KaonZeroLong::KaonZeroLong(); // K_L
2122 else theDefinition = G4KaonZeroShort::KaonZeroShort(); // K_S
2123 }
2124 else if(PDGCode==91000999) theDefinition = G4SigmaPlus::SigmaPlus();
2125 else if(PDGCode==90999001) theDefinition = G4SigmaMinus::SigmaMinus();
2126 else if(PDGCode==91999000) theDefinition = G4XiMinus::XiMinus();
2127 else if(PDGCode==91999999) theDefinition = G4XiZero::XiZero();
2128 else if(PDGCode==92998999) theDefinition = G4OmegaMinus::OmegaMinus();
2129 else if(PDGCode==90000000)
2130 {
2131#ifdef pdebug
2132 G4cout<<"-Warning-G4QInelastic::PostStepDoIt:Vacuum PDG="<<PDGCode
2133 <<", 4Mom="<<hadr->Get4Momentum()<<G4endl;
2134#endif
2135 theDefinition = G4Gamma::Gamma();
2136 G4double hM2=(hadr->Get4Momentum()).m2();
2137 if(std::fabs(hM2)>.01) G4cout<<"-Warning-G4QInel::PoStDoIt:90000000M2="<<hM2<<G4endl;
2138 else if(hadr->Get4Momentum()==vacuum4M)
2139 {
2140 delete hadr;
2141 continue;
2142 }
2143 }
2144 else if(PDGCode >80000000) // Defines hypernuclei as normal nuclei (N=N+S Correction!)
2145 {
2146 G4int aZ = hadr->GetCharge();
2147 G4int aA = hadr->GetBaryonNumber();
2148#ifdef pdebug
2149 G4cout<<"G4QInelastic::PostStepDoIt:Ion Z="<<aZ<<", A="<<aA<<G4endl;
2150#endif
2151 theDefinition = G4ParticleTable::GetParticleTable()->FindIon(aZ,aA,0,aZ);
2152 }
2153 //else theDefinition = G4ParticleTable::GetParticleTable()->FindParticle(PDGCode);
2154 else if(PDGCode==89999998 || PDGCode==89998000 || PDGCode==88000000) // anti-di-baryon
2155 {
2156 G4double rM=mNeut; // Prototype of the baryon mass
2157 G4int rPDG=-2112; // Prototype of the baryon PDG
2158 G4ParticleDefinition* BarDef=G4Neutron::Neutron();// Prototype of theBaryonDefinition
2159 if (PDGCode==89998000)
2160 {
2161 rM=mProt;
2162 rPDG=-2212;
2163 BarDef=G4Proton::Proton();
2164 }
2165 else if(PDGCode==88000000)
2166 {
2167 rM=mLamb;
2168 rPDG=-3122;
2169 BarDef=G4Lambda::Lambda();
2170 }
2171 G4LorentzVector t4M=hadr->Get4Momentum(); // 4m of the di-baryon
2172 G4LorentzVector f4M=G4LorentzVector(0.,0.,0.,rM); // 4mom of the 1st anti-baryon
2173 G4LorentzVector s4M=G4LorentzVector(0.,0.,0.,rM); // 4mom of the 2nd anti-baryon
2174#ifdef qedebug
2175 G4cout<<"G4QInel::PStDoIt:AntiDiBar,t4M="<<tM<<",m="<<rM<<",PDG="<<PDGCode<<G4endl;
2176#endif
2177 if(!G4QHadron(t4M).DecayIn2(f4M, s4M))
2178 {
2179 G4cerr<<"G4QIn::PostStDoIt: ADB, M="<<t4M.m()<<" < 2*rM="<<rM<<" = "<<2*rM<<G4endl;
2180 // throw G4QException("G4QInelastic::HadronizeQuasm:Can't decay anti-dibaryon");
2181 G4Exception("G4QInelastic::PostStepDoIt()", "HAD_CHPS_0004",
2182 FatalException, "Hadronize quasmon: Can't decay anti-dibaryon");
2183 }
2184 // --- End of the moving cluster implementation ---
2185#ifdef qedebug
2186 G4cout<<"G4QInelastic::PStDoIt: ADB, H1="<<rM<<f4M<<", H2="<<rM<<s4M<<G4endl;
2187#endif
2188 G4QHadron fH(rPDG,f4M);
2189 hadr->Set4Momentum(f4M);
2190 hadr->SetQPDG(fH.GetQPDG());
2191 theDefinition=BarDef;
2192#ifdef debug
2193 G4cout<<"G4QInel::PostStDoIt:Anti-DiBar, DecayIn2, h1="<<rPDG<<f4M<<G4endl;
2194#endif
2195 G4QHadron* sH = new G4QHadron(rPDG,s4M);
2196 output->push_back(sH);
2197 ++tNH;
2198#ifdef debug
2199 G4cout<<"G4QInel::PostStDoIt:Anti-DiBar, DecayIn2, h2="<<rPDG<<s4M<<G4endl;
2200#endif
2201 }
2202 else if(PDGCode==90000997 || PDGCode==89997001) // anti-NDelta
2203 {
2204 G4double rM=mNeut; // Prototype of the baryon mass
2205 G4int rPDG=-2112; // Prototype of the baryon PDG
2206 G4double iM=mPi; // Prototype of the pion mass
2207 G4int iPDG= 211; // Prototype of the pion PDG
2208 G4ParticleDefinition* BarDef=G4Neutron::Neutron();// Prototype of theBaryonDefinition
2209 if(PDGCode==90000997)
2210 {
2211 rM=mProt;
2212 rPDG=-2212;
2213 iPDG=-211;
2214 BarDef=G4Proton::Proton();
2215 }
2216 G4LorentzVector t4M=hadr->Get4Momentum(); // 4m of the di-baryon
2217 G4LorentzVector f4M=G4LorentzVector(0.,0.,0.,rM); // 4mom of the 1st anti-baryon
2218 G4LorentzVector s4M=G4LorentzVector(0.,0.,0.,rM); // 4mom of the 2nd anti-baryon
2219 G4LorentzVector u4M=G4LorentzVector(0.,0.,0.,iM); // 4mom of the pion
2220#ifdef qedebug
2221 G4cout<<"G4QInel::PStDoIt:AntiNDelta, t4M="<<tM<<",m="<<rM<<",PDG="<<PDGCode<<G4endl;
2222#endif
2223 if(!G4QHadron(t4M).DecayIn3(f4M, s4M, u4M))
2224 {
2225 G4cerr<<"G4QIn::PostStDoIt: AND, tM="<<t4M.m()<<" < 2*mB+mPi="<<2*rM+iM<<G4endl;
2226 // throw G4QException("G4QInelastic::HadronizeQuasm:Can't decay anti-NDelta");
2227 G4Exception("G4QInelastic::PostStepDoIt()", "HAD_CHPS_0005",
2228 FatalException, "Hadronize quasmon: Can't decay anti-NDelta");
2229 }
2230 // --- End of the moving cluster implementation ---
2231#ifdef qedebug
2232 G4cout<<"G4QInel::PStDoI:AND,B1="<<rM<<f4M<<",B2="<<rM<<s4M<<",Pi="<<iM<<u4M<<G4endl;
2233#endif
2234 G4QHadron fH(rPDG,f4M);
2235 hadr->Set4Momentum(f4M);
2236 hadr->SetQPDG(fH.GetQPDG());
2237 theDefinition=BarDef;
2238#ifdef debug
2239 G4cout<<"G4QInel::PostStDoIt:Anti-NDelta, DecayIn2, h1="<<rPDG<<f4M<<G4endl;
2240#endif
2241 G4QHadron* sH = new G4QHadron(rPDG,s4M);
2242 output->push_back(sH);
2243 ++tNH;
2244#ifdef debug
2245 G4cout<<"G4QInel::PostStDoIt:Anti-NDelta, DecayIn2, h2="<<rPDG<<s4M<<G4endl;
2246#endif
2247 G4QHadron* uH = new G4QHadron(iPDG,u4M);
2248 output->push_back(uH);
2249 ++tNH;
2250#ifdef debug
2251 G4cout<<"G4QInel::PostStDoIt:Anti-NDelta, DecayIn2, h2="<<rPDG<<s4M<<G4endl;
2252#endif
2253 }
2254 else
2255 {
2256#ifdef pdebug
2257 G4cout<<"G4QInelastic::PostStepDoIt:Define particle with PDG="<<PDGCode<<G4endl;
2258#endif
2259 theDefinition = G4QPDGToG4Particle::Get()->GetParticleDefinition(PDGCode);
2260#ifdef pdebug
2261 G4cout<<"G4QInelastic::PostStepDoIt:AfterParticleDefinition PDG="<<PDGCode<<G4endl;
2262#endif
2263 }
2264 if(!theDefinition)
2265 { // !! Commenting of this print costs days of searching for E/mom nonconservation !!
2266 if(PDGCode!=90000000 || hadr->Get4Momentum()!=vacuum4M)
2267 G4cout<<"---Warning---G4QInelastic::PostStepDoIt: drop PDG="<<PDGCode<<", 4Mom="
2268 <<hadr->Get4Momentum()<<G4endl;
2269 delete hadr;
2270 continue;
2271 }
2272#ifdef pdebug
2273 G4cout<<"G4QInelastic::PostStepDoIt:Name="<<theDefinition->GetParticleName()<<G4endl;
2274#endif
2275 theSec->SetDefinition(theDefinition);
2276 G4LorentzVector h4M=hadr->Get4Momentum();
2277 EnMomConservation-=h4M;
2278#ifdef tdebug
2279 G4cout<<"G4QInelast::PSDI: "<<i<<","<<PDGCode<<h4M<<h4M.m()<<EnMomConservation<<G4endl;
2280#endif
2281#ifdef debug
2282 G4cout<<"G4QInelastic::PostStepDoIt:#"<<i<<",PDG="<<PDGCode<<",4M="<<h4M<<G4endl;
2283#endif
2284 theSec->Set4Momentum(h4M); // ^
2285 delete hadr; // <-----<-----------<-------------<---------------------<---------<-----+
2286#ifdef debug
2287 G4ThreeVector curD=theSec->GetMomentumDirection(); // ^
2288 G4double curM=theSec->GetMass(); // |
2289 G4double curE=theSec->GetKineticEnergy()+curM; // ^
2290 G4cout<<"G4QInelast::PSDoIt:p="<<curD<<curD.mag()<<",e="<<curE<<",m="<<curM<<G4endl;//|
2291#endif
2292 G4Track* aNewTrack = new G4Track(theSec, localtime, position ); // ^
2293 aNewTrack->SetWeight(weight); // weighted |
2294 aNewTrack->SetTouchableHandle(trTouchable); // |
2295 aParticleChange.AddSecondary( aNewTrack ); // |
2296#ifdef debug
2297 G4cout<<"G4QInelastic::PostStepDoIt:#"<<i<<" is done."<<G4endl; // |
2298#endif
2299 } // |
2300 delete output; // instances of the G4QHadrons from the output are already deleted above +
2301 if(leadhs) // To satisfy Valgrind ( How can that be?)
2302 {
2303 qNH=leadhs->size();
2304 if(qNH) for(G4int iq=0; iq<qNH; iq++) delete (*leadhs)[iq];
2305 delete leadhs;
2306 leadhs=0;
2307 }
2308#ifdef debug
2309 G4cout<<"G4QInelastic::PostStDoIt: after St="<<aParticleChange.GetTrackStatus()<<G4endl;
2310#endif
2311 if(aProjPDG!=11 && aProjPDG!=13 && aProjPDG!=15)
2312 aParticleChange.ProposeTrackStatus(fStopAndKill); // Kill the absorbed particle
2313#ifdef pdebug
2314 G4cout<<"G4QInelastic::PostStepDoIt: E="<<aParticleChange.GetEnergy()
2316#endif
2317#ifdef ldebug
2318 G4cout<<"G4QInelastic::PostStepDoIt:*** PostStepDoIt is done ***, P="<<aProjPDG<<", St="
2320#endif
2321 return G4VDiscreteProcess::PostStepDoIt(track, step);
2322}
2323
2324std::pair<G4double,G4double> G4QInelastic::Random2DDirection()
2325{
2326 G4double sp=0; // sin(phi)
2327 G4double cp=1.; // cos(phi)
2328 G4double r2=2.; // to enter the loop
2329 while(r2>1. || r2<.0001) // pi/4 efficiency
2330 {
2331 G4double sine=G4UniformRand();
2332 G4double cosine=G4UniformRand();
2333 sp=1.-sine-sine;
2334 cp=1.-cosine-cosine;
2335 r2=sp*sp+cp*cp;
2336 }
2337 G4double norm=std::sqrt(r2);
2338 return std::make_pair(sp/norm,cp/norm);
2339}
std::vector< G4Element * > G4ElementVector
@ FatalException
G4ForceCondition
@ NotForced
#define G4HadronicDeprecate(name)
std::vector< G4Isotope * > G4IsotopeVector
CLHEP::HepLorentzVector G4LorentzVector
@ fHadronic
std::vector< G4QHadron * > G4QHadronVector
G4double G4QThd(G4int i)
Definition: G4QThd.hh:47
G4ThreeVector G4RandomDirection()
CLHEP::Hep3Vector G4ThreeVector
@ fAlive
@ fStopAndKill
@ fStopButAlive
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
bool G4bool
Definition: G4Types.hh:67
#define G4endl
Definition: G4ios.hh:52
G4DLLIMPORT std::ostream G4cerr
G4DLLIMPORT std::ostream G4cout
#define G4UniformRand()
Definition: Randomize.hh:53
Hep3Vector unit() const
Hep3Vector orthogonal() const
double mag2() const
Hep3Vector cross(const Hep3Vector &) const
double mag() const
Hep3Vector vect() const
static G4Alpha * Alpha()
Definition: G4Alpha.cc:89
static G4AntiKaonZero * AntiKaonZero()
static G4AntiLambda * AntiLambda()
static G4AntiNeutrinoE * AntiNeutrinoE()
static G4AntiNeutrinoMu * AntiNeutrinoMu()
static G4AntiNeutrinoTau * AntiNeutrinoTau()
static G4AntiNeutron * AntiNeutron()
static G4AntiOmegaMinus * AntiOmegaMinus()
static G4AntiProton * AntiProton()
Definition: G4AntiProton.cc:93
static G4AntiSigmaMinus * AntiSigmaMinus()
static G4AntiSigmaPlus * AntiSigmaPlus()
static G4AntiSigmaZero * AntiSigmaZero()
static G4AntiXiMinus * AntiXiMinus()
static G4AntiXiZero * AntiXiZero()
static G4Deuteron * Deuteron()
Definition: G4Deuteron.cc:94
G4double GetMass() const
const G4ThreeVector & GetMomentumDirection() const
void SetDefinition(const G4ParticleDefinition *aParticleDefinition)
G4ParticleDefinition * GetDefinition() const
G4LorentzVector Get4Momentum() const
G4double GetKineticEnergy() const
void Set4Momentum(const G4LorentzVector &momentum)
G4double GetTotalMomentum() const
static G4Electron * Electron()
Definition: G4Electron.cc:94
G4double * GetRelativeAbundanceVector() const
Definition: G4Element.hh:166
G4double GetZ() const
Definition: G4Element.hh:131
const G4Isotope * GetIsotope(G4int iso) const
Definition: G4Element.hh:169
size_t GetIndex() const
Definition: G4Element.hh:182
G4IsotopeVector * GetIsotopeVector() const
Definition: G4Element.hh:162
static G4Gamma * Gamma()
Definition: G4Gamma.cc:86
static G4GenericIon * GenericIon()
Definition: G4GenericIon.cc:92
static G4He3 * He3()
Definition: G4He3.cc:94
G4int GetZ() const
Definition: G4Isotope.hh:91
G4int GetN() const
Definition: G4Isotope.hh:94
static G4KaonMinus * KaonMinus()
Definition: G4KaonMinus.cc:113
static G4KaonPlus * KaonPlus()
Definition: G4KaonPlus.cc:113
static G4KaonZeroLong * KaonZeroLong()
static G4KaonZeroShort * KaonZeroShort()
static G4KaonZero * KaonZero()
Definition: G4KaonZero.cc:104
static G4Lambda * Lambda()
Definition: G4Lambda.cc:108
const G4ElementVector * GetElementVector() const
Definition: G4Material.hh:189
size_t GetNumberOfElements() const
Definition: G4Material.hh:185
const G4double * GetVecNbOfAtomsPerVolume() const
Definition: G4Material.hh:205
static G4MuonMinus * MuonMinus()
Definition: G4MuonMinus.cc:100
static G4MuonPlus * MuonPlus()
Definition: G4MuonPlus.cc:99
static G4NeutrinoE * NeutrinoE()
Definition: G4NeutrinoE.cc:85
static G4NeutrinoMu * NeutrinoMu()
Definition: G4NeutrinoMu.cc:85
static G4NeutrinoTau * NeutrinoTau()
static G4Neutron * Neutron()
Definition: G4Neutron.cc:104
static G4OmegaMinus * OmegaMinus()
void AddSecondary(G4Track *aSecondary)
G4double GetEnergy() const
const G4ThreeVector * GetMomentumDirection() const
void ProposeEnergy(G4double finalEnergy)
void ProposeMomentumDirection(G4double Px, G4double Py, G4double Pz)
virtual void Initialize(const G4Track &)
G4int GetAtomicNumber() const
G4int GetAtomicMass() const
const G4String & GetParticleName() const
G4ParticleDefinition * FindIon(G4int atomicNumber, G4int atomicMass, G4double excitationEnergy)
static G4ParticleTable * GetParticleTable()
static G4PionMinus * PionMinus()
Definition: G4PionMinus.cc:98
static G4PionPlus * PionPlus()
Definition: G4PionPlus.cc:98
static G4Positron * Positron()
Definition: G4Positron.cc:94
static G4Proton * Proton()
Definition: G4Proton.cc:93
static G4VQCrossSection * GetPointer()
static G4VQCrossSection * GetPointer()
static G4VQCrossSection * GetPointer()
static G4QCHIPSWorld * Get()
G4QParticleVector * GetParticles(G4int nOfParts=0)
static void SetParameters(G4double solAn=0.4, G4bool efFlag=false, G4double piThresh=141.4, G4double mpisq=20000., G4double dinum=1880.)
G4QHadronVector * Fragment()
G4LorentzVector Get4Momentum() const
Definition: G4QHadron.hh:79
G4int GetBaryonNumber() const
Definition: G4QHadron.hh:181
G4int GetCharge() const
Definition: G4QHadron.hh:179
G4int GetPDGCode() const
Definition: G4QHadron.hh:170
void SetQPDG(const G4QPDGCode &QPDG)
Definition: G4QHadron.cc:275
G4int GetNFragments() const
Definition: G4QHadron.hh:174
void Set4Momentum(const G4LorentzVector &aMom)
Definition: G4QHadron.hh:187
G4QPDGCode GetQPDG() const
Definition: G4QHadron.hh:172
static void SetStandard()
Definition: G4QInelastic.cc:95
G4int GetNumberOfNeutronsInTarget()
G4QInelastic(const G4String &processName="CHIPS_Inelastic")
Definition: G4QInelastic.cc:57
static void SetManual()
Definition: G4QInelastic.cc:94
static void SetPhotNucBias(G4double phnB=1.)
G4VParticleChange * PostStepDoIt(const G4Track &aTrack, const G4Step &aStep)
static void SetParameters(G4double temper=180., G4double ssin2g=.1, G4double etaetap=.3, G4double fN=0., G4double fD=0., G4double cP=1., G4double mR=1., G4int npCHIPSWorld=234, G4double solAn=.5, G4bool efFlag=false, G4double piTh=141.4, G4double mpi2=20000., G4double dinum=1880.)
Definition: G4QInelastic.cc:98
static void SetWeakNucBias(G4double ccnB=1.)
G4double GetMeanFreePath(const G4Track &aTrack, G4double previousStepSize, G4ForceCondition *condition)
G4bool IsApplicable(const G4ParticleDefinition &particle)
G4LorentzVector GetEnegryMomentumConservation()
G4QHadronVector * Fragment()
std::vector< std::pair< G4int, G4double > * > * GetCSVector(G4int Z, G4int index=0)
Definition: G4QIsotope.cc:1737
G4bool IsDefined(G4int Z, G4int Ind)
Definition: G4QIsotope.cc:1660
G4double GetMeanCrossSection(G4int Z, G4int index=0)
Definition: G4QIsotope.cc:1842
static G4QIsotope * Get()
Definition: G4QIsotope.cc:720
G4int InitElement(G4int Z, G4int index, std::vector< std::pair< G4int, G4double > * > *abund)
Definition: G4QIsotope.cc:1557
static G4VQCrossSection * GetPointer()
G4double GetRatio(G4double pIU, G4int tgZ, G4int tgN)
static G4QNeutronCaptureRatio * GetPointer()
static G4VQCrossSection * GetPointer()
static G4VQCrossSection * GetPointer()
static G4VQCrossSection * GetPointer()
static void SetParameters(G4double fN=.1, G4double fD=.05, G4double cP=4., G4double mR=1., G4double nD=.8 *CLHEP::fermi)
Definition: G4QNucleus.cc:347
G4double GetMass()
Definition: G4QPDGCode.cc:693
G4double GetNuclMass(G4int Z, G4int N, G4int S)
Definition: G4QPDGCode.cc:766
G4ParticleDefinition * GetParticleDefinition(G4int PDGCode)
static G4QPDGToG4Particle * Get()
static G4VQCrossSection * GetPointer()
static G4VQCrossSection * GetPointer()
static G4VQCrossSection * GetPointer()
G4double ChExElCoef(G4double p, G4int Z, G4int N, G4int pPDG)
std::pair< G4LorentzVector, G4LorentzVector > Scatter(G4int NPDG, G4LorentzVector N4M, G4int pPDG, G4LorentzVector p4M)
static G4QuasiFreeRatios * GetPointer()
std::pair< G4double, G4double > GetRatios(G4double pIU, G4int prPDG, G4int tgZ, G4int tgN)
G4QHadronVector * Fragment(G4QNucleus &nucEnviron, G4int nQ=1)
Definition: G4Quasmon.cc:6178
static void SetParameters(G4double temper=180., G4double ssin2g=.3, G4double etaetap=.3)
Definition: G4Quasmon.cc:192
static G4SigmaMinus * SigmaMinus()
static G4SigmaPlus * SigmaPlus()
Definition: G4SigmaPlus.cc:108
static G4SigmaZero * SigmaZero()
Definition: G4SigmaZero.cc:99
Definition: G4Step.hh:78
static G4TauMinus * TauMinus()
Definition: G4TauMinus.cc:135
static G4TauPlus * TauPlus()
Definition: G4TauPlus.cc:134
G4double GetWeight() const
void SetWeight(G4double aValue)
const G4ThreeVector & GetPosition() const
void SetTouchableHandle(const G4TouchableHandle &apValue)
G4double GetGlobalTime() const
G4Material * GetMaterial() const
const G4DynamicParticle * GetDynamicParticle() const
const G4TouchableHandle & GetTouchableHandle() const
static G4Triton * Triton()
Definition: G4Triton.cc:95
virtual G4VParticleChange * PostStepDoIt(const G4Track &, const G4Step &)
void ProposeTrackStatus(G4TrackStatus status)
void ProposeLocalEnergyDeposit(G4double anEnergyPart)
void SetNumberOfSecondaries(G4int totSecondaries)
G4TrackStatus GetTrackStatus() const
G4ParticleChange aParticleChange
Definition: G4VProcess.hh:289
G4int verboseLevel
Definition: G4VProcess.hh:368
const G4String & GetProcessName() const
Definition: G4VProcess.hh:379
virtual G4double GetExchangeEnergy()
virtual G4double GetQEL_ExchangeQ2()
virtual G4double GetNQE_ExchangeQ2()
virtual G4double GetLastQELCS()
virtual G4double GetLastTOTCS()
virtual G4double GetVirtualFactor(G4double nu, G4double Q2)
virtual G4double GetCrossSection(G4bool, G4double, G4int, G4int, G4int pPDG=0)
virtual G4int GetExchangePDGCode()
virtual G4double GetExchangeQ2(G4double nu=0)
static G4XiMinus * XiMinus()
Definition: G4XiMinus.cc:106
static G4XiZero * XiZero()
Definition: G4XiZero.cc:106
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
#define DBL_MAX
Definition: templates.hh:83