void Foam::decompositionMethod::calcCellCells ( const polyMesh& mesh, const labelList& agglom, const label nLocalCoarse, const bool parallel, CompactListList<label>& cellCells ) { const labelList& faceOwner = mesh.faceOwner(); const labelList& faceNeighbour = mesh.faceNeighbour(); const polyBoundaryMesh& patches = mesh.boundaryMesh(); // Create global cell numbers // ~~~~~~~~~~~~~~~~~~~~~~~~~~ globalIndex globalAgglom ( nLocalCoarse, Pstream::msgType(), Pstream::worldComm, parallel ); // Get agglomerate owner on other side of coupled faces // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ labelList globalNeighbour(mesh.nFaces()-mesh.nInternalFaces()); forAll(patches, patchI) { const polyPatch& pp = patches[patchI]; if (pp.coupled() && (parallel || !isA<processorPolyPatch>(pp))) { label faceI = pp.start(); label bFaceI = pp.start() - mesh.nInternalFaces(); forAll(pp, i) { globalNeighbour[bFaceI] = globalAgglom.toGlobal ( agglom[faceOwner[faceI]] ); bFaceI++; faceI++; } }
Foam::Cloud<ParticleType>::Cloud ( const polyMesh& pMesh, const IDLList<ParticleType>& particles ) : cloud(pMesh), IDLList<ParticleType>(particles), polyMesh_(pMesh), allFaces_(pMesh.faces()), points_(pMesh.points()), cellFaces_(pMesh.cells()), allFaceCentres_(pMesh.faceCentres()), owner_(pMesh.faceOwner()), neighbour_(pMesh.faceNeighbour()), meshInfo_(polyMesh_) {}
Foam::Cloud<ParticleType>::Cloud ( const polyMesh& pMesh, const bool checkClass ) : cloud(pMesh), polyMesh_(pMesh), allFaces_(pMesh.faces()), points_(pMesh.points()), cellFaces_(pMesh.cells()), allFaceCentres_(pMesh.faceCentres()), owner_(pMesh.faceOwner()), neighbour_(pMesh.faceNeighbour()), meshInfo_(polyMesh_) { initCloud(checkClass); }
Foam::label Foam::polyMeshTetDecomposition::findSharedBasePoint ( const polyMesh& mesh, label fI, const point& nCc, scalar tol, bool report ) { const faceList& pFaces = mesh.faces(); const pointField& pPts = mesh.points(); const vectorField& pC = mesh.cellCentres(); const labelList& pOwner = mesh.faceOwner(); const face& f = pFaces[fI]; label oCI = pOwner[fI]; const point& oCc = pC[oCI]; List<scalar> tetQualities(2, 0.0); forAll(f, faceBasePtI) { scalar thisBaseMinTetQuality = VGREAT; const point& tetBasePt = pPts[f[faceBasePtI]]; for (label tetPtI = 1; tetPtI < f.size() - 1; tetPtI++) { label facePtI = (tetPtI + faceBasePtI) % f.size(); label otherFacePtI = f.fcIndex(facePtI); { // owner cell tet label ptAI = f[facePtI]; label ptBI = f[otherFacePtI]; const point& pA = pPts[ptAI]; const point& pB = pPts[ptBI]; tetPointRef tet(oCc, tetBasePt, pA, pB); tetQualities[0] = tet.quality(); } { // neighbour cell tet label ptAI = f[otherFacePtI]; label ptBI = f[facePtI]; const point& pA = pPts[ptAI]; const point& pB = pPts[ptBI]; tetPointRef tet(nCc, tetBasePt, pA, pB); tetQualities[1] = tet.quality(); } if (min(tetQualities) < thisBaseMinTetQuality) { thisBaseMinTetQuality = min(tetQualities); } } if (thisBaseMinTetQuality > tol) { return faceBasePtI; } }
Foam::vtkTopo::vtkTopo(const polyMesh& mesh) : mesh_(mesh), vertLabels_(), cellTypes_(), addPointCellLabels_(), superCells_() { const cellModel& tet = *(cellModeller::lookup("tet")); const cellModel& pyr = *(cellModeller::lookup("pyr")); const cellModel& prism = *(cellModeller::lookup("prism")); const cellModel& tetWedge = *(cellModeller::lookup("tetWedge")); const cellModel& hex = *(cellModeller::lookup("hex")); const cellShapeList& cellShapes = mesh_.cellShapes(); // Number of additional points needed by the decomposition of polyhedra label nAddPoints = 0; // Number of additional cells generated by the decomposition of polyhedra label nAddCells = 0; // face owner is needed to determine the face orientation const labelList& owner = mesh.faceOwner(); // Scan for cells which need to be decomposed and count additional points // and cells if (decomposePoly) { forAll(cellShapes, cellI) { const cellModel& model = cellShapes[cellI].model(); if ( model != hex // && model != wedge // See above. && model != prism && model != pyr && model != tet && model != tetWedge ) { const cell& cFaces = mesh_.cells()[cellI]; forAll(cFaces, cFaceI) { const face& f = mesh_.faces()[cFaces[cFaceI]]; label nQuads = 0; label nTris = 0; f.nTrianglesQuads(mesh_.points(), nTris, nQuads); nAddCells += nQuads + nTris; } nAddCells--; nAddPoints++; } } } // Set size of additional point addressing array // (from added point to original cell) addPointCellLabels_.setSize(nAddPoints); // Set size of additional cells mapping array // (from added cell to original cell) superCells_.setSize(nAddCells); // List of vertex labels in VTK ordering vertLabels_.setSize(cellShapes.size() + nAddCells); // Label of vtk type cellTypes_.setSize(cellShapes.size() + nAddCells); // Set counters for additional points and additional cells label addPointI = 0, addCellI = 0; forAll(cellShapes, cellI) { const cellShape& cellShape = cellShapes[cellI]; const cellModel& cellModel = cellShape.model(); labelList& vtkVerts = vertLabels_[cellI]; if (cellModel == tet) { vtkVerts = cellShape; cellTypes_[cellI] = VTK_TETRA; } else if (cellModel == pyr) { vtkVerts = cellShape; cellTypes_[cellI] = VTK_PYRAMID; } else if (cellModel == prism) { // VTK has a different node order for VTK_WEDGE // their triangles point outwards! vtkVerts = cellShape; Foam::Swap(vtkVerts[1], vtkVerts[2]); Foam::Swap(vtkVerts[4], vtkVerts[5]); cellTypes_[cellI] = VTK_WEDGE; } else if (cellModel == tetWedge) { // Treat as squeezed prism vtkVerts.setSize(6); vtkVerts[0] = cellShape[0]; vtkVerts[1] = cellShape[2]; vtkVerts[2] = cellShape[1]; vtkVerts[3] = cellShape[3]; vtkVerts[4] = cellShape[4]; vtkVerts[5] = cellShape[4]; cellTypes_[cellI] = VTK_WEDGE; } // else if (cellModel == wedge) // { // // Treat as squeezed hex // vtkVerts.setSize(8); // vtkVerts[0] = cellShape[0]; // vtkVerts[1] = cellShape[1]; // vtkVerts[2] = cellShape[2]; // vtkVerts[3] = cellShape[0]; // vtkVerts[4] = cellShape[3]; // vtkVerts[5] = cellShape[4]; // vtkVerts[6] = cellShape[5]; // vtkVerts[7] = cellShape[6]; // // cellTypes_[cellI] = VTK_HEXAHEDRON; // } else if (cellModel == hex) { vtkVerts = cellShape; cellTypes_[cellI] = VTK_HEXAHEDRON; } else if (decomposePoly) { // Polyhedral cell. Decompose into tets + pyramids. // Mapping from additional point to cell addPointCellLabels_[addPointI] = cellI; // The new vertex from the cell-centre const label newVertexLabel = mesh_.nPoints() + addPointI; // Whether to insert cell in place of original or not. bool substituteCell = true; const labelList& cFaces = mesh_.cells()[cellI]; forAll(cFaces, cFaceI) { const face& f = mesh_.faces()[cFaces[cFaceI]]; const bool isOwner = (owner[cFaces[cFaceI]] == cellI); // Number of triangles and quads in decomposition label nTris = 0; label nQuads = 0; f.nTrianglesQuads(mesh_.points(), nTris, nQuads); // Do actual decomposition into triFcs and quadFcs. faceList triFcs(nTris); faceList quadFcs(nQuads); label trii = 0; label quadi = 0; f.trianglesQuads(mesh_.points(), trii, quadi, triFcs, quadFcs); forAll(quadFcs, quadI) { label thisCellI; if (substituteCell) { thisCellI = cellI; substituteCell = false; } else { thisCellI = mesh_.nCells() + addCellI; superCells_[addCellI++] = cellI; } labelList& addVtkVerts = vertLabels_[thisCellI]; addVtkVerts.setSize(5); const face& quad = quadFcs[quadI]; // Ensure we have the correct orientation for the // base of the primitive cell shape. // If the cell is face owner, the orientation needs to be // flipped. // At the moment, VTK doesn't actually seem to care if // negative cells are defined, but we'll do it anyhow // (for safety). if (isOwner) { addVtkVerts[0] = quad[3]; addVtkVerts[1] = quad[2]; addVtkVerts[2] = quad[1]; addVtkVerts[3] = quad[0]; } else { addVtkVerts[0] = quad[0]; addVtkVerts[1] = quad[1]; addVtkVerts[2] = quad[2]; addVtkVerts[3] = quad[3]; } addVtkVerts[4] = newVertexLabel; cellTypes_[thisCellI] = VTK_PYRAMID; } forAll(triFcs, triI) { label thisCellI; if (substituteCell) { thisCellI = cellI; substituteCell = false; } else { thisCellI = mesh_.nCells() + addCellI; superCells_[addCellI++] = cellI; } labelList& addVtkVerts = vertLabels_[thisCellI]; const face& tri = triFcs[triI]; addVtkVerts.setSize(4); // See note above about the orientation. if (isOwner) { addVtkVerts[0] = tri[2]; addVtkVerts[1] = tri[1]; addVtkVerts[2] = tri[0]; } else { addVtkVerts[0] = tri[0]; addVtkVerts[1] = tri[1]; addVtkVerts[2] = tri[2]; } addVtkVerts[3] = newVertexLabel; cellTypes_[thisCellI] = VTK_TETRA; } } addPointI++; }
void Foam::cellPointWeight::findTriangle ( const polyMesh& mesh, const vector& position, const label facei ) { if (debug) { Pout<< "\nbool Foam::cellPointWeight::findTriangle" << nl << "position = " << position << nl << "facei = " << facei << endl; } List<tetIndices> faceTets = polyMeshTetDecomposition::faceTetIndices ( mesh, facei, mesh.faceOwner()[facei] ); const scalar faceAreaSqr = magSqr(mesh.faceAreas()[facei]); forAll(faceTets, tetI) { const tetIndices& tetIs = faceTets[tetI]; // Barycentric coordinates of the position barycentric2D triWeights; const scalar det = tetIs.faceTri(mesh).pointToBarycentric(position, triWeights); if (0.25*mag(det)/faceAreaSqr > tol) { const scalar& u = triWeights[0]; const scalar& v = triWeights[1]; if ( (u + tol > 0) && (v + tol > 0) && (u + v < 1 + tol) ) { // Weight[0] is for the cell centre. weights_[0] = 0; weights_[1] = triWeights[0]; weights_[2] = triWeights[1]; weights_[3] = triWeights[2]; faceVertices_ = tetIs.faceTriIs(mesh); return; } } } // A suitable point in a triangle was not found, find the nearest. scalar minNearDist = vGreat; label nearestTetI = -1; forAll(faceTets, tetI) { const tetIndices& tetIs = faceTets[tetI]; scalar nearDist = tetIs.faceTri(mesh).nearestPoint(position).distance(); if (nearDist < minNearDist) { minNearDist = nearDist; nearestTetI = tetI; } } if (debug) { Pout<< "cellPointWeight::findTriangle" << nl << " Triangle search failed; using closest tri to point " << position << nl << " face: " << facei << nl << endl; } const tetIndices& tetIs = faceTets[nearestTetI]; // Barycentric coordinates of the position, ignoring if the // determinant is suitable. If not, the return from barycentric // to triWeights is safe. const barycentric2D triWeights = tetIs.faceTri(mesh).pointToBarycentric(position); // Weight[0] is for the cell centre. weights_[0] = 0; weights_[1] = triWeights[0]; weights_[2] = triWeights[1]; weights_[3] = triWeights[2]; faceVertices_ = tetIs.faceTriIs(mesh); }
void insertDuplicateMerge ( const polyMesh& mesh, const labelList& duplicates, polyTopoChange& meshMod ) { const faceList& faces = mesh.faces(); const labelList& faceOwner = mesh.faceOwner(); const faceZoneMesh& faceZones = mesh.faceZones(); forAll(duplicates, bFacei) { label otherFacei = duplicates[bFacei]; if (otherFacei != -1 && otherFacei > bFacei) { // Two duplicate faces. Merge. label face0 = mesh.nInternalFaces() + bFacei; label face1 = mesh.nInternalFaces() + otherFacei; label own0 = faceOwner[face0]; label own1 = faceOwner[face1]; if (own0 < own1) { // Use face0 as the new internal face. label zoneID = faceZones.whichZone(face0); bool zoneFlip = false; if (zoneID >= 0) { const faceZone& fZone = faceZones[zoneID]; zoneFlip = fZone.flipMap()[fZone.whichFace(face0)]; } meshMod.setAction(polyRemoveFace(face1)); meshMod.setAction ( polyModifyFace ( faces[face0], // modified face face0, // label of face being modified own0, // owner own1, // neighbour false, // face flip -1, // patch for face false, // remove from zone zoneID, // zone for face zoneFlip // face flip in zone ) ); } else { // Use face1 as the new internal face. label zoneID = faceZones.whichZone(face1); bool zoneFlip = false; if (zoneID >= 0) { const faceZone& fZone = faceZones[zoneID]; zoneFlip = fZone.flipMap()[fZone.whichFace(face1)]; } meshMod.setAction(polyRemoveFace(face0)); meshMod.setAction ( polyModifyFace ( faces[face1], // modified face face1, // label of face being modified own1, // owner own0, // neighbour false, // face flip -1, // patch for face false, // remove from zone zoneID, // zone for face zoneFlip // face flip in zone ) ); } } }