label addFaceZone(const polyMesh& mesh, const word& name) { label zoneID = mesh.faceZones().findZoneID(name); if (zoneID != -1) { Info<< "Reusing existing faceZone " << mesh.faceZones()[zoneID].name() << " at index " << zoneID << endl; } else { faceZoneMesh& faceZones = const_cast<polyMesh&>(mesh).faceZones(); zoneID = faceZones.size(); Info<< "Adding faceZone " << name << " at index " << zoneID << endl; faceZones.setSize(zoneID+1); faceZones.set ( zoneID, new faceZone ( name, labelList(0), boolList(), zoneID, faceZones ) ); } return zoneID; }
void Foam::meshReader::addFaceZones(polyMesh& mesh) const { label nZone = monitoringSets_.size(); mesh.faceZones().setSize(nZone); if (!nZone) { return; } nZone = 0; for ( HashTable<List<label>, word, string::hash>::const_iterator iter = monitoringSets_.begin(); iter != monitoringSets_.end(); ++iter ) { Info<< "faceZone " << nZone << " (size: " << iter().size() << ") name: " << iter.key() << endl; mesh.faceZones().set ( nZone, new faceZone ( iter.key(), iter(), List<bool>(iter().size(), false), nZone, mesh.faceZones() ) ); nZone++; } mesh.faceZones().writeOpt() = IOobject::AUTO_WRITE; warnDuplicates("faceZones", mesh.faceZones().names()); }
// 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]); } } }
Foam::displacementInterpolationFvMotionSolver:: displacementInterpolationFvMotionSolver ( const polyMesh& mesh, Istream& is ) : displacementFvMotionSolver(mesh, is), dynamicMeshCoeffs_ ( IOdictionary ( IOobject ( "dynamicMeshDict", mesh.time().constant(), mesh, IOobject::MUST_READ, IOobject::NO_WRITE, false ) ).subDict(typeName + "Coeffs") ) { // Get zones and their interpolation tables for displacement // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ List<Pair<word> > faceZoneToTable ( dynamicMeshCoeffs_.lookup("interpolationTables") ); const faceZoneMesh& fZones = mesh.faceZones(); times_.setSize(fZones.size()); displacements_.setSize(fZones.size()); forAll(faceZoneToTable, i) { const word& zoneName = faceZoneToTable[i][0]; label zoneI = fZones.findZoneID(zoneName); if (zoneI == -1) { FatalErrorIn ( "displacementInterpolationFvMotionSolver::" "displacementInterpolationFvMotionSolver(const polyMesh&," "Istream&)" ) << "Cannot find zone " << zoneName << endl << "Valid zones are " << mesh.faceZones().names() << exit(FatalError); } const word& tableName = faceZoneToTable[i][1]; IOList<Tuple2<scalar, vector> > table ( IOobject ( tableName, mesh.time().constant(), "tables", mesh, IOobject::MUST_READ, IOobject::NO_WRITE, false ) ); // Copy table times_[zoneI].setSize(table.size()); displacements_[zoneI].setSize(table.size()); forAll(table, j) { times_[zoneI][j] = table[j].first(); displacements_[zoneI][j] = table[j].second(); } }
void Foam::printMeshStats(const polyMesh& mesh, const bool allTopology) { Info<< "Mesh stats" << nl << " points: " << returnReduce(mesh.points().size(), sumOp<label>()) << nl; label nInternalPoints = returnReduce ( mesh.nInternalPoints(), sumOp<label>() ); if (nInternalPoints != -Pstream::nProcs()) { Info<< " internal points: " << nInternalPoints << nl; if (returnReduce(mesh.nInternalPoints(), minOp<label>()) == -1) { WarningIn("Foam::printMeshStats(const polyMesh&, const bool)") << "Some processors have their points sorted into internal" << " and external and some do not." << endl << "This can cause problems later on." << endl; } } if (allTopology && nInternalPoints != -Pstream::nProcs()) { label nEdges = returnReduce(mesh.nEdges(), sumOp<label>()); label nInternalEdges = returnReduce ( mesh.nInternalEdges(), sumOp<label>() ); label nInternal1Edges = returnReduce ( mesh.nInternal1Edges(), sumOp<label>() ); label nInternal0Edges = returnReduce ( mesh.nInternal0Edges(), sumOp<label>() ); Info<< " edges: " << nEdges << nl << " internal edges: " << nInternalEdges << nl << " internal edges using one boundary point: " << nInternal1Edges-nInternal0Edges << nl << " internal edges using two boundary points: " << nInternalEdges-nInternal1Edges << nl; } label nFaces = returnReduce(mesh.faces().size(), sumOp<label>()); label nIntFaces = returnReduce(mesh.faceNeighbour().size(), sumOp<label>()); label nCells = returnReduce(mesh.cells().size(), sumOp<label>()); Info<< " faces: " << nFaces << nl << " internal faces: " << nIntFaces << nl << " cells: " << nCells << nl << " faces per cell: " << scalar(nFaces + nIntFaces)/max(1, nCells) << nl << " boundary patches: " << mesh.boundaryMesh().size() << nl << " point zones: " << mesh.pointZones().size() << nl << " face zones: " << mesh.faceZones().size() << nl << " cell zones: " << mesh.cellZones().size() << nl << endl; // Construct shape recognizers hexMatcher hex; prismMatcher prism; wedgeMatcher wedge; pyrMatcher pyr; tetWedgeMatcher tetWedge; tetMatcher tet; // Counters for different cell types label nHex = 0; label nWedge = 0; label nPrism = 0; label nPyr = 0; label nTet = 0; label nTetWedge = 0; label nUnknown = 0; Map<label> polyhedralFaces; for (label cellI = 0; cellI < mesh.nCells(); cellI++) { if (hex.isA(mesh, cellI)) { nHex++; } else if (tet.isA(mesh, cellI)) { nTet++; } else if (pyr.isA(mesh, cellI)) { nPyr++; } else if (prism.isA(mesh, cellI)) { nPrism++; } else if (wedge.isA(mesh, cellI)) { nWedge++; } else if (tetWedge.isA(mesh, cellI)) { nTetWedge++; } else { nUnknown++; polyhedralFaces(mesh.cells()[cellI].size())++; } } reduce(nHex,sumOp<label>()); reduce(nPrism,sumOp<label>()); reduce(nWedge,sumOp<label>()); reduce(nPyr,sumOp<label>()); reduce(nTetWedge,sumOp<label>()); reduce(nTet,sumOp<label>()); reduce(nUnknown,sumOp<label>()); Info<< "Overall number of cells of each type:" << nl << " hexahedra: " << nHex << nl << " prisms: " << nPrism << nl << " wedges: " << nWedge << nl << " pyramids: " << nPyr << nl << " tet wedges: " << nTetWedge << nl << " tetrahedra: " << nTet << nl << " polyhedra: " << nUnknown << endl; if (nUnknown > 0) { Pstream::mapCombineGather(polyhedralFaces, plusEqOp<label>()); Info<< " Breakdown of polyhedra by number of faces:" << nl << " faces" << " number of cells" << endl; const labelList sortedKeys = polyhedralFaces.sortedToc(); forAll(sortedKeys, keyI) { const label nFaces = sortedKeys[keyI]; Info<< setf(std::ios::right) << setw(13) << nFaces << " " << polyhedralFaces[nFaces] << nl; } }
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 ) ); } } }