int DofOrdering::getDofIndex(int varID, int basisDofOrdinal, int sideIndex, int subSideIndex) { TEUCHOS_TEST_FOR_EXCEPTION( ( _indexNeedsToBeRebuilt ), std::invalid_argument, "getDofIndex called when _indexNeedsToBeRebuilt = true. Call rebuildIndex() first."); if (subSideIndex >= 0) { // then we've got a MultiBasis, and the basisDofOrdinal we have is *relative* to the subbasis BasisPtr basis = getBasis(varID,sideIndex); if ( ! BasisFactory::basisFactory()->isMultiBasis(basis) ) { TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "subSideIndex >= 0 for non-MultiBasis..."); } MultiBasis<>* multiBasis = (MultiBasis<>*) basis.get(); //cout << "(basisDofOrdinal, subSideIndex) : (" << basisDofOrdinal << ", " << subSideIndex << ") --> "; basisDofOrdinal = multiBasis->relativeToAbsoluteDofOrdinal(basisDofOrdinal,subSideIndex); //cout << basisDofOrdinal << endl; } pair<int,int> key = make_pair(varID, sideIndex); map< pair<int,int>, vector<int> >::iterator entryIt = indices.find(key); if ( entryIt != indices.end() ) { int dofIndex = ((*entryIt).second)[basisDofOrdinal]; if ((dofIndex < 0) || (dofIndex >= _nextIndex)) { cout << "dofIndex out of bounds.\n"; TEUCHOS_TEST_FOR_EXCEPTION( (dofIndex < 0) || (dofIndex >= _nextIndex), std::invalid_argument, "dofIndex out of bounds."); } return dofIndex; } else { cout << "No entry found for dofIndex\n"; TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "No entry found for DofIndex."); return -1; } }
bool MeshTestUtility::checkMeshDofConnectivities(Teuchos::RCP<Mesh> mesh) { int numCells = mesh->activeElements().size(); bool success = true; int numGlobalDofs = mesh->numGlobalDofs(); vector<int> globalDofIndexHitCount(numGlobalDofs,0); for (int cellIndex=0; cellIndex<numCells; cellIndex++) { Teuchos::RCP<Element> elem = mesh->activeElements()[cellIndex]; GlobalIndexType cellID = elem->cellID(); DofOrdering trialOrder = *(elem->elementType()->trialOrderPtr.get()); vector< int > trialIDs = mesh->bilinearForm()->trialIDs(); for (vector< int >::iterator trialIt = trialIDs.begin(); trialIt != trialIDs.end(); trialIt++) { int trialID = *(trialIt); const vector<int>* sidesForVar = &trialOrder.getSidesForVarID(trialID); for (vector<int>::const_iterator sideIt = sidesForVar->begin(); sideIt != sidesForVar->end(); sideIt++) { int sideIndex = *sideIt; int numBasisDofs = trialOrder.getBasisCardinality(trialID, sideIndex); for (int dofOrdinal=0; dofOrdinal<numBasisDofs; dofOrdinal++) { // a very basic check on the mesh dof ordering: the globalDofIndices for all localDofs should not be negative! int localDofIndex = trialOrder.getDofIndex(trialID, dofOrdinal, sideIndex); int globalDofIndex = mesh->globalDofIndex(cellID,localDofIndex); if (globalDofIndex < 0) { cout << "mesh->globalDofIndex(" << cellID << "," << localDofIndex << ") = " << globalDofIndex << " < 0. Error!"; success = false; } else if (globalDofIndex >= mesh->numGlobalDofs()) { cout << "mesh->globalDofIndex(" << cellID << "," << localDofIndex << ") = " << globalDofIndex << " >= mymesh->numGlobalDofs(). Error!"; success = false; } else { globalDofIndexHitCount[globalDofIndex]++; } } // now a more subtle check: given the mesh layout (that all vertices are specified CCW), // the dofs for boundary variables (fluxes & traces) should be reversed between element and its neighbor if (mesh->bilinearForm()->isFluxOrTrace(trialID)) { CellPtr cell = mesh->getTopology()->getCell(cellID); if (! mesh->getTopology()->getCell(cellID)->isBoundary(sideIndex)) // not boundary... { // if (neighbor->cellID() != -1) { // not boundary... int ancestralSideIndexInNeighbor; Teuchos::RCP<Element> neighbor = mesh->ancestralNeighborForSide(elem, sideIndex, ancestralSideIndexInNeighbor); Teuchos::RCP<DofOrdering> neighborTrialOrder = neighbor->elementType()->trialOrderPtr; int neighborNumBasisDofs = neighborTrialOrder->getBasisCardinality(trialID,ancestralSideIndexInNeighbor); if (neighborNumBasisDofs != numBasisDofs) { if ( mesh->usePatchBasis() ) { cout << "FAILURE: usePatchBasis==true, but neighborNumBasisDofs != numBasisDofs.\n"; success = false; continue; } if ( neighbor->isParent() ) { // Here, we need to deal with the possibility that neighbor is a parent, broken along the shared side // -- if so, we have a MultiBasis, and we need to match with each of neighbor's descendants along that side... vector< pair<int,int> > descendantsForSide = neighbor->getDescendantsForSide(ancestralSideIndexInNeighbor); vector< pair<int,int> >:: iterator entryIt; int descendantIndex = -1; for (entryIt = descendantsForSide.begin(); entryIt != descendantsForSide.end(); entryIt++) { descendantIndex++; int neighborSubSideIndexInMe = GDAMaximumRule2D::neighborChildPermutation(descendantIndex, descendantsForSide.size()); int neighborCellID = (*entryIt).first; int mySideIndexInNeighbor = (*entryIt).second; neighbor = mesh->getElement(neighborCellID); int neighborNumDofs = neighbor->elementType()->trialOrderPtr->getBasisCardinality(trialID,mySideIndexInNeighbor); for (int dofOrdinal=0; dofOrdinal<neighborNumDofs; dofOrdinal++) { int myLocalDofIndex; if ((descendantsForSide.size() > 1) && !mesh->usePatchBasis()) { myLocalDofIndex = elem->elementType()->trialOrderPtr->getDofIndex(trialID,dofOrdinal,sideIndex,neighborSubSideIndexInMe); } else { myLocalDofIndex = elem->elementType()->trialOrderPtr->getDofIndex(trialID,dofOrdinal,sideIndex); } int globalDofIndex = mesh->globalDofIndex(cellID,myLocalDofIndex); // neighbor's dofs are in reverse order from mine along each side int permutedDofOrdinal = GDAMaximumRule2D::neighborDofPermutation(dofOrdinal,neighborNumDofs); int neighborLocalDofIndex = neighbor->elementType()->trialOrderPtr->getDofIndex(trialID,permutedDofOrdinal,mySideIndexInNeighbor); int neighborsGlobalDofIndex = mesh->globalDofIndex(neighbor->cellID(),neighborLocalDofIndex); if (neighborsGlobalDofIndex != globalDofIndex) { cout << "FAILURE: checkDofConnectivities--(cellID, localDofIndex) : (" << cellID << ", " << myLocalDofIndex << ") != ("; cout << neighborCellID << ", " << neighborLocalDofIndex << ") -- "; cout << globalDofIndex << " != " << neighborsGlobalDofIndex << "\n"; success = false; } } } } else if (neighbor->getNeighborCellID(ancestralSideIndexInNeighbor) != cellID) { // elem is small, neighbor big // first, find my leaf index in neighbor: int ancestorCellID = neighbor->getNeighborCellID(ancestralSideIndexInNeighbor); Teuchos::RCP<Element> ancestor = mesh->getElement(ancestorCellID); int ancestorSideIndex = neighbor->getSideIndexInNeighbor(ancestralSideIndexInNeighbor); vector< pair<int,int> > descendantsForSide = ancestor->getDescendantsForSide(ancestorSideIndex); int descendantIndex = 0; int leafIndexInNeighbor = -1; for (vector< pair<int,int> >::iterator entryIt = descendantsForSide.begin(); entryIt != descendantsForSide.end(); entryIt++, descendantIndex++) { if (entryIt->first == cellID) { leafIndexInNeighbor = GDAMaximumRule2D::neighborChildPermutation(descendantIndex, descendantsForSide.size()); break; } } if (leafIndexInNeighbor == -1) { TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "Could not determine leafIndexInNeigbor."); } // check whether the basis is the right size: MultiBasis<>* neighborMultiBasis = (MultiBasis<>*) neighbor->elementType()->trialOrderPtr->getBasis(trialID,ancestralSideIndexInNeighbor).get(); BasisPtr neighborLeafBasis = neighborMultiBasis->getLeafBasis(leafIndexInNeighbor); if (numBasisDofs != neighborLeafBasis->getCardinality()) { success = false; cout << "FAILURE: cellID " << cellID << "'s basis for trialID " << trialID; cout << " along sideIndex " << sideIndex << " has cardinality " << numBasisDofs; cout << ", but neighbor leaf basis along that side (cellID " << neighbor->cellID(); cout << ", sideIndex " << ancestralSideIndexInNeighbor; cout << ", leaf node " << leafIndexInNeighbor; cout << ") has cardinality " << neighborLeafBasis->getCardinality() << endl; } else { // cardinalities match, check that global dofs line up for (int dofOrdinal = 0; dofOrdinal < numBasisDofs; dofOrdinal++) { int permutedDofOrdinal = GDAMaximumRule2D::neighborDofPermutation(dofOrdinal, numBasisDofs); int neighborDofOrdinal = neighborMultiBasis->relativeToAbsoluteDofOrdinal(permutedDofOrdinal, leafIndexInNeighbor); int neighborLocalDofIndex = neighbor->elementType()->trialOrderPtr->getDofIndex(trialID, neighborDofOrdinal,ancestralSideIndexInNeighbor); int neighborGlobalDofIndex = mesh->globalDofIndex(neighbor->cellID(), neighborLocalDofIndex); int myLocalDofIndex = elem->elementType()->trialOrderPtr->getDofIndex(trialID, dofOrdinal, sideIndex); int myGlobalDofIndex = mesh->globalDofIndex(cellID, myLocalDofIndex); if (neighborGlobalDofIndex != myGlobalDofIndex) { success = false; cout << "FAILURE: checkDofConnectivities--(cellID, localDofIndex) : (" << cellID << ", "; cout << myLocalDofIndex << ") != ("; cout << neighbor->cellID() << ", " << neighborLocalDofIndex << ") -- "; cout << myGlobalDofIndex << " != " << neighborGlobalDofIndex << "\n"; } } } } else { cout << "FAILURE: cellID " << cellID << "'s basis for trialID " << trialID; cout << " along sideIndex " << sideIndex << " has cardinality " << numBasisDofs; cout << ", but neighbor along that side (cellID " << neighbor->cellID(); cout << ", sideIndex " << ancestralSideIndexInNeighbor << ") has cardinality " << neighborNumBasisDofs << endl; success = false; } } else // (neighborNumBasisDofs == numBasisDofs) { if (! neighbor->isParent() ) { for (int dofOrdinal=0; dofOrdinal<numBasisDofs; dofOrdinal++) { int permutedDofOrdinal = GDAMaximumRule2D::neighborDofPermutation(dofOrdinal,numBasisDofs); int neighborsLocalDofIndex = neighborTrialOrder->getDofIndex(trialID, permutedDofOrdinal, ancestralSideIndexInNeighbor); GlobalIndexType neighborsGlobalDofIndex = mesh->globalDofIndex(neighbor->cellID(),neighborsLocalDofIndex); int localDofIndex = trialOrder.getDofIndex(trialID, dofOrdinal, sideIndex); GlobalIndexType globalDofIndex = mesh->globalDofIndex(cellID,localDofIndex); if (neighborsGlobalDofIndex != globalDofIndex) { cout << "FAILURE: cellID " << cellID << "'s neighbor " << sideIndex << "'s globalDofIndex " << neighborsGlobalDofIndex << " doesn't match element globalDofIndex " << globalDofIndex << ". (trialID, element dofOrdinal)=(" << trialID << "," << dofOrdinal << ")" << endl; success = false; } } } else // neighbor->isParent() { // for PatchBasis: for (int dofOrdinal=0; dofOrdinal<numBasisDofs; dofOrdinal++) { int localDofIndex = trialOrder.getDofIndex(trialID, dofOrdinal, sideIndex); GlobalIndexType globalDofIndex = mesh->globalDofIndex(cellID,localDofIndex); vector< pair<int,int> > descendantsForSide = neighbor->getDescendantsForSide(ancestralSideIndexInNeighbor); vector< pair<int,int> >:: iterator entryIt; for (entryIt = descendantsForSide.begin(); entryIt != descendantsForSide.end(); entryIt++) { GlobalIndexType neighborCellID = (*entryIt).first; int mySideIndexInNeighbor = (*entryIt).second; neighbor = mesh->getElement(neighborCellID); neighborTrialOrder = neighbor->elementType()->trialOrderPtr; int permutedDofOrdinal = GDAMaximumRule2D::neighborDofPermutation(dofOrdinal,numBasisDofs); int neighborsLocalDofIndex = neighborTrialOrder->getDofIndex(trialID, permutedDofOrdinal, mySideIndexInNeighbor); GlobalIndexType neighborsGlobalDofIndex = mesh->globalDofIndex(neighbor->cellID(),neighborsLocalDofIndex); if (neighborsGlobalDofIndex != globalDofIndex) { cout << "FAILURE: cellID " << cellID << "'s neighbor on side " << sideIndex; cout << " (cellID " << neighborCellID << ")'s globalDofIndex " << neighborsGlobalDofIndex; cout << " doesn't match element globalDofIndex " << globalDofIndex; cout << ". (trialID, element dofOrdinal): (" << trialID << "," << dofOrdinal << ")" << endl; cout << " (cellID,localDofIndex): (" << cellID << "," << localDofIndex << ") ≠ ("; cout << neighborCellID << "," << neighborsLocalDofIndex << ")\n"; success = false; } } } } } } } } } } for (int i=0; i<numGlobalDofs; i++) { if ( globalDofIndexHitCount[i] == 0 ) { success = false; cout << "FAILURE: meshDofConnectivity: globalDofIndex " << i << " is unreachable.\n"; } } return success; }