/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2024-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. OpenFOAM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OpenFOAM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenFOAM. If not, see . \*---------------------------------------------------------------------------*/ #include "cellPointConnectivity.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // namespace Foam { defineTypeNameAndDebug(cellPointConnectivity, 0); } // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // void Foam::cellPointConnectivity::generateCellPointConnectivity(label cellI) { const cell& cFaceLabels(mesh_.cells()[cellI]); const labelList cPointLabels(cFaceLabels.labels(mesh_.faces())); const edgeList cEdges(cFaceLabels.edges(mesh_.faces())); // Generate a sorted list of points and corresponding point indices labelPairList pointLabelPointIndices(cPointLabels.size()); forAll(cPointLabels, pointI) { pointLabelPointIndices[pointI] = labelPair(cPointLabels[pointI], pointI); } sort(pointLabelPointIndices); // Generate a sorted list of edge labels and corresponding edge indices // Negative values indicate an edge which runs in an opposite direction to // the face node listing labelListList edgeLabelsEdgeIndices ( 2*cEdges.size(), labelList(3, label(-1)) ); forAll(cEdges, cEdgeI) { edgeLabelsEdgeIndices[2*cEdgeI][0] = cEdges[cEdgeI][0]; edgeLabelsEdgeIndices[2*cEdgeI][1] = cEdges[cEdgeI][1]; edgeLabelsEdgeIndices[2*cEdgeI][2] = cEdgeI; edgeLabelsEdgeIndices[2*cEdgeI+1][0] = cEdges[cEdgeI][1]; edgeLabelsEdgeIndices[2*cEdgeI+1][1] = cEdges[cEdgeI][0]; edgeLabelsEdgeIndices[2*cEdgeI+1][2] = - cEdgeI - 1; } sort(edgeLabelsEdgeIndices); // Generate a sorted list of edge labels and correspoinding face indices labelListList edgeLabelsFaceIndices; forAll(cFaceLabels, cFaceI) { const face& cFace(mesh_.faces()[cFaceLabels[cFaceI]]); const bool owner(mesh_.faceOwner()[cFaceLabels[cFaceI]] == cellI); const label cFaceNEdges(cFace.size()); forAll(cFace, cFaceEdgeI) { edgeLabelsFaceIndices.append(labelList(3, label(-1))); edgeLabelsFaceIndices.last()[0] = cFace[(cFaceEdgeI + owner) % cFaceNEdges]; edgeLabelsFaceIndices.last()[1] = cFace[(cFaceEdgeI + !owner) % cFaceNEdges]; edgeLabelsFaceIndices.last()[2] = cFaceI; } } sort(edgeLabelsFaceIndices); // Assemble lists of edge-face and cell-face connectivities // Negative values indicate an edge which runs in an opposite direction to // the face node listing labelListList edgeFaceIndices(cEdges.size()); labelListList faceEdgeIndices(cFaceLabels.size()); forAll(edgeLabelsFaceIndices, I) { const label edgeLabelsEdgeIndex(edgeLabelsEdgeIndices[I][2]); const label absCellEdgeEdgeIndex ( edgeLabelsEdgeIndex >= 0 ? edgeLabelsEdgeIndex : - edgeLabelsEdgeIndex - 1 ); const label absCellEdgeFaceIndex(edgeLabelsFaceIndices[I][2]); const label edgeLabelsFaceIndex ( edgeLabelsEdgeIndex >= 0 ? absCellEdgeFaceIndex : - absCellEdgeFaceIndex - 1 ); edgeFaceIndices[absCellEdgeEdgeIndex].append(edgeLabelsFaceIndex); faceEdgeIndices[absCellEdgeFaceIndex].append(edgeLabelsEdgeIndex); } // Generate a list of point labels and face index pairs labelListList pointLabelEdgeIndexFaceIndexPairs; forAll(cEdges, edgeI) { const labelPair pointIndices(cEdges[edgeI]); const labelPair faceIndices ( edgeFaceIndices[edgeI][0], edgeFaceIndices[edgeI][1] ); const labelPair absFaceIndices ( faceIndices[0] >= 0 ? faceIndices[0] : - faceIndices[0] - 1, faceIndices[1] >= 0 ? faceIndices[1] : - faceIndices[1] - 1 ); const bool order(faceIndices[0] > faceIndices[1]); pointLabelEdgeIndexFaceIndexPairs.append(labelList(4, label(-1))); pointLabelEdgeIndexFaceIndexPairs.last()[0] = pointIndices[0]; pointLabelEdgeIndexFaceIndexPairs.last()[1] = edgeI; pointLabelEdgeIndexFaceIndexPairs.last()[2] = absFaceIndices[order]; pointLabelEdgeIndexFaceIndexPairs.last()[3] = absFaceIndices[!order]; pointLabelEdgeIndexFaceIndexPairs.append(labelList(4, label(-1))); pointLabelEdgeIndexFaceIndexPairs.last()[0] = pointIndices[1]; pointLabelEdgeIndexFaceIndexPairs.last()[1] = edgeI; pointLabelEdgeIndexFaceIndexPairs.last()[2] = absFaceIndices[!order]; pointLabelEdgeIndexFaceIndexPairs.last()[3] = absFaceIndices[order]; } sort(pointLabelEdgeIndexFaceIndexPairs); // Assemble a list of point face pairs from the sorted lists labelListList pointEdgeIndices(cPointLabels.size()); List > > pointFaceIndexPairs(cPointLabels.size()); { label I(0); label pointLabelOld(pointLabelEdgeIndexFaceIndexPairs[0][0]); forAll ( pointLabelEdgeIndexFaceIndexPairs, pointLabelEdgeIndexFaceIndexPairI ) { const labelList& pointLabelEdgeIndexFaceIndexPair ( pointLabelEdgeIndexFaceIndexPairs [ pointLabelEdgeIndexFaceIndexPairI ] ); if (pointLabelOld != pointLabelEdgeIndexFaceIndexPair[0]) { I ++; pointLabelOld = pointLabelEdgeIndexFaceIndexPair[0]; } const label pointI(pointLabelPointIndices[I][1]); pointEdgeIndices[pointI].append ( pointLabelEdgeIndexFaceIndexPair[1] ); pointFaceIndexPairs[pointI].append ( labelPair ( pointLabelEdgeIndexFaceIndexPair[2], pointLabelEdgeIndexFaceIndexPair[3] ) ); } } // Order the point face pairs and assemble a list of point face indices labelListList pointFaceIndices(cPointLabels.size()); forAll(pointFaceIndexPairs, pointI) { labelPairList& faceIndexPairs(pointFaceIndexPairs[pointI]); pointFaceIndices[pointI].append(faceIndexPairs[0][0]); for (label pairI = 1; pairI < faceIndexPairs.size(); pairI ++) { for (label pairJ = pairI; pairJ < faceIndexPairs.size(); ++ pairJ) { if (faceIndexPairs[pairI-1][1] == faceIndexPairs[pairJ][0]) { Swap ( pointEdgeIndices[pointI][pairI], pointEdgeIndices[pointI][pairJ] ); Swap ( faceIndexPairs[pairI], faceIndexPairs[pairJ] ); break; } } pointFaceIndices[pointI].append(faceIndexPairs[pairI][0]); } } // convert to global indices forAll(cPointLabels, pointI) { labelList& edgeIndices(pointEdgeIndices[pointI]); labelList& faceIndices(pointFaceIndices[pointI]); const label nPointFaces(faceIndices.size()); cellPointPoints_[cellI][pointI].resize(nPointFaces); forAll(edgeIndices, edgeI) { cellPointPoints_[cellI][pointI][edgeI] = cEdges[edgeIndices[edgeI]] [ cEdges[edgeIndices[edgeI]][0] == cPointLabels[pointI] ]; } cellPointFaces_[cellI][pointI].resize(nPointFaces); forAll(faceIndices, faceI) { cellPointFaces_[cellI][pointI][faceI] = cFaceLabels [ faceIndices[faceI] ]; } } } // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::cellPointConnectivity::cellPointConnectivity(const polyMesh& mesh) : MoveableMeshObject(typeName, mesh), mesh_(mesh), cellPointPoints_(mesh.nCells()), cellPointFaces_(mesh.nCells()) { forAll(mesh.cells(), cellI) { const label nPoints(mesh.cellPoints()[cellI].size()); cellPointPoints_[cellI].resize(nPoints); cellPointFaces_[cellI].resize(nPoints); generateCellPointConnectivity(cellI); } } // ************************************************************************* //