// Find a good edge forAll(singleEdges, edgeI) { SLList<label> pointChain; bool blockHead = false; bool blockTail = false; if (!singleEdgeUsage[edgeI]) { // found a new edge singleEdgeUsage[edgeI] = true; label newEdgeStart = singleEdges[edgeI].start(); label newEdgeEnd = singleEdges[edgeI].end(); pointChain.insert(newEdgeStart); pointChain.append(newEdgeEnd); # ifdef DEBUG_CHAIN Info<< "found edge to start with: " << singleEdges[edgeI] << endl; # endif // Check if head or tail are blocked forAll(cellPoints, pointI) { if (cellPoints[pointI] == newEdgeStart) { if (pointUsage[pointI] > 2) { # ifdef DEBUG_CHAIN Info<< "start head blocked" << endl; # endif blockHead = true; } } else if (cellPoints[pointI] == newEdgeEnd) { if (pointUsage[pointI] > 2) { # ifdef DEBUG_CHAIN Info<< "start tail blocked" << endl; # endif blockTail = true; } } } bool stopSearching = false; // Go through the unused edges and try to chain them up do { stopSearching = false; forAll(singleEdges, addEdgeI) { if (!singleEdgeUsage[addEdgeI]) { // Grab start and end of the candidate label addStart = singleEdges[addEdgeI].start(); label addEnd = singleEdges[addEdgeI].end(); # ifdef DEBUG_CHAIN Info<< "Trying candidate " << singleEdges[addEdgeI] << endl; # endif // Try to add the edge onto the head if (!blockHead) { if (pointChain.first() == addStart) { // Added at start mark as used pointChain.insert(addEnd); singleEdgeUsage[addEdgeI] = true; } else if (pointChain.first() == addEnd) { pointChain.insert(addStart); singleEdgeUsage[addEdgeI] = true; } } // Try the other end only if the first end // did not add it if (!blockTail && !singleEdgeUsage[addEdgeI]) { if (pointChain.last() == addStart) { // Added at start mark as used pointChain.append(addEnd); singleEdgeUsage[addEdgeI] = true; } else if (pointChain.last() == addEnd) { pointChain.append(addStart); singleEdgeUsage[addEdgeI] = true; } } // check if the new head or tail are blocked label curEdgeStart = pointChain.first(); label curEdgeEnd = pointChain.last(); # ifdef DEBUG_CHAIN Info<< "curEdgeStart: " << curEdgeStart << " curEdgeEnd: " << curEdgeEnd << endl; # endif forAll(cellPoints, pointI) { if (cellPoints[pointI] == curEdgeStart) { if (pointUsage[pointI] > 2) { # ifdef DEBUG_CHAIN Info<< "head blocked" << endl; # endif blockHead = true; } } else if (cellPoints[pointI] == curEdgeEnd) { if (pointUsage[pointI] > 2) { # ifdef DEBUG_CHAIN Info<< "tail blocked" << endl; # endif blockTail = true; } } } // Check if the loop is closed if (curEdgeStart == curEdgeEnd) { # ifdef DEBUG_CHAIN Info<< "closed loop" << endl; # endif pointChain.removeHead(); blockHead = true; blockTail = true; stopSearching = true; } # ifdef DEBUG_CHAIN Info<< "current pointChain: " << pointChain << endl; # endif if (stopSearching) break; } } } while (stopSearching); }
// Constructor from components Foam::labelList Foam::bandCompression(const labelListList& cellCellAddressing) { labelList newOrder(cellCellAddressing.size()); // the business bit of the renumbering SLList<label> nextCell; labelList visited(cellCellAddressing.size()); label currentCell; label cellInOrder = 0; // reset the visited cells list forAll (visited, cellI) { visited[cellI] = 0; } // loop over the cells forAll (visited, cellI) { // find the first cell that has not been visited yet if (visited[cellI] == 0) { currentCell = cellI; // use this cell as a start nextCell.append(currentCell); // loop through the nextCell list. Add the first cell into the // cell order if it has not already been visited and ask for its // neighbours. If the neighbour in question has not been visited, // add it to the end of the nextCell list while (nextCell.size()) { currentCell = nextCell.removeHead(); if (visited[currentCell] == 0) { visited[currentCell] = 1; // add into cellOrder newOrder[cellInOrder] = currentCell; cellInOrder++; // find if the neighbours have been visited const labelList& neighbours = cellCellAddressing[currentCell]; forAll (neighbours, nI) { if (visited[neighbours[nI]] == 0) { // not visited, add to the list nextCell.append(neighbours[nI]); } } } } }
void Foam::immersedBoundaryFvPatch::makeTriAddressing() const { if (debug) { InfoIn("void immersedBoundaryFvPatch::makeTriAddressing() const") << "creating tri addressing for immersed boundary " << name() << endl; } // It is an error to attempt to recalculate // if the pointer is already set if (cellsToTriAddrPtr_ || cellsToTriWeightsPtr_) { FatalErrorIn("immersedBoundaryFvPatch::makeTriAddressing() const") << "tri addressing already exist" << "for immersed boundary" << name() << abort(FatalError); } // Get reference to tri patch and hit faces const triSurface& triPatch = ibPolyPatch_.ibMesh(); const vectorField& triCentres = triPatch.faceCentres(); const labelList& hf = hitFaces(); const vectorField& ibp = ibPoints(); // Create a markup field and mark all tris containing an ib point with its // index labelList hitTris(triPatch.size(), -1); forAll (hf, hfI) { hitTris[hf[hfI]] = hfI; } // Allocate storage cellsToTriAddrPtr_ = new labelListList(triPatch.size()); labelListList& addr = *cellsToTriAddrPtr_; cellsToTriWeightsPtr_ = new scalarListList(triPatch.size()); scalarListList& w = *cellsToTriWeightsPtr_; // Algorithm: // For each tri face, check if it contains an IB point // - if so, set the addressing to the index of IB point and weight to 1 // - if not, search the neighbouring faces of the visited faces until // at least 3 IB points are found, or the neighbourhood is exhausted. // When a sufficient number of points is found, calculate the weights // using inverse distance weighting // Get addressing from the triangular patch const labelListList& pf = triPatch.pointFaces(); forAll (triPatch, triI) { if (hitTris[triI] > -1) { // Triangle contains IB point addr[triI].setSize(1); w[triI].setSize(1); addr[triI] = hitTris[triI]; w[triI] = 1; } else { // No direct hit. Start a neighbourhood search // Record already visited faces labelHashSet visited; // Collect new faces to visit SLList<label> nextToVisit; // Collect IB points for interpolation labelHashSet ibPointsToUse; // Initialise with the original tri nextToVisit.insert(triI); do { const label curTri = nextToVisit.removeHead(); // Discard tri if already visited if (visited[curTri]) continue; visited.insert(curTri); const triFace& curTriPoints = triPatch[curTri]; // For all current points of face, pick up neighbouring faces forAll (curTriPoints, tpI) { const labelList curNbrs = pf[curTriPoints[tpI]]; forAll (curNbrs, nbrI) { if (!visited.found(curNbrs[nbrI])) { // Found a face which is not visited. Add it to // the list of faces to visit nextToVisit.append(curNbrs[nbrI]); if (hitTris[curNbrs[nbrI]] > -1) { // Found a neighbour with a hit: use this // IB point ibPointsToUse.insert(hitTris[curNbrs[nbrI]]); } } } } } while ( ibPointsToUse.size() < 3 && !nextToVisit.empty() ); // Found neighbourhood: collect addressing and weights addr[triI] = ibPointsToUse.toc(); w[triI].setSize(addr[triI].size()); labelList& curAddr = addr[triI]; scalarList& curW = w[triI]; vector curTriCentre = triCentres[triI]; scalar sumW = 0; forAll (curAddr, ibI) { curW[ibI] = 1/mag(curTriCentre - ibp[curAddr[ibI]]); sumW += curW[ibI]; } // Divide weights by sum distance forAll (curW, ibI) { curW[ibI] /= sumW; } } }