source: trunk/source/processes/electromagnetic/utils/src/G4VEnergyLossProcess.cc@ 1315

Last change on this file since 1315 was 1315, checked in by garnier, 15 years ago

update geant4-09-04-beta-cand-01 interfaces-V09-03-09 vis-V09-03-08

File size: 57.9 KB
RevLine 
[819]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//
[1315]26// $Id: G4VEnergyLossProcess.cc,v 1.167 2010/05/26 10:41:34 vnivanch Exp $
27// GEANT4 tag $Name: geant4-09-04-beta-cand-01 $
[819]28//
29// -------------------------------------------------------------------
30//
31// GEANT4 Class file
32//
33//
34// File name: G4VEnergyLossProcess
35//
36// Author: Vladimir Ivanchenko
37//
38// Creation date: 03.01.2002
39//
40// Modifications:
41//
42// 13-11-02 Minor fix - use normalised direction (V.Ivanchenko)
43// 04-12-02 Minor change in PostStepDoIt (V.Ivanchenko)
44// 23-12-02 Change interface in order to move to cut per region (V.Ivanchenko)
45// 26-12-02 Secondary production moved to derived classes (V.Ivanchenko)
46// 04-01-03 Fix problem of very small steps for ions (V.Ivanchenko)
47// 20-01-03 Migrade to cut per region (V.Ivanchenko)
48// 24-01-03 Temporarily close a control on usage of couples (V.Ivanchenko)
49// 24-01-03 Make models region aware (V.Ivanchenko)
50// 05-02-03 Fix compilation warnings (V.Ivanchenko)
51// 06-02-03 Add control on tmax in PostStepDoIt (V.Ivanchenko)
52// 13-02-03 SubCutoffProcessors defined for regions (V.Ivanchenko)
53// 15-02-03 Lambda table can be scaled (V.Ivanchenko)
54// 17-02-03 Fix problem of store/restore tables (V.Ivanchenko)
55// 18-02-03 Add control on CutCouple usage (V.Ivanchenko)
56// 26-02-03 Simplify control on GenericIons (V.Ivanchenko)
57// 06-03-03 Control on GenericIons using SubType + update verbose (V.Ivanchenko)
58// 10-03-03 Add Ion registration (V.Ivanchenko)
59// 22-03-03 Add Initialisation of cash (V.Ivanchenko)
60// 26-03-03 Remove finalRange modification (V.Ivanchenko)
61// 09-04-03 Fix problem of negative range limit for non integral (V.Ivanchenko)
62// 26-04-03 Fix retrieve tables (V.Ivanchenko)
63// 06-05-03 Set defalt finalRange = 1 mm (V.Ivanchenko)
64// 12-05-03 Update range calculations + lowKinEnergy (V.Ivanchenko)
65// 13-05-03 Add calculation of precise range (V.Ivanchenko)
66// 23-05-03 Remove tracking cuts (V.Ivanchenko)
67// 03-06-03 Fix initialisation problem for STD ionisation (V.Ivanchenko)
68// 21-07-03 Add UpdateEmModel method (V.Ivanchenko)
69// 03-11-03 Fix initialisation problem in RetrievePhysicsTable (V.Ivanchenko)
70// 04-11-03 Add checks in RetrievePhysicsTable (V.Ivanchenko)
71// 12-11-03 G4EnergyLossSTD -> G4EnergyLossProcess (V.Ivanchenko)
72// 21-01-04 Migrade to G4ParticleChangeForLoss (V.Ivanchenko)
73// 27-02-04 Fix problem of loss in low presure gases, cleanup precise range
74// calculation, use functions ForLoss in AlongStepDoIt (V.Ivanchenko)
75// 10-03-04 Fix a problem of Precise Range table (V.Ivanchenko)
76// 19-03-04 Fix a problem energy below lowestKinEnergy (V.Ivanchenko)
77// 31-03-04 Fix a problem of retrieve tables (V.Ivanchenko)
78// 21-07-04 Check weather AtRest are active or not (V.Ivanchenko)
79// 03-08-04 Add pointer of DEDX table to all processes (V.Ivanchenko)
80// 06-08-04 Clear up names of member functions (V.Ivanchenko)
81// 06-08-04 Clear up names of member functions (V.Ivanchenko)
82// 27-08-04 Add NeedBuildTables method (V.Ivanchneko)
83// 08-11-04 Migration to new interface of Store/Retrieve tables (V.Ivantchenko)
84// 11-03-05 Shift verbose level by 1 (V.Ivantchenko)
85// 08-04-05 Major optimisation of internal interfaces (V.Ivantchenko)
86// 11-04-05 Use MaxSecondaryEnergy from a model (V.Ivanchenko)
87// 25-07-05 Add extra protection PostStep for non-integral mode (V.Ivanchenko)
88// 12-08-05 Integral=false; SetStepFunction(0.2, 0.1*mm) (mma)
89// 18-08-05 Return back both AlongStep and PostStep from 7.0 (V.Ivanchenko)
90// 02-09-05 Default StepFunction 0.2 1 mm + integral (V.Ivanchenko)
91// 04-09-05 default lambdaFactor 0.8 (V.Ivanchenko)
92// 05-10-05 protection against 0 energy loss added (L.Urban)
93// 17-10-05 protection above has been removed (L.Urban)
94// 06-01-06 reset currentCouple when StepFunction is changed (V.Ivanchenko)
95// 10-01-06 PreciseRange -> CSDARange (V.Ivantchenko)
96// 18-01-06 Clean up subcutoff including recalculation of presafety (VI)
97// 20-01-06 Introduce G4EmTableType and reducing number of methods (VI)
98// 22-03-06 Add control on warning printout AlongStep (VI)
99// 23-03-06 Use isIonisation flag (V.Ivanchenko)
100// 07-06-06 Do not reflect AlongStep in subcutoff regime (V.Ivanchenko)
101// 14-01-07 add SetEmModel(index) and SetFluctModel() (mma)
102// 16-01-07 add IonisationTable and IonisationSubTable (V.Ivanchenko)
103// 16-02-07 set linLossLimit=1.e-6 (V.Ivanchenko)
104// 13-03-07 use SafetyHelper instead of navigator (V.Ivanchenko)
105// 10-04-07 use unique SafetyHelper (V.Ivanchenko)
106// 12-04-07 Add verbosity at destruction (V.Ivanchenko)
107// 25-04-07 move initialisation of safety helper to BuildPhysicsTable (VI)
108// 27-10-07 Virtual functions moved to source (V.Ivanchenko)
[1196]109// 24-06-09 Removed hidden bin in G4PhysicsVector (V.Ivanchenko)
[819]110//
111// Class Description:
112//
113// It is the unified energy loss process it calculates the continuous
114// energy loss for charged particles using a set of Energy Loss
115// models valid for different energy regions. There are a possibility
116// to create and access to dE/dx and range tables, or to calculate
117// that information on fly.
118// -------------------------------------------------------------------
119//
120//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
121//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
122
123#include "G4VEnergyLossProcess.hh"
124#include "G4LossTableManager.hh"
125#include "G4Step.hh"
126#include "G4ParticleDefinition.hh"
127#include "G4VEmModel.hh"
128#include "G4VEmFluctuationModel.hh"
129#include "G4DataVector.hh"
130#include "G4PhysicsLogVector.hh"
131#include "G4VParticleChange.hh"
132#include "G4Gamma.hh"
133#include "G4Electron.hh"
134#include "G4Positron.hh"
135#include "G4Proton.hh"
136#include "G4ProcessManager.hh"
137#include "G4UnitsTable.hh"
138#include "G4GenericIon.hh"
139#include "G4ProductionCutsTable.hh"
140#include "G4Region.hh"
141#include "G4RegionStore.hh"
142#include "G4PhysicsTableHelper.hh"
143#include "G4SafetyHelper.hh"
144#include "G4TransportationManager.hh"
[1055]145#include "G4EmConfigurator.hh"
[819]146
147//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
148
149G4VEnergyLossProcess::G4VEnergyLossProcess(const G4String& name,
[961]150 G4ProcessType type):
151 G4VContinuousDiscreteProcess(name, type),
152 secondaryParticle(0),
[819]153 nSCoffRegions(0),
[1055]154 nDERegions(0),
[819]155 idxSCoffRegions(0),
[1055]156 idxDERegions(0),
[819]157 nProcesses(0),
158 theDEDXTable(0),
159 theDEDXSubTable(0),
160 theDEDXunRestrictedTable(0),
161 theIonisationTable(0),
162 theIonisationSubTable(0),
163 theRangeTableForLoss(0),
164 theCSDARangeTable(0),
165 theSecondaryRangeTable(0),
166 theInverseRangeTable(0),
167 theLambdaTable(0),
168 theSubLambdaTable(0),
169 theDEDXAtMaxEnergy(0),
170 theRangeAtMaxEnergy(0),
171 theEnergyOfCrossSectionMax(0),
172 theCrossSectionMax(0),
173 baseParticle(0),
174 minSubRange(0.1),
175 lossFluctuationFlag(true),
176 rndmStepFlag(false),
177 tablesAreBuilt(false),
178 integral(true),
[961]179 isIon(false),
[819]180 isIonisation(true),
[961]181 useSubCutoff(false),
[1055]182 useDeexcitation(false),
[961]183 particle(0),
184 currentCouple(0),
185 nWarnings(0),
186 mfpKinEnergy(0.0)
[819]187{
188 SetVerboseLevel(1);
189
[961]190 // low energy limit
[819]191 lowestKinEnergy = 1.*eV;
[961]192
193 // Size of tables assuming spline
[819]194 minKinEnergy = 0.1*keV;
[1055]195 maxKinEnergy = 10.0*TeV;
196 nBins = 77;
[819]197 maxKinEnergyCSDA = 1.0*GeV;
[961]198 nBinsCSDA = 35;
[819]199
[961]200 // default linear loss limit for spline
201 linLossLimit = 0.01;
202
[819]203 // default dRoverRange and finalRange
204 SetStepFunction(0.2, 1.0*mm);
205
[961]206 // default lambda factor
207 lambdaFactor = 0.8;
[819]208
[961]209 // particle types
210 theElectron = G4Electron::Electron();
211 thePositron = G4Positron::Positron();
212 theGenericIon = 0;
213
[819]214 // run time objects
215 pParticleChange = &fParticleChange;
216 modelManager = new G4EmModelManager();
217 safetyHelper = G4TransportationManager::GetTransportationManager()
218 ->GetSafetyHelper();
219 aGPILSelection = CandidateForSelection;
220
221 // initialise model
222 (G4LossTableManager::Instance())->Register(this);
223 fluctModel = 0;
224
225 scTracks.reserve(5);
226 secParticles.reserve(5);
227
228 // Data for stragling of ranges from ICRU'37 report
229 const G4int nrbins = 7;
[961]230 vstrag = new G4PhysicsLogVector(keV, GeV, nrbins-1);
231 vstrag->SetSpline(true);
[819]232 G4double s[nrbins] = {-0.2, -0.85, -1.3, -1.578, -1.76, -1.85, -1.9};
[1196]233 for(G4int i=0; i<nrbins; ++i) {vstrag->PutValue(i, s[i]);}
[819]234}
235
236//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
237
238G4VEnergyLossProcess::~G4VEnergyLossProcess()
239{
240 if(1 < verboseLevel)
241 G4cout << "G4VEnergyLossProcess destruct " << GetProcessName()
242 << G4endl;
243 delete vstrag;
[1055]244 Clean();
[819]245
246 if ( !baseParticle ) {
247 if(theDEDXTable && theRangeTableForLoss) {
248 if(theIonisationTable == theDEDXTable) theIonisationTable = 0;
249 theDEDXTable->clearAndDestroy();
250 delete theDEDXTable;
251 if(theDEDXSubTable) {
252 if(theIonisationSubTable == theDEDXSubTable)
253 theIonisationSubTable = 0;
254 theDEDXSubTable->clearAndDestroy();
255 delete theDEDXSubTable;
256 }
257 }
258 if(theIonisationTable) {
259 theIonisationTable->clearAndDestroy();
260 delete theIonisationTable;
261 }
262 if(theIonisationSubTable) {
263 theIonisationSubTable->clearAndDestroy();
264 delete theIonisationSubTable;
265 }
266 if(theDEDXunRestrictedTable && theCSDARangeTable) {
267 theDEDXunRestrictedTable->clearAndDestroy();
268 delete theDEDXunRestrictedTable;
269 }
270 if(theCSDARangeTable) {
271 theCSDARangeTable->clearAndDestroy();
272 delete theCSDARangeTable;
273 }
274 if(theRangeTableForLoss) {
275 theRangeTableForLoss->clearAndDestroy();
276 delete theRangeTableForLoss;
277 }
278 if(theInverseRangeTable) {
279 theInverseRangeTable->clearAndDestroy();
280 delete theInverseRangeTable;
281 }
282 if(theLambdaTable) {
283 theLambdaTable->clearAndDestroy();
284 delete theLambdaTable;
285 }
286 if(theSubLambdaTable) {
287 theSubLambdaTable->clearAndDestroy();
288 delete theSubLambdaTable;
289 }
290 }
291
292 delete modelManager;
293 (G4LossTableManager::Instance())->DeRegister(this);
294}
295
296//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
297
[1055]298void G4VEnergyLossProcess::Clean()
[819]299{
[961]300 if(1 < verboseLevel) {
[819]301 G4cout << "G4VEnergyLossProcess::Clear() for " << GetProcessName()
[961]302 << G4endl;
303 }
[819]304 delete [] theDEDXAtMaxEnergy;
305 delete [] theRangeAtMaxEnergy;
306 delete [] theEnergyOfCrossSectionMax;
307 delete [] theCrossSectionMax;
308 delete [] idxSCoffRegions;
[1055]309 delete [] idxDERegions;
[819]310
311 theDEDXAtMaxEnergy = 0;
312 theRangeAtMaxEnergy = 0;
313 theEnergyOfCrossSectionMax = 0;
314 theCrossSectionMax = 0;
315 tablesAreBuilt = false;
316
[961]317 //scTracks.clear();
[819]318 scProcesses.clear();
[961]319 nProcesses = 0;
[819]320}
321
322//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
323
[1055]324G4double G4VEnergyLossProcess::MinPrimaryEnergy(const G4ParticleDefinition*,
325 const G4Material*,
326 G4double cut)
327{
328 return cut;
329}
330
331//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
332
333void G4VEnergyLossProcess::AddEmModel(G4int order, G4VEmModel* p,
334 G4VEmFluctuationModel* fluc,
335 const G4Region* region)
336{
337 modelManager->AddEmModel(order, p, fluc, region);
[1315]338 if(p) { p->SetParticleChange(pParticleChange, fluc); }
[1055]339}
340
341//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
342
343void G4VEnergyLossProcess::UpdateEmModel(const G4String& nam,
344 G4double emin, G4double emax)
345{
346 modelManager->UpdateEmModel(nam, emin, emax);
347}
348
349//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
350
351void G4VEnergyLossProcess::SetEmModel(G4VEmModel* p, G4int index)
352{
353 G4int n = emModels.size();
[1196]354 if(index >= n) { for(G4int i=n; i<=index; ++i) {emModels.push_back(0);} }
[1055]355 emModels[index] = p;
356}
357
358//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
359
360G4VEmModel* G4VEnergyLossProcess::EmModel(G4int index)
361{
362 G4VEmModel* p = 0;
[1196]363 if(index >= 0 && index < G4int(emModels.size())) { p = emModels[index]; }
[1055]364 return p;
365}
366
367//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
368
369G4VEmModel* G4VEnergyLossProcess::GetModelByIndex(G4int idx, G4bool ver)
370{
371 return modelManager->GetModel(idx, ver);
372}
373
374//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
375
376G4int G4VEnergyLossProcess::NumberOfModels()
377{
378 return modelManager->NumberOfModels();
379}
380
381//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
382
[961]383void
384G4VEnergyLossProcess::PreparePhysicsTable(const G4ParticleDefinition& part)
385{
[819]386 if(1 < verboseLevel) {
387 G4cout << "G4VEnergyLossProcess::PreparePhysicsTable for "
388 << GetProcessName()
389 << " for " << part.GetParticleName()
390 << G4endl;
391 }
392
[961]393 currentCouple = 0;
394 preStepLambda = 0.0;
395 mfpKinEnergy = DBL_MAX;
396 fRange = DBL_MAX;
397 preStepKinEnergy = 0.0;
398 chargeSqRatio = 1.0;
399 massRatio = 1.0;
400 reduceFactor = 1.0;
401
[819]402 G4LossTableManager* lManager = G4LossTableManager::Instance();
403
[961]404 // Are particle defined?
405 if( !particle ) {
406 particle = &part;
407 if(part.GetParticleType() == "nucleus") {
[1315]408 if(!theGenericIon) { theGenericIon = G4GenericIon::GenericIon(); }
[961]409 if(particle == theGenericIon) { isIon = true; }
410 else if(part.GetPDGCharge() > eplus) {
411 isIon = true;
412
413 // generic ions created on-fly
414 if(part.GetPDGCharge() > 2.5*eplus) {
415 particle = theGenericIon;
416 }
417 }
418 }
419 }
420
421 if( particle != &part) {
422 if(part.GetParticleType() == "nucleus") {
423 isIon = true;
424 lManager->RegisterIon(&part, this);
425 } else {
426 lManager->RegisterExtraParticle(&part, this);
427 }
[1315]428 if(1 < verboseLevel) {
429 G4cout << "### G4VEnergyLossProcess::PreparePhysicsTable() end for "
430 << part.GetParticleName() << G4endl;
431 }
[819]432 return;
433 }
434
[1055]435 Clean();
[1315]436 lManager->PreparePhysicsTable(&part, this);
[819]437
438 // Base particle and set of models can be defined here
439 InitialiseEnergyLossProcess(particle, baseParticle);
440
441 // Tables preparation
442 if (!baseParticle) {
443
444 theDEDXTable = G4PhysicsTableHelper::PreparePhysicsTable(theDEDXTable);
445 if (lManager->BuildCSDARange()) {
446 theDEDXunRestrictedTable =
447 G4PhysicsTableHelper::PreparePhysicsTable(theDEDXunRestrictedTable);
448 theCSDARangeTable =
449 G4PhysicsTableHelper::PreparePhysicsTable(theCSDARangeTable);
450 }
451
452 theRangeTableForLoss =
453 G4PhysicsTableHelper::PreparePhysicsTable(theRangeTableForLoss);
454 theInverseRangeTable =
455 G4PhysicsTableHelper::PreparePhysicsTable(theInverseRangeTable);
456
457 theLambdaTable = G4PhysicsTableHelper::PreparePhysicsTable(theLambdaTable);
458 if (nSCoffRegions) {
459 theDEDXSubTable =
460 G4PhysicsTableHelper::PreparePhysicsTable(theDEDXSubTable);
461 theSubLambdaTable =
462 G4PhysicsTableHelper::PreparePhysicsTable(theSubLambdaTable);
463 }
464 }
465
466 G4double initialCharge = particle->GetPDGCharge();
467 G4double initialMass = particle->GetPDGMass();
468
469 if (baseParticle) {
470 massRatio = (baseParticle->GetPDGMass())/initialMass;
471 G4double q = initialCharge/baseParticle->GetPDGCharge();
472 chargeSqRatio = q*q;
[1196]473 if(chargeSqRatio > 0.0) { reduceFactor = 1.0/(chargeSqRatio*massRatio); }
[819]474 }
475
[1196]476 // initialisation of models
477 G4int nmod = modelManager->NumberOfModels();
478 for(G4int i=0; i<nmod; ++i) {
479 G4VEmModel* mod = modelManager->GetModel(i);
480 if(mod->HighEnergyLimit() > maxKinEnergy) {
481 mod->SetHighEnergyLimit(maxKinEnergy);
482 }
483 }
484
[819]485 theCuts = modelManager->Initialise(particle, secondaryParticle,
486 minSubRange, verboseLevel);
487
[1055]488 // Sub Cutoff and Deexcitation
489 if (nSCoffRegions>0 || nDERegions>0) {
[819]490 theSubCuts = modelManager->SubCutoff();
491
492 const G4ProductionCutsTable* theCoupleTable=
493 G4ProductionCutsTable::GetProductionCutsTable();
494 size_t numOfCouples = theCoupleTable->GetTableSize();
[1055]495
496 if(nSCoffRegions>0) idxSCoffRegions = new G4bool[numOfCouples];
497 if(nDERegions>0) idxDERegions = new G4bool[numOfCouples];
[819]498
[1196]499 for (size_t j=0; j<numOfCouples; ++j) {
[819]500
501 const G4MaterialCutsCouple* couple =
502 theCoupleTable->GetMaterialCutsCouple(j);
503 const G4ProductionCuts* pcuts = couple->GetProductionCuts();
[1055]504
505 if(nSCoffRegions>0) {
506 G4bool reg = false;
[1196]507 for(G4int i=0; i<nSCoffRegions; ++i) {
[1315]508 if( pcuts == scoffRegions[i]->GetProductionCuts()) { reg = true; }
[1055]509 }
510 idxSCoffRegions[j] = reg;
[819]511 }
[1055]512 if(nDERegions>0) {
513 G4bool reg = false;
[1196]514 for(G4int i=0; i<nDERegions; ++i) {
[1315]515 if( pcuts == deRegions[i]->GetProductionCuts()) { reg = true; }
[1055]516 }
517 idxDERegions[j] = reg;
518 }
[819]519 }
520 }
521
522 if (1 < verboseLevel) {
523 G4cout << "G4VEnergyLossProcess::Initialise() is done "
[961]524 << " for local " << particle->GetParticleName()
525 << " isIon= " << isIon
[819]526 << " chargeSqRatio= " << chargeSqRatio
527 << " massRatio= " << massRatio
528 << " reduceFactor= " << reduceFactor << G4endl;
529 if (nSCoffRegions) {
530 G4cout << " SubCutoff Regime is ON for regions: " << G4endl;
[1196]531 for (G4int i=0; i<nSCoffRegions; ++i) {
[819]532 const G4Region* r = scoffRegions[i];
533 G4cout << " " << r->GetName() << G4endl;
534 }
535 }
[1055]536 if (nDERegions) {
537 G4cout << " Deexcitation is ON for regions: " << G4endl;
[1196]538 for (G4int i=0; i<nDERegions; ++i) {
[1055]539 const G4Region* r = deRegions[i];
540 G4cout << " " << r->GetName() << G4endl;
541 }
542 }
[819]543 }
544}
545
546//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
547
548void G4VEnergyLossProcess::BuildPhysicsTable(const G4ParticleDefinition& part)
549{
550 if(1 < verboseLevel) {
551 G4cout << "### G4VEnergyLossProcess::BuildPhysicsTable() for "
552 << GetProcessName()
553 << " and particle " << part.GetParticleName()
554 << "; local: " << particle->GetParticleName();
555 if(baseParticle) G4cout << "; base: " << baseParticle->GetParticleName();
556 G4cout << G4endl;
557 }
558
[961]559 if(&part == particle) {
560 if(!tablesAreBuilt) {
561 G4LossTableManager::Instance()->BuildPhysicsTable(particle, this);
562 }
563 if(!baseParticle) {
564 if(0 < verboseLevel) PrintInfoDefinition();
565
566 // needs to be done only once
567 safetyHelper->InitialiseHelper();
568 }
[819]569 }
570
[1196]571 // Added tracking cut to avoid tracking artifacts
[1315]572 if(isIonisation) { fParticleChange.SetLowEnergyLimit(lowestKinEnergy); }
[1196]573
[819]574 if(1 < verboseLevel) {
575 G4cout << "### G4VEnergyLossProcess::BuildPhysicsTable() done for "
576 << GetProcessName()
577 << " and particle " << part.GetParticleName();
[1315]578 if(isIonisation) { G4cout << " isIonisation flag = 1"; }
[819]579 G4cout << G4endl;
580 }
581}
582
583//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
584
585G4PhysicsTable* G4VEnergyLossProcess::BuildDEDXTable(G4EmTableType tType)
586{
587 if(1 < verboseLevel) {
588 G4cout << "G4VEnergyLossProcess::BuildDEDXTable() of type " << tType
589 << " for " << GetProcessName()
590 << " and particle " << particle->GetParticleName()
591 << G4endl;
592 }
593 G4PhysicsTable* table = 0;
594 G4double emax = maxKinEnergy;
595 G4int bin = nBins;
596
597 if(fTotal == tType) {
598 emax = maxKinEnergyCSDA;
599 bin = nBinsCSDA;
600 table = theDEDXunRestrictedTable;
601 } else if(fRestricted == tType) {
602 table = theDEDXTable;
603 if(theIonisationTable)
604 table = G4PhysicsTableHelper::PreparePhysicsTable(theIonisationTable);
605 } else if(fSubRestricted == tType) {
606 table = theDEDXSubTable;
607 if(theIonisationSubTable)
608 table = G4PhysicsTableHelper::PreparePhysicsTable(theIonisationSubTable);
609 } else {
610 G4cout << "G4VEnergyLossProcess::BuildDEDXTable WARNING: wrong type "
611 << tType << G4endl;
612 }
613
614 // Access to materials
615 const G4ProductionCutsTable* theCoupleTable=
616 G4ProductionCutsTable::GetProductionCutsTable();
617 size_t numOfCouples = theCoupleTable->GetTableSize();
618
619 if(1 < verboseLevel) {
620 G4cout << numOfCouples << " materials"
621 << " minKinEnergy= " << minKinEnergy
[1315]622 << " maxKinEnergy= " << emax
623 << " nbin= " << bin
[819]624 << " EmTableType= " << tType
625 << " table= " << table
626 << G4endl;
627 }
628 if(!table) return table;
629
[1196]630 G4bool splineFlag = (G4LossTableManager::Instance())->SplineFlag();
631 G4PhysicsLogVector* aVector = 0;
632 G4PhysicsLogVector* bVector = 0;
[819]633
[1196]634 for(size_t i=0; i<numOfCouples; ++i) {
635
[961]636 if(1 < verboseLevel) {
[819]637 G4cout << "G4VEnergyLossProcess::BuildDEDXVector flag= "
638 << table->GetFlag(i) << G4endl;
[961]639 }
[819]640 if (table->GetFlag(i)) {
641
642 // create physics vector and fill it
643 const G4MaterialCutsCouple* couple =
644 theCoupleTable->GetMaterialCutsCouple(i);
[1196]645 if(!bVector) {
[1315]646 aVector = new G4PhysicsLogVector(minKinEnergy, emax, bin);
[1196]647 bVector = aVector;
648 } else {
649 aVector = new G4PhysicsLogVector(*bVector);
650 }
651 aVector->SetSpline(splineFlag);
[961]652
[819]653 modelManager->FillDEDXVector(aVector, couple, tType);
[1315]654 if(splineFlag) { aVector->FillSecondDerivatives(); }
[819]655
656 // Insert vector for this material into the table
657 G4PhysicsTableHelper::SetPhysicsVector(table, i, aVector);
658 }
659 }
660
661 if(1 < verboseLevel) {
662 G4cout << "G4VEnergyLossProcess::BuildDEDXTable(): table is built for "
663 << particle->GetParticleName()
664 << " and process " << GetProcessName()
665 << G4endl;
666 // if(2 < verboseLevel) G4cout << (*table) << G4endl;
667 }
668
669 return table;
670}
671
672//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
673
674G4PhysicsTable* G4VEnergyLossProcess::BuildLambdaTable(G4EmTableType tType)
675{
676 G4PhysicsTable* table = 0;
677
678 if(fRestricted == tType) {
679 table = theLambdaTable;
680 } else if(fSubRestricted == tType) {
681 table = theSubLambdaTable;
682 } else {
683 G4cout << "G4VEnergyLossProcess::BuildLambdaTable WARNING: wrong type "
684 << tType << G4endl;
685 }
686
687 if(1 < verboseLevel) {
688 G4cout << "G4VEnergyLossProcess::BuildLambdaTable() of type "
689 << tType << " for process "
690 << GetProcessName() << " and particle "
691 << particle->GetParticleName()
692 << " EmTableType= " << tType
693 << " table= " << table
694 << G4endl;
695 }
[961]696 if(!table) {return table;}
[819]697
698 // Access to materials
699 const G4ProductionCutsTable* theCoupleTable=
700 G4ProductionCutsTable::GetProductionCutsTable();
701 size_t numOfCouples = theCoupleTable->GetTableSize();
702
[1196]703 G4bool splineFlag = (G4LossTableManager::Instance())->SplineFlag();
[1315]704 G4PhysicsLogVector* aVector = 0;
705 G4PhysicsLogVector* bVector = 0;
[819]706
[1196]707 for(size_t i=0; i<numOfCouples; ++i) {
708
[819]709 if (table->GetFlag(i)) {
710
711 // create physics vector and fill it
712 const G4MaterialCutsCouple* couple =
713 theCoupleTable->GetMaterialCutsCouple(i);
[1315]714 if(!bVector) {
715 aVector = new G4PhysicsLogVector(minKinEnergy, maxKinEnergy, nBins);
716 bVector = aVector;
717 } else {
718 aVector = new G4PhysicsLogVector(*bVector);
719 }
[1196]720 aVector->SetSpline(splineFlag);
721
[819]722 modelManager->FillLambdaVector(aVector, couple, true, tType);
[1315]723 if(splineFlag) { aVector->FillSecondDerivatives(); }
[819]724
725 // Insert vector for this material into the table
726 G4PhysicsTableHelper::SetPhysicsVector(table, i, aVector);
727 }
728 }
729
730 if(1 < verboseLevel) {
731 G4cout << "Lambda table is built for "
732 << particle->GetParticleName()
733 << G4endl;
734 }
735
736 return table;
737}
738
739//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
740
[1055]741void G4VEnergyLossProcess::PrintInfoDefinition()
[819]742{
[1055]743 if(0 < verboseLevel) {
744 G4cout << G4endl << GetProcessName() << ": for "
745 << particle->GetParticleName()
746 << " SubType= " << GetProcessSubType()
747 << G4endl
748 << " dE/dx and range tables from "
749 << G4BestUnit(minKinEnergy,"Energy")
750 << " to " << G4BestUnit(maxKinEnergy,"Energy")
751 << " in " << nBins << " bins" << G4endl
752 << " Lambda tables from threshold to "
753 << G4BestUnit(maxKinEnergy,"Energy")
754 << " in " << nBins << " bins, spline: "
755 << (G4LossTableManager::Instance())->SplineFlag()
756 << G4endl;
757 if(theRangeTableForLoss && isIonisation) {
758 G4cout << " finalRange(mm)= " << finalRange/mm
759 << ", dRoverRange= " << dRoverRange
760 << ", integral: " << integral
761 << ", fluct: " << lossFluctuationFlag
762 << ", linLossLimit= " << linLossLimit
763 << G4endl;
764 }
765 PrintInfo();
766 modelManager->DumpModelList(verboseLevel);
767 if(theCSDARangeTable && isIonisation) {
768 G4cout << " CSDA range table up"
769 << " to " << G4BestUnit(maxKinEnergyCSDA,"Energy")
770 << " in " << nBinsCSDA << " bins" << G4endl;
771 }
772 if(nSCoffRegions>0 && isIonisation) {
773 G4cout << " Subcutoff sampling in " << nSCoffRegions
774 << " regions" << G4endl;
775 }
776 if(2 < verboseLevel) {
777 G4cout << " DEDXTable address= " << theDEDXTable << G4endl;
778 if(theDEDXTable && isIonisation) G4cout << (*theDEDXTable) << G4endl;
779 G4cout << "non restricted DEDXTable address= "
780 << theDEDXunRestrictedTable << G4endl;
781 if(theDEDXunRestrictedTable && isIonisation) {
782 G4cout << (*theDEDXunRestrictedTable) << G4endl;
783 }
784 if(theDEDXSubTable && isIonisation) {
785 G4cout << (*theDEDXSubTable) << G4endl;
786 }
787 G4cout << " CSDARangeTable address= " << theCSDARangeTable
788 << G4endl;
789 if(theCSDARangeTable && isIonisation) {
790 G4cout << (*theCSDARangeTable) << G4endl;
791 }
792 G4cout << " RangeTableForLoss address= " << theRangeTableForLoss
793 << G4endl;
794 if(theRangeTableForLoss && isIonisation) {
795 G4cout << (*theRangeTableForLoss) << G4endl;
796 }
797 G4cout << " InverseRangeTable address= " << theInverseRangeTable
798 << G4endl;
799 if(theInverseRangeTable && isIonisation) {
800 G4cout << (*theInverseRangeTable) << G4endl;
801 }
802 G4cout << " LambdaTable address= " << theLambdaTable << G4endl;
803 if(theLambdaTable && isIonisation) {
804 G4cout << (*theLambdaTable) << G4endl;
805 }
806 G4cout << " SubLambdaTable address= " << theSubLambdaTable << G4endl;
807 if(theSubLambdaTable && isIonisation) {
808 G4cout << (*theSubLambdaTable) << G4endl;
809 }
810 }
811 }
[819]812}
813
814//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
815
[1055]816void G4VEnergyLossProcess::ActivateSubCutoff(G4bool val, const G4Region* r)
817{
818 G4RegionStore* regionStore = G4RegionStore::GetInstance();
819 const G4Region* reg = r;
820 if (!reg) {reg = regionStore->GetRegion("DefaultRegionForTheWorld", false);}
821
822 // the region is in the list
823 if (nSCoffRegions) {
[1196]824 for (G4int i=0; i<nSCoffRegions; ++i) {
[1055]825 if (reg == scoffRegions[i]) {
826 if(!val) deRegions[i] = 0;
827 return;
828 }
829 }
830 }
831
832 // new region
833 if(val) {
834 useSubCutoff = true;
835 scoffRegions.push_back(reg);
[1196]836 ++nSCoffRegions;
[1055]837 } else {
838 useSubCutoff = false;
839 }
840}
841
842//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
843
844void G4VEnergyLossProcess::ActivateDeexcitation(G4bool val, const G4Region* r)
845{
846 G4RegionStore* regionStore = G4RegionStore::GetInstance();
847 const G4Region* reg = r;
848 if (!reg) {reg = regionStore->GetRegion("DefaultRegionForTheWorld", false);}
849
850 // the region is in the list
851 if (nDERegions) {
[1196]852 for (G4int i=0; i<nDERegions; ++i) {
[1055]853 if (reg == deRegions[i]) {
854 if(!val) deRegions[i] = 0;
855 return;
856 }
857 }
858 }
859
860 // new region
861 if(val) {
862 useDeexcitation = true;
863 deRegions.push_back(reg);
[1196]864 ++nDERegions;
[1055]865 } else {
866 useDeexcitation = false;
867 }
868}
869
870//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
871
[819]872G4double G4VEnergyLossProcess::AlongStepGetPhysicalInteractionLength(
873 const G4Track&,
874 G4double,
875 G4double currentMinStep,
876 G4double&,
877 G4GPILSelection* selection)
878{
879 G4double x = DBL_MAX;
880 *selection = aGPILSelection;
881 if(isIonisation) {
882 fRange = GetScaledRangeForScaledEnergy(preStepScaledEnergy)*reduceFactor;
883
884 x = fRange;
885 G4double y = x*dRoverRange;
886
887 if(x > finalRange && y < currentMinStep) {
888 x = y + finalRange*(1.0 - dRoverRange)*(2.0 - finalRange/fRange);
[1315]889 } else if (rndmStepFlag) { x = SampleRange(); }
[961]890 //G4cout<<GetProcessName()<<": e= "<<preStepKinEnergy
891 // <<" range= "<<fRange <<" cMinSt="<<currentMinStep
892 // << " limit= " << x <<G4endl;
[819]893 }
[961]894 //G4cout<<GetProcessName()<<": e= "<<preStepKinEnergy
[819]895 // <<" stepLimit= "<<x<<G4endl;
896 return x;
897}
898
899//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
900
901G4double G4VEnergyLossProcess::PostStepGetPhysicalInteractionLength(
902 const G4Track& track,
903 G4double previousStepSize,
904 G4ForceCondition* condition)
905{
906 // condition is set to "Not Forced"
907 *condition = NotForced;
908 G4double x = DBL_MAX;
[961]909
910 // initialisation of material, mass, charge, model at the beginning of the step
911 DefineMaterial(track.GetMaterialCutsCouple());
912
913 const G4ParticleDefinition* currPart = track.GetDefinition();
914 if(theGenericIon == particle) {
915 massRatio = proton_mass_c2/currPart->GetPDGMass();
916 }
917 preStepKinEnergy = track.GetKineticEnergy();
918 preStepScaledEnergy = preStepKinEnergy*massRatio;
919 SelectModel(preStepScaledEnergy);
[1315]920 if(!currentModel->IsActive(preStepScaledEnergy)) { return x; }
[961]921
[1315]922 if(isIon) {
923 chargeSqRatio = currentModel->ChargeSquareRatio(track);
[961]924 reduceFactor = 1.0/(chargeSqRatio*massRatio);
925 }
926 //G4cout << "q2= " << chargeSqRatio << " massRatio= " << massRatio << G4endl;
927 // initialisation for sampling of the interaction length
[1315]928 if(previousStepSize <= DBL_MIN) { theNumberOfInteractionLengthLeft = -1.0; }
929 if(theNumberOfInteractionLengthLeft < 0.0) { mfpKinEnergy = DBL_MAX; }
[819]930
[961]931 // compute mean free path
[819]932 if(preStepScaledEnergy < mfpKinEnergy) {
[1315]933 if (integral) { ComputeLambdaForScaledEnergy(preStepScaledEnergy); }
934 else { preStepLambda = GetLambdaForScaledEnergy(preStepScaledEnergy); }
935 if(preStepLambda <= DBL_MIN) { mfpKinEnergy = 0.0; }
[819]936 }
937
938 // non-zero cross section
939 if(preStepLambda > DBL_MIN) {
940 if (theNumberOfInteractionLengthLeft < 0.0) {
941 // beggining of tracking (or just after DoIt of this process)
[961]942 //G4cout<<"G4VEnergyLossProcess::PostStepGetPhysicalInteractionLength Reset"<<G4endl;
[819]943 ResetNumberOfInteractionLengthLeft();
944 } else if(currentInteractionLength < DBL_MAX) {
945 // subtract NumberOfInteractionLengthLeft
946 SubtractNumberOfInteractionLengthLeft(previousStepSize);
[1315]947 if(theNumberOfInteractionLengthLeft < 0.) {
[819]948 theNumberOfInteractionLengthLeft = perMillion;
[1315]949 }
[819]950 }
951
952 // get mean free path and step limit
953 currentInteractionLength = 1.0/preStepLambda;
954 x = theNumberOfInteractionLengthLeft * currentInteractionLength;
955
956#ifdef G4VERBOSE
957 if (verboseLevel>2){
958 G4cout << "G4VEnergyLossProcess::PostStepGetPhysicalInteractionLength ";
959 G4cout << "[ " << GetProcessName() << "]" << G4endl;
[961]960 G4cout << " for " << currPart->GetParticleName()
[819]961 << " in Material " << currentMaterial->GetName()
962 << " Ekin(MeV)= " << preStepKinEnergy/MeV
963 <<G4endl;
964 G4cout << "MeanFreePath = " << currentInteractionLength/cm << "[cm]"
965 << "InteractionLength= " << x/cm <<"[cm] " <<G4endl;
966 }
967#endif
968 // zero cross section case
969 } else {
970 if(theNumberOfInteractionLengthLeft > DBL_MIN &&
971 currentInteractionLength < DBL_MAX) {
972 // subtract NumberOfInteractionLengthLeft
973 SubtractNumberOfInteractionLengthLeft(previousStepSize);
[1315]974 if(theNumberOfInteractionLengthLeft < 0.) {
[819]975 theNumberOfInteractionLengthLeft = perMillion;
[1315]976 }
[819]977 }
978 currentInteractionLength = DBL_MAX;
979 }
980 return x;
981}
982
983//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
984
985G4VParticleChange* G4VEnergyLossProcess::AlongStepDoIt(const G4Track& track,
986 const G4Step& step)
987{
988 fParticleChange.InitializeForAlongStep(track);
989 // The process has range table - calculate energy loss
[1196]990 if(!isIonisation || !currentModel->IsActive(preStepScaledEnergy)) {
991 return &fParticleChange;
992 }
[819]993
994 // Get the actual (true) Step length
995 G4double length = step.GetStepLength();
[1315]996 if(length <= DBL_MIN) { return &fParticleChange; }
[819]997 G4double eloss = 0.0;
[961]998
999 /*
[819]1000 if(-1 < verboseLevel) {
1001 const G4ParticleDefinition* d = track.GetDefinition();
1002 G4cout << "AlongStepDoIt for "
1003 << GetProcessName() << " and particle "
1004 << d->GetParticleName()
1005 << " eScaled(MeV)= " << preStepScaledEnergy/MeV
1006 << " range(mm)= " << fRange/mm
1007 << " s(mm)= " << length/mm
1008 << " q^2= " << chargeSqRatio
1009 << " md= " << d->GetPDGMass()
1010 << " status= " << track.GetTrackStatus()
1011 << G4endl;
1012 }
1013 */
1014
[961]1015 const G4DynamicParticle* dynParticle = track.GetDynamicParticle();
1016
[819]1017 // stopping
1018 if (length >= fRange) {
[961]1019 eloss = preStepKinEnergy;
[1055]1020 if (useDeexcitation) {
1021 if(idxDERegions[currentMaterialIndex]) {
1022 currentModel->SampleDeexcitationAlongStep(currentMaterial, track, eloss);
1023 if(eloss < 0.0) eloss = 0.0;
1024 }
1025 }
[819]1026 fParticleChange.SetProposedKineticEnergy(0.0);
[1055]1027 fParticleChange.ProposeLocalEnergyDeposit(eloss);
[819]1028 return &fParticleChange;
1029 }
1030
1031 // Short step
1032 eloss = GetDEDXForScaledEnergy(preStepScaledEnergy)*length;
1033
1034 // Long step
1035 //} else {
1036 if(eloss > preStepKinEnergy*linLossLimit) {
1037
1038 G4double x =
1039 GetScaledRangeForScaledEnergy(preStepScaledEnergy) - length/reduceFactor;
1040 eloss = preStepKinEnergy - ScaledKinEnergyForLoss(x)/massRatio;
[961]1041
[819]1042 /*
1043 if(-1 < verboseLevel)
1044 G4cout << "Long STEP: rPre(mm)= "
1045 << GetScaledRangeForScaledEnergy(preStepScaledEnergy)/mm
1046 << " rPost(mm)= " << x/mm
1047 << " ePre(MeV)= " << preStepScaledEnergy/MeV
1048 << " eloss(MeV)= " << eloss/MeV
1049 << " eloss0(MeV)= "
1050 << GetDEDXForScaledEnergy(preStepScaledEnergy)*length/MeV
[961]1051 << " lim(MeV)= " << preStepKinEnergy*linLossLimit/MeV
[819]1052 << G4endl;
1053 */
1054 }
1055
[961]1056 /*
[819]1057 G4double eloss0 = eloss;
1058 if(-1 < verboseLevel ) {
1059 G4cout << "Before fluct: eloss(MeV)= " << eloss/MeV
1060 << " e-eloss= " << preStepKinEnergy-eloss
1061 << " step(mm)= " << length/mm
1062 << " range(mm)= " << fRange/mm
1063 << " fluct= " << lossFluctuationFlag
1064 << G4endl;
1065 }
1066 */
1067
1068 G4double cut = (*theCuts)[currentMaterialIndex];
1069 G4double esec = 0.0;
1070
1071 // SubCutOff
1072 if(useSubCutoff) {
1073 if(idxSCoffRegions[currentMaterialIndex]) {
1074
[961]1075 G4bool yes = false;
[819]1076 G4StepPoint* prePoint = step.GetPreStepPoint();
1077
[961]1078 // Check boundary
[1315]1079 if(prePoint->GetStepStatus() == fGeomBoundary) { yes = true; }
[819]1080
[961]1081 // Check PrePoint
1082 else {
1083 G4double preSafety = prePoint->GetSafety();
1084 G4double rcut = currentCouple->GetProductionCuts()->GetProductionCut(1);
[819]1085
[961]1086 // recompute presafety
1087 if(preSafety < rcut) {
[819]1088 preSafety = safetyHelper->ComputeSafety(prePoint->GetPosition());
[961]1089 }
[819]1090
[1315]1091 if(preSafety < rcut) { yes = true; }
[961]1092
1093 // Check PostPoint
1094 else {
1095 G4double postSafety = preSafety - length;
1096 if(postSafety < rcut) {
1097 postSafety =
1098 safetyHelper->ComputeSafety(step.GetPostStepPoint()->GetPosition());
[1315]1099 if(postSafety < rcut) { yes = true; }
[961]1100 }
1101 }
[819]1102 }
[961]1103
[819]1104 // Decide to start subcut sampling
[961]1105 if(yes) {
[819]1106
1107 cut = (*theSubCuts)[currentMaterialIndex];
1108 eloss -= GetSubDEDXForScaledEnergy(preStepScaledEnergy)*length;
1109 scTracks.clear();
1110 SampleSubCutSecondaries(scTracks, step,
[1315]1111 currentModel,currentMaterialIndex);
[961]1112 // add bremsstrahlung sampling
[819]1113 /*
1114 if(nProcesses > 0) {
[1196]1115 for(G4int i=0; i<nProcesses; ++i) {
[819]1116 (scProcesses[i])->SampleSubCutSecondaries(
1117 scTracks, step, (scProcesses[i])->
1118 SelectModelForMaterial(preStepKinEnergy, currentMaterialIndex),
[1315]1119 currentMaterialIndex);
[819]1120 }
1121 }
1122 */
1123 G4int n = scTracks.size();
1124 if(n>0) {
1125 G4ThreeVector mom = dynParticle->GetMomentum();
1126 fParticleChange.SetNumberOfSecondaries(n);
[1196]1127 for(G4int i=0; i<n; ++i) {
[819]1128 G4Track* t = scTracks[i];
1129 G4double e = t->GetKineticEnergy();
[1315]1130 if (t->GetDefinition() == thePositron) { e += 2.0*electron_mass_c2; }
[819]1131 esec += e;
1132 pParticleChange->AddSecondary(t);
1133 }
1134 }
1135 }
1136 }
1137 }
1138
1139 // Corrections, which cannot be tabulated
[1315]1140 if(isIon) {
1141 G4double eadd = 0.0;
1142 currentModel->CorrectionsAlongStep(currentCouple, dynParticle,
1143 eloss, eadd, length);
1144 }
[819]1145
1146 // Sample fluctuations
1147 if (lossFluctuationFlag) {
1148 G4VEmFluctuationModel* fluc = currentModel->GetModelOfFluctuations();
1149 if(fluc &&
[1315]1150 (eloss + esec + lowestKinEnergy) < preStepKinEnergy) {
[819]1151
1152 G4double tmax =
1153 std::min(currentModel->MaxSecondaryKinEnergy(dynParticle),cut);
[1055]1154 G4double emean = eloss;
[819]1155 eloss = fluc->SampleFluctuations(currentMaterial,dynParticle,
[1055]1156 tmax,length,emean);
[961]1157 /*
[819]1158 if(-1 < verboseLevel)
1159 G4cout << "After fluct: eloss(MeV)= " << eloss/MeV
1160 << " fluc= " << (eloss-eloss0)/MeV
[961]1161 << " ChargeSqRatio= " << chargeSqRatio
[819]1162 << " massRatio= " << massRatio
1163 << " tmax= " << tmax
1164 << G4endl;
1165 */
1166 }
1167 }
1168
[1055]1169 // deexcitation
[1315]1170 if (useDeexcitation) {
1171 if(idxDERegions[currentMaterialIndex] && eloss > 0.0) {
[1055]1172 currentModel->SampleDeexcitationAlongStep(currentMaterial, track, eloss);
[1315]1173 if(eloss < 0.0) { eloss = 0.0; }
[1055]1174 }
1175 }
1176
[819]1177 // Energy balanse
1178 G4double finalT = preStepKinEnergy - eloss - esec;
1179 if (finalT <= lowestKinEnergy) {
1180 eloss = preStepKinEnergy - esec;
1181 finalT = 0.0;
[961]1182 } else if(isIon) {
1183 fParticleChange.SetProposedCharge(
1184 currentModel->GetParticleCharge(track.GetDefinition(),currentMaterial,finalT));
[819]1185 }
1186
1187 fParticleChange.SetProposedKineticEnergy(finalT);
1188 fParticleChange.ProposeLocalEnergyDeposit(eloss);
1189
[961]1190 /*
[819]1191 if(-1 < verboseLevel) {
1192 G4cout << "Final value eloss(MeV)= " << eloss/MeV
1193 << " preStepKinEnergy= " << preStepKinEnergy
1194 << " postStepKinEnergy= " << finalT
1195 << " lossFlag= " << lossFluctuationFlag
1196 << " status= " << track.GetTrackStatus()
1197 << G4endl;
1198 }
[961]1199 */
[819]1200
1201 return &fParticleChange;
1202}
1203
1204//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1205
1206void G4VEnergyLossProcess::SampleSubCutSecondaries(
1207 std::vector<G4Track*>& tracks,
1208 const G4Step& step,
1209 G4VEmModel* model,
[1315]1210 G4int idx)
[819]1211{
1212 // Fast check weather subcutoff can work
1213 G4double subcut = (*theSubCuts)[idx];
1214 G4double cut = (*theCuts)[idx];
[1315]1215 if(cut <= subcut) { return; }
[819]1216
1217 const G4Track* track = step.GetTrack();
1218 const G4DynamicParticle* dp = track->GetDynamicParticle();
[961]1219 G4double e = dp->GetKineticEnergy()*massRatio;
[1196]1220 G4double cross = chargeSqRatio*(((*theSubLambdaTable)[idx])->Value(e));
[819]1221 G4double length = step.GetStepLength();
1222
1223 // negligible probability to get any interaction
[1315]1224 if(length*cross < perMillion) { return; }
[961]1225 /*
[819]1226 if(-1 < verboseLevel)
1227 G4cout << "<<< Subcutoff for " << GetProcessName()
1228 << " cross(1/mm)= " << cross*mm << ">>>"
1229 << " e(MeV)= " << preStepScaledEnergy
1230 << " matIdx= " << currentMaterialIndex
1231 << G4endl;
1232 */
1233
1234 // Sample subcutoff secondaries
1235 G4StepPoint* preStepPoint = step.GetPreStepPoint();
[961]1236 G4StepPoint* postStepPoint = step.GetPostStepPoint();
[819]1237 G4ThreeVector prepoint = preStepPoint->GetPosition();
[961]1238 G4ThreeVector dr = postStepPoint->GetPosition() - prepoint;
[819]1239 G4double pretime = preStepPoint->GetGlobalTime();
[961]1240 G4double dt = postStepPoint->GetGlobalTime() - pretime;
1241 //G4double dt = length/preStepPoint->GetVelocity();
[819]1242 G4double fragment = 0.0;
1243
1244 do {
1245 G4double del = -std::log(G4UniformRand())/cross;
1246 fragment += del/length;
1247 if (fragment > 1.0) break;
1248
1249 // sample secondaries
1250 secParticles.clear();
1251 model->SampleSecondaries(&secParticles,track->GetMaterialCutsCouple(),
1252 dp,subcut,cut);
1253
1254 // position of subcutoff particles
1255 G4ThreeVector r = prepoint + fragment*dr;
1256 std::vector<G4DynamicParticle*>::iterator it;
[1196]1257 for(it=secParticles.begin(); it!=secParticles.end(); ++it) {
[819]1258
1259 G4bool addSec = true;
[961]1260 /*
[819]1261 // do not track very low-energy delta-electrons
1262 if(theSecondaryRangeTable && (*it)->GetDefinition() == theElectron) {
1263 G4double ekin = (*it)->GetKineticEnergy();
[1196]1264 G4double rg = ((*theSecondaryRangeTable)[idx]->Value(ekin));
[819]1265 // if(rg < currentMinSafety) {
1266 if(rg < safetyHelper->ComputeSafety(r)) {
1267 extraEdep += ekin;
1268 delete (*it);
1269 addSec = false;
1270 }
1271 }
[961]1272 */
[819]1273 if(addSec) {
[961]1274 G4Track* t = new G4Track((*it), pretime + fragment*dt, r);
[819]1275 t->SetTouchableHandle(track->GetTouchableHandle());
1276 tracks.push_back(t);
1277
[961]1278 /*
1279 if(-1 < verboseLevel)
1280 G4cout << "New track " << t->GetDefinition()->GetParticleName()
1281 << " e(keV)= " << t->GetKineticEnergy()/keV
1282 << " fragment= " << fragment
1283 << G4endl;
[819]1284 */
1285 }
1286 }
1287 } while (fragment <= 1.0);
1288}
1289
1290//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1291
1292G4VParticleChange* G4VEnergyLossProcess::PostStepDoIt(const G4Track& track,
1293 const G4Step&)
1294{
1295 fParticleChange.InitializeForPostStep(track);
1296 G4double finalT = track.GetKineticEnergy();
1297 if(finalT <= lowestKinEnergy) return &fParticleChange;
1298
1299 G4double postStepScaledEnergy = finalT*massRatio;
[1196]1300
[1315]1301 if(!currentModel->IsActive(postStepScaledEnergy)) { return &fParticleChange; }
[819]1302 /*
1303 if(-1 < verboseLevel) {
1304 G4cout << GetProcessName()
1305 << "::PostStepDoIt: E(MeV)= " << finalT/MeV
1306 << G4endl;
1307 }
1308 */
1309 // Integral approach
1310 if (integral) {
1311 G4double lx = GetLambdaForScaledEnergy(postStepScaledEnergy);
1312 /*
1313 if(preStepLambda<lx && 1 < verboseLevel && nWarnings<200) {
1314 G4cout << "WARNING: for " << particle->GetParticleName()
1315 << " and " << GetProcessName()
1316 << " E(MeV)= " << finalT/MeV
1317 << " preLambda= " << preStepLambda
1318 << " < " << lx << " (postLambda) "
1319 << G4endl;
[1196]1320 ++nWarnings;
[819]1321 }
1322 */
1323 if(preStepLambda*G4UniformRand() > lx) {
1324 ClearNumberOfInteractionLengthLeft();
1325 return &fParticleChange;
1326 }
1327 }
1328
[961]1329 SelectModel(postStepScaledEnergy);
[1055]1330 if(useDeexcitation) {
1331 currentModel->SetDeexcitationFlag(idxDERegions[currentMaterialIndex]);
1332 }
1333
[819]1334 const G4DynamicParticle* dynParticle = track.GetDynamicParticle();
1335 G4double tcut = (*theCuts)[currentMaterialIndex];
1336
1337 // sample secondaries
1338 secParticles.clear();
1339 currentModel->SampleSecondaries(&secParticles, currentCouple, dynParticle, tcut);
1340
1341 // save secondaries
1342 G4int num = secParticles.size();
1343 if(num > 0) {
1344 fParticleChange.SetNumberOfSecondaries(num);
[1196]1345 for (G4int i=0; i<num; ++i) {
[819]1346 fParticleChange.AddSecondary(secParticles[i]);
1347 }
1348 }
1349
1350 /*
1351 if(-1 < verboseLevel) {
1352 G4cout << "::PostStepDoIt: Sample secondary; Efin= "
1353 << fParticleChange.GetProposedKineticEnergy()/MeV
1354 << " MeV; model= (" << currentModel->LowEnergyLimit()
1355 << ", " << currentModel->HighEnergyLimit() << ")"
1356 << " preStepLambda= " << preStepLambda
1357 << " dir= " << track.GetMomentumDirection()
1358 << " status= " << track.GetTrackStatus()
1359 << G4endl;
1360 }
1361 */
1362 ClearNumberOfInteractionLengthLeft();
1363 return &fParticleChange;
1364}
1365
1366//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1367
[961]1368G4bool G4VEnergyLossProcess::StorePhysicsTable(
1369 const G4ParticleDefinition* part, const G4String& directory,
1370 G4bool ascii)
[819]1371{
[961]1372 G4bool res = true;
1373 if ( baseParticle || part != particle ) return res;
1374
1375 if(!StoreTable(part,theDEDXTable,ascii,directory,"DEDX"))
1376 {res = false;}
1377
1378 if(!StoreTable(part,theDEDXunRestrictedTable,ascii,directory,"DEDXnr"))
1379 {res = false;}
1380
1381 if(!StoreTable(part,theDEDXSubTable,ascii,directory,"SubDEDX"))
1382 {res = false;}
1383
1384 if(!StoreTable(part,theIonisationTable,ascii,directory,"Ionisation"))
1385 {res = false;}
1386
1387 if(!StoreTable(part,theIonisationSubTable,ascii,directory,"SubIonisation"))
1388 {res = false;}
1389
1390 if(isIonisation &&
1391 !StoreTable(part,theCSDARangeTable,ascii,directory,"CSDARange"))
1392 {res = false;}
1393
1394 if(isIonisation &&
1395 !StoreTable(part,theRangeTableForLoss,ascii,directory,"Range"))
1396 {res = false;}
1397
1398 if(isIonisation &&
1399 !StoreTable(part,theInverseRangeTable,ascii,directory,"InverseRange"))
1400 {res = false;}
1401
1402 if(!StoreTable(part,theLambdaTable,ascii,directory,"Lambda"))
1403 {res = false;}
1404
1405 if(!StoreTable(part,theSubLambdaTable,ascii,directory,"SubLambda"))
1406 {res = false;}
1407
1408 if ( res ) {
1409 if(0 < verboseLevel) {
1410 G4cout << "Physics tables are stored for " << particle->GetParticleName()
1411 << " and process " << GetProcessName()
1412 << " in the directory <" << directory
1413 << "> " << G4endl;
1414 }
1415 } else {
1416 G4cout << "Fail to store Physics Tables for "
1417 << particle->GetParticleName()
1418 << " and process " << GetProcessName()
1419 << " in the directory <" << directory
1420 << "> " << G4endl;
1421 }
1422 return res;
1423}
1424
1425//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
1426
[1196]1427G4bool
1428G4VEnergyLossProcess::RetrievePhysicsTable(const G4ParticleDefinition* part,
1429 const G4String& directory,
1430 G4bool ascii)
[961]1431{
1432 G4bool res = true;
1433 const G4String particleName = part->GetParticleName();
1434
1435 if(1 < verboseLevel) {
1436 G4cout << "G4VEnergyLossProcess::RetrievePhysicsTable() for "
1437 << particleName << " and process " << GetProcessName()
1438 << "; tables_are_built= " << tablesAreBuilt
[819]1439 << G4endl;
[961]1440 }
1441 if(particle == part) {
[819]1442
[961]1443 if ( !baseParticle ) {
1444
1445 G4bool fpi = true;
1446 if(!RetrieveTable(part,theDEDXTable,ascii,directory,"DEDX",fpi))
1447 {fpi = false;}
1448
[1196]1449 // ionisation table keeps individual dEdx and not sum of sub-processes
1450 if(!RetrieveTable(part,theDEDXTable,ascii,directory,"Ionisation",false))
[961]1451 {fpi = false;}
1452
1453 if(!RetrieveTable(part,theRangeTableForLoss,ascii,directory,"Range",fpi))
1454 {res = false;}
1455
1456 if(!RetrieveTable(part,theDEDXunRestrictedTable,ascii,directory,"DEDXnr",false))
1457 {res = false;}
1458
1459 if(!RetrieveTable(part,theCSDARangeTable,ascii,directory,"CSDARange",false))
1460 {res = false;}
1461
1462 if(!RetrieveTable(part,theInverseRangeTable,ascii,directory,"InverseRange",fpi))
1463 {res = false;}
1464
1465 if(!RetrieveTable(part,theLambdaTable,ascii,directory,"Lambda",true))
1466 {res = false;}
1467
1468 G4bool yes = false;
1469 if(nSCoffRegions > 0) {yes = true;}
1470
1471 if(!RetrieveTable(part,theDEDXSubTable,ascii,directory,"SubDEDX",yes))
1472 {res = false;}
1473
1474 if(!RetrieveTable(part,theSubLambdaTable,ascii,directory,"SubLambda",yes))
1475 {res = false;}
1476
1477 if(!fpi) yes = false;
[1196]1478 if(!RetrieveTable(part,theIonisationSubTable,ascii,directory,"SubIonisation",yes))
[961]1479 {res = false;}
1480 }
1481 }
1482
1483 return res;
1484}
1485
1486//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
1487
[1055]1488G4bool G4VEnergyLossProcess::StoreTable(const G4ParticleDefinition* part,
1489 G4PhysicsTable* aTable, G4bool ascii,
1490 const G4String& directory,
1491 const G4String& tname)
1492{
1493 G4bool res = true;
1494 if ( aTable ) {
1495 const G4String name = GetPhysicsTableFileName(part,directory,tname,ascii);
1496 if( !aTable->StorePhysicsTable(name,ascii)) res = false;
1497 }
1498 return res;
1499}
1500
1501//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
1502
[1196]1503G4bool
1504G4VEnergyLossProcess::RetrieveTable(const G4ParticleDefinition* part,
1505 G4PhysicsTable* aTable,
1506 G4bool ascii,
1507 const G4String& directory,
1508 const G4String& tname,
1509 G4bool mandatory)
[961]1510{
[1315]1511 G4bool isRetrieved = false;
[961]1512 G4String filename = GetPhysicsTableFileName(part,directory,tname,ascii);
[1315]1513 if(aTable) {
1514 if(aTable->ExistPhysicsTable(filename)) {
1515 if(G4PhysicsTableHelper::RetrievePhysicsTable(aTable,filename,ascii)) {
1516 isRetrieved = true;
1517 if((G4LossTableManager::Instance())->SplineFlag()) {
1518 size_t n = aTable->length();
1519 for(size_t i=0; i<n; ++i) {
1520 if((*aTable)[i]) { (*aTable)[i]->SetSpline(true); }
1521 }
[1196]1522 }
[1315]1523 if (0 < verboseLevel) {
1524 G4cout << tname << " table for " << part->GetParticleName()
1525 << " is Retrieved from <" << filename << ">"
1526 << G4endl;
1527 }
[1196]1528 }
[961]1529 }
1530 }
[1315]1531 if(mandatory && !isRetrieved) {
1532 if(0 < verboseLevel) {
[961]1533 G4cout << tname << " table for " << part->GetParticleName()
1534 << " from file <"
1535 << filename << "> is not Retrieved"
[819]1536 << G4endl;
1537 }
[1315]1538 return false;
[819]1539 }
[1315]1540 return true;
[819]1541}
1542
1543//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
[1055]1544
1545G4double G4VEnergyLossProcess::GetDEDXDispersion(
1546 const G4MaterialCutsCouple *couple,
1547 const G4DynamicParticle* dp,
1548 G4double length)
1549{
1550 DefineMaterial(couple);
1551 G4double ekin = dp->GetKineticEnergy();
1552 SelectModel(ekin*massRatio);
1553 G4double tmax = currentModel->MaxSecondaryKinEnergy(dp);
1554 tmax = std::min(tmax,(*theCuts)[currentMaterialIndex]);
1555 G4double d = 0.0;
1556 G4VEmFluctuationModel* fm = currentModel->GetModelOfFluctuations();
1557 if(fm) d = fm->Dispersion(currentMaterial,dp,tmax,length);
1558 return d;
1559}
1560
1561//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1562
1563G4double G4VEnergyLossProcess::CrossSectionPerVolume(
1564 G4double kineticEnergy, const G4MaterialCutsCouple* couple)
1565{
1566 // Cross section per volume is calculated
1567 DefineMaterial(couple);
1568 G4double cross = 0.0;
1569 if(theLambdaTable) {
[1196]1570 cross = ((*theLambdaTable)[currentMaterialIndex])->Value(kineticEnergy);
[1055]1571 } else {
1572 SelectModel(kineticEnergy);
[1196]1573 cross = currentModel->CrossSectionPerVolume(currentMaterial,
1574 particle, kineticEnergy,
1575 (*theCuts)[currentMaterialIndex]);
[1055]1576 }
[1315]1577 if(cross < 0.0) { cross = 0.0; }
[1055]1578 return cross;
1579}
1580
1581//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1582
1583G4double G4VEnergyLossProcess::MeanFreePath(const G4Track& track)
1584{
1585 DefineMaterial(track.GetMaterialCutsCouple());
1586 preStepLambda = GetLambdaForScaledEnergy(track.GetKineticEnergy()*massRatio);
1587 G4double x = DBL_MAX;
[1315]1588 if(DBL_MIN < preStepLambda) { x = 1.0/preStepLambda; }
[1055]1589 return x;
1590}
1591
1592//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1593
1594G4double G4VEnergyLossProcess::ContinuousStepLimit(const G4Track& track,
1595 G4double x, G4double y,
1596 G4double& z)
1597{
1598 G4GPILSelection sel;
1599 return AlongStepGetPhysicalInteractionLength(track, x, y, z, &sel);
1600}
1601
1602//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1603
1604G4double G4VEnergyLossProcess::GetMeanFreePath(
1605 const G4Track& track,
1606 G4double,
1607 G4ForceCondition* condition)
1608
1609{
1610 *condition = NotForced;
1611 return MeanFreePath(track);
1612}
1613
1614//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1615
1616G4double G4VEnergyLossProcess::GetContinuousStepLimit(
1617 const G4Track&,
1618 G4double, G4double, G4double&)
1619{
1620 return DBL_MAX;
1621}
1622
1623//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1624
[1315]1625G4PhysicsVector*
1626G4VEnergyLossProcess::LambdaPhysicsVector(const G4MaterialCutsCouple* /*couple*/,
1627 G4double /*cut*/)
[1055]1628{
[1315]1629 /*
[1055]1630 G4double tmin =
1631 std::max(MinPrimaryEnergy(particle, couple->GetMaterial(), cut),
1632 minKinEnergy);
[1315]1633 if(tmin >= maxKinEnergy) { tmin = 0.5*maxKinEnergy; }
[1055]1634 G4PhysicsVector* v = new G4PhysicsLogVector(tmin, maxKinEnergy, nBins);
[1315]1635 */
1636 G4PhysicsVector* v = new G4PhysicsLogVector(minKinEnergy, maxKinEnergy, nBins);
[1055]1637 v->SetSpline((G4LossTableManager::Instance())->SplineFlag());
1638 return v;
1639}
1640
1641//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
[961]1642
1643void G4VEnergyLossProcess::AddCollaborativeProcess(
1644 G4VEnergyLossProcess* p)
1645{
1646 G4bool add = true;
[1315]1647 if(p->GetProcessName() != "eBrem") { add = false; }
[961]1648 if(add && nProcesses > 0) {
[1196]1649 for(G4int i=0; i<nProcesses; ++i) {
[961]1650 if(p == scProcesses[i]) {
1651 add = false;
1652 break;
1653 }
1654 }
1655 }
1656 if(add) {
1657 scProcesses.push_back(p);
[1196]1658 ++nProcesses;
[961]1659 if (1 < verboseLevel) {
1660 G4cout << "### The process " << p->GetProcessName()
1661 << " is added to the list of collaborative processes of "
1662 << GetProcessName() << G4endl;
1663 }
1664 }
1665}
1666
1667//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1668
[1055]1669void G4VEnergyLossProcess::SetDEDXTable(G4PhysicsTable* p, G4EmTableType tType)
[819]1670{
[1055]1671 if(fTotal == tType && theDEDXunRestrictedTable != p) {
1672 if(theDEDXunRestrictedTable) theDEDXunRestrictedTable->clearAndDestroy();
1673 theDEDXunRestrictedTable = p;
1674 if(p) {
1675 size_t n = p->length();
1676 G4PhysicsVector* pv = (*p)[0];
1677 G4double emax = maxKinEnergyCSDA;
1678 theDEDXAtMaxEnergy = new G4double [n];
1679
[1196]1680 for (size_t i=0; i<n; ++i) {
[1055]1681 pv = (*p)[i];
[1196]1682 G4double dedx = pv->Value(emax);
[1055]1683 theDEDXAtMaxEnergy[i] = dedx;
1684 //G4cout << "i= " << i << " emax(MeV)= " << emax/MeV<< " dedx= "
1685 //<< dedx << G4endl;
1686 }
1687 }
1688
1689 } else if(fRestricted == tType) {
1690 theDEDXTable = p;
1691 } else if(fSubRestricted == tType) {
1692 theDEDXSubTable = p;
1693 } else if(fIsIonisation == tType && theIonisationTable != p) {
1694 if(theIonisationTable) theIonisationTable->clearAndDestroy();
1695 theIonisationTable = p;
1696 } else if(fIsSubIonisation == tType && theIonisationSubTable != p) {
1697 if(theIonisationSubTable) theIonisationSubTable->clearAndDestroy();
1698 theIonisationSubTable = p;
1699 }
[819]1700}
1701
1702//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1703
[1055]1704void G4VEnergyLossProcess::SetCSDARangeTable(G4PhysicsTable* p)
1705{
[1315]1706 if(theCSDARangeTable != p) { theCSDARangeTable = p; }
[819]1707
[1055]1708 if(p) {
1709 size_t n = p->length();
1710 G4PhysicsVector* pv = (*p)[0];
1711 G4double emax = maxKinEnergyCSDA;
1712 theRangeAtMaxEnergy = new G4double [n];
1713
[1196]1714 for (size_t i=0; i<n; ++i) {
[1055]1715 pv = (*p)[i];
[1196]1716 G4double r2 = pv->Value(emax);
[1055]1717 theRangeAtMaxEnergy[i] = r2;
1718 //G4cout << "i= " << i << " e2(MeV)= " << emax/MeV << " r2= "
1719 //<< r2<< G4endl;
1720 }
1721 }
1722}
1723
[819]1724//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1725
[1055]1726void G4VEnergyLossProcess::SetRangeTableForLoss(G4PhysicsTable* p)
1727{
1728 if(theRangeTableForLoss != p) {
1729 theRangeTableForLoss = p;
1730 if(1 < verboseLevel) {
1731 G4cout << "### Set Range table " << p
1732 << " for " << particle->GetParticleName()
1733 << " and process " << GetProcessName() << G4endl;
1734 }
1735 }
1736}
1737
1738//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1739
1740void G4VEnergyLossProcess::SetSecondaryRangeTable(G4PhysicsTable* p)
1741{
1742 if(theSecondaryRangeTable != p) {
1743 theSecondaryRangeTable = p;
1744 if(1 < verboseLevel) {
1745 G4cout << "### Set SecondaryRange table " << p
1746 << " for " << particle->GetParticleName()
1747 << " and process " << GetProcessName() << G4endl;
1748 }
1749 }
1750}
1751
1752//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1753
1754void G4VEnergyLossProcess::SetInverseRangeTable(G4PhysicsTable* p)
1755{
1756 if(theInverseRangeTable != p) {
1757 theInverseRangeTable = p;
1758 if(1 < verboseLevel) {
1759 G4cout << "### Set InverseRange table " << p
1760 << " for " << particle->GetParticleName()
1761 << " and process " << GetProcessName() << G4endl;
1762 }
1763 }
1764}
1765
1766//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1767
1768void G4VEnergyLossProcess::SetLambdaTable(G4PhysicsTable* p)
1769{
1770 if(1 < verboseLevel) {
1771 G4cout << "### Set Lambda table " << p
1772 << " for " << particle->GetParticleName()
1773 << " and process " << GetProcessName() << G4endl;
1774 }
[1315]1775 if(theLambdaTable != p) { theLambdaTable = p; }
[1055]1776 tablesAreBuilt = true;
1777
1778 if(p) {
1779 size_t n = p->length();
1780 G4PhysicsVector* pv = (*p)[0];
1781 G4double e, s, smax, emax;
1782 theEnergyOfCrossSectionMax = new G4double [n];
1783 theCrossSectionMax = new G4double [n];
1784
[1196]1785 for (size_t i=0; i<n; ++i) {
[1055]1786 pv = (*p)[i];
1787 emax = DBL_MAX;
1788 smax = 0.0;
1789 if(pv) {
1790 size_t nb = pv->GetVectorLength();
[1196]1791 if(nb > 0) {
1792 for (size_t j=0; j<nb; ++j) {
1793 e = pv->Energy(j);
1794 s = (*pv)(j);
1795 if(s > smax) {
1796 smax = s;
1797 emax = e;
1798 }
[1055]1799 }
1800 }
1801 }
1802 theEnergyOfCrossSectionMax[i] = emax;
1803 theCrossSectionMax[i] = smax;
1804 if(1 < verboseLevel) {
1805 G4cout << "For " << particle->GetParticleName()
1806 << " Max CS at i= " << i << " emax(MeV)= " << emax/MeV
1807 << " lambda= " << smax << G4endl;
1808 }
1809 }
1810 }
1811}
1812
1813//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1814
1815void G4VEnergyLossProcess::SetSubLambdaTable(G4PhysicsTable* p)
1816{
1817 if(theSubLambdaTable != p) {
1818 theSubLambdaTable = p;
1819 if(1 < verboseLevel) {
1820 G4cout << "### Set SebLambda table " << p
1821 << " for " << particle->GetParticleName()
1822 << " and process " << GetProcessName() << G4endl;
1823 }
1824 }
1825}
1826
1827//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1828
[1315]1829const G4Element* G4VEnergyLossProcess::GetCurrentElement() const
1830{
1831 const G4Element* elm = 0;
1832 if(currentModel) { elm = currentModel->GetCurrentElement(); }
1833 return elm;
1834}
1835
1836//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1837
Note: See TracBrowser for help on using the repository browser.