/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2017 OpenFOAM Foundation Copyright (C) 2019-2022 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 "meshCutter.H" #include "polyMesh.H" #include "polyTopoChange.H" #include "cellCuts.H" #include "mapPolyMesh.H" #include "meshTools.H" #include "polyModifyFace.H" #include "polyAddPoint.H" #include "polyAddFace.H" #include "polyAddCell.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 (elems2.found(elems1[elemI])) { return true; } } return false; } bool Foam::meshCutter::isIn ( const edge& twoCuts, const labelList& cuts ) { label index = cuts.find(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]; } } } void Foam::meshCutter::getFaceInfo ( const label facei, label& patchID, label& zoneID, label& zoneFlip ) const { patchID = -1; if (!mesh().isInternalFace(facei)) { patchID = mesh().boundaryMesh().whichPatch(facei); } zoneID = mesh().faceZones().whichZone(facei); zoneFlip = false; if (zoneID >= 0) { const faceZone& fZone = mesh().faceZones()[zoneID]; zoneFlip = fZone.flipMap()[fZone.whichFace(facei)]; } } void Foam::meshCutter::addFace ( polyTopoChange& meshMod, const label facei, const face& newFace, const label own, const label nei ) { label patchID, zoneID, zoneFlip; getFaceInfo(facei, patchID, zoneID, zoneFlip); if ((nei == -1) || (own < nei)) { // Ordering ok. if (debug & 2) { Pout<< "Adding face " << newFace << " with new owner:" << own << " with new neighbour:" << nei << " patchID:" << patchID << " zoneID:" << zoneID << " zoneFlip:" << zoneFlip << endl; } meshMod.setAction ( polyAddFace ( newFace, // face own, // owner nei, // neighbour -1, // master point -1, // master edge facei, // master face for addition false, // flux flip patchID, // patch for face zoneID, // zone for face zoneFlip // face zone flip ) ); } else { // Reverse owner/neighbour if (debug & 2) { Pout<< "Adding (reversed) face " << newFace.reverseFace() << " with new owner:" << nei << " with new neighbour:" << own << " patchID:" << patchID << " zoneID:" << zoneID << " zoneFlip:" << zoneFlip << endl; } meshMod.setAction ( polyAddFace ( newFace.reverseFace(), // face nei, // owner own, // neighbour -1, // master point -1, // master edge facei, // master face for addition false, // flux flip patchID, // patch for face zoneID, // zone for face zoneFlip // face zone flip ) ); } } void Foam::meshCutter::modFace ( polyTopoChange& meshMod, const label facei, const face& newFace, const label own, const label nei ) { label patchID, zoneID, zoneFlip; getFaceInfo(facei, patchID, zoneID, zoneFlip); 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 << " new zoneID:" << zoneID << " new zoneFlip:" << zoneFlip << endl; } if ((nei == -1) || (own < nei)) { meshMod.setAction ( polyModifyFace ( newFace, // modified face facei, // label of face being modified own, // owner nei, // neighbour false, // face flip patchID, // patch for face false, // remove from zone zoneID, // zone for face zoneFlip // face flip in zone ) ); } else { meshMod.setAction ( polyModifyFace ( newFace.reverseFace(), // modified face facei, // label of face being modified nei, // owner own, // neighbour false, // face flip patchID, // patch for face false, // remove from zone zoneID, // zone for face zoneFlip // face flip in zone ) ); } } } 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 = f.find(v0); if (startFp == -1) { FatalErrorInFunction << "Cannot find vertex (new numbering) " << v0 << " on face " << f << abort(FatalError); } label endFp = f.find(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); EdgeMap