ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4MuNeutrinoNucleusProcess.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4MuNeutrinoNucleusProcess.cc
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 //
27 // Geant4 Hadron Elastic Scattering Process
28 //
29 // Created from G4HadronElasticProcess
30 //
31 // Modified:
32 //
33 // 2.2.19 V.Grichine - PostStepDoIt implementation
34 // 24.04.19 V. Grichine - G4Region name and optionally total cross section biased in the region only.
35 
36 #include <iostream>
37 #include <typeinfo>
38 
40 #include "G4SystemOfUnits.hh"
41 #include "G4Nucleus.hh"
42 #include "G4ProcessManager.hh"
44 #include "G4HadronElasticDataSet.hh" //???
45 #include "G4ProductionCutsTable.hh"
46 #include "G4HadronicException.hh"
47 #include "G4HadronicDeprecate.hh"
48 #include "G4HadronicInteraction.hh"
49 #include "G4VCrossSectionRatio.hh"
50 #include "G4VDiscreteProcess.hh"
51 
53 //#include "G4NuMuNucleusCcModel.hh"
54 //#include "G4NuMuNucleusNcModel.hh"
55 
56 #include "G4RotationMatrix.hh"
57 #include "G4ThreeVector.hh"
58 #include "G4AffineTransform.hh"
59 #include "G4DynamicParticle.hh"
60 #include "G4StepPoint.hh"
61 #include "G4VSolid.hh"
62 #include "G4LogicalVolume.hh"
63 #include "G4SafetyHelper.hh"
65 
67 
68 
70  : G4HadronicProcess( pName, fHadronInelastic ), isInitialised(false), fBiased(true) // fHadronElastic???
71 {
72  // AddDataSet(new G4HadronElasticDataSet); //???
73  lowestEnergy = 1.*keV;
74  fEnvelope = nullptr;
75  fEnvelopeName = anEnvelopeName;
76  fTotXsc = nullptr; // new G4MuNeutrinoNucleusTotXsc();
77  fNuNuclCcBias=1.;
78  fNuNuclNcBias=1.;
82 }
83 
85 {
86  if( fTotXsc ) delete fTotXsc;
87 }
88 
90 
92 {
93  fNuNuclTotXscBias = bf;
94 
97 }
98 
100 
102 {
103  fNuNuclCcBias=bfCc;
104  fNuNuclNcBias=bfNc;
105 
107  // fTotXsc->SetBiasingFactors(bfCc, bfNc);
108 }
109 
111 
114 {
115  //G4cout << "GetMeanFreePath " << aTrack.GetDefinition()->GetParticleName()
116  // << " Ekin= " << aTrack.GetKineticEnergy() << G4endl;
118  G4double totxsc(0.);
119  try
120  {
121  if( rName == fEnvelopeName && fNuNuclTotXscBias > 1.)
122  {
123  totxsc = fNuNuclTotXscBias*
125  aTrack.GetMaterial());
126  }
127  else
128  {
130  aTrack.GetMaterial());
131  }
132  }
133  catch(G4HadronicException & aR)
134  {
136  aR.Report(ed);
137  DumpState(aTrack,"GetMeanFreePath",ed);
138  ed << " Cross section is not available" << G4endl;
139  G4Exception("G4MuNeutrinoNucleusProcess::GetMeanFreePath", "had002", FatalException,
140  ed);
141  }
142  G4double res = (totxsc>0.0) ? 1.0/totxsc : DBL_MAX;
143  //G4cout << " xsection= " << totxsc << G4endl;
144  return res;
145 }
146 
148 
149 void G4MuNeutrinoNucleusProcess::ProcessDescription(std::ostream& outFile) const
150 {
151 
152  outFile << "G4MuNeutrinoNucleusProcess handles the scattering of \n"
153  << "neutrino on electrons by invoking the following model(s) and \n"
154  << "cross section(s).\n";
155 
156 }
157 
159 
162 {
163  // track.GetVolume()->GetLogicalVolume()->GetName()
164  // if( track.GetVolume()->GetLogicalVolume() != fEnvelope )
165 
167 
168  if( rName != fEnvelopeName )
169  {
170  if( verboseLevel > 0 )
171  {
172  G4cout<<"Go out from G4MuNeutrinoNucleusProcess::PostStepDoIt: wrong volume "<<G4endl;
173  }
174  return G4VDiscreteProcess::PostStepDoIt( track, step );
175  }
177  theTotalResult->Initialize(track);
178  G4double weight = track.GetWeight();
179  theTotalResult->ProposeWeight(weight);
180 
181  if( track.GetTrackStatus() != fAlive )
182  {
183  return theTotalResult;
184  }
185  // Next check for illegal track status
186  //
187  if (track.GetTrackStatus() != fAlive &&
188  track.GetTrackStatus() != fSuspend)
189  {
190  if (track.GetTrackStatus() == fStopAndKill ||
193  {
195  ed << "G4HadronicProcess: track in unusable state - "
196  << track.GetTrackStatus() << G4endl;
197  ed << "G4HadronicProcess: returning unchanged track " << G4endl;
198  DumpState(track,"PostStepDoIt",ed);
199  G4Exception("G4HadronicProcess::PostStepDoIt", "had004", JustWarning, ed);
200  }
201  // No warning for fStopButAlive which is a legal status here
202  return theTotalResult;
203  }
204 
205  // For elastic scattering, _any_ result is considered an interaction
207 
208  G4double kineticEnergy = track.GetKineticEnergy();
209  const G4DynamicParticle* dynParticle = track.GetDynamicParticle();
210  const G4ParticleDefinition* part = dynParticle->GetDefinition();
211 
212  // NOTE: Very low energy scatters were causing numerical (FPE) errors
213  // in earlier releases; these limits have not been changed since.
214 
215  if ( kineticEnergy <= lowestEnergy ) return theTotalResult;
216 
217  const G4Material* material = track.GetMaterial();
218  G4Nucleus* targNucleus = GetTargetNucleusPointer();
219 
221 
222  const G4StepPoint* pPostStepPoint = step.GetPostStepPoint();
223  const G4DynamicParticle* aParticle = track.GetDynamicParticle();
224  G4ThreeVector position = pPostStepPoint->GetPosition(), newPosition=position;
225  G4ParticleMomentum direction = aParticle->GetMomentumDirection();
226  G4double startTime = pPostStepPoint->GetGlobalTime();
227 
228 
229  if( fNuNuclCcBias > 1.0 || fNuNuclNcBias > 1.0) // = true, if fBiasingfactor != 1., i.e. xsc is biased
230  {
231  const G4RotationMatrix* rotM = pPostStepPoint->GetTouchable()->GetRotation();
232  G4ThreeVector transl = pPostStepPoint->GetTouchable()->GetTranslation();
234  transform.Invert();
235 
236  G4ThreeVector localP = transform.TransformPoint(position);
237  G4ThreeVector localV = transform.TransformAxis(direction);
238 
239  G4double forward = track.GetVolume()->GetLogicalVolume()->GetSolid()->DistanceToOut(localP, localV);
240  G4double backward = track.GetVolume()->GetLogicalVolume()->GetSolid()->DistanceToOut(localP, -localV);
241 
242  G4double distance = forward+backward;
243 
244  // G4cout<<distance/cm<<", ";
245 
246  // uniform sampling of nu-e interaction point
247  // along neutrino direction in current volume
248 
249  G4double range = -backward+G4UniformRand()*distance;
250 
251  G4double delta = range - backward;
252 
253  startTime += delta/track.GetVelocity();
254 
255  newPosition = position + range*direction;
256 
257  safetyHelper->ReLocateWithinVolume(newPosition);
258 
259  theTotalResult->ProposePosition(newPosition); // G4Exception : GeomNav1002
260  // theTotalResult->ProposeGlobalTime(startTime); // time is updated for 'elastic' only
261  }
262  G4HadProjectile theProj( track );
263  G4HadronicInteraction* hadi = nullptr;
264  G4HadFinalState* result = nullptr;
265 
266  // Select element
267  const G4Element* elm = nullptr;
268  G4int ZZ=1;
269 
270  try
271  {
272  elm = GetCrossSectionDataStore()->SampleZandA(dynParticle, material,
273  *targNucleus);
274  }
275  catch( G4HadronicException & aR )
276  {
278  aR.Report(ed);
279  DumpState(track,"SampleZandA",ed);
280  ed << " PostStepDoIt failed on element selection" << G4endl;
281  G4Exception("G4MuNeutrinoNucleusProcess::PostStepDoIt", "had003",
282  FatalException, ed);
283  }
284  if( elm ) ZZ = elm->GetZ();
285 
286  G4double xsc = fTotXsc->GetElementCrossSection(dynParticle, ZZ, material);
287  xsc *= 1.;
288  G4double ccTotRatio = fTotXsc->GetCcTotRatio();
289 
290  if( G4UniformRand() < ccTotRatio ) // Cc-model
291  {
292  // Initialize the hadronic projectile from the track
293  thePro.Initialise(track);
294 
295  hadi = (GetHadronicInteractionList())[0];
296 
297  result = hadi->ApplyYourself( thePro, *targNucleus);
298 
300 
302 
303  FillResult(result, track);
304  }
305  else // Nc-model
306  {
307 
308  hadi = (GetHadronicInteractionList())[1];
309 
310  size_t idx = track.GetMaterialCutsCouple()->GetIndex();
311 
313 
314  hadi->SetRecoilEnergyThreshold(tcut);
315 
316  if( verboseLevel > 1 )
317  {
318  G4cout << "G4MuNeutrinoNucleusProcess::PostStepDoIt for "
319  << part->GetParticleName()
320  << " in " << material->GetName()
321  << " Target Z= " << targNucleus->GetZ_asInt()
322  << " A= " << targNucleus->GetA_asInt() << G4endl;
323  }
324  try
325  {
326  result = hadi->ApplyYourself( theProj, *targNucleus);
327  }
328  catch(G4HadronicException & aR)
329  {
331  aR.Report(ed);
332  ed << "Call for " << hadi->GetModelName() << G4endl;
333  ed << "Target element "<< elm->GetName()<<" Z= "
334  << targNucleus->GetZ_asInt()
335  << " A= " << targNucleus->GetA_asInt() << G4endl;
336  DumpState(track,"ApplyYourself",ed);
337  ed << " ApplyYourself failed" << G4endl;
338  G4Exception("G4MuNeutrinoNucleusProcess::PostStepDoIt", "had006",
339  FatalException, ed);
340  }
341  // directions
342 
343  G4ThreeVector indir = track.GetMomentumDirection();
345  G4ThreeVector it(0., 0., 1.);
346  G4ThreeVector outdir = result->GetMomentumChange();
347 
348  if(verboseLevel>1)
349  {
350  G4cout << "Efin= " << result->GetEnergyChange()
351  << " de= " << result->GetLocalEnergyDeposit()
352  << " nsec= " << result->GetNumberOfSecondaries()
353  << " dir= " << outdir
354  << G4endl;
355  }
356  // energies
357 
358  G4double edep = result->GetLocalEnergyDeposit();
359  G4double efinal = result->GetEnergyChange();
360 
361  if(efinal < 0.0) { efinal = 0.0; }
362  if(edep < 0.0) { edep = 0.0; }
363 
364  // NOTE: Very low energy scatters were causing numerical (FPE) errors
365  // in earlier releases; these limits have not been changed since.
366 
367  if(efinal <= lowestEnergy)
368  {
369  edep += efinal;
370  efinal = 0.0;
371  }
372  // primary change
373 
374  theTotalResult->ProposeEnergy(efinal);
375 
376  G4TrackStatus status = track.GetTrackStatus();
377 
378  if(efinal > 0.0)
379  {
380  outdir.rotate(phi, it);
381  outdir.rotateUz(indir);
383  }
384  else
385  {
386  if( part->GetProcessManager()->GetAtRestProcessVector()->size() > 0)
387  {
388  status = fStopButAlive;
389  }
390  else
391  {
392  status = fStopAndKill;
393  }
395  }
396  //G4cout << "Efinal= " << efinal << " TrackStatus= " << status << G4endl;
397 
399 
400  // recoil
401 
402  if( result->GetNumberOfSecondaries() > 0 )
403  {
404  G4DynamicParticle* p = result->GetSecondary(0)->GetParticle();
405 
406  if(p->GetKineticEnergy() > tcut)
407  {
410 
411  // G4cout << "recoil " << pdir << G4endl;
413 
414  pdir.rotate(phi, it);
415  pdir.rotateUz(indir);
416 
417  // G4cout << "recoil rotated " << pdir << G4endl;
418 
419  p->SetMomentumDirection(pdir);
420 
421  // in elastic scattering time and weight are not changed
422 
423  G4Track* t = new G4Track(p, track.GetGlobalTime(),
424  track.GetPosition());
425  t->SetWeight(weight);
428  }
429  else
430  {
431  edep += p->GetKineticEnergy();
432  delete p;
433  }
434  }
437  result->Clear();
438  }
439  return theTotalResult;
440 }
441 
442 void
444 {
445  if(!isInitialised) {
446  isInitialised = true;
447  if(G4Neutron::Neutron() == &part) { lowestEnergy = 1.e-6*eV; }
448  }
450 }
451 
452 void
454 {
455  lowestEnergy = val;
456 }
457