ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4VEmProcess.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4VEmProcess.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 //
28 // GEANT4 Class file
29 //
30 //
31 // File name: G4VEmProcess
32 //
33 // Author: Vladimir Ivanchenko on base of Laszlo Urban code
34 //
35 // Creation date: 01.10.2003
36 //
37 // Modifications: by V.Ivanchenko
38 //
39 // Class Description: based class for discrete and rest/discrete EM processes
40 //
41 
42 // -------------------------------------------------------------------
43 //
44 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
45 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
46 
47 #include "G4VEmProcess.hh"
48 #include "G4PhysicalConstants.hh"
49 #include "G4SystemOfUnits.hh"
50 #include "G4ProcessManager.hh"
51 #include "G4LossTableManager.hh"
52 #include "G4LossTableBuilder.hh"
53 #include "G4Step.hh"
54 #include "G4ParticleDefinition.hh"
55 #include "G4VEmModel.hh"
56 #include "G4DataVector.hh"
57 #include "G4PhysicsTable.hh"
58 #include "G4EmDataHandler.hh"
59 #include "G4PhysicsLogVector.hh"
60 #include "G4VParticleChange.hh"
61 #include "G4ProductionCutsTable.hh"
62 #include "G4Region.hh"
63 #include "G4Gamma.hh"
64 #include "G4Electron.hh"
65 #include "G4Positron.hh"
66 #include "G4PhysicsTableHelper.hh"
67 #include "G4EmBiasingManager.hh"
68 #include "G4GenericIon.hh"
69 #include "G4Log.hh"
70 #include <iostream>
71 
72 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
73 
75  G4VDiscreteProcess(name, type),
76  secondaryParticle(nullptr),
77  buildLambdaTable(true),
78  numberOfModels(0),
79  theLambdaTable(nullptr),
80  theLambdaTablePrim(nullptr),
81  integral(false),
82  applyCuts(false),
83  startFromNull(false),
84  splineFlag(true),
85  isIon(false),
86  currentCouple(nullptr),
87  isTheMaster(true),
88  masterProc(nullptr),
89  theData(nullptr),
90  currentModel(nullptr),
91  particle(nullptr),
92  currentParticle(nullptr)
93 {
95  SetVerboseLevel(1);
96 
97  // Size of tables assuming spline
98  minKinEnergy = 0.1*keV;
99  maxKinEnergy = 100.0*TeV;
100  nLambdaBins = 84;
103 
104  // default lambda factor
105  lambdaFactor = 0.8;
107 
108  // default limit on polar angle
109  biasFactor = fFactor = 1.0;
110 
111  // particle types
115 
117 
120  secParticles.reserve(5);
121 
122  baseMaterial = currentMaterial = nullptr;
123 
127  massRatio = 1.0;
128 
130 
132  biasManager = nullptr;
133  biasFlag = false;
134  weightFlag = false;
136  lManager->Register(this);
140 
141  secID = fluoID = augerID = biasID = -1;
142  mainSecondaries = 100;
143  if("phot" == GetProcessName() || "compt" == GetProcessName()
144  || "e-_G4DNAIonisation" == GetProcessName()
145  || "hydrogen_G4DNAIonisation" == GetProcessName()
146  || "helium_G4DNAIonisation" == GetProcessName()
147  || "alpha_G4DNAIonisation" == GetProcessName()
148  || "alpha+_G4DNAIonisation" == GetProcessName()
149  || "proton_G4DNAIonisation" == GetProcessName()
150  || "GenericIon_G4DNAIonisation" == GetProcessName() )
151  {
152  mainSecondaries = 1;
153  }
154 }
155 
156 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
157 
159 {
160  /*
161  if(1 < verboseLevel) {
162  G4cout << "G4VEmProcess destruct " << GetProcessName()
163  << " " << this << " " << theLambdaTable <<G4endl;
164  }
165  */
166  if(isTheMaster) {
167  delete theData;
168  theData = nullptr;
169  }
170  delete modelManager;
171  delete biasManager;
172  lManager->DeRegister(this);
173  //std::cout << "G4VEmProcess removed " << GetProcessName() << G4endl;
174 }
175 
176 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
177 
179 {
180  currentCouple = nullptr;
181  preStepLambda = 0.0;
182  idxLambda = idxLambdaPrim = 0;
183 }
184 
185 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
186 
188  const G4Material*)
189 {
190  return 0.0;
191 }
192 
193 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
194 
196  const G4Region* region)
197 {
198  G4VEmFluctuationModel* fm = nullptr;
199  modelManager->AddEmModel(order, p, fm, region);
200  if(p) { p->SetParticleChange(pParticleChange); }
201 }
202 
203 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
204 
206 {
207  for(auto & em : emModels) { if(em == ptr) { return; } }
208  emModels.push_back(ptr);
209 }
210 
211 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
212 
213 G4VEmModel* G4VEmProcess::EmModel(size_t index) const
214 {
215  return (index < emModels.size()) ? emModels[index] : nullptr;
216 }
217 
218 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
219 
222 {
223  modelManager->UpdateEmModel(nam, emin, emax);
224 }
225 
226 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
227 
229 {
230  return modelManager->NumberOfModels();
231 }
232 
233 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
234 
236 {
237  return modelManager->NumberOfRegionModels(couple_index);
238 }
239 
240 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
241 
242 G4VEmModel* G4VEmProcess::GetRegionModel(G4int idx, size_t couple_index) const
243 {
244  return modelManager->GetRegionModel(idx, couple_index);
245 }
246 
247 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
248 
250 {
251  return modelManager->GetModel(idx, ver);
252 }
253 
254 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
255 
257 {
259 
260  if(!particle) { SetParticle(&part); }
261 
262  if(part.GetParticleType() == "nucleus" &&
263  part.GetParticleSubType() == "generic") {
264 
265  G4String pname = part.GetParticleName();
266  if(pname != "deuteron" && pname != "triton" &&
267  pname != "alpha" && pname != "He3" &&
268  pname != "alpha+" && pname != "helium" &&
269  pname != "hydrogen") {
270 
272  isIon = true;
273  }
274  }
275 
276  if(1 < verboseLevel) {
277  G4cout << "G4VEmProcess::PreparePhysicsTable() for "
278  << GetProcessName()
279  << " and particle " << part.GetParticleName()
280  << " local particle " << particle->GetParticleName()
281  << G4endl;
282  }
283 
284  if(particle != &part) { return; }
285 
287 
289 
290  Clear();
292 
293  const G4ProductionCutsTable* theCoupleTable=
295  size_t n = theCoupleTable->GetTableSize();
296 
297  theEnergyOfCrossSectionMax.resize(n, 0.0);
298  theCrossSectionMax.resize(n, DBL_MAX);
299 
300  // initialisation of the process
304 
305  if(isTheMaster) {
307  if(!theData) { theData = new G4EmDataHandler(2); }
308  } else {
310  }
315 
316  // initialisation of models
318  for(G4int i=0; i<numberOfModels; ++i) {
319  G4VEmModel* mod = modelManager->GetModel(i);
320  if(0 == i) { currentModel = mod; }
323  if(mod->HighEnergyLimit() > maxKinEnergy) {
325  }
326  }
327 
330  2.,verboseLevel);
334 
335  // prepare tables
339  }
340  // high energy table
344  }
346  // forced biasing
347  if(biasManager) {
349  biasFlag = false;
350  }
351  // defined ID of secondary particles
352  G4String nam1 = GetProcessName();
354  if(100 > mainSecondaries) {
355  G4String nam2 = nam1 + "_fluo" ;
356  G4String nam3 = nam1 + "_auger";
357  G4String nam4 = nam1 + "_split";
361  }
362 }
363 
364 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
365 
367 {
368  if(!masterProc) {
369  if(isTheMaster) { masterProc = this; }
370  else { masterProc = static_cast<const G4VEmProcess*>(GetMasterProcess());}
371  }
372 
373  G4String num = part.GetParticleName();
374  if(1 < verboseLevel) {
375  G4cout << "### G4VEmProcess::BuildPhysicsTable() for "
376  << GetProcessName()
377  << " and particle " << num
378  << " buildLambdaTable= " << buildLambdaTable
379  << " isTheMaster= " << isTheMaster
380  << " " << masterProc
381  << G4endl;
382  }
383 
384  if(particle == &part) {
385 
386  // worker initialisation
387  if(!isTheMaster) {
390 
391  if(theLambdaTable) { FindLambdaMax(); }
392 
393  // local initialisation of models
394  G4bool printing = true;
396  for(G4int i=0; i<numberOfModels; ++i) {
397  G4VEmModel* mod = GetModelByIndex(i, printing);
398  G4VEmModel* mod0= masterProc->GetModelByIndex(i, printing);
399  //G4cout << i << ". " << mod << " " << mod0 << " "
400  // << particle->GetParticleName() << G4endl;
401  mod->InitialiseLocal(particle, mod0);
402  }
403  // master thread
404  } else {
407  }
408  }
409  }
410 
411  // explicitly defined printout by particle name
412  if(1 < verboseLevel ||
413  (0 < verboseLevel && (num == "gamma" || num == "e-" ||
414  num == "e+" || num == "mu+" ||
415  num == "mu-" || num == "proton"||
416  num == "pi+" || num == "pi-" ||
417  num == "kaon+" || num == "kaon-" ||
418  num == "alpha" || num == "anti_proton" ||
419  num == "GenericIon"|| num == "alpha++" ||
420  num == "alpha+" || num == "helium" ||
421  num == "hydrogen")))
422  {
423  StreamInfo(G4cout, part);
424  }
425 
426  if(1 < verboseLevel) {
427  G4cout << "### G4VEmProcess::BuildPhysicsTable() done for "
428  << GetProcessName()
429  << " and particle " << num
430  << G4endl;
431  }
432 }
433 
434 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
435 
437 {
438  if(1 < verboseLevel) {
439  G4cout << "G4EmProcess::BuildLambdaTable() for process "
440  << GetProcessName() << " and particle "
441  << particle->GetParticleName() << " " << this
442  << G4endl;
443  }
444 
445  // Access to materials
446  const G4ProductionCutsTable* theCoupleTable=
448  size_t numOfCouples = theCoupleTable->GetTableSize();
449 
451 
452  G4PhysicsLogVector* aVector = nullptr;
453  G4PhysicsLogVector* aVectorPrim = nullptr;
454  G4PhysicsLogVector* bVectorPrim = nullptr;
455 
457  G4int nbin =
458  theParameters->NumberOfBinsPerDecade()*G4lrint(std::log10(scale));
459  scale = G4Log(scale);
460  if(actBinning) { nbin = std::max(nbin, nLambdaBins); }
462 
463  for(size_t i=0; i<numOfCouples; ++i) {
464 
465  if (bld->GetFlag(i)) {
466 
467  // create physics vector and fill it
468  const G4MaterialCutsCouple* couple =
469  theCoupleTable->GetMaterialCutsCouple(i);
470 
471  // build main table
472  if(buildLambdaTable) {
473  delete (*theLambdaTable)[i];
474 
475  // if start from zero then change the scale
477  G4bool startNull = false;
478  if(startFromNull) {
480  if(e >= emin) {
481  emin = e;
482  startNull = true;
483  }
484  }
485  G4double emax = emax1;
486  if(emax <= emin) { emax = 2*emin; }
487  G4int bin = G4lrint(nbin*G4Log(emax/emin)/scale);
488  if(bin < 3) { bin = 3; }
489  aVector = new G4PhysicsLogVector(emin, emax, bin);
490  aVector->SetSpline(splineFlag);
491  modelManager->FillLambdaVector(aVector, couple, startNull);
492  if(splineFlag) { aVector->FillSecondDerivatives(); }
494  }
495  // build high energy table
497  delete (*theLambdaTablePrim)[i];
498 
499  // start not from zero
500  if(!bVectorPrim) {
502  if(bin < 3) { bin = 3; }
503  aVectorPrim =
505  bVectorPrim = aVectorPrim;
506  } else {
507  aVectorPrim = new G4PhysicsLogVector(*bVectorPrim);
508  }
509  // always use spline
510  aVectorPrim->SetSpline(splineFlag);
511  modelManager->FillLambdaVector(aVectorPrim, couple, false,
513  aVectorPrim->FillSecondDerivatives();
515  aVectorPrim);
516  }
517  }
518  }
519 
521 
522  if(1 < verboseLevel) {
523  G4cout << "Lambda table is built for "
525  << G4endl;
526  }
527 }
528 
529 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
530 
531 void G4VEmProcess::StreamInfo(std::ostream& out,
532  const G4ParticleDefinition& part, G4bool rst) const
533 {
534  G4String indent = (rst ? " " : "");
535  out << std::setprecision(6);
536  out << G4endl << indent << GetProcessName() << ": ";
537  if (!rst) {
538  out << " for " << part.GetParticleName();
539  if (integral) { out << ","; }
540  }
541  if(integral) { out << " integral:1 "; }
542  if(applyCuts) { out << " applyCuts:1 "; }
543  out << " SubType=" << GetProcessSubType();
544  if(biasFactor != 1.0) { out << " BiasingFactor= " << biasFactor; }
545  out << " BuildTable=" << buildLambdaTable << G4endl;
546  if(buildLambdaTable) {
547  if(particle == &part) {
548  size_t length = theLambdaTable->length();
549  for(size_t i=0; i<length; ++i) {
550  G4PhysicsVector* v = (*theLambdaTable)[i];
551  if(v) {
552  out << " Lambda table from ";
553  G4double emin = v->Energy(0);
554  G4double emax = v->GetMaxEnergy();
555  G4int nbin = v->GetVectorLength() - 1;
556  if(emin > minKinEnergy) { out << "threshold "; }
557  else { out << G4BestUnit(emin,"Energy"); }
558  out << " to "
559  << G4BestUnit(emax,"Energy")
560  << ", " << G4lrint(nbin/std::log10(emax/emin))
561  << " bins/decade, spline: "
562  << splineFlag << G4endl;
563  break;
564  }
565  }
566  } else {
567  out << " Used Lambda table of "
569  }
570  }
572  if(particle == &part) {
573  size_t length = theLambdaTablePrim->length();
574  for(size_t i=0; i<length; ++i) {
575  G4PhysicsVector* v = (*theLambdaTablePrim)[i];
576  if(v) {
577  out << " LambdaPrime table from "
578  << G4BestUnit(v->Energy(0),"Energy")
579  << " to "
580  << G4BestUnit(v->GetMaxEnergy(),"Energy")
581  << " in " << v->GetVectorLength()-1
582  << " bins " << G4endl;
583  break;
584  }
585  }
586  } else {
587  out << " Used LambdaPrime table of "
589  }
590  }
591  StreamProcessInfo(out);
593 
594  if(verboseLevel > 2 && buildLambdaTable) {
595  out << " LambdaTable address= " << theLambdaTable << G4endl;
596  if(theLambdaTable && particle == &part) {
597  out << (*theLambdaTable) << G4endl;
598  }
599  }
600 }
601 
602 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
603 
605 {
606  // reset parameters for the new track
611 
612  // forced biasing only for primary particles
613  if(biasManager) {
614  if(0 == track->GetParentID()) {
615  // primary particle
616  biasFlag = true;
618  }
619  }
620 }
621 
622 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
623 
625  const G4Track& track,
626  G4double previousStepSize,
628 {
629  *condition = NotForced;
630  G4double x = DBL_MAX;
631 
635  G4double scaledEnergy = preStepKinEnergy*massRatio;
636  SelectModel(scaledEnergy, currentCoupleIndex);
637 
638  if(!currentModel->IsActive(scaledEnergy)) {
641  return x;
642  }
643 
644  // forced biasing only for primary particles
645  if(biasManager) {
646  if(0 == track.GetParentID()) {
647  if(biasFlag &&
649  return biasManager->GetStepLimit(currentCoupleIndex, previousStepSize);
650  }
651  }
652  }
653 
654  // compute mean free path
655  if(preStepKinEnergy < mfpKinEnergy) {
656  if (integral) {
657  ComputeIntegralLambda(preStepKinEnergy, preStepLogKinEnergy);
658  } else {
660  }
661 
662  // zero cross section
663  if(preStepLambda <= 0.0) {
666  }
667  }
668 
669  // non-zero cross section
670  if(preStepLambda > 0.0) {
671 
673 
674  // beggining of tracking (or just after DoIt of this process)
677 
678  } else if(currentInteractionLength < DBL_MAX) {
679 
681  previousStepSize/currentInteractionLength;
684  }
685 
686  // new mean free path and step limit for the next step
689  }
690  return x;
691 }
692 
693 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
694 
696 {
697  // condition to skip recomputation of cross section
699  if(e <= epeak && e/lambdaFactor >= mfpKinEnergy) { return; }
700 
701  // recomputation is needed
702  if (e <= epeak) {
703  preStepLambda = GetCurrentLambda(e, loge);
704  mfpKinEnergy = e;
705  } else {
706  const G4double e1 = e*lambdaFactor;
707  if (e1 > epeak) {
708  preStepLambda = GetCurrentLambda(e, loge);
709  mfpKinEnergy = e;
710  const G4double preStepLambda1 = GetCurrentLambda(e1,loge+logLambdaFactor);
711  if (preStepLambda1 > preStepLambda) {
712  mfpKinEnergy = e1;
713  preStepLambda = preStepLambda1;
714  }
715  } else {
717  mfpKinEnergy = epeak;
718  }
719  }
720 }
721 
722 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
723 
725  const G4Step& step)
726 {
727  // In all cases clear number of interaction lengths
730 
732 
733  // Do not make anything if particle is stopped, the annihilation then
734  // should be performed by the AtRestDoIt!
735  if (track.GetTrackStatus() == fStopButAlive) { return &fParticleChange; }
736 
737  const G4double finalT = track.GetKineticEnergy();
738  const G4double logFinalT = track.GetDynamicParticle()->GetLogKineticEnergy();
739 
740  // forced process - should happen only once per track
741  if(biasFlag) {
743  biasFlag = false;
744  }
745  }
746 
747  // Integral approach
748  if (integral) {
749  G4double lx = GetLambda(finalT, currentCouple, logFinalT);
750  if(preStepLambda<lx && 1 < verboseLevel) {
751  G4cout << "WARNING: for " << currentParticle->GetParticleName()
752  << " and " << GetProcessName()
753  << " E(MeV)= " << finalT/MeV
754  << " preLambda= " << preStepLambda << " < "
755  << lx << " (postLambda) "
756  << G4endl;
757  }
758 
759  if(preStepLambda*G4UniformRand() > lx) {
761  return &fParticleChange;
762  }
763  }
764 
765  G4double scaledEnergy = finalT*massRatio;
766  SelectModel(scaledEnergy, currentCoupleIndex);
767  if(!currentModel->IsActive(scaledEnergy)) { return &fParticleChange; }
768 
769  // define new weight for primary and secondaries
771  if(weightFlag) {
772  weight /= biasFactor;
774  }
775 
776  /*
777  if(0 < verboseLevel) {
778  G4cout << "G4VEmProcess::PostStepDoIt: Sample secondary; E= "
779  << finalT/MeV
780  << " MeV; model= (" << currentModel->LowEnergyLimit()
781  << ", " << currentModel->HighEnergyLimit() << ")"
782  << G4endl;
783  }
784  */
785 
786  // sample secondaries
787  secParticles.clear();
789  currentCouple,
790  track.GetDynamicParticle(),
791  (*theCuts)[currentCoupleIndex]);
792 
793  G4int num0 = secParticles.size();
794 
795  // splitting or Russian roulette
796  if(biasManager) {
798  G4double eloss = 0.0;
800  secParticles, track, currentModel, &fParticleChange, eloss,
802  step.GetPostStepPoint()->GetSafety());
803  if(eloss > 0.0) {
806  }
807  }
808  }
809 
810  // save secondaries
811  G4int num = secParticles.size();
812  if(num > 0) {
813 
816  G4double time = track.GetGlobalTime();
817 
818  for (G4int i=0; i<num; ++i) {
819  if (secParticles[i]) {
822  G4double e = dp->GetKineticEnergy();
823  G4bool good = true;
824  if(applyCuts) {
825  if (p == theGamma) {
826  if (e < (*theCutsGamma)[currentCoupleIndex]) { good = false; }
827 
828  } else if (p == theElectron) {
829  if (e < (*theCutsElectron)[currentCoupleIndex]) { good = false; }
830 
831  } else if (p == thePositron) {
834  good = false;
835  e += 2.0*electron_mass_c2;
836  }
837  }
838  // added secondary if it is good
839  }
840  if (good) {
841  G4Track* t = new G4Track(dp, time, track.GetPosition());
843  if (biasManager) {
844  t->SetWeight(weight * biasManager->GetWeight(i));
845  } else {
846  t->SetWeight(weight);
847  }
849 
850  // define type of secondary
852  else if(i < num0) {
853  if(p == theGamma) {
855  } else {
857  }
858  } else {
860  }
861  /*
862  G4cout << "Secondary(post step) has weight " << t->GetWeight()
863  << ", Ekin= " << t->GetKineticEnergy()/MeV << " MeV "
864  << GetProcessName() << " fluoID= " << fluoID
865  << " augerID= " << augerID <<G4endl;
866  */
867  } else {
868  delete dp;
869  edep += e;
870  }
871  }
872  }
874  }
875 
881  }
882 
883  return &fParticleChange;
884 }
885 
886 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
887 
889  const G4String& directory,
890  G4bool ascii)
891 {
892  G4bool yes = true;
893  if(!isTheMaster) { return yes; }
894 
895  if ( theLambdaTable && part == particle) {
896  const G4String& nam =
897  GetPhysicsTableFileName(part,directory,"Lambda",ascii);
898  yes = theLambdaTable->StorePhysicsTable(nam,ascii);
899 
900  if ( yes ) {
901  G4cout << "Physics table is stored for " << particle->GetParticleName()
902  << " and process " << GetProcessName()
903  << " in the directory <" << directory
904  << "> " << G4endl;
905  } else {
906  G4cout << "Fail to store Physics Table for "
908  << " and process " << GetProcessName()
909  << " in the directory <" << directory
910  << "> " << G4endl;
911  }
912  }
913  if ( theLambdaTablePrim && part == particle) {
914  const G4String& name =
915  GetPhysicsTableFileName(part,directory,"LambdaPrim",ascii);
916  yes = theLambdaTablePrim->StorePhysicsTable(name,ascii);
917 
918  if ( yes ) {
919  G4cout << "Physics table prim is stored for "
921  << " and process " << GetProcessName()
922  << " in the directory <" << directory
923  << "> " << G4endl;
924  } else {
925  G4cout << "Fail to store Physics Table Prim for "
927  << " and process " << GetProcessName()
928  << " in the directory <" << directory
929  << "> " << G4endl;
930  }
931  }
932  return yes;
933 }
934 
935 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
936 
938  const G4String& directory,
939  G4bool ascii)
940 {
941  if(1 < verboseLevel) {
942  G4cout << "G4VEmProcess::RetrievePhysicsTable() for "
943  << part->GetParticleName() << " and process "
944  << GetProcessName() << G4endl;
945  }
946  G4bool yes = true;
947 
949  || particle != part) { return yes; }
950 
951  const G4String particleName = part->GetParticleName();
952 
953  if(buildLambdaTable) {
954  const G4String& filename =
955  GetPhysicsTableFileName(part,directory,"Lambda",ascii);
957  filename,ascii);
958  if ( yes ) {
959  if (0 < verboseLevel) {
960  G4cout << "Lambda table for " << particleName
961  << " is Retrieved from <"
962  << filename << ">"
963  << G4endl;
964  }
965  if(theParameters->Spline()) {
966  size_t n = theLambdaTable->length();
967  for(size_t i=0; i<n; ++i) {
968  if((* theLambdaTable)[i]) {
969  (* theLambdaTable)[i]->SetSpline(true);
970  }
971  }
972  }
973  } else {
974  if (1 < verboseLevel) {
975  G4cout << "Lambda table for " << particleName << " in file <"
976  << filename << "> is not exist"
977  << G4endl;
978  }
979  }
980  }
982  const G4String& filename =
983  GetPhysicsTableFileName(part,directory,"LambdaPrim",ascii);
985  filename,ascii);
986  if ( yes ) {
987  if (0 < verboseLevel) {
988  G4cout << "Lambda table prim for " << particleName
989  << " is Retrieved from <"
990  << filename << ">"
991  << G4endl;
992  }
993  if(theParameters->Spline()) {
994  size_t n = theLambdaTablePrim->length();
995  for(size_t i=0; i<n; ++i) {
996  if((* theLambdaTablePrim)[i]) {
997  (* theLambdaTablePrim)[i]->SetSpline(true);
998  }
999  }
1000  }
1001  } else {
1002  if (1 < verboseLevel) {
1003  G4cout << "Lambda table prim for " << particleName << " in file <"
1004  << filename << "> is not exist"
1005  << G4endl;
1006  }
1007  }
1008  }
1009  return yes;
1010 }
1011 
1012 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1013 
1014 G4double
1016  const G4MaterialCutsCouple* couple)
1017 {
1018  // Cross section per atom is calculated
1019  DefineMaterial(couple);
1020  G4double cross = 0.0;
1021  if(buildLambdaTable) {
1022  cross = GetCurrentLambda(kineticEnergy);
1023  } else {
1024  SelectModel(kineticEnergy, currentCoupleIndex);
1025  if(currentModel) {
1028  kineticEnergy);
1029  }
1030  }
1031  return std::max(cross, 0.0);
1032 }
1033 
1034 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1035 
1037  G4double,
1039 {
1040  *condition = NotForced;
1041  return G4VEmProcess::MeanFreePath(track);
1042 }
1043 
1044 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1045 
1047 {
1048  const G4double kinEnergy = track.GetKineticEnergy();
1049  CurrentSetup(track.GetMaterialCutsCouple(), kinEnergy);
1050  const G4double xs = GetCurrentLambda(kinEnergy,
1052  return (0.0 < xs) ? 1.0/xs : DBL_MAX;
1053 }
1054 
1055 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1056 
1057 G4double
1059  G4double Z, G4double A, G4double cut)
1060 {
1061  SelectModel(kinEnergy, currentCoupleIndex);
1062  return (currentModel) ?
1064  Z, A, cut) : 0.0;
1065 }
1066 
1067 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1068 
1070 {
1071  if(1 < verboseLevel) {
1072  G4cout << "### G4VEmProcess::FindLambdaMax: "
1073  << particle->GetParticleName()
1074  << " and process " << GetProcessName() << " " << G4endl;
1075  }
1076  size_t n = theLambdaTable->length();
1077  G4PhysicsVector* pv;
1078  G4double e, ss, emax, smax;
1079 
1080  size_t i;
1081 
1082  // first loop on existing vectors
1083  for (i=0; i<n; ++i) {
1084  pv = (*theLambdaTable)[i];
1085  if(pv) {
1086  size_t nb = pv->GetVectorLength();
1087  emax = DBL_MAX;
1088  smax = 0.0;
1089  if(nb > 0) {
1090  for (size_t j=0; j<nb; ++j) {
1091  e = pv->Energy(j);
1092  ss = (*pv)(j);
1093  if(ss > smax) {
1094  smax = ss;
1095  emax = e;
1096  }
1097  }
1098  }
1100  theCrossSectionMax[i] = smax;
1101  if(1 < verboseLevel) {
1102  G4cout << "For " << particle->GetParticleName()
1103  << " Max CS at i= " << i << " emax(MeV)= " << emax/MeV
1104  << " lambda= " << smax << G4endl;
1105  }
1106  }
1107  }
1108  // second loop using base materials
1109  for (i=0; i<n; ++i) {
1110  pv = (*theLambdaTable)[i];
1111  if(!pv){
1112  G4int j = (*theDensityIdx)[i];
1114  theCrossSectionMax[i] = (*theDensityFactor)[i]*theCrossSectionMax[j];
1115  }
1116  }
1117 }
1118 
1119 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1120 
1123 {
1124  G4PhysicsVector* v =
1127  return v;
1128 }
1129 
1130 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1131 
1133 {
1134  const G4Element* elm =
1135  (currentModel) ? currentModel->GetCurrentElement() : nullptr;
1136  return elm;
1137 }
1138 
1139 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1140 
1142 {
1143  if(f > 0.0) {
1144  biasFactor = f;
1145  weightFlag = flag;
1146  if(1 < verboseLevel) {
1147  G4cout << "### SetCrossSectionBiasingFactor: for "
1148  << particle->GetParticleName()
1149  << " and process " << GetProcessName()
1150  << " biasFactor= " << f << " weightFlag= " << flag
1151  << G4endl;
1152  }
1153  }
1154 }
1155 
1156 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1157 
1158 void
1160  G4bool flag)
1161 {
1162  if(!biasManager) { biasManager = new G4EmBiasingManager(); }
1163  if(1 < verboseLevel) {
1164  G4cout << "### ActivateForcedInteraction: for "
1165  << particle->GetParticleName()
1166  << " and process " << GetProcessName()
1167  << " length(mm)= " << length/mm
1168  << " in G4Region <" << r
1169  << "> weightFlag= " << flag
1170  << G4endl;
1171  }
1172  weightFlag = flag;
1174 }
1175 
1176 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1177 
1178 void
1180  G4double factor,
1181  G4double energyLimit)
1182 {
1183  if (0.0 <= factor) {
1184 
1185  // Range cut can be applied only for e-
1186  if(0.0 == factor && secondaryParticle != G4Electron::Electron())
1187  { return; }
1188 
1189  if(!biasManager) { biasManager = new G4EmBiasingManager(); }
1190  biasManager->ActivateSecondaryBiasing(region, factor, energyLimit);
1191  if(1 < verboseLevel) {
1192  G4cout << "### ActivateSecondaryBiasing: for "
1193  << " process " << GetProcessName()
1194  << " factor= " << factor
1195  << " in G4Region <" << region
1196  << "> energyLimit(MeV)= " << energyLimit/MeV
1197  << G4endl;
1198  }
1199  }
1200 }
1201 
1202 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1203 
1205 {
1206  if(5 < n && n < 10000000) {
1207  nLambdaBins = n;
1208  actBinning = true;
1209  } else {
1210  G4double e = (G4double)n;
1211  PrintWarning("SetLambdaBinning", e);
1212  }
1213 }
1214 
1215 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1216 
1218 {
1219  if(1.e-3*eV < e && e < maxKinEnergy) {
1222  minKinEnergy = e;
1223  actMinKinEnergy = true;
1224  } else { PrintWarning("SetMinKinEnergy", e); }
1225 }
1226 
1227 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1228 
1230 {
1231  if(minKinEnergy < e && e < 1.e+6*TeV) {
1234  maxKinEnergy = e;
1235  actMaxKinEnergy = true;
1236  } else { PrintWarning("SetMaxKinEnergy", e); }
1237 }
1238 
1239 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1240 
1242 {
1243  if(theParameters->MinKinEnergy() <= e &&
1244  e <= theParameters->MaxKinEnergy()) { minKinEnergyPrim = e; }
1245  else { PrintWarning("SetMinKinEnergyPrim", e); }
1246 }
1247 
1248 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1249 
1251 {
1252  return (nam == GetProcessName()) ? this : nullptr;
1253 }
1254 
1255 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1256 
1258 {
1259  G4String ss = "G4VEmProcess::" + tit;
1261  ed << "Parameter is out of range: " << val
1262  << " it will have no effect!\n" << " Process "
1263  << GetProcessName() << " nbins= " << theParameters->NumberOfBins()
1264  << " Emin(keV)= " << theParameters->MinKinEnergy()/keV
1265  << " Emax(GeV)= " << theParameters->MaxKinEnergy()/GeV;
1266  G4Exception(ss, "em0044", JustWarning, ed);
1267 }
1268 
1269 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1270 
1271 void G4VEmProcess::ProcessDescription(std::ostream& out) const
1272 {
1273  if(particle) {
1274  StreamInfo(out, *particle, true);
1275  }
1276 }
1277 
1278 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....