Geant4  9.6.p02
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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$
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 
87 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
88 
90  G4VDiscreteProcess(name, type),
91  secondaryParticle(0),
92  buildLambdaTable(true),
93  numberOfModels(0),
94  theLambdaTable(0),
95  theLambdaTablePrim(0),
96  theDensityFactor(0),
97  theDensityIdx(0),
98  integral(false),
99  applyCuts(false),
100  startFromNull(false),
101  splineFlag(true),
102  currentModel(0),
103  particle(0),
104  currentParticle(0),
105  currentCouple(0)
106 {
107  SetVerboseLevel(1);
108 
109  // Size of tables assuming spline
110  minKinEnergy = 0.1*keV;
111  maxKinEnergy = 10.0*TeV;
112  nLambdaBins = 77;
113  minKinEnergyPrim = DBL_MAX;
114 
115  // default lambda factor
116  lambdaFactor = 0.8;
117 
118  // default limit on polar angle
119  polarAngleLimit = 0.0;
120  biasFactor = 1.0;
121 
122  // particle types
123  theGamma = G4Gamma::Gamma();
124  theElectron = G4Electron::Electron();
125  thePositron = G4Positron::Positron();
126 
128  secParticles.reserve(5);
129 
130  preStepLambda = 0.0;
131  mfpKinEnergy = DBL_MAX;
132 
133  modelManager = new G4EmModelManager();
134  biasManager = 0;
135  biasFlag = false;
136  weightFlag = false;
137  (G4LossTableManager::Instance())->Register(this);
138  warn = 0;
139 }
140 
141 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
142 
144 {
145  if(1 < verboseLevel) {
146  G4cout << "G4VEmProcess destruct " << GetProcessName()
147  << " " << this << " " << theLambdaTable <<G4endl;
148  }
149  Clear();
150  if(theLambdaTable) {
151  theLambdaTable->clearAndDestroy();
152  delete theLambdaTable;
153  }
154  if(theLambdaTablePrim) {
155  theLambdaTablePrim->clearAndDestroy();
156  delete theLambdaTablePrim;
157  }
158  delete modelManager;
159  delete biasManager;
160  (G4LossTableManager::Instance())->DeRegister(this);
161 }
162 
163 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
164 
165 void G4VEmProcess::Clear()
166 {
167  currentCouple = 0;
168  preStepLambda = 0.0;
169  mfpKinEnergy = DBL_MAX;
170 }
171 
172 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
173 
175  const G4Material*)
176 {
177  return 0.0;
178 }
179 
180 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
181 
183  const G4Region* region)
184 {
185  G4VEmFluctuationModel* fm = 0;
186  modelManager->AddEmModel(order, p, fm, region);
187  if(p) { p->SetParticleChange(pParticleChange); }
188 }
189 
190 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
191 
193 {
194  ++warn;
195  if(warn < 10) {
196  G4cout << "### G4VEmProcess::SetModel is obsolete method and will be "
197  << "removed for the next release." << G4endl;
198  G4cout << " Please, use SetEmModel" << G4endl;
199  }
200  G4int n = emModels.size();
201  if(index >= n) { for(G4int i=n; i<=index; ++i) {emModels.push_back(0);} }
202  emModels[index] = p;
203 }
204 
205 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
206 
208 {
209  if(warn < 10) {
210  G4cout << "### G4VEmProcess::Model is obsolete method and will be "
211  << "removed for the next release." << G4endl;
212  G4cout << " Please, use EmModel" << G4endl;
213  }
214  G4VEmModel* p = 0;
215  if(index >= 0 && index < G4int(emModels.size())) { p = emModels[index]; }
216  return p;
217 }
218 
219 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
220 
222 {
223  G4int n = emModels.size();
224  if(index >= n) { for(G4int i=n; i<=index; ++i) {emModels.push_back(0);} }
225  emModels[index] = p;
226 }
227 
228 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
229 
231 {
232  G4VEmModel* p = 0;
233  if(index >= 0 && index < G4int(emModels.size())) { p = emModels[index]; }
234  return p;
235 }
236 
237 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
238 
240  G4double emin, G4double emax)
241 {
242  modelManager->UpdateEmModel(nam, emin, emax);
243 }
244 
245 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
246 
248 {
249  return modelManager->GetModel(idx, ver);
250 }
251 
252 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
253 
255 {
256  if(!particle) { SetParticle(&part); }
257 
258  if(part.GetParticleType() == "nucleus" &&
259  part.GetParticleSubType() == "generic") {
260 
261  G4String pname = part.GetParticleName();
262  if(pname != "deuteron" && pname != "triton" &&
263  pname != "alpha" && pname != "He3" &&
264  pname != "alpha+" && pname != "helium" &&
265  pname != "hydrogen") {
266 
267  particle = G4GenericIon::GenericIon();
268  }
269  }
270 
271  if(1 < verboseLevel) {
272  G4cout << "G4VEmProcess::PreparePhysicsTable() for "
273  << GetProcessName()
274  << " and particle " << part.GetParticleName()
275  << " local particle " << particle->GetParticleName()
276  << G4endl;
277  }
278 
280  G4LossTableBuilder* bld = man->GetTableBuilder();
281 
282  man->PreparePhysicsTable(&part, this);
283 
284  if(particle == &part) {
285  Clear();
286  InitialiseProcess(particle);
287 
288  const G4ProductionCutsTable* theCoupleTable=
290  size_t n = theCoupleTable->GetTableSize();
291 
292  theEnergyOfCrossSectionMax.resize(n, 0.0);
293  theCrossSectionMax.resize(n, DBL_MAX);
294 
295  // initialisation of models
296  numberOfModels = modelManager->NumberOfModels();
297  for(G4int i=0; i<numberOfModels; ++i) {
298  G4VEmModel* mod = modelManager->GetModel(i);
299  if(0 == i) { currentModel = mod; }
300  mod->SetPolarAngleLimit(polarAngleLimit);
301  if(mod->HighEnergyLimit() > maxKinEnergy) {
302  mod->SetHighEnergyLimit(maxKinEnergy);
303  }
304  }
305 
306  if(man->AtomDeexcitation()) { modelManager->SetFluoFlag(true); }
307  theCuts = modelManager->Initialise(particle,secondaryParticle,
308  2.,verboseLevel);
309  theCutsGamma = theCoupleTable->GetEnergyCutsVector(idxG4GammaCut);
310  theCutsElectron = theCoupleTable->GetEnergyCutsVector(idxG4ElectronCut);
311  theCutsPositron = theCoupleTable->GetEnergyCutsVector(idxG4PositronCut);
312 
313  // prepare tables
314  if(buildLambdaTable){
315  theLambdaTable = G4PhysicsTableHelper::PreparePhysicsTable(theLambdaTable);
316  bld->InitialiseBaseMaterials(theLambdaTable);
317  }
318  // high energy table
319  if(minKinEnergyPrim < maxKinEnergy){
320  theLambdaTablePrim =
321  G4PhysicsTableHelper::PreparePhysicsTable(theLambdaTablePrim);
322  bld->InitialiseBaseMaterials(theLambdaTablePrim);
323  }
324  // forced biasing
325  if(biasManager) {
326  biasManager->Initialise(part,GetProcessName(),verboseLevel);
327  biasFlag = false;
328  }
329  }
330  theDensityFactor = bld->GetDensityFactors();
331  theDensityIdx = bld->GetCoupleIndexes();
332 }
333 
334 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
335 
337 {
338  G4String num = part.GetParticleName();
339  if(1 < verboseLevel) {
340  G4cout << "G4VEmProcess::BuildPhysicsTable() for "
341  << GetProcessName()
342  << " and particle " << num
343  << " buildLambdaTable= " << buildLambdaTable
344  << G4endl;
345  }
346 
348 
349  if(buildLambdaTable || minKinEnergyPrim < maxKinEnergy) {
350  BuildLambdaTable();
351  }
352 
353  // explicitly defined printout by particle name
354  if(1 < verboseLevel ||
355  (0 < verboseLevel && (num == "gamma" || num == "e-" ||
356  num == "e+" || num == "mu+" ||
357  num == "mu-" || num == "proton"||
358  num == "pi+" || num == "pi-" ||
359  num == "kaon+" || num == "kaon-" ||
360  num == "alpha" || num == "anti_proton" ||
361  num == "GenericIon")))
362  {
363  particle = &part;
365  }
366 
367  if(1 < verboseLevel) {
368  G4cout << "G4VEmProcess::BuildPhysicsTable() done for "
369  << GetProcessName()
370  << " and particle " << num
371  << G4endl;
372  }
373 }
374 
375 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
376 
377 void G4VEmProcess::BuildLambdaTable()
378 {
379  if(1 < verboseLevel) {
380  G4cout << "G4EmProcess::BuildLambdaTable() for process "
381  << GetProcessName() << " and particle "
382  << particle->GetParticleName() << " " << this
383  << G4endl;
384  }
385 
386  // Access to materials
387  const G4ProductionCutsTable* theCoupleTable=
389  size_t numOfCouples = theCoupleTable->GetTableSize();
390 
391  G4LossTableBuilder* bld = (G4LossTableManager::Instance())->GetTableBuilder();
392 
393  G4PhysicsLogVector* aVector = 0;
394  G4PhysicsLogVector* bVector = 0;
395  G4PhysicsLogVector* aVectorPrim = 0;
396  G4PhysicsLogVector* bVectorPrim = 0;
397 
398  G4double scale = 1.0;
399  G4double emax1 = maxKinEnergy;
400  if(startFromNull || minKinEnergyPrim < maxKinEnergy ) {
401  scale = std::log(maxKinEnergy/minKinEnergy);
402  if(minKinEnergyPrim < maxKinEnergy) { emax1 = minKinEnergyPrim; }
403  }
404 
405  for(size_t i=0; i<numOfCouples; ++i) {
406 
407  if (bld->GetFlag(i)) {
408 
409  // create physics vector and fill it
410  const G4MaterialCutsCouple* couple =
411  theCoupleTable->GetMaterialCutsCouple(i);
412 
413  // build main table
414  if(buildLambdaTable) {
415  delete (*theLambdaTable)[i];
416 
417  G4bool startNull = startFromNull;
418  // if start from zero then change the scale
419  if(startFromNull || minKinEnergyPrim < maxKinEnergy) {
420  G4double emin = MinPrimaryEnergy(particle,couple->GetMaterial());
421  if(emin < minKinEnergy) {
422  emin = minKinEnergy;
423  startNull = false;
424  }
425  G4double emax = emax1;
426  if(emax <= emin) { emax = 2*emin; }
427  G4int bin =
428  G4lrint(nLambdaBins*std::log(emax/emin)/scale);
429  if(bin < 3) { bin = 3; }
430  aVector = new G4PhysicsLogVector(emin, emax, bin);
431 
432  // start not from zero
433  } else if(!bVector) {
434  aVector =
435  new G4PhysicsLogVector(minKinEnergy, maxKinEnergy, nLambdaBins);
436  bVector = aVector;
437  } else {
438  aVector = new G4PhysicsLogVector(*bVector);
439  }
440  aVector->SetSpline(splineFlag);
441  modelManager->FillLambdaVector(aVector, couple, startNull);
442  if(splineFlag) { aVector->FillSecondDerivatives(); }
443  G4PhysicsTableHelper::SetPhysicsVector(theLambdaTable, i, aVector);
444  }
445  // build high energy table
446  if(minKinEnergyPrim < maxKinEnergy) {
447  delete (*theLambdaTablePrim)[i];
448 
449  // start not from zero
450  if(!bVectorPrim) {
451  G4int bin =
452  G4lrint(nLambdaBins*std::log(maxKinEnergy/minKinEnergyPrim)/scale);
453  if(bin < 3) { bin = 3; }
454  aVectorPrim =
455  new G4PhysicsLogVector(minKinEnergyPrim, maxKinEnergy, bin);
456  bVectorPrim = aVectorPrim;
457  } else {
458  aVectorPrim = new G4PhysicsLogVector(*bVectorPrim);
459  }
460  // always use spline
461  aVectorPrim->SetSpline(true);
462  modelManager->FillLambdaVector(aVectorPrim, couple, false,
464  aVectorPrim->FillSecondDerivatives();
465  G4PhysicsTableHelper::SetPhysicsVector(theLambdaTablePrim, i, aVectorPrim);
466  }
467  }
468  }
469 
470  if(buildLambdaTable) { FindLambdaMax(); }
471 
472  if(1 < verboseLevel) {
473  G4cout << "Lambda table is built for "
474  << particle->GetParticleName()
475  << G4endl;
476  }
477 }
478 
479 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
480 
482 {
483  if(verboseLevel > 0) {
484  G4cout << G4endl << GetProcessName() << ": for "
485  << particle->GetParticleName();
486  if(integral) { G4cout << ", integral: 1 "; }
487  if(applyCuts) { G4cout << ", applyCuts: 1 "; }
488  G4cout << " SubType= " << GetProcessSubType();;
489  if(biasFactor != 1.0) { G4cout << " BiasingFactor= " << biasFactor; }
490  G4cout << G4endl;
491  if(buildLambdaTable) {
492  size_t length = theLambdaTable->length();
493  for(size_t i=0; i<length; ++i) {
494  G4PhysicsVector* v = (*theLambdaTable)[i];
495  if(v) {
496  G4cout << " Lambda table from "
497  << G4BestUnit(minKinEnergy,"Energy")
498  << " to "
499  << G4BestUnit(v->GetMaxEnergy(),"Energy")
500  << " in " << v->GetVectorLength()-1
501  << " bins, spline: "
502  << splineFlag
503  << G4endl;
504  break;
505  }
506  }
507  }
508  if(minKinEnergyPrim < maxKinEnergy) {
509  size_t length = theLambdaTablePrim->length();
510  for(size_t i=0; i<length; ++i) {
511  G4PhysicsVector* v = (*theLambdaTablePrim)[i];
512  if(v) {
513  G4cout << " LambdaPrime table from "
514  << G4BestUnit(minKinEnergyPrim,"Energy")
515  << " to "
516  << G4BestUnit(maxKinEnergy,"Energy")
517  << " in " << v->GetVectorLength()-1
518  << " bins "
519  << G4endl;
520  break;
521  }
522  }
523  }
524  PrintInfo();
525  modelManager->DumpModelList(verboseLevel);
526  }
527 
528  if(verboseLevel > 2 && buildLambdaTable) {
529  G4cout << " LambdaTable address= " << theLambdaTable << G4endl;
530  if(theLambdaTable) { G4cout << (*theLambdaTable) << G4endl; }
531  }
532 }
533 
534 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
535 
537 {
538  // reset parameters for the new track
539  currentParticle = track->GetParticleDefinition();
541  //currentInteractionLength = -1.0;
542  // theInitialNumberOfInteractionLength=-1.0;
543  mfpKinEnergy = DBL_MAX;
544 
545  // forced biasing only for primary particles
546  if(biasManager) {
547  if(0 == track->GetParentID()) {
548  // primary particle
549  biasFlag = true;
550  biasManager->ResetForcedInteraction();
551  }
552  }
553 }
554 
555 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
556 
558  const G4Track& track,
559  G4double previousStepSize,
561 {
562  *condition = NotForced;
563  G4double x = DBL_MAX;
564 
565  preStepKinEnergy = track.GetKineticEnergy();
566  DefineMaterial(track.GetMaterialCutsCouple());
567  SelectModel(preStepKinEnergy, currentCoupleIndex);
568 
569  if(!currentModel->IsActive(preStepKinEnergy)) { return x; }
570 
571  // forced biasing only for primary particles
572  if(biasManager) {
573  if(0 == track.GetParentID()) {
574  if(biasFlag && biasManager->ForcedInteractionRegion(currentCoupleIndex)) {
575  return biasManager->GetStepLimit(currentCoupleIndex, previousStepSize);
576  }
577  }
578  }
579 
580  // compute mean free path
581  if(preStepKinEnergy < mfpKinEnergy) {
582  if (integral) { ComputeIntegralLambda(preStepKinEnergy); }
583  else { preStepLambda = GetCurrentLambda(preStepKinEnergy); }
584 
585  // zero cross section
586  if(preStepLambda <= 0.0) {
589  }
590  }
591 
592  // non-zero cross section
593  if(preStepLambda > 0.0) {
594 
596 
597  // beggining of tracking (or just after DoIt of this process)
599 
600  } else if(currentInteractionLength < DBL_MAX) {
601 
602  // subtract NumberOfInteractionLengthLeft using previous step
604  //SubtractNumberOfInteractionLengthLeft(previousStepSize);
607  //theNumberOfInteractionLengthLeft = perMillion;
608  }
609  }
610 
611  // new mean free path and step limit for the next step
612  currentInteractionLength = 1.0/preStepLambda;
614 #ifdef G4VERBOSE
615  if (verboseLevel>2){
616  G4cout << "G4VEmProcess::PostStepGetPhysicalInteractionLength ";
617  G4cout << "[ " << GetProcessName() << "]" << G4endl;
618  G4cout << " for " << currentParticle->GetParticleName()
619  << " in Material " << currentMaterial->GetName()
620  << " Ekin(MeV)= " << preStepKinEnergy/MeV
621  <<G4endl;
622  G4cout << " MeanFreePath = " << currentInteractionLength/cm << "[cm]"
623  << " InteractionLength= " << x/cm <<"[cm] " <<G4endl;
624  }
625 #endif
626  }
627  return x;
628 }
629 
630 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
631 
633  const G4Step& step)
634 {
635  // In all cases clear number of interaction lengths
637  mfpKinEnergy = DBL_MAX;
638 
640 
641  // Do not make anything if particle is stopped, the annihilation then
642  // should be performed by the AtRestDoIt!
643  if (track.GetTrackStatus() == fStopButAlive) { return &fParticleChange; }
644 
645  G4double finalT = track.GetKineticEnergy();
646 
647  // forced process - should happen only once per track
648  if(biasFlag) {
649  if(biasManager->ForcedInteractionRegion(currentCoupleIndex)) {
650  biasFlag = false;
651  }
652  }
653 
654  // Integral approach
655  if (integral) {
656  G4double lx = GetLambda(finalT, currentCouple);
657  if(preStepLambda<lx && 1 < verboseLevel) {
658  G4cout << "WARNING: for " << currentParticle->GetParticleName()
659  << " and " << GetProcessName()
660  << " E(MeV)= " << finalT/MeV
661  << " preLambda= " << preStepLambda << " < "
662  << lx << " (postLambda) "
663  << G4endl;
664  }
665 
666  if(preStepLambda*G4UniformRand() > lx) {
668  return &fParticleChange;
669  }
670  }
671 
672  SelectModel(finalT, currentCoupleIndex);
673  if(!currentModel->IsActive(finalT)) { return &fParticleChange; }
674 
675  // define new weight for primary and secondaries
677  if(weightFlag) {
678  weight /= biasFactor;
680  }
681 
682  /*
683  if(0 < verboseLevel) {
684  G4cout << "G4VEmProcess::PostStepDoIt: Sample secondary; E= "
685  << finalT/MeV
686  << " MeV; model= (" << currentModel->LowEnergyLimit()
687  << ", " << currentModel->HighEnergyLimit() << ")"
688  << G4endl;
689  }
690  */
691 
692  // sample secondaries
693  secParticles.clear();
694  currentModel->SampleSecondaries(&secParticles,
695  currentCouple,
696  track.GetDynamicParticle(),
697  (*theCuts)[currentCoupleIndex]);
698 
699  // bremsstrahlung splitting or Russian roulette
700  if(biasManager) {
701  if(biasManager->SecondaryBiasingRegion(currentCoupleIndex)) {
702  G4double eloss = 0.0;
703  weight *= biasManager->ApplySecondaryBiasing(secParticles,
704  track, currentModel,
706  eloss, currentCoupleIndex,
707  (*theCuts)[currentCoupleIndex],
708  step.GetPostStepPoint()->GetSafety());
709  if(eloss > 0.0) {
712  }
713  }
714  }
715 
716  // save secondaries
717  G4int num = secParticles.size();
718  if(num > 0) {
719 
722 
723  for (G4int i=0; i<num; ++i) {
724  if (secParticles[i]) {
725  G4DynamicParticle* dp = secParticles[i];
727  G4double e = dp->GetKineticEnergy();
728  G4bool good = true;
729  if(applyCuts) {
730  if (p == theGamma) {
731  if (e < (*theCutsGamma)[currentCoupleIndex]) { good = false; }
732 
733  } else if (p == theElectron) {
734  if (e < (*theCutsElectron)[currentCoupleIndex]) { good = false; }
735 
736  } else if (p == thePositron) {
737  if (electron_mass_c2 < (*theCutsGamma)[currentCoupleIndex] &&
738  e < (*theCutsPositron)[currentCoupleIndex]) {
739  good = false;
740  e += 2.0*electron_mass_c2;
741  }
742  }
743  // added secondary if it is good
744  }
745  if (good) {
746  G4Track* t = new G4Track(dp, track.GetGlobalTime(), track.GetPosition());
748  t->SetWeight(weight);
750  //G4cout << "Secondary(post step) has weight " << t->GetWeight()
751  // << ", Ekin= " << t->GetKineticEnergy()/MeV << " MeV" <<G4endl;
752  } else {
753  delete dp;
754  edep += e;
755  }
756  }
757  }
759  }
760 
763  if(particle->GetProcessManager()->GetAtRestProcessVector()->size() > 0)
766  }
767 
768  // ClearNumberOfInteractionLengthLeft();
769  return &fParticleChange;
770 }
771 
772 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
773 
775  const G4String& directory,
776  G4bool ascii)
777 {
778  G4bool yes = true;
779 
780  if ( theLambdaTable && part == particle) {
781  const G4String name =
782  GetPhysicsTableFileName(part,directory,"Lambda",ascii);
783  yes = theLambdaTable->StorePhysicsTable(name,ascii);
784 
785  if ( yes ) {
786  G4cout << "Physics table is stored for " << particle->GetParticleName()
787  << " and process " << GetProcessName()
788  << " in the directory <" << directory
789  << "> " << G4endl;
790  } else {
791  G4cout << "Fail to store Physics Table for "
792  << particle->GetParticleName()
793  << " and process " << GetProcessName()
794  << " in the directory <" << directory
795  << "> " << G4endl;
796  }
797  }
798  if ( theLambdaTablePrim && part == particle) {
799  const G4String name =
800  GetPhysicsTableFileName(part,directory,"LambdaPrim",ascii);
801  yes = theLambdaTablePrim->StorePhysicsTable(name,ascii);
802 
803  if ( yes ) {
804  G4cout << "Physics table prim is stored for " << particle->GetParticleName()
805  << " and process " << GetProcessName()
806  << " in the directory <" << directory
807  << "> " << G4endl;
808  } else {
809  G4cout << "Fail to store Physics Table Prim for "
810  << particle->GetParticleName()
811  << " and process " << GetProcessName()
812  << " in the directory <" << directory
813  << "> " << G4endl;
814  }
815  }
816  return yes;
817 }
818 
819 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
820 
822  const G4String& directory,
823  G4bool ascii)
824 {
825  if(1 < verboseLevel) {
826  G4cout << "G4VEmProcess::RetrievePhysicsTable() for "
827  << part->GetParticleName() << " and process "
828  << GetProcessName() << G4endl;
829  }
830  G4bool yes = true;
831 
832  if((!buildLambdaTable && minKinEnergyPrim > maxKinEnergy)
833  || particle != part) { return yes; }
834 
835  const G4String particleName = part->GetParticleName();
836  G4String filename;
837 
838  if(buildLambdaTable) {
839  filename = GetPhysicsTableFileName(part,directory,"Lambda",ascii);
840  yes = G4PhysicsTableHelper::RetrievePhysicsTable(theLambdaTable,
841  filename,ascii);
842  if ( yes ) {
843  if (0 < verboseLevel) {
844  G4cout << "Lambda table for " << particleName
845  << " is Retrieved from <"
846  << filename << ">"
847  << G4endl;
848  }
849  if((G4LossTableManager::Instance())->SplineFlag()) {
850  size_t n = theLambdaTable->length();
851  for(size_t i=0; i<n; ++i) {
852  if((* theLambdaTable)[i]) {
853  (* theLambdaTable)[i]->SetSpline(true);
854  }
855  }
856  }
857  } else {
858  if (1 < verboseLevel) {
859  G4cout << "Lambda table for " << particleName << " in file <"
860  << filename << "> is not exist"
861  << G4endl;
862  }
863  }
864  }
865  if(minKinEnergyPrim < maxKinEnergy) {
866  filename = GetPhysicsTableFileName(part,directory,"LambdaPrim",ascii);
867  yes = G4PhysicsTableHelper::RetrievePhysicsTable(theLambdaTablePrim,
868  filename,ascii);
869  if ( yes ) {
870  if (0 < verboseLevel) {
871  G4cout << "Lambda table prim for " << particleName
872  << " is Retrieved from <"
873  << filename << ">"
874  << G4endl;
875  }
876  if((G4LossTableManager::Instance())->SplineFlag()) {
877  size_t n = theLambdaTablePrim->length();
878  for(size_t i=0; i<n; ++i) {
879  if((* theLambdaTablePrim)[i]) {
880  (* theLambdaTablePrim)[i]->SetSpline(true);
881  }
882  }
883  }
884  } else {
885  if (1 < verboseLevel) {
886  G4cout << "Lambda table prim for " << particleName << " in file <"
887  << filename << "> is not exist"
888  << G4endl;
889  }
890  }
891  }
892 
893  return yes;
894 }
895 
896 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
897 
898 G4double
900  const G4MaterialCutsCouple* couple)
901 {
902  // Cross section per atom is calculated
903  DefineMaterial(couple);
904  G4double cross = 0.0;
905  if(theLambdaTable) {
906  cross = (*theDensityFactor)[currentCoupleIndex]*
907  (((*theLambdaTable)[basedCoupleIndex])->Value(kineticEnergy));
908  } else {
909  SelectModel(kineticEnergy, currentCoupleIndex);
910  cross = currentModel->CrossSectionPerVolume(currentMaterial,
911  currentParticle,kineticEnergy);
912  }
913 
914  if(cross < 0.0) { cross = 0.0; }
915  return cross;
916 }
917 
918 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
919 
921  G4double,
923 {
924  *condition = NotForced;
925  return G4VEmProcess::MeanFreePath(track);
926 }
927 
928 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
929 
931 {
932  DefineMaterial(track.GetMaterialCutsCouple());
933  preStepLambda = GetCurrentLambda(track.GetKineticEnergy());
934  G4double x = DBL_MAX;
935  if(0.0 < preStepLambda) { x = 1.0/preStepLambda; }
936  return x;
937 }
938 
939 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
940 
941 G4double
943  G4double Z, G4double A, G4double cut)
944 {
945  SelectModel(kineticEnergy, currentCoupleIndex);
946  G4double x = 0.0;
947  if(currentModel) {
948  x = currentModel->ComputeCrossSectionPerAtom(currentParticle,kineticEnergy,
949  Z,A,cut);
950  }
951  return x;
952 }
953 
954 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
955 
956 void G4VEmProcess::FindLambdaMax()
957 {
958  if(1 < verboseLevel) {
959  G4cout << "### G4VEmProcess::FindLambdaMax: "
960  << particle->GetParticleName()
961  << " and process " << GetProcessName() << G4endl;
962  }
963  size_t n = theLambdaTable->length();
964  G4PhysicsVector* pv;
965  G4double e, ss, emax, smax;
966 
967  size_t i;
968 
969  // first loop on existing vectors
970  for (i=0; i<n; ++i) {
971  pv = (*theLambdaTable)[i];
972  if(pv) {
973  size_t nb = pv->GetVectorLength();
974  emax = DBL_MAX;
975  smax = 0.0;
976  if(nb > 0) {
977  for (size_t j=0; j<nb; ++j) {
978  e = pv->Energy(j);
979  ss = (*pv)(j);
980  if(ss > smax) {
981  smax = ss;
982  emax = e;
983  }
984  }
985  }
986  theEnergyOfCrossSectionMax[i] = emax;
987  theCrossSectionMax[i] = smax;
988  if(1 < verboseLevel) {
989  G4cout << "For " << particle->GetParticleName()
990  << " Max CS at i= " << i << " emax(MeV)= " << emax/MeV
991  << " lambda= " << smax << G4endl;
992  }
993  }
994  }
995  // second loop using base materials
996  for (i=0; i<n; ++i) {
997  pv = (*theLambdaTable)[i];
998  if(!pv){
999  G4int j = (*theDensityIdx)[i];
1000  theEnergyOfCrossSectionMax[i] = theEnergyOfCrossSectionMax[j];
1001  theCrossSectionMax[i] = (*theDensityFactor)[i]*theCrossSectionMax[j];
1002  }
1003  }
1004 }
1005 
1006 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1007 
1010 {
1011  G4PhysicsVector* v =
1012  new G4PhysicsLogVector(minKinEnergy, maxKinEnergy, nLambdaBins);
1013  v->SetSpline((G4LossTableManager::Instance())->SplineFlag());
1014  return v;
1015 }
1016 
1017 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1018 
1020 {
1021  const G4Element* elm = 0;
1022  if(currentModel) {elm = currentModel->GetCurrentElement(); }
1023  return elm;
1024 }
1025 
1026 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1027 
1029 {
1030  if(f > 0.0) {
1031  biasFactor = f;
1032  weightFlag = flag;
1033  if(1 < verboseLevel) {
1034  G4cout << "### SetCrossSectionBiasingFactor: for "
1035  << particle->GetParticleName()
1036  << " and process " << GetProcessName()
1037  << " biasFactor= " << f << " weightFlag= " << flag
1038  << G4endl;
1039  }
1040  }
1041 }
1042 
1043 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1044 
1045 void
1047  G4bool flag)
1048 {
1049  if(!biasManager) { biasManager = new G4EmBiasingManager(); }
1050  if(1 < verboseLevel) {
1051  G4cout << "### ActivateForcedInteraction: for "
1052  << particle->GetParticleName()
1053  << " and process " << GetProcessName()
1054  << " length(mm)= " << length/mm
1055  << " in G4Region <" << r
1056  << "> weightFlag= " << flag
1057  << G4endl;
1058  }
1059  weightFlag = flag;
1060  biasManager->ActivateForcedInteraction(length, r);
1061 }
1062 
1063 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1064 
1065 void
1067  G4double factor,
1068  G4double energyLimit)
1069 {
1070  if (0.0 <= factor) {
1071 
1072  // Range cut can be applied only for e-
1073  if(0.0 == factor && secondaryParticle != G4Electron::Electron())
1074  { return; }
1075 
1076  if(!biasManager) { biasManager = new G4EmBiasingManager(); }
1077  biasManager->ActivateSecondaryBiasing(region, factor, energyLimit);
1078  if(1 < verboseLevel) {
1079  G4cout << "### ActivateSecondaryBiasing: for "
1080  << " process " << GetProcessName()
1081  << " factor= " << factor
1082  << " in G4Region <" << region
1083  << "> energyLimit(MeV)= " << energyLimit/MeV
1084  << G4endl;
1085  }
1086  }
1087 }
1088 
1089 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1090 
1092 {
1093  nLambdaBins = G4lrint(nLambdaBins*std::log(maxKinEnergy/e)
1094  /std::log(maxKinEnergy/minKinEnergy));
1095  minKinEnergy = e;
1096 }
1097 
1098 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1099 
1101 {
1102  nLambdaBins = G4lrint(nLambdaBins*std::log(e/minKinEnergy)
1103  /std::log(maxKinEnergy/minKinEnergy));
1104  maxKinEnergy = e;
1105 }
1106 
1107 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....