I am currently trying to generate recoil energy distributions of a proton projectile colliding with different elements at varying proton energies and it seems that every time I call G4HadronElastic::ApplyYourself memory usage of my program increase. Since I need to call this function a lot of times for multiple different distributions it becomes an issue and my program crashes.
It seems like there is some sort of memory leak that I cannot seem to remove. If anyone has any way of solving issue or alternative to generating recoil energy distributions it would be really appreciated! I have attached a snippet of the function I call to generate different distributions at the bottom of this post.
If you are running with the interactive Qt Graphical User Interface, please make sure you are not doing any printing to G4cout. The GUI stores it up for printing at there end of run.
If that’s not the issue, then you may have found a problem in G4HadronElastic. Let us know, then perhaps an expert in hadronics can help.
No I’m not using the Qt Graphical User Interface, I’m running the above function in simple c++ script to generate multiple recoil energy distributions which I save to a json file for later use.
You said you’re calling this function in a standalone loop, so not part of G4RunManager? In that case, do you need to delete the G4HadronElastic object at the end of your function?
Or, since the model gets registered into the (singleton) G4HadronicInteractionRegistry, maybe what you want is to replace those first two lines with an if-block: Ask the Registry to give you the object (via FindModel); if it doesn’t have one, then do those first two lines just once.
I think the code would look something like this:
G4HadronicInteractionRegistry* hadReg = G4HadronicInteractionRegistry::Instance();
G4HadronicInteraction* hadElastic = hadReg->FindModel("hElasticLHEP");
if (!hadElastic) {
hadElastic = new G4HadronElastic();
hadElastic->InitializeModel()
}
// The rest of your function goes here
You could wrap the above in your own “GetModel()” function, rather than embedding it directly.
Oh ya, I’m sorry that was a mistake, I’ve been changing the function a lot lately to see if I can fix this issue. Even with this variation of the function below where I use the same G4HadronElastic object for all calls of the function I still have the increasing memory usage problem. The problem only becomes significant when the “numberOfGenerations” variable is too large, even if I only call the function a couple of times. So it must be something to do with calling “hadElastic->ApplyYourself(projectileProton, targetNucleus)” a large number of times, but I’m really unsure?
Notice that ApplyYourself is returning a pointer to an object. I think you’re being given ownership of that object, so its your responsibility to delete it whenyou’re finished using it. Clear() does not delete the object.
Whenever I try to the delete the object “G4HadFinalState *finalstate” such as by using “delete finalstate” inside my function my code crash, so possible I don’t have ownership of the object, or am doing something wrong?
It appears that my descripation above was wrong. The Toolkit Developer documents ( Hadronic Physics — Book For Toolkit Developers 11.3 documentation ) doesn’t seem to explicitly state whether G4HadFinalState* is owned or not. But looking at G4HadronicInteraction.hh, I see near the bottom:
G4HadFinalState theParticleChange;
// the G4HadFinalState object which is modified and returned
// by address by the ApplyYourself method,
// (instead of aParticleChange as found in G4VProcess)
This is exactly the same way processes work: The G4HadronicInteraction instance owns an instance of G4HadFinalState which is returned by address, but should not be deleted.
But that still doesn’t explain your memory leak. The G4HadFinalState is going to be a single object, reused on each iteration of your loop. You call Clear() on it which “should” discard the vector of secondaries (there’s a separate ClearSecondaries() function, but the main Clear() ought to be calling that. Do you want to try calling finalstate->ClearSecondaries() and see if that makes a difference?
Two questions: Do you have verbosity enable for the hadronics? And are you running this interactively in Qt, or as a simple terminal or batch job? The Qt interface caches all of the output in memory, so verbosity can blow things up unexpectedly. But that’s not relevant to simple batch running.
Sadly applying finalstate->ClearSecondaries() doesn’t solve the memory issue. I’m now running the code in terminal in a very simple c++ script and I don’t have verbosity enabled for hardonics.