void addInternalProcessor( DataProcessorGenerator3D const& generator,
                           MultiBlock3D& object, plint level )
{
    std::vector<MultiBlock3D*> objects(1);
    objects[0] = &object;
    addInternalProcessor(generator, objects, level);
}
void addInternalProcessor( DataProcessorGenerator3D const& generator,
                           std::vector<MultiGrid3D*> multiGrids,
                           plint referenceLevel,
                           plint processorLevel)
{
    if(multiGrids.empty()) return;
    for (plint iLevel=0; iLevel<(plint)multiGrids[0]->getNumLevels(); ++iLevel) {
        std::auto_ptr<DataProcessorGenerator3D> localGenerator(generator.clone());
        int dxScale = (int)referenceLevel - (int)iLevel;
        int dtScale = dxScale;  // TODO: here, we assume convective scaling; general case should be considered.
        
        localGenerator -> setscale(dxScale,dtScale);
        plint boxRescaleFactor = util::roundToInt(util::twoToThePowerPlint(std::abs(referenceLevel-iLevel)));
        // if dxScale < 0 this means we go to a coarser grid
        if (dxScale < 0)
            localGenerator->divide(boxRescaleFactor);  
        else
            localGenerator->multiply(boxRescaleFactor);
        
        std::vector<MultiBlock3D*> localBlocks(multiGrids.size());
        for (plint iBlock=0; iBlock<(plint)localBlocks.size(); ++iBlock) {
            localBlocks[iBlock] =  &multiGrids[iBlock]->getComponent(iLevel);
        }
        addInternalProcessor(*localGenerator, localBlocks, processorLevel);
    }
}
void addInternalProcessor( DataProcessorGenerator3D const& generator,
                           std::vector<MultiBlock3D*> multiBlocks, plint level )
{
    if (multiBlocks.size()>0) {
        addInternalProcessor(generator, *multiBlocks[0], multiBlocks, level);
    }
}
void integrateProcessingFunctional(DotProcessingFunctional2D* functional,
                                   DotList2D const& dotList,
                                   std::vector<AtomicBlock2D*> atomicBlocks,
                                   plint level)
{
    addInternalProcessor( DotProcessorGenerator2D(functional, dotList),
                          atomicBlocks, level );
}
void integrateProcessingFunctional(BoxProcessingFunctional2D* functional,
                                   Box2D domain,
                                   std::vector<AtomicBlock2D*> atomicBlocks,
                                   plint level)
{
    addInternalProcessor( BoxProcessorGenerator2D(functional, domain),
                          atomicBlocks, level );
}
void addInternalProcessor( DataProcessorGenerator3D const& generator,
                           MultiGrid3D& object,
                           plint referenceLevel,
                           plint processorLevel)
{
    std::vector<MultiGrid3D*> blocks;
    blocks.push_back(&object);
    addInternalProcessor(generator,blocks,referenceLevel, processorLevel);
}
void addInternalProcessor( DataProcessorGenerator2D const& generator,
                           MultiBlock2D& object1, MultiBlock2D& object2,
                           plint level )
{
    std::vector<MultiBlock2D*> objects(2);
    objects[0] = &object1;
    objects[1] = &object2;
    addInternalProcessor(generator, objects, level);
}
void integrateProcessingFunctional(BoundedBoxProcessingFunctional2D* functional,
                                   Box2D domain, std::vector<AtomicBlock2D*> atomicBlocks,
                                   plint boundaryWidth, plint level)
{
    std::vector<BoxProcessorGenerator2D*> generators;
    functional -> getGenerators(domain, boundaryWidth, generators);
    delete functional;
    for (pluint iGen=0; iGen<generators.size(); ++iGen) {
        addInternalProcessor( *generators[iGen], atomicBlocks, level );
        delete generators[iGen];
    }
}