Import Geant4 11.1.0.beta source tree

This commit is contained in:
Gabriele Cosmo
2022-07-01 10:44:02 +02:00
parent b3bf75a2a1
commit c07cea1fe0
2172 changed files with 183300 additions and 123938 deletions
+2 -5
View File
@@ -1,6 +1,3 @@
# - G4tracking category build
# Add (private) allocation export symbol
add_definitions(-DG4TRACKING_ALLOC_EXPORT)
geant4_global_library_target(COMPONENTS sources.cmake)
include(sources.cmake)
geant4_add_category(G4tracking MODULES G4tracking)
-2
View File
@@ -27,8 +27,6 @@ CPPFLAGS += -I$(G4BASE)/global/management/include \
-I$(G4BASE)/track/include \
-I$(G4BASE)/materials/include \
-I$(G4BASE)/processes/management/include \
-I$(G4BASE)/processes/cuts/include \
-I$(G4BASE)/processes/electromagnetic/utils/include \
-I$(G4BASE)/particles/management/include \
-I$(G4BASE)/digits_hits/detector/include \
-I$(G4BASE)/digits_hits/hits/include \
+38 -14
View File
@@ -1,20 +1,44 @@
-------------------------------------------------------------------
# Category tracking History
=========================================================
Geant4 - an Object-Oriented Toolkit for Simulation in HEP
=========================================================
See `CONTRIBUTING.rst` for details of **required** info/format for each entry,
which **must** added in reverse chronological order (newest at the top). It must **not**
be used as a substitute for writing good git commit messages!
Category History file
---------------------
This file should be used by G4 developers and category coordinators
to briefly summarize all major modifications introduced in the code
and keep track of all category-tags.
It DOES NOT substitute the CVS log-message one should put at every
committal in the CVS repository !
## 2022-06-21 Ben Morgan (tracking-V11-00-06)
- Merge `G4SteppingManager` implementation files
----------------------------------------------------------
* Reverse chronological order (last date on top), please *
----------------------------------------------------------
## 2022-06-05 Vladimir Ivanchenko (tracking-V11-00-05)
- `G4SteppingManager2`: removed check on cuts and removed dependence of
tracking from EM physics; ApplyCut method in this place was never used and cannot be
use consistently, because energy deposition strongly depend on particle type, physics
models, and user requirement. It is very difficult implementing ApplyCuts here for
all use cases, it is why the real implementation is done within EM physics classes
## 2022-05-10 Jonas Hahnfeld (tracking-V11-00-04)
- `G4SteppingManager`:
* Use new virtual method `GetCreatorProcess()` when processing secondaries
* Correct ProcessDefinedStep for AtRest case
## 2022-05-04 Jonas Hahnfeld (tracking-V11-00-03)
- `G4SteppingManager`:
* Refactor and simplify processing of secondaries
* Use process from PostStepPoint as creator
## 2022-04-19 Jonas Hahnfeld (tracking-V11-00-02)
- Only set step status of `fGeomBoundary` on volume boundary
## 2022-01-28 Ben Morgan (tracking-V11-00-01)
- Replace `geant4_global_library_target` with direct file inclusion and
call to `geant4_add_category` to define library build from source modules.
- Make DLL export symbol a CMake module-level compile definition to aid
future modularization
## 2021-12-10 Ben Morgan (tracking-V11-00-00)
- Change to new Markdown History format
---
# History entries prior to 11.0
October 25, 2021 B.Morgan (tracking-V10-07-19)
- Use G4StrUtil functions replacing deprecated G4String member functions
+1 -1
View File
@@ -175,9 +175,9 @@ class G4SteppingManager
void InvokeAlongStepDoItProcs();
void InvokePostStepDoItProcs();
void InvokePSDIP(size_t); //
G4int ProcessSecondariesFromParticleChange();
G4double CalculateSafety();
// Return the estimated safety value at the PostStepPoint
void ApplyProductionCut(G4Track*);
// Member data
+2 -3
View File
@@ -35,7 +35,6 @@ geant4_add_module(G4tracking
G4SmoothTrajectory.cc
G4SmoothTrajectoryPoint.cc
G4SteppingManager.cc
G4SteppingManager2.cc
G4SteppingVerbose.cc
G4SteppingVerboseWithUnits.cc
G4TrackingManager.cc
@@ -51,6 +50,8 @@ geant4_add_module(G4tracking
G4VTrajectoryPoint.cc
G4MultiSteppingAction.cc)
geant4_module_compile_definitions(G4tracking PRIVATE G4TRACKING_ALLOC_EXPORT)
geant4_module_link_libraries(G4tracking
PUBLIC
G4geometrymng
@@ -63,7 +64,5 @@ geant4_module_link_libraries(G4tracking
G4track
G4volumes
PRIVATE
G4cuts
G4detector
G4emutils
G4graphics_reps)
+533
View File
@@ -42,9 +42,12 @@
#include "G4UserLimits.hh"
#include "G4VSensitiveDetector.hh" // Include from 'hits/digi'
#include "G4GeometryTolerance.hh"
#include "G4ParticleTable.hh"
#include "G4Profiler.hh"
#include "G4TiMemory.hh"
// #define debug
//////////////////////////////////////
G4SteppingManager::G4SteppingManager()
//////////////////////////////////////
@@ -210,6 +213,10 @@ G4StepStatus G4SteppingManager::Stepping()
// Invoke AlongStepDoIt
InvokeAlongStepDoItProcs();
// Get StepStatus from PostStepPoint - a process such as transportation
// might have changed it.
fStepStatus = fStep->GetPostStepPoint()->GetStepStatus();
// Update track by taking into account all changes by AlongStepDoIt
fStep->UpdateTrack();
@@ -397,3 +404,529 @@ void G4SteppingManager::SetInitialStep(G4Track* valueTrack)
if(verboseLevel>0) fVerbose->TrackingStarted();
#endif
}
/////////////////////////////////////////////////
void G4SteppingManager::GetProcessNumber()
/////////////////////////////////////////////////
{
#ifdef debug
G4cout << "G4SteppingManager::GetProcessNumber: is called track="
<< fTrack << G4endl;
#endif
G4ProcessManager* pm= fTrack->GetDefinition()->GetProcessManager();
if(pm == nullptr)
{
G4cerr << "ERROR - G4SteppingManager::GetProcessNumber()" << G4endl
<< " ProcessManager is NULL for particle = "
<< fTrack->GetDefinition()->GetParticleName() << ", PDG_code = "
<< fTrack->GetDefinition()->GetPDGEncoding() << G4endl;
G4Exception("G4SteppingManager::GetProcessNumber()", "Tracking0011",
FatalException, "Process Manager is not found.");
return;
}
// AtRestDoits
//
MAXofAtRestLoops = pm->GetAtRestProcessVector()->entries();
fAtRestDoItVector = pm->GetAtRestProcessVector(typeDoIt);
fAtRestGetPhysIntVector = pm->GetAtRestProcessVector(typeGPIL);
#ifdef debug
G4cout << "G4SteppingManager::GetProcessNumber: #ofAtRest="
<< MAXofAtRestLoops << G4endl;
#endif
// AlongStepDoits
//
MAXofAlongStepLoops = pm->GetAlongStepProcessVector()->entries();
fAlongStepDoItVector = pm->GetAlongStepProcessVector(typeDoIt);
fAlongStepGetPhysIntVector = pm->GetAlongStepProcessVector(typeGPIL);
#ifdef debug
G4cout << "G4SteppingManager::GetProcessNumber:#ofAlongStp="
<< MAXofAlongStepLoops << G4endl;
#endif
// PostStepDoits
//
MAXofPostStepLoops = pm->GetPostStepProcessVector()->entries();
fPostStepDoItVector = pm->GetPostStepProcessVector(typeDoIt);
fPostStepGetPhysIntVector = pm->GetPostStepProcessVector(typeGPIL);
#ifdef debug
G4cout << "G4SteppingManager::GetProcessNumber: #ofPostStep="
<< MAXofPostStepLoops << G4endl;
#endif
if (SizeOfSelectedDoItVector<MAXofAtRestLoops ||
SizeOfSelectedDoItVector<MAXofAlongStepLoops ||
SizeOfSelectedDoItVector<MAXofPostStepLoops )
{
G4cerr << "ERROR - G4SteppingManager::GetProcessNumber()" << G4endl
<< " SizeOfSelectedDoItVector= " << SizeOfSelectedDoItVector
<< " ; is smaller then one of MAXofAtRestLoops= "
<< MAXofAtRestLoops << G4endl
<< " or MAXofAlongStepLoops= " << MAXofAlongStepLoops
<< " or MAXofPostStepLoops= " << MAXofPostStepLoops << G4endl;
G4Exception("G4SteppingManager::GetProcessNumber()",
"Tracking0012", FatalException,
"The array size is smaller than the actual No of processes.");
}
}
// ************************************************************************
//
// Private Member Functions
//
// ************************************************************************
/////////////////////////////////////////////////////////
void G4SteppingManager::DefinePhysicalStepLength()
/////////////////////////////////////////////////////////
{
// ReSet the counter etc.
//
PhysicalStep = DBL_MAX; // Initialize by a huge number
physIntLength = DBL_MAX; // Initialize by a huge number
#ifdef G4VERBOSE
if(verboseLevel>0) fVerbose->DPSLStarted();
#endif
// GPIL for PostStep
//
fPostStepDoItProcTriggered = MAXofPostStepLoops;
for(std::size_t np=0; np<MAXofPostStepLoops; ++np)
{
fCurrentProcess = (*fPostStepGetPhysIntVector)(np);
if (fCurrentProcess == nullptr)
{
(*fSelectedPostStepDoItVector)[np] = InActivated;
continue;
} // NULL means the process is inactivated by a user on fly
physIntLength = fCurrentProcess->PostStepGPIL( *fTrack,
fPreviousStepSize, &fCondition );
#ifdef G4VERBOSE
if(verboseLevel>0) fVerbose->DPSLPostStep();
#endif
switch (fCondition)
{
case ExclusivelyForced:
(*fSelectedPostStepDoItVector)[np] = ExclusivelyForced;
fStepStatus = fExclusivelyForcedProc;
fStep->GetPostStepPoint()->SetProcessDefinedStep(fCurrentProcess);
break;
case Conditionally:
// (*fSelectedPostStepDoItVector)[np] = Conditionally;
G4Exception("G4SteppingManager::DefinePhysicalStepLength()",
"Tracking1001", FatalException,
"This feature no more supported");
break;
case Forced:
(*fSelectedPostStepDoItVector)[np] = Forced;
break;
case StronglyForced:
(*fSelectedPostStepDoItVector)[np] = StronglyForced;
break;
default:
(*fSelectedPostStepDoItVector)[np] = InActivated;
break;
}
if (fCondition==ExclusivelyForced)
{
for(std::size_t nrest=np+1; nrest<MAXofPostStepLoops; ++nrest)
{
(*fSelectedPostStepDoItVector)[nrest] = InActivated;
}
return; // Take note the 'return' at here !!!
}
else
{
if(physIntLength < PhysicalStep )
{
PhysicalStep = physIntLength;
fStepStatus = fPostStepDoItProc;
fPostStepDoItProcTriggered = G4int(np);
fStep->GetPostStepPoint()->SetProcessDefinedStep(fCurrentProcess);
}
}
}
if (fPostStepDoItProcTriggered<MAXofPostStepLoops)
{
if ((*fSelectedPostStepDoItVector)[fPostStepDoItProcTriggered] == InActivated)
{
(*fSelectedPostStepDoItVector)[fPostStepDoItProcTriggered] = NotForced;
}
}
// GPIL for AlongStep
//
proposedSafety = DBL_MAX;
G4double safetyProposedToAndByProcess = proposedSafety;
G4bool delegateToTransportation = false;
for(std::size_t kp=0; kp<MAXofAlongStepLoops; ++kp)
{
fCurrentProcess = (*fAlongStepGetPhysIntVector)[kp];
if (fCurrentProcess == nullptr) continue;
// NULL means the process is inactivated by a user on fly
physIntLength = fCurrentProcess->AlongStepGPIL( *fTrack,
fPreviousStepSize, PhysicalStep,
safetyProposedToAndByProcess,
&fGPILSelection );
#ifdef G4VERBOSE
if(verboseLevel>0) fVerbose->DPSLAlongStep();
#endif
if(physIntLength < PhysicalStep)
{
PhysicalStep = physIntLength;
// Check if the process wants to be the GPIL winner. For example,
// multi-scattering proposes Step limit, but won't be the winner
//
if(fGPILSelection==CandidateForSelection)
{
fStepStatus = fAlongStepDoItProc;
fStep->GetPostStepPoint()->SetProcessDefinedStep(fCurrentProcess);
}
else if(fCurrentProcess->GetProcessType()==fParallel)
{ // a parallel world is proposing the shortest but expecting Transportation
// to win.
delegateToTransportation = true;
}
// Transportation is assumed to be the last process in the vector
// Transportation is winning
if(kp == MAXofAlongStepLoops-1)
{
// This used to set fStepStatus = fGeomBoundary, but it was moved to
// G4Transportation::AlongStepDoIt where the process can actually
// decide if there is a volume boundary.
delegateToTransportation = false;
}
}
// Make sure to check the safety, even if Step is not limited
// by this process
//
if (safetyProposedToAndByProcess < proposedSafety)
{
// proposedSafety keeps the smallest value
//
proposedSafety = safetyProposedToAndByProcess;
}
else
{
// safetyProposedToAndByProcess always proposes a valid safety
//
safetyProposedToAndByProcess = proposedSafety;
}
}
if(delegateToTransportation)
{
fStepStatus = fGeomBoundary;
fStep->GetPostStepPoint()->SetProcessDefinedStep(fCurrentProcess);
}
}
//////////////////////////////////////////////////////
G4int G4SteppingManager::ProcessSecondariesFromParticleChange()
//////////////////////////////////////////////////////
{
G4Track* tempSecondaryTrack;
G4int num2ndaries;
G4int pushedSecondaries = 0;
num2ndaries = fParticleChange->GetNumberOfSecondaries();
if(num2ndaries == 0)
{
return 0;
}
// Get the creator process. This may be different from fCurrentProcess for a
// "combined" process such as G4GammaGeneralProcess.
const G4VProcess* creatorProcess = fCurrentProcess->GetCreatorProcess();
for(G4int DSecLoop=0; DSecLoop< num2ndaries; ++DSecLoop)
{
tempSecondaryTrack = fParticleChange->GetSecondary(DSecLoop);
// Set parentID
tempSecondaryTrack->SetParentID( fTrack->GetTrackID() );
// Set the process pointer which created this track
tempSecondaryTrack->SetCreatorProcess( creatorProcess );
// If this 2ndry particle has 'zero' kinetic energy, make sure
// it invokes a rest process at the beginning of the tracking
//
if(tempSecondaryTrack->GetKineticEnergy() <= DBL_MIN)
{
G4ProcessManager* pm = tempSecondaryTrack->GetDefinition()
->GetProcessManager();
if(pm == nullptr)
{
G4ExceptionDescription ED;
ED << "A track without proper process manager is pushed\n"
<< "into the track stack.\n"
<< " Particle name : "
<< tempSecondaryTrack->GetDefinition()->GetParticleName()
<< " -- created by " << creatorProcess->GetProcessName() << ".";
G4Exception("G4SteppingManager::ProcessSecondariesFromParticleChange()",
"Tracking10051", FatalException, ED);
}
if (pm->GetAtRestProcessVector()->entries()>0)
{
tempSecondaryTrack->SetTrackStatus( fStopButAlive );
fSecondary->push_back( tempSecondaryTrack );
++pushedSecondaries;
}
else
{
delete tempSecondaryTrack;
}
}
else
{
fSecondary->push_back( tempSecondaryTrack );
++pushedSecondaries;
}
} //end of loop on secondary
return pushedSecondaries;
}
//////////////////////////////////////////////////////
void G4SteppingManager::InvokeAtRestDoItProcs()
//////////////////////////////////////////////////////
{
// Select the rest process which has the shortest time before
// it is invoked. In rest processes, GPIL()
// returns the time before a process occurs
G4double lifeTime, shortestLifeTime;
fAtRestDoItProcTriggered = 0;
shortestLifeTime = DBL_MAX;
unsigned int NofInactiveProc = 0;
for( std::size_t ri=0 ; ri < MAXofAtRestLoops ; ++ri )
{
fCurrentProcess = (*fAtRestGetPhysIntVector)[ri];
if (fCurrentProcess == nullptr)
{
(*fSelectedAtRestDoItVector)[ri] = InActivated;
++NofInactiveProc;
continue;
} // NULL means the process is inactivated by a user on fly
lifeTime = fCurrentProcess->AtRestGPIL( *fTrack, &fCondition );
if(fCondition == Forced)
{
(*fSelectedAtRestDoItVector)[ri] = Forced;
}
else
{
(*fSelectedAtRestDoItVector)[ri] = InActivated;
if(lifeTime < shortestLifeTime )
{
shortestLifeTime = lifeTime;
fAtRestDoItProcTriggered = G4int(ri);
fStep->GetPostStepPoint()->SetProcessDefinedStep(fCurrentProcess);
}
}
}
(*fSelectedAtRestDoItVector)[fAtRestDoItProcTriggered] = NotForced;
// at least one process is necessary to destroy the particle exit with warning
//
if(NofInactiveProc==MAXofAtRestLoops)
{
G4Exception("G4SteppingManager::InvokeAtRestDoItProcs()", "Tracking0013",
JustWarning, "No AtRestDoIt process is active!" );
}
fStep->SetStepLength( 0. ); // the particle has stopped
fTrack->SetStepLength( 0. );
// Condition to avoid that stable ions are handled by Radioactive Decay.
// We use a very large time threshold (many orders of magnitude bigger than
// the universe's age) but not DBL_MAX because shortestLifeTime can be
// sometimes slightly smaller for stable ions.
if(shortestLifeTime < 1.0e+100) // Unstable ion at rest: Radioactive Decay will decay it
{
// invoke selected process
//
for(std::size_t np=0; np<MAXofAtRestLoops; ++np)
{
//
// Note: DoItVector has inverse order against GetPhysIntVector
// and SelectedAtRestDoItVector.
//
if( (*fSelectedAtRestDoItVector)[MAXofAtRestLoops-np-1] != InActivated)
{
fCurrentProcess = (*fAtRestDoItVector)[np];
fParticleChange = fCurrentProcess->AtRestDoIt(*fTrack, *fStep);
// Update Step
//
fParticleChange->UpdateStepForAtRest(fStep);
// Now Store the secondaries from ParticleChange to SecondaryList
fN2ndariesAtRestDoIt += ProcessSecondariesFromParticleChange();
// clear ParticleChange
fParticleChange->Clear();
} // if(fSelectedAtRestDoItVector[np] != InActivated){
} // for(std::size_t np=0; np<MAXofAtRestLoops; ++np){
}
else // Stable ion at rest
{
fStep->GetPostStepPoint()->SetProcessDefinedStep( fNoProcess );
} // if(shortestLifeTime < 1.0e+100)
fStep->UpdateTrack();
fTrack->SetTrackStatus( fStopAndKill );
}
/////////////////////////////////////////////////////////
void G4SteppingManager::InvokeAlongStepDoItProcs()
/////////////////////////////////////////////////////////
{
// If the current Step is defined by a 'ExclusivelyForced'
// PostStepDoIt, then don't invoke any AlongStepDoIt
//
if(fStepStatus == fExclusivelyForcedProc)
{
return; // Take note 'return' is here !!!
}
// Invoke all active continuous processes
//
for( std::size_t ci=0; ci<MAXofAlongStepLoops; ++ci )
{
fCurrentProcess = (*fAlongStepDoItVector)[ci];
if (fCurrentProcess== 0) continue;
// NULL means the process is inactivated by a user on fly.
fParticleChange = fCurrentProcess->AlongStepDoIt( *fTrack, *fStep );
// Update the PostStepPoint of Step according to ParticleChange
fParticleChange->UpdateStepForAlongStep(fStep);
#ifdef G4VERBOSE
if(verboseLevel>0) fVerbose->AlongStepDoItOneByOne();
#endif
// Now Store the secondaries from ParticleChange to SecondaryList
fN2ndariesAlongStepDoIt += ProcessSecondariesFromParticleChange();
// Set the track status according to what the process defined
// if kinetic energy >0, otherwise set fStopButAlive
//
fTrack->SetTrackStatus( fParticleChange->GetTrackStatus() );
// clear ParticleChange
fParticleChange->Clear();
}
fStep->UpdateTrack();
G4TrackStatus fNewStatus = fTrack->GetTrackStatus();
if ( fNewStatus == fAlive && fTrack->GetKineticEnergy() <= DBL_MIN )
{
if(MAXofAtRestLoops>0) fNewStatus = fStopButAlive;
else fNewStatus = fStopAndKill;
fTrack->SetTrackStatus( fNewStatus );
}
}
////////////////////////////////////////////////////////
void G4SteppingManager::InvokePostStepDoItProcs()
////////////////////////////////////////////////////////
{
// Invoke the specified discrete processes
//
for(std::size_t np=0; np<MAXofPostStepLoops; ++np)
{
//
// Note: DoItVector has inverse order against GetPhysIntVector
// and SelectedPostStepDoItVector.
//
G4int Cond = (*fSelectedPostStepDoItVector)[MAXofPostStepLoops-np-1];
if(Cond != InActivated)
{
if( ((Cond == NotForced) && (fStepStatus == fPostStepDoItProc)) ||
((Cond == Forced) && (fStepStatus != fExclusivelyForcedProc)) ||
((Cond == ExclusivelyForced) && (fStepStatus == fExclusivelyForcedProc)) ||
((Cond == StronglyForced) ) )
{
InvokePSDIP(np);
if ((np==0) && (fTrack->GetNextVolume() == nullptr))
{
fStepStatus = fWorldBoundary;
fStep->GetPostStepPoint()->SetStepStatus( fStepStatus );
}
}
}
// Exit from PostStepLoop if the track has been killed,
// but extra treatment for processes with Strongly Forced flag
//
if(fTrack->GetTrackStatus() == fStopAndKill)
{
for(std::size_t np1=np+1; np1<MAXofPostStepLoops; ++np1)
{
G4int Cond2 = (*fSelectedPostStepDoItVector)[MAXofPostStepLoops-np1-1];
if (Cond2 == StronglyForced)
{
InvokePSDIP(np1);
}
}
break;
}
}
}
////////////////////////////////////////////////////////
void G4SteppingManager::InvokePSDIP(size_t np)
////////////////////////////////////////////////////////
{
fCurrentProcess = (*fPostStepDoItVector)[np];
fParticleChange = fCurrentProcess->PostStepDoIt( *fTrack, *fStep);
// Update PostStepPoint of Step according to ParticleChange
fParticleChange->UpdateStepForPostStep(fStep);
#ifdef G4VERBOSE
if(verboseLevel>0) fVerbose->PostStepDoItOneByOne();
#endif
// Update G4Track according to ParticleChange after each PostStepDoIt
fStep->UpdateTrack();
// Update safety after each invocation of PostStepDoIts
fStep->GetPostStepPoint()->SetSafety( CalculateSafety() );
// Now Store the secondaries from ParticleChange to SecondaryList
fN2ndariesPostStepDoIt += ProcessSecondariesFromParticleChange();
// Set the track status according to what the process defined
fTrack->SetTrackStatus( fParticleChange->GetTrackStatus() );
// clear ParticleChange
fParticleChange->Clear();
}
-747
View File
@@ -1,747 +0,0 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4SteppingManager class implementation - part 2
//
// Contact:
// Questions and comments to this code should be sent to
// Katsuya Amako (e-mail: Katsuya.Amako@kek.jp)
// Takashi Sasaki (e-mail: Takashi.Sasaki@kek.jp)
// --------------------------------------------------------------------
// #define debug
#include "G4UImanager.hh"
#include "G4ForceCondition.hh"
#include "G4GPILSelection.hh"
#include "G4SteppingControl.hh"
#include "G4TransportationManager.hh"
#include "G4SteppingManager.hh"
#include "G4LossTableManager.hh"
#include "G4ParticleTable.hh"
#include "G4EnergyLossTables.hh"
#include "G4ProductionCuts.hh"
#include "G4ProductionCutsTable.hh"
/////////////////////////////////////////////////
void G4SteppingManager::GetProcessNumber()
/////////////////////////////////////////////////
{
#ifdef debug
G4cout << "G4SteppingManager::GetProcessNumber: is called track="
<< fTrack << G4endl;
#endif
G4ProcessManager* pm= fTrack->GetDefinition()->GetProcessManager();
if(pm == nullptr)
{
G4cerr << "ERROR - G4SteppingManager::GetProcessNumber()" << G4endl
<< " ProcessManager is NULL for particle = "
<< fTrack->GetDefinition()->GetParticleName() << ", PDG_code = "
<< fTrack->GetDefinition()->GetPDGEncoding() << G4endl;
G4Exception("G4SteppingManager::GetProcessNumber()", "Tracking0011",
FatalException, "Process Manager is not found.");
return;
}
// AtRestDoits
//
MAXofAtRestLoops = pm->GetAtRestProcessVector()->entries();
fAtRestDoItVector = pm->GetAtRestProcessVector(typeDoIt);
fAtRestGetPhysIntVector = pm->GetAtRestProcessVector(typeGPIL);
#ifdef debug
G4cout << "G4SteppingManager::GetProcessNumber: #ofAtRest="
<< MAXofAtRestLoops << G4endl;
#endif
// AlongStepDoits
//
MAXofAlongStepLoops = pm->GetAlongStepProcessVector()->entries();
fAlongStepDoItVector = pm->GetAlongStepProcessVector(typeDoIt);
fAlongStepGetPhysIntVector = pm->GetAlongStepProcessVector(typeGPIL);
#ifdef debug
G4cout << "G4SteppingManager::GetProcessNumber:#ofAlongStp="
<< MAXofAlongStepLoops << G4endl;
#endif
// PostStepDoits
//
MAXofPostStepLoops = pm->GetPostStepProcessVector()->entries();
fPostStepDoItVector = pm->GetPostStepProcessVector(typeDoIt);
fPostStepGetPhysIntVector = pm->GetPostStepProcessVector(typeGPIL);
#ifdef debug
G4cout << "G4SteppingManager::GetProcessNumber: #ofPostStep="
<< MAXofPostStepLoops << G4endl;
#endif
if (SizeOfSelectedDoItVector<MAXofAtRestLoops ||
SizeOfSelectedDoItVector<MAXofAlongStepLoops ||
SizeOfSelectedDoItVector<MAXofPostStepLoops )
{
G4cerr << "ERROR - G4SteppingManager::GetProcessNumber()" << G4endl
<< " SizeOfSelectedDoItVector= " << SizeOfSelectedDoItVector
<< " ; is smaller then one of MAXofAtRestLoops= "
<< MAXofAtRestLoops << G4endl
<< " or MAXofAlongStepLoops= " << MAXofAlongStepLoops
<< " or MAXofPostStepLoops= " << MAXofPostStepLoops << G4endl;
G4Exception("G4SteppingManager::GetProcessNumber()",
"Tracking0012", FatalException,
"The array size is smaller than the actual No of processes.");
}
}
// ************************************************************************
//
// Private Member Functions
//
// ************************************************************************
/////////////////////////////////////////////////////////
void G4SteppingManager::DefinePhysicalStepLength()
/////////////////////////////////////////////////////////
{
// ReSet the counter etc.
//
PhysicalStep = DBL_MAX; // Initialize by a huge number
physIntLength = DBL_MAX; // Initialize by a huge number
#ifdef G4VERBOSE
if(verboseLevel>0) fVerbose->DPSLStarted();
#endif
// GPIL for PostStep
//
fPostStepDoItProcTriggered = MAXofPostStepLoops;
for(std::size_t np=0; np<MAXofPostStepLoops; ++np)
{
fCurrentProcess = (*fPostStepGetPhysIntVector)(np);
if (fCurrentProcess == nullptr)
{
(*fSelectedPostStepDoItVector)[np] = InActivated;
continue;
} // NULL means the process is inactivated by a user on fly
physIntLength = fCurrentProcess->PostStepGPIL( *fTrack,
fPreviousStepSize, &fCondition );
#ifdef G4VERBOSE
if(verboseLevel>0) fVerbose->DPSLPostStep();
#endif
switch (fCondition)
{
case ExclusivelyForced:
(*fSelectedPostStepDoItVector)[np] = ExclusivelyForced;
fStepStatus = fExclusivelyForcedProc;
fStep->GetPostStepPoint()->SetProcessDefinedStep(fCurrentProcess);
break;
case Conditionally:
// (*fSelectedPostStepDoItVector)[np] = Conditionally;
G4Exception("G4SteppingManager::DefinePhysicalStepLength()",
"Tracking1001", FatalException,
"This feature no more supported");
break;
case Forced:
(*fSelectedPostStepDoItVector)[np] = Forced;
break;
case StronglyForced:
(*fSelectedPostStepDoItVector)[np] = StronglyForced;
break;
default:
(*fSelectedPostStepDoItVector)[np] = InActivated;
break;
}
if (fCondition==ExclusivelyForced)
{
for(std::size_t nrest=np+1; nrest<MAXofPostStepLoops; ++nrest)
{
(*fSelectedPostStepDoItVector)[nrest] = InActivated;
}
return; // Take note the 'return' at here !!!
}
else
{
if(physIntLength < PhysicalStep )
{
PhysicalStep = physIntLength;
fStepStatus = fPostStepDoItProc;
fPostStepDoItProcTriggered = G4int(np);
fStep->GetPostStepPoint()->SetProcessDefinedStep(fCurrentProcess);
}
}
}
if (fPostStepDoItProcTriggered<MAXofPostStepLoops)
{
if ((*fSelectedPostStepDoItVector)[fPostStepDoItProcTriggered] == InActivated)
{
(*fSelectedPostStepDoItVector)[fPostStepDoItProcTriggered] = NotForced;
}
}
// GPIL for AlongStep
//
proposedSafety = DBL_MAX;
G4double safetyProposedToAndByProcess = proposedSafety;
G4bool delegateToTransportation = false;
for(std::size_t kp=0; kp<MAXofAlongStepLoops; ++kp)
{
fCurrentProcess = (*fAlongStepGetPhysIntVector)[kp];
if (fCurrentProcess == nullptr) continue;
// NULL means the process is inactivated by a user on fly
physIntLength = fCurrentProcess->AlongStepGPIL( *fTrack,
fPreviousStepSize, PhysicalStep,
safetyProposedToAndByProcess,
&fGPILSelection );
#ifdef G4VERBOSE
if(verboseLevel>0) fVerbose->DPSLAlongStep();
#endif
if(physIntLength < PhysicalStep)
{
PhysicalStep = physIntLength;
// Check if the process wants to be the GPIL winner. For example,
// multi-scattering proposes Step limit, but won't be the winner
//
if(fGPILSelection==CandidateForSelection)
{
fStepStatus = fAlongStepDoItProc;
fStep->GetPostStepPoint()->SetProcessDefinedStep(fCurrentProcess);
}
else if(fCurrentProcess->GetProcessType()==fParallel)
{ // a parallel world is proposing the shortest but expecting Transportation
// to win.
delegateToTransportation = true;
}
// Transportation is assumed to be the last process in the vector
// Transportation is winning
if(kp == MAXofAlongStepLoops-1)
{
fStepStatus = fGeomBoundary;
delegateToTransportation = false;
}
}
// Make sure to check the safety, even if Step is not limited
// by this process
//
if (safetyProposedToAndByProcess < proposedSafety)
{
// proposedSafety keeps the smallest value
//
proposedSafety = safetyProposedToAndByProcess;
}
else
{
// safetyProposedToAndByProcess always proposes a valid safety
//
safetyProposedToAndByProcess = proposedSafety;
}
}
if(delegateToTransportation)
{
fStepStatus = fGeomBoundary;
fStep->GetPostStepPoint()->SetProcessDefinedStep(fCurrentProcess);
}
}
//////////////////////////////////////////////////////
void G4SteppingManager::InvokeAtRestDoItProcs()
//////////////////////////////////////////////////////
{
// Select the rest process which has the shortest time before
// it is invoked. In rest processes, GPIL()
// returns the time before a process occurs
G4double lifeTime, shortestLifeTime;
fAtRestDoItProcTriggered = 0;
shortestLifeTime = DBL_MAX;
unsigned int NofInactiveProc = 0;
for( std::size_t ri=0 ; ri < MAXofAtRestLoops ; ++ri )
{
fCurrentProcess = (*fAtRestGetPhysIntVector)[ri];
if (fCurrentProcess == nullptr)
{
(*fSelectedAtRestDoItVector)[ri] = InActivated;
++NofInactiveProc;
continue;
} // NULL means the process is inactivated by a user on fly
lifeTime = fCurrentProcess->AtRestGPIL( *fTrack, &fCondition );
if(fCondition == Forced)
{
(*fSelectedAtRestDoItVector)[ri] = Forced;
}
else
{
(*fSelectedAtRestDoItVector)[ri] = InActivated;
if(lifeTime < shortestLifeTime )
{
shortestLifeTime = lifeTime;
fAtRestDoItProcTriggered = G4int(ri);
}
}
}
(*fSelectedAtRestDoItVector)[fAtRestDoItProcTriggered] = NotForced;
// at least one process is necessary to destroy the particle exit with warning
//
if(NofInactiveProc==MAXofAtRestLoops)
{
G4Exception("G4SteppingManager::InvokeAtRestDoItProcs()", "Tracking0013",
JustWarning, "No AtRestDoIt process is active!" );
}
fStep->SetStepLength( 0. ); // the particle has stopped
fTrack->SetStepLength( 0. );
// Condition to avoid that stable ions are handled by Radioactive Decay.
// We use a very large time threshold (many orders of magnitude bigger than
// the universe's age) but not DBL_MAX because shortestLifeTime can be
// sometimes slightly smaller for stable ions.
if(shortestLifeTime < 1.0e+100) // Unstable ion at rest: Radioactive Decay will decay it
{
// invoke selected process
//
for(std::size_t np=0; np<MAXofAtRestLoops; ++np)
{
//
// Note: DoItVector has inverse order against GetPhysIntVector
// and SelectedAtRestDoItVector.
//
if( (*fSelectedAtRestDoItVector)[MAXofAtRestLoops-np-1] != InActivated)
{
fCurrentProcess = (*fAtRestDoItVector)[np];
fParticleChange = fCurrentProcess->AtRestDoIt(*fTrack, *fStep);
// Set the current process as a process which defined this Step length
//
fStep->GetPostStepPoint()->SetProcessDefinedStep(fCurrentProcess);
// Update Step
//
fParticleChange->UpdateStepForAtRest(fStep);
// Now Store the secondaries from ParticleChange to SecondaryList
G4Track* tempSecondaryTrack;
G4int num2ndaries;
num2ndaries = fParticleChange->GetNumberOfSecondaries();
for(G4int DSecLoop=0; DSecLoop< num2ndaries; ++DSecLoop)
{
tempSecondaryTrack = fParticleChange->GetSecondary(DSecLoop);
if(tempSecondaryTrack->GetDefinition()->GetApplyCutsFlag())
{
ApplyProductionCut(tempSecondaryTrack);
}
// Set parentID
tempSecondaryTrack->SetParentID( fTrack->GetTrackID() );
// Set the process pointer which created this track
tempSecondaryTrack->SetCreatorProcess( fCurrentProcess );
// If this 2ndry particle has 'zero' kinetic energy, make sure
// it invokes a rest process at the beginning of the tracking
//
if(tempSecondaryTrack->GetKineticEnergy() <= DBL_MIN)
{
G4ProcessManager* pm = tempSecondaryTrack->GetDefinition()
->GetProcessManager();
if(pm == nullptr)
{
G4ExceptionDescription ED;
ED << "A track without proper process manager is pushed\n"
<< "into the track stack.\n"
<< " Particle name : "
<< tempSecondaryTrack->GetDefinition()->GetParticleName()
<< " -- ";
if(tempSecondaryTrack->GetParentID()<0)
{
ED << "created by a primary particle generator.";
}
else
{
const G4VProcess* vp = tempSecondaryTrack->GetCreatorProcess();
if(vp != nullptr)
{ ED << "created by " << vp->GetProcessName() << "."; }
else
{ ED << "creaded by unknown process."; }
}
G4Exception("G4SteppingManager::InvokeAtRestDoItProcs()",
"Tracking10051", FatalException, ED);
}
if (pm->GetAtRestProcessVector()->entries()>0)
{
tempSecondaryTrack->SetTrackStatus( fStopButAlive );
fSecondary->push_back( tempSecondaryTrack );
++fN2ndariesAtRestDoIt;
}
else
{
delete tempSecondaryTrack;
}
}
else
{
fSecondary->push_back( tempSecondaryTrack );
++fN2ndariesAtRestDoIt;
}
} //end of loop on secondary
// clear ParticleChange
fParticleChange->Clear();
} // if(fSelectedAtRestDoItVector[np] != InActivated){
} // for(std::size_t np=0; np<MAXofAtRestLoops; ++np){
}
else // Stable ion at rest
{
fStep->GetPostStepPoint()->SetProcessDefinedStep( fNoProcess );
} // if(shortestLifeTime < 1.0e+100)
fStep->UpdateTrack();
fTrack->SetTrackStatus( fStopAndKill );
}
/////////////////////////////////////////////////////////
void G4SteppingManager::InvokeAlongStepDoItProcs()
/////////////////////////////////////////////////////////
{
// If the current Step is defined by a 'ExclusivelyForced'
// PostStepDoIt, then don't invoke any AlongStepDoIt
//
if(fStepStatus == fExclusivelyForcedProc)
{
return; // Take note 'return' is here !!!
}
// Invoke all active continuous processes
//
for( std::size_t ci=0; ci<MAXofAlongStepLoops; ++ci )
{
fCurrentProcess = (*fAlongStepDoItVector)[ci];
if (fCurrentProcess== 0) continue;
// NULL means the process is inactivated by a user on fly.
fParticleChange = fCurrentProcess->AlongStepDoIt( *fTrack, *fStep );
// Update the PostStepPoint of Step according to ParticleChange
fParticleChange->UpdateStepForAlongStep(fStep);
#ifdef G4VERBOSE
if(verboseLevel>0) fVerbose->AlongStepDoItOneByOne();
#endif
// Now Store the secondaries from ParticleChange to SecondaryList
G4Track* tempSecondaryTrack;
G4int num2ndaries;
num2ndaries = fParticleChange->GetNumberOfSecondaries();
for(G4int DSecLoop=0; DSecLoop<num2ndaries; ++DSecLoop)
{
tempSecondaryTrack = fParticleChange->GetSecondary(DSecLoop);
if(tempSecondaryTrack->GetDefinition()->GetApplyCutsFlag())
{
ApplyProductionCut(tempSecondaryTrack);
}
// Set parentID
tempSecondaryTrack->SetParentID( fTrack->GetTrackID() );
// Set the process pointer which created this track
tempSecondaryTrack->SetCreatorProcess( fCurrentProcess );
// If this secondary particle has 'zero' kinetic energy, make sure
// it invokes a rest process at the beginning of the tracking
//
if(tempSecondaryTrack->GetKineticEnergy() <= DBL_MIN)
{
G4ProcessManager* pm = tempSecondaryTrack->GetDefinition()
->GetProcessManager();
if(pm == nullptr)
{
G4ExceptionDescription ED;
ED << "A track without proper process manager is pushed\n"
<< "into the track stack.\n"
<< " Particle name : "
<< tempSecondaryTrack->GetDefinition()->GetParticleName()
<< " -- ";
if(tempSecondaryTrack->GetParentID()<0)
{
ED << "created by a primary particle generator.";
}
else
{
const G4VProcess* vp = tempSecondaryTrack->GetCreatorProcess();
if(vp != nullptr)
{ ED << "created by " << vp->GetProcessName() << "."; }
else
{ ED << "creaded by unknown process."; }
}
G4Exception("G4SteppingManager::InvokeAlongStepDoItProcs()",
"Tracking10051", FatalException, ED);
}
if (pm->GetAtRestProcessVector()->entries()>0)
{
tempSecondaryTrack->SetTrackStatus( fStopButAlive );
fSecondary->push_back( tempSecondaryTrack );
++fN2ndariesAlongStepDoIt;
}
else
{
delete tempSecondaryTrack;
}
}
else
{
fSecondary->push_back( tempSecondaryTrack );
++fN2ndariesAlongStepDoIt;
}
} //end of loop on secondary
// Set the track status according to what the process defined
// if kinetic energy >0, otherwise set fStopButAlive
//
fTrack->SetTrackStatus( fParticleChange->GetTrackStatus() );
// clear ParticleChange
fParticleChange->Clear();
}
fStep->UpdateTrack();
G4TrackStatus fNewStatus = fTrack->GetTrackStatus();
if ( fNewStatus == fAlive && fTrack->GetKineticEnergy() <= DBL_MIN )
{
if(MAXofAtRestLoops>0) fNewStatus = fStopButAlive;
else fNewStatus = fStopAndKill;
fTrack->SetTrackStatus( fNewStatus );
}
}
////////////////////////////////////////////////////////
void G4SteppingManager::InvokePostStepDoItProcs()
////////////////////////////////////////////////////////
{
// Invoke the specified discrete processes
//
for(std::size_t np=0; np<MAXofPostStepLoops; ++np)
{
//
// Note: DoItVector has inverse order against GetPhysIntVector
// and SelectedPostStepDoItVector.
//
G4int Cond = (*fSelectedPostStepDoItVector)[MAXofPostStepLoops-np-1];
if(Cond != InActivated)
{
if( ((Cond == NotForced) && (fStepStatus == fPostStepDoItProc)) ||
((Cond == Forced) && (fStepStatus != fExclusivelyForcedProc)) ||
((Cond == ExclusivelyForced) && (fStepStatus == fExclusivelyForcedProc)) ||
((Cond == StronglyForced) ) )
{
InvokePSDIP(np);
if ((np==0) && (fTrack->GetNextVolume() == nullptr))
{
fStepStatus = fWorldBoundary;
fStep->GetPostStepPoint()->SetStepStatus( fStepStatus );
}
}
}
// Exit from PostStepLoop if the track has been killed,
// but extra treatment for processes with Strongly Forced flag
//
if(fTrack->GetTrackStatus() == fStopAndKill)
{
for(std::size_t np1=np+1; np1<MAXofPostStepLoops; ++np1)
{
G4int Cond2 = (*fSelectedPostStepDoItVector)[MAXofPostStepLoops-np1-1];
if (Cond2 == StronglyForced)
{
InvokePSDIP(np1);
}
}
break;
}
}
}
////////////////////////////////////////////////////////
void G4SteppingManager::InvokePSDIP(size_t np)
////////////////////////////////////////////////////////
{
fCurrentProcess = (*fPostStepDoItVector)[np];
fParticleChange = fCurrentProcess->PostStepDoIt( *fTrack, *fStep);
// Update PostStepPoint of Step according to ParticleChange
fParticleChange->UpdateStepForPostStep(fStep);
#ifdef G4VERBOSE
if(verboseLevel>0) fVerbose->PostStepDoItOneByOne();
#endif
// Update G4Track according to ParticleChange after each PostStepDoIt
fStep->UpdateTrack();
// Update safety after each invocation of PostStepDoIts
fStep->GetPostStepPoint()->SetSafety( CalculateSafety() );
// Now Store the secondaries from ParticleChange to SecondaryList
G4Track* tempSecondaryTrack;
G4int num2ndaries;
num2ndaries = fParticleChange->GetNumberOfSecondaries();
for(G4int DSecLoop=0; DSecLoop<num2ndaries; ++DSecLoop)
{
tempSecondaryTrack = fParticleChange->GetSecondary(DSecLoop);
if(tempSecondaryTrack->GetDefinition()->GetApplyCutsFlag())
{
ApplyProductionCut(tempSecondaryTrack);
}
// Set parentID
tempSecondaryTrack->SetParentID( fTrack->GetTrackID() );
// Set the process pointer which created this track
tempSecondaryTrack->SetCreatorProcess( fCurrentProcess );
// If this secondary particle has 'zero' kinetic energy, make sure
// it invokes a rest process at the beginning of the tracking
//
if(tempSecondaryTrack->GetKineticEnergy() <= DBL_MIN)
{
G4ProcessManager* pm = tempSecondaryTrack->GetDefinition()
->GetProcessManager();
if(pm == nullptr)
{
G4ExceptionDescription ED;
ED << "A track without proper process manager is pushed\n"
<< "into the track stack.\n"
<< " Particle name : "
<< tempSecondaryTrack->GetDefinition()->GetParticleName()
<< " -- ";
if(tempSecondaryTrack->GetParentID()<0)
{
ED << "created by a primary particle generator.";
}
else
{
const G4VProcess* vp = tempSecondaryTrack->GetCreatorProcess();
if(vp != nullptr)
{ ED << "created by " << vp->GetProcessName() << "."; }
else
{ ED << "creaded by unknown process."; }
}
G4Exception("G4SteppingManager::InvokePSDIP()","Tracking10053",
FatalException,ED);
}
if (pm->GetAtRestProcessVector()->entries()>0)
{
tempSecondaryTrack->SetTrackStatus( fStopButAlive );
fSecondary->push_back( tempSecondaryTrack );
++fN2ndariesPostStepDoIt;
}
else
{
delete tempSecondaryTrack;
}
}
else
{
fSecondary->push_back( tempSecondaryTrack );
++fN2ndariesPostStepDoIt;
}
} //end of loop on secondary
// Set the track status according to what the process defined
fTrack->SetTrackStatus( fParticleChange->GetTrackStatus() );
// clear ParticleChange
fParticleChange->Clear();
}
////////////////////////////////////////////////////////
void G4SteppingManager::ApplyProductionCut(G4Track* aSecondary)
////////////////////////////////////////////////////////
{
G4bool tBelowCutEnergyAndSafety = false;
G4int tPtclIdx
= G4ProductionCuts::GetIndex(aSecondary->GetDefinition());
if (tPtclIdx<0) { return; }
G4ProductionCutsTable* tCutsTbl
= G4ProductionCutsTable::GetProductionCutsTable();
G4int tCoupleIdx
= tCutsTbl->GetCoupleIndex(fPreStepPoint->GetMaterialCutsCouple());
if (tCoupleIdx<0) { return; }
G4double tProdThreshold
= (*(tCutsTbl->GetEnergyCutsVector(tPtclIdx)))[tCoupleIdx];
if( aSecondary->GetKineticEnergy()<tProdThreshold )
{
tBelowCutEnergyAndSafety = true;
if(std::abs(aSecondary->GetDynamicParticle()->GetCharge()) > DBL_MIN)
{
G4double currentRange
= G4LossTableManager::Instance()->GetRange(aSecondary->GetDefinition(),
aSecondary->GetKineticEnergy(),
fPreStepPoint->GetMaterialCutsCouple());
tBelowCutEnergyAndSafety = (currentRange < CalculateSafety() );
}
}
if( tBelowCutEnergyAndSafety )
{
if( !(aSecondary->IsGoodForTracking()) )
{
// Add kinetic energy to the total energy deposit
fStep->AddTotalEnergyDeposit( aSecondary->GetKineticEnergy() );
aSecondary->SetKineticEnergy(0.0);
}
}
}