Geant4 11.2.2
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 " << GetProcessName() << " and "
214 << part.GetParticleName() << " isIon=" << isIon
215 << " spline=" << spline << G4endl;
216 }
217 return;
218 }
219
220 tablesAreBuilt = false;
221
222 G4LossTableBuilder* bld = lManager->GetTableBuilder();
223 lManager->PreparePhysicsTable(&part, this);
224
225 // Base particle and set of models can be defined here
226 InitialiseEnergyLossProcess(particle, baseParticle);
227
228 // parameters of the process
229 if(!actLossFluc) { lossFluctuationFlag = theParameters->LossFluctuation(); }
230 useCutAsFinalRange = theParameters->UseCutAsFinalRange();
231 if(!actMinKinEnergy) { minKinEnergy = theParameters->MinKinEnergy(); }
232 if(!actMaxKinEnergy) { maxKinEnergy = theParameters->MaxKinEnergy(); }
233 if(!actBinning) { nBins = theParameters->NumberOfBins(); }
234 maxKinEnergyCSDA = theParameters->MaxEnergyForCSDARange();
235 nBinsCSDA = theParameters->NumberOfBinsPerDecade()
236 *G4lrint(std::log10(maxKinEnergyCSDA/minKinEnergy));
237 if(!actLinLossLimit) { linLossLimit = theParameters->LinearLossLimit(); }
238 lambdaFactor = theParameters->LambdaFactor();
239 invLambdaFactor = 1.0/lambdaFactor;
240 if(isMaster) { SetVerboseLevel(theParameters->Verbose()); }
241 else { SetVerboseLevel(theParameters->WorkerVerbose()); }
242 // integral option may be disabled
243 if(!theParameters->Integral()) { fXSType = fEmNoIntegral; }
244
245 theParameters->DefineRegParamForLoss(this);
246
247 fRangeEnergy = 0.0;
248
249 G4double initialCharge = particle->GetPDGCharge();
250 G4double initialMass = particle->GetPDGMass();
251
252 theParameters->FillStepFunction(particle, this);
253
254 // parameters for scaling from the base particle
255 if (nullptr != baseParticle) {
256 massRatio = (baseParticle->GetPDGMass())/initialMass;
257 logMassRatio = G4Log(massRatio);
258 G4double q = initialCharge/baseParticle->GetPDGCharge();
259 chargeSqRatio = q*q;
260 if(chargeSqRatio > 0.0) { reduceFactor = 1.0/(chargeSqRatio*massRatio); }
261 }
262 lowestKinEnergy = (initialMass < CLHEP::MeV)
263 ? theParameters->LowestElectronEnergy()
264 : theParameters->LowestMuHadEnergy();
265
266 // Tables preparation
267 if (isMaster && nullptr == baseParticle) {
268 if(nullptr == theData) { theData = new G4EmDataHandler(7); }
269
270 if(nullptr != theDEDXTable && isIonisation) {
271 if(nullptr != theIonisationTable && theDEDXTable != theIonisationTable) {
272 theData->CleanTable(0);
273 theDEDXTable = theIonisationTable;
274 theIonisationTable = nullptr;
275 }
276 }
277
278 theDEDXTable = theData->MakeTable(theDEDXTable, 0);
279 bld->InitialiseBaseMaterials(theDEDXTable);
280 theData->UpdateTable(theIonisationTable, 1);
281
282 if (theParameters->BuildCSDARange()) {
283 theDEDXunRestrictedTable = theData->MakeTable(2);
284 if(isIonisation) { theCSDARangeTable = theData->MakeTable(3); }
285 }
286
287 theLambdaTable = theData->MakeTable(4);
288 if(isIonisation) {
289 theRangeTableForLoss = theData->MakeTable(5);
290 theInverseRangeTable = theData->MakeTable(6);
291 }
292 }
293
294 // forced biasing
295 if(nullptr != biasManager) {
296 biasManager->Initialise(part,GetProcessName(),verboseLevel);
297 biasFlag = false;
298 }
299 baseMat = bld->GetBaseMaterialFlag();
300 numberOfModels = modelManager->NumberOfModels();
301 currentModel = modelManager->GetModel(0);
302 G4EmTableUtil::UpdateModels(this, modelManager, maxKinEnergy,
303 numberOfModels, secID, biasID,
304 mainSecondaries, baseMat, isMaster,
305 theParameters->UseAngularGeneratorForIonisation());
306 theCuts = modelManager->Initialise(particle, secondaryParticle,
308 // subcut processor
309 if(isIonisation) {
310 subcutProducer = lManager->SubCutProducer();
311 }
312 if(1 == nSCoffRegions) {
313 if((*scoffRegions)[0]->GetName() == "DefaultRegionForTheWorld") {
314 delete scoffRegions;
315 scoffRegions = nullptr;
316 nSCoffRegions = 0;
317 }
318 }
319
320 if(1 < verboseLevel) {
321 G4cout << "G4VEnergyLossProcess::PrepearPhysicsTable() is done "
322 << " for " << GetProcessName() << " and " << particle->GetParticleName()
323 << " isIon= " << isIon << " spline=" << spline;
324 if(baseParticle) {
325 G4cout << "; base: " << baseParticle->GetParticleName();
326 }
327 G4cout << G4endl;
328 G4cout << " chargeSqRatio= " << chargeSqRatio
329 << " massRatio= " << massRatio
330 << " reduceFactor= " << reduceFactor << G4endl;
331 if (nSCoffRegions > 0) {
332 G4cout << " SubCut secondary production is ON for regions: " << G4endl;
333 for (G4int i=0; i<nSCoffRegions; ++i) {
334 const G4Region* r = (*scoffRegions)[i];
335 G4cout << " " << r->GetName() << G4endl;
336 }
337 } else if(nullptr != subcutProducer) {
338 G4cout << " SubCut secondary production is ON for all regions" << G4endl;
339 }
340 }
341}
342
343//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
344
346{
347 if(1 < verboseLevel) {
348 G4cout << "### G4VEnergyLossProcess::BuildPhysicsTable() for "
349 << GetProcessName()
350 << " and particle " << part.GetParticleName()
351 << "; the first particle " << particle->GetParticleName();
352 if(baseParticle) {
353 G4cout << "; base: " << baseParticle->GetParticleName();
354 }
355 G4cout << G4endl;
356 G4cout << " TablesAreBuilt= " << tablesAreBuilt << " isIon= " << isIon
357 << " spline=" << spline << " ptr: " << this << G4endl;
358 }
359
360 if(&part == particle) {
361 if(isMaster) {
362 lManager->BuildPhysicsTable(particle, this);
363
364 } else {
365 const auto masterProcess =
366 static_cast<const G4VEnergyLossProcess*>(GetMasterProcess());
367
368 numberOfModels = modelManager->NumberOfModels();
369 G4EmTableUtil::BuildLocalElossProcess(this, masterProcess,
370 particle, numberOfModels);
371 tablesAreBuilt = true;
372 baseMat = masterProcess->UseBaseMaterial();
373 lManager->LocalPhysicsTables(particle, this);
374 }
375
376 // needs to be done only once
377 safetyHelper->InitialiseHelper();
378 }
379 // Added tracking cut to avoid tracking artifacts
380 // and identified deexcitation flag
381 if(isIonisation) {
382 atomDeexcitation = lManager->AtomDeexcitation();
383 if(nullptr != atomDeexcitation) {
384 if(atomDeexcitation->IsPIXEActive()) { useDeexcitation = true; }
385 }
386 }
387
388 // protection against double printout
389 if(theParameters->IsPrintLocked()) { return; }
390
391 // explicitly defined printout by particle name
392 G4String num = part.GetParticleName();
393 if(1 < verboseLevel ||
394 (0 < verboseLevel && (num == "e-" ||
395 num == "e+" || num == "mu+" ||
396 num == "mu-" || num == "proton"||
397 num == "pi+" || num == "pi-" ||
398 num == "kaon+" || num == "kaon-" ||
399 num == "alpha" || num == "anti_proton" ||
400 num == "GenericIon"|| num == "alpha+" ))) {
401 StreamInfo(G4cout, part);
402 }
403 if(1 < verboseLevel) {
404 G4cout << "### G4VEnergyLossProcess::BuildPhysicsTable() done for "
405 << GetProcessName()
406 << " and particle " << part.GetParticleName();
407 if(isIonisation) { G4cout << " isIonisation flag=1"; }
408 G4cout << " baseMat=" << baseMat << G4endl;
409 }
410}
411
412//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
413
415{
416 G4PhysicsTable* table = nullptr;
417 G4double emax = maxKinEnergy;
418 G4int bin = nBins;
419
420 if(fTotal == tType) {
421 emax = maxKinEnergyCSDA;
422 bin = nBinsCSDA;
423 table = theDEDXunRestrictedTable;
424 } else if(fRestricted == tType) {
425 table = theDEDXTable;
426 } else {
427 G4cout << "G4VEnergyLossProcess::BuildDEDXTable WARNING: wrong type "
428 << tType << G4endl;
429 }
430 if(1 < verboseLevel) {
431 G4cout << "G4VEnergyLossProcess::BuildDEDXTable() of type " << tType
432 << " for " << GetProcessName()
433 << " and " << particle->GetParticleName()
434 << "spline=" << spline << G4endl;
435 }
436 if(nullptr == table) { return table; }
437
438 G4LossTableBuilder* bld = lManager->GetTableBuilder();
439 G4EmTableUtil::BuildDEDXTable(this, particle, modelManager, bld,
440 table, minKinEnergy, emax, bin,
441 verboseLevel, tType, spline);
442 return table;
443}
444
445//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
446
448{
449 if(nullptr == theLambdaTable) { return theLambdaTable; }
450
451 G4double scale = theParameters->MaxKinEnergy()/theParameters->MinKinEnergy();
452 G4int nbin =
453 theParameters->NumberOfBinsPerDecade()*G4lrint(std::log10(scale));
454 scale = nbin/G4Log(scale);
455
456 G4LossTableBuilder* bld = lManager->GetTableBuilder();
457 G4EmTableUtil::BuildLambdaTable(this, particle, modelManager,
458 bld, theLambdaTable, theCuts,
459 minKinEnergy, maxKinEnergy, scale,
460 verboseLevel, spline);
461 return theLambdaTable;
462}
463
464//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
465
466void G4VEnergyLossProcess::StreamInfo(std::ostream& out,
467 const G4ParticleDefinition& part, G4bool rst) const
468{
469 G4String indent = (rst ? " " : "");
470 out << std::setprecision(6);
471 out << G4endl << indent << GetProcessName() << ": ";
472 if (!rst) out << " for " << part.GetParticleName();
473 out << " XStype:" << fXSType
474 << " SubType=" << GetProcessSubType() << G4endl
475 << " dE/dx and range tables from "
476 << G4BestUnit(minKinEnergy,"Energy")
477 << " to " << G4BestUnit(maxKinEnergy,"Energy")
478 << " in " << nBins << " bins" << G4endl
479 << " Lambda tables from threshold to "
480 << G4BestUnit(maxKinEnergy,"Energy")
481 << ", " << theParameters->NumberOfBinsPerDecade()
482 << " bins/decade, spline: " << spline
483 << G4endl;
484 if(nullptr != theRangeTableForLoss && isIonisation) {
485 out << " StepFunction=(" << dRoverRange << ", "
486 << finalRange/mm << " mm)"
487 << ", integ: " << fXSType
488 << ", fluct: " << lossFluctuationFlag
489 << ", linLossLim= " << linLossLimit
490 << G4endl;
491 }
493 modelManager->DumpModelList(out, verboseLevel);
494 if(nullptr != theCSDARangeTable && isIonisation) {
495 out << " CSDA range table up"
496 << " to " << G4BestUnit(maxKinEnergyCSDA,"Energy")
497 << " in " << nBinsCSDA << " bins" << G4endl;
498 }
499 if(nSCoffRegions>0 && isIonisation) {
500 out << " Subcutoff sampling in " << nSCoffRegions
501 << " regions" << G4endl;
502 }
503 if(2 < verboseLevel) {
504 for(std::size_t i=0; i<7; ++i) {
505 auto ta = theData->Table(i);
506 out << " " << tnames[i] << " address: " << ta << G4endl;
507 if(nullptr != ta) { out << *ta << G4endl; }
508 }
509 }
510}
511
512//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
513
515{
516 if(nullptr == scoffRegions) {
517 scoffRegions = new std::vector<const G4Region*>;
518 }
519 // the region is in the list
520 if(!scoffRegions->empty()) {
521 for (auto & reg : *scoffRegions) {
522 if (reg == r) { return; }
523 }
524 }
525 // new region
526 scoffRegions->push_back(r);
527 ++nSCoffRegions;
528}
529
530//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
531
532G4bool G4VEnergyLossProcess::IsRegionForCubcutProcessor(const G4Track& aTrack)
533{
534 if(0 == nSCoffRegions) { return true; }
535 const G4Region* r = aTrack.GetVolume()->GetLogicalVolume()->GetRegion();
536 for(auto & reg : *scoffRegions) {
537 if(r == reg) { return true; }
538 }
539 return false;
540}
541
542//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
543
545{
546 // reset parameters for the new track
549 preStepLambda = 0.0;
550 currentCouple = nullptr;
551
552 // reset ion
553 if(isIon) {
554 const G4double newmass = track->GetDefinition()->GetPDGMass();
555 massRatio = (nullptr == baseParticle) ? CLHEP::proton_mass_c2/newmass
556 : baseParticle->GetPDGMass()/newmass;
557 logMassRatio = G4Log(massRatio);
558 }
559 // forced biasing only for primary particles
560 if(nullptr != biasManager) {
561 if(0 == track->GetParentID()) {
562 biasFlag = true;
563 biasManager->ResetForcedInteraction();
564 }
565 }
566}
567
568//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
569
571 const G4Track& track, G4double, G4double, G4double&,
572 G4GPILSelection* selection)
573{
574 G4double x = DBL_MAX;
575 *selection = aGPILSelection;
576 if(isIonisation && currentModel->IsActive(preStepScaledEnergy)) {
577 GetScaledRangeForScaledEnergy(preStepScaledEnergy, LogScaledEkin(track));
578 x = (useCutAsFinalRange) ? std::min(finalRange,
580 x = (fRange > x) ? fRange*dRoverRange + x*(1.0 - dRoverRange)*(2.0 - x/fRange)
581 : fRange;
582 /*
583 G4cout<<"AlongStepGPIL: " << GetProcessName()<<": e="<<preStepKinEnergy
584 << " fRange=" << fRange << " finR=" << finR <<" stepLimit="<<x<<G4endl;
585 */
586 }
587 return x;
588}
589
590//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
591
593 const G4Track& track,
594 G4double previousStepSize,
596{
597 // condition is set to "Not Forced"
599 G4double x = DBL_MAX;
600
601 // initialisation of material, mass, charge, model
602 // at the beginning of the step
603 DefineMaterial(track.GetMaterialCutsCouple());
607
608 if(!currentModel->IsActive(preStepScaledEnergy)) {
611 preStepLambda = 0.0;
613 return x;
614 }
615
616 // change effective charge of a charged particle on fly
617 if(isIon) {
618 const G4double q2 = currentModel->ChargeSquareRatio(track);
619 fFactor = q2*biasFactor;
620 if(baseMat) { fFactor *= (*theDensityFactor)[currentCoupleIndex]; }
621 reduceFactor = 1.0/(fFactor*massRatio);
622 if (lossFluctuationFlag) {
623 auto fluc = currentModel->GetModelOfFluctuations();
624 fluc->SetParticleAndCharge(track.GetDefinition(), q2);
625 }
626 }
627
628 // forced biasing only for primary particles
629 if(biasManager) {
630 if(0 == track.GetParentID() && biasFlag &&
632 return biasManager->GetStepLimit((G4int)currentCoupleIndex, previousStepSize);
633 }
634 }
635
636 ComputeLambdaForScaledEnergy(preStepScaledEnergy, track);
637
638 // zero cross section
639 if(preStepLambda <= 0.0) {
642 } else {
643
644 // non-zero cross section
646
647 // beggining of tracking (or just after DoIt of this process)
650
651 } else if(currentInteractionLength < DBL_MAX) {
652
653 // subtract NumberOfInteractionLengthLeft using previous step
655 previousStepSize/currentInteractionLength;
656
659 }
660
661 // new mean free path and step limit
664 }
665#ifdef G4VERBOSE
666 if (verboseLevel>2) {
667 G4cout << "G4VEnergyLossProcess::PostStepGetPhysicalInteractionLength ";
668 G4cout << "[ " << GetProcessName() << "]" << G4endl;
669 G4cout << " for " << track.GetDefinition()->GetParticleName()
670 << " in Material " << currentMaterial->GetName()
671 << " Ekin(MeV)= " << preStepKinEnergy/MeV
672 << " track material: " << track.GetMaterial()->GetName()
673 <<G4endl;
674 G4cout << "MeanFreePath = " << currentInteractionLength/cm << "[cm]"
675 << "InteractionLength= " << x/cm <<"[cm] " <<G4endl;
676 }
677#endif
678 return x;
679}
680
681//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
682
683void
684G4VEnergyLossProcess::ComputeLambdaForScaledEnergy(G4double e, const G4Track& track)
685{
686 // cross section increased with energy
687 if(fXSType == fEmIncreasing) {
688 if(e*invLambdaFactor < mfpKinEnergy) {
689 preStepLambda = GetLambdaForScaledEnergy(e, LogScaledEkin(track));
690 mfpKinEnergy = (preStepLambda > 0.0) ? e : 0.0;
691 }
692
693 // cross section has one peak
694 } else if(fXSType == fEmOnePeak) {
695 const G4double epeak = (*theEnergyOfCrossSectionMax)[basedCoupleIndex];
696 if(e <= epeak) {
697 if(e*invLambdaFactor < mfpKinEnergy) {
698 preStepLambda = GetLambdaForScaledEnergy(e, LogScaledEkin(track));
699 mfpKinEnergy = (preStepLambda > 0.0) ? e : 0.0;
700 }
701 } else if(e < mfpKinEnergy) {
702 const G4double e1 = std::max(epeak, e*lambdaFactor);
703 mfpKinEnergy = e1;
704 preStepLambda = GetLambdaForScaledEnergy(e1);
705 }
706
707 // cross section has more than one peaks
708 } else if(fXSType == fEmTwoPeaks) {
709 G4TwoPeaksXS* xs = (*fXSpeaks)[basedCoupleIndex];
710 const G4double e1peak = xs->e1peak;
711
712 // below the 1st peak
713 if(e <= e1peak) {
714 if(e*invLambdaFactor < mfpKinEnergy) {
715 preStepLambda = GetLambdaForScaledEnergy(e, LogScaledEkin(track));
716 mfpKinEnergy = (preStepLambda > 0.0) ? e : 0.0;
717 }
718 return;
719 }
720 const G4double e1deep = xs->e1deep;
721 // above the 1st peak, below the deep
722 if(e <= e1deep) {
723 if(mfpKinEnergy >= e1deep || e <= mfpKinEnergy) {
724 const G4double e1 = std::max(e1peak, e*lambdaFactor);
725 mfpKinEnergy = e1;
726 preStepLambda = GetLambdaForScaledEnergy(e1);
727 }
728 return;
729 }
730 const G4double e2peak = xs->e2peak;
731 // above the deep, below 2nd peak
732 if(e <= e2peak) {
733 if(e*invLambdaFactor < mfpKinEnergy) {
734 mfpKinEnergy = e;
735 preStepLambda = GetLambdaForScaledEnergy(e, LogScaledEkin(track));
736 }
737 return;
738 }
739 const G4double e2deep = xs->e2deep;
740 // above the 2nd peak, below the deep
741 if(e <= e2deep) {
742 if(mfpKinEnergy >= e2deep || e <= mfpKinEnergy) {
743 const G4double e1 = std::max(e2peak, e*lambdaFactor);
744 mfpKinEnergy = e1;
745 preStepLambda = GetLambdaForScaledEnergy(e1);
746 }
747 return;
748 }
749 const G4double e3peak = xs->e3peak;
750 // above the deep, below 3d peak
751 if(e <= e3peak) {
752 if(e*invLambdaFactor < mfpKinEnergy) {
753 mfpKinEnergy = e;
754 preStepLambda = GetLambdaForScaledEnergy(e, LogScaledEkin(track));
755 }
756 return;
757 }
758 // above 3d peak
759 if(e <= mfpKinEnergy) {
760 const G4double e1 = std::max(e3peak, e*lambdaFactor);
761 mfpKinEnergy = e1;
762 preStepLambda = GetLambdaForScaledEnergy(e1);
763 }
764 // integral method is not used
765 } else {
766 preStepLambda = GetLambdaForScaledEnergy(e, LogScaledEkin(track));
767 }
768}
769
770//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
771
773 const G4Step& step)
774{
776 // The process has range table - calculate energy loss
777 if(!isIonisation || !currentModel->IsActive(preStepScaledEnergy)) {
778 return &fParticleChange;
779 }
780
781 G4double length = step.GetStepLength();
782 G4double eloss = 0.0;
783
784 /*
785 if(-1 < verboseLevel) {
786 const G4ParticleDefinition* d = track.GetParticleDefinition();
787 G4cout << "AlongStepDoIt for "
788 << GetProcessName() << " and particle " << d->GetParticleName()
789 << " eScaled(MeV)=" << preStepScaledEnergy/MeV
790 << " range(mm)=" << fRange/mm << " s(mm)=" << length/mm
791 << " rf=" << reduceFactor << " q^2=" << chargeSqRatio
792 << " md=" << d->GetPDGMass() << " status=" << track.GetTrackStatus()
793 << " " << track.GetMaterial()->GetName() << G4endl;
794 }
795 */
796 const G4DynamicParticle* dynParticle = track.GetDynamicParticle();
797
798 // define new weight for primary and secondaries
800 if(weightFlag) {
801 weight /= biasFactor;
803 }
804
805 // stopping, check actual range and kinetic energy
806 if (length >= fRange || preStepKinEnergy <= lowestKinEnergy) {
807 eloss = preStepKinEnergy;
808 if (useDeexcitation) {
809 atomDeexcitation->AlongStepDeexcitation(scTracks, step,
810 eloss, (G4int)currentCoupleIndex);
811 if(scTracks.size() > 0) { FillSecondariesAlongStep(weight); }
812 eloss = std::max(eloss, 0.0);
813 }
816 return &fParticleChange;
817 }
818 // zero step length with non-zero range
819 if(length <= 0.0) { return &fParticleChange; }
820
821 // Short step
822 eloss = length*GetDEDXForScaledEnergy(preStepScaledEnergy,
823 LogScaledEkin(track));
824 /*
825 G4cout << "##### Short STEP: eloss= " << eloss
826 << " Escaled=" << preStepScaledEnergy
827 << " R=" << fRange
828 << " L=" << length
829 << " fFactor=" << fFactor << " minE=" << minKinEnergy
830 << " idxBase=" << basedCoupleIndex << G4endl;
831 */
832 // Long step
833 if(eloss > preStepKinEnergy*linLossLimit) {
834
835 const G4double x = (fRange - length)/reduceFactor;
836 const G4double de = preStepKinEnergy - ScaledKinEnergyForLoss(x)/massRatio;
837 if(de > 0.0) { eloss = de; }
838 /*
839 if(-1 < verboseLevel)
840 G4cout << " Long STEP: rPre(mm)="
841 << GetScaledRangeForScaledEnergy(preStepScaledEnergy)/mm
842 << " x(mm)=" << x/mm
843 << " eloss(MeV)=" << eloss/MeV
844 << " rFactor=" << reduceFactor
845 << " massRatio=" << massRatio
846 << G4endl;
847 */
848 }
849
850 /*
851 if(-1 < verboseLevel ) {
852 G4cout << "Before fluct: eloss(MeV)= " << eloss/MeV
853 << " e-eloss= " << preStepKinEnergy-eloss
854 << " step(mm)= " << length/mm << " range(mm)= " << fRange/mm
855 << " fluct= " << lossFluctuationFlag << G4endl;
856 }
857 */
858
859 const G4double cut = (*theCuts)[currentCoupleIndex];
860 G4double esec = 0.0;
861
862 // Corrections, which cannot be tabulated
863 if(isIon) {
864 currentModel->CorrectionsAlongStep(currentCouple, dynParticle,
865 length, eloss);
866 eloss = std::max(eloss, 0.0);
867 }
868
869 // Sample fluctuations if not full energy loss
870 if(eloss >= preStepKinEnergy) {
871 eloss = preStepKinEnergy;
872
873 } else if (lossFluctuationFlag) {
874 const G4double tmax = currentModel->MaxSecondaryKinEnergy(dynParticle);
875 const G4double tcut = std::min(cut, tmax);
876 G4VEmFluctuationModel* fluc = currentModel->GetModelOfFluctuations();
877 eloss = fluc->SampleFluctuations(currentCouple,dynParticle,
878 tcut, tmax, length, eloss);
879 /*
880 if(-1 < verboseLevel)
881 G4cout << "After fluct: eloss(MeV)= " << eloss/MeV
882 << " fluc= " << (eloss-eloss0)/MeV
883 << " ChargeSqRatio= " << chargeSqRatio
884 << " massRatio= " << massRatio << " tmax= " << tmax << G4endl;
885 */
886 }
887
888 // deexcitation
889 if (useDeexcitation) {
890 G4double esecfluo = preStepKinEnergy;
891 G4double de = esecfluo;
892 atomDeexcitation->AlongStepDeexcitation(scTracks, step,
894
895 // sum of de-excitation energies
896 esecfluo -= de;
897
898 // subtracted from energy loss
899 if(eloss >= esecfluo) {
900 esec += esecfluo;
901 eloss -= esecfluo;
902 } else {
903 esec += esecfluo;
904 eloss = 0.0;
905 }
906 }
907 if(nullptr != subcutProducer && IsRegionForCubcutProcessor(track)) {
908 subcutProducer->SampleSecondaries(step, scTracks, eloss, cut);
909 }
910 // secondaries from atomic de-excitation and subcut
911 if(!scTracks.empty()) { FillSecondariesAlongStep(weight); }
912
913 // Energy balance
914 G4double finalT = preStepKinEnergy - eloss - esec;
915 if (finalT <= lowestKinEnergy) {
916 eloss += finalT;
917 finalT = 0.0;
918 } else if(isIon) {
920 currentModel->GetParticleCharge(track.GetParticleDefinition(),
921 currentMaterial,finalT));
922 }
923 eloss = std::max(eloss, 0.0);
924
927 /*
928 if(-1 < verboseLevel) {
929 G4double del = finalT + eloss + esec - preStepKinEnergy;
930 G4cout << "Final value eloss(MeV)= " << eloss/MeV
931 << " preStepKinEnergy= " << preStepKinEnergy
932 << " postStepKinEnergy= " << finalT
933 << " de(keV)= " << del/keV
934 << " lossFlag= " << lossFluctuationFlag
935 << " status= " << track.GetTrackStatus()
936 << G4endl;
937 }
938 */
939 return &fParticleChange;
940}
941
942//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
943
944void G4VEnergyLossProcess::FillSecondariesAlongStep(G4double wt)
945{
946 const std::size_t n0 = scTracks.size();
947 G4double weight = wt;
948 // weight may be changed by biasing manager
949 if(biasManager) {
951 weight *=
952 biasManager->ApplySecondaryBiasing(scTracks, (G4int)currentCoupleIndex);
953 }
954 }
955
956 // fill secondaries
957 const std::size_t n = scTracks.size();
959
960 for(std::size_t i=0; i<n; ++i) {
961 G4Track* t = scTracks[i];
962 if(nullptr != t) {
963 t->SetWeight(weight);
965 if(i >= n0) { t->SetCreatorModelID(biasID); }
966 }
967 }
968 scTracks.clear();
969}
970
971//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
972
974 const G4Step& step)
975{
976 // clear number of interaction lengths in any case
979
981 const G4double finalT = track.GetKineticEnergy();
982
983 const G4double postStepScaledEnergy = finalT*massRatio;
984 SelectModel(postStepScaledEnergy);
985
986 if(!currentModel->IsActive(postStepScaledEnergy)) {
987 return &fParticleChange;
988 }
989 /*
990 if(1 < verboseLevel) {
991 G4cout<<GetProcessName()<<" PostStepDoIt: E(MeV)= "<< finalT/MeV<< G4endl;
992 }
993 */
994 // forced process - should happen only once per track
995 if(biasFlag) {
997 biasFlag = false;
998 }
999 }
1000 const G4DynamicParticle* dp = track.GetDynamicParticle();
1001
1002 // Integral approach
1003 if (fXSType != fEmNoIntegral) {
1004 const G4double logFinalT = dp->GetLogKineticEnergy();
1005 G4double lx = GetLambdaForScaledEnergy(postStepScaledEnergy,
1006 logFinalT + logMassRatio);
1007 lx = std::max(lx, 0.0);
1008
1009 // if both lg and lx are zero then no interaction
1010 if(preStepLambda*G4UniformRand() >= lx) {
1011 return &fParticleChange;
1012 }
1013 }
1014
1015 // define new weight for primary and secondaries
1017 if(weightFlag) {
1018 weight /= biasFactor;
1020 }
1021
1022 const G4double tcut = (*theCuts)[currentCoupleIndex];
1023
1024 // sample secondaries
1025 secParticles.clear();
1026 currentModel->SampleSecondaries(&secParticles, currentCouple, dp, tcut);
1027
1028 const G4int num0 = (G4int)secParticles.size();
1029
1030 // bremsstrahlung splitting or Russian roulette
1031 if(biasManager) {
1033 G4double eloss = 0.0;
1034 weight *= biasManager->ApplySecondaryBiasing(
1035 secParticles,
1036 track, currentModel,
1037 &fParticleChange, eloss,
1038 (G4int)currentCoupleIndex, tcut,
1039 step.GetPostStepPoint()->GetSafety());
1040 if(eloss > 0.0) {
1043 }
1044 }
1045 }
1046
1047 // save secondaries
1048 const G4int num = (G4int)secParticles.size();
1049 if(num > 0) {
1050
1052 G4double time = track.GetGlobalTime();
1053
1054 G4int n1(0), n2(0);
1055 if(num0 > mainSecondaries) {
1056 currentModel->FillNumberOfSecondaries(n1, n2);
1057 }
1058
1059 for (G4int i=0; i<num; ++i) {
1060 if(nullptr != secParticles[i]) {
1061 G4Track* t = new G4Track(secParticles[i], time, track.GetPosition());
1063 if (biasManager) {
1064 t->SetWeight(weight * biasManager->GetWeight(i));
1065 } else {
1066 t->SetWeight(weight);
1067 }
1068 if(i < num0) {
1069 t->SetCreatorModelID(secID);
1070 } else if(i < num0 + n1) {
1071 t->SetCreatorModelID(tripletID);
1072 } else {
1073 t->SetCreatorModelID(biasID);
1074 }
1075
1076 //G4cout << "Secondary(post step) has weight " << t->GetWeight()
1077 // << ", kenergy " << t->GetKineticEnergy()/MeV << " MeV"
1078 // << " time= " << time/ns << " ns " << G4endl;
1080 }
1081 }
1082 }
1083
1086 if(particle->GetProcessManager()->GetAtRestProcessVector()->size() > 0)
1089 }
1090
1091 /*
1092 if(-1 < verboseLevel) {
1093 G4cout << "::PostStepDoIt: Sample secondary; Efin= "
1094 << fParticleChange.GetProposedKineticEnergy()/MeV
1095 << " MeV; model= (" << currentModel->LowEnergyLimit()
1096 << ", " << currentModel->HighEnergyLimit() << ")"
1097 << " preStepLambda= " << preStepLambda
1098 << " dir= " << track.GetMomentumDirection()
1099 << " status= " << track.GetTrackStatus()
1100 << G4endl;
1101 }
1102 */
1103 return &fParticleChange;
1104}
1105
1106//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1107
1109 const G4ParticleDefinition* part, const G4String& dir, G4bool ascii)
1110{
1111 if (!isMaster || nullptr != baseParticle || part != particle ) return true;
1112 for(std::size_t i=0; i<7; ++i) {
1113 if(nullptr != theData->Table(i)) {
1114 if(1 < verboseLevel) {
1115 G4cout << "G4VEnergyLossProcess::StorePhysicsTable i=" << i
1116 << " " << particle->GetParticleName()
1117 << " " << GetProcessName()
1118 << " " << tnames[i] << " " << theData->Table(i) << G4endl;
1119 }
1120 if(!G4EmTableUtil::StoreTable(this, part, theData->Table(i),
1121 dir, tnames[i], verboseLevel, ascii)) {
1122 return false;
1123 }
1124 }
1125 }
1126 return true;
1127}
1128
1129//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
1130
1131G4bool
1133 const G4String& dir, G4bool ascii)
1134{
1135 if (!isMaster || nullptr != baseParticle || part != particle ) return true;
1136 for(std::size_t i=0; i<7; ++i) {
1137 if(!G4EmTableUtil::RetrieveTable(this, part, theData->Table(i), dir, tnames[i],
1138 verboseLevel, ascii, spline)) {
1139 return false;
1140 }
1141 }
1142 return true;
1143}
1144
1145//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1146
1148 const G4MaterialCutsCouple *couple,
1149 const G4DynamicParticle* dp,
1150 G4double length)
1151{
1152 DefineMaterial(couple);
1153 G4double ekin = dp->GetKineticEnergy();
1154 SelectModel(ekin*massRatio);
1155 G4double tmax = currentModel->MaxSecondaryKinEnergy(dp);
1156 G4double tcut = std::min(tmax,(*theCuts)[currentCoupleIndex]);
1157 G4double d = 0.0;
1158 G4VEmFluctuationModel* fm = currentModel->GetModelOfFluctuations();
1159 if(nullptr != fm) { d = fm->Dispersion(currentMaterial,dp,tcut,tmax,length); }
1160 return d;
1161}
1162
1163//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1164
1167 const G4MaterialCutsCouple* couple,
1168 G4double logKineticEnergy)
1169{
1170 // Cross section per volume is calculated
1171 DefineMaterial(couple);
1172 G4double cross = 0.0;
1173 if (nullptr != theLambdaTable) {
1174 cross = GetLambdaForScaledEnergy(kineticEnergy * massRatio,
1175 logKineticEnergy + logMassRatio);
1176 } else {
1177 SelectModel(kineticEnergy*massRatio);
1178 cross = (!baseMat) ? biasFactor : biasFactor*(*theDensityFactor)[currentCoupleIndex];
1179 cross *= (currentModel->CrossSectionPerVolume(currentMaterial, particle, kineticEnergy,
1180 (*theCuts)[currentCoupleIndex]));
1181 }
1182 return std::max(cross, 0.0);
1183}
1184
1185//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1186
1188{
1189 DefineMaterial(track.GetMaterialCutsCouple());
1190 const G4double kinEnergy = track.GetKineticEnergy();
1191 const G4double logKinEnergy = track.GetDynamicParticle()->GetLogKineticEnergy();
1192 const G4double cs = GetLambdaForScaledEnergy(kinEnergy * massRatio,
1193 logKinEnergy + logMassRatio);
1194 return (0.0 < cs) ? 1.0/cs : DBL_MAX;
1195}
1196
1197//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1198
1200 G4double x, G4double y,
1201 G4double& z)
1202{
1203 return AlongStepGetPhysicalInteractionLength(track, x, y, z, &aGPILSelection);
1204}
1205
1206//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1207
1209 const G4Track& track,
1210 G4double,
1212
1213{
1215 return MeanFreePath(track);
1216}
1217
1218//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1219
1226
1227//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1228
1231 G4double)
1232{
1233 DefineMaterial(couple);
1234 G4PhysicsVector* v = (*theLambdaTable)[basedCoupleIndex];
1235 return new G4PhysicsVector(*v);
1236}
1237
1238//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1239
1240void
1242{
1243 if(1 < verboseLevel) {
1244 G4cout << "### Set DEDX table " << p << " " << theDEDXTable
1245 << " " << theDEDXunRestrictedTable << " " << theIonisationTable
1246 << " for " << particle->GetParticleName()
1247 << " and process " << GetProcessName()
1248 << " type=" << tType << " isIonisation:" << isIonisation << G4endl;
1249 }
1250 if(fTotal == tType) {
1251 theDEDXunRestrictedTable = p;
1252 } else if(fRestricted == tType) {
1253 theDEDXTable = p;
1254 if(isMaster && nullptr == baseParticle) {
1255 theData->UpdateTable(theDEDXTable, 0);
1256 }
1257 } else if(fIsIonisation == tType) {
1258 theIonisationTable = p;
1259 if(isMaster && nullptr == baseParticle) {
1260 theData->UpdateTable(theIonisationTable, 1);
1261 }
1262 }
1263}
1264
1265//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1266
1268{
1269 theCSDARangeTable = p;
1270}
1271
1272//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1273
1275{
1276 theRangeTableForLoss = p;
1277}
1278
1279//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1280
1282{
1283 theInverseRangeTable = p;
1284}
1285
1286//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1287
1289{
1290 if(1 < verboseLevel) {
1291 G4cout << "### Set Lambda table " << p << " " << theLambdaTable
1292 << " for " << particle->GetParticleName()
1293 << " and process " << GetProcessName() << G4endl;
1294 }
1295 theLambdaTable = p;
1296 tablesAreBuilt = true;
1297
1298 if(isMaster && nullptr != p) {
1299 delete theEnergyOfCrossSectionMax;
1300 theEnergyOfCrossSectionMax = nullptr;
1301 if(fEmTwoPeaks == fXSType) {
1302 if(nullptr != fXSpeaks) {
1303 for(auto & ptr : *fXSpeaks) { delete ptr; }
1304 delete fXSpeaks;
1305 }
1306 G4LossTableBuilder* bld = lManager->GetTableBuilder();
1307 fXSpeaks = G4EmUtility::FillPeaksStructure(p, bld);
1308 if(nullptr == fXSpeaks) { fXSType = fEmOnePeak; }
1309 }
1310 if(fXSType == fEmOnePeak) {
1311 theEnergyOfCrossSectionMax = G4EmUtility::FindCrossSectionMax(p);
1312 if(nullptr == theEnergyOfCrossSectionMax) { fXSType = fEmIncreasing; }
1313 }
1314 }
1315}
1316
1317//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1318
1320{
1321 theEnergyOfCrossSectionMax = p;
1322}
1323
1324//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1325
1326void G4VEnergyLossProcess::SetTwoPeaksXS(std::vector<G4TwoPeaksXS*>* ptr)
1327{
1328 fXSpeaks = ptr;
1329}
1330
1331//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1332
1334{
1335 return (nullptr != currentModel)
1336 ? currentModel->GetCurrentElement(currentMaterial) : nullptr;
1337}
1338
1339//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1340
1342 G4bool flag)
1343{
1344 if(f > 0.0) {
1345 biasFactor = f;
1346 weightFlag = flag;
1347 if(1 < verboseLevel) {
1348 G4cout << "### SetCrossSectionBiasingFactor: for "
1349 << " process " << GetProcessName()
1350 << " biasFactor= " << f << " weightFlag= " << flag
1351 << G4endl;
1352 }
1353 }
1354}
1355
1356//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1357
1359 const G4String& region,
1360 G4bool flag)
1361{
1362 if(nullptr == biasManager) { biasManager = new G4EmBiasingManager(); }
1363 if(1 < verboseLevel) {
1364 G4cout << "### ActivateForcedInteraction: for "
1365 << " process " << GetProcessName()
1366 << " length(mm)= " << length/mm
1367 << " in G4Region <" << region
1368 << "> weightFlag= " << flag
1369 << G4endl;
1370 }
1371 weightFlag = flag;
1372 biasManager->ActivateForcedInteraction(length, region);
1373}
1374
1375//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1376
1377void
1379 G4double factor,
1380 G4double energyLimit)
1381{
1382 if (0.0 <= factor) {
1383 // Range cut can be applied only for e-
1384 if(0.0 == factor && secondaryParticle != G4Electron::Electron())
1385 { return; }
1386
1387 if(nullptr == biasManager) { biasManager = new G4EmBiasingManager(); }
1388 biasManager->ActivateSecondaryBiasing(region, factor, energyLimit);
1389 if(1 < verboseLevel) {
1390 G4cout << "### ActivateSecondaryBiasing: for "
1391 << " process " << GetProcessName()
1392 << " factor= " << factor
1393 << " in G4Region <" << region
1394 << "> energyLimit(MeV)= " << energyLimit/MeV
1395 << G4endl;
1396 }
1397 }
1398}
1399
1400//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1401
1403{
1404 isIonisation = val;
1405 aGPILSelection = (val) ? CandidateForSelection : NotCandidateForSelection;
1406}
1407
1408//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1409
1411{
1412 if(0.0 < val && val < 1.0) {
1413 linLossLimit = val;
1414 actLinLossLimit = true;
1415 } else { PrintWarning("SetLinearLossLimit", val); }
1416}
1417
1418//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1419
1421{
1422 if(0.0 < v1 && 0.0 < v2) {
1423 dRoverRange = std::min(1.0, v1);
1424 finalRange = std::min(v2, 1.e+50);
1425 } else {
1426 PrintWarning("SetStepFunctionV1", v1);
1427 PrintWarning("SetStepFunctionV2", v2);
1428 }
1429}
1430
1431//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1432
1434{
1435 if(1.e-18 < val && val < 1.e+50) { lowestKinEnergy = val; }
1436 else { PrintWarning("SetLowestEnergyLimit", val); }
1437}
1438
1439//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1440
1442{
1443 if(2 < n && n < 1000000000) {
1444 nBins = n;
1445 actBinning = true;
1446 } else {
1447 G4double e = (G4double)n;
1448 PrintWarning("SetDEDXBinning", e);
1449 }
1450}
1451
1452//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1453
1455{
1456 if(1.e-18 < e && e < maxKinEnergy) {
1457 minKinEnergy = e;
1458 actMinKinEnergy = true;
1459 } else { PrintWarning("SetMinKinEnergy", e); }
1460}
1461
1462//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1463
1465{
1466 if(minKinEnergy < e && e < 1.e+50) {
1467 maxKinEnergy = e;
1468 actMaxKinEnergy = true;
1469 if(e < maxKinEnergyCSDA) { maxKinEnergyCSDA = e; }
1470 } else { PrintWarning("SetMaxKinEnergy", e); }
1471}
1472
1473//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1474
1475void G4VEnergyLossProcess::PrintWarning(const G4String& tit, G4double val) const
1476{
1477 G4String ss = "G4VEnergyLossProcess::" + tit;
1479 ed << "Parameter is out of range: " << val
1480 << " it will have no effect!\n" << " Process "
1481 << GetProcessName() << " nbins= " << nBins
1482 << " Emin(keV)= " << minKinEnergy/keV
1483 << " Emax(GeV)= " << maxKinEnergy/GeV;
1484 G4Exception(ss, "em0044", JustWarning, ed);
1485}
1486
1487//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1488
1489void G4VEnergyLossProcess::ProcessDescription(std::ostream& out) const
1490{
1491 if(nullptr != particle) { StreamInfo(out, *particle, true); }
1492}
1493
1494//....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)
std::ostringstream G4ExceptionDescription
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:67
G4GLOB_DLL std::ostream G4cout
#define G4UniformRand()
Definition Randomize.hh:52
G4double GetLogKineticEnergy() const
G4double GetKineticEnergy() const
static G4Electron * Electron()
Definition G4Electron.cc:91
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 *)
static std::vector< G4double > * FindCrossSectionMax(G4PhysicsTable *)
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 BuildPhysicsTable(const G4ParticleDefinition *aParticle)
G4VSubCutProducer * SubCutProducer()
void DeRegister(G4VEnergyLossProcess *p)
void Register(G4VEnergyLossProcess *p)
G4VAtomDeexcitation * AtomDeexcitation()
void PreparePhysicsTable(const G4ParticleDefinition *aParticle, G4VEnergyLossProcess *p)
void RegisterExtraParticle(const G4ParticleDefinition *aParticle, G4VEnergyLossProcess *p)
G4ProductionCuts * GetProductionCuts() const
const G4String & GetName() const
void InitializeForPostStep(const G4Track &)
void InitializeForAlongStep(const G4Track &)
void SetProposedKineticEnergy(G4double proposedKinEnergy)
void SetProposedCharge(G4double theCharge)
G4ProcessManager * GetProcessManager() 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
G4double GetSafety() const
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)
G4VEmFluctuationModel * GetModelOfFluctuations()
virtual G4double GetParticleCharge(const G4ParticleDefinition *, const G4Material *, G4double kineticEnergy)
virtual G4double CrossSectionPerVolume(const G4Material *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy=0.0, G4double maxEnergy=DBL_MAX)
void SetParticleChange(G4VParticleChange *, G4VEmFluctuationModel *f=nullptr)
G4bool IsActive(G4double kinEnergy) const
virtual void CorrectionsAlongStep(const G4MaterialCutsCouple *, const G4DynamicParticle *, const G4double &length, G4double &eloss)
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
G4double MaxSecondaryKinEnergy(const G4DynamicParticle *dynParticle)
virtual G4double ChargeSquareRatio(const G4Track &)
void AddEmModel(G4int, G4VEmModel *, G4VEmFluctuationModel *fluc=nullptr, const G4Region *region=nullptr)
G4double GetContinuousStepLimit(const G4Track &track, G4double previousStepSize, G4double currentMinimumStep, G4double &currentSafety) override
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
G4double AlongStepGetPhysicalInteractionLength(const G4Track &, G4double previousStepSize, G4double currentMinimumStep, G4double &currentSafety, G4GPILSelection *selection) override
void SetLinearLossLimit(G4double val)
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
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
G4double theInitialNumberOfInteractionLength
void SetVerboseLevel(G4int value)
const G4VProcess * GetMasterProcess() const
G4int verboseLevel
G4double theNumberOfInteractionLengthLeft
G4VParticleChange * pParticleChange
G4int GetProcessSubType() const
const G4String & GetProcessName() const
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