Geant4  10.01
G4VEmProcess.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: G4VEmProcess.cc 85424 2014-10-29 08:23:44Z gcosmo $
27 //
28 // -------------------------------------------------------------------
29 //
30 // GEANT4 Class file
31 //
32 //
33 // File name: G4VEmProcess
34 //
35 // Author: Vladimir Ivanchenko on base of Laszlo Urban code
36 //
37 // Creation date: 01.10.2003
38 //
39 // Modifications:
40 // 30-06-04 make it to be pure discrete process (V.Ivanchenko)
41 // 30-09-08 optimise integral option (V.Ivanchenko)
42 // 08-11-04 Migration to new interface of Store/Retrieve tables (V.Ivanchenko)
43 // 11-03-05 Shift verbose level by 1, add applyCuts and killPrimary flags (VI)
44 // 14-03-05 Update logic PostStepDoIt (V.Ivanchenko)
45 // 08-04-05 Major optimisation of internal interfaces (V.Ivanchenko)
46 // 18-04-05 Use G4ParticleChangeForGamma (V.Ivanchenko)
47 // 25-07-05 Add protection: integral mode only for charged particles (VI)
48 // 04-09-05 default lambdaFactor 0.8 (V.Ivanchenko)
49 // 11-01-06 add A to parameters of ComputeCrossSectionPerAtom (VI)
50 // 12-09-06 add SetModel() (mma)
51 // 12-04-07 remove double call to Clear model manager (V.Ivanchenko)
52 // 27-10-07 Virtual functions moved to source (V.Ivanchenko)
53 // 24-06-09 Removed hidden bin in G4PhysicsVector (V.Ivanchenko)
54 // 17-02-10 Added pointer currentParticle (VI)
55 // 30-05-12 allow Russian roulette, brem splitting (D. Sawkey)
56 //
57 // Class Description:
58 //
59 
60 // -------------------------------------------------------------------
61 //
62 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
63 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
64 
65 #include "G4VEmProcess.hh"
66 #include "G4PhysicalConstants.hh"
67 #include "G4SystemOfUnits.hh"
68 #include "G4ProcessManager.hh"
69 #include "G4LossTableManager.hh"
70 #include "G4LossTableBuilder.hh"
71 #include "G4Step.hh"
72 #include "G4ParticleDefinition.hh"
73 #include "G4VEmModel.hh"
74 #include "G4DataVector.hh"
75 #include "G4PhysicsTable.hh"
76 #include "G4PhysicsLogVector.hh"
77 #include "G4VParticleChange.hh"
78 #include "G4ProductionCutsTable.hh"
79 #include "G4Region.hh"
80 #include "G4Gamma.hh"
81 #include "G4Electron.hh"
82 #include "G4Positron.hh"
83 #include "G4PhysicsTableHelper.hh"
84 #include "G4EmBiasingManager.hh"
85 #include "G4GenericIon.hh"
86 #include "G4Log.hh"
87 
88 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
89 
91  G4VDiscreteProcess(name, type),
92  secondaryParticle(0),
93  buildLambdaTable(true),
94  numberOfModels(0),
95  theLambdaTable(0),
96  theLambdaTablePrim(0),
97  theDensityFactor(0),
98  theDensityIdx(0),
99  integral(false),
100  applyCuts(false),
101  startFromNull(false),
102  splineFlag(true),
103  currentModel(0),
104  particle(0),
105  currentParticle(0),
106  currentCouple(0)
107 {
109  SetVerboseLevel(1);
110 
111  // Size of tables assuming spline
112  minKinEnergy = 0.1*keV;
113  maxKinEnergy = 10.0*TeV;
114  nLambdaBins = 77;
116  actBinning = false;
117  actSpline = false;
118  actMinKinEnergy = false;
119  actMaxKinEnergy = false;
120 
121  // default lambda factor
122  lambdaFactor = 0.8;
123 
124  // default limit on polar angle
125  biasFactor = fFactor = 1.0;
126 
127  // particle types
131 
133 
136  secParticles.reserve(5);
137 
139 
142 
144  = basedCoupleIndex = 0;
145 
147  biasManager = 0;
148  biasFlag = false;
149  weightFlag = false;
151  lManager->Register(this);
152  secID = fluoID = augerID = biasID = -1;
153  mainSecondaries = 100;
154  if("phot" == GetProcessName() || "compt" == GetProcessName()) {
155  mainSecondaries = 1;
156  }
157 }
158 
159 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
160 
162 {
163  if(1 < verboseLevel) {
164  G4cout << "G4VEmProcess destruct " << GetProcessName()
165  << " " << this << " " << theLambdaTable <<G4endl;
166  }
167  if(lManager->IsMaster()) {
168  if(theLambdaTable) {
170  delete theLambdaTable;
171  }
172  if(theLambdaTablePrim) {
174  delete theLambdaTablePrim;
175  }
177  }
178  delete modelManager;
179  delete biasManager;
180  lManager->DeRegister(this);
181  //G4cout << "G4VEmProcess removed " << G4endl;
182 }
183 
184 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
185 
187 {
188  currentCouple = 0;
189  preStepLambda = 0.0;
191  idxLambda = idxLambdaPrim = 0;
192 }
193 
194 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
195 
197  const G4Material*)
198 {
199  return 0.0;
200 }
201 
202 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
203 
205  const G4Region* region)
206 {
207  G4VEmFluctuationModel* fm = 0;
208  modelManager->AddEmModel(order, p, fm, region);
209  if(p) { p->SetParticleChange(pParticleChange); }
210 }
211 
212 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
213 
215 {
216  G4int n = emModels.size();
217  if(index >= n) { for(G4int i=n; i<=index; ++i) {emModels.push_back(0);} }
218  emModels[index] = p;
219 }
220 
221 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
222 
224 {
225  G4VEmModel* p = 0;
226  if(index >= 0 && index < G4int(emModels.size())) { p = emModels[index]; }
227  return p;
228 }
229 
230 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
231 
233  G4double emin, G4double emax)
234 {
235  modelManager->UpdateEmModel(nam, emin, emax);
236 }
237 
238 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
239 
241 {
242  return modelManager->GetModel(idx, ver);
243 }
244 
245 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
246 
248 {
249  G4bool isMaster = true;
250  const G4VEmProcess* masterProcess =
251  static_cast<const G4VEmProcess*>(GetMasterProcess());
252  if(masterProcess && masterProcess != this) { isMaster = false; }
253 
254  if(!particle) { SetParticle(&part); }
255 
256  if(part.GetParticleType() == "nucleus" &&
257  part.GetParticleSubType() == "generic") {
258 
259  G4String pname = part.GetParticleName();
260  if(pname != "deuteron" && pname != "triton" &&
261  pname != "alpha" && pname != "He3" &&
262  pname != "alpha+" && pname != "helium" &&
263  pname != "hydrogen") {
264 
266  }
267  }
268 
269  if(1 < verboseLevel) {
270  G4cout << "G4VEmProcess::PreparePhysicsTable() for "
271  << GetProcessName()
272  << " and particle " << part.GetParticleName()
273  << " local particle " << particle->GetParticleName()
274  << G4endl;
275  }
276 
277  if(particle != &part) { return; }
278 
280 
281  lManager->PreparePhysicsTable(&part, this, isMaster);
282 
283  Clear();
285 
286  const G4ProductionCutsTable* theCoupleTable=
288  size_t n = theCoupleTable->GetTableSize();
289 
290  theEnergyOfCrossSectionMax.resize(n, 0.0);
291  theCrossSectionMax.resize(n, DBL_MAX);
292 
293  // initialisation of the process
296  if(isMaster) { SetVerboseLevel(theParameters->Verbose()); }
300 
301  // initialisation of models
303  for(G4int i=0; i<numberOfModels; ++i) {
304  G4VEmModel* mod = modelManager->GetModel(i);
305  if(0 == i) { currentModel = mod; }
307  mod->SetMasterThread(isMaster);
308  if(mod->HighEnergyLimit() > maxKinEnergy) {
310  }
311  }
312 
315  2.,verboseLevel);
319 
320  // prepare tables
321  if(buildLambdaTable && isMaster){
322  theLambdaTable =
325  }
326  // high energy table
327  if(isMaster && minKinEnergyPrim < maxKinEnergy){
331  }
332  // forced biasing
333  if(biasManager) {
335  biasFlag = false;
336  }
337  // defined ID of secondary particles
338  G4String nam1 = GetProcessName();
339  G4String nam2 = nam1 + "_fluo" ;
340  G4String nam3 = nam1 + "_auger";
341  G4String nam4 = nam1 + "_split";
346 }
347 
348 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
349 
351 {
352  G4bool isMaster = true;
353  const G4VEmProcess* masterProc =
354  static_cast<const G4VEmProcess*>(GetMasterProcess());
355  if(masterProc && masterProc != this) { isMaster = false; }
356 
357  G4String num = part.GetParticleName();
358  if(1 < verboseLevel) {
359  G4cout << "G4VEmProcess::BuildPhysicsTable() for "
360  << GetProcessName()
361  << " and particle " << num
362  << " buildLambdaTable= " << buildLambdaTable
363  << G4endl;
364  }
365 
366  if(particle == &part) {
367 
369 
370  // worker initialisation
371  if(!isMaster) {
372  theLambdaTable = masterProc->LambdaTable();
373  theLambdaTablePrim = masterProc->LambdaTablePrim();
374 
375  if(theLambdaTable) {
377  } else if(theLambdaTablePrim) {
379  }
382  if(theLambdaTable) { FindLambdaMax(); }
383 
384  // local initialisation of models
385  G4bool printing = true;
387  for(G4int i=0; i<numberOfModels; ++i) {
388  G4VEmModel* mod = GetModelByIndex(i, printing);
389  G4VEmModel* mod0= masterProc->GetModelByIndex(i, printing);
390  mod->InitialiseLocal(particle, mod0);
391  }
392  // master thread
393  } else {
398  }
399  }
400  }
401 
402  // explicitly defined printout by particle name
403  if(1 < verboseLevel ||
404  (0 < verboseLevel && (num == "gamma" || num == "e-" ||
405  num == "e+" || num == "mu+" ||
406  num == "mu-" || num == "proton"||
407  num == "pi+" || num == "pi-" ||
408  num == "kaon+" || num == "kaon-" ||
409  num == "alpha" || num == "anti_proton" ||
410  num == "GenericIon")))
411  {
412  PrintInfoProcess(part);
413  }
414 
415  if(1 < verboseLevel) {
416  G4cout << "G4VEmProcess::BuildPhysicsTable() done for "
417  << GetProcessName()
418  << " and particle " << num
419  << G4endl;
420  }
421 }
422 
423 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
424 
426 {
427  if(1 < verboseLevel) {
428  G4cout << "G4EmProcess::BuildLambdaTable() for process "
429  << GetProcessName() << " and particle "
430  << particle->GetParticleName() << " " << this
431  << G4endl;
432  }
433 
434  // Access to materials
435  const G4ProductionCutsTable* theCoupleTable=
437  size_t numOfCouples = theCoupleTable->GetTableSize();
438 
440 
441  G4PhysicsLogVector* aVector = 0;
442  G4PhysicsLogVector* aVectorPrim = 0;
443  G4PhysicsLogVector* bVectorPrim = 0;
444 
445  G4double scale =
447  G4int nbin = theParameters->NumberOfBins();
448  if(actBinning) { nbin = std::max(nbin, nLambdaBins); }
451 
452  for(size_t i=0; i<numOfCouples; ++i) {
453 
454  if (bld->GetFlag(i)) {
455 
456  // create physics vector and fill it
457  const G4MaterialCutsCouple* couple =
458  theCoupleTable->GetMaterialCutsCouple(i);
459 
460  // build main table
461  if(buildLambdaTable) {
462  delete (*theLambdaTable)[i];
463 
464  // if start from zero then change the scale
465  G4double emin = minKinEnergy;
466  G4bool startNull = false;
467  if(startFromNull) {
469  if(e >= emin) {
470  emin = e;
471  startNull = true;
472  }
473  }
474  G4double emax = emax1;
475  if(emax <= emin) { emax = 2*emin; }
476  G4int bin = G4lrint(nbin*G4Log(emax/emin)/scale);
477  if(bin < 3) { bin = 3; }
478  aVector = new G4PhysicsLogVector(emin, emax, bin);
479  aVector->SetSpline(splineFlag);
480  modelManager->FillLambdaVector(aVector, couple, startNull);
481  if(splineFlag) { aVector->FillSecondDerivatives(); }
483  }
484  // build high energy table
486  delete (*theLambdaTablePrim)[i];
487 
488  // start not from zero
489  if(!bVectorPrim) {
490  G4int bin = G4lrint(nbin*G4Log(maxKinEnergy/minKinEnergyPrim)/scale);
491  if(bin < 3) { bin = 3; }
492  aVectorPrim =
494  bVectorPrim = aVectorPrim;
495  } else {
496  aVectorPrim = new G4PhysicsLogVector(*bVectorPrim);
497  }
498  // always use spline
499  aVectorPrim->SetSpline(splineFlag);
500  modelManager->FillLambdaVector(aVectorPrim, couple, false,
502  aVectorPrim->FillSecondDerivatives();
504  aVectorPrim);
505  }
506  }
507  }
508 
510 
511  if(1 < verboseLevel) {
512  G4cout << "Lambda table is built for "
514  << G4endl;
515  }
516 }
517 
518 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
519 
521 {
522  if(verboseLevel > 0) {
523  G4cout << std::setprecision(6);
524  G4cout << G4endl << GetProcessName() << ": for "
525  << part.GetParticleName();
526  if(integral) { G4cout << ", integral: 1 "; }
527  if(applyCuts) { G4cout << ", applyCuts: 1 "; }
528  G4cout << " SubType= " << GetProcessSubType();;
529  if(biasFactor != 1.0) { G4cout << " BiasingFactor= " << biasFactor; }
530  G4cout << " BuildTable= " << buildLambdaTable;
531  G4cout << G4endl;
532  if(buildLambdaTable) {
533  size_t length = theLambdaTable->length();
534  for(size_t i=0; i<length; ++i) {
535  G4PhysicsVector* v = (*theLambdaTable)[i];
536  if(v) {
537  G4cout << " Lambda table from ";
538  G4double emin = v->Energy(0);
539  G4double emax = v->GetMaxEnergy();
540  G4int nbin = v->GetVectorLength() - 1;
541  if(emin > minKinEnergy) { G4cout << "threshold "; }
542  else { G4cout << G4BestUnit(emin,"Energy"); }
543  G4cout << " to "
544  << G4BestUnit(emax,"Energy")
545  << ", " << G4lrint(nbin/std::log10(emax/emin))
546  << " bins per decade, spline: "
547  << splineFlag
548  << G4endl;
549  break;
550  }
551  }
552  }
554  size_t length = theLambdaTablePrim->length();
555  for(size_t i=0; i<length; ++i) {
556  G4PhysicsVector* v = (*theLambdaTablePrim)[i];
557  if(v) {
558  G4cout << " LambdaPrime table from "
559  << G4BestUnit(v->Energy(0),"Energy")
560  << " to "
561  << G4BestUnit(v->GetMaxEnergy(),"Energy")
562  << " in " << v->GetVectorLength()-1
563  << " bins "
564  << G4endl;
565  break;
566  }
567  }
568  }
569  PrintInfo();
571  }
572 
573  if(verboseLevel > 2 && buildLambdaTable) {
574  G4cout << " LambdaTable address= " << theLambdaTable << G4endl;
575  if(theLambdaTable) { G4cout << (*theLambdaTable) << G4endl; }
576  }
577 }
578 
579 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
580 
582 {
583  // reset parameters for the new track
587 
588  // forced biasing only for primary particles
589  if(biasManager) {
590  if(0 == track->GetParentID()) {
591  // primary particle
592  biasFlag = true;
594  }
595  }
596 }
597 
598 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
599 
601  const G4Track& track,
602  G4double previousStepSize,
604 {
605  *condition = NotForced;
606  G4double x = DBL_MAX;
607 
611 
615  return x;
616  }
617 
618  // forced biasing only for primary particles
619  if(biasManager) {
620  if(0 == track.GetParentID()) {
621  if(biasFlag &&
623  return biasManager->GetStepLimit(currentCoupleIndex, previousStepSize);
624  }
625  }
626  }
627 
628  // compute mean free path
632 
633  // zero cross section
634  if(preStepLambda <= 0.0) {
637  }
638  }
639 
640  // non-zero cross section
641  if(preStepLambda > 0.0) {
642 
644 
645  // beggining of tracking (or just after DoIt of this process)
646  // ResetNumberOfInteractionLengthLeft();
647 
650 
651  } else if(currentInteractionLength < DBL_MAX) {
652 
653  // subtract NumberOfInteractionLengthLeft using previous step
655  previousStepSize/currentInteractionLength;
656  //SubtractNumberOfInteractionLengthLeft(previousStepSize);
659  }
660 
661  // new mean free path and step limit for the next step
664 #ifdef G4VERBOSE
665  if (verboseLevel>2){
666  G4cout << "G4VEmProcess::PostStepGetPhysicalInteractionLength ";
667  G4cout << "[ " << GetProcessName() << "]" << G4endl;
668  G4cout << " for " << currentParticle->GetParticleName()
669  << " in Material " << currentMaterial->GetName()
670  << " Ekin(MeV)= " << preStepKinEnergy/MeV
671  <<G4endl;
672  G4cout << " MeanFreePath = " << currentInteractionLength/cm << "[cm]"
673  << " InteractionLength= " << x/cm <<"[cm] " <<G4endl;
674  }
675 #endif
676  }
677  return x;
678 }
679 
680 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
681 
683  const G4Step& step)
684 {
685  // In all cases clear number of interaction lengths
688 
690 
691  // Do not make anything if particle is stopped, the annihilation then
692  // should be performed by the AtRestDoIt!
693  if (track.GetTrackStatus() == fStopButAlive) { return &fParticleChange; }
694 
695  G4double finalT = track.GetKineticEnergy();
696 
697  // forced process - should happen only once per track
698  if(biasFlag) {
700  biasFlag = false;
701  }
702  }
703 
704  // Integral approach
705  if (integral) {
706  G4double lx = GetLambda(finalT, currentCouple);
707  if(preStepLambda<lx && 1 < verboseLevel) {
708  G4cout << "WARNING: for " << currentParticle->GetParticleName()
709  << " and " << GetProcessName()
710  << " E(MeV)= " << finalT/MeV
711  << " preLambda= " << preStepLambda << " < "
712  << lx << " (postLambda) "
713  << G4endl;
714  }
715 
716  if(preStepLambda*G4UniformRand() > lx) {
718  return &fParticleChange;
719  }
720  }
721 
723  if(!currentModel->IsActive(finalT)) { return &fParticleChange; }
724 
725  // define new weight for primary and secondaries
727  if(weightFlag) {
728  weight /= biasFactor;
730  }
731 
732  /*
733  if(0 < verboseLevel) {
734  G4cout << "G4VEmProcess::PostStepDoIt: Sample secondary; E= "
735  << finalT/MeV
736  << " MeV; model= (" << currentModel->LowEnergyLimit()
737  << ", " << currentModel->HighEnergyLimit() << ")"
738  << G4endl;
739  }
740  */
741 
742  // sample secondaries
743  secParticles.clear();
745  currentCouple,
746  track.GetDynamicParticle(),
747  (*theCuts)[currentCoupleIndex]);
748 
749  G4int num0 = secParticles.size();
750 
751  // splitting or Russian roulette
752  if(biasManager) {
754  G4double eloss = 0.0;
756  secParticles, track, currentModel, &fParticleChange, eloss,
758  step.GetPostStepPoint()->GetSafety());
759  if(eloss > 0.0) {
762  }
763  }
764  }
765 
766  // save secondaries
767  G4int num = secParticles.size();
768  if(num > 0) {
769 
772  G4double time = track.GetGlobalTime();
773 
774  for (G4int i=0; i<num; ++i) {
775  if (secParticles[i]) {
778  G4double e = dp->GetKineticEnergy();
779  G4bool good = true;
780  if(applyCuts) {
781  if (p == theGamma) {
782  if (e < (*theCutsGamma)[currentCoupleIndex]) { good = false; }
783 
784  } else if (p == theElectron) {
785  if (e < (*theCutsElectron)[currentCoupleIndex]) { good = false; }
786 
787  } else if (p == thePositron) {
788  if (electron_mass_c2 < (*theCutsGamma)[currentCoupleIndex] &&
790  good = false;
791  e += 2.0*electron_mass_c2;
792  }
793  }
794  // added secondary if it is good
795  }
796  if (good) {
797  G4Track* t = new G4Track(dp, time, track.GetPosition());
799  t->SetWeight(weight);
801 
802  // define type of secondary
804  else if(i < num0) {
805  if(p == theGamma) {
807  } else {
809  }
810  } else {
812  }
813 
814  //G4cout << "Secondary(post step) has weight " << t->GetWeight()
815  // << ", Ekin= " << t->GetKineticEnergy()/MeV << " MeV" <<G4endl;
816  } else {
817  delete dp;
818  edep += e;
819  }
820  }
821  }
823  }
824 
830  }
831 
832  return &fParticleChange;
833 }
834 
835 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
836 
838  const G4String& directory,
839  G4bool ascii)
840 {
841  G4bool yes = true;
842 
843  if ( theLambdaTable && part == particle) {
844  const G4String name =
845  GetPhysicsTableFileName(part,directory,"Lambda",ascii);
846  yes = theLambdaTable->StorePhysicsTable(name,ascii);
847 
848  if ( yes ) {
849  G4cout << "Physics table is stored for " << particle->GetParticleName()
850  << " and process " << GetProcessName()
851  << " in the directory <" << directory
852  << "> " << G4endl;
853  } else {
854  G4cout << "Fail to store Physics Table for "
856  << " and process " << GetProcessName()
857  << " in the directory <" << directory
858  << "> " << G4endl;
859  }
860  }
861  if ( theLambdaTablePrim && part == particle) {
862  const G4String name =
863  GetPhysicsTableFileName(part,directory,"LambdaPrim",ascii);
864  yes = theLambdaTablePrim->StorePhysicsTable(name,ascii);
865 
866  if ( yes ) {
867  G4cout << "Physics table prim is stored for "
869  << " and process " << GetProcessName()
870  << " in the directory <" << directory
871  << "> " << G4endl;
872  } else {
873  G4cout << "Fail to store Physics Table Prim for "
875  << " and process " << GetProcessName()
876  << " in the directory <" << directory
877  << "> " << G4endl;
878  }
879  }
880  return yes;
881 }
882 
883 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
884 
886  const G4String& directory,
887  G4bool ascii)
888 {
889  if(1 < verboseLevel) {
890  G4cout << "G4VEmProcess::RetrievePhysicsTable() for "
891  << part->GetParticleName() << " and process "
892  << GetProcessName() << G4endl;
893  }
894  G4bool yes = true;
895 
897  || particle != part) { return yes; }
898 
899  const G4String particleName = part->GetParticleName();
900  G4String filename;
901 
902  if(buildLambdaTable) {
903  filename = GetPhysicsTableFileName(part,directory,"Lambda",ascii);
905  filename,ascii);
906  if ( yes ) {
907  if (0 < verboseLevel) {
908  G4cout << "Lambda table for " << particleName
909  << " is Retrieved from <"
910  << filename << ">"
911  << G4endl;
912  }
913  if(theParameters->Spline()) {
914  size_t n = theLambdaTable->length();
915  for(size_t i=0; i<n; ++i) {
916  if((* theLambdaTable)[i]) {
917  (* theLambdaTable)[i]->SetSpline(true);
918  }
919  }
920  }
921  } else {
922  if (1 < verboseLevel) {
923  G4cout << "Lambda table for " << particleName << " in file <"
924  << filename << "> is not exist"
925  << G4endl;
926  }
927  }
928  }
930  filename = GetPhysicsTableFileName(part,directory,"LambdaPrim",ascii);
932  filename,ascii);
933  if ( yes ) {
934  if (0 < verboseLevel) {
935  G4cout << "Lambda table prim for " << particleName
936  << " is Retrieved from <"
937  << filename << ">"
938  << G4endl;
939  }
940  if(theParameters->Spline()) {
941  size_t n = theLambdaTablePrim->length();
942  for(size_t i=0; i<n; ++i) {
943  if((* theLambdaTablePrim)[i]) {
944  (* theLambdaTablePrim)[i]->SetSpline(true);
945  }
946  }
947  }
948  } else {
949  if (1 < verboseLevel) {
950  G4cout << "Lambda table prim for " << particleName << " in file <"
951  << filename << "> is not exist"
952  << G4endl;
953  }
954  }
955  }
956 
957  return yes;
958 }
959 
960 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
961 
962 G4double
964  const G4MaterialCutsCouple* couple)
965 {
966  // Cross section per atom is calculated
967  DefineMaterial(couple);
968  G4double cross = 0.0;
970  cross = GetCurrentLambda(kineticEnergy);
971  } else {
972  SelectModel(kineticEnergy, currentCoupleIndex);
975  kineticEnergy);
976  }
977 
978  if(cross < 0.0) { cross = 0.0; }
979  return cross;
980 }
981 
982 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
983 
985  G4double,
987 {
988  *condition = NotForced;
989  return G4VEmProcess::MeanFreePath(track);
990 }
991 
992 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
993 
995 {
998  G4double x = DBL_MAX;
999  if(0.0 < preStepLambda) { x = 1.0/preStepLambda; }
1000  return x;
1001 }
1002 
1003 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1004 
1005 G4double
1007  G4double Z, G4double A, G4double cut)
1008 {
1009  SelectModel(kineticEnergy, currentCoupleIndex);
1010  G4double x = 0.0;
1011  if(currentModel) {
1013  Z,A,cut);
1014  }
1015  return x;
1016 }
1017 
1018 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1019 
1021 {
1022  if(1 < verboseLevel) {
1023  G4cout << "### G4VEmProcess::FindLambdaMax: "
1024  << particle->GetParticleName()
1025  << " and process " << GetProcessName() << " " << G4endl;
1026  }
1027  size_t n = theLambdaTable->length();
1028  G4PhysicsVector* pv;
1029  G4double e, ss, emax, smax;
1030 
1031  size_t i;
1032 
1033  // first loop on existing vectors
1034  for (i=0; i<n; ++i) {
1035  pv = (*theLambdaTable)[i];
1036  if(pv) {
1037  size_t nb = pv->GetVectorLength();
1038  emax = DBL_MAX;
1039  smax = 0.0;
1040  if(nb > 0) {
1041  for (size_t j=0; j<nb; ++j) {
1042  e = pv->Energy(j);
1043  ss = (*pv)(j);
1044  if(ss > smax) {
1045  smax = ss;
1046  emax = e;
1047  }
1048  }
1049  }
1050  theEnergyOfCrossSectionMax[i] = emax;
1051  theCrossSectionMax[i] = smax;
1052  if(1 < verboseLevel) {
1053  G4cout << "For " << particle->GetParticleName()
1054  << " Max CS at i= " << i << " emax(MeV)= " << emax/MeV
1055  << " lambda= " << smax << G4endl;
1056  }
1057  }
1058  }
1059  // second loop using base materials
1060  for (i=0; i<n; ++i) {
1061  pv = (*theLambdaTable)[i];
1062  if(!pv){
1063  G4int j = (*theDensityIdx)[i];
1065  theCrossSectionMax[i] = (*theDensityFactor)[i]*theCrossSectionMax[j];
1066  }
1067  }
1068 }
1069 
1070 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1071 
1074 {
1075  G4PhysicsVector* v =
1078  return v;
1079 }
1080 
1081 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1082 
1084 {
1085  const G4Element* elm = 0;
1087  return elm;
1088 }
1089 
1090 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1091 
1093 {
1094  if(f > 0.0) {
1095  biasFactor = f;
1096  weightFlag = flag;
1097  if(1 < verboseLevel) {
1098  G4cout << "### SetCrossSectionBiasingFactor: for "
1099  << particle->GetParticleName()
1100  << " and process " << GetProcessName()
1101  << " biasFactor= " << f << " weightFlag= " << flag
1102  << G4endl;
1103  }
1104  }
1105 }
1106 
1107 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1108 
1109 void
1111  G4bool flag)
1112 {
1113  if(!biasManager) { biasManager = new G4EmBiasingManager(); }
1114  if(1 < verboseLevel) {
1115  G4cout << "### ActivateForcedInteraction: for "
1116  << particle->GetParticleName()
1117  << " and process " << GetProcessName()
1118  << " length(mm)= " << length/mm
1119  << " in G4Region <" << r
1120  << "> weightFlag= " << flag
1121  << G4endl;
1122  }
1123  weightFlag = flag;
1125 }
1126 
1127 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1128 
1129 void
1131  G4double factor,
1132  G4double energyLimit)
1133 {
1134  if (0.0 <= factor) {
1135 
1136  // Range cut can be applied only for e-
1137  if(0.0 == factor && secondaryParticle != G4Electron::Electron())
1138  { return; }
1139 
1140  if(!biasManager) { biasManager = new G4EmBiasingManager(); }
1141  biasManager->ActivateSecondaryBiasing(region, factor, energyLimit);
1142  if(1 < verboseLevel) {
1143  G4cout << "### ActivateSecondaryBiasing: for "
1144  << " process " << GetProcessName()
1145  << " factor= " << factor
1146  << " in G4Region <" << region
1147  << "> energyLimit(MeV)= " << energyLimit/MeV
1148  << G4endl;
1149  }
1150  }
1151 }
1152 
1153 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1154 
1156 {
1157  if(5 < n && n < 10000000) {
1158  nLambdaBins = n;
1159  actBinning = true;
1160  } else {
1161  G4double e = (G4double)n;
1162  PrintWarning("SetLambdaBinning", e);
1163  }
1164 }
1165 
1166 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1167 
1169 {
1170  if(1.e-3*eV < e && e < maxKinEnergy) {
1173  minKinEnergy = e;
1174  actMinKinEnergy = true;
1175  } else { PrintWarning("SetMinKinEnergy", e); }
1176 }
1177 
1178 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1179 
1181 {
1182  if(minKinEnergy < e && e < 1.e+6*TeV) {
1185  maxKinEnergy = e;
1186  actMaxKinEnergy = true;
1187  } else { PrintWarning("SetMaxKinEnergy", e); }
1188 }
1189 
1190 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1191 
1193 {
1194  if(theParameters->MinKinEnergy() <= e &&
1195  e <= theParameters->MaxKinEnergy()) { minKinEnergyPrim = e; }
1196  else { PrintWarning("SetMinKinEnergyPrim", e); }
1197 }
1198 
1199 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1200 
1202 {
1203  G4String ss = "G4VEmProcess::" + tit;
1205  ed << "Parameter is out of range: " << val
1206  << " it will have no effect!\n" << " Process "
1207  << GetProcessName() << " nbins= " << theParameters->NumberOfBins()
1208  << " Emin(keV)= " << theParameters->MinKinEnergy()/keV
1209  << " Emax(GeV)= " << theParameters->MaxKinEnergy()/GeV;
1210  G4Exception(ss, "em0044", JustWarning, ed);
1211 }
1212 
1213 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void ActivateForcedInteraction(G4double length=0.0, const G4String &r="", G4bool flag=true)
static const double cm
Definition: G4SIunits.hh:106
G4double condition(const G4ErrorSymMatrix &m)
G4PhysicsTable * LambdaTable() const
const std::vector< G4double > * theCutsGamma
const G4VProcess * GetMasterProcess() const
Definition: G4VProcess.hh:538
std::vector< G4double > theCrossSectionMax
void DefineMaterial(const G4MaterialCutsCouple *couple)
virtual void PrintInfo()=0
G4int GetParentID() const
G4double GetLambda(G4double &kinEnergy, const G4MaterialCutsCouple *couple)
virtual G4double CrossSectionPerVolume(const G4Material *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy=0.0, G4double maxEnergy=DBL_MAX)
Definition: G4VEmModel.cc:271
static const double MeV
Definition: G4SIunits.hh:193
G4int NumberOfBins() const
G4PhysicsTable * LambdaTablePrim() const
const std::vector< G4double > * GetEnergyCutsVector(size_t pcIdx) const
G4VEmModel * SelectModel(G4double &kinEnergy, size_t index)
const std::vector< G4double > * GetDensityFactors()
static void SetPhysicsVector(G4PhysicsTable *physTable, size_t idx, G4PhysicsVector *vec)
G4bool Spline() const
G4int WorkerVerbose() const
G4double MaxKinEnergy() const
G4bool weightFlag
static G4LossTableManager * Instance()
void ActivateForcedInteraction(G4double length=0.0, const G4String &r="")
G4double GetMaxEnergy() const
G4double ApplySecondaryBiasing(std::vector< G4DynamicParticle * > &, const G4Track &track, G4VEmModel *currentModel, G4ParticleChangeForGamma *pParticleChange, G4double &eloss, G4int coupleIdx, G4double tcut, G4double safety=0.0)
G4int verboseLevel
Definition: G4VProcess.hh:368
void UpdateEmModel(const G4String &, G4double, G4double)
virtual void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin=0.0, G4double tmax=DBL_MAX)=0
std::ostringstream G4ExceptionDescription
Definition: globals.hh:76
G4PhysicsTable * theLambdaTablePrim
G4double GetKineticEnergy() const
G4double HighEnergyLimit() const
Definition: G4VEmModel.hh:615
G4VEmProcess(const G4String &name, G4ProcessType type=fElectromagnetic)
Definition: G4VEmProcess.cc:90
const G4DynamicParticle * GetDynamicParticle() const
G4VEmModel * currentModel
G4bool SecondaryBiasingRegion(G4int coupleIdx)
G4double ComputeCrossSectionPerAtom(G4double kineticEnergy, G4double Z, G4double A=0., G4double cut=0.0)
G4VEmModel * EmModel(G4int index=1) const
G4VEmModel * GetModel(G4int, G4bool ver=false)
void DeRegister(G4VEnergyLossProcess *p)
G4String name
Definition: TRTMaterials.hh:40
const G4String & GetName() const
Definition: G4Material.hh:176
G4double MscThetaLimit() const
const G4ThreeVector & GetPosition() const
G4ParticleChangeForGamma fParticleChange
virtual void InitialiseLocal(const G4ParticleDefinition *, G4VEmModel *masterModel)
Definition: G4VEmModel.cc:232
G4TrackStatus GetTrackStatus() const
G4bool ForcedInteractionRegion(G4int coupleIdx)
G4EmParameters * theParameters
const G4MaterialCutsCouple * GetMaterialCutsCouple() const
const std::vector< G4double > * theCutsPositron
virtual void InitialiseProcess(const G4ParticleDefinition *)=0
size_t basedCoupleIndex
virtual ~G4VEmProcess()
G4double theNumberOfInteractionLengthLeft
Definition: G4VProcess.hh:293
const G4MaterialCutsCouple * currentCouple
G4bool GetFlag(size_t idx) const
void SetTouchableHandle(const G4TouchableHandle &apValue)
void AddEmModel(G4int, G4VEmModel *, G4VEmFluctuationModel *, const G4Region *)
G4double GetParentWeight() const
G4double lambdaFactor
#define G4BestUnit(a, b)
#define G4_USE_G4BESTUNIT_FOR_VERBOSE 1
void BuildPhysicsTable(const G4ParticleDefinition &)
G4bool ApplyCuts() const
G4double PostStepGetPhysicalInteractionLength(const G4Track &track, G4double previousStepSize, G4ForceCondition *condition)
size_t GetVectorLength() const
const G4String & GetParticleSubType() const
const G4Material * baseMaterial
G4double fFactor
G4PhysicsTable * theLambdaTable
void ClearNumberOfInteractionLengthLeft()
Definition: G4VProcess.hh:447
void FillLambdaVector(G4PhysicsVector *, const G4MaterialCutsCouple *, G4bool startFromNull=true, G4EmTableType t=fRestricted)
G4double minKinEnergyPrim
G4ProcessManager * GetProcessManager() const
int G4int
Definition: G4Types.hh:78
void FillSecondDerivatives()
void UpdateEmModel(const G4String &, G4double, G4double)
G4double GetCurrentLambda(G4double kinEnergy)
const G4String & GetPhysicsTableFileName(const G4ParticleDefinition *, const G4String &directory, const G4String &tableName, G4bool ascii=false)
Definition: G4VProcess.cc:186
static G4PhysicsTable * PreparePhysicsTable(G4PhysicsTable *physTable)
const G4int smax
const G4String & GetParticleName() const
G4bool applyCuts
void ActivateSecondaryBiasing(const G4String &region, G4double factor, G4double energyLimit)
G4LossTableBuilder * GetTableBuilder()
void SetWeight(G4double aValue)
void ProposeLocalEnergyDeposit(G4double anEnergyPart)
void SetCreatorModelIndex(G4int idx)
void SetSpline(G4bool)
void Initialise(const G4ParticleDefinition &part, const G4String &procName, G4int verbose)
void SetHighEnergyLimit(G4double)
Definition: G4VEmModel.hh:706
void SetMinKinEnergyPrim(G4double e)
G4double mfpKinEnergy
void SetCrossSectionBiasingFactor(G4double f, G4bool flag=true)
virtual G4double MinPrimaryEnergy(const G4ParticleDefinition *, const G4Material *)
G4double MeanFreePath(const G4Track &track)
const G4ParticleDefinition * currentParticle
void SetLambdaBinning(G4int nbins)
void ProposeWeight(G4double finalWeight)
G4double minKinEnergy
void SetSecondaryWeightByProcess(G4bool)
G4double LambdaFactor() const
void SetEmModel(G4VEmModel *, G4int index=1)
G4ProcessVector * GetAtRestProcessVector(G4ProcessVectorTypeIndex typ=typeGPIL) const
G4double GetKineticEnergy() const
G4bool splineFlag
#define G4UniformRand()
Definition: Randomize.hh:95
G4GLOB_DLL std::ostream G4cout
G4int Verbose() const
G4bool RetrievePhysicsTable(const G4ParticleDefinition *, const G4String &directory, G4bool ascii)
void SetParticleChange(G4VParticleChange *, G4VEmFluctuationModel *f=0)
Definition: G4VEmModel.cc:413
G4bool startFromNull
bool G4bool
Definition: G4Types.hh:79
const std::vector< G4int > * theDensityIdx
void SetParticle(const G4ParticleDefinition *p)
G4double GetStepLimit(G4int coupleIdx, G4double previousStep)
G4double currentInteractionLength
Definition: G4VProcess.hh:297
void PrintInfoProcess(const G4ParticleDefinition &)
std::vector< G4DynamicParticle * > secParticles
G4double GetMeanFreePath(const G4Track &track, G4double previousStepSize, G4ForceCondition *condition)
const G4ParticleDefinition * GetParticleDefinition() const
G4bool actSpline
G4bool IsMaster() const
G4LossTableManager * lManager
static const double GeV
Definition: G4SIunits.hh:196
const G4String & GetParticleType() const
void Register(G4VEnergyLossProcess *p)
const G4ParticleDefinition * secondaryParticle
Definition: G4Step.hh:76
G4double MinKinEnergy() const
std::vector< G4double > theEnergyOfCrossSectionMax
G4bool actBinning
const G4ParticleDefinition * GetParticleDefinition() const
const G4int n
G4double GetGlobalTime() const
const G4ParticleDefinition * particle
void PreparePhysicsTable(const G4ParticleDefinition &)
static G4Gamma * Gamma()
Definition: G4Gamma.cc:86
G4double Energy(size_t index) const
const std::vector< G4double > * theCuts
static const G4double A[nN]
const G4String & GetProcessName() const
Definition: G4VProcess.hh:408
void AddSecondary(G4Track *aSecondary)
virtual G4double ComputeCrossSectionPerAtom(const G4ParticleDefinition *, G4double kinEnergy, G4double Z, G4double A=0., G4double cutEnergy=0.0, G4double maxEnergy=DBL_MAX)
Definition: G4VEmModel.cc:326
const G4TouchableHandle & GetTouchableHandle() const
G4bool IsActive(G4double kinEnergy)
Definition: G4VEmModel.hh:734
void DumpModelList(G4int verb)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
const G4DataVector * Initialise(const G4ParticleDefinition *part, const G4ParticleDefinition *secPart, G4double minSubRange, G4int verb)
void SetMasterThread(G4bool val)
Definition: G4VEmModel.hh:692
size_t length() const
G4double G4Log(G4double x)
Definition: G4Log.hh:230
std::vector< G4VEmModel * > emModels
G4int size() const
void ActivateSecondaryBiasing(const G4String &region, G4double factor, G4double energyLimit)
static G4ProductionCutsTable * GetProductionCutsTable()
static const double eV
Definition: G4SIunits.hh:194
G4PhysicsVector * LambdaPhysicsVector(const G4MaterialCutsCouple *)
static G4Positron * Positron()
Definition: G4Positron.cc:94
static G4GenericIon * GenericIon()
Definition: G4GenericIon.cc:93
G4int NumberOfModels() const
const G4Material * currentMaterial
void SetMaxKinEnergy(G4double e)
size_t idxLambdaPrim
void FindLambdaMax()
static const G4double factor
const G4ParticleDefinition * theElectron
const G4MaterialCutsCouple * GetMaterialCutsCouple(G4int i) const
void AddEmModel(G4int, G4VEmModel *, const G4Region *region=0)
int G4lrint(double ad)
Definition: templates.hh:163
G4bool actMaxKinEnergy
G4double GetProposedKineticEnergy() const
T max(const T t1, const T t2)
brief Return the largest of the two arguments
void InitialiseBaseMaterials(G4PhysicsTable *table)
size_t idxLambda
void SetNumberOfSecondaries(G4int totSecondaries)
static G4int Register(const G4String &)
G4double GetLocalEnergyDeposit() const
G4StepPoint * GetPostStepPoint() const
G4EmModelManager * modelManager
static G4EmParameters * Instance()
G4VParticleChange * pParticleChange
Definition: G4VProcess.hh:283
const G4Element * GetCurrentElement() const
T min(const T t1, const T t2)
brief Return the smallest of the two arguments
G4double preStepLambda
void ComputeIntegralLambda(G4double kinEnergy)
G4EmBiasingManager * biasManager
G4double GetSafety() const
void PreparePhysicsTable(const G4ParticleDefinition *aParticle, G4VEnergyLossProcess *p, G4bool theMaster)
static G4Electron * Electron()
Definition: G4Electron.cc:94
#define G4endl
Definition: G4ios.hh:61
void SetFluoFlag(G4bool val)
static const double TeV
Definition: G4SIunits.hh:197
G4bool StorePhysicsTable(const G4String &filename, G4bool ascii=false)
G4TrackStatus GetTrackStatus() const
G4VEmModel * GetModelByIndex(G4int idx=0, G4bool ver=false) const
G4int numberOfModels
const std::vector< G4double > * theDensityFactor
G4VAtomDeexcitation * AtomDeexcitation()
static const double keV
Definition: G4SIunits.hh:195
G4double biasFactor
size_t currentCoupleIndex
G4bool actMinKinEnergy
void SetMinKinEnergy(G4double e)
G4double theInitialNumberOfInteractionLength
Definition: G4VProcess.hh:300
double G4double
Definition: G4Types.hh:76
void ProposeTrackStatus(G4TrackStatus status)
const std::vector< G4double > * theCutsElectron
void InitializeForPostStep(const G4Track &)
G4ForceCondition
void StartTracking(G4Track *)
static G4bool RetrievePhysicsTable(G4PhysicsTable *physTable, const G4String &fileName, G4bool ascii)
#define DBL_MAX
Definition: templates.hh:83
G4double CrossSectionPerVolume(G4double kineticEnergy, const G4MaterialCutsCouple *couple)
void PrintWarning(G4String tit, G4double val)
G4bool StorePhysicsTable(const G4ParticleDefinition *, const G4String &directory, G4bool ascii=false)
static const double mm
Definition: G4SIunits.hh:102
G4int GetProcessSubType() const
Definition: G4VProcess.hh:426
G4double maxKinEnergy
G4double preStepKinEnergy
G4bool buildLambdaTable
void SetPolarAngleLimit(G4double)
Definition: G4VEmModel.hh:741
G4VParticleChange * PostStepDoIt(const G4Track &, const G4Step &)
void clearAndDestroy()
const G4ParticleDefinition * theGamma
void SetVerboseLevel(G4int value)
Definition: G4VProcess.hh:437
const G4ParticleDefinition * thePositron
const G4Material * GetMaterial() const
G4int mainSecondaries
void BuildLambdaTable()
const std::vector< G4int > * GetCoupleIndexes()
G4ProcessType
const G4Element * GetCurrentElement() const
Definition: G4VEmModel.hh:448