示例#1
0
MeshPartitionPolicyPtr MeshPartitionPolicy::inducedPartitionPolicyFromRefinedMesh(MeshTopologyViewPtr inducedMeshTopo, MeshPtr inducingRefinedMesh)
{
    // generate using the inducing mesh
    vector<GlobalIndexTypeToCast> myEntries;

    auto myCellIDs = &inducingRefinedMesh->cellIDsInPartition();
    bool rotateChildOrdinalThatOwns = false; // the 6-27-16 modification -- I don't think this actually helps with load balance, the way things are presently implemented, and it may introduce additional communication costs
    if (rotateChildOrdinalThatOwns)
    {
        /*
         Modification 6-27-16: instead of assigning parent to owner of first child,
         assign parent to owner of child with ordinal equal to the level of the
         parent, modulo the number of children.  This should result in better load
         balancing for multigrid.
         */
        for (GlobalIndexType myCellID : *myCellIDs)
        {
            IndexType ancestralCellIndex = myCellID;
            bool hasMatchingChild = true;
            while (inducingRefinedMesh->getTopology()->isValidCellIndex(ancestralCellIndex)
                    && !inducedMeshTopo->isValidCellIndex(ancestralCellIndex))
            {
                CellPtr myCell = inducingRefinedMesh->getTopology()->getCell(ancestralCellIndex);
                CellPtr parent = myCell->getParent();
                TEUCHOS_TEST_FOR_EXCEPTION(parent == Teuchos::null, std::invalid_argument, "ancestor not found in inducedMeshTopo");
                int childOrdinal = parent->findChildOrdinal(myCell->cellIndex());
                int numChildren = parent->numChildren();
                hasMatchingChild = ((parent->level() % numChildren) == childOrdinal);
                ancestralCellIndex = parent->cellIndex();
            }
            if (hasMatchingChild)
            {
                myEntries.push_back(ancestralCellIndex);
                myEntries.push_back(myCellID);
            }
        }
    }
    else
    {
        // first child is always owner
        for (GlobalIndexType myCellID : *myCellIDs)
        {
            IndexType ancestralCellIndex = myCellID;
            bool isFirstChild = true;
            while (isFirstChild && !inducedMeshTopo->isValidCellIndex(ancestralCellIndex))
            {
                CellPtr myCell = inducingRefinedMesh->getTopology()->getCell(ancestralCellIndex);
                CellPtr parent = myCell->getParent();
                TEUCHOS_TEST_FOR_EXCEPTION(parent == Teuchos::null, std::invalid_argument, "ancestor not found in inducedMeshTopo");
                int childOrdinal = parent->findChildOrdinal(myCell->cellIndex());
                isFirstChild = (childOrdinal == 0);
                ancestralCellIndex = parent->cellIndex();
            }
            if (isFirstChild)
            {
                myEntries.push_back(ancestralCellIndex);
                myEntries.push_back(myCellID);
            }
        }
    }
    // all-gather the entries
    vector<GlobalIndexTypeToCast> allEntries;
    vector<int> offsets;
    MPIWrapper::allGatherVariable(*inducingRefinedMesh->Comm(), allEntries, myEntries, offsets);

    map<GlobalIndexType,GlobalIndexType> cellIDMap;
    for (int i=0; i<allEntries.size()/2; i++)
    {
        GlobalIndexType ancestralCellIndex = allEntries[2*i+0];
        GlobalIndexType inducingMeshCellID = allEntries[2*i+1];
        cellIDMap[ancestralCellIndex] = inducingMeshCellID;
    }

    return Teuchos::rcp( new InducedMeshPartitionPolicy(inducingRefinedMesh, cellIDMap) );
}