Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4VEnergyLossProcess.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26// -------------------------------------------------------------------
27//
28// GEANT4 Class file
29//
30//
31// File name: G4VEnergyLossProcess
32//
33// Author: Vladimir Ivanchenko
34//
35// Creation date: 03.01.2002
36//
37// Modifications: Vladimir Ivanchenko
38//
39//
40// Class Description:
41//
42// It is the unified energy loss process it calculates the continuous
43// energy loss for charged particles using a set of Energy Loss
44// models valid for different energy regions. There are a possibility
45// to create and access to dE/dx and range tables, or to calculate
46// that information on fly.
47// -------------------------------------------------------------------
48//
49//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
50//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
51
54#include "G4SystemOfUnits.hh"
55#include "G4ProcessManager.hh"
56#include "G4LossTableManager.hh"
57#include "G4LossTableBuilder.hh"
58#include "G4Step.hh"
60#include "G4ParticleTable.hh"
61#include "G4EmParameters.hh"
62#include "G4EmUtility.hh"
63#include "G4EmTableUtil.hh"
64#include "G4VEmModel.hh"
66#include "G4DataVector.hh"
67#include "G4PhysicsLogVector.hh"
68#include "G4VParticleChange.hh"
69#include "G4Electron.hh"
70#include "G4ProcessManager.hh"
71#include "G4UnitsTable.hh"
72#include "G4Region.hh"
73#include "G4RegionStore.hh"
75#include "G4SafetyHelper.hh"
76#include "G4EmDataHandler.hh"
79#include "G4VSubCutProducer.hh"
80#include "G4EmBiasingManager.hh"
81#include "G4Log.hh"
82#include <iostream>
83
84//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
85
86namespace
87{
88 G4String tnames[7] =
89 {"DEDX","Ionisation","DEDXnr","CSDARange","Lambda","Range","InverseRange"};
90}
91
92
94 G4ProcessType type):
96{
97 theParameters = G4EmParameters::Instance();
99
100 // low energy limit
101 lowestKinEnergy = theParameters->LowestElectronEnergy();
102
103 // Size of tables
104 minKinEnergy = 0.1*CLHEP::keV;
105 maxKinEnergy = 100.0*CLHEP::TeV;
106 maxKinEnergyCSDA = 1.0*CLHEP::GeV;
107 nBins = 84;
108 nBinsCSDA = 35;
109
110 invLambdaFactor = 1.0/lambdaFactor;
111
112 // default linear loss limit
113 finalRange = 1.*CLHEP::mm;
114
115 // run time objects
118 modelManager = new G4EmModelManager();
120 ->GetSafetyHelper();
121 aGPILSelection = CandidateForSelection;
122
123 // initialise model
124 lManager = G4LossTableManager::Instance();
125 lManager->Register(this);
126 isMaster = lManager->IsMaster();
127
128 G4LossTableBuilder* bld = lManager->GetTableBuilder();
129 theDensityFactor = bld->GetDensityFactors();
130 theDensityIdx = bld->GetCoupleIndexes();
131
132 scTracks.reserve(10);
133 secParticles.reserve(12);
134 emModels = new std::vector<G4VEmModel*>;
135}
136
137//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
138
140{
141 if (isMaster) {
142 if(nullptr == baseParticle) { delete theData; }
143 delete theEnergyOfCrossSectionMax;
144 if(nullptr != fXSpeaks) {
145 for(auto const & v : *fXSpeaks) { delete v; }
146 delete fXSpeaks;
147 }
148 }
149 delete modelManager;
150 delete biasManager;
151 delete scoffRegions;
152 delete emModels;
153 lManager->DeRegister(this);
154}
155
156//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
157
159 const G4Material*,
160 G4double cut)
161{
162 return cut;
163}
164
165//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
166
169 const G4Region* region)
170{
171 if(nullptr == ptr) { return; }
172 G4VEmFluctuationModel* afluc = (nullptr == fluc) ? fluctModel : fluc;
173 modelManager->AddEmModel(order, ptr, afluc, region);
175}
176
177//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
178
180{
181 if(nullptr == ptr) { return; }
182 if(!emModels->empty()) {
183 for(auto & em : *emModels) { if(em == ptr) { return; } }
184 }
185 emModels->push_back(ptr);
186}
187
188//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
189
191 G4double charge2ratio)
192{
193 massRatio = massratio;
194 logMassRatio = G4Log(massRatio);
195 fFactor = charge2ratio*biasFactor;
196 if(baseMat) { fFactor *= (*theDensityFactor)[currentCoupleIndex]; }
197 chargeSqRatio = charge2ratio;
198 reduceFactor = 1.0/(fFactor*massRatio);
199}
200
201//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
202
203void
205{
206 particle = G4EmTableUtil::CheckIon(this, &part, particle,
207 verboseLevel, isIon);
208
209 if( particle != &part ) {
210 if(!isIon) { lManager->RegisterExtraParticle(&part, this); }
211 if(1 < verboseLevel) {
212 G4cout << "### G4VEnergyLossProcess::PreparePhysicsTable()"
213 << " interrupted for "
214 << part.GetParticleName() << " isIon=" << isIon << G4endl;
215 }
216 return;
217 }
218
219 tablesAreBuilt = false;
220
221 G4LossTableBuilder* bld = lManager->GetTableBuilder();
222 lManager->PreparePhysicsTable(&part, this, isMaster);
223
224 // Base particle and set of models can be defined here
225 InitialiseEnergyLossProcess(particle, baseParticle);
226
227 // parameters of the process
228 if(!actLossFluc) { lossFluctuationFlag = theParameters->LossFluctuation(); }
229 rndmStepFlag = theParameters->UseCutAsFinalRange();
230 if(!actMinKinEnergy) { minKinEnergy = theParameters->MinKinEnergy(); }
231 if(!actMaxKinEnergy) { maxKinEnergy = theParameters->MaxKinEnergy(); }
232 if(!actBinning) { nBins = theParameters->NumberOfBins(); }
233 maxKinEnergyCSDA = theParameters->MaxEnergyForCSDARange();
234 nBinsCSDA = theParameters->NumberOfBinsPerDecade()
235 *G4lrint(std::log10(maxKinEnergyCSDA/minKinEnergy));
236 if(!actLinLossLimit) { linLossLimit = theParameters->LinearLossLimit(); }
237 lambdaFactor = theParameters->LambdaFactor();
238 invLambdaFactor = 1.0/lambdaFactor;
239 if(isMaster) { SetVerboseLevel(theParameters->Verbose()); }
240 else { SetVerboseLevel(theParameters->WorkerVerbose()); }
241 // integral option may be disabled
242 if(!theParameters->Integral()) { fXSType = fEmNoIntegral; }
243
244 theParameters->DefineRegParamForLoss(this);
245
246 fRangeEnergy = 0.0;
247
248 G4double initialCharge = particle->GetPDGCharge();
249 G4double initialMass = particle->GetPDGMass();
250
251 theParameters->FillStepFunction(particle, this);
252
253 // parameters for scaling from the base particle
254 if (nullptr != baseParticle) {
255 massRatio = (baseParticle->GetPDGMass())/initialMass;
256 logMassRatio = G4Log(massRatio);
257 G4double q = initialCharge/baseParticle->GetPDGCharge();
258 chargeSqRatio = q*q;
259 if(chargeSqRatio > 0.0) { reduceFactor = 1.0/(chargeSqRatio*massRatio); }
260 }
261 lowestKinEnergy = (initialMass < CLHEP::MeV)
262 ? theParameters->LowestElectronEnergy()
263 : theParameters->LowestMuHadEnergy();
264
265 // Tables preparation
266 if (isMaster && nullptr == baseParticle) {
267 if(nullptr == theData) { theData = new G4EmDataHandler(7); }
268
269 if(nullptr != theDEDXTable && isIonisation) {
270 if(nullptr != theIonisationTable && theDEDXTable != theIonisationTable) {
271 theData->CleanTable(0);
272 theDEDXTable = theIonisationTable;
273 theIonisationTable = nullptr;
274 }
275 }
276
277 theDEDXTable = theData->MakeTable(theDEDXTable, 0);
278 bld->InitialiseBaseMaterials(theDEDXTable);
279 theData->UpdateTable(theIonisationTable, 1);
280
281 if (theParameters->BuildCSDARange()) {
282 theDEDXunRestrictedTable = theData->MakeTable(2);
283 if(isIonisation) { theCSDARangeTable = theData->MakeTable(3); }
284 }
285
286 theLambdaTable = theData->MakeTable(4);
287 if(isIonisation) {
288 theRangeTableForLoss = theData->MakeTable(5);
289 theInverseRangeTable = theData->MakeTable(6);
290 }
291 }
292
293 // forced biasing
294 if(nullptr != biasManager) {
295 biasManager->Initialise(part,GetProcessName(),verboseLevel);
296 biasFlag = false;
297 }
298 baseMat = bld->GetBaseMaterialFlag();
299 numberOfModels = modelManager->NumberOfModels();
300 currentModel = modelManager->GetModel(0);
301 G4EmTableUtil::UpdateModels(this, modelManager, maxKinEnergy,
302 numberOfModels, secID, biasID,
303 mainSecondaries, baseMat, isMaster,
304 theParameters->UseAngularGeneratorForIonisation());
305 theCuts = modelManager->Initialise(particle, secondaryParticle,
307 // subcut processor
308 if(isIonisation) {
309 subcutProducer = lManager->SubCutProducer();
310 }
311 if(1 == nSCoffRegions) {
312 if((*scoffRegions)[0]->GetName() == "DefaultRegionForTheWorld") {
313 delete scoffRegions;
314 scoffRegions = nullptr;
315 nSCoffRegions = 0;
316 }
317 }
318
319 if(1 < verboseLevel) {
320 G4cout << "G4VEnergyLossProcess::PrepearPhysicsTable() is done "
321 << " for local " << particle->GetParticleName()
322 << " isIon= " << isIon;
323 if(baseParticle) {
324 G4cout << "; base: " << baseParticle->GetParticleName();
325 }
326 G4cout << " chargeSqRatio= " << chargeSqRatio
327 << " massRatio= " << massRatio
328 << " reduceFactor= " << reduceFactor << G4endl;
329 if (nSCoffRegions > 0) {
330 G4cout << " SubCut secondary production is ON for regions: " << G4endl;
331 for (G4int i=0; i<nSCoffRegions; ++i) {
332 const G4Region* r = (*scoffRegions)[i];
333 G4cout << " " << r->GetName() << G4endl;
334 }
335 } else if(nullptr != subcutProducer) {
336 G4cout << " SubCut secondary production is ON for all regions" << G4endl;
337 }
338 }
339}
340
341//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
342
344{
345 if(1 < verboseLevel) {
346 G4cout << "### G4VEnergyLossProcess::BuildPhysicsTable() for "
347 << GetProcessName()
348 << " and particle " << part.GetParticleName()
349 << "; local: " << particle->GetParticleName();
350 if(baseParticle) {
351 G4cout << "; base: " << baseParticle->GetParticleName();
352 }
353 G4cout << " TablesAreBuilt= " << tablesAreBuilt
354 << " isIon= " << isIon << " " << this << G4endl;
355 }
356
357 if(&part == particle) {
358
359 if(isMaster) {
360 lManager->BuildPhysicsTable(particle, this);
361
362 } else {
363 const auto masterProcess =
364 static_cast<const G4VEnergyLossProcess*>(GetMasterProcess());
365
366 numberOfModels = modelManager->NumberOfModels();
367 G4EmTableUtil::BuildLocalElossProcess(this, masterProcess,
368 particle, numberOfModels);
369 tablesAreBuilt = true;
370 baseMat = masterProcess->UseBaseMaterial();
371 lManager->LocalPhysicsTables(particle, this);
372 }
373
374 // needs to be done only once
375 safetyHelper->InitialiseHelper();
376 }
377 // Added tracking cut to avoid tracking artifacts
378 // and identified deexcitation flag
379 if(isIonisation) {
380 atomDeexcitation = lManager->AtomDeexcitation();
381 if(nullptr != atomDeexcitation) {
382 if(atomDeexcitation->IsPIXEActive()) { useDeexcitation = true; }
383 }
384 }
385
386 // protection against double printout
387 if(theParameters->IsPrintLocked()) { return; }
388
389 // explicitly defined printout by particle name
390 G4String num = part.GetParticleName();
391 if(1 < verboseLevel ||
392 (0 < verboseLevel && (num == "e-" ||
393 num == "e+" || num == "mu+" ||
394 num == "mu-" || num == "proton"||
395 num == "pi+" || num == "pi-" ||
396 num == "kaon+" || num == "kaon-" ||
397 num == "alpha" || num == "anti_proton" ||
398 num == "GenericIon"|| num == "alpha+" ))) {
399 StreamInfo(G4cout, part);
400 }
401 if(1 < verboseLevel) {
402 G4cout << "### G4VEnergyLossProcess::BuildPhysicsTable() done for "
403 << GetProcessName()
404 << " and particle " << part.GetParticleName();
405 if(isIonisation) { G4cout << " isIonisation flag=1"; }
406 G4cout << " baseMat=" << baseMat << G4endl;
407 }
408}
409
410//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
411
413{
414 G4PhysicsTable* table = nullptr;
415 G4double emax = maxKinEnergy;
416 G4int bin = nBins;
417
418 if(fTotal == tType) {
419 emax = maxKinEnergyCSDA;
420 bin = nBinsCSDA;
421 table = theDEDXunRestrictedTable;
422 } else if(fRestricted == tType) {
423 table = theDEDXTable;
424 } else {
425 G4cout << "G4VEnergyLossProcess::BuildDEDXTable WARNING: wrong type "
426 << tType << G4endl;
427 }
428 if(1 < verboseLevel) {
429 G4cout << "G4VEnergyLossProcess::BuildDEDXTable() of type " << tType
430 << " for " << GetProcessName()
431 << " and " << particle->GetParticleName() << G4endl;
432 }
433 if(nullptr == table) { return table; }
434
435 G4LossTableBuilder* bld = lManager->GetTableBuilder();
436 G4EmTableUtil::BuildDEDXTable(this, particle, modelManager, bld,
437 table, minKinEnergy, emax, bin,
438 verboseLevel, tType, spline);
439 return table;
440}
441
442//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
443
445{
446 if(nullptr == theLambdaTable) { return theLambdaTable; }
447
448 G4double scale = theParameters->MaxKinEnergy()/theParameters->MinKinEnergy();
449 G4int nbin =
450 theParameters->NumberOfBinsPerDecade()*G4lrint(std::log10(scale));
451 scale = nbin/G4Log(scale);
452
453 G4LossTableBuilder* bld = lManager->GetTableBuilder();
454 G4EmTableUtil::BuildLambdaTable(this, particle, modelManager,
455 bld, theLambdaTable, theCuts,
456 minKinEnergy, maxKinEnergy, scale,
457 verboseLevel, spline);
458 return theLambdaTable;
459}
460
461//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
462
463void G4VEnergyLossProcess::StreamInfo(std::ostream& out,
464 const G4ParticleDefinition& part, G4bool rst) const
465{
466 G4String indent = (rst ? " " : "");
467 out << std::setprecision(6);
468 out << G4endl << indent << GetProcessName() << ": ";
469 if (!rst) out << " for " << part.GetParticleName();
470 out << " XStype:" << fXSType
471 << " SubType=" << GetProcessSubType() << G4endl
472 << " dE/dx and range tables from "
473 << G4BestUnit(minKinEnergy,"Energy")
474 << " to " << G4BestUnit(maxKinEnergy,"Energy")
475 << " in " << nBins << " bins" << G4endl
476 << " Lambda tables from threshold to "
477 << G4BestUnit(maxKinEnergy,"Energy")
478 << ", " << theParameters->NumberOfBinsPerDecade()
479 << " bins/decade, spline: " << spline
480 << G4endl;
481 if(nullptr != theRangeTableForLoss && isIonisation) {
482 out << " StepFunction=(" << dRoverRange << ", "
483 << finalRange/mm << " mm)"
484 << ", integ: " << fXSType
485 << ", fluct: " << lossFluctuationFlag
486 << ", linLossLim= " << linLossLimit
487 << G4endl;
488 }
490 modelManager->DumpModelList(out, verboseLevel);
491 if(nullptr != theCSDARangeTable && isIonisation) {
492 out << " CSDA range table up"
493 << " to " << G4BestUnit(maxKinEnergyCSDA,"Energy")
494 << " in " << nBinsCSDA << " bins" << G4endl;
495 }
496 if(nSCoffRegions>0 && isIonisation) {
497 out << " Subcutoff sampling in " << nSCoffRegions
498 << " regions" << G4endl;
499 }
500 if(2 < verboseLevel) {
501 for(std::size_t i=0; i<7; ++i) {
502 auto ta = theData->Table(i);
503 out << " " << tnames[i] << " address: " << ta << G4endl;
504 if(nullptr != ta) { out << *ta << G4endl; }
505 }
506 }
507}
508
509//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
510
512{
513 if(nullptr == scoffRegions) {
514 scoffRegions = new std::vector<const G4Region*>;
515 }
516 // the region is in the list
517 if(!scoffRegions->empty()) {
518 for (auto & reg : *scoffRegions) {
519 if (reg == r) { return; }
520 }
521 }
522 // new region
523 scoffRegions->push_back(r);
524 ++nSCoffRegions;
525}
526
527//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
528
529G4bool G4VEnergyLossProcess::IsRegionForCubcutProcessor(const G4Track& aTrack)
530{
531 if(0 == nSCoffRegions) { return true; }
532 const G4Region* r = aTrack.GetVolume()->GetLogicalVolume()->GetRegion();
533 for(auto & reg : *scoffRegions) {
534 if(r == reg) { return true; }
535 }
536 return false;
537}
538
539//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
540
542{
543 // reset parameters for the new track
546 currentCouple = nullptr;
547
548 // reset ion
549 if(isIon) {
550 const G4double newmass = track->GetDefinition()->GetPDGMass();
551 if(nullptr != baseParticle) {
552 massRatio = baseParticle->GetPDGMass()/newmass;
553 logMassRatio = G4Log(massRatio);
554 } else if(isIon) {
555 massRatio = CLHEP::proton_mass_c2/newmass;
556 logMassRatio = G4Log(massRatio);
557 } else {
558 massRatio = 1.0;
559 logMassRatio = 0.0;
560 }
561 }
562 // forced biasing only for primary particles
563 if(nullptr != biasManager) {
564 if(0 == track->GetParentID()) {
565 biasFlag = true;
566 biasManager->ResetForcedInteraction();
567 }
568 }
569}
570
571//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
572
575 G4GPILSelection* selection)
576{
577 G4double x = DBL_MAX;
578 *selection = aGPILSelection;
579 if(isIonisation && currentModel->IsActive(preStepScaledEnergy)) {
580 GetScaledRangeForScaledEnergy(preStepScaledEnergy, preStepLogScaledEnergy);
581 const G4double finR = (rndmStepFlag) ? std::min(finalRange,
583 x = (fRange > finR) ?
584 fRange*dRoverRange + finR*(1.0-dRoverRange)*(2.0-finR/fRange) : fRange;
585 }
586 //G4cout<<"AlongStepGPIL: " << GetProcessName()<<": e= "<<preStepKinEnergy
587 //<<" stepLimit= "<<x<<G4endl;
588 return x;
589}
590
591//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
592
594 const G4Track& track,
595 G4double previousStepSize,
597{
598 // condition is set to "Not Forced"
600 G4double x = DBL_MAX;
601
602 // initialisation of material, mass, charge, model
603 // at the beginning of the step
604 DefineMaterial(track.GetMaterialCutsCouple());
610
611 if(!currentModel->IsActive(preStepScaledEnergy)) {
614 return x;
615 }
616
617 // change effective charge of a charged particle on fly
618 if(isIon) {
619 const G4double q2 = currentModel->ChargeSquareRatio(track);
620 if(q2 != chargeSqRatio) {
621 fFactor *= q2/chargeSqRatio;
622 reduceFactor = 1.0/(fFactor*massRatio);
623 chargeSqRatio = q2;
624 }
625 if (lossFluctuationFlag) {
626 auto fluc = currentModel->GetModelOfFluctuations();
627 fluc->SetParticleAndCharge(track.GetDefinition(), q2);
628 }
629 }
630
631 // forced biasing only for primary particles
632 if(biasManager) {
633 if(0 == track.GetParentID() && biasFlag &&
635 return biasManager->GetStepLimit((G4int)currentCoupleIndex, previousStepSize);
636 }
637 }
638
639 // compute mean free path
640 ComputeLambdaForScaledEnergy(preStepScaledEnergy, preStepLogScaledEnergy);
641
642 // zero cross section
643 if(preStepLambda <= 0.0) {
646 } else {
647
648 // non-zero cross section
650
651 // beggining of tracking (or just after DoIt of this process)
654
655 } else if(currentInteractionLength < DBL_MAX) {
656
657 // subtract NumberOfInteractionLengthLeft using previous step
659 previousStepSize/currentInteractionLength;
660
663 }
664
665 // new mean free path and step limit
668 }
669#ifdef G4VERBOSE
670 if (verboseLevel>2) {
671 G4cout << "G4VEnergyLossProcess::PostStepGetPhysicalInteractionLength ";
672 G4cout << "[ " << GetProcessName() << "]" << G4endl;
673 G4cout << " for " << track.GetDefinition()->GetParticleName()
674 << " in Material " << currentMaterial->GetName()
675 << " Ekin(MeV)= " << preStepKinEnergy/MeV
676 << " track material: " << track.GetMaterial()->GetName()
677 <<G4endl;
678 G4cout << "MeanFreePath = " << currentInteractionLength/cm << "[cm]"
679 << "InteractionLength= " << x/cm <<"[cm] " <<G4endl;
680 }
681#endif
682 return x;
683}
684
685//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
686
687void
688G4VEnergyLossProcess::ComputeLambdaForScaledEnergy(G4double e, G4double loge)
689{
690 // cross section increased with energy
691 if(fXSType == fEmIncreasing) {
692 if(e*invLambdaFactor < mfpKinEnergy) {
693 mfpKinEnergy = e;
694 preStepLambda = GetLambdaForScaledEnergy(e, loge);
695 }
696
697 // cross section has one peak
698 } else if(fXSType == fEmOnePeak) {
699 const G4double epeak = (*theEnergyOfCrossSectionMax)[basedCoupleIndex];
700 if(e <= epeak) {
701 if(e*invLambdaFactor < mfpKinEnergy) {
702 mfpKinEnergy = e;
703 preStepLambda = GetLambdaForScaledEnergy(e, loge);
704 }
705 } else if(e < mfpKinEnergy) {
706 const G4double e1 = std::max(epeak, e*lambdaFactor);
707 mfpKinEnergy = e1;
708 preStepLambda = GetLambdaForScaledEnergy(e1);
709 }
710
711 // cross section has more than one peaks
712 } else if(fXSType == fEmTwoPeaks) {
713 G4TwoPeaksXS* xs = (*fXSpeaks)[basedCoupleIndex];
714 const G4double e1peak = xs->e1peak;
715
716 // below the 1st peak
717 if(e <= e1peak) {
718 if(e*invLambdaFactor < mfpKinEnergy) {
719 mfpKinEnergy = e;
720 preStepLambda = GetLambdaForScaledEnergy(e, loge);
721 }
722 return;
723 }
724 const G4double e1deep = xs->e1deep;
725 // above the 1st peak, below the deep
726 if(e <= e1deep) {
727 if(mfpKinEnergy >= e1deep || e <= mfpKinEnergy) {
728 const G4double e1 = std::max(e1peak, e*lambdaFactor);
729 mfpKinEnergy = e1;
730 preStepLambda = GetLambdaForScaledEnergy(e1);
731 }
732 return;
733 }
734 const G4double e2peak = xs->e2peak;
735 // above the deep, below 2nd peak
736 if(e <= e2peak) {
737 if(e*invLambdaFactor < mfpKinEnergy) {
738 mfpKinEnergy = e;
739 preStepLambda = GetLambdaForScaledEnergy(e, loge);
740 }
741 return;
742 }
743 const G4double e2deep = xs->e2deep;
744 // above the 2nd peak, below the deep
745 if(e <= e2deep) {
746 if(mfpKinEnergy >= e2deep || e <= mfpKinEnergy) {
747 const G4double e1 = std::max(e2peak, e*lambdaFactor);
748 mfpKinEnergy = e1;
749 preStepLambda = GetLambdaForScaledEnergy(e1);
750 }
751 return;
752 }
753 const G4double e3peak = xs->e3peak;
754 // above the deep, below 3d peak
755 if(e <= e3peak) {
756 if(e*invLambdaFactor < mfpKinEnergy) {
757 mfpKinEnergy = e;
758 preStepLambda = GetLambdaForScaledEnergy(e, loge);
759 }
760 return;
761 }
762 // above 3d peak
763 if(e <= mfpKinEnergy) {
764 const G4double e1 = std::max(e3peak, e*lambdaFactor);
765 mfpKinEnergy = e1;
766 preStepLambda = GetLambdaForScaledEnergy(e1);
767 }
768 // integral method is not used
769 } else {
770 preStepLambda = GetLambdaForScaledEnergy(e, loge);
771 }
772}
773
774//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
775
777 const G4Step& step)
778{
780 // The process has range table - calculate energy loss
781 if(!isIonisation || !currentModel->IsActive(preStepScaledEnergy)) {
782 return &fParticleChange;
783 }
784
785 // Get the actual (true) Step length
786 G4double length = step.GetStepLength();
787 if(length <= 0.0) { return &fParticleChange; }
788 G4double eloss = 0.0;
789
790 /*
791 if(-1 < verboseLevel) {
792 const G4ParticleDefinition* d = track.GetParticleDefinition();
793 G4cout << "AlongStepDoIt for "
794 << GetProcessName() << " and particle " << d->GetParticleName()
795 << " eScaled(MeV)=" << preStepScaledEnergy/MeV
796 << " range(mm)=" << fRange/mm << " s(mm)=" << length/mm
797 << " rf=" << reduceFactor << " q^2=" << chargeSqRatio
798 << " md=" << d->GetPDGMass() << " status=" << track.GetTrackStatus()
799 << " " << track.GetMaterial()->GetName() << G4endl;
800 }
801 */
802 const G4DynamicParticle* dynParticle = track.GetDynamicParticle();
803
804 // define new weight for primary and secondaries
806 if(weightFlag) {
807 weight /= biasFactor;
809 }
810
811 // stopping
812 if (length >= fRange || preStepKinEnergy <= lowestKinEnergy) {
813 eloss = preStepKinEnergy;
814 if (useDeexcitation) {
815 atomDeexcitation->AlongStepDeexcitation(scTracks, step,
816 eloss, (G4int)currentCoupleIndex);
817 if(scTracks.size() > 0) { FillSecondariesAlongStep(weight); }
818 eloss = std::max(eloss, 0.0);
819 }
822 return &fParticleChange;
823 }
824 // Short step
825 eloss = length*GetDEDXForScaledEnergy(preStepScaledEnergy,
827 //G4cout << "Short STEP: eloss= " << eloss << G4endl;
828
829 // Long step
830 if(eloss > preStepKinEnergy*linLossLimit) {
831
832 G4double x = (fRange - length)/reduceFactor;
833 //G4cout << "x= " << x << " " << theInverseRangeTable << G4endl;
834 eloss = preStepKinEnergy - ScaledKinEnergyForLoss(x)/massRatio;
835
836 /*
837 if(-1 < verboseLevel)
838 G4cout << "Long STEP: rPre(mm)= "
839 << GetScaledRangeForScaledEnergy(preStepScaledEnergy)/mm
840 << " rPost(mm)= " << x/mm
841 << " ePre(MeV)= " << preStepScaledEnergy/MeV
842 << " eloss(MeV)= " << eloss/MeV << " eloss0(MeV)= "
843 << GetDEDXForScaledEnergy(preStepScaledEnergy)*length/MeV
844 << " lim(MeV)= " << preStepKinEnergy*linLossLimit/MeV
845 << G4endl;
846 */
847 }
848
849 /*
850 if(-1 < verboseLevel ) {
851 G4cout << "Before fluct: eloss(MeV)= " << eloss/MeV
852 << " e-eloss= " << preStepKinEnergy-eloss
853 << " step(mm)= " << length/mm << " range(mm)= " << fRange/mm
854 << " fluct= " << lossFluctuationFlag << G4endl;
855 }
856 */
857
858 const G4double cut = (*theCuts)[currentCoupleIndex];
859 G4double esec = 0.0;
860
861 // Corrections, which cannot be tabulated
862 if(isIon) {
863 currentModel->CorrectionsAlongStep(currentCouple, dynParticle,
864 length, eloss);
865 eloss = std::max(eloss, 0.0);
866 }
867
868 // Sample fluctuations if not full energy loss
869 if(eloss >= preStepKinEnergy) {
870 eloss = preStepKinEnergy;
871
872 } else if (lossFluctuationFlag) {
873 const G4double tmax = currentModel->MaxSecondaryKinEnergy(dynParticle);
874 const G4double tcut = std::min(cut, tmax);
875 G4VEmFluctuationModel* fluc = currentModel->GetModelOfFluctuations();
876 eloss = fluc->SampleFluctuations(currentCouple,dynParticle,
877 tcut, tmax, length, eloss);
878 /*
879 if(-1 < verboseLevel)
880 G4cout << "After fluct: eloss(MeV)= " << eloss/MeV
881 << " fluc= " << (eloss-eloss0)/MeV
882 << " ChargeSqRatio= " << chargeSqRatio
883 << " massRatio= " << massRatio << " tmax= " << tmax << G4endl;
884 */
885 }
886
887 // deexcitation
888 if (useDeexcitation) {
889 G4double esecfluo = preStepKinEnergy;
890 G4double de = esecfluo;
891 atomDeexcitation->AlongStepDeexcitation(scTracks, step,
893
894 // sum of de-excitation energies
895 esecfluo -= de;
896
897 // subtracted from energy loss
898 if(eloss >= esecfluo) {
899 esec += esecfluo;
900 eloss -= esecfluo;
901 } else {
902 esec += esecfluo;
903 eloss = 0.0;
904 }
905 }
906 if(nullptr != subcutProducer && IsRegionForCubcutProcessor(track)) {
907 subcutProducer->SampleSecondaries(step, scTracks, eloss, cut);
908 }
909 // secondaries from atomic de-excitation and subcut
910 if(!scTracks.empty()) { FillSecondariesAlongStep(weight); }
911
912 // Energy balance
913 G4double finalT = preStepKinEnergy - eloss - esec;
914 if (finalT <= lowestKinEnergy) {
915 eloss += finalT;
916 finalT = 0.0;
917 } else if(isIon) {
919 currentModel->GetParticleCharge(track.GetParticleDefinition(),
920 currentMaterial,finalT));
921 }
922 eloss = std::max(eloss, 0.0);
923
926 /*
927 if(-1 < verboseLevel) {
928 G4double del = finalT + eloss + esec - preStepKinEnergy;
929 G4cout << "Final value eloss(MeV)= " << eloss/MeV
930 << " preStepKinEnergy= " << preStepKinEnergy
931 << " postStepKinEnergy= " << finalT
932 << " de(keV)= " << del/keV
933 << " lossFlag= " << lossFluctuationFlag
934 << " status= " << track.GetTrackStatus()
935 << G4endl;
936 }
937 */
938 return &fParticleChange;
939}
940
941//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
942
943void G4VEnergyLossProcess::FillSecondariesAlongStep(G4double wt)
944{
945 const std::size_t n0 = scTracks.size();
946 G4double weight = wt;
947 // weight may be changed by biasing manager
948 if(biasManager) {
950 weight *=
951 biasManager->ApplySecondaryBiasing(scTracks, (G4int)currentCoupleIndex);
952 }
953 }
954
955 // fill secondaries
956 const std::size_t n = scTracks.size();
958
959 for(std::size_t i=0; i<n; ++i) {
960 G4Track* t = scTracks[i];
961 if(nullptr != t) {
962 t->SetWeight(weight);
964 if(i >= n0) { t->SetCreatorModelID(biasID); }
965 }
966 }
967 scTracks.clear();
968}
969
970//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
971
973 const G4Step& step)
974{
975 // clear number of interaction lengths in any case
978
980 const G4double finalT = track.GetKineticEnergy();
981
982 const G4double postStepScaledEnergy = finalT*massRatio;
983 SelectModel(postStepScaledEnergy);
984
985 if(!currentModel->IsActive(postStepScaledEnergy)) {
986 return &fParticleChange;
987 }
988 /*
989 if(1 < verboseLevel) {
990 G4cout<<GetProcessName()<<" PostStepDoIt: E(MeV)= "<< finalT/MeV<< G4endl;
991 }
992 */
993 // forced process - should happen only once per track
994 if(biasFlag) {
996 biasFlag = false;
997 }
998 }
999 const G4DynamicParticle* dp = track.GetDynamicParticle();
1000
1001 // Integral approach
1002 if (fXSType != fEmNoIntegral) {
1003 const G4double logFinalT = dp->GetLogKineticEnergy();
1004 G4double lx = GetLambdaForScaledEnergy(postStepScaledEnergy,
1005 logFinalT + logMassRatio);
1006 lx = std::max(lx, 0.0);
1007
1008 // if both lg and lx are zero then no interaction
1009 if(preStepLambda*G4UniformRand() >= lx) {
1010 return &fParticleChange;
1011 }
1012 }
1013
1014 // define new weight for primary and secondaries
1016 if(weightFlag) {
1017 weight /= biasFactor;
1019 }
1020
1021 const G4double tcut = (*theCuts)[currentCoupleIndex];
1022
1023 // sample secondaries
1024 secParticles.clear();
1025 currentModel->SampleSecondaries(&secParticles, currentCouple, dp, tcut);
1026
1027 const G4int num0 = (G4int)secParticles.size();
1028
1029 // bremsstrahlung splitting or Russian roulette
1030 if(biasManager) {
1032 G4double eloss = 0.0;
1033 weight *= biasManager->ApplySecondaryBiasing(
1034 secParticles,
1035 track, currentModel,
1036 &fParticleChange, eloss,
1037 (G4int)currentCoupleIndex, tcut,
1038 step.GetPostStepPoint()->GetSafety());
1039 if(eloss > 0.0) {
1042 }
1043 }
1044 }
1045
1046 // save secondaries
1047 const G4int num = (G4int)secParticles.size();
1048 if(num > 0) {
1049
1051 G4double time = track.GetGlobalTime();
1052
1053 G4int n1(0), n2(0);
1054 if(num0 > mainSecondaries) {
1055 currentModel->FillNumberOfSecondaries(n1, n2);
1056 }
1057
1058 for (G4int i=0; i<num; ++i) {
1059 if(nullptr != secParticles[i]) {
1060 G4Track* t = new G4Track(secParticles[i], time, track.GetPosition());
1062 if (biasManager) {
1063 t->SetWeight(weight * biasManager->GetWeight(i));
1064 } else {
1065 t->SetWeight(weight);
1066 }
1067 if(i < num0) {
1068 t->SetCreatorModelID(secID);
1069 } else if(i < num0 + n1) {
1070 t->SetCreatorModelID(tripletID);
1071 } else {
1072 t->SetCreatorModelID(biasID);
1073 }
1074
1075 //G4cout << "Secondary(post step) has weight " << t->GetWeight()
1076 // << ", kenergy " << t->GetKineticEnergy()/MeV << " MeV"
1077 // << " time= " << time/ns << " ns " << G4endl;
1079 }
1080 }
1081 }
1082
1085 if(particle->GetProcessManager()->GetAtRestProcessVector()->size() > 0)
1088 }
1089
1090 /*
1091 if(-1 < verboseLevel) {
1092 G4cout << "::PostStepDoIt: Sample secondary; Efin= "
1093 << fParticleChange.GetProposedKineticEnergy()/MeV
1094 << " MeV; model= (" << currentModel->LowEnergyLimit()
1095 << ", " << currentModel->HighEnergyLimit() << ")"
1096 << " preStepLambda= " << preStepLambda
1097 << " dir= " << track.GetMomentumDirection()
1098 << " status= " << track.GetTrackStatus()
1099 << G4endl;
1100 }
1101 */
1102 return &fParticleChange;
1103}
1104
1105//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1106
1108 const G4ParticleDefinition* part, const G4String& dir, G4bool ascii)
1109{
1110 if (!isMaster || nullptr != baseParticle || part != particle ) return true;
1111 for(std::size_t i=0; i<7; ++i) {
1112 if(nullptr != theData->Table(i)) {
1113 if(1 < verboseLevel) {
1114 G4cout << "G4VEnergyLossProcess::StorePhysicsTable i=" << i
1115 << " " << particle->GetParticleName()
1116 << " " << GetProcessName()
1117 << " " << tnames[i] << " " << theData->Table(i) << G4endl;
1118 }
1119 if(!G4EmTableUtil::StoreTable(this, part, theData->Table(i),
1120 dir, tnames[i], verboseLevel, ascii)) {
1121 return false;
1122 }
1123 }
1124 }
1125 return true;
1126}
1127
1128//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
1129
1130G4bool
1132 const G4String& dir, G4bool ascii)
1133{
1134 if (!isMaster || nullptr != baseParticle || part != particle ) return true;
1135 for(std::size_t i=0; i<7; ++i) {
1136 if(!G4EmTableUtil::RetrieveTable(this, part, theData->Table(i), dir, tnames[i],
1137 verboseLevel, ascii, spline)) {
1138 return false;
1139 }
1140 }
1141 return true;
1142}
1143
1144//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1145
1147 const G4MaterialCutsCouple *couple,
1148 const G4DynamicParticle* dp,
1149 G4double length)
1150{
1151 DefineMaterial(couple);
1152 G4double ekin = dp->GetKineticEnergy();
1153 SelectModel(ekin*massRatio);
1154 G4double tmax = currentModel->MaxSecondaryKinEnergy(dp);
1155 G4double tcut = std::min(tmax,(*theCuts)[currentCoupleIndex]);
1156 G4double d = 0.0;
1157 G4VEmFluctuationModel* fm = currentModel->GetModelOfFluctuations();
1158 if(nullptr != fm) { d = fm->Dispersion(currentMaterial,dp,tcut,tmax,length); }
1159 return d;
1160}
1161
1162//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1163
1166 const G4MaterialCutsCouple* couple,
1167 G4double logKineticEnergy)
1168{
1169 // Cross section per volume is calculated
1170 DefineMaterial(couple);
1171 G4double cross = 0.0;
1172 if (nullptr != theLambdaTable) {
1173 cross = GetLambdaForScaledEnergy(kineticEnergy * massRatio,
1174 logKineticEnergy + logMassRatio);
1175 } else {
1176 SelectModel(kineticEnergy*massRatio);
1177 cross = (!baseMat) ? biasFactor : biasFactor*(*theDensityFactor)[currentCoupleIndex];
1178 cross *= (currentModel->CrossSectionPerVolume(currentMaterial, particle, kineticEnergy,
1179 (*theCuts)[currentCoupleIndex]));
1180 }
1181 return std::max(cross, 0.0);
1182}
1183
1184//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1185
1187{
1188 DefineMaterial(track.GetMaterialCutsCouple());
1189 const G4double kinEnergy = track.GetKineticEnergy();
1190 const G4double logKinEnergy = track.GetDynamicParticle()->GetLogKineticEnergy();
1191 const G4double cs = GetLambdaForScaledEnergy(kinEnergy * massRatio,
1192 logKinEnergy + logMassRatio);
1193 return (0.0 < cs) ? 1.0/cs : DBL_MAX;
1194}
1195
1196//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1197
1199 G4double x, G4double y,
1200 G4double& z)
1201{
1202 return AlongStepGetPhysicalInteractionLength(track, x, y, z, &aGPILSelection);
1203}
1204
1205//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1206
1208 const G4Track& track,
1209 G4double,
1211
1212{
1214 return MeanFreePath(track);
1215}
1216
1217//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1218
1220 const G4Track&,
1222{
1223 return DBL_MAX;
1224}
1225
1226//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1227
1230 G4double)
1231{
1232 DefineMaterial(couple);
1233 G4PhysicsVector* v = (*theLambdaTable)[basedCoupleIndex];
1234 return new G4PhysicsVector(*v);
1235}
1236
1237//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1238
1239void
1241{
1242 if(1 < verboseLevel) {
1243 G4cout << "### Set DEDX table " << p << " " << theDEDXTable
1244 << " " << theDEDXunRestrictedTable << " " << theIonisationTable
1245 << " for " << particle->GetParticleName()
1246 << " and process " << GetProcessName()
1247 << " type=" << tType << " isIonisation:" << isIonisation << G4endl;
1248 }
1249 if(fTotal == tType) {
1250 theDEDXunRestrictedTable = p;
1251 } else if(fRestricted == tType) {
1252 theDEDXTable = p;
1253 if(isMaster && nullptr == baseParticle) {
1254 theData->UpdateTable(theDEDXTable, 0);
1255 }
1256 } else if(fIsIonisation == tType) {
1257 theIonisationTable = p;
1258 if(isMaster && nullptr == baseParticle) {
1259 theData->UpdateTable(theIonisationTable, 1);
1260 }
1261 }
1262}
1263
1264//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1265
1267{
1268 theCSDARangeTable = p;
1269}
1270
1271//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1272
1274{
1275 theRangeTableForLoss = p;
1276}
1277
1278//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1279
1281{
1282 theInverseRangeTable = p;
1283}
1284
1285//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1286
1288{
1289 if(1 < verboseLevel) {
1290 G4cout << "### Set Lambda table " << p << " " << theLambdaTable
1291 << " for " << particle->GetParticleName()
1292 << " and process " << GetProcessName() << G4endl;
1293 }
1294 theLambdaTable = p;
1295 tablesAreBuilt = true;
1296
1297 if(isMaster && nullptr != p) {
1298 delete theEnergyOfCrossSectionMax;
1299 theEnergyOfCrossSectionMax = nullptr;
1300 if(fEmTwoPeaks == fXSType) {
1301 if(nullptr != fXSpeaks) {
1302 for(auto & ptr : *fXSpeaks) { delete ptr; }
1303 delete fXSpeaks;
1304 }
1305 G4LossTableBuilder* bld = lManager->GetTableBuilder();
1306 fXSpeaks = G4EmUtility::FillPeaksStructure(p, bld);
1307 if(nullptr == fXSpeaks) { fXSType = fEmOnePeak; }
1308 }
1309 if(fXSType == fEmOnePeak) {
1310 theEnergyOfCrossSectionMax = G4EmUtility::FindCrossSectionMax(p);
1311 if(nullptr == theEnergyOfCrossSectionMax) { fXSType = fEmIncreasing; }
1312 }
1313 }
1314}
1315
1316//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1317
1319{
1320 theEnergyOfCrossSectionMax = p;
1321}
1322
1323//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1324
1325void G4VEnergyLossProcess::SetTwoPeaksXS(std::vector<G4TwoPeaksXS*>* ptr)
1326{
1327 fXSpeaks = ptr;
1328}
1329
1330//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1331
1333{
1334 return (nullptr != currentModel)
1335 ? currentModel->GetCurrentElement(currentMaterial) : nullptr;
1336}
1337
1338//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1339
1341 G4bool flag)
1342{
1343 if(f > 0.0) {
1344 biasFactor = f;
1345 weightFlag = flag;
1346 if(1 < verboseLevel) {
1347 G4cout << "### SetCrossSectionBiasingFactor: for "
1348 << " process " << GetProcessName()
1349 << " biasFactor= " << f << " weightFlag= " << flag
1350 << G4endl;
1351 }
1352 }
1353}
1354
1355//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1356
1358 const G4String& region,
1359 G4bool flag)
1360{
1361 if(nullptr == biasManager) { biasManager = new G4EmBiasingManager(); }
1362 if(1 < verboseLevel) {
1363 G4cout << "### ActivateForcedInteraction: for "
1364 << " process " << GetProcessName()
1365 << " length(mm)= " << length/mm
1366 << " in G4Region <" << region
1367 << "> weightFlag= " << flag
1368 << G4endl;
1369 }
1370 weightFlag = flag;
1371 biasManager->ActivateForcedInteraction(length, region);
1372}
1373
1374//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1375
1376void
1378 G4double factor,
1379 G4double energyLimit)
1380{
1381 if (0.0 <= factor) {
1382 // Range cut can be applied only for e-
1383 if(0.0 == factor && secondaryParticle != G4Electron::Electron())
1384 { return; }
1385
1386 if(nullptr == biasManager) { biasManager = new G4EmBiasingManager(); }
1387 biasManager->ActivateSecondaryBiasing(region, factor, energyLimit);
1388 if(1 < verboseLevel) {
1389 G4cout << "### ActivateSecondaryBiasing: for "
1390 << " process " << GetProcessName()
1391 << " factor= " << factor
1392 << " in G4Region <" << region
1393 << "> energyLimit(MeV)= " << energyLimit/MeV
1394 << G4endl;
1395 }
1396 }
1397}
1398
1399//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1400
1402{
1403 isIonisation = val;
1404 aGPILSelection = (val) ? CandidateForSelection : NotCandidateForSelection;
1405}
1406
1407//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1408
1410{
1411 if(0.0 < val && val < 1.0) {
1412 linLossLimit = val;
1413 actLinLossLimit = true;
1414 } else { PrintWarning("SetLinearLossLimit", val); }
1415}
1416
1417//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1418
1420{
1421 if(0.0 < v1 && 0.0 < v2) {
1422 dRoverRange = std::min(1.0, v1);
1423 finalRange = std::min(v2, 1.e+50);
1424 } else {
1425 PrintWarning("SetStepFunctionV1", v1);
1426 PrintWarning("SetStepFunctionV2", v2);
1427 }
1428}
1429
1430//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1431
1433{
1434 if(1.e-18 < val && val < 1.e+50) { lowestKinEnergy = val; }
1435 else { PrintWarning("SetLowestEnergyLimit", val); }
1436}
1437
1438//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1439
1441{
1442 if(2 < n && n < 1000000000) {
1443 nBins = n;
1444 actBinning = true;
1445 } else {
1446 G4double e = (G4double)n;
1447 PrintWarning("SetDEDXBinning", e);
1448 }
1449}
1450
1451//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1452
1454{
1455 if(1.e-18 < e && e < maxKinEnergy) {
1456 minKinEnergy = e;
1457 actMinKinEnergy = true;
1458 } else { PrintWarning("SetMinKinEnergy", e); }
1459}
1460
1461//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1462
1464{
1465 if(minKinEnergy < e && e < 1.e+50) {
1466 maxKinEnergy = e;
1467 actMaxKinEnergy = true;
1468 if(e < maxKinEnergyCSDA) { maxKinEnergyCSDA = e; }
1469 } else { PrintWarning("SetMaxKinEnergy", e); }
1470}
1471
1472//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1473
1474void G4VEnergyLossProcess::PrintWarning(const G4String& tit, G4double val) const
1475{
1476 G4String ss = "G4VEnergyLossProcess::" + tit;
1478 ed << "Parameter is out of range: " << val
1479 << " it will have no effect!\n" << " Process "
1480 << GetProcessName() << " nbins= " << nBins
1481 << " Emin(keV)= " << minKinEnergy/keV
1482 << " Emax(GeV)= " << maxKinEnergy/GeV;
1483 G4Exception(ss, "em0044", JustWarning, ed);
1484}
1485
1486//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1487
1488void G4VEnergyLossProcess::ProcessDescription(std::ostream& out) const
1489{
1490 if(nullptr != particle) { StreamInfo(out, *particle, true); }
1491}
1492
1493//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4EmTableType
@ fTotal
@ fRestricted
@ fIsIonisation
@ fEmOnePeak
@ fEmNoIntegral
@ fEmTwoPeaks
@ fEmIncreasing
G4double condition(const G4ErrorSymMatrix &m)
@ JustWarning
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:59
std::ostringstream G4ExceptionDescription
Definition: G4Exception.hh:40
G4ForceCondition
@ NotForced
G4GPILSelection
@ CandidateForSelection
@ NotCandidateForSelection
G4double G4Log(G4double x)
Definition: G4Log.hh:227
G4ProcessType
#define G4BestUnit(a, b)
@ fAlive
@ fStopAndKill
@ fStopButAlive
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
#define G4UniformRand()
Definition: Randomize.hh:52
G4double GetLogKineticEnergy() const
G4double GetKineticEnergy() const
static G4Electron * Electron()
Definition: G4Electron.cc:93
G4bool ForcedInteractionRegion(G4int coupleIdx)
G4double ApplySecondaryBiasing(std::vector< G4DynamicParticle * > &, const G4Track &track, G4VEmModel *currentModel, G4ParticleChangeForGamma *pParticleChange, G4double &eloss, G4int coupleIdx, G4double tcut, G4double safety=0.0)
void ActivateSecondaryBiasing(const G4String &region, G4double factor, G4double energyLimit)
void Initialise(const G4ParticleDefinition &part, const G4String &procName, G4int verbose)
G4double GetWeight(G4int i)
void ActivateForcedInteraction(G4double length=0.0, const G4String &r="")
G4bool SecondaryBiasingRegion(G4int coupleIdx)
G4double GetStepLimit(G4int coupleIdx, G4double previousStep)
void CleanTable(size_t idx)
G4PhysicsTable * MakeTable(size_t idx)
void UpdateTable(G4PhysicsTable *, size_t idx)
G4PhysicsTable * Table(size_t idx) const
void AddEmModel(G4int, G4VEmModel *, G4VEmFluctuationModel *fm, const G4Region *r)
const G4DataVector * Initialise(const G4ParticleDefinition *part, const G4ParticleDefinition *secPart, G4int verb)
void DumpModelList(std::ostream &out, G4int verb)
G4int NumberOfModels() const
G4VEmModel * GetModel(G4int idx, G4bool ver=false) const
G4bool IsPrintLocked() const
void DefineRegParamForLoss(G4VEnergyLossProcess *) const
void FillStepFunction(const G4ParticleDefinition *, G4VEnergyLossProcess *) const
static G4EmParameters * Instance()
G4int NumberOfBins() const
G4double MinKinEnergy() const
G4int NumberOfBinsPerDecade() const
G4bool BuildCSDARange() const
G4bool LossFluctuation() const
G4bool UseCutAsFinalRange() const
G4int Verbose() const
G4int WorkerVerbose() const
G4double MaxKinEnergy() const
G4bool Integral() const
G4double MaxEnergyForCSDARange() const
G4bool UseAngularGeneratorForIonisation() const
G4double LinearLossLimit() const
G4double LowestMuHadEnergy() const
G4double LambdaFactor() const
G4double LowestElectronEnergy() const
static G4bool RetrieveTable(G4VProcess *ptr, const G4ParticleDefinition *part, G4PhysicsTable *aTable, const G4String &dir, const G4String &tname, const G4int verb, const G4bool ascii, const G4bool spline)
static void UpdateModels(G4VEnergyLossProcess *proc, G4EmModelManager *modelManager, const G4double maxKinEnergy, const G4int nModels, G4int &secID, G4int &biasID, G4int &mainSecondaries, const G4bool baseMat, const G4bool isMaster, const G4bool useAGen)
static void BuildLocalElossProcess(G4VEnergyLossProcess *proc, const G4VEnergyLossProcess *masterProc, const G4ParticleDefinition *part, const G4int nModels)
static G4bool StoreTable(G4VProcess *, const G4ParticleDefinition *, G4PhysicsTable *, const G4String &dir, const G4String &tname, G4int verb, G4bool ascii)
static void BuildDEDXTable(G4VEnergyLossProcess *proc, const G4ParticleDefinition *part, G4EmModelManager *modelManager, G4LossTableBuilder *bld, G4PhysicsTable *table, const G4double minKinEnergy, const G4double maxKinEnergy, const G4int nbins, const G4int verbose, const G4EmTableType tType, const G4bool splineFlag)
static const G4ParticleDefinition * CheckIon(G4VEnergyLossProcess *proc, const G4ParticleDefinition *part, const G4ParticleDefinition *particle, const G4int verboseLevel, G4bool &isIon)
static void BuildLambdaTable(G4VEmProcess *proc, const G4ParticleDefinition *part, G4EmModelManager *modelManager, G4LossTableBuilder *bld, G4PhysicsTable *theLambdaTable, G4PhysicsTable *theLambdaTablePrim, const G4double minKinEnergy, const G4double minKinEnergyPrim, const G4double maxKinEnergy, const G4double scale, const G4int verbose, const G4bool startFromNull, const G4bool splineFlag)
static std::vector< G4TwoPeaksXS * > * FillPeaksStructure(G4PhysicsTable *, G4LossTableBuilder *)
Definition: G4EmUtility.cc:211
static std::vector< G4double > * FindCrossSectionMax(G4PhysicsTable *)
Definition: G4EmUtility.cc:104
G4Region * GetRegion() const
const std::vector< G4double > * GetDensityFactors() const
const std::vector< G4int > * GetCoupleIndexes() const
void InitialiseBaseMaterials(const G4PhysicsTable *table=nullptr)
static G4LossTableManager * Instance()
void LocalPhysicsTables(const G4ParticleDefinition *aParticle, G4VEnergyLossProcess *p)
G4LossTableBuilder * GetTableBuilder()
void PreparePhysicsTable(const G4ParticleDefinition *aParticle, G4VEnergyLossProcess *p, G4bool theMaster)
void BuildPhysicsTable(const G4ParticleDefinition *aParticle)
G4VSubCutProducer * SubCutProducer()
void DeRegister(G4VEnergyLossProcess *p)
void Register(G4VEnergyLossProcess *p)
G4VAtomDeexcitation * AtomDeexcitation()
void RegisterExtraParticle(const G4ParticleDefinition *aParticle, G4VEnergyLossProcess *p)
G4ProductionCuts * GetProductionCuts() const
const G4String & GetName() const
Definition: G4Material.hh:172
void InitializeForPostStep(const G4Track &)
void InitializeForAlongStep(const G4Track &)
G4double GetProposedKineticEnergy() const
void SetProposedKineticEnergy(G4double proposedKinEnergy)
void SetProposedCharge(G4double theCharge)
G4ProcessManager * GetProcessManager() const
G4double GetPDGCharge() const
const G4String & GetParticleName() const
G4ProcessVector * GetAtRestProcessVector(G4ProcessVectorTypeIndex typ=typeGPIL) const
std::size_t size() const
G4double GetProductionCut(G4int index) const
const G4String & GetName() const
void InitialiseHelper()
G4double GetSafety() const
Definition: G4Step.hh:62
G4double GetStepLength() const
G4StepPoint * GetPostStepPoint() const
const G4ParticleDefinition * GetParticleDefinition() const
G4VPhysicalVolume * GetVolume() const
void SetWeight(G4double aValue)
const G4ThreeVector & GetPosition() const
void SetTouchableHandle(const G4TouchableHandle &apValue)
G4double GetGlobalTime() const
G4Material * GetMaterial() const
G4ParticleDefinition * GetDefinition() const
const G4DynamicParticle * GetDynamicParticle() const
const G4TouchableHandle & GetTouchableHandle() const
G4double GetKineticEnergy() const
void SetCreatorModelID(const G4int id)
G4int GetParentID() const
const G4MaterialCutsCouple * GetMaterialCutsCouple() const
static G4TransportationManager * GetTransportationManager()
G4SafetyHelper * GetSafetyHelper() const
void AlongStepDeexcitation(std::vector< G4Track * > &tracks, const G4Step &step, G4double &eLoss, G4int coupleIndex)
virtual G4double Dispersion(const G4Material *, const G4DynamicParticle *, const G4double tcut, const G4double tmax, const G4double length)=0
virtual void SetParticleAndCharge(const G4ParticleDefinition *, G4double q2)
virtual G4double SampleFluctuations(const G4MaterialCutsCouple *, const G4DynamicParticle *, const G4double tcut, const G4double tmax, const G4double length, const G4double meanLoss)=0
virtual void FillNumberOfSecondaries(G4int &numberOfTriplets, G4int &numberOfRecoil)
Definition: G4VEmModel.cc:308
G4VEmFluctuationModel * GetModelOfFluctuations()
Definition: G4VEmModel.hh:593
virtual G4double GetParticleCharge(const G4ParticleDefinition *, const G4Material *, G4double kineticEnergy)
Definition: G4VEmModel.cc:334
virtual G4double CrossSectionPerVolume(const G4Material *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy=0.0, G4double maxEnergy=DBL_MAX)
Definition: G4VEmModel.cc:181
void SetParticleChange(G4VParticleChange *, G4VEmFluctuationModel *f=nullptr)
Definition: G4VEmModel.cc:390
G4bool IsActive(G4double kinEnergy) const
Definition: G4VEmModel.hh:774
virtual void CorrectionsAlongStep(const G4MaterialCutsCouple *, const G4DynamicParticle *, const G4double &length, G4double &eloss)
Definition: G4VEmModel.cc:342
virtual void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin=0.0, G4double tmax=DBL_MAX)=0
const G4Element * GetCurrentElement(const G4Material *mat=nullptr) const
Definition: G4VEmModel.cc:242
G4double MaxSecondaryKinEnergy(const G4DynamicParticle *dynParticle)
Definition: G4VEmModel.hh:501
virtual G4double ChargeSquareRatio(const G4Track &)
Definition: G4VEmModel.cc:317
void AddEmModel(G4int, G4VEmModel *, G4VEmFluctuationModel *fluc=nullptr, const G4Region *region=nullptr)
G4double GetContinuousStepLimit(const G4Track &track, G4double previousStepSize, G4double currentMinimumStep, G4double &currentSafety) override
void SetMaxKinEnergy(G4double e)
G4ParticleChangeForLoss fParticleChange
void PreparePhysicsTable(const G4ParticleDefinition &) override
G4double MeanFreePath(const G4Track &track)
virtual void InitialiseEnergyLossProcess(const G4ParticleDefinition *, const G4ParticleDefinition *)=0
void SelectModel(G4double kinEnergy)
void SetRangeTableForLoss(G4PhysicsTable *p)
G4PhysicsVector * LambdaPhysicsVector(const G4MaterialCutsCouple *, G4double cut)
void ProcessDescription(std::ostream &outFile) const override
G4PhysicsTable * BuildDEDXTable(G4EmTableType tType=fRestricted)
void SetTwoPeaksXS(std::vector< G4TwoPeaksXS * > *)
const G4MaterialCutsCouple * currentCouple
virtual G4double MinPrimaryEnergy(const G4ParticleDefinition *, const G4Material *, G4double cut)
void ActivateSecondaryBiasing(const G4String &region, G4double factor, G4double energyLimit)
G4double PostStepGetPhysicalInteractionLength(const G4Track &track, G4double previousStepSize, G4ForceCondition *condition) override
const G4Element * GetCurrentElement() const
void SetDEDXBinning(G4int nbins)
void SetStepFunction(G4double v1, G4double v2)
void SetEmModel(G4VEmModel *, G4int index=0)
void SetCrossSectionBiasingFactor(G4double f, G4bool flag=true)
const G4Material * currentMaterial
G4double GetMeanFreePath(const G4Track &track, G4double previousStepSize, G4ForceCondition *condition) override
G4double ContinuousStepLimit(const G4Track &track, G4double previousStepSize, G4double currentMinimumStep, G4double &currentSafety)
void SetInverseRangeTable(G4PhysicsTable *p)
G4bool RetrievePhysicsTable(const G4ParticleDefinition *, const G4String &directory, G4bool ascii) override
void ActivateForcedInteraction(G4double length, const G4String &region, G4bool flag=true)
void SetDynamicMassCharge(G4double massratio, G4double charge2ratio)
void SetEnergyOfCrossSectionMax(std::vector< G4double > *)
G4double CrossSectionPerVolume(G4double kineticEnergy, const G4MaterialCutsCouple *couple)
void SetDEDXTable(G4PhysicsTable *p, G4EmTableType tType)
G4PhysicsTable * BuildLambdaTable(G4EmTableType tType=fRestricted)
G4bool StorePhysicsTable(const G4ParticleDefinition *, const G4String &directory, G4bool ascii=false) override
void SetIonisation(G4bool val)
G4double AlongStepGetPhysicalInteractionLength(const G4Track &, G4double previousStepSize, G4double currentMinimumStep, G4double &currentSafety, G4GPILSelection *selection) override
void SetLinearLossLimit(G4double val)
void SetLowestEnergyLimit(G4double)
void SetLambdaTable(G4PhysicsTable *p)
void BuildPhysicsTable(const G4ParticleDefinition &) override
G4VEnergyLossProcess(const G4String &name="EnergyLoss", G4ProcessType type=fElectromagnetic)
G4VParticleChange * AlongStepDoIt(const G4Track &, const G4Step &) override
G4double GetDEDXDispersion(const G4MaterialCutsCouple *couple, const G4DynamicParticle *dp, G4double length)
void ActivateSubCutoff(const G4Region *region)
void SetCSDARangeTable(G4PhysicsTable *pRange)
virtual void StreamProcessInfo(std::ostream &) const
G4VParticleChange * PostStepDoIt(const G4Track &, const G4Step &) override
void StartTracking(G4Track *) override
void SetMinKinEnergy(G4double e)
G4double GetParentWeight() const
void ProposeTrackStatus(G4TrackStatus status)
void SetSecondaryWeightByProcess(G4bool)
void ProposeWeight(G4double finalWeight)
G4double GetLocalEnergyDeposit() const
void AddSecondary(G4Track *aSecondary)
void ProposeLocalEnergyDeposit(G4double anEnergyPart)
void SetNumberOfSecondaries(G4int totSecondaries)
G4TrackStatus GetTrackStatus() const
G4LogicalVolume * GetLogicalVolume() const
G4double currentInteractionLength
Definition: G4VProcess.hh:339
G4double theInitialNumberOfInteractionLength
Definition: G4VProcess.hh:342
void SetVerboseLevel(G4int value)
Definition: G4VProcess.hh:416
const G4VProcess * GetMasterProcess() const
Definition: G4VProcess.hh:522
G4int verboseLevel
Definition: G4VProcess.hh:360
G4double theNumberOfInteractionLengthLeft
Definition: G4VProcess.hh:335
G4VParticleChange * pParticleChange
Definition: G4VProcess.hh:325
G4int GetProcessSubType() const
Definition: G4VProcess.hh:404
const G4String & GetProcessName() const
Definition: G4VProcess.hh:386
virtual void SampleSecondaries(const G4Step &step, std::vector< G4Track * > &tracks, G4double &eloss, G4double cut) const =0
G4double e1peak
G4double e3peak
G4double e2deep
G4double e1deep
G4double e2peak
int G4lrint(double ad)
Definition: templates.hh:134
#define DBL_MAX
Definition: templates.hh:62