Commands instantiated after initialization (in UserTrackingAction) aren't being properly registered

In my UserTrackingAction class, I have a UI command that dynamically creates new sensitive detectors. The tracking action’s command is added to the list of commands after I call /run/initialize, and I can verify that when i call it, new SDs are indeed created, so that all seems to work.

But my sensitive detector class also has a G4UImessenger that is created in the SD class’s constructor. These commands don’t show up in the list of available commands, and generate an error if I call them. I’m running on G4 10.06.p02 with a multithreaded build.

So if executing a G4UI command results in a new G4UImessenger to be constructed, do I have to take some additional step to register the new messenger and its commands? Does it have something to do with the fact that the UserTrackingAction instances are in worker threads, and I somehow need to also construct a copy of my messenger in the master thread?

We have the same situation in our simulation framework. I think the problem you’re seeing is because SDs do not get created when they are requested. Rather, then are created in the worker threads only after /run/beamOn, when your geometry->ConstructSDandField() is called.

What you likely need to do is have a separate “SD configuration” class, which can be constructed and filled via your macro commands. This configuration class should be a thread-local singleton (because UI commands are silently re-executed by all the worker threads, too).

The TrackingAction messenger would trigger the instances of these configuration objects on request, at the same time it triggers your geometry class that the SDs are supposed to be created.

Then, you can have your SDs, in their own constructors, access the corresponding container singleton to find out how they’re supposed to be set up.

It’s kind of a weird indirection, but it allows you to do all of the setup and configuration before the SDs are actually instantiated.

I don’t think this is the answer, or at least not the whole answer. When I run the UI command to create the new SDs, they are created. If I run it multiple times, the SDManager complains that I’m registering a detector with the same name as one that’s already created.

I think the fact that the new messenger happens to be owned by a sensitive detector that I’m using oddly is a red herring. The new UImessenger is being instantiated (since it is done so in my SD class’s constructor, so it doesn’t matter whether the SD manager knows about the SD or not). But it’s not showing up in the command list on the master thread.

Is there some extra step I need to take to add new UI commands in the Idle state (after /run/initialize), or am I just not supposed to be creating commands then period?

[ Hah. I didn’t notice the username, Ben. Are we talking about the same simulation framework here? Or your own application? ]

The problem may be on the worker threads rather than the master thread. When you first create the SD (and its Messenger), that’s happening (I think) on the master thread. All your macro commands get collected, and re-executed on the worker threads. That should include both your “SD-creating” command as well as the subsequent commands to configure it.

One ugly way to see what’s going on might be to stick a G4cout statement right into the constructors of both your free-standing SD and it’s Messenger. On the master thread, the G4cout messages will be printed verbatim. On each of the worker threads, they’ll be prefixed with "G4WT# > " (where # is the worker index).

This is a different framework. I ended up working around the problem, but I don’t understand why it worked. I just moved the functionality from my UserTrackingAction to my UserRunAction. I guess this works because I create a run action in my UserActionInitialization::BuildForMaster.

Still very unintuitive why I can’t dynamically create commands in my other UserAction classes though…

Yes, it’s the BuildForMaster() and Build() difference that’s involved with the UserAction classes. The workaround I implemented (with thanks to Makoto!) is to have local, owned data members in my UserActionInitialization for all of the UserAction classes which we want to be available with UI commands.

Specifically, in CDMSActionInitialization.hh we have:

private:
  G4int verboseLevel;

  // Local instances to get UI commands defined for master thread
  // Commands issued on master will be propagated to worker threads
  mutable CDMSEventAction*    masterEventAction;
  mutable CDMSTrackingAction* masterTrackingAction;
  mutable CDMSSteppingAction* masterSteppingAction;

Then, we have CDMSActionInitialization:BuildForMaster():

void CDMSActionInitialization::BuildForMaster() const {
  CDMSRunAction* run = new CDMSRunAction;
  run->SetVerboseLevel(verboseLevel);
  SetUserAction(run);

  // To get UI commands at startup, create local actions here (not registered)
  masterEventAction    = new CDMSEventAction(0,0);      // Never invoked
  masterTrackingAction = new CDMSTrackingAction;
  masterSteppingAction = new CDMSSteppingAction;
}

These local data members get deleted by hand in the ActionInitialization destructor. That’s necessary since they aren’t owned by the RunManager. If you don’t delete them, they show up as spurious memory leaks in Valgrind, for instance.

In Build() we don’t touch these local objects at all, making and registering thread-local instances normally. Those three actions never actually get used for anything. Their sole purpose in life is to instantiate their Messengers, local containers, whatever, on the master thread. That way all the UI commands you invoke before /run/beamOn do what they’re supposed to do. Those commands get collected, and re-broadcast to all the worker threads. Since the workers have their own instances of the action classes, the re-broadcast commands do the right thing in each thread.

Ugh. Using mutable for anything but caching smells of dirty hacks.

Now I’m even more confused too. The command I was trying to do in my UserTrackingAction and moved to my UserRunAction was creating a new sensitive detector and adding it to a vector:

void TrackingActionMessenger::SetNewValue(G4UIcommand* , G4String newvalue)
{
  fTrackingAction->AddNewDetector(newvalue);
}

When this command belongs to my UserRunAction (or an action created in BuildForMaster like the mutables above), it is available during the PreInit state. But then the TrackingAction class created in the worker threads is a new object, so it shouldn’t have those detectors built, right? Because I tried calling the command both before and after /run/initialize, and I get the same effect, i.e. the detectors seem to be present in the worker threads in both cases. Does the UI manager replay the preinit command history to all the worker threads on startip or something?

The Build() and BuildForMaster() virtual functions are declared const in the base class, so that can’t be changed. The master-only local action objects need to be saved if we want to be able to delete them at end of job. If we don’t want to bother with that, they could be instantiated without saving the pointer (recall how many bare new G4PVPlacement(...); lines there are!).

Right! The worker threads don’t see those created objects at all, nor their Messengers. In fact, being on the master thread, those created objects are unused for anything.

Yes, that’s exactly what happens, with the exception of any UI commands which were created with a “nobroadcast” flag set. That’s typically only done by a few specific commands that are internal to G4.