void Foam::syncTools::swapBoundaryCellPositions ( const polyMesh& mesh, const UList<point>& cellData, List<point>& neighbourCellData ) { if (cellData.size() != mesh.nCells()) { FatalErrorInFunction << "Number of cell values " << cellData.size() << " is not equal to the number of cells in the mesh " << mesh.nCells() << abort(FatalError); } const polyBoundaryMesh& patches = mesh.boundaryMesh(); label nBnd = mesh.nFaces()-mesh.nInternalFaces(); neighbourCellData.setSize(nBnd); forAll(patches, patchI) { const polyPatch& pp = patches[patchI]; const labelUList& faceCells = pp.faceCells(); forAll(faceCells, i) { label bFaceI = pp.start()+i-mesh.nInternalFaces(); neighbourCellData[bFaceI] = cellData[faceCells[i]]; } }
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++; } }
void Foam::scotchDecomp::calcCSR ( const polyMesh& mesh, List<int>& adjncy, List<int>& xadj ) { // Make Metis CSR (Compressed Storage Format) storage // adjncy : contains neighbours (= edges in graph) // xadj(celli) : start of information in adjncy for celli xadj.setSize(mesh.nCells()+1); // Initialise the number of internal faces of the cells to twice the // number of internal faces label nInternalFaces = 2*mesh.nInternalFaces(); // Check the boundary for coupled patches and add to the number of // internal faces const polyBoundaryMesh& pbm = mesh.boundaryMesh(); forAll(pbm, patchi) { if (isA<cyclicPolyPatch>(pbm[patchi])) { nInternalFaces += pbm[patchi].size(); } } // Create the adjncy array the size of the total number of internal and // coupled faces adjncy.setSize(nInternalFaces); // Fill in xadj // ~~~~~~~~~~~~ label freeAdj = 0; for (label cellI = 0; cellI < mesh.nCells(); cellI++) { xadj[cellI] = freeAdj; const labelList& cFaces = mesh.cells()[cellI]; forAll(cFaces, i) { label faceI = cFaces[i]; if ( mesh.isInternalFace(faceI) || isA<cyclicPolyPatch>(pbm[pbm.whichPatch(faceI)]) ) { freeAdj++; } } }
// Determines face blocking void Foam::channelIndex::walkOppositeFaces ( const polyMesh& mesh, const labelList& startFaces, boolList& blockedFace ) { const cellList& cells = mesh.cells(); const faceList& faces = mesh.faces(); label nBnd = mesh.nFaces() - mesh.nInternalFaces(); DynamicList<label> frontFaces(startFaces); forAll(frontFaces, i) { label facei = frontFaces[i]; blockedFace[facei] = true; }
// Adds empty patch if not yet there. Returns patchID. label addPatch(polyMesh& mesh, const word& patchName) { label patchi = mesh.boundaryMesh().findPatchID(patchName); if (patchi == -1) { const polyBoundaryMesh& patches = mesh.boundaryMesh(); List<polyPatch*> newPatches(patches.size() + 1); // Add empty patch as 0th entry (Note: only since subsetMesh wants this) patchi = 0; newPatches[patchi] = new emptyPolyPatch ( Foam::word(patchName), 0, mesh.nInternalFaces(), patchi, patches, emptyPolyPatch::typeName ); forAll(patches, i) { const polyPatch& pp = patches[i]; newPatches[i+1] = pp.clone ( patches, i+1, pp.size(), pp.start() ).ptr(); } mesh.removeBoundary(); mesh.addPatches(newPatches); Info<< "Created patch oldInternalFaces at " << patchi << endl; } else {
// Naive feature detection. All boundary edges with angle > featureAngle become // feature edges. All points on feature edges become feature points. All // boundary faces become feature faces. void simpleMarkFeatures ( const polyMesh& mesh, const PackedBoolList& isBoundaryEdge, const scalar featureAngle, const bool concaveMultiCells, const bool doNotPreserveFaceZones, labelList& featureFaces, labelList& featureEdges, labelList& singleCellFeaturePoints, labelList& multiCellFeaturePoints ) { scalar minCos = Foam::cos(featureAngle * mathematicalConstant::pi/180.0); const polyBoundaryMesh& patches = mesh.boundaryMesh(); // Working sets labelHashSet featureEdgeSet; labelHashSet singleCellFeaturePointSet; labelHashSet multiCellFeaturePointSet; // 1. Mark all edges between patches // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ forAll(patches, patchI) { const polyPatch& pp = patches[patchI]; const labelList& meshEdges = pp.meshEdges(); // All patch corner edges. These need to be feature points & edges! for (label edgeI = pp.nInternalEdges(); edgeI < pp.nEdges(); edgeI++) { label meshEdgeI = meshEdges[edgeI]; featureEdgeSet.insert(meshEdgeI); singleCellFeaturePointSet.insert(mesh.edges()[meshEdgeI][0]); singleCellFeaturePointSet.insert(mesh.edges()[meshEdgeI][1]); } } // 2. Mark all geometric feature edges // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Make distinction between convex features where the boundary point becomes // a single cell and concave features where the boundary point becomes // multiple 'half' cells. // Addressing for all outside faces primitivePatch allBoundary ( SubList<face> ( mesh.faces(), mesh.nFaces()-mesh.nInternalFaces(), mesh.nInternalFaces() ), mesh.points() ); // Check for non-manifold points (surface pinched at point) allBoundary.checkPointManifold(false, &singleCellFeaturePointSet); // Check for non-manifold edges (surface pinched at edge) const labelListList& edgeFaces = allBoundary.edgeFaces(); const labelList& meshPoints = allBoundary.meshPoints(); forAll(edgeFaces, edgeI) { const labelList& eFaces = edgeFaces[edgeI]; if (eFaces.size() > 2) { const edge& e = allBoundary.edges()[edgeI]; //Info<< "Detected non-manifold boundary edge:" << edgeI // << " coords:" // << allBoundary.points()[meshPoints[e[0]]] // << allBoundary.points()[meshPoints[e[1]]] << endl; singleCellFeaturePointSet.insert(meshPoints[e[0]]); singleCellFeaturePointSet.insert(meshPoints[e[1]]); } } // Check for features. forAll(edgeFaces, edgeI) { const labelList& eFaces = edgeFaces[edgeI]; if (eFaces.size() == 2) { label f0 = eFaces[0]; label f1 = eFaces[1]; // check angle const vector& n0 = allBoundary.faceNormals()[f0]; const vector& n1 = allBoundary.faceNormals()[f1]; if ((n0 & n1) < minCos) { const edge& e = allBoundary.edges()[edgeI]; label v0 = meshPoints[e[0]]; label v1 = meshPoints[e[1]]; label meshEdgeI = meshTools::findEdge(mesh, v0, v1); featureEdgeSet.insert(meshEdgeI); // Check if convex or concave by looking at angle // between face centres and normal vector c1c0 ( allBoundary[f1].centre(allBoundary.points()) - allBoundary[f0].centre(allBoundary.points()) ); if (concaveMultiCells && (c1c0 & n0) > SMALL) { // Found concave edge. Make into multiCell features Info<< "Detected concave feature edge:" << edgeI << " cos:" << (c1c0 & n0) << " coords:" << allBoundary.points()[v0] << allBoundary.points()[v1] << endl; singleCellFeaturePointSet.erase(v0); multiCellFeaturePointSet.insert(v0); singleCellFeaturePointSet.erase(v1); multiCellFeaturePointSet.insert(v1); } else { // Convex. singleCell feature. if (!multiCellFeaturePointSet.found(v0)) { singleCellFeaturePointSet.insert(v0); } if (!multiCellFeaturePointSet.found(v1)) { singleCellFeaturePointSet.insert(v1); } } } } } // 3. Mark all feature faces // ~~~~~~~~~~~~~~~~~~~~~~~~~ // Face centres that need inclusion in the dual mesh labelHashSet featureFaceSet(mesh.nFaces()-mesh.nInternalFaces()); // A. boundary faces. for (label faceI = mesh.nInternalFaces(); faceI < mesh.nFaces(); faceI++) { featureFaceSet.insert(faceI); } // B. face zones. const faceZoneMesh& faceZones = mesh.faceZones(); if (doNotPreserveFaceZones) { if (faceZones.size() > 0) { WarningIn("simpleMarkFeatures(..)") << "Detected " << faceZones.size() << " faceZones. These will not be preserved." << endl; } } else { if (faceZones.size() > 0) { Info<< "Detected " << faceZones.size() << " faceZones. Preserving these by marking their" << " points, edges and faces as features." << endl; } forAll(faceZones, zoneI) { const faceZone& fz = faceZones[zoneI]; Info<< "Inserting all faces in faceZone " << fz.name() << " as features." << endl; forAll(fz, i) { label faceI = fz[i]; const face& f = mesh.faces()[faceI]; const labelList& fEdges = mesh.faceEdges()[faceI]; featureFaceSet.insert(faceI); forAll(f, fp) { // Mark point as multi cell point (since both sides of // face should have different cells) singleCellFeaturePointSet.erase(f[fp]); multiCellFeaturePointSet.insert(f[fp]); // Make sure there are points on the edges. featureEdgeSet.insert(fEdges[fp]); } } }
// Check the blockMesh topology void Foam::blockMesh::checkBlockMesh(const polyMesh& bm) const { if (verboseOutput) { Info<< nl << "Check topology" << endl; } bool ok = true; const pointField& points = bm.points(); const faceList& faces = bm.faces(); const cellList& cells = bm.cells(); const polyPatchList& patches = bm.boundaryMesh(); label nBoundaryFaces = 0; forAll(cells, celli) { nBoundaryFaces += cells[celli].nFaces(); } nBoundaryFaces -= 2*bm.nInternalFaces(); label nDefinedBoundaryFaces = 0; forAll(patches, patchi) { nDefinedBoundaryFaces += patches[patchi].size(); } if (verboseOutput) { Info<< nl << tab << "Basic statistics" << nl << tab << tab << "Number of internal faces : " << bm.nInternalFaces() << nl << tab << tab << "Number of boundary faces : " << nBoundaryFaces << nl << tab << tab << "Number of defined boundary faces : " << nDefinedBoundaryFaces << nl << tab << tab << "Number of undefined boundary faces : " << nBoundaryFaces - nDefinedBoundaryFaces << nl; if ((nBoundaryFaces - nDefinedBoundaryFaces) > 0) { Info<< tab << tab << tab << "(Warning : only leave undefined the front and back planes " << "of 2D planar geometries!)" << endl; } Info<< tab << "Checking patch -> block consistency" << endl; } forAll(patches, patchi) { const faceList& Patch = patches[patchi]; forAll(Patch, patchFacei) { const face& patchFace = Patch[patchFacei]; bool patchFaceOK = false; forAll(cells, celli) { const labelList& cellFaces = cells[celli]; forAll(cellFaces, cellFacei) { if (patchFace == faces[cellFaces[cellFacei]]) { patchFaceOK = true; if ( ( patchFace.normal(points) & faces[cellFaces[cellFacei]].normal(points) ) < 0.0 ) { Info<< tab << tab << "Face " << patchFacei << " of patch " << patchi << " (" << patches[patchi].name() << ")" << " points inwards" << endl; ok = false; } } } } if (!patchFaceOK) { Info<< tab << tab << "Face " << patchFacei << " of patch " << patchi << " (" << patches[patchi].name() << ")" << " does not match any block faces" << endl; ok = false; } } } if (verboseOutput) { Info<< endl; } if (!ok) { FatalErrorIn("blockMesh::checkBlockMesh(const polyMesh& bm)") << "Block mesh topology incorrect, stopping mesh generation!" << exit(FatalError); } }
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 ) ); } } }