Files
geant4/source/tracking/include/G4SteppingManager.icc
T
2016-06-08 15:34:16 +02:00

550 lines
20 KiB
Plaintext

// This code implementation is the intellectual property of
// the GEANT4 collaboration.
//
// By copying, distributing or modifying the Program (or any work
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4SteppingManager.icc,v 1.4 1999/12/15 14:53:57 gunter Exp $
// GEANT4 tag $Name: geant4-01-01 $
//
//
//---------------------------------------------------------------
//
// G4SteppingManager.icc
//
// Description:
// This class represents the manager who steers to move the give
// particle from the TrackingManger by one Step.
//
// 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)
//
//---------------------------------------------------------------
#include "G4UImanager.hh"
#include "G4ForceCondition.hh"
#include "G4GPILSelection.hh"
#include "G4SteppingControl.hh"
#include "G4TransportationManager.hh"
#include "G4UserLimits.hh"
#include "G4EnergyLossTables.hh"
/////////////////////////////////////////////////
inline void G4SteppingManager::GetProcessNumber()
/////////////////////////////////////////////////
{
G4ProcessManager* pm= fTrack->GetDefinition()->GetProcessManager();
// AtRestDoits
MAXofAtRestLoops = pm->GetAtRestProcessVector()->entries();
fAtRestDoItVector = pm->GetAtRestProcessVector(typeDoIt);
fAtRestGetPhysIntVector = pm->GetAtRestProcessVector(typeGPIL);
// AlongStepDoits
MAXofAlongStepLoops = pm->GetAlongStepProcessVector()->entries();
fAlongStepDoItVector = pm->GetAlongStepProcessVector(typeDoIt);
fAlongStepGetPhysIntVector = pm->GetAlongStepProcessVector(typeGPIL);
// PostStepDoits
MAXofPostStepLoops = pm->GetPostStepProcessVector()->entries();
fPostStepDoItVector = pm->GetPostStepProcessVector(typeDoIt);
fPostStepGetPhysIntVector = pm->GetPostStepProcessVector(typeGPIL);
}
// ************************************************************************
//
// Private Member Functions
//
// ************************************************************************
/////////////////////////////////////////////////////////
inline 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
// !!!!! Verbose
if(verboseLevel>0) fVerbose->DPSLStarted();
#endif
// Obtain the user defined maximum allowed Step in the volume
// 1997.12.13 adds argument for GetMaxAllowedStep by K.Kurashige
G4UserLimits* ul= fCurrentVolume->GetLogicalVolume()->GetUserLimits();
if (ul) {
physIntLength = ul->GetMaxAllowedStep(*fTrack);
#ifdef G4VERBOSE
// !!!!! Verbose
if(verboseLevel>0) fVerbose->DPSLUserLimit();
#endif
}
if(physIntLength < PhysicalStep ){
PhysicalStep = physIntLength;
fStepStatus = fUserDefinedLimit;
fStep->GetPostStepPoint()
->SetProcessDefinedStep(NULL);
// Take note that the process pointer is 'NULL' if the Step
// is defined by the user defined limit.
}
// GetPhysicalInteractionLength for PostStep
fPostStepDoItProcTriggered = MAXofPostStepLoops;
for(size_t np=0; np < MAXofPostStepLoops; np++){
fCurrentProcess = (*fPostStepGetPhysIntVector)(np);
if (fCurrentProcess== NULL) {
(*fSelectedPostStepDoItVector)(np) = 0;
continue;
} // NULL means the process is inactivated by a user on fly.
physIntLength = fCurrentProcess->
PostStepGetPhysicalInteractionLength( *fTrack,
fPreviousStepSize,
&fCondition );
#ifdef G4VERBOSE
// !!!!! Verbose
if(verboseLevel>0) fVerbose->DPSLPostStep();
#endif
switch (fCondition) {
case ExclusivelyForced:
(*fSelectedPostStepDoItVector)(np) = 4;
fStepStatus = fExclusivelyForcedProc;
fStep->GetPostStepPoint()
->SetProcessDefinedStep(fCurrentProcess);
break;
case Conditionally:
(*fSelectedPostStepDoItVector)(np) = 3;
break;
case Forced:
(*fSelectedPostStepDoItVector)(np) = 2;
break;
default:
(*fSelectedPostStepDoItVector)(np) = 0;
if(physIntLength < PhysicalStep ){
PhysicalStep = physIntLength;
fStepStatus = fPostStepDoItProc;
fPostStepDoItProcTriggered = G4int(np);
fStep->GetPostStepPoint()
->SetProcessDefinedStep(fCurrentProcess);
}
}
if (fCondition==ExclusivelyForced) return; // Take note the 'return' at here !!!
}
if(fPostStepDoItProcTriggered<MAXofPostStepLoops)
(*fSelectedPostStepDoItVector)(fPostStepDoItProcTriggered) = 1;
// GetPhysicalInteractionLength for AlongStep
proposedSafety = DBL_MAX;
G4double safetyProposedToAndByProcess = proposedSafety;
for(size_t kp=0; kp < MAXofAlongStepLoops; kp++){
fCurrentProcess = (*fAlongStepGetPhysIntVector)(kp);
if (fCurrentProcess== NULL) continue;
// NULL means the process is inactivated by a user on fly.
physIntLength = fCurrentProcess->
AlongStepGetPhysicalInteractionLength( *fTrack,
fPreviousStepSize,
PhysicalStep,
safetyProposedToAndByProcess,
&fGPILSelection );
#ifdef G4VERBOSE
// !!!!! Verbose
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);
}
// Transportation is assumed to be the last process in the vector
if(kp == MAXofAlongStepLoops-1) fStepStatus = fGeomBoundary;
}
// Make sure to check the safety, even if Step is not limited
// by this process. J. Apostolakis, June 20, 1998
//
if (safetyProposedToAndByProcess < proposedSafety)
// proposedSafety keeps the smallest value:
proposedSafety = safetyProposedToAndByProcess;
else
// safetyProposedToAndByProcess always proposes a valid safety:
safetyProposedToAndByProcess = proposedSafety;
}
} // void G4SteppingManager::DefinePhysicalStepLength() //
//////////////////////////////////////////////////////
inline void G4SteppingManager::InvokeAtRestDoItProcs()
//////////////////////////////////////////////////////
{
// Select the rest process which has the shortest time before
// it is invoked. In rest processes, GetPhysicalInteractionLength()
// returns the time before a process occurs.
G4double lifeTime, shortestLifeTime;
fN2ndariesAtRestDoIt = 0;
shortestLifeTime = DBL_MAX;
for( size_t ri=0 ; ri < MAXofAtRestLoops ; ri++ ){
fCurrentProcess = (*fAtRestGetPhysIntVector)(ri);
if (fCurrentProcess== NULL) {
(*fSelectedAtRestDoItVector)(ri) = 0;
continue;
} // NULL means the process is inactivated by a user on fly.
lifeTime =
fCurrentProcess->AtRestGetPhysicalInteractionLength(
*fTrack,
&fCondition );
if(fCondition==Forced){
(*fSelectedAtRestDoItVector)(ri) = 2;
}
else{
(*fSelectedAtRestDoItVector)(ri) = 0;
if(lifeTime < shortestLifeTime ){
shortestLifeTime = lifeTime;
fAtRestDoItProcTriggered = G4int(int(ri));
}
}
}
(*fSelectedAtRestDoItVector)(fAtRestDoItProcTriggered) = 1;
fStep->SetStepLength( 0. ); //the particle has stopped
fTrack->SetStepLength( 0. );
// invoke selected process
for(size_t np=0; np < MAXofAtRestLoops; np++){
//
// Note: DoItVector has inverse order against GetPhysIntVector
// and SelectedAtRestDoItVector.
//
if((*fSelectedAtRestDoItVector)(MAXofAtRestLoops-np-1) != 0){
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;
G4bool tApplyCutFlag;
G4double tProdThreshold;
G4Material* tMaterial;
G4double tBelowCutEnergyAndSafety;
fN2ndariesAtRestDoIt = fParticleChange->GetNumberOfSecondaries();
for(G4int DSecLoop=0 ; DSecLoop< fN2ndariesAtRestDoIt; DSecLoop++){
tempSecondaryTrack = fParticleChange->GetSecondary(DSecLoop);
tApplyCutFlag = tempSecondaryTrack->GetDefinition()
->GetApplyCutsFlag();
// Check if the particle should be passed without coherent cut
if(tApplyCutFlag){
tBelowCutEnergyAndSafety = false;
tMaterial = fPostStepPoint->GetMaterial();
tProdThreshold = tempSecondaryTrack->GetDefinition()
-> GetEnergyThreshold(tMaterial);
if( tempSecondaryTrack->GetKineticEnergy()<tProdThreshold ){
G4double currentRange
= G4EnergyLossTables::GetRange(
tempSecondaryTrack->GetDefinition(),
tempSecondaryTrack->GetKineticEnergy(),
tMaterial
);
if (currentRange < CalculateSafety() ){
tBelowCutEnergyAndSafety = true;
}
}
if( tBelowCutEnergyAndSafety ){
if( !(tempSecondaryTrack->IsGoodForTracking()) ){
//// G4cout << "!! Warning - G4SteppingManager:" << G4endl;
//// << " This physics process generated a secondary"
//// << " of which energy is below cut but"
//// << " GoodForTracking is off !!!!!" << G4endl;
// Add kinetic energy to the total energy deposit
fStep->AddTotalEnergyDeposit(
tempSecondaryTrack->GetKineticEnergy() );
tempSecondaryTrack->SetKineticEnergy(0.0);
}
}
}
// If this 2ndry particle has 'zero' kinetic energy, make sure
// it invokes a rest process at the beginning of the tracking
if(tempSecondaryTrack->GetKineticEnergy() <= 0.){
tempSecondaryTrack->SetTrackStatus( fStopButAlive );
}
// Set parentID
tempSecondaryTrack->SetParentID( fTrack->GetTrackID() );
// Set the process pointer which created this track
tempSecondaryTrack->SetCreatorProcess( fCurrentProcess );
fSecondary->insert( tempSecondaryTrack );
}
// clear ParticleChange
fParticleChange->Clear();
} //if(fSelectedAtRestDoItVector(np) != 0){
} //for(size_t np=0; np < MAXofAtRestLoops; np++){
fStep->UpdateTrack();
fTrack->SetTrackStatus( fStopAndKill );
}
/////////////////////////////////////////////////////////
inline 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' at here !!!
}
// Invoke the all active continuous processes
fN2ndariesAlongStepDoIt = 0;
for( size_t ci=0 ; ci<MAXofAlongStepLoops ; ci++ ){
fCurrentProcess = (*fAlongStepDoItVector)(ci);
if (fCurrentProcess== NULL) 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
// !!!!! Verbose
if(verboseLevel>0) fVerbose->AlongStepDoItOneByOne();
#endif
// Now Store the secondaries from ParticleChange to SecondaryList
G4Track* tempSecondaryTrack;
G4bool tApplyCutFlag;
G4double tProdThreshold;
G4Material* tMaterial;
G4double tBelowCutEnergyAndSafety;
fN2ndariesAlongStepDoIt = fParticleChange->GetNumberOfSecondaries();
for(G4int DSecLoop=0 ; DSecLoop< fN2ndariesAlongStepDoIt; DSecLoop++){
tempSecondaryTrack = fParticleChange->GetSecondary(DSecLoop);
tApplyCutFlag = tempSecondaryTrack->GetDefinition()
->GetApplyCutsFlag();
// Check if the particle should be passed without coherent cut
if(tApplyCutFlag){
tBelowCutEnergyAndSafety = false;
tMaterial = fPostStepPoint->GetMaterial();
tProdThreshold = tempSecondaryTrack->GetDefinition()
-> GetEnergyThreshold(tMaterial);
if( tempSecondaryTrack->GetKineticEnergy()<tProdThreshold ){
G4double currentRange
= G4EnergyLossTables::GetRange(
tempSecondaryTrack->GetDefinition(),
tempSecondaryTrack->GetKineticEnergy(),
tMaterial
);
if (currentRange < CalculateSafety() ){
tBelowCutEnergyAndSafety = true;
}
}
if( tBelowCutEnergyAndSafety ){
if( !(tempSecondaryTrack->IsGoodForTracking()) ){
//// G4cout << "!! Warning - G4SteppingManager:" << G4endl;
//// << " This physics process generated a secondary"
//// << " of which energy is below cut but"
//// << " GoodForTracking is off !!!!!" << G4endl;
// Add kinetic energy to the total energy deposit
fStep->AddTotalEnergyDeposit(
tempSecondaryTrack->GetKineticEnergy() );
tempSecondaryTrack->SetKineticEnergy(0.0);
}
}
}
// If this 2ndry particle has 'zero' kinetic energy, make sure
// it invokes a rest process at the beginning of the tracking
if(tempSecondaryTrack->GetKineticEnergy() <= 0.){
tempSecondaryTrack->SetTrackStatus( fStopButAlive );
}
// Set parentID
tempSecondaryTrack->SetParentID( fTrack->GetTrackID() );
// Set the process pointer which created this track
tempSecondaryTrack->SetCreatorProcess( fCurrentProcess );
fSecondary->insert( tempSecondaryTrack );
}
// Set the track status according to what the process defined
fTrack->SetTrackStatus( fParticleChange->GetStatusChange() );
// clear ParticleChange
fParticleChange->Clear();
}
}
////////////////////////////////////////////////////////
inline void G4SteppingManager::InvokePostStepDoItProcs()
////////////////////////////////////////////////////////
{
// Invoke the specified discrete processes
fN2ndariesPostStepDoIt = 0;
for(size_t np=0; np < MAXofPostStepLoops; np++){
//
// Note: DoItVector has inverse order against GetPhysIntVector
// and SelectedPostStepDoItVector.
//
size_t npGPIL = MAXofPostStepLoops-np-1;
G4int tmp= (*fSelectedPostStepDoItVector)(npGPIL);
if(tmp != 0){
if ( ((tmp == 1) && (fStepStatus == fPostStepDoItProc)) ||
((tmp == 2) && (fStepStatus != fExclusivelyForcedProc)) ||
((tmp == 3) && (fStepStatus == fAlongStepDoItProc)) ||
((tmp == 4) && (fStepStatus == fExclusivelyForcedProc)) ) {
fCurrentProcess = (*fPostStepDoItVector)(np);
fParticleChange
= fCurrentProcess->PostStepDoIt( *fTrack, *fStep);
// Update PostStepPoint of Step according to ParticleChange
fParticleChange->UpdateStepForPostStep(fStep);
#ifdef G4VERBOSE
// !!!!! Verbose
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;
G4bool tApplyCutFlag;
G4double tProdThreshold;
G4Material* tMaterial;
G4double tBelowCutEnergyAndSafety;
fN2ndariesPostStepDoIt = fParticleChange->GetNumberOfSecondaries();
for(G4int DSecLoop=0 ; DSecLoop< fN2ndariesPostStepDoIt; DSecLoop++){
tempSecondaryTrack = fParticleChange->GetSecondary(DSecLoop);
tApplyCutFlag = tempSecondaryTrack->GetDefinition()
->GetApplyCutsFlag();
// Check if the particle should be passed without coherent cut
if(tApplyCutFlag){
tBelowCutEnergyAndSafety = false;
tMaterial = fPostStepPoint->GetMaterial();
tProdThreshold = tempSecondaryTrack->GetDefinition()
-> GetEnergyThreshold(tMaterial);
if( tempSecondaryTrack->GetKineticEnergy()<tProdThreshold ){
G4double currentRange
= G4EnergyLossTables::GetRange(
tempSecondaryTrack->GetDefinition(),
tempSecondaryTrack->GetKineticEnergy(),
tMaterial
);
if (currentRange < CalculateSafety() ){
tBelowCutEnergyAndSafety = true;
}
}
if( tBelowCutEnergyAndSafety ){
if( !(tempSecondaryTrack->IsGoodForTracking()) ){
//// G4cout << "!! Warning - G4SteppingManager:" << G4endl;
//// << " This physics process generated a secondary"
//// << " of which energy is below cut but"
//// << " GoodForTracking is off !!!!!" << G4endl;
// Add kinetic energy to the total energy deposit
fStep->AddTotalEnergyDeposit(
tempSecondaryTrack->GetKineticEnergy() );
tempSecondaryTrack->SetKineticEnergy(0.0);
}
}
}
// If this 2ndry particle has 'zero' kinetic energy, make sure
// it invokes a rest process at the beginning of the tracking
if(tempSecondaryTrack->GetKineticEnergy() <= 0.){
tempSecondaryTrack->SetTrackStatus( fStopButAlive );
}
// Set parentID
tempSecondaryTrack->SetParentID( fTrack->GetTrackID() );
// Set the process pointer which created this track
tempSecondaryTrack->SetCreatorProcess( fCurrentProcess );
fSecondary->insert( tempSecondaryTrack );
}
// Set the track status according to what the process defined
fTrack->SetTrackStatus( fParticleChange->GetStatusChange() );
// clear ParticleChange
fParticleChange->Clear();
}
} //if(*fSelectedPostStepDoItVector(np) != 0){
// Exit from PostStepLoop if the track has been killed
if(fTrack->GetTrackStatus() == fStopAndKill) break;
} //for(size_t np=0; np < MAXofPostStepLoops; np++){
}