Comments below aim at developing an external Optical Photon Propagation Stategy
source/event/include/G4StackManager.hh:
049 // class description:
050 //
051 // This is the manager class of handling stacks of G4Track objects.
052 // This class must be a singleton and be constructed by G4EventManager.
053 // Almost all methods must be invoked exclusively by G4EventManager.
054 // Especially, some Clear() methods MUST NOT be invoked by the user.
055 // Event abortion is handled by G4EventManager.
056 //
057 // This G4StackingManager has three stacks, the urgent stack, the
058 // waiting stack, and the postpone to next event stack. The meanings
059 // of each stack is descrived in the Geant4 user's manual.
060 //
061
062 class G4StackManager
063 {
064 public:
065 G4StackManager();
066 ~G4StackManager();
067
068 private:
069 const G4StackManager& operator=(const G4StackManager &right);
070 G4int operator==(const G4StackManager &right) const;
071 G4int operator!=(const G4StackManager &right) const;
072
073 public:
074 G4int PushOneTrack(G4Track *newTrack, G4VTrajectory *newTrajectory = 0);
075 G4Track * PopNextTrack(G4VTrajectory**newTrajectory);
076 G4int PrepareNewEvent();
077
078 public: // with description
079 void ReClassify();
080 // Send all tracks stored in the Urgent stack one by one to
081 // the user's concrete ClassifyNewTrack() method. This method
082 // can be invoked from the user's G4UserStackingAction concrete
083 // class, especially fron its NewStage() method. Be aware that
084 // when the urgent stack becomes empty, all tracks in the waiting
085 // stack are send to the urgent stack and then the user's NewStage()
086 // method is invoked.
087
088 void SetNumberOfAdditionalWaitingStacks(G4int iAdd);
089 // Set the number of additional (optional) waiting stacks.
090 // This method must be invoked at PreInit, Init or Idle states.
091 // Once the user set the number of additional waiting stacks,
092 // he/she can use the corresponding ENUM in G4ClassificationOfNewTrack.
093 // The user should invoke G4RunManager::SetNumberOfAdditionalWaitingStacks
094 // method, which invokes this method.
095
096 void TransferStackedTracks(G4ClassificationOfNewTrack origin, G4ClassificationOfNewTrack destination);
097 // Transfter all stacked tracks from the origin stack to the destination stack.
098 // The destination stack needs not be empty.
099 // If the destination is fKill, tracks are deleted.
100 // If the origin is fKill, nothing happen.
101
102 void TransferOneStackedTrack(G4ClassificationOfNewTrack origin, G4ClassificationOfNewTrack destination);
103 // Transfter one stacked track from the origin stack to the destination stack.
104 // The transfered track is the one which came last to the origin stack.
105 // The destination stack needs not be empty.
106 // If the destination is fKill, the track is deleted.
107 // If the origin is fKill, nothing happen.
108
109 private:
110 G4UserStackingAction * userStackingAction;
111 G4int verboseLevel;
112 #ifdef G4_USESMARTSTACK
113 G4SmartTrackStack * urgentStack;
114 #else
115 G4TrackStack * urgentStack;
116 #endif
117 G4TrackStack * waitingStack;
118 G4TrackStack * postponeStack;
119 G4StackingMessenger* theMessenger;
120 std::vector<G4TrackStack*> additionalWaitingStacks;
121 G4int numberOfAdditionalWaitingStacks;
122
123 public:
124 void clear();
125 void ClearUrgentStack();
126 void ClearWaitingStack(int i=0);
127 void ClearPostponeStack();
128 G4int GetNTotalTrack() const;
129 G4int GetNUrgentTrack() const;
130 G4int GetNWaitingTrack(int i=0) const;
131 G4int GetNPostponedTrack() const;
132 void SetVerboseLevel( G4int const value );
133 void SetUserStackingAction(G4UserStackingAction* value);
134
135 private:
136 G4ClassificationOfNewTrack DefaultClassification(G4Track *aTrack);
137 };
138
139 #endif
source/event/src/G4StackManager.cc:
39 G4StackManager::G4StackManager()
40 :userStackingAction(0),verboseLevel(0),numberOfAdditionalWaitingStacks(0)
41 {
42 theMessenger = new G4StackingMessenger(this);
43 #ifdef G4_USESMARTSTACK
44 urgentStack = new G4SmartTrackStack;
45 // G4cout<<"+++ G4StackManager uses G4SmartTrackStack. +++"<<G4endl;
46 #else
47 urgentStack = new G4TrackStack(5000);
48 // G4cout<<"+++ G4StackManager uses ordinary G4TrackStack. +++"<<G4endl;
49 #endif
50 waitingStack = new G4TrackStack(1000);
51 postponeStack = new G4TrackStack(1000);
52 }
..
45 // This is a stack class used by G4StackManager. This class object
46 // stores G4StackedTrack class objects in the form of bi-directional
47 // linked list.
48
49 class G4TrackStack : public std::vector<G4StackedTrack>
50 {
51 public:
52 G4TrackStack() : safetyValve1(0), safetyValve2(0), nstick(0) {}
53 G4TrackStack(size_t n) : safetyValve1(4*n/5), safetyValve2(4*n/5-100), nstick(100) { reserve(n);}
54 ~G4TrackStack();
55
source/event/include/G4StackedTrack.hh:
41 //
42 // This class is exclusively used by G4StackManager and G4TrackStack
43 // classes for storing a G4Track object.
44
45 class G4StackedTrack
46 {
47 public:
48 G4StackedTrack() : track(0), trajectory(0) {}
49 G4StackedTrack(G4Track* aTrack, G4VTrajectory* aTraj = 0) : track(aTrack), trajectory(aTraj) {}
50 ~G4StackedTrack() {}
51
52 private:
53 G4Track* track;
54 G4VTrajectory* trajectory;
55
56 public:
57 G4Track* GetTrack() const { return track; }
58 G4VTrajectory* GetTrajectory() const { return trajectory; }
59 };
60
61 #endif
source/track/include/G4Track.hh:
072 //////////////
073 class G4Track
074 //////////////
075 {
076
077 //--------
078 public: // With description
079
080 // Constructor
081 G4Track();
082 G4Track(G4DynamicParticle* apValueDynamicParticle,
083 G4double aValueTime,
084 const G4ThreeVector& aValuePosition);
085 // aValueTime is a global time
086 G4Track(const G4Track&);
087 // Copy Constructor copys members other than tracking information
088
...
114 G4int GetTrackID() const;
115 void SetTrackID(const G4int aValue);
116
117 G4int GetParentID() const;
118 void SetParentID(const G4int aValue);
119
120 // dynamic particle
121 const G4DynamicParticle* GetDynamicParticle() const;
source/track/src/G4Track.cc:
094 //////////////////
095 G4Track::G4Track()
096 //////////////////
097 : fCurrentStepNumber(0),
098 fGlobalTime(0), fLocalTime(0.),
099 fTrackLength(0.),
100 fParentID(0), fTrackID(0),
101 fVelocity(c_light),
102 fpDynamicParticle(0),
103 fTrackStatus(fAlive),
104 fBelowThreshold(false), fGoodForTracking(false),
105 fStepLength(0.0), fWeight(1.0),
106 fpStep(0),
107 fVtxKineticEnergy(0.0),
108 fpLVAtVertex(0), fpCreatorProcess(0),
109 fCreatorModelIndex(-1),
110 fpUserInformation(0),
111 prev_mat(0), groupvel(0),
112 prev_velocity(0.0), prev_momentum(0.0),
113 is_OpticalPhoton(false),
114 useGivenVelocity(false)
115 {
116 }
/// default ctor : not so fat
source/particles/management/include/G4DynamicParticle.hh:
73 class G4DynamicParticle
74 {
75 // Class Description
76 // The dynamic particle is a class which contains the purely
77 // dynamic aspects of a moving particle. It also has a
78 // pointer to a G4ParticleDefinition object, which holds
79 // all the static information.
80 //
92 G4int G4StackManager::PushOneTrack(G4Track *newTrack,G4VTrajectory *newTrajectory)
93 {
...
166 G4ClassificationOfNewTrack classification = DefaultClassification( newTrack );
167 if(userStackingAction)
168 { classification = userStackingAction->ClassifyNewTrack( newTrack ); }
/// Maybe could in ClassifyNewTrack:
///
/// * collect OP trackinfo into ChromaPhotonList
/// * delete the OP track, set pointer to NULL (hmm its called `const G4Track*`, maybe need some patching)
/// [this would avoid pointlessly holding large memory expensive stacks of OPs ]
/// * return fWaiting for OPs
///
169
170 if(classification==fKill) // delete newTrack without stacking
171 {
...
180 delete newTrack;
181 delete newTrajectory;
182 }
183 else
184 {
185 G4StackedTrack newStackedTrack( newTrack, newTrajectory );
186 switch (classification)
187 {
188 case fUrgent:
189 urgentStack->PushToStack( newStackedTrack );
190 break;
191 case fWaiting:
192 waitingStack->PushToStack( newStackedTrack );
/// newTrack could be NULL here without harm
193 break;
194 case fPostpone:
195 postponeStack->PushToStack( newStackedTrack );
196 break;
197 default:
198 G4int i = classification - 10;
199 if(i<1||i>numberOfAdditionalWaitingStacks) {
200 G4ExceptionDescription ED;
201 ED << "invalid classification " << classification << G4endl;
202 G4Exception("G4StackManager::PushOneTrack","Event0051",
203 FatalException,ED);
204 } else {
205 additionalWaitingStacks[i-1]->PushToStack( newStackedTrack );
206 }
207 break;
208 }
209 }
210
211 return GetNUrgentTrack();
212 }
At NewStage:
Thus within NewStage for interesting events:
Maybe:
084 // when the urgent stack becomes empty, all tracks in the waiting
085 // stack are send to the urgent stack and then the user's NewStage()
086 // method is invoked.
pops from urgent until thats empty
then waiting stack transferred to urgent
additional waiting stacks are shunted to one higher priority notch
userStackingAction::NewStage then gives opportunity to
- ReClassify OR clear
- the ReClassify calls ClassifyNewTrack for each track that has been waiting
215 G4Track * G4StackManager::PopNextTrack(G4VTrajectory**newTrajectory)
216 {
225 while( GetNUrgentTrack() == 0 )
226 {
...
231 waitingStack->TransferTo(urgentStack);
232 if(numberOfAdditionalWaitingStacks>0) {
233 for(int i=0;i<numberOfAdditionalWaitingStacks;i++) {
234 if(i==0) {
235 additionalWaitingStacks[0]->TransferTo(waitingStack);
236 } else {
237 additionalWaitingStacks[i]->TransferTo(additionalWaitingStacks[i-1]);
238 }
239 }
240 }
241 if(userStackingAction) userStackingAction->NewStage();
...
247 if( ( GetNUrgentTrack()==0 ) && ( GetNWaitingTrack()==0 ) ) return 0;
248 }
249
250 G4StackedTrack selectedStackedTrack = urgentStack->PopFromStack();
251 G4Track * selectedTrack = selectedStackedTrack.GetTrack();
252 *newTrajectory = selectedStackedTrack.GetTrajectory();
...
265 return selectedTrack;
266 }
268 void G4StackManager::ReClassify()
269 {
270 G4StackedTrack aStackedTrack;
271 G4TrackStack tmpStack;
272
273 if( !userStackingAction ) return;
274 if( GetNUrgentTrack() == 0 ) return;
275
276 urgentStack->TransferTo(&tmpStack);
277 while( tmpStack.GetNTrack() > 0 )
278 {
279 aStackedTrack=tmpStack.PopFromStack();
280 G4ClassificationOfNewTrack classification =
281 userStackingAction->ClassifyNewTrack( aStackedTrack.GetTrack() );
282 switch (classification)
283 {
284 case fKill:
285 delete aStackedTrack.GetTrack();
286 delete aStackedTrack.GetTrajectory();
287 break;
288 case fUrgent:
289 urgentStack->PushToStack( aStackedTrack );
290 break;
291 case fWaiting:
292 waitingStack->PushToStack( aStackedTrack );
293 break;
294 case fPostpone:
295 postponeStack->PushToStack( aStackedTrack );
296 break;
297 default:
298 G4int i = classification - 10;
299 if(i<1||i>numberOfAdditionalWaitingStacks) {
300 G4ExceptionDescription ED;
301 ED << "invalid classification " << classification << G4endl;
302 G4Exception("G4StackManager::ReClassify","Event0052",
303 FatalException,ED);
304 } else {
305 additionalWaitingStacks[i-1]->PushToStack( aStackedTrack );
306 }
307 break;
308 }
309 }
310 }
312 G4int G4StackManager::PrepareNewEvent()
313 {
314 if(userStackingAction) userStackingAction->PrepareNewEvent();
315
316 urgentStack->clearAndDestroy(); // Set the urgentStack in a defined state. Not doing it would affect reproducibility.
317
318 G4int n_passedFromPrevious = 0;
319
320 if( GetNPostponedTrack() > 0 )
321 {
...
379 }
380
381 return n_passedFromPrevious;
382 }