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