diff --git a/src/mesh/snappyHexMesh/meshRefinement/meshRefinement.H b/src/mesh/snappyHexMesh/meshRefinement/meshRefinement.H index 40607fbe18..7e3b43f9cb 100644 --- a/src/mesh/snappyHexMesh/meshRefinement/meshRefinement.H +++ b/src/mesh/snappyHexMesh/meshRefinement/meshRefinement.H @@ -555,8 +555,21 @@ private: label& nRefine ) const; - //- Mark cells for surface proximity based refinement. - label markProximityRefinementWave + //- Mark faces for additional proximity based testing. Extends + // testFaces + void markProximityCandidateFaces + ( + const labelList& blockedSurfaces, + const List& regionToBlockSize, + const labelList& neiLevel, + const pointField& neiCc, + + labelList& testFaces + ) const; + + //- Mark cells for surface proximity based refinement. Uses + // ray-shooting from markInternalGapRefinement. + label markFakeGapRefinement ( const scalar planarCos, const labelList& blockedSurfaces, diff --git a/src/mesh/snappyHexMesh/meshRefinement/meshRefinementBlock.C b/src/mesh/snappyHexMesh/meshRefinement/meshRefinementBlock.C index fc27ab08af..435cadd56d 100644 --- a/src/mesh/snappyHexMesh/meshRefinement/meshRefinementBlock.C +++ b/src/mesh/snappyHexMesh/meshRefinement/meshRefinementBlock.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2018-2022 OpenCFD Ltd. + Copyright (C) 2018-2024 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -455,16 +455,14 @@ void Foam::meshRefinement::growSet //} -Foam::label Foam::meshRefinement::markProximityRefinementWave +void Foam::meshRefinement::markProximityCandidateFaces ( - const scalar planarCos, const labelList& blockedSurfaces, - const label nAllowRefine, + const List& regionToBlockSize, const labelList& neiLevel, const pointField& neiCc, - labelList& refineCell, - label& nRefine + labelList& testFaces ) const { labelListList faceZones(surfaces_.surfaces().size()); @@ -498,35 +496,6 @@ Foam::label Foam::meshRefinement::markProximityRefinementWave } - // Re-work the blockLevel of the blockedSurfaces into a length scale - // and a number of cells to cross - List regionToBlockSize(surfaces_.surfaces().size()); - for (const label surfi : blockedSurfaces) - { - const label geomi = surfaces_.surfaces()[surfi]; - const searchableSurface& s = surfaces_.geometry()[geomi]; - const label nRegions = s.regions().size(); - regionToBlockSize[surfi].setSize(nRegions); - for (label regioni = 0; regioni < nRegions; regioni++) - { - const label globalRegioni = surfaces_.globalRegion(surfi, regioni); - const label bLevel = surfaces_.blockLevel()[globalRegioni]; - regionToBlockSize[surfi][regioni] = - meshCutter_.level0EdgeLength()/pow(2.0, bLevel); - - //const label mLevel = surfaces_.maxLevel()[globalRegioni]; - //// TBD: check for higher cached level of surface due to vol - //// refinement. Problem: might still miss refinement bubble - //// fully inside thin channel - //if (isA(s) && !isA(s)) - //{ - // const triSurfaceMesh& surf = refCast(s); - //} - - //nIters = max(nIters, (2<<(mLevel-bLevel))); - } - } - // Clever limiting of the number of iterations (= max cells in the channel) // since it has too many problematic issues, e.g. with volume refinement // and the real check uses the proper distance anyway just disable. @@ -535,7 +504,7 @@ Foam::label Foam::meshRefinement::markProximityRefinementWave // Collect candidate faces (i.e. intersecting any surface and // owner/neighbour not yet refined) - const labelList testFaces(getRefineCandidateFaces(refineCell)); + //const labelList testFaces(getRefineCandidateFaces(refineCell)); // Collect segments pointField start(testFaces.size()); @@ -729,208 +698,309 @@ Foam::label Foam::meshRefinement::markProximityRefinementWave wallDistCalc.iterate(nIters); - if (debug&meshRefinement::MESH) - { - // Dump current nearest opposite surfaces - volScalarField distance - ( - IOobject - ( - "gapSize", - mesh_.time().timeName(), - mesh_, - IOobject::NO_READ, - IOobject::NO_WRITE, - IOobject::NO_REGISTER - ), - mesh_, - dimensionedScalar - ( - "zero", - dimLength, //dimensionSet(0, 1, 0, 0, 0), - -1 - ) - ); + // Extract faces of visited cells - forAll(allCellInfo, celli) - { - if (allCellInfo[celli].valid(wallDistCalc.data())) - { - const point& cc = mesh_.cellCentres()[celli]; - // Nearest surface points - const List& origin = allCellInfo[celli].origin(); - - // Find 'opposite' pair with minimum distance - for (label i = 0; i < origin.size(); i++) - { - for (label j = i + 1; j < origin.size(); j++) - { - if (((cc-origin[i]) & (cc-origin[j])) < 0) - { - const scalar d(mag(origin[i]-origin[j])); - if (distance[celli] < 0) - { - distance[celli] = d; - } - else - { - distance[celli] = min(distance[celli], d); - } - } - } - } - } - } - distance.correctBoundaryConditions(); - - Info<< "Writing measured gap distance to " - << distance.name() << endl; - distance.write(); - } - - - - // Detect tight gaps: - // - cell is inbetween the two surfaces - // - two surfaces are planarish - // - two surfaces are not too far apart - // (number of walking iterations is a too-coarse measure) - - scalarField smallGapDistance(mesh_.nCells(), 0.0); - label nMulti = 0; - label nSmallGap = 0; - - //OBJstream str(mesh_.time().timePath()/"multiRegion.obj"); + bitSet isProximityFace(mesh_.nFaces(), false); + // Make sure to include initial intersected ones + isProximityFace.set(testFaces); forAll(allCellInfo, celli) { if (allCellInfo[celli].valid(wallDistCalc.data())) { - const point& cc = mesh_.cellCentres()[celli]; + isProximityFace.set(mesh_.cells()[celli]); + } + } - const List& origin = allCellInfo[celli].origin(); - const List>& surface = - allCellInfo[celli].surface(); + syncTools::syncFaceList + ( + mesh_, + isProximityFace, + orEqOp(), + 0u + ); - // Find pair with minimum distance - for (label i = 0; i < origin.size(); i++) + testFaces = isProximityFace.toc(); +} + + +Foam::label Foam::meshRefinement::markFakeGapRefinement +( + const scalar planarCos, + const labelList& blockedSurfaces, + const label nAllowRefine, + const labelList& neiLevel, + const pointField& neiCc, + + labelList& refineCell, + label& nRefine +) const +{ + // Re-work the blockLevel of the blockedSurfaces into a length scale + // and a number of cells to cross + List regionToBlockSize(surfaces_.surfaces().size()); + scalar maxBlockSize(-1); + for (const label surfi : blockedSurfaces) + { + const label geomi = surfaces_.surfaces()[surfi]; + const searchableSurface& s = surfaces_.geometry()[geomi]; + const label nRegions = s.regions().size(); + + regionToBlockSize[surfi].setSize(nRegions, -1); + for (label regioni = 0; regioni < nRegions; regioni++) + { + const label globalRegioni = surfaces_.globalRegion(surfi, regioni); + const label bLevel = surfaces_.blockLevel()[globalRegioni]; + + // If valid blockLevel specified + if (bLevel != labelMax) { - for (label j = i + 1; j < origin.size(); j++) + regionToBlockSize[surfi][regioni] = + meshCutter_.level0EdgeLength()/pow(2.0, bLevel); + } + + maxBlockSize = max(maxBlockSize, regionToBlockSize[surfi][regioni]); + + //const label mLevel = surfaces_.maxLevel()[globalRegioni]; + //// TBD: check for higher cached level of surface due to vol + //// refinement. Problem: might still miss refinement bubble + //// fully inside thin channel + //if (isA(s) && !isA(s)) + //{ + // const triSurfaceMesh& surf = refCast(s); + //} + } + } + + // Collect candidate faces (i.e. intersecting any surface and + // owner/neighbour not yet refined) and their cells + labelList cellMap; + { + labelList testFaces(getRefineCandidateFaces(refineCell)); + + // Extend the set by faceCellFace wave upto given 3*blockLevel size + markProximityCandidateFaces + ( + blockedSurfaces, + regionToBlockSize, + neiLevel, + neiCc, + testFaces + ); + + + bitSet isTestCell(mesh_.nCells()); + for (const label facei : testFaces) + { + const label own = mesh_.faceOwner()[facei]; + if (refineCell[own] == -1) + { + isTestCell.set(own); + } + if (mesh_.isInternalFace(facei)) + { + const label nei = mesh_.faceNeighbour()[facei]; + if (refineCell[nei] == -1) { - //if (isMultiRegion[celli]) - //{ - // // The intersection locations are too inaccurate - // // (since not proper nearest, just a cell-cell ray - // // intersection) so include always - // - // smallGapDistance[celli] = - // max(smallGapDistance[celli], maxDist); - // - // - // str.writeLine(cc, origin[i]); - // str.writeLine(cc, origin[j]); - // - // nMulti++; - //} - //else - if (((cc-origin[i]) & (cc-origin[j])) < 0) - { - const label surfi = surface[i][0]; - const label regioni = surface[i][1]; + isTestCell.set(nei); + } + } + } + cellMap = isTestCell.sortedToc(); + } - const label surfj = surface[j][0]; - const label regionj = surface[j][1]; - const scalar maxSize = max - ( - regionToBlockSize[surfi][regioni], - regionToBlockSize[surfj][regionj] - ); + // Shoot rays in all 6 directions + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + // Almost exact copy of meshRefinement::markInternalGapRefinement. + // Difference is only in the length scale (now based on blockLevel) - if - ( - magSqr(origin[i]-origin[j]) - < Foam::sqr(2*maxSize) - ) - { - const scalar maxDist - ( - max - ( - mag(cc-origin[i]), - mag(cc-origin[j]) - ) - ); - smallGapDistance[celli] = - max(smallGapDistance[celli], maxDist); - nSmallGap++; - } - } + // Find per cell centre the nearest point and normal on the surfaces + List nearInfo; + vectorField nearNormal; + labelList nearSurface; + labelList nearRegion; + { + surfaces_.findNearestRegion + ( + blockedSurfaces, + pointField(mesh_.cellCentres(), cellMap), + scalarField(cellMap.size(), maxBlockSize), // use uniform for now + nearSurface, + nearInfo, + nearRegion, + nearNormal + ); + } + + + DynamicList