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) ); }