bool MeshTestUtility::checkConstraintConsistency(MeshPtr meshMinimumRule) { MeshTopologyViewPtr meshTopo = meshMinimumRule->getTopology(); GDAMinimumRule* minRule = dynamic_cast<GDAMinimumRule*>(meshMinimumRule->globalDofAssignment().get()); bool consistent = true; for (IndexType cellID : meshMinimumRule->cellIDsInPartition()) { CellConstraints constraints = minRule->getCellConstraints(cellID); CellPtr cell = meshTopo->getCell(cellID); CellTopoPtr cellTopo = cell->topology(); for (int d=0; d<cellTopo->getDimension(); d++) { int scCount = cellTopo->getSubcellCount(d); for (int scord=0; scord<scCount; scord++) { IndexType entityIndex = cell->entityIndex(d, scord); AnnotatedEntity constrainingEntity = constraints.subcellConstraints[d][scord]; bool isConsistent = constraintIsConsistent(meshTopo, constrainingEntity, d, entityIndex, true); if (!isConsistent) { cout << "Failed consistency test for standard constraints on cell " << cellID << ", " << CamelliaCellTools::entityTypeString(d) << " " << scord << endl; consistent = false; break; } // now, check space-only constraints (for space-time meshes), if these are defined for this subcell if (constraints.spatialSliceConstraints != Teuchos::null) { AnnotatedEntity constrainingEntityForSpatialSlice = constraints.spatialSliceConstraints->subcellConstraints[d][scord]; if (constrainingEntityForSpatialSlice.cellID != -1) { isConsistent = constraintIsConsistent(meshTopo, constrainingEntityForSpatialSlice, d, entityIndex, true); } if (!isConsistent) { cout << "Failed consistency test for spatial slice on cell " << cellID << ", " << CamelliaCellTools::entityTypeString(d) << " " << scord << endl; consistent = false; break; } } } if (!consistent) break; } if (!consistent) break; } return consistent; }
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) ); }