/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | Website: https://openfoam.org \\ / A nd | Copyright (C) 2011-2024 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- 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 "meshCutter.H" #include "polyMesh.H" #include "polyTopoChange.H" #include "cellCuts.H" #include "polyTopoChangeMap.H" #include "meshTools.H" #include "syncTools.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // namespace Foam { defineTypeNameAndDebug(meshCutter, 0); } // * * * * * * * * * * * * * Private Static Functions * * * * * * * * * * * // bool Foam::meshCutter::uses(const labelList& elems1, const labelList& elems2) { forAll(elems1, elemI) { if (findIndex(elems2, elems1[elemI]) != -1) { return true; } } return false; } bool Foam::meshCutter::isIn ( const edge& twoCuts, const labelList& cuts ) { label index = findIndex(cuts, twoCuts[0]); if (index == -1) { return false; } return ( cuts[cuts.fcIndex(index)] == twoCuts[1] || cuts[cuts.rcIndex(index)] == twoCuts[1] ); } // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // Foam::label Foam::meshCutter::findCutCell ( const cellCuts& cuts, const labelList& cellLabels ) const { forAll(cellLabels, labelI) { label celli = cellLabels[labelI]; if (cuts.cellLoops()[celli].size()) { return celli; } } return -1; } Foam::label Foam::meshCutter::findInternalFacePoint ( const labelList& pointLabels ) const { forAll(pointLabels, labelI) { label pointi = pointLabels[labelI]; const labelList& pFaces = mesh().pointFaces()[pointi]; forAll(pFaces, pFacei) { label facei = pFaces[pFacei]; if (mesh().isInternalFace(facei)) { return pointi; } } } if (pointLabels.empty()) { FatalErrorInFunction << "Empty pointLabels" << abort(FatalError); } return -1; } void Foam::meshCutter::faceCells ( const cellCuts& cuts, const label facei, label& own, label& nei ) const { const labelListList& anchorPts = cuts.cellAnchorPoints(); const labelListList& cellLoops = cuts.cellLoops(); const face& f = mesh().faces()[facei]; own = mesh().faceOwner()[facei]; if (cellLoops[own].size() && uses(f, anchorPts[own])) { own = addedCells_[own]; } nei = -1; if (mesh().isInternalFace(facei)) { nei = mesh().faceNeighbour()[facei]; if (cellLoops[nei].size() && uses(f, anchorPts[nei])) { nei = addedCells_[nei]; } } } Foam::label Foam::meshCutter::getPatchIndex(const label facei) const { label patchID = -1; if (!mesh().isInternalFace(facei)) { patchID = mesh().boundaryMesh().whichPatch(facei); } return patchID; } void Foam::meshCutter::addFace ( polyTopoChange& meshMod, const label facei, const face& newFace, const label own, const label nei ) { const label patchID = getPatchIndex(facei); if ((nei == -1) || (own < nei)) { // Ordering ok. if (debug & 2) { Pout<< "Adding face " << newFace << " with new owner:" << own << " with new neighbour:" << nei << " patchID:" << patchID << endl; } meshMod.addFace ( newFace, // face own, // owner nei, // neighbour facei, // master face for addition false, // flux flip patchID // patch for face ); } else { // Reverse owner/neighbour if (debug & 2) { Pout<< "Adding (reversed) face " << newFace.reverseFace() << " with new owner:" << nei << " with new neighbour:" << own << " patchID:" << patchID << endl; } meshMod.addFace ( newFace.reverseFace(), // face nei, // owner own, // neighbour facei, // master face for addition false, // flux flip patchID // patch for face ); } } void Foam::meshCutter::modifyFace ( polyTopoChange& meshMod, const label facei, const face& newFace, const label own, const label nei ) { const label patchID = getPatchIndex(facei); if ( (own != mesh().faceOwner()[facei]) || ( mesh().isInternalFace(facei) && (nei != mesh().faceNeighbour()[facei]) ) || (newFace != mesh().faces()[facei]) ) { if (debug & 2) { Pout<< "Modifying face " << facei << " old vertices:" << mesh().faces()[facei] << " new vertices:" << newFace << " new owner:" << own << " new neighbour:" << nei << endl; } if ((nei == -1) || (own < nei)) { meshMod.modifyFace ( newFace, // modified face facei, // label of face being modified own, // owner nei, // neighbour false, // face flip patchID // patch for face ); } else { meshMod.modifyFace ( newFace.reverseFace(), // modified face facei, // label of face being modified nei, // owner own, // neighbour false, // face flip patchID // patch for face ); } } } void Foam::meshCutter::copyFace ( const face& f, const label startFp, const label endFp, face& newFace ) const { label fp = startFp; label newFp = 0; while (fp != endFp) { newFace[newFp++] = f[fp]; fp = (fp + 1) % f.size(); } newFace[newFp] = f[fp]; } void Foam::meshCutter::splitFace ( const face& f, const label v0, const label v1, face& f0, face& f1 ) const { // Check if we find any new vertex which is part of the splitEdge. label startFp = findIndex(f, v0); if (startFp == -1) { FatalErrorInFunction << "Cannot find vertex (new numbering) " << v0 << " on face " << f << abort(FatalError); } label endFp = findIndex(f, v1); if (endFp == -1) { FatalErrorInFunction << "Cannot find vertex (new numbering) " << v1 << " on face " << f << abort(FatalError); } f0.setSize((endFp + 1 + f.size() - startFp) % f.size()); f1.setSize(f.size() - f0.size() + 2); copyFace(f, startFp, endFp, f0); copyFace(f, endFp, startFp, f1); } Foam::face Foam::meshCutter::addEdgeCutsToFace(const label facei) const { const face& f = mesh().faces()[facei]; face newFace(2 * f.size()); label newFp = 0; forAll(f, fp) { // Duplicate face vertex . newFace[newFp++] = f[fp]; // Check if edge has been cut. label fp1 = f.fcIndex(fp); HashTable>::const_iterator fnd = addedPoints_.find(edge(f[fp], f[fp1])); if (fnd != addedPoints_.end()) { // edge has been cut. Introduce new vertex. newFace[newFp++] = fnd(); } } newFace.setSize(newFp); return newFace; } Foam::face Foam::meshCutter::loopToFace ( const label celli, const labelList& loop ) const { face newFace(2*loop.size()); label newFacei = 0; forAll(loop, fp) { label cut = loop[fp]; if (isEdge(cut)) { label edgeI = getEdge(cut); const edge& e = mesh().edges()[edgeI]; label vertI = addedPoints_[e]; newFace[newFacei++] = vertI; } else { // cut is vertex. label vertI = getVertex(cut); newFace[newFacei++] = vertI; label nextCut = loop[loop.fcIndex(fp)]; if (!isEdge(nextCut)) { // From vertex to vertex -> cross cut only if no existing edge. label nextVertI = getVertex(nextCut); label edgeI = meshTools::findEdge(mesh(), vertI, nextVertI); if (edgeI != -1) { // Existing edge. Insert split-edge point if any. HashTable>::const_iterator fnd = addedPoints_.find(mesh().edges()[edgeI]); if (fnd != addedPoints_.end()) { newFace[newFacei++] = fnd(); } } } } } newFace.setSize(newFacei); return newFace; } // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::meshCutter::meshCutter(const polyMesh& mesh) : edgeVertex(mesh), addedCells_(), addedFaces_(), addedPoints_() {} // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // Foam::meshCutter::~meshCutter() {} // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // void Foam::meshCutter::setRefinement ( const cellCuts& cuts, polyTopoChange& meshMod ) { // Clear and size maps here since mesh size will change. addedCells_.clear(); addedCells_.resize(cuts.nLoops()); addedFaces_.clear(); addedFaces_.resize(cuts.nLoops()); addedPoints_.clear(); addedPoints_.resize(cuts.nLoops()); if (returnReduce(cuts.nLoops(), sumOp