void LocalMultiBlockInfo3D::computePeriodicOverlaps (
        SparseBlockStructure3D const& sparseBlock, plint blockId )
{
    Box3D intersection; // Temporary variable.
    std::vector<plint> neighbors; // Temporary variable.
    SmartBulk3D bulk(sparseBlock, envelopeWidth, blockId);

    for (plint dx=-1; dx<=+1; dx+=1) {
        for (plint dy=-1; dy<=+1; dy+=1) {
            for (plint dz=-1; dz<=+1; dz+=1) {
                if (dx!=0 || dy!=0 || dz!=0) {
                    // The new block is shifted by the length of the full multi block in each space
                    //   direction. Consequently, overlaps between the original multi block and the
                    //   shifted new block are identified as periodic overlaps.
                    plint shiftX = dx*sparseBlock.getBoundingBox().getNx();
                    plint shiftY = dy*sparseBlock.getBoundingBox().getNy();
                    plint shiftZ = dz*sparseBlock.getBoundingBox().getNz();
                    Box3D shiftedBulk(bulk.getBulk().shift(shiftX,shiftY,shiftZ));
                    Box3D shiftedEnvelope(bulk.computeEnvelope().shift(shiftX,shiftY,shiftZ));
                    // Speed optimization: perform following checks only if the shifted
                    //   domain touches the bounding box.
                    Box3D dummyIntersection;
                    if (intersect(shiftedEnvelope, sparseBlock.getBoundingBox(), dummyIntersection)) {
                        neighbors.clear();
                        sparseBlock.findNeighbors(shiftedBulk, envelopeWidth, neighbors);
                        // Check overlap with each existing block in the neighborhood, including with the newly added one.
                        for (pluint iNeighbor=0; iNeighbor<neighbors.size(); ++iNeighbor) {
                            plint neighborId = neighbors[iNeighbor];
                            SmartBulk3D neighborBulk(sparseBlock, envelopeWidth, neighborId);
                            // Does the envelope of the shifted new block overlap with the bulk of a previous
                            //   block? If yes, add an overlap, in which the previous block has the "original
                            //   position", and the new block has the "overlap position".
                            if (intersect(neighborBulk.getBulk(), shiftedEnvelope, intersection)) {
                                PeriodicOverlap3D overlap (
                                    Overlap3D(neighborId, blockId, intersection, shiftX, shiftY, shiftZ),
                                    dx, dy, dz );
                                periodicOverlaps.push_back(overlap);
                                periodicOverlapWithRemoteData.push_back(overlap);
                            }
                            // Does the bulk of the shifted new block overlap with the envelope of a previous
                            //   block? If yes, add an overlap, in which the new block has the "original position",
                            //   and the previous block has the "overlap position".
                            //   If we are in the situation in which the newly added block is periodic with itself,
                            //   this step must be skipped, because otherwise the overlap is counted twice.
                            if (!(neighborId==blockId) &&
                                intersect(shiftedBulk, neighborBulk.computeEnvelope(), intersection))
                            {
                                intersection = intersection.shift(-shiftX,-shiftY, -shiftZ);
                                periodicOverlaps.push_back (
                                        PeriodicOverlap3D (
                                            Overlap3D(blockId, neighborId, intersection, -shiftX, -shiftY, -shiftZ),
                                            -dx, -dy, -dz ) );
                            }
                        }
                    }
                }
            }
        }
    }
}
Box3D SmartBulk3D::toLocal(Box3D const& coord) const
{
    return Box3D( coord.shift(-bulk.x0+envelopeWidth, -bulk.y0+envelopeWidth,
                              -bulk.z0+envelopeWidth) );

}