/*---------------------------------------------------------------------------*\ ========= | \\ / 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) 2015-2023 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 "meshRefinement.H" #include "trackedParticle.H" #include "syncTools.H" #include "Time.H" #include "refinementSurfaces.H" #include "refinementFeatures.H" #include "shellSurfaces.H" #include "faceSet.H" #include "decompositionMethod.H" #include "fvMeshDistribute.H" #include "polyTopoChange.H" #include "mapDistributePolyMesh.H" #include "Cloud.H" //#include "globalIndex.H" #include "cellSet.H" #include "treeDataCell.H" #include "cellCuts.H" #include "refineCell.H" #include "hexCellLooper.H" #include "meshCutter.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // namespace Foam { //- To compare normals static bool less(const vector& x, const vector& y) { for (direction i = 0; i < vector::nComponents; i++) { if (x[i] < y[i]) { return true; } else if (x[i] > y[i]) { return false; } } // All components the same return false; } //- To compare normals class normalLess { const vectorList& values_; public: normalLess(const vectorList& values) : values_(values) {} bool operator()(const label a, const label b) const { return less(values_[a], values_[b]); } }; //- Template specialization for pTraits so we can have fields template<> class pTraits { public: //- Component type typedef labelList cmptType; }; //- Template specialization for pTraits so we can have fields template<> class pTraits { public: //- Component type typedef vectorList cmptType; }; } // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // Get faces (on the new mesh) that have in some way been affected by the // mesh change. Picks up all faces but those that are between two // unrefined faces. (Note that of an unchanged face the edge still might be // split but that does not change any face centre or cell centre. Foam::labelList Foam::meshRefinement::getChangedFaces ( const mapPolyMesh& map, const labelList& oldCellsToRefine ) { const polyMesh& mesh = map.mesh(); labelList changedFaces; // For reporting: number of masterFaces changed label nMasterChanged = 0; bitSet isMasterFace(syncTools::getMasterFaces(mesh)); { // Mark any face on a cell which has been added or changed // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Note that refining a face changes the face centre (for a warped face) // which changes the cell centre. This again changes the cellcentre- // cellcentre edge across all faces of the cell. // Note: this does not happen for unwarped faces but unfortunately // we don't have this information. const labelList& faceOwner = mesh.faceOwner(); const labelList& faceNeighbour = mesh.faceNeighbour(); const cellList& cells = mesh.cells(); const label nInternalFaces = mesh.nInternalFaces(); // Mark refined cells on old mesh bitSet oldRefineCell(map.nOldCells(), oldCellsToRefine); // Mark refined faces bitSet refinedInternalFace(nInternalFaces); // 1. Internal faces for (label faceI = 0; faceI < nInternalFaces; faceI++) { label oldOwn = map.cellMap()[faceOwner[faceI]]; label oldNei = map.cellMap()[faceNeighbour[faceI]]; if ( oldOwn >= 0 && !oldRefineCell.test(oldOwn) && oldNei >= 0 && !oldRefineCell.test(oldNei) ) { // Unaffected face since both neighbours were not refined. } else { refinedInternalFace.set(faceI); } } // 2. Boundary faces boolList refinedBoundaryFace(mesh.nBoundaryFaces(), false); forAll(mesh.boundaryMesh(), patchI) { const polyPatch& pp = mesh.boundaryMesh()[patchI]; label faceI = pp.start(); forAll(pp, i) { label oldOwn = map.cellMap()[faceOwner[faceI]]; if (oldOwn >= 0 && !oldRefineCell.test(oldOwn)) { // owner did exist and wasn't refined. } else { refinedBoundaryFace[faceI-nInternalFaces] = true; } faceI++; } } // Synchronise refined face status syncTools::syncBoundaryFaceList ( mesh, refinedBoundaryFace, orEqOp() ); // 3. Mark all faces affected by refinement. Refined faces are in // - refinedInternalFace // - refinedBoundaryFace boolList changedFace(mesh.nFaces(), false); forAll(refinedInternalFace, faceI) { if (refinedInternalFace.test(faceI)) { const cell& ownFaces = cells[faceOwner[faceI]]; forAll(ownFaces, ownI) { changedFace[ownFaces[ownI]] = true; } const cell& neiFaces = cells[faceNeighbour[faceI]]; forAll(neiFaces, neiI) { changedFace[neiFaces[neiI]] = true; } } } forAll(refinedBoundaryFace, i) { if (refinedBoundaryFace[i]) { const cell& ownFaces = cells[faceOwner[i+nInternalFaces]]; forAll(ownFaces, ownI) { changedFace[ownFaces[ownI]] = true; } } } syncTools::syncFaceList ( mesh, changedFace, orEqOp() ); // Now we have in changedFace marked all affected faces. Pack. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ changedFaces = findIndices(changedFace, true); // Count changed master faces. nMasterChanged = 0; forAll(changedFace, faceI) { if (changedFace[faceI] && isMasterFace.test(faceI)) { nMasterChanged++; } } } if (debug&meshRefinement::MESH) { Pout<< "getChangedFaces : Detected " << " local:" << changedFaces.size() << " global:" << returnReduce(nMasterChanged, sumOp