4 // See the class description in the header file.
6 #include "TG4StepManager.h"
7 #include "TG4GeometryServices.h"
8 #include "TG4ParticlesManager.h"
9 #include "TG4PhysicsManager.h"
10 #include "TG4VSensitiveDetector.h"
11 #include "TG4Limits.h"
12 #include "TG4Globals.h"
13 #include "TG4G3Units.h"
15 #include <G4SteppingManager.hh>
16 #include <G4UserLimits.hh>
17 #include <G4UImanager.hh>
18 #include <G4AffineTransform.hh>
19 #include <G4TransportationManager.hh>
20 #include <G4Navigator.hh>
21 #include <G4VProcess.hh>
22 #include <G4ProcessManager.hh>
23 #include <G4ProcessVector.hh>
25 #include <Randomize.hh>
26 #include <TLorentzVector.h>
28 TG4StepManager* TG4StepManager::fgInstance = 0;
30 TG4StepManager::TG4StepManager()
33 fStepStatus(kNormalStep),
38 TG4Globals::Exception(
39 "TG4StepManager: attempt to create two instances of singleton.");
45 TG4StepManager::TG4StepManager(const TG4StepManager& right) {
47 TG4Globals::Exception(
48 "Attempt to copy TG4StepManager singleton.");
51 TG4StepManager::~TG4StepManager() {
57 TG4StepManager& TG4StepManager::operator=(const TG4StepManager& right)
59 // check assignement to self
60 if (this == &right) return *this;
62 TG4Globals::Exception(
63 "Attempt to assign TG4StepManager singleton.");
70 void TG4StepManager::CheckTrack() const
72 // Gives exception in case the track is not defined.
76 TG4Globals::Exception("TG4StepManager: Track is not defined.");
80 void TG4StepManager::CheckStep(const G4String& method) const
82 // Gives exception in case the step is not defined.
86 G4String text = "TG4StepManager::";
87 text = text + method + ": Step is not defined.";
88 TG4Globals::Exception(text);
93 void TG4StepManager::CheckSteppingManager() const
95 // Gives exception in case the step is not defined.
98 if (!fSteppingManager)
99 TG4Globals::Exception("TG4StepManager: Stepping manager is not defined.");
103 void TG4StepManager::SetTLorentzVector(G4ThreeVector xyz, G4double t,
104 TLorentzVector& lv) const
106 // Fills TLorentzVector with G4ThreeVector and G4double.
115 G4VPhysicalVolume* TG4StepManager::GetCurrentOffPhysicalVolume(G4int off) const
117 // Returns the physical volume of the off-th mother's
118 // of the current volume.
121 G4VPhysicalVolume* physVolume = GetCurrentPhysicalVolume();
123 G4VPhysicalVolume* mother = physVolume;
127 if (mother) mother = mother->GetMother();
132 G4String text = "TG4StepManager::CurrentVolOff: \n";
133 text = text + " Volume ";
134 text = text + physVolume->GetName();
135 text = text + " has not defined mother in the required level.";
136 TG4Globals::Warning(text);
144 void TG4StepManager::StopTrack()
146 // Stops the current track and skips to the next.
147 // ?? do we want to invoke rest processes?
148 // ?? do we want to stop secondaries too?
149 // possible "stop" track status from G4:
150 // fStopButAlive, // Invoke active rest physics processes and
151 // // and kill the current track afterward
152 // fStopAndKill, // Kill the current track
153 // fKillTrackAndSecondaries,
154 // // Kill the current track and also associated
162 fTrack->SetTrackStatus(fStopAndKill);
163 // fTrack->SetTrackStatus(fStopButAlive);
164 // fTrack->SetTrackStatus(fKillTrackAndSecondaries);
167 void TG4StepManager::StopEvent()
169 // Aborts the current event processing.
176 fTrack->SetTrackStatus(fKillTrackAndSecondaries);
177 //StopTrack(); // cannot be used as it keeps secondaries
178 G4UImanager::GetUIpointer()->ApplyCommand("/event/abort");
179 G4UImanager::GetUIpointer()->ApplyCommand("/alStacking/clearStack");
182 void TG4StepManager::SetMaxStep(Float_t step)
184 // Maximum step allowed in the current logical volume.
187 G4LogicalVolume* curLogVolume
188 = GetCurrentPhysicalVolume()->GetLogicalVolume();
189 G4UserLimits* userLimits
190 = curLogVolume->GetUserLimits();
192 if (userLimits == 0) {
194 userLimits = new TG4Limits();
196 // set limits to all logical volumes
197 // corresponding to the current "G3" volume
198 TG4GeometryServices* geometryServices = TG4GeometryServices::Instance();
199 G4int nofLV = geometryServices->SetUserLimits(userLimits, curLogVolume);
203 userLimits->SetMaxAllowedStep(step*TG4G3Units::Length());
206 void TG4StepManager::SetMaxNStep(Int_t maxNofSteps)
208 // Not yet implemented.
212 "TG4StepManager::SetMaxNStep(..) is not yet implemented.");
215 void TG4StepManager::SetUserDecay(Int_t pdg)
217 // Not yet implemented.
220 TG4Globals::Exception(
221 "TG4StepManager::SetUserDecay(..) is not yet implemented.");
224 G4VPhysicalVolume* TG4StepManager::GetCurrentPhysicalVolume() const
226 // Returns the current physical volume.
227 // According to fStepStatus the volume from track vertex,
228 // pre step point or post step point is returned.
231 G4VPhysicalVolume* physVolume;
232 if (fStepStatus == kNormalStep) {
235 CheckStep("GetCurrentPhysicalVolume");
238 physVolume = fStep->GetPreStepPoint()->GetPhysicalVolume();
240 else if (fStepStatus == kBoundary) {
243 CheckStep("GetCurrentPhysicalVolume");
246 physVolume = fStep->GetPostStepPoint()->GetPhysicalVolume();
254 G4ThreeVector position = fTrack->GetPosition();
255 G4Navigator* navigator =
256 G4TransportationManager::GetTransportationManager()->
257 GetNavigatorForTracking();
259 = navigator->LocateGlobalPointAndSetup(position);
265 Int_t TG4StepManager::CurrentVolID(Int_t& copyNo) const
267 // Returns the current sensitive detector ID
268 // and the copy number of the current physical volume.
271 G4VPhysicalVolume* physVolume = GetCurrentPhysicalVolume();
272 copyNo = physVolume->GetCopyNo() + 1;
274 // sensitive detector ID
275 TG4GeometryServices* geometryServices = TG4GeometryServices::Instance();
276 return geometryServices->GetVolumeID(physVolume->GetLogicalVolume());
279 Int_t TG4StepManager::CurrentVolOffID(Int_t off, Int_t& copyNo) const
281 // Returns the off-th mother's of the current volume
282 // the sensitive detector ID and the copy number.
285 if (off == 0) return CurrentVolID(copyNo);
287 G4VPhysicalVolume* mother = GetCurrentOffPhysicalVolume(off);
290 copyNo = mother->GetCopyNo() + 1;
292 // sensitive detector ID
293 TG4GeometryServices* geometryServices = TG4GeometryServices::Instance();
294 return geometryServices->GetVolumeID(mother->GetLogicalVolume());
302 const char* TG4StepManager::CurrentVolName() const
304 // Returns the current physical volume name.
307 return GetCurrentPhysicalVolume()->GetName();
310 const char* TG4StepManager::CurrentVolOffName(Int_t off) const
312 // Returns the off-th mother's physical volume name.
315 if (off == 0) return CurrentVolName();
317 G4VPhysicalVolume* mother = GetCurrentOffPhysicalVolume(off);
320 return mother->GetName();
325 Int_t TG4StepManager::CurrentMaterial(Float_t &a, Float_t &z, Float_t &dens,
326 Float_t &radl, Float_t &absl) const
328 // Returns the parameters of the current material during transport
329 // the return value is the number of elements in the mixture.
332 G4VPhysicalVolume* physVolume = GetCurrentPhysicalVolume();
335 = physVolume->GetLogicalVolume()->GetMaterial();
338 G4int nofElements = material->GetNumberOfElements();
339 TG4GeometryServices* geometryServices = TG4GeometryServices::Instance();
340 a = geometryServices->GetEffA(material);
341 z = geometryServices->GetEffZ(material);
344 dens = material->GetDensity();
345 dens /= TG4G3Units::MassDensity();
348 radl = material->GetRadlen();
349 radl /= TG4G3Units::Length();
351 absl = 0.; // this parameter is not defined in Geant4
355 TG4Globals::Exception(
356 "TG4StepManager::CurrentMaterial(..): material is not defined.");
361 void TG4StepManager::Gmtod(Float_t* xm, Float_t* xd, Int_t iflag)
363 // Transforms a position from the world reference frame
364 // to the current volume reference frame.
366 // Geant3 desription:
367 // ==================
368 // Computes coordinates XD (in DRS)
369 // from known coordinates XM in MRS
370 // The local reference system can be initialized by
371 // - the tracking routines and GMTOD used in GUSTEP
372 // - a call to GMEDIA(XM,NUMED)
373 // - a call to GLVOLU(NLEVEL,NAMES,NUMBER,IER)
374 // (inverse routine is GDTOM)
376 // If IFLAG=1 convert coordinates
377 // IFLAG=2 convert direction cosinus
381 G4AffineTransform affineTransform;
383 if (fStepStatus == kVertex) {
384 G4Navigator* navigator =
385 G4TransportationManager::GetTransportationManager()->
386 GetNavigatorForTracking();
388 affineTransform = navigator->GetGlobalToLocalTransform();
397 = fStep->GetPreStepPoint()->GetTouchable()->GetHistory()
401 G4ThreeVector theGlobalPoint(xm[0],xm[1],xm[2]);
402 G4ThreeVector theLocalPoint;
404 theLocalPoint = affineTransform.TransformPoint(theGlobalPoint);
405 else if ( iflag == 2)
406 theLocalPoint = affineTransform.TransformAxis(theGlobalPoint);
408 TG4Globals::Exception(
409 "TG4StepManager::Gmtod(..,iflag): iflag is not in 1..2");
411 xd[0] = theLocalPoint.x();
412 xd[1] = theLocalPoint.y();
413 xd[2] = theLocalPoint.z();
416 void TG4StepManager::Gdtom(Float_t* xd, Float_t* xm, Int_t iflag)
418 // Transforms a position from the current volume reference frame
419 // to the world reference frame.
421 // Geant3 desription:
422 // ==================
423 // Computes coordinates XM (Master Reference System
424 // knowing the coordinates XD (Detector Ref System)
425 // The local reference system can be initialized by
426 // - the tracking routines and GDTOM used in GUSTEP
427 // - a call to GSCMED(NLEVEL,NAMES,NUMBER)
428 // (inverse routine is GMTOD)
430 // If IFLAG=1 convert coordinates
431 // IFLAG=2 convert direction cosinus
435 G4AffineTransform affineTransform;
437 if (fStepStatus == kVertex) {
438 G4Navigator* navigator =
439 G4TransportationManager::GetTransportationManager()->
440 GetNavigatorForTracking();
442 affineTransform = navigator->GetLocalToGlobalTransform();
453 = fStep->GetPreStepPoint()->GetTouchable()->GetHistory()
454 ->GetTopTransform().Inverse();
457 G4ThreeVector theLocalPoint(xd[0],xd[1],xd[2]);
458 G4ThreeVector theGlobalPoint;
460 theGlobalPoint = affineTransform.TransformPoint(theLocalPoint);
462 theGlobalPoint = affineTransform.TransformAxis(theLocalPoint);
465 "TG4StepManager::Gdtom(...,iflag): iflag is not in 1..2");
467 xm[0] = theGlobalPoint.x();
468 xm[1] = theGlobalPoint.y();
469 xm[2] = theGlobalPoint.z();
472 Float_t TG4StepManager::MaxStep() const
474 // Returns maximum step allowed in the current logical volume
478 G4LogicalVolume* curLogVolume
479 = GetCurrentPhysicalVolume()->GetLogicalVolume();
482 G4UserLimits* userLimits
483 = curLogVolume->GetUserLimits();
486 if (userLimits == 0) {
487 G4String text = "User Limits are not defined for log volume ";
488 text = text + curLogVolume->GetName();
489 TG4Globals::Warning(text);
493 const G4Track& trackRef = *(fTrack);
494 maxStep = userLimits->GetMaxAllowedStep(trackRef);
495 maxStep /= TG4G3Units::Length();
500 Int_t TG4StepManager::GetMaxNStep() const
502 // Not yet implemented.
506 "Method GetMaxNStep is not yet implemented in TG4StepManager.");
510 void TG4StepManager::TrackPosition(TLorentzVector& position) const
512 // Current particle position (in the world reference frame)
513 // and the local time since the current track is created
514 // (position of the PostStepPoint).
522 // check if this is == to PostStepPoint position !!
523 G4ThreeVector positionVector = fTrack->GetPosition();
524 positionVector *= 1./(TG4G3Units::Length());
527 G4double time = fTrack->GetLocalTime();
528 time /= TG4G3Units::Time();
530 SetTLorentzVector(positionVector, time, position);
533 Int_t TG4StepManager::GetMedium() const
535 // Returns the second index of the current material (corresponding to
536 // G3 tracking medium index).
540 G4Material* curMaterial
541 = GetCurrentPhysicalVolume()->GetLogicalVolume()->GetMaterial();
544 TG4GeometryServices* geometryServices = TG4GeometryServices::Instance();
545 return geometryServices->GetMediumId(curMaterial);
548 void TG4StepManager::TrackMomentum(TLorentzVector& momentum) const
550 // Current particle "momentum" (px, py, pz, Etot).
557 G4ThreeVector momentumVector = fTrack->GetMomentum();
558 momentumVector *= 1./(TG4G3Units::Energy());
560 G4double energy = fTrack->GetDynamicParticle()->GetTotalEnergy();
561 energy /= TG4G3Units::Energy();
563 SetTLorentzVector(momentumVector, energy, momentum);
566 void TG4StepManager::TrackVertexPosition(TLorentzVector& position) const
568 // The vertex particle position (in the world reference frame)
569 // and the local time since the current track is created.
577 G4ThreeVector positionVector = fTrack->GetVertexPosition();
578 positionVector *= 1./(TG4G3Units::Length());
582 G4double time = fTrack->GetLocalTime();
583 time /= TG4G3Units::Time();
585 SetTLorentzVector(positionVector, time, position);
588 void TG4StepManager::TrackVertexMomentum(TLorentzVector& momentum) const
590 // The vertex particle "momentum" (px, py, pz, Ekin)
591 // to do: change Ekin -> Etot
598 G4ThreeVector momentumVector = fTrack->GetVertexMomentumDirection();
599 momentumVector *= 1./(TG4G3Units::Energy());
601 G4double energy = fTrack->GetVertexKineticEnergy();
602 energy /= TG4G3Units::Energy();
604 SetTLorentzVector(momentumVector, energy, momentum);
607 Float_t TG4StepManager::TrackStep() const
609 // Returns the current step length.
613 if (fStepStatus == kNormalStep) {
616 CheckStep("TrackStep");
619 length = fStep->GetStepLength();
620 length /= TG4G3Units::Length();
628 Float_t TG4StepManager::TrackLength() const
630 // Returns the length of the current track from its origin.
637 G4double length = fTrack->GetTrackLength();
638 length /= TG4G3Units::Length();
642 Float_t TG4StepManager::TrackTime() const
644 // Returns the local time since the current track is created.
646 // in Geant4: there is also defined proper time as
647 // the proper time of the dynamical particle of the current track.
654 G4double time = fTrack->GetLocalTime();
655 time /= TG4G3Units::Time();
659 Float_t TG4StepManager::Edep() const
661 // Returns total energy deposit in this step.
664 G4double energyDeposit;
665 if (fStepStatus == kNormalStep) {
671 energyDeposit = fStep->GetTotalEnergyDeposit();
672 energyDeposit /= TG4G3Units::Energy();
677 return energyDeposit;
680 Int_t TG4StepManager::TrackPid() const
682 // Returns the current particle PDG encoding.
689 G4ParticleDefinition* particle
690 = fTrack->GetDynamicParticle()->GetDefinition();
692 // ask TG4ParticlesManager to get PDG encoding
693 // (in order to get PDG from extended TDatabasePDG
694 // in case the standard PDG code is not defined)
696 = TG4ParticlesManager::Instance()->GetPDGEncodingFast(particle);
701 Float_t TG4StepManager::TrackCharge() const
703 // Returns the current particle charge.
711 = fTrack->GetDynamicParticle()->GetDefinition()
713 charge /= TG4G3Units::Charge();
717 Float_t TG4StepManager::TrackMass() const
719 // Returns current particle rest mass.
727 = fTrack->GetDynamicParticle()->GetDefinition()
729 mass /= TG4G3Units::Mass();
733 Float_t TG4StepManager::Etot() const
735 // Returns total energy of the current particle.
743 = fTrack->GetDynamicParticle()->GetTotalEnergy();
744 energy /= TG4G3Units::Energy();
748 Bool_t TG4StepManager::IsTrackInside() const
750 // Returns true if particle does not cross geometrical boundary
751 // and is not in vertex.
754 if (fStepStatus == kNormalStep && !(IsTrackExiting()) ) {
755 // track is always inside during a normal step
762 Bool_t TG4StepManager::IsTrackEntering() const
764 // Returns true if particle cross a geometrical boundary
768 if (fStepStatus != kNormalStep) {
769 // track is entering during a vertex or boundary step
776 Bool_t TG4StepManager::IsTrackExiting() const
778 // Returns true if particle cross a geometrical boundary.
781 if (fStepStatus == kNormalStep) {
784 CheckStep("IsTrackExiting");
787 if (fStep->GetPostStepPoint()->GetStepStatus() == fGeomBoundary)
794 Bool_t TG4StepManager::IsTrackOut() const
796 // Returns true if particle cross the world boundary
797 // at post-step point.
800 if (fStepStatus == kVertex) return false;
803 CheckStep("IsTrackCut");
808 = fStep->GetPostStepPoint()->GetStepStatus();
809 if (status == fWorldBoundary)
815 Bool_t TG4StepManager::IsTrackStop() const
817 // Returns true if particle has stopped
818 // or has been killed, suspended or postponed to next event.
820 // Possible track status from G4:
821 // fAlive, // Continue the tracking
822 // fStopButAlive, // Invoke active rest physics processes and
823 // // and kill the current track afterward
824 // fStopAndKill, // Kill the current track
825 // fKillTrackAndSecondaries,
826 // // Kill the current track and also associated
828 // fSuspend, // Suspend the current track
829 // fPostponeToNextEvent
830 // // Postpones the tracking of thecurrent track
831 // // to the next event.
840 = fTrack->GetTrackStatus();
841 if ((status == fStopAndKill) ||
842 (status == fKillTrackAndSecondaries) ||
843 (status == fSuspend) ||
844 (status == fPostponeToNextEvent)) {
851 Bool_t TG4StepManager::IsTrackDisappeared() const
853 // Returns true if particle has disappeared
854 // (due to any physical process)
855 // or has been killed, suspended or postponed to next event.
864 = fTrack->GetTrackStatus();
865 if ((status == fStopButAlive) ||
866 (status == fKillTrackAndSecondaries) ||
867 (status == fSuspend) ||
868 (status == fPostponeToNextEvent)) {
875 Bool_t TG4StepManager::IsTrackAlive() const
877 // Returns true if particle continues tracking.
885 = fTrack->GetTrackStatus();
886 if (status == fAlive)
892 Bool_t TG4StepManager::IsNewTrack() const
894 // Returns true when track performs the first step.
897 if (fStepStatus == kVertex)
903 Int_t TG4StepManager::NSecondaries() const
905 // Returns the number of secondary particles generated
906 // in the current step.
910 CheckSteppingManager();
913 G4int nofSecondaries = 0;
914 nofSecondaries += fSteppingManager->GetfN2ndariesAtRestDoIt();
915 nofSecondaries += fSteppingManager->GetfN2ndariesAlongStepDoIt();
916 nofSecondaries += fSteppingManager->GetfN2ndariesPostStepDoIt();
918 return nofSecondaries;
921 void TG4StepManager::GetSecondary(Int_t index, Int_t& particleId,
922 TLorentzVector& position, TLorentzVector& momentum)
924 // Fills the parameters (particle encoding, position, momentum)
925 // of the generated secondary particle which is specified by index.
926 // !! Check if indexing of secondaries is same !!
930 CheckSteppingManager();
933 G4int nofSecondaries = NSecondaries();
934 G4TrackVector* secondaryTracks = fSteppingManager->GetSecondary();
936 if (secondaryTracks){
937 if (index < nofSecondaries) {
939 // the index of the first secondary of this step
941 = secondaryTracks->entries() - nofSecondaries;
942 // (the secondaryTracks vector contains secondaries
943 // produced by the track at previous steps, too)
945 = (*secondaryTracks)[startIndex + index];
949 = track->GetDynamicParticle()->GetDefinition()->GetPDGEncoding();
952 G4ThreeVector positionVector = track->GetPosition();
953 positionVector *= 1./(TG4G3Units::Length());
954 G4double time = track->GetLocalTime();
955 time /= TG4G3Units::Time();
956 SetTLorentzVector(positionVector, time, position);
959 G4ThreeVector momentumVector = track->GetMomentum();
960 G4double energy = track->GetDynamicParticle()->GetTotalEnergy();
961 energy /= TG4G3Units::Energy();
962 SetTLorentzVector(momentumVector, energy, momentum);
965 TG4Globals::Exception(
966 "TG4StepManager::GetSecondary(): wrong secondary track index.");
970 TG4Globals::Exception(
971 "TG4StepManager::GetSecondary(): secondary tracks vector is empty");
975 AliMCProcess TG4StepManager::ProdProcess(Int_t isec) const
977 // The process that has produced the secondary particles specified
978 // with isec index in the current step.
981 G4int nofSecondaries = NSecondaries();
982 if (fStepStatus == kVertex || !nofSecondaries) return kPNoProcess;
985 CheckStep("ProdProcess");
988 G4TrackVector* secondaryTracks = fSteppingManager->GetSecondary();
990 // should never happen
991 if (!secondaryTracks) {
992 TG4Globals::Exception(
993 "TG4StepManager::ProdProcess(): secondary tracks vector is empty.");
998 if (isec < nofSecondaries) {
1000 // the index of the first secondary of this step
1002 = secondaryTracks->entries() - nofSecondaries;
1003 // the secondaryTracks vector contains secondaries
1004 // produced by the track at previous steps, too
1006 // the secondary track with specified isec index
1007 G4Track* track = (*secondaryTracks)[startIndex + isec];
1009 const G4VProcess* kpProcess = track->GetCreatorProcess();
1011 AliMCProcess mcProcess
1012 = TG4PhysicsManager::Instance()->GetMCProcess(kpProcess);
1014 // distinguish kPDeltaRay from kPEnergyLoss
1015 if (mcProcess == kPEnergyLoss) mcProcess = kPDeltaRay;
1020 TG4Globals::Exception(
1021 "TG4StepManager::GetSecondary(): wrong secondary track index.");
1028 Int_t TG4StepManager::StepProcesses(TArrayI &proc) const
1030 // Fills the array of processes that were active in the current step
1031 // and returns the number of them.
1032 // TBD: Distinguish between kPDeltaRay and kPEnergyLoss
1035 if (fStepStatus == kVertex) {
1036 G4cout << "kVertex" << G4endl;
1037 G4int nofProcesses = 1;
1038 proc.Set(nofProcesses);
1040 return nofProcesses;
1043 #ifdef TGEANT4_DEBUG
1044 CheckSteppingManager();
1045 CheckStep("StepProcesses");
1048 // along step processes
1049 G4ProcessManager* processManager
1050 = fStep->GetTrack()->GetDefinition()->GetProcessManager();
1051 G4ProcessVector* alongStepProcessVector
1052 = processManager->GetAlongStepProcessVector();
1053 G4int nofProcesses = alongStepProcessVector->entries();
1055 // process defined step
1056 const G4VProcess* kpLastProcess
1057 = fStep->GetPostStepPoint()->GetProcessDefinedStep();
1059 // fill the array of processes
1060 proc.Set(nofProcesses);
1061 TG4PhysicsManager* physicsManager = TG4PhysicsManager::Instance();
1063 for (i=0; i<nofProcesses-1; i++) {
1064 G4VProcess* g4Process = (*alongStepProcessVector)[i];
1065 // do not fill transportation along step process
1066 if (g4Process->GetProcessName() != "Transportation") {
1067 physicsManager->GetMCProcess(g4Process);
1068 proc[i] = physicsManager->GetMCProcess(g4Process);
1071 proc[nofProcesses-1] = physicsManager->GetMCProcess(kpLastProcess);
1073 return nofProcesses;