How to initialize multiple G4Accumulables

Hi everyone,

I’m currently building a program which requires me to record more than 20 values on the run-level. And those values come from steps.

It is clear I should use G4Accumulables for this and it worked. However I really don’t want to declare more than twenty accumulables in my code (which is so ugly :p), so is there a way for me to declare 20 G4Accumulables with one line of code?

I tried using array of accumulables which looks like this:
G4Accumulable PhotonCount[20];
I declared this in my head files but I don’t know how to initialize it in my source file.

I can really use some help here. Thanks!

I’m not 100% familiar with G4Accumulable so what follows should be taken as hints rather than definitive!

If the quantities to be accumulated are all of the same type, e.g. G4int, then it’s possible to use a std::vector(*):

// This could be in the class that manages the accumulables
std::vector<G4Accumulable<G4int>> PhotonCount;

it could then be initialised, e.g., in the body of a constructor as

G4AccumulableManager* accumulableManager = G4AccumulableManager::Instance();

for (size_t i = 0 ; i < 20 ; ++i)
{
  PhotonCount.emplace_back(0); // assuming the initial value is 0
  accumulableManager->RegisterAccumulable(PhotonCount[i]);
}

(*) One gotcha with G4Accumulable is that it has a deleted default constructor, so a plain C array or std::array would need to store pointers. That can be done, but requires more memory management and code.

The other option could be to use the CreateAccumulable/GetAccumulable member functions of G4AccumulableManager. Again, assuming the quantities are all the same type, then these could be created by assuming no other accumulables:

G4AccumulableManager* accumulableManager = G4AccumulableManager::Instance();

for (size_t i = 0 ; i < 20 ; ++i)
{
  accumulableManager->CreateAccumulable<G4int>(0);
}

The no other accumulables is required because the integer id they get in the G4AccumulableManager is based on the order of addition. So if you’d already created N accumulables, the ones above would have ids starting from N rather than zero.

Accumulables created this way can be retrieved by:

G4AccumulableManager* accumulableManager = G4AccumulableManager::Instance();

for (size_t i = 0 ; i < 20 ; ++i)
{
  G4Accumulable<G4int>* a = accumulableManager->GetAccumulable<G4int>(i);
  // Do something with retrieved accumulable
}

There are a few more adaptions possible to the above if you need the accumulables to have a named id (via G4String). The Application Developer Guide section on Accumulables covers these.

1 Like

Wow thanks a lot! This definitely works

hi, Your tips have enlightened me.
but when i use your first way to define a vector and register in G4AccumulableManager, the merge()and reset() member functions of G4AccumulableManager will lead to segmentation fault.
so can you help me to solve it?