コード例 #1
0
void saveFull( MultiBlock2D& multiBlock, FileName fName, IndexOrdering::OrderingT ordering )
{
    global::profiler().start("io");
    SparseBlockStructure2D blockStructure(multiBlock.getBoundingBox());
    Box2D bbox = multiBlock.getBoundingBox();
    if (ordering==IndexOrdering::forward) {
        plint nBlocks = std::min(bbox.getNx(), (plint)global::mpi().getSize());
        std::vector<std::pair<plint,plint> > ranges;
        util::linearRepartition(bbox.x0, bbox.x1, nBlocks, ranges);
        for (pluint iRange=0; iRange<ranges.size(); ++iRange) {
            blockStructure.addBlock (
                    Box2D( ranges[iRange].first, ranges[iRange].second,
                           bbox.y0, bbox.y1 ),
                    iRange );
        }
    }
    else if (ordering==IndexOrdering::backward) {
        plint nBlocks = std::min(bbox.getNy(), (plint)global::mpi().getSize());
        std::vector<std::pair<plint,plint> > ranges;
        util::linearRepartition(bbox.y0, bbox.y1, nBlocks, ranges);
        for (pluint iRange=0; iRange<ranges.size(); ++iRange) {
            blockStructure.addBlock (
                    Box2D( bbox.x0, bbox.x1, ranges[iRange].first, ranges[iRange].second ),
                    iRange );
        }
    }
    else {
        // Sparse ordering not defined.
        PLB_ASSERT( false );
    }
    plint envelopeWidth=1;
    MultiBlockManagement2D adjacentMultiBlockManagement (
            blockStructure, new OneToOneThreadAttribution, envelopeWidth );
    MultiBlock2D* multiAdjacentBlock = multiBlock.clone(adjacentMultiBlockManagement);
    
    std::vector<plint> offset;
    std::vector<plint> myBlockIds;
    std::vector<std::vector<char> > data;

    bool dynamicContent = false;
    dumpData(*multiAdjacentBlock, dynamicContent, offset, myBlockIds, data);
    if (ordering==IndexOrdering::backward && myBlockIds.size()==1) {
        PLB_ASSERT( data.size()==1 );
        Box2D domain;
        blockStructure.getBulk(myBlockIds[0], domain);
        plint sizeOfCell = multiAdjacentBlock->sizeOfCell();
        PLB_ASSERT( domain.nCells()*sizeOfCell == (plint)data[0].size() );
        transposeToBackward( sizeOfCell, domain, data[0] );
    }

    plint totalSize = offset[offset.size()-1];
    writeOneBlockXmlSpec(*multiAdjacentBlock, fName, totalSize, ordering);
    writeRawData(fName, myBlockIds, offset, data);
    delete multiAdjacentBlock;
    global::profiler().stop("io");
}
コード例 #2
0
MultiGridManagement2D::MultiGridManagement2D(Box2D coarseBoundingBox, 
                                             plint numLevels, plint overlapWidth_, plint referenceLevel_)
                                  : overlapWidth(overlapWidth_),
                                    referenceLevel(referenceLevel_),
                                    boundingBoxes(numLevels),
                                    coarseGridInterfaces(numLevels),
                                    fineGridInterfaces(numLevels),
                                    bulks(numLevels),
                                    coarseInterfaceOrientations(numLevels),
                                    fineInterfaceOrientations(numLevels)
{
    PLB_ASSERT( numLevels > 0 );
    PLB_ASSERT( referenceLevel < numLevels );
    initialize(coarseBoundingBox);
}
コード例 #3
0
void addInternalProcessor( DataProcessorGenerator3D const& generator, MultiBlock3D& actor,
                           std::vector<MultiBlock3D*> multiBlockArgs, plint level )
{
    MultiProcessing3D<DataProcessorGenerator3D const, DataProcessorGenerator3D >
        multiProcessing(generator, multiBlockArgs);
    std::vector<DataProcessorGenerator3D*> const& retainedGenerators = multiProcessing.getRetainedGenerators();
    std::vector<std::vector<plint> > const& atomicBlockNumbers = multiProcessing.getAtomicBlockNumbers();

    for (pluint iGenerator=0; iGenerator<retainedGenerators.size(); ++iGenerator) {
        std::vector<AtomicBlock3D*> extractedAtomicBlocks(multiBlockArgs.size());
        for (pluint iBlock=0; iBlock<extractedAtomicBlocks.size(); ++iBlock) {
            extractedAtomicBlocks[iBlock] =
                &multiBlockArgs[iBlock]->getComponent(atomicBlockNumbers[iGenerator][iBlock]);
        }
        // It is assumed that the actor has the same distribution as block 0.
        PLB_ASSERT(!atomicBlockNumbers[iGenerator].empty());
        AtomicBlock3D& atomicActor = actor.getComponent(atomicBlockNumbers[iGenerator][0]);
        // Delegate to the "AtomicBlock version" of addInternal.
        plb::addInternalProcessor(*retainedGenerators[iGenerator], atomicActor, extractedAtomicBlocks, level);
    }
    // Subscribe the processor in the multi-block. This guarantees that the multi-block is aware
    //   of the maximal current processor level, and it instantiates the communication pattern
    //   for an update of envelopes after processor execution.
    std::vector<MultiBlock3D*> updatedMultiBlocks;
    std::vector<modif::ModifT> typeOfModification;
    multiProcessing.multiBlocksWhichRequireUpdate(updatedMultiBlocks, typeOfModification);
    actor.subscribeProcessor (
            level,
            updatedMultiBlocks, typeOfModification,
            BlockDomain::usesEnvelope(generator.appliesTo()) );
    actor.storeProcessor(generator, multiBlockArgs, level);
}
コード例 #4
0
AtomicContainerBlock3D const& MultiContainerBlock3D::
    getComponent(plint blockId) const
{
    BlockMap::const_iterator it = blocks.find(blockId);
    PLB_ASSERT (it != blocks.end());
    return *it->second;
}
コード例 #5
0
void BoxProcessingFunctional3D::getModificationPattern(std::vector<bool>& isWritten) const {
    std::vector<modif::ModifT> modified(isWritten.size());
    getTypeOfModification(modified);
    PLB_ASSERT(modified.size()==isWritten.size());
    for (pluint iBlock=0; iBlock<isWritten.size(); ++iBlock) {
        isWritten[iBlock] = modified[iBlock]==modif::nothing ? false:true;
    }
}
コード例 #6
0
MultiContainerBlock3D* MultiContainerBlock3D::clone (
        MultiBlockManagement3D const& multiBlockManagement ) const
{
    // By definition, a multi container block cannot be redistributed over
    //   a different block arrangement.
    PLB_ASSERT( false );
    return 0;
}
コード例 #7
0
ReductiveBoxProcessorGenerator2D::ReductiveBoxProcessorGenerator2D (
        ReductiveBoxProcessingFunctional2D* functional_,
        Box2D domain )
    : BoxedReductiveDataProcessorGenerator2D(domain),
      functional(functional_)
{
    // Must be non-null, because it is then used without further checks.
    PLB_ASSERT(functional);
}
コード例 #8
0
std::vector<MultiBlock3D*> MultiBlock3D::ProcessorStorage3D::getMultiBlocks() const
{
    std::vector<MultiBlock3D*> multiBlocks(multiBlockIds.size());
    for(pluint iBlock=0; iBlock<multiBlockIds.size(); ++iBlock) {
        multiBlocks[iBlock] = multiBlockRegistration3D().find(multiBlockIds[iBlock]);
        PLB_ASSERT( multiBlocks[iBlock] );
    }
    return multiBlocks;
}
コード例 #9
0
Box3D MultiBlockManagement3D::getUniqueBulk(plint blockId) const {
    Box3D uniqueBulk;
#ifdef PLB_DEBUG
    bool ok =
#endif
        sparseBlock.getUniqueBulk(blockId, uniqueBulk);
    PLB_ASSERT( ok );
    return uniqueBulk;
}
コード例 #10
0
Box3D MultiBlockManagement3D::getEnvelope(plint blockId) const {
    Box3D bulk;
#ifdef PLB_DEBUG
    bool ok =
#endif
        sparseBlock.getBulk(blockId, bulk);
    PLB_ASSERT( ok );
    return SmartBulk3D(sparseBlock, envelopeWidth, bulk).computeEnvelope();
}
コード例 #11
0
void writeOneBlockXmlSpec( MultiBlock2D& multiBlock, FileName fName, plint dataSize,
                           IndexOrdering::OrderingT ordering )
{
    fName.defaultExt("plb");
    MultiBlockManagement2D const& management = multiBlock.getMultiBlockManagement();
    std::vector<std::string> typeInfo = multiBlock.getTypeInfo();
    std::string blockName = multiBlock.getBlockName();
    PLB_ASSERT( !typeInfo.empty() );

    XMLwriter xml;
    XMLwriter& xmlMultiBlock = xml["Block2D"];
    xmlMultiBlock["General"]["Family"].setString(blockName);
    xmlMultiBlock["General"]["Datatype"].setString(typeInfo[0]);
    if (typeInfo.size()>1) {
        xmlMultiBlock["General"]["Descriptor"].setString(typeInfo[1]);
    }
    xmlMultiBlock["General"]["cellDim"].set(multiBlock.getCellDim());
    bool dynamicContent = false;
    xmlMultiBlock["General"]["dynamicContent"].set(dynamicContent);

    Array<plint,4> boundingBox = multiBlock.getBoundingBox().to_plbArray();
    xmlMultiBlock["Structure"]["BoundingBox"].set<plint,4>(boundingBox);
    xmlMultiBlock["Structure"]["EnvelopeWidth"].set(management.getEnvelopeWidth());
    xmlMultiBlock["Structure"]["NumComponents"].set(1);

    xmlMultiBlock["Data"]["File"].setString(FileName(fName).setExt("dat"));
    if (ordering == IndexOrdering::forward) {
        xmlMultiBlock["Data"]["IndexOrdering"].setString("zIsFastest");
    }
    else {
        xmlMultiBlock["Data"]["IndexOrdering"].setString("xIsFastest");
    }


    XMLwriter& xmlBulks = xmlMultiBlock["Data"]["Component"];
    xmlBulks.set<plint,4>(multiBlock.getBoundingBox().to_plbArray());

    xmlMultiBlock["Data"]["Offsets"].set(dataSize);

    xml.print(FileName(fName).defaultPath(global::directories().getOutputDir()));
}
コード例 #12
0
void MultiProcessing3D<OriginalGenerator,MutableGenerator>::multiBlocksWhichRequireUpdate (
        std::vector<MultiBlock3D*>& multiBlocksModifiedByProcessor,
        std::vector<modif::ModifT>& typesOfModification ) const
{
    multiBlocksModifiedByProcessor.clear();
    typesOfModification.clear();
    // If the generator includes envelopes, the envelopes need no update in any case.
    if ( ! BlockDomain::usesEnvelope(generator.appliesTo()) ) {
        // Otherwise, all blocks that have been modified by the processor must
        //   be updated.
        std::vector<modif::ModifT> allModifications(multiBlocks.size(), modif::undefined);
        // Default initialize to no-change.
        generator.getTypeOfModification(allModifications);
        for (pluint iBlock=0; iBlock<allModifications.size(); ++iBlock) {
            PLB_ASSERT( allModifications[iBlock] != modif::undefined );
            if (allModifications[iBlock] != modif::nothing) {
                multiBlocksModifiedByProcessor.push_back(multiBlocks[iBlock]);
                typesOfModification.push_back(allModifications[iBlock]);
            }
        }
    }
}
コード例 #13
0
void writeXmlSpec( MultiBlock2D& multiBlock, FileName fName,
                   std::vector<plint> const& offset, bool dynamicContent )
{
    fName.defaultExt("plb");
    MultiBlockManagement2D const& management = multiBlock.getMultiBlockManagement();
    std::map<plint,Box2D> const& bulks = management.getSparseBlockStructure().getBulks();
    PLB_ASSERT( offset.empty() || bulks.size()==offset.size() );
    std::vector<std::string> typeInfo = multiBlock.getTypeInfo();
    std::string blockName = multiBlock.getBlockName();
    PLB_ASSERT( !typeInfo.empty() );

    XMLwriter xml;
    XMLwriter& xmlMultiBlock = xml["Block2D"];
    xmlMultiBlock["General"]["Family"].setString(blockName);
    xmlMultiBlock["General"]["Datatype"].setString(typeInfo[0]);
    if (typeInfo.size()>1) {
        xmlMultiBlock["General"]["Descriptor"].setString(typeInfo[1]);
    }
    xmlMultiBlock["General"]["cellDim"].set(multiBlock.getCellDim());
    xmlMultiBlock["General"]["dynamicContent"].set(dynamicContent);
    xmlMultiBlock["General"]["globalId"].set(multiBlock.getId());

    Array<plint,4> boundingBox = multiBlock.getBoundingBox().to_plbArray();
    xmlMultiBlock["Structure"]["BoundingBox"].set<plint,4>(boundingBox);
    xmlMultiBlock["Structure"]["EnvelopeWidth"].set(management.getEnvelopeWidth());
    xmlMultiBlock["Structure"]["GridLevel"].set(management.getRefinementLevel());
    xmlMultiBlock["Structure"]["NumComponents"].set(bulks.size());

    xmlMultiBlock["Data"]["File"].setString(FileName(fName).setExt("dat"));

    XMLwriter& xmlBulks = xmlMultiBlock["Data"]["Component"];
    std::map<plint,Box2D>::const_iterator it = bulks.begin();
    plint iComp=0;
    for(; it != bulks.end(); ++it) {
        Box2D bulk = it->second;
        xmlBulks[iComp].set<plint,4>(bulk.to_plbArray());
        ++iComp;
    }
    if (!offset.empty()) {
        xmlMultiBlock["Data"]["Offsets"].set(offset);
    }

    // The following prints a unique list of dynamics-id pairs for all dynamics
    //   classes used in the multi-block. This is necessary, because dynamics
    //   classes may be ordered differently from one compilation to the other,
    //   or from one compiler to the other.
    //
    // Given that the dynamics classes are unique, they can be indexed by their
    //   name (which is not the case of the data processors below).
    std::map<std::string,int> dynamicsDict;
    multiBlock.getDynamicsDict(multiBlock.getBoundingBox(), dynamicsDict);
    if (!dynamicsDict.empty()) {
        XMLwriter& xmlDynamicsDict = xmlMultiBlock["Data"]["DynamicsDict"];
        for( std::map<std::string,int>::const_iterator it = dynamicsDict.begin();
             it != dynamicsDict.end(); ++it )
        {
            xmlDynamicsDict[it->first].set(it->second);
        }
    }

    // This is the only section in which actual content is stored outside the
    //   binary blob: the serialization of the data processors. This
    //   serialization was chosen to be in ASCII, because it takes little space
    //   and can be somewhat complicated.
    //
    // It is important that the processors are indexed by a continuous index
    //   "iProcessor". They cannot be indexed by the class name ("Name") or static
    //   id ("id") because several instances of the same class may occur.
    XMLwriter& xmlProcessors = xmlMultiBlock["Data"]["Processor"];
    std::vector<MultiBlock2D::ProcessorStorage2D> const& processors = multiBlock.getStoredProcessors();
    for (plint iProcessor=0; iProcessor<(plint)processors.size(); ++iProcessor) {
        int id = processors[iProcessor].getGenerator().getStaticId();
        if (id>=0) {
            Box2D domain;
            std::string data;
            processors[iProcessor].getGenerator().serialize(domain, data);
            xmlProcessors[iProcessor]["Name"].set(meta::processorRegistration2D().getName(id));
            xmlProcessors[iProcessor]["Domain"].set<plint,4>(domain.to_plbArray());
            xmlProcessors[iProcessor]["Data"].setString(data);
            xmlProcessors[iProcessor]["Level"].set(processors[iProcessor].getLevel());
            xmlProcessors[iProcessor]["Blocks"].set(processors[iProcessor].getMultiBlockIds());
        }
    }
    xml.print(FileName(fName).defaultPath(global::directories().getOutputDir()));
}
コード例 #14
0
void MultiProcessing3D<OriginalGenerator,MutableGenerator>::subdivideGenerator()
{
    // To start with, determine which multi-blocks are read and which are written
    std::vector<bool> isWritten(multiBlocks.size());
    generator.getModificationPattern(isWritten);
    PLB_ASSERT( isWritten.size() == multiBlocks.size() );

    // The reference block (the one for which the envelope is included if
    //   the domain generator.appliesTo() include the envelope) is either the
    //   multi-block which is written, or the first multi-block if all are read-only.
    pluint referenceBlock = 0;
    for (pluint iBlock=0; iBlock<isWritten.size(); ++iBlock) {
        if (isWritten[iBlock]) {
            referenceBlock = iBlock;
            break;
        }
    }

    // In debug mode, make sure that a most one multi-block is written when envelope is included.
#ifdef PLB_DEBUG
    if ( BlockDomain::usesEnvelope(generator.appliesTo()) ) {
        plint numWritten = 0;
        for (pluint iBlock=0; iBlock<isWritten.size(); ++iBlock) {
            if (isWritten[iBlock]) {
                ++numWritten;
            }
        }
        PLB_ASSERT( numWritten <= 1 );
    }
#endif
    
    // The first step is to access the domains of the the atomic blocks, as well
    //   as their IDs in each of the coupled multi blocks. The domain corresponds
    //   to the bulk and/or to the envelope, depending on the value of generator.appliesTo().
    std::vector<std::vector<DomainAndId3D> > domainsWithId(multiBlocks.size());
    for (pluint iMulti=0; iMulti<multiBlocks.size(); ++iMulti) {
        std::vector<plint> const& blocks
            = multiBlocks[iMulti]->getMultiBlockManagement().getLocalInfo().getBlocks();
        for (pluint iBlock=0; iBlock<blocks.size(); ++iBlock) {
            plint blockId = blocks[iBlock];
            SmartBulk3D bulk(multiBlocks[iMulti]->getMultiBlockManagement(), blockId);
            switch (generator.appliesTo()) {
                case BlockDomain::bulk:
                    domainsWithId[iMulti].push_back(DomainAndId3D(bulk.getBulk(),blockId));
                    break;
                case BlockDomain::bulkAndEnvelope:
                    // It's only the reference block that should have the envelope. However, we start
                    //   by assigning bulk and envelope to all of them, and eliminate overlapping
                    //   envelope components further down.
                    domainsWithId[iMulti].push_back(DomainAndId3D(bulk.computeEnvelope(),blockId));
                    break;
                case BlockDomain::envelope:
                    // For the reference block, we restrict ourselves to the envelope, because
                    //   that's the desired domain of application.
                    if (iMulti==referenceBlock) {
                        std::vector<Box3D> envelopeOnly;
                        except(bulk.computeEnvelope(), bulk.getBulk(), envelopeOnly);
                        for (pluint iEnvelope=0; iEnvelope<envelopeOnly.size(); ++iEnvelope) {
                            domainsWithId[iMulti].push_back(DomainAndId3D(envelopeOnly[iEnvelope], blockId));
                        }
                    }
                    // For the other blocks, we need to take bulk and envelope, because all these domains
                    //   potentially intersect with the envelope of the reference block.
                    else {
                        domainsWithId[iMulti].push_back(DomainAndId3D(bulk.computeEnvelope(),blockId));
                    }
                    break;
            }
        }
    }

    // If the multi-blocks are not at the same level of grid refinement, the level
    //   of the first block is taken as reference, and the coordinates of the other
    //   blocks are rescaled accordingly.
    plint firstLevel = multiBlocks[0]->getMultiBlockManagement().getRefinementLevel();
    for (pluint iMulti=1; iMulti<multiBlocks.size(); ++iMulti) {
        plint relativeLevel = firstLevel -
                             multiBlocks[iMulti]->getMultiBlockManagement().getRefinementLevel();
        if (relativeLevel != 0) {
            for (pluint iBlock=0; iBlock<domainsWithId[iMulti].size(); ++iBlock) {
                domainsWithId[iMulti][iBlock].domain =
                    global::getDefaultMultiScaleManager().scaleBox (
                            domainsWithId[iMulti][iBlock].domain, relativeLevel );
            }
        }
    }

    // If the envelopes are included as well, it is assumed that at most one of
    //   the multi blocks has write-access. All others (those that have read-only
    //   access) need to be non-overlaping, to avoid multiple writes on the cells
    //   of the write-access-multi-block. Thus, overlaps are now eliminitated in
    //   the read-access-multi-blocks.
    if ( BlockDomain::usesEnvelope(generator.appliesTo()) ) {
        for (pluint iMulti=0; iMulti<multiBlocks.size(); ++iMulti) {
            if (!isWritten[iMulti]) {
                std::vector<DomainAndId3D> nonOverlapBlocks(getNonOverlapingBlocks(domainsWithId[iMulti]));
                domainsWithId[iMulti].swap(nonOverlapBlocks);
            }
        }
    }

    // This is the heart of the whole procedure: intersecting atomic blocks
    //   between all coupled multi blocks are identified.
    std::vector<Box3D> finalDomains;
    std::vector<std::vector<plint> > finalIds;
    intersectDomainsAndIds(domainsWithId, finalDomains, finalIds);

    // And, to end with, re-create processor generators adapted to the
    //   computed domains of intersection.
    if ( BlockDomain::usesEnvelope(generator.appliesTo()) ) {
        // In case the envelope is included, periodicity must be explicitly treated.
        //   Indeed, the user indicates the domain of applicability with respect to
        //   bulk nodes only. The generator is therefore shifted in all space directions
        //   to englobe periodic boundary nodes as well.
        plint shiftX = firstMultiBlock->getNx();
        plint shiftY = firstMultiBlock->getNy();
        plint shiftZ = firstMultiBlock->getNz();
        PeriodicitySwitch3D const& periodicity = firstMultiBlock->periodicity();
        for (plint orientX=-1; orientX<=+1; ++orientX) {
            for (plint orientY=-1; orientY<=+1; ++orientY) {
                for (plint orientZ=-1; orientZ<=+1; ++orientZ) {
                    if (periodicity.get(orientX,orientY,orientZ)) {
                        extractGeneratorOnBlocks( finalDomains, finalIds,
                                                  orientX*shiftX, orientY*shiftY, orientZ*shiftZ );
                    }
                }
            }
        }
    }
    else {
        extractGeneratorOnBlocks(finalDomains, finalIds);
    }
}
コード例 #15
0
DataUnSerializer* MultiGrid2D::getBlockUnSerializer (
        Box2D const& domain, IndexOrdering::OrderingT ordering )
{
    PLB_ASSERT(false);
    return 0;
}
コード例 #16
0
void MultiContainerBlock3D::copyReceive (
                MultiBlock3D const& fromBlock, Box3D const& fromDomain,
                Box3D const& toDomain, modif::ModifT whichData )
{
    PLB_ASSERT( false );
}