Are Initialize() and EndOfEvent() really called in G4VSensitiveDetector?

I have the impression that the virtual methods Initialize() and EndOfEvent() of G4VSensitiveDetector are no called. Looking the code I do not see them being called. Can somebody confirm it? If they are not called why are they there?

1 Like

Sorry, forgot to mention in the MT case.

Sensitive detecter class object is thread-local. And in the current Geant4 MT mode, individual events are tasked to the worker threads.

The methods you are pointing out are invoked at the beginning and the end of processing each individual event, respectively. They are invoked from G4EventManager class (and supposed to be invoked solely from G4EventManager).

1] Initialize() is invoked at the beginning of each individual event and the most typical use of this method is instantiating hit-collection object(s) for that event (and associate it/them to G4Event). A sensitive detector may generates more than one kinds of hits (e.g. anode and cathode hits for two-dimensional silicon microstrip tracker). So the behavior of this Initialize() method is specific to each detector implementation.

2] EndOfEvent() is invoked at the end of processing an event. Hit-collection object(s) are automatically deleted along with the associated G4Event object. So the user does not need to delete it/them. This method is invoked even if the current event is aborted. Thus, if the user wants to do something for this detector regardless of the success or abortion of the event, this is the method to implement. I understand this is not very common case, though.

Some additional (and a bit more detailed) information.

Actually G4VSensitiveDetector::Initialize() and G4VSensitiveDetector::EndOfEvent() are invoked from G4SDStructure::Initialize() and G4SDStructure::Terminate().
https://geant4.kek.jp/lxr/source/digits_hits/detector/src/G4SDStructure.cc#L211
https://geant4.kek.jp/lxr/source/digits_hits/detector/src/G4SDStructure.cc#L226

And these G4SDStructure class methods are invoked from G4SDManager::PrepareNewEvent() and G4SDManager::TerminateCurrentEvent(), respectively.
https://geant4.kek.jp/lxr/source/digits_hits/detector/src/G4SDManager.cc#L113
https://geant4.kek.jp/lxr/source/digits_hits/detector/src/G4SDManager.cc#L120

And these G4SDManager methods are invoked from G4EventManager.
https://geant4.kek.jp/lxr/source/event/src/G4EventManager.cc#L134
https://geant4.kek.jp/lxr/source/event/src/G4EventManager.cc#L300

This sequence enables the user to activate/inactivate each individual or a group of detector(s).

Thanks Makoto. My problem could be that is SD is not active and therefore is not called.

void G4SDStructure::Initialize(G4HCofThisEvent* HCE)
{
  // Broadcast to subdirectories.
  for (auto st : structure) {
    st->Initialize(HCE);
  }
  // Initialize all detectors in this directory.
  for (auto dt : detector) {
    if (dt->isActive()) dt->Initialize(HCE);   <==========
  }
}

What do you mean with?

I do instantiate mySD that inherits from G4VSensitiveDetector in the main thread, and then I call G4VUserDetectorConstruction::SetSensitiveDetector(lv, sad, true) in the function ConstructSDandField() that is called for each WorkerThread as far I can see. Is this sufficient to get the SD active?

I think I understand. Probably I need to instantiate inside ConstructSDandField() and call G4SDManager::GetSDMpointer()->AddNewDetector(...).

1 Like

Yes, sensitive detector object must be instantiated in your ConstructSDandField() method and set to the corresponding logical volume. This ConstructSDandField() method is invoked for each individual worker threads, and the assigned logical volume stores the thread-local pointers.

1 Like

Hi Makoto. I do have a MT related questions.

I see that the PrimaryGeneratorAction is also per worker thread. A new one is instantiated in the G4VUserActionInitialization::Build() that is called by the worker thread at init time.

The questions are:

  • Why I must have one per thread? My initial attempt was to share an instance (assuming it was thread safe) but on shutting-down the G4MTRunManager I was getting a EXC_BAD_ACCESS error because the instance was deleted several times.

  • If I want to change some event generation parameters (e.g. energy of the particle gun) in subsequent runs, do I need to modify the parameter in N objects?

Hi Pere,

I’m not sure whether user’s PrimaryGeneratorAction class object is just impossible to be shared by multiple worker threads, but at least, if it is shared, its GeneratePrimaries() method has to be fully mutex-ed. Also, associated primary generator (e.g. particle gun) has to be thread-local or fully protected by mutex. Comparing with such complications, making PrimaryGeneratorAction thread-local is much cleaner and simpler for the user.

If you set the parameter of the generator by a UI command, that command is broadcasted to all worker threads. If you are directly invoking a set-method of the generator, yes, you have to invoke it for each thread-local objects, or you need to create a static method in your PrimaryGeneratorAction.