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

Last change on this file since 953 was 819, checked in by garnier, 17 years ago

import all except CVS

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