Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/physics_lists/constructors/electromagnetic/src/G4EmModelActivator.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  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 //
 29 // ClassName:   G4EmModelActivator
 30 //
 31 // Author:      V.Ivanchenko 01.06.2015
 32 //
 33 // Organisation:   G4AI
 34 // Contract:       ESA contract 4000107387/12/NL/AT
 35 // Customer:       ESA/ESTEC
 36 //
 37 // Modified:
 38 //
 39 //----------------------------------------------------------------------------
 40 //
 41 
 42 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
 43 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
 44 
 45 #include "G4EmModelActivator.hh"
 46 #include "G4EmParameters.hh"
 47 #include "G4ParticleDefinition.hh"
 48 #include "G4ParticleTable.hh"
 49 #include "G4RegionStore.hh"
 50 #include "G4Region.hh"
 51 #include "G4VEnergyLossProcess.hh"
 52 #include "G4VMscModel.hh"
 53 #include "G4LossTableManager.hh"
 54 #include "G4EmConfigurator.hh"
 55 #include "G4PAIModel.hh"
 56 #include "G4PAIPhotModel.hh"
 57 #include "G4Gamma.hh"
 58 #include "G4Electron.hh"
 59 #include "G4Positron.hh"
 60 #include "G4MuonPlus.hh"
 61 #include "G4MuonMinus.hh"
 62 #include "G4Proton.hh"
 63 #include "G4GenericIon.hh"
 64 #include "G4Alpha.hh"
 65 #include "G4ProcessManager.hh"
 66 #include "G4DummyModel.hh"
 67 #include "G4EmProcessSubType.hh"
 68 #include "G4PhysicsListHelper.hh"
 69 #include "G4EmParticleList.hh"
 70 #include "G4EmUtility.hh"
 71 
 72 #include "G4MicroElecElastic.hh"
 73 #include "G4MicroElecElasticModel.hh"
 74 
 75 #include "G4MicroElecInelastic.hh"
 76 #include "G4MicroElecInelasticModel.hh"
 77 
 78 #include "G4BraggModel.hh"
 79 #include "G4BraggIonModel.hh"
 80 #include "G4BetheBlochModel.hh"
 81 #include "G4UrbanMscModel.hh"
 82 #include "G4MollerBhabhaModel.hh"
 83 #include "G4IonFluctuations.hh"
 84 #include "G4UniversalFluctuation.hh"
 85 #include "G4LowECapture.hh"
 86 #include "G4hMultipleScattering.hh"
 87 #include "G4eCoulombScatteringModel.hh"
 88 #include "G4IonCoulombScatteringModel.hh"
 89 #include "G4ionIonisation.hh"
 90 #include "G4KleinNishinaModel.hh"
 91 
 92 #include "G4GammaGeneralProcess.hh"
 93 #include "G4CoulombScattering.hh"
 94 #include "G4eCoulombScatteringModel.hh"
 95 #include "G4WentzelVIModel.hh"
 96 #include "G4UniversalFluctuation.hh"
 97 #include "G4RayleighScattering.hh" 
 98 #include "G4UrbanMscModel.hh"
 99 #include "G4GoudsmitSaundersonMscModel.hh"
100 #include "G4LowEPComptonModel.hh"
101 #include "G4BetheHeitler5DModel.hh"
102 #include "G4LindhardSorensenIonModel.hh"
103 
104 #include "G4LivermorePhotoElectricModel.hh"
105 #include "G4LivermoreComptonModel.hh"
106 #include "G4LivermoreGammaConversionModel.hh"
107 #include "G4LivermoreRayleighModel.hh"
108 #include "G4LivermoreIonisationModel.hh"
109 #include "G4LivermoreBremsstrahlungModel.hh"
110 
111 #include "G4PenelopePhotoElectricModel.hh"
112 #include "G4PenelopeComptonModel.hh"
113 #include "G4PenelopeGammaConversionModel.hh"
114 #include "G4PenelopeRayleighModel.hh"
115 #include "G4PenelopeIonisationModel.hh"
116 #include "G4PenelopeBremsstrahlungModel.hh"
117 #include "G4PenelopeAnnihilationModel.hh"
118 
119 #include "G4SystemOfUnits.hh"
120 #include "G4Threading.hh"
121 #include <vector>
122 
123 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
124 
125 G4EmModelActivator::G4EmModelActivator(const G4String& emphys)
126   : baseName(emphys)
127 {
128   theParameters = G4EmParameters::Instance();
129 
130   const std::vector<G4String>& regnamesPAI = theParameters->RegionsPAI();
131   if(regnamesPAI.size() > 0)
132   {
133     ActivatePAI();
134   }
135   const std::vector<G4String>& regnamesME = theParameters->RegionsMicroElec();
136   if(regnamesME.size() > 0)
137   {
138     ActivateMicroElec();
139   }
140   const std::vector<G4String>& regnamesMSC = theParameters->RegionsPhysics();
141   if(regnamesMSC.size() > 0)
142   {
143     ActivateEmOptions();
144   }
145 }
146 
147 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
148 
149 void G4EmModelActivator::ActivateEmOptions()
150 {
151   const std::vector<G4String>& regnamesPhys = theParameters->RegionsPhysics();
152   std::size_t nreg = regnamesPhys.size();
153   if(0 == nreg) { return; }
154   G4int verbose = theParameters->Verbose() - 1;
155   if(verbose > 0) {
156     G4cout << "### G4EmModelActivator::ActivateEmOptions for " << nreg << " regions"
157            << G4endl;
158   }
159   const std::vector<G4String>& typesPhys = theParameters->TypesPhysics();
160 
161   // start configuration of models
162   const G4ParticleDefinition* elec = G4Electron::Electron();
163   const G4ParticleDefinition* posi = G4Positron::Positron();
164   const G4ParticleDefinition* phot = G4Gamma::Gamma();
165   const G4ParticleDefinition* prot = G4Proton::Proton();
166   G4LossTableManager* man = G4LossTableManager::Instance();
167   G4EmConfigurator* em_config = man->EmConfigurator();
168   G4VAtomDeexcitation* adeexc = man->AtomDeexcitation(); 
169   G4ParticleTable* table = G4ParticleTable::GetParticleTable();
170   G4VEmModel* mod = nullptr;
171   G4VEmProcess* proc = nullptr;
172 
173   // high energy limit for low-energy e+- model of msc
174   G4double mscEnergyLimit = theParameters->MscEnergyLimit();
175 
176   // high energy limit for Livermore and Penelope models
177   G4double highEnergyLimit = 1*GeV;
178 
179   // general high energy limit
180   G4double highEnergy = theParameters->MaxKinEnergy();
181 
182   for(std::size_t i=0; i<nreg; ++i) {
183     const G4String reg = regnamesPhys[i];
184     auto region = G4EmUtility::FindRegion(reg);
185     if(verbose > 0) {
186       G4cout << i << ". region <" << reg << ">; physics type <"
187        << typesPhys[i] << "> region ptr: " << region << G4endl;
188     }
189 
190     if(baseName == typesPhys[i]) { continue; }
191 
192     if("G4EmStandard" == typesPhys[i]) {
193       G4UrbanMscModel* msc = new G4UrbanMscModel();
194       AddStandardScattering(elec, em_config, msc, reg,  mscEnergyLimit, highEnergy, typesPhys[i]);
195       
196       msc = new G4UrbanMscModel();
197       AddStandardScattering(posi, em_config, msc, reg, mscEnergyLimit, highEnergy, typesPhys[i]);
198 
199     } else if("G4EmStandard_opt1" == typesPhys[i] || "G4EmStandard_opt2" == typesPhys[i]) {
200       G4UrbanMscModel* msc = new G4UrbanMscModel();
201       AddStandardScattering(elec, em_config, msc, reg, mscEnergyLimit, highEnergy, typesPhys[i]);
202 
203       msc = new G4UrbanMscModel();
204       AddStandardScattering(posi, em_config, msc, reg,  mscEnergyLimit, highEnergy, typesPhys[i]);
205       
206     } else if("G4EmStandard_opt3" == typesPhys[i]) { 
207 
208       G4DummyModel* dummy = new G4DummyModel();
209       G4UrbanMscModel* msc = new G4UrbanMscModel();
210       SetMscParameters(elec, msc, typesPhys[i]);
211       em_config->SetExtraEmModel("e-", "msc", msc, reg);
212       proc = FindOrAddProcess(elec, "CoulombScat");
213       proc->AddEmModel(-1, dummy, region);
214 
215       msc = new G4UrbanMscModel();
216       SetMscParameters(posi, msc, typesPhys[i]);
217       em_config->SetExtraEmModel("e+", "msc", msc, reg);
218       proc = FindOrAddProcess(posi, "CoulombScat");
219       proc->AddEmModel(-1, dummy, region);
220 
221       msc = new G4UrbanMscModel();
222       SetMscParameters(prot, msc, typesPhys[i]);
223       em_config->SetExtraEmModel("proton", "msc", msc, reg);
224       proc = FindOrAddProcess(prot, "CoulombScat");
225       proc->AddEmModel(-1, dummy, region);
226 
227       theParameters->SetNumberOfBinsPerDecade(20);
228       if(G4Threading::IsMasterThread()) {
229         theParameters->SetDeexActiveRegion(reg, true, false, false);
230       }
231       theParameters->DefineRegParamForDeex(adeexc);
232       proc = FindOrAddProcess(phot, "Rayl");
233       proc->AddEmModel(-1, new G4LivermoreRayleighModel(), region);
234       proc = FindOrAddProcess(phot, "compt");
235       proc->AddEmModel(-1, new G4KleinNishinaModel(), region);
236 
237     } else if("G4EmStandard_opt4" == typesPhys[i]) {
238       G4VMscModel* msc = new G4GoudsmitSaundersonMscModel();
239       AddStandardScattering(elec, em_config, msc, reg, mscEnergyLimit, highEnergy, typesPhys[i]);
240 
241       msc = new G4GoudsmitSaundersonMscModel();
242       AddStandardScattering(posi, em_config, msc, reg, mscEnergyLimit, highEnergy, typesPhys[i]);
243 
244       theParameters->SetNumberOfBinsPerDecade(20);
245       theParameters->SetUseMottCorrection(true);  
246       if(G4Threading::IsMasterThread()) {
247         theParameters->SetDeexActiveRegion(reg, true, false, false);
248       }
249       theParameters->DefineRegParamForDeex(adeexc);
250 
251       proc = FindOrAddProcess(phot, "Rayl");
252       proc->AddEmModel(-1, new G4LivermoreRayleighModel(), region);
253       proc = FindOrAddProcess(phot, "compt");
254       proc->AddEmModel(-1, new G4KleinNishinaModel(), region);
255       mod = new G4LowEPComptonModel();
256       mod->SetHighEnergyLimit(20*MeV);
257       proc->AddEmModel(-2, mod, region);
258       proc = FindOrAddProcess(phot, "conv");
259       proc->AddEmModel(-1, new G4BetheHeitler5DModel(), region);
260 
261     } else if("G4EmStandardGS" == typesPhys[i]) {
262       G4GoudsmitSaundersonMscModel* msc = new G4GoudsmitSaundersonMscModel();
263       AddStandardScattering(elec, em_config, msc, reg, mscEnergyLimit, highEnergy, typesPhys[i]);
264 
265       msc = new G4GoudsmitSaundersonMscModel();
266       AddStandardScattering(posi, em_config, msc, reg, mscEnergyLimit, highEnergy, typesPhys[i]);
267 
268     } else if("G4EmStandardWVI" == typesPhys[i]) {
269       G4WentzelVIModel* msc = new G4WentzelVIModel();
270       AddStandardScattering(elec, em_config, msc, reg, mscEnergyLimit, highEnergy, typesPhys[i]);
271 
272       msc = new G4WentzelVIModel();
273       AddStandardScattering(posi, em_config, msc, reg, mscEnergyLimit, highEnergy, typesPhys[i]);
274 
275       theParameters->SetMscThetaLimit(0.15);
276  
277       if(G4Threading::IsMasterThread()) {
278         theParameters->SetDeexActiveRegion(regnamesPhys[i], true, false, false);
279       }
280       theParameters->DefineRegParamForDeex(adeexc);
281 
282     } else if("G4EmStandardSS" == typesPhys[i]) {
283       G4EmParticleList emList;
284       for(const auto& particleName : emList.EmChargedPartNames()) {
285   G4ParticleDefinition* particle = table->FindParticle(particleName);
286         if(nullptr != particle && 0.0 != particle->GetPDGCharge()) {
287     proc = FindOrAddProcess(particle, "CoulombScat");
288           if(nullptr != proc) {
289       proc->AddEmModel(-1, new G4DummyModel(), region);
290     }
291     auto pm = particle->GetProcessManager();
292           proc = new G4CoulombScattering("SingleCoulombScat", false);
293     pm->AddDiscreteProcess(proc);
294           proc->SetEmModel(new G4DummyModel());
295           G4VEmModel* scmod = nullptr;
296           if(particle->GetPDGMass() > CLHEP::GeV ||
297              particle->GetParticleType() == "nucleus") {
298       scmod = new G4IonCoulombScatteringModel();
299     } else {
300       scmod = new G4eCoulombScatteringModel(false);
301     }
302     scmod->SetPolarAngleLimit(0.0);
303     scmod->SetLocked(true);
304     proc->AddEmModel(-1, scmod, region);
305 
306     // multiple scattering should be disabled
307           if(particleName == "mu+" || particleName == "mu-") {
308       em_config->SetExtraEmModel(particleName, "muMsc", 
309                new G4DummyModel(), reg);
310     } else {
311       em_config->SetExtraEmModel(particleName, "msc", 
312                new G4DummyModel(), reg);
313     }
314   }
315       }
316       if(G4Threading::IsMasterThread()) {
317         theParameters->SetDeexActiveRegion(regnamesPhys[i], true, true, true);
318       }
319       theParameters->DefineRegParamForDeex(adeexc);
320 
321     } else if("G4EmLivermore" == typesPhys[i]) {
322 
323       G4VMscModel* msc = new G4GoudsmitSaundersonMscModel();
324       AddStandardScattering(elec, em_config, msc, reg, mscEnergyLimit, highEnergy, typesPhys[i]);
325 
326       msc = new G4GoudsmitSaundersonMscModel();
327       AddStandardScattering(posi, em_config, msc, reg, mscEnergyLimit, highEnergy, typesPhys[i]);
328 
329       mod = new G4LivermorePhotoElectricModel();
330       em_config->SetExtraEmModel("gamma", "phot", mod, reg);
331       mod = new G4LivermoreComptonModel();
332       em_config->SetExtraEmModel("gamma", "compt", mod, reg);
333       mod = new G4LivermoreGammaConversionModel();
334       em_config->SetExtraEmModel("gamma", "conv", mod, reg);
335 
336       FindOrAddProcess(phot, "Rayl");
337       mod = new G4LivermoreRayleighModel();
338       em_config->SetExtraEmModel("gamma", "Rayl", mod, reg);
339 
340       mod = new G4LivermoreIonisationModel();
341       G4UniversalFluctuation* uf = new G4UniversalFluctuation();
342       em_config->SetExtraEmModel("e-", "eIoni", mod, reg, 0.0, 0.1*MeV, uf);
343       mod = new G4LivermoreBremsstrahlungModel();
344       em_config->SetExtraEmModel("e-", "eBrem", mod, reg, 0.0, highEnergyLimit);
345 
346       theParameters->SetNumberOfBinsPerDecade(20);
347       theParameters->SetUseMottCorrection(true);  
348       if(G4Threading::IsMasterThread()) {
349         theParameters->SetDeexActiveRegion(regnamesPhys[i], true, false, false);
350       }
351       theParameters->DefineRegParamForDeex(adeexc);
352 
353     } else if("G4EmPenelope" == typesPhys[i]) {
354 
355       G4VMscModel* msc = new G4GoudsmitSaundersonMscModel();
356       AddStandardScattering(elec, em_config, msc, reg, mscEnergyLimit, highEnergy, typesPhys[i]);
357 
358       msc = new G4GoudsmitSaundersonMscModel();
359       AddStandardScattering(posi, em_config, msc, reg, mscEnergyLimit, highEnergy, typesPhys[i]);
360 
361       mod = new G4PenelopePhotoElectricModel();
362       em_config->SetExtraEmModel("gamma", "phot", mod, reg);
363       mod = new G4PenelopeComptonModel();
364       em_config->SetExtraEmModel("gamma", "compt", mod, reg);
365       mod = new G4PenelopeGammaConversionModel();
366       em_config->SetExtraEmModel("gamma", "conv", mod, reg);
367 
368       FindOrAddProcess(phot, "Rayl");
369       mod = new G4PenelopeRayleighModel();
370       em_config->SetExtraEmModel("gamma", "Rayl", mod, reg);
371 
372       mod = new G4PenelopeIonisationModel();
373       G4UniversalFluctuation* uf = new G4UniversalFluctuation();
374       em_config->SetExtraEmModel("e-", "eIoni", mod, reg, 0.0, highEnergyLimit, uf);
375       mod = new G4PenelopeBremsstrahlungModel();
376       em_config->SetExtraEmModel("e-", "eBrem", mod, reg, 0.0, highEnergyLimit);
377 
378       mod = new G4PenelopeIonisationModel();
379       uf = new G4UniversalFluctuation();
380       em_config->SetExtraEmModel("e+", "eIoni", mod, reg, 0.0, highEnergyLimit, uf);
381       mod = new G4PenelopeBremsstrahlungModel();
382       em_config->SetExtraEmModel("e+", "eBrem", mod, reg, 0.0, highEnergyLimit);
383       mod = new G4PenelopeAnnihilationModel();
384       em_config->SetExtraEmModel("e+", "annihil", mod, reg, 0.0, highEnergyLimit);
385 
386       theParameters->SetNumberOfBinsPerDecade(20);
387       theParameters->SetUseMottCorrection(true);  
388       if(G4Threading::IsMasterThread()) {
389         theParameters->SetDeexActiveRegion(regnamesPhys[i], true, false, false);
390       }
391       theParameters->DefineRegParamForDeex(adeexc);
392 
393     } else {
394       if(verbose > 0 && G4Threading::IsMasterThread()) {
395         G4cout << "### G4EmModelActivator::ActivateEmOptions WARNING: \n"
396          << "    EM Physics configuration name <" << typesPhys[i]
397          << "> is not known - ignored" << G4endl;
398       }
399     }
400   }
401 }
402 
403 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
404 
405 void G4EmModelActivator::ActivatePAI()
406 {
407   const std::vector<G4String> regnamesPAI = theParameters->RegionsPAI();
408   std::size_t nreg = regnamesPAI.size();
409   if(0 == nreg) { return; }
410   G4int verbose = theParameters->Verbose() - 1;
411   if(verbose > 0) {
412     G4cout << "### G4EmModelActivator::ActivatePAI for " << nreg << " regions"
413            << G4endl;
414   }
415   const std::vector<G4String> particlesPAI = theParameters->ParticlesPAI();
416   const std::vector<G4String> typesPAI = theParameters->TypesPAI();
417 
418   const std::vector<G4VEnergyLossProcess*>& v = G4LossTableManager::Instance()
419       ->GetEnergyLossProcessVector();
420 
421   G4RegionStore* regionStore = G4RegionStore::GetInstance();
422 
423   const G4ParticleDefinition* elec = G4Electron::Electron();
424   const G4ParticleDefinition* posi = G4Positron::Positron();
425   const G4ParticleDefinition* mupl = G4MuonPlus::MuonPlus();
426   const G4ParticleDefinition* mumi = G4MuonMinus::MuonMinus();
427   const G4ParticleDefinition* gion = G4GenericIon::GenericIon();
428 
429   for(std::size_t i = 0; i < nreg; ++i) {
430     const G4ParticleDefinition* p = nullptr;
431     if(particlesPAI[i] != "all") {
432       p = G4ParticleTable::GetParticleTable()->FindParticle(particlesPAI[i]);
433       if(!p) {
434         G4cout << "### WARNING: ActivatePAI::FindParticle fails to find "
435                << particlesPAI[i] << G4endl;
436         continue;
437       }
438     }
439     const G4Region* r = regionStore->GetRegion(regnamesPAI[i], false);
440     if(!r) {
441       G4cout << "### WARNING: ActivatePAI::GetRegion fails to find "
442        << regnamesPAI[i] << G4endl;
443       continue;
444     }
445 
446     G4String name = "hIoni";
447     if(p == elec || p == posi)
448       { name = "eIoni"; }
449     else if (p == mupl || p == mumi)
450       { name = "muIoni"; }
451     else if (p == gion)
452       { name = "ionIoni"; }
453 
454     for(auto proc : v) {
455 
456       if(!proc->IsIonisationProcess()) { continue; }
457 
458       G4String namep = proc->GetProcessName();
459       if(p) {        
460   if(name != namep) { continue; }
461       } else {
462         if(namep != "hIoni" && namep != "muIoni" && 
463      namep != "eIoni" && namep != "ionIoni")
464     { continue; }
465       }
466       G4double emin = 50*CLHEP::keV;
467       if(namep == "eIoni") emin = 110*CLHEP::eV;
468       else if(namep == "muIoni") emin = 5*CLHEP::keV;
469 
470       G4VEmModel* em = nullptr;
471       G4VEmFluctuationModel* fm = nullptr;
472       if(typesPAI[i] == "PAIphoton" || typesPAI[i] == "pai_photon") {
473   G4PAIPhotModel* mod = new G4PAIPhotModel(p,"PAIPhotModel");
474   em = mod;
475   fm = mod;
476       } else {
477   G4PAIModel* mod = new G4PAIModel(p,"PAIModel");
478   em = mod;
479   fm = mod;
480       }
481       // first added the default model for world
482       // second added low energy model below PAI threshold in the region
483       // finally added PAI for the region
484       G4VEmModel* em0 = nullptr;
485       G4VEmFluctuationModel* fm0 = nullptr;
486       if(namep == "eIoni") {
487         fm0 = new G4UniversalFluctuation();
488         proc->SetEmModel(new G4MollerBhabhaModel());
489         proc->SetFluctModel(fm0);
490         em0 = new G4MollerBhabhaModel();
491       } else if(namep == "ionIoni") {
492         fm0 = new G4IonFluctuations();
493         proc->SetEmModel(new G4LindhardSorensenIonModel());
494         proc->SetFluctModel(fm0);
495         em0 = new G4LindhardSorensenIonModel();
496       } else {
497         fm0 = new G4UniversalFluctuation();
498         proc->SetEmModel(new G4BraggModel());
499         proc->SetEmModel(new G4BetheBlochModel());
500         proc->SetFluctModel(fm0);
501         em0 = new G4BraggModel();
502       }
503       em0->SetHighEnergyLimit(emin);
504       proc->AddEmModel(-1, em0, fm0, r);
505       em->SetLowEnergyLimit(emin);
506       proc->AddEmModel(-1, em, fm, r);
507       if(verbose > 0) {
508   G4cout << "### G4EmModelActivator: add <" << typesPAI[i]
509          << "> model for " << particlesPAI[i]
510          << " in the " << regnamesPAI[i] 
511                << " Emin(keV)= " << emin/CLHEP::keV << G4endl;
512       }
513     }
514   }
515 }
516 
517 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
518 
519 void G4EmModelActivator::ActivateMicroElec()
520 {
521   const std::vector<G4String> regnamesME = theParameters->RegionsMicroElec();
522   std::size_t nreg = regnamesME.size();
523   if(0 == nreg)
524   {
525     return;
526   }
527   G4int verbose = theParameters->Verbose() - 1;
528   if(verbose > 0)
529   {
530     G4cout << "### G4EmModelActivator::ActivateMicroElec for " << nreg
531            << " regions" << G4endl;
532   }
533   G4LossTableManager* man = G4LossTableManager::Instance();
534 
535   const G4ParticleDefinition* elec = G4Electron::Electron();
536   const G4ParticleDefinition* prot = G4Proton::Proton();
537   const G4ParticleDefinition* gion = G4GenericIon::GenericIon();
538   G4ProcessManager* eman = elec->GetProcessManager();
539   G4ProcessManager* pman = prot->GetProcessManager();
540   G4ProcessManager* iman = gion->GetProcessManager();
541 
542   G4bool emsc = HasMsc(eman);
543 
544   // MicroElec elastic is not active in the world 
545   G4MicroElecElastic* eElasProc =
546       new G4MicroElecElastic("e-G4MicroElecElastic");
547   eman->AddDiscreteProcess(eElasProc);
548 
549   G4MicroElecInelastic* eInelProc =
550       new G4MicroElecInelastic("e-G4MicroElecInelastic");
551   eman->AddDiscreteProcess(eInelProc);
552 
553   G4MicroElecInelastic* pInelProc =
554       new G4MicroElecInelastic("p_G4MicroElecInelastic");
555   pman->AddDiscreteProcess(pInelProc);
556 
557   G4MicroElecInelastic* iInelProc =
558       new G4MicroElecInelastic("ion_G4MicroElecInelastic");
559   iman->AddDiscreteProcess(iInelProc);
560 
561   // start configuration of models
562   G4EmConfigurator* em_config = man->EmConfigurator();
563   G4VEmModel* mod;
564 
565   // limits for MicroElec applicability
566   G4double elowest = 16.7 * eV;
567   G4double elimel = 100 * MeV;
568   G4double elimin = 9 * MeV;
569   G4double pmin = 50 * keV;
570   G4double pmax = 99.9 * MeV;
571 
572   G4LowECapture* ecap = new G4LowECapture(elowest);
573   eman->AddDiscreteProcess(ecap);
574 
575   for(std::size_t i = 0; i < nreg; ++i)
576   {
577 
578     G4String reg = regnamesME[i];
579     G4cout << "### MicroElec models are activated for G4Region " << reg
580            << G4endl
581            << "    Energy limits for e- elastic:    " << elowest/eV << " eV - "
582            << elimel/MeV << " MeV"
583            << G4endl
584            << "    Energy limits for e- inelastic:  " << elowest/eV << " eV - "
585            << elimin/MeV << " MeV"
586            << G4endl
587            << "    Energy limits for hadrons/ions:  " << pmin/MeV << " MeV - "
588            << pmax/MeV << " MeV"
589            << G4endl;
590 
591     // e-  
592     if(emsc)
593     {
594       G4UrbanMscModel* msc = new G4UrbanMscModel();
595       msc->SetActivationLowEnergyLimit(elimel);
596       em_config->SetExtraEmModel("e-", "msc", msc, reg);
597     }
598     else
599     {
600       mod = new G4DummyModel();
601       em_config->SetExtraEmModel("e-", "CoulombScat", mod, reg, 0.0, elimel);
602     }
603 
604     mod = new G4MicroElecElasticModel();
605     em_config->SetExtraEmModel("e-",
606                                "e-G4MicroElecElastic",
607                                mod,
608                                reg,
609                                elowest,
610                                elimin);
611 
612     mod = new G4MollerBhabhaModel();
613     mod->SetActivationLowEnergyLimit(elimin);
614     em_config->SetExtraEmModel("e-",
615                                "eIoni",
616                                mod,
617                                reg,
618                                0.0,
619                                10 * TeV,
620                                new G4UniversalFluctuation());
621 
622     mod = new G4MicroElecInelasticModel();
623     em_config->SetExtraEmModel("e-",
624                                "e-G4MicroElecInelastic",
625                                mod,
626                                reg,
627                                elowest,
628                                elimin);
629 
630     // proton
631     mod = new G4BraggModel();
632     mod->SetActivationHighEnergyLimit(pmin);
633     em_config->SetExtraEmModel("proton",
634                                "hIoni",
635                                mod,
636                                reg,
637                                0.0,
638                                2 * MeV,
639                                new G4UniversalFluctuation());
640 
641     mod = new G4BetheBlochModel();
642     mod->SetActivationLowEnergyLimit(pmax);
643     em_config->SetExtraEmModel("proton",
644                                "hIoni",
645                                mod,
646                                reg,
647                                2 * MeV,
648                                10 * TeV,
649                                new G4UniversalFluctuation());
650 
651     mod = new G4MicroElecInelasticModel();
652     em_config->SetExtraEmModel("proton",
653                                "p_G4MicroElecInelastic",
654                                mod,
655                                reg,
656                                pmin,
657                                pmax);
658 
659     // ions
660     mod = new G4BraggIonModel();
661     mod->SetActivationHighEnergyLimit(pmin);
662     em_config->SetExtraEmModel("GenericIon",
663                                "ionIoni",
664                                mod,
665                                reg,
666                                0.0,
667                                2 * MeV,
668                                new G4IonFluctuations());
669 
670     mod = new G4BetheBlochModel();
671     mod->SetActivationLowEnergyLimit(pmax);
672     em_config->SetExtraEmModel("GenericIon",
673                                "ionIoni",
674                                mod,
675                                reg,
676                                2 * MeV,
677                                10 * TeV,
678                                new G4IonFluctuations());
679 
680     mod = new G4MicroElecInelasticModel();
681     em_config->SetExtraEmModel("GenericIon",
682                                "ion_G4MicroElecInelastic",
683                                mod,
684                                reg,
685                                pmin,
686                                pmax);
687   }
688 }
689 
690 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
691 
692 G4bool G4EmModelActivator::HasMsc(G4ProcessManager* pm) const
693 {
694   G4bool res = false;
695   G4ProcessVector* pv = pm->GetProcessList();
696   G4int nproc = pm->GetProcessListLength();
697   for(G4int i = 0; i < nproc; ++i)
698   {
699     if(((*pv)[i])->GetProcessSubType() == fMultipleScattering)
700     {
701       res = true;
702       break;
703     }
704   }
705   return res;
706 }
707 
708 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
709 
710 void G4EmModelActivator::AddStandardScattering(const G4ParticleDefinition* part,
711                                                G4EmConfigurator* em_config,
712                                                G4VMscModel* mscmod,
713                                                const G4String& reg, 
714                                                G4double e1, G4double e2,
715                                                const G4String& type)
716 {
717   G4String pname = part->GetParticleName();
718 
719   // low-energy msc model
720   SetMscParameters(part, mscmod, type);
721   em_config->SetExtraEmModel(pname, "msc", mscmod, reg, 0.0, e1);
722 
723   // high energy msc model
724   G4WentzelVIModel* msc = new G4WentzelVIModel();
725   SetMscParameters(part, msc, type);
726   em_config->SetExtraEmModel(pname, "msc", msc, reg, e1, e2);
727 
728   // high energy single scattering model
729   FindOrAddProcess(part, "CoulombScat");
730   G4eCoulombScatteringModel* mod = new G4eCoulombScatteringModel();
731   mod->SetActivationLowEnergyLimit(e1);
732   mod->SetLocked(true);
733   em_config->SetExtraEmModel(pname, "CoulombScat", mod, reg, 0.0, e2);
734 }
735 
736 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
737 
738 void G4EmModelActivator::SetMscParameters(const G4ParticleDefinition* part, 
739                                           G4VMscModel* msc, const G4String& phys) 
740 {
741   if(part == G4Electron::Electron() || part == G4Positron::Positron()) {
742     if(phys == "G4EmStandard_opt1" || phys == "G4EmStandard_opt2") {
743       msc->SetRangeFactor(0.2);
744       msc->SetStepLimitType(fMinimal);
745     } else if(phys == "G4EmStandard_opt3") {
746       msc->SetStepLimitType(fUseDistanceToBoundary);
747     } else if(phys == "G4EmStandard_opt4" || phys == "G4EmLivermore" || phys == "G4EmPenelope") {
748       msc->SetRangeFactor(0.08);
749       msc->SetStepLimitType(fUseSafetyPlus);
750       msc->SetSkin(3);
751     } else if(phys == "G4EmStandardGS") {
752       msc->SetRangeFactor(0.06);
753     }
754   } else {
755     if(phys != "G4EmStandard" && phys != "G4EmStandard_opt1" && phys != "G4EmStandard_opt2") {
756       msc->SetLateralDisplasmentFlag(true); 
757     }
758   }
759   msc->SetLocked(true);
760 }
761 
762 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
763 
764 G4VEmProcess* 
765 G4EmModelActivator::FindOrAddProcess(const G4ParticleDefinition* part, 
766              const G4String& name)
767 {
768   G4VEmProcess* proc = nullptr;
769   auto pm = part->GetProcessManager();
770   auto emproc = pm->GetProcessList();
771   G4int n = (G4int)emproc->size();
772   for(auto i=0; i<n; ++i) {
773     auto ptr = (*emproc)[i];
774     if(part->GetPDGEncoding() == 22 && 
775        ptr->GetProcessSubType() == fGammaGeneralProcess) {
776       proc = (static_cast<G4GammaGeneralProcess*>(ptr))->GetEmProcess(name);
777     } else if(ptr->GetProcessName() == name) {
778       proc = dynamic_cast<G4VEmProcess*>(ptr);
779     }
780     if(nullptr != proc) { return proc; }
781   }
782   if(name == "Rayl") {
783     G4RayleighScattering* rs = new G4RayleighScattering();
784     rs->SetEmModel(new G4DummyModel());
785     pm->AddDiscreteProcess(rs);
786     return rs;
787   }
788   return proc;
789 }
790 
791 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
792