A problem for the swap algorithms

Dear developer,
I have studied the framework of the palabos for several months, I have trouble understanding some algorithms in the BlockLattice::collideAndStream(Box2D domain). in the collideAndStream

[code=“cpp”]
PLB_PRECONDITION( (plint)Descriptor::q==(plint)Descriptor::numPop );
// Make sure domain is contained within current lattice
PLB_PRECONDITION( contained(domain, this->getBoundingBox()) );

global::profiler().start("collStream");
global::profiler().increment("collStreamCells", domain.nCells());

static const plint vicinity = Descriptor<T>::vicinity;

// First, do the collision on cells within a boundary envelope of width
// equal to the range of the lattice vectors (e.g. 1 for D2Q9)
[b]collide(Box2D(domain.x0,domain.x0+vicinity-1, domain.y0,domain.y1));
collide(Box2D(domain.x1-vicinity+1,domain.x1, domain.y0,domain.y1));
collide(Box2D(domain.x0+vicinity,domain.x1-vicinity, domain.y0,domain.y0+vicinity-1));
collide(Box2D(domain.x0+vicinity,domain.x1-vicinity, domain.y1-vicinity+1,domain.y1));[/b]

// Then, do the efficient collideAndStream algorithm in the bulk,
// excluding the envelope (this is efficient because there is no
// if-then-else statement within the loop, given that the boundary
// region is excluded)
bulkCollideAndStream(Box2D(domain.x0+vicinity,domain.x1-vicinity,
                           domain.y0+vicinity,domain.y1-vicinity));

// Finally, do streaming in the boundary envelope to conclude the
// collision-stream cycle
boundaryStream(domain, Box2D(domain.x0,domain.x0+vicinity-1,
                             domain.y0,domain.y1));
boundaryStream(domain, Box2D(domain.x1-vicinity+1,domain.x1,
                             domain.y0,domain.y1));
boundaryStream(domain, Box2D(domain.x0+vicinity,domain.x1-vicinity,
                             domain.y0,domain.y0+vicinity-1));
boundaryStream(domain, Box2D(domain.x0+vicinity,domain.x1-vicinity,
                             domain.y1-vicinity+1,domain.y1));
global::profiler().stop("collStream");


The BlockLattice::coliide is called on the boundary of lattice, then the grid[iX][iY].collide and grid[iX][iY].revert is called in BlockLattice::collide, 
[code="cpp"]
template<typename T, template<typename U> class Descriptor>
void BlockLattice2D<T,Descriptor>::collide(Box2D domain) {
    PLB_PRECONDITION( (plint)Descriptor<T>::q==(plint)Descriptor<T>::numPop );
    // Make sure domain is contained within current lattice
    PLB_PRECONDITION( contained(domain, this->getBoundingBox()) );

    for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
        for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
            [b]grid[iX][iY].collide(this->getInternalStatistics());
            grid[iX][iY].revert();[/b]
        }
    }
}

grid[iX][iY].collide will lead to the execution of the dynamics::collide in grid[iX][iY] ,
and the implementation of grid[iX][iY].revert follows

[code=“cpp”]
template<typename T, template class Descriptor>
void Cell<T,Descriptor>::revert() {
for (plint iPop=1; iPop<=Descriptor::numPop/2; ++iPop) {
std::swap(f[iPop],f[iPop+Descriptor::numPop/2]);
}
}


     In Cell::revert, all populations are assigned the population value from the opposite location on the same node,which is same as the behavior of the BounceBack::collide.
     As I know,the revert is a swap algorithm,which can optimize the performance of the BlockLattice::stream.But I think it will automatically impose a BounceBack condition on the boundary of the lattice.
     So,if I define a BounceBack dynamics on the boundary of lattice with the method defineDynamics,will the BounceBack condition be execute twice on the boundary of lattice? most likely it is,thank you in advance.