diff --git a/src/dynamicMesh/dynamicMesh/Make/files b/src/dynamicMesh/dynamicMesh/Make/files index ec3738647..7400b7e69 100644 --- a/src/dynamicMesh/dynamicMesh/Make/files +++ b/src/dynamicMesh/dynamicMesh/Make/files @@ -37,8 +37,8 @@ $(slidingInterface)/decoupleSlidingInterface.C repatchCoverage = $(polyMeshModifiers)/repatchCoverage $(repatchCoverage)/repatchCoverage.C -polyhedralRefinement = $(polyMeshModifiers)/polyhedralRefinement -$(polyhedralRefinement)/polyhedralRefinement.C +$(polyMeshModifiers)/polyhedralRefinement/polyhedralRefinement.C +$(polyMeshModifiers)/prismatic2DRefinement/prismatic2DRefinement.C polyTopoChange/polyTopoChange/polyTopoChange.C polyTopoChange/polyTopoChange/actions/topoAction/topoActions.C diff --git a/src/dynamicMesh/dynamicMesh/polyMeshModifiers/prismatic2DRefinement/prismatic2DRefinement.C b/src/dynamicMesh/dynamicMesh/polyMeshModifiers/prismatic2DRefinement/prismatic2DRefinement.C new file mode 100644 index 000000000..ed0cfe212 --- /dev/null +++ b/src/dynamicMesh/dynamicMesh/polyMeshModifiers/prismatic2DRefinement/prismatic2DRefinement.C @@ -0,0 +1,5368 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | foam-extend: Open Source CFD + \\ / O peration | Version: 4.0 + \\ / A nd | Web: http://www.foam-extend.org + \\/ M anipulation | For copyright notice see file Copyright +------------------------------------------------------------------------------- +License + This file is part of foam-extend. + + foam-extend 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. + + foam-extend 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 foam-extend. If not, see . + +Author + Vuko Vukcevic, Wikki Ltd. All rights reserved. + +Notes + Specialisation of prismatic2DRefinement for 2D simulations on arbitrary + prismatic meshes (tet, hex, etc). + +\*---------------------------------------------------------------------------*/ + +#include "prismatic2DRefinement.H" +#include "polyTopoChanger.H" +#include "polyMesh.H" +#include "foamTime.H" +#include "primitiveMesh.H" +#include "polyTopoChange.H" +#include "syncTools.H" +#include "meshTools.H" +#include "cellSet.H" +#include "faceSet.H" +#include "pointSet.H" +#include "mapPolyMesh.H" +#include "emptyPolyPatch.H" +#include "addToRunTimeSelectionTable.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ + defineTypeNameAndDebug(prismatic2DRefinement, 0); + addToRunTimeSelectionTable + ( + polyMeshModifier, + prismatic2DRefinement, + dictionary + ); +} + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +Foam::label Foam::prismatic2DRefinement::getAnchorLevel +( + const label faceI, + const label nPoints +) const +{ + // Get the face + const face& f = mesh_.faces()[faceI]; + + // Sanity check for expected number of points + if (nPoints != 3 && nPoints != 4) + { + FatalErrorIn + ( + "label prismatic2DRefinement::getAnchorLevel" + "\n(" + "\n const label faceI," + "\n const label nPoints" + "\n) const" + ) << "Trying to find anchor level with " << nPoints << " points" + << " smaller than anchor level. Only nPoints = 3 and 4 are" + << " supported." + << abort(FatalError); + } + + // Sanity check: if we are expecting to find 4 points on a face which is not + // on empty patch and we find a face with 3 points, issue an error + if (f.size() <= 3 && nPoints == 4) + { + FatalErrorIn + ( + "label prismatic2DRefinement::getAnchorLevel" + "\n(" + "\n const label faceI," + "\n const label nPoints" + "\n) const" + ) << "Expected to find at least 4 points with level lower than" + << " anchor level." + << nl + << "Make sure to call this function with nPoints = 4 only if" + << " you do not expect triangular faces." + << abort(FatalError); + } + + if (f.size() <= nPoints) + { + return pointLevel_[f[findMaxLevel(f)]]; + } + else + { + const label& ownLevel = cellLevel_[mesh_.faceOwner()[faceI]]; + + if (countAnchors(f, ownLevel) >= nPoints) + { + return ownLevel; + } + else if (countAnchors(f, ownLevel + 1) >= nPoints) + { + return ownLevel + 1; + } + else + { + return -1; + } + } +} + + +void Foam::prismatic2DRefinement::calcLevel0EdgeLength() +{ + if (cellLevel_.size() != mesh_.nCells()) + { + FatalErrorIn("scalar prismatic2DRefinement::getLevel0EdgeLength() const") + << "Number of cells in mesh:" << mesh_.nCells() + << " does not equal size of cellLevel:" << cellLevel_.size() + << endl + << "This might be because of a restart with inconsistent cellLevel." + << abort(FatalError); + } + + // Determine minimum edge length per refinement level + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + const scalar GREAT2 = sqr(GREAT); + + const label nLevels = gMax(cellLevel_) + 1; + + // Initialise typical edge length squared to dummy large value + scalarField typEdgeLenSqr(nLevels, GREAT2); + + + // 1. Look only at edges surrounded by cellLevel cells only + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + // Edge list containing cellLevel of connected cells. + // Note: + // - If not set = -1 + // - Levels of connected cells = from 0 to nLevels - 1 + // - If different levels = labelMax + labelList edgeLevel(mesh_.nEdges(), -1); + + // Mark edges on empty patches. This will be used to skip edges on internal + // faces and ordinary boundaries + boolList edgeOnEmptyPatch(mesh_.nEdges() , false); + + // Get boundary mesh + const polyBoundaryMesh& boundaryMesh = mesh_.boundaryMesh(); + + // Get face-edge addressing + const labelListList& meshFaceEdges = mesh_.faceEdges(); + + // Loop through all patches + forAll (boundaryMesh, patchI) + { + // Get current patch + const polyPatch& curPatch = boundaryMesh[patchI]; + + // Check whether this patch is emptyPolyPatch + if (isA(curPatch)) + { + // Get start and end face labels + const label startFaceI = curPatch.start(); + const label endFaceI = startFaceI + curPatch.size(); + + // Mark all the faces and edges on the patch + for (label faceI = startFaceI; faceI < endFaceI; ++faceI) + { + // Get edges of this face + const labelList& curEdges = meshFaceEdges[faceI]; + + // Mark all edges + forAll (curEdges, i) + { + edgeOnEmptyPatch[curEdges[i]] = true; + } + } // End for all patch faces + } // End if the patch is empty + } // End for all patches + + // Get cell edges + const labelListList& meshCellEdges = mesh_.cellEdges(); + + // Loop through cells + forAll(cellLevel_, cellI) + { + // Get cell level and cell edges + const label& cLevel = cellLevel_[cellI]; + const labelList& edges = meshCellEdges[cellI]; + + // Loop through all edges + forAll(edges, i) + { + const label& edgeI = edges[i]; + + // Check whether the edge is on empty patch + if (edgeOnEmptyPatch[edgeI]) + { + if (edgeLevel[edgeI] == -1) + { + // Edge level not set, mark it with current cell level + edgeLevel[edgeI] = cLevel; + } + else if (edgeLevel[edgeI] == labelMax) + { + // Already marked as on different cellLevels + } + else if (edgeLevel[edgeI] != cLevel) + { + // Edge level with different cell levels + edgeLevel[edgeI] = labelMax; + } + } + // Else leave edgeLevel to dummy -1 value + } + } + + // Make sure that edges with different levels on different processors + // are also marked. Do the same test (edgeLevel != cLevel) on coupled + // edges. + syncTools::syncEdgeList + ( + mesh_, + edgeLevel, + ifEqEqAssignFirstOp(), + labelMin, + false // no separation + ); + + // Now use the edgeLevel with a valid value to determine the + // length per level. + + // Get mesh edges and points + const edgeList& meshEdges = mesh_.edges(); + const pointField& meshPoints = mesh_.points(); + + forAll(edgeLevel, edgeI) + { + // Get edge level + const label& eLevel = edgeLevel[edgeI]; + + // Edge has unique cell level (both cells have the same level) + if (eLevel > -1 && eLevel < labelMax) + { + // Get the edge and calculate the square of the length + const edge& e = meshEdges[edgeI]; + const scalar edgeLenSqr = magSqr(e.vec(meshPoints)); + + typEdgeLenSqr[eLevel] = min(typEdgeLenSqr[eLevel], edgeLenSqr); + } + // Else typical edge length squared is not affected + } + + // Get the minimum per level over all processors. Note: using minEqOp + // because if the cells are not cubic, we end up using the smallest edge + Pstream::listCombineGather(typEdgeLenSqr, minEqOp()); + Pstream::listCombineScatter(typEdgeLenSqr); + + if (debug) + { + Pout<< "prismatic2DRefinement::calcLevel0EdgeLength() :" + << " Initial edge lengths squared per refinementlevel:" + << typEdgeLenSqr << endl; + } + + + // 2. For any levels where we haven't determined a valid length yet + // use any surrounding cell level. Here we use the max so we don't + // pick up levels between cellLevel and higher cellLevel (will have + // edges sized according to highest cellLevel) + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + // Initialise maximum edge length to dummy large value + scalarField maxEdgeLenSqr(nLevels, -GREAT2); + + // Loop through cells + forAll(cellLevel_, cellI) + { + // Get cell level and cell edges + const label& cLevel = cellLevel_[cellI]; + const labelList& cEdges = meshCellEdges[cellI]; + + // Loop through edges + forAll(cEdges, i) + { + // Get the edge + const label& edgeI = cEdges[i]; + + if (edgeOnEmptyPatch[edgeI]) + { + // Edge is on empty patch, calculate the max edge length + const edge& e = meshEdges[cEdges[i]]; + const scalar edgeLenSqr = magSqr(e.vec(meshPoints)); + + maxEdgeLenSqr[cLevel] = max(maxEdgeLenSqr[cLevel], edgeLenSqr); + } + // Else typical max edge length squared is not affected + } + } + + // Get maximum per level over all processors + Pstream::listCombineGather(maxEdgeLenSqr, maxEqOp()); + Pstream::listCombineScatter(maxEdgeLenSqr); + + if (debug) + { + Pout<< "prismatic2DRefinement::calcLevel0EdgeLength() :" + << " Basic edge lengths squared per refinementlevel:" + << maxEdgeLenSqr << endl; + } + + + // 3. Combine the two sets of lengths + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + forAll(typEdgeLenSqr, levelI) + { + if + ( + equal(typEdgeLenSqr[levelI], GREAT2) + && maxEdgeLenSqr[levelI] >= 0 + ) + { + typEdgeLenSqr[levelI] = maxEdgeLenSqr[levelI]; + } + } + + if (debug) + { + Pout<< "prismatic2DRefinement::calcLevel0EdgeLength() :" + << " Final edge lengths squared per refinementlevel:" + << typEdgeLenSqr << endl; + } + + // Find lowest length present across all levels + level0EdgeLength_ = -1; + + forAll(typEdgeLenSqr, levelI) + { + const scalar& lenSqr = typEdgeLenSqr[levelI]; + + if (lenSqr < GREAT2) + { + // Note: use power instead of left shift operator to multiply the + // length with appropriate level. Easier to read. VV, 5/Jan/2018. + level0EdgeLength_ = Foam::sqrt(lenSqr)*(Foam::pow(2, levelI)); + + if (debug) + { + Pout<< "prismatic2DRefinement::calcLevel0EdgeLength() :" + << " Edge length: " << Foam::sqrt(lenSqr) << ", " + << "with edge level: " << levelI << ", " + << "has equivalent level0 lenght of:" << level0EdgeLength_ + << endl; + } + + break; + } + } + + if (level0EdgeLength_ == -1) + { + FatalErrorIn("prismatic2DRefinement::calcLevel0EdgeLength()") + << "Problem in definition of typical edge length squared: " + << typEdgeLenSqr << abort(FatalError); + } +} + + +void Foam::prismatic2DRefinement::setInstance(const fileName& inst) const +{ + if (debug) + { + Pout<< "prismatic2DRefinement::setInstance(const fileName& inst)" + << nl + << "Resetting file instance of refinement data to " << inst + << endl; + } + + cellLevel_.instance() = inst; + pointLevel_.instance() = inst; +} + + +void Foam::prismatic2DRefinement::extendMarkedCellsAcrossFaces +( + boolList& markedCell +) const +{ + // Mark all faces for all marked cells + const label nFaces = mesh_.nFaces(); + boolList markedFace(nFaces, false); + + // Get mesh cells + const cellList& meshCells = mesh_.cells(); + + // Loop through all cells + forAll (markedCell, cellI) + { + if (markedCell[cellI]) + { + // This cell is marked, get its faces + const cell& cFaces = meshCells[cellI]; + + forAll (cFaces, i) + { + markedFace[cFaces[i]] = true; + } + } + } + + // Snyc the face list across processor boundaries + syncTools::syncFaceList(mesh_, markedFace, orEqOp(), false); + + // Get necessary mesh data + const label nInternalFaces = mesh_.nInternalFaces(); + const labelList& owner = mesh_.faceOwner(); + const labelList& neighbour = mesh_.faceNeighbour(); + + // Internal faces + for (label faceI = 0; faceI < nInternalFaces; ++faceI) + { + if (markedFace[faceI]) + { + // Face will be marked, mark both owner and neighbour + markedCell[owner[faceI]] = true; + markedCell[neighbour[faceI]] = true; + } + } + + // Boundary faces + for (label faceI = nInternalFaces; faceI < nFaces; ++faceI) + { + if (markedFace[faceI]) + { + // Face will be markedd, mark owner + markedCell[owner[faceI]] = true; + } + } +} + + +void Foam::prismatic2DRefinement::extendMarkedCellsAcrossPoints +( + boolList& markedCell +) const +{ + // Mark all points for all marked cells + const label nPoints = mesh_.nPoints(); + boolList markedPoint(nPoints, false); + + // Get cell points + const labelListList& meshCellPoints = mesh_.cellPoints(); + + // Loop through all cells + forAll (markedCell, cellI) + { + if (markedCell[cellI]) + { + // This cell is marked, get its points + const labelList& cPoints = meshCellPoints[cellI]; + + forAll (cPoints, i) + { + markedPoint[cPoints[i]] = true; + } + } + } + + // Snyc point list across processor boundaries + syncTools::syncPointList + ( + mesh_, + markedPoint, + orEqOp(), + true, // Default value + true // Apply separation for parallel cyclics + ); + + // Get point cells + const labelListList& meshPointCells = mesh_.pointCells(); + + // Loop through all points + forAll (markedPoint, pointI) + { + if (markedPoint[pointI]) + { + // This point is marked, mark all of its cells + const labelList& pCells = meshPointCells[pointI]; + + forAll (pCells, i) + { + markedCell[pCells[i]] = true; + } + } + } +} + + +void Foam::prismatic2DRefinement::appendFaceSplitInfo +( + const label& faceI, + const boolList& edgeOnEmptyPatch, + const labelList& edgeMidPoint, + DynamicList