Constructor and Destructor of BodyForceGroup

Asked by Feng Chen

Hi, All:

I am trying to add something to the BodyForceGroup template class, I want to initialize an dynamic array in its constructor and then delete it in the destructor like this:

template <class TmplParticle>
BodyForceGroup<TmplParticle>::BodyForceGroup(
  const BodyForceIGP &prms,
  ParticleArray &particleArray
)
  : m_acceleration(prms.getAcceleration()),
    m_pParticleArray(&particleArray)
{
   arrayVec=new double[numParticles]; // te arrayVec is defined in private
}

then I want to clear the array in the destructor:

template <class TmplParticle>
BodyForceGroup<TmplParticle>::~BodyForceGroup()
{
    delete[] arrayVec;
    cout << "destructor called." << endl;
}

However when I tried to run a script using this body force, it appears that the BodyForceGroup destructor was never called, hence the arrayVec is not freed.

I wonder if there is some kind of basic conceptual mistakes when I was using this template class?

Any suggestion is welcome! Thanks a lot!

Feng

Question information

Language:
English Edit question
Status:
Solved
For:
ESyS-Particle Edit question
Assignee:
No assignee Edit question
Solved by:
Vince Boros
Solved:
Last query:
Last reply:
Revision history for this message
Launchpad Janitor (janitor) said :
#1

This question was expired because it remained in the 'Open' state without activity for the last 15 days.

Revision history for this message
Vince Boros (v-boros) said :
#2

Answer pending.

Revision history for this message
Vince Boros (v-boros) said :
#3

Hello Feng:

Your code to allocate memory at runtime to arrayVec in the constructor and then to deallocate memory in the destructor looks to be textbook perfect. The problem may be elsewhere in the code. Specifically, there may be no call to delete BodyForceGroup, which may explain why the BodyForceGroup destructor is not called.

There is a line:

  new esys::lsm::BodyForceGroup<T>(prms, *m_ppa)

in SubLattice.hpp within TSubLattice<T>::addSingleIG() to add a new single-particle interaction, but i can find nothing that deletes it. I expect that this could appear in TSubLattice<T>::removeIG(). This is currently coded to remove unbonded particle-pair interactions and unbonded wall interactions, which may be short-lived over the course of the simulation, but not single-particle interactions (gravity), which would remain until the end. From a housekeeping point of view, to deallocate memory that has been allocated with "new", at the latest when the program ends, you might add this code to TSubLattice<T>::removeIG():

   } else {
    // if not found, look in single-particle interactions
    typename map<string,AInteractionGroup<T>*>::iterator it3=m_singleParticleInteractions.find(igname);
    if(it3!=m_singleParticleInteractions.end()){
      found=true;
      delete m_singleParticleInteractions[igname];
      m_singleParticleInteractions.erase(it3);
    }

This may not be the end of the matter. It depends on the circumstances in which TSubLattice<T>::removeIG() is called. I expect that it is called whenever two particles have ended their collision with each other and when a particle is no longer touching a wall, but probably not when gravity ceases, since it does not stop acting on a particle. I need to dig down some more and get some advice.

Vince

Revision history for this message
Feng Chen (fchen3-gmail) said :
#4

Hi, Vince:

Thank your for the detailed answer, do you have any idea about know how the TSubLattice<T>::removeIG() is called?
and do we need to implement a TSubLattice<T>::removeSingleIG() for these body forces?
It seems to me if an object is "new"ed but not "delete"ed, memory leak will occur unless you use some kind of smart pointers (like boost shared_ptr), but is this the case for a "new"ed object as a parameter?

Thanks a lot!

Feng

Revision history for this message
Vince Boros (v-boros) said :
#5

Hi Feng:

I need to make a correction on my last post. TSubLattice<T>::removeIG() removes an entire interaction group, not the individual interactions. A body force group (Gravity) is not removed during simulation, which is why there is no code to remove it here.

Yes, you can implement TSubLattice<T>::removeSingleIG() for a body force group, or you can simply add lines of code in TSubLattice<T>::removeIG() as in my last post. Calling TSubLattice<T>::removeIG() is ultimately done through the Python API, using removeInteractionGroup(..) (part of LsmMpi, LsmPy module) in your script.

Vince

Revision history for this message
Feng Chen (fchen3-gmail) said :
#6

Hi, Vince:

I have added the code in your previous post to TSubLattice<T>::removeIG(), however, it seems that the removeIG is not called, do I need to explicitly call the sim.removeInteractionGroup() in my script somewhere? Thanks!

Feng

Revision history for this message
Best Vince Boros (v-boros) said :
#7

Hi Feng:

Yes, you need to call sim.removeInteractionGroup() explicitly in your script. This means that you will not be able to use sim.run() because by then the simulation will have finished. Instead, run the simulation time steps as in the bingle_output.py tutorial script:

N_max = sim.getNumTimeSteps()
n=0
while (n < N_max):
  sim.runTimeStep()
sim.removeInteractionGroup(name = "name of interaction")
sim.exit()

Not as elegant as calling sim.run() unfortunately. I hope that it will suffice for the time being. I will follow up on advice from a colleague about implementing destructors for the ParallelInteractionStorage classes in the code as a better way of dealing with memory leakage rather than extending removeIG(). But that may take some time.

Vince

Revision history for this message
Vince Boros (v-boros) said :
#8

Oops. You will need to increment n inside the loop to eventually complete the simulation.

Vince

Revision history for this message
Feng Chen (fchen3-gmail) said :
#9

Hi, Vince:

Thank you for the answer, my final solution is to modify the CLatticeMaster::run() in LatticeMaster.cpp

void CLatticeMaster::run()
{
  while (m_t < m_max_ts) {
    runOneStep();
  }
  //runEnd(); //comment this because it does not allow us to remove the interaction groups in our python script
}

so that we can still use the sim.run() in our script, but after that, do clean-up by explicitly removing the interaction group, then call sim.exit(), since the sim.exit() actually calls the CLatticeMaster::runEnd().

and the final script will look like:

...
sim.setNumTimeSteps(nt)
sim.setTimeStepSize(dt)
#execute the simulation
sim.run()
#remove the interaction groups
sim.removeInteractionGroup(name="earth-gravity")
sim.exit()

Revision history for this message
Feng Chen (fchen3-gmail) said :
#10

Thanks Vince Boros, that solved my question.