OneCell Functional

Hi,

There is something I do not understand. I wanted to use OneCellIndexedFunctional to compute an average of my lattice over time but without success. I tried something simple like copying a lattice, but no more success. Here is my code of copy:

[code=“cpp”]
template<typename T, template class Descriptor>
class CopyLatticeCell : public OneCellIndexedFunctional3D<T,Descriptor>
{
public:
CopyLatticeCell(MultiBlockLattice3D<T,Descriptor>* s) : source(s) {}
CopyLatticeCell<T,Descriptor>* clone() const {
return new CopyLatticeCell<T,Descriptor>(*this); }

virtual void execute(plint iX, plint iY, plint iZ, Cell<T,Descriptor>& cell) const
{
  Cell<T,Descriptor>& cell_source = source->get(iX,iY,iZ);
  for (plint i = 0; i < n; i++) { cell[i] = cell_source[i]; }
}

private:
MultiBlockLattice3D<T,Descriptor>* source;
const static plint n = CellInfo<T,Descriptor>::n;
};

void copy(MultiBlockLattice3D<T,DESCRIPTOR>& sourceLattice,
MultiBlockLattice3D<T,DESCRIPTOR>& resultLattice)
{
applyIndexed(resultLattice, resultLattice.getBoundingBox(),
new CopyLatticeCell<T,DESCRIPTOR>(&sourceLattice));
}



To use it just add at the end of a computation

[code="cpp"]
copy(lattice, result_lattice);

I declare result_lattice in the same time I declare lattice. The result lattice has the BC fine (from creation) but velocity is zero elsewhere. If you have any idea…

TIA,

Olivier.

I found the bug and it is not is the source code above. It is almost there:

My real function copy was

[code=“cpp”]
void copy(MultiBlockLattice3D<T,DESCRIPTOR>& sourceLattice,
MultiBlockLattice3D<T,DESCRIPTOR>& resultLattice)
{
CopyLatticeCell<T,DESCRIPTOR> my_copy(&sourceLattice);
applyIndexed(resultLattice, resultLattice.getBoundingBox(),
&my_copy);
}


instead of
[code="cpp"]
void copy(MultiBlockLattice3D<T,DESCRIPTOR>& sourceLattice,
          MultiBlockLattice3D<T,DESCRIPTOR>& resultLattice)
{
  applyIndexed(resultLattice, resultLattice.getBoundingBox(),
               new CopyLatticeCell<T,DESCRIPTOR>(&sourceLattice));
}

I did the change when I send my example to make it shorter… Normally it should be exactly then same however Palabos delete the third argument at line 164 of dataInitializerFunctional3D.hh (version 1.1r0). Then copy want to delete it also and kaboom.

Deleting an object you did not create is not a good habit. Could you remove that or at least write it in the documentation and warn the user in the example and tutorial?

Thanks,

Olivier.

Dear Olivier,

As a general rule in Palabos, the semantics of providing a pointer argument to a function is that the ownership of the object pointed to is transferred to the function. In case the argument is passed by reference, you keep the ownership and thus the responsibility of deleting it.

The reason for this rule is related to the mechanism of memory management in Palabos, and the rule is clearly stated in the programming guidelines: http://www.palabos.org/documentation/userguide/programming.html#memory-management . The guidelines are very short, and I strongly suggest you give them a look to avoid future kabooms.

Cheers,
Jonas

Dear Jonas,

Thanks for your answer and sorry for having forgetting this rule. I did read the guidelines long time ago but I should have done it again.

BTW in my case I don’t do any delete. I understand it is the same since C++ call the delete at the end of the scope, but maybe you want to add a line about that (or you expect everyone know that).

Now this copy example is still interresting because even with that correction it does not work. It needs 2 more corrections:

Instead of

[code=“cpp”]
for (plint i = 0; i < n; i++) { cell[i] = cell_source[i]; }


I have to do
[code="cpp"]
        Array<T,n> ff;
        cell_source.getPopulations(ff);
        cell.setPopulations(ff);

or it will copy nothing.

The second point is I have to check I don’t cross boundaries or it never finishes, so I put first in my execute method:

[code=“cpp”]
if (iX < 0 or iX >= source->getNx() or
iY < 0 or iY >= source->getNy() or
iZ < 0 or iZ >= source->getNz() ) return;



And then it works as expected and I can everage lattices over time, however it is very slow. I guess the call to source->get(iX,iY,iZ) is responsible. Would you have a faster way to do that Add functor:

[code="cpp"]

virtual void execute(plint iX, plint iY, plint iZ, Cell<T,DESCRIPTOR>& cell) const
    {
      if (iX < 0 or iX >= source->getNx()
          or iY < 0 or iY >= source->getNy()
          or iZ < 0 or iZ >= source->getNz() ) return;

      Cell<T,DESCRIPTOR>& cell_source = source->get(iX,iY,iZ);
      Array<T,n> fs, fd;

      cell.getPopulations(fd);
      cell_source.getPopulations(fs);
      for (int i = 0; i < n; i++) { fd[i] += fs[i]; }
      cell.setPopulations(fd);
    }

Best,

Olivier.