diff --git a/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMesh.C b/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMesh.C index 14bf0ee9eb..fb177e101f 100644 --- a/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMesh.C +++ b/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMesh.C @@ -49,11 +49,606 @@ Description #include "vtkSetWriter.H" #include "faceSet.H" #include "motionSmoother.H" +#include "polyTopoChange.H" +#include "cellModeller.H" +#include "uindirectPrimitivePatch.H" +#include "surfZoneIdentifierList.H" +#include "UnsortedMeshedSurface.H" +#include "MeshedSurface.H" +#include "globalIndex.H" using namespace Foam; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +autoPtr createRefinementSurfaces +( + const searchableSurfaces& allGeometry, + const dictionary& surfacesDict, + const dictionary& shapeControlDict +) +{ + autoPtr surfacePtr; + + // Count number of surfaces. + label surfI = 0; + forAll(allGeometry.names(), geomI) + { + const word& geomName = allGeometry.names()[geomI]; + + if (surfacesDict.found(geomName)) + { + surfI++; + } + } + + labelList surfaces(surfI); + wordList names(surfI); + wordList faceZoneNames(surfI); + wordList cellZoneNames(surfI); + List zoneInside + ( + surfI, + refinementSurfaces::NONE + ); + pointField zoneInsidePoints(surfI); + List faceType + ( + surfI, + refinementSurfaces::INTERNAL + ); + labelList regionOffset(surfI); + + labelList globalMinLevel(surfI, 0); + labelList globalMaxLevel(surfI, 0); + labelList globalLevelIncr(surfI, 0); + scalarField globalAngle(surfI, -GREAT); + PtrList globalPatchInfo(surfI); + List > regionMinLevel(surfI); + List > regionMaxLevel(surfI); + List > regionLevelIncr(surfI); + List > regionAngle(surfI); + List > > regionPatchInfo(surfI); + + surfI = 0; + forAll(allGeometry.names(), geomI) + { + const word& geomName = allGeometry.names()[geomI]; + + if (surfacesDict.found(geomName)) + { + const dictionary& dict = surfacesDict.subDict(geomName); + + names[surfI] = geomName; + surfaces[surfI] = geomI; + + // Find the index in shapeControlDict + // Invert surfaceCellSize to get the refinementLevel + if (shapeControlDict.found(geomName)) + { + const dictionary& shapeDict = + shapeControlDict.subDict(geomName); + + const word scsFuncName = + shapeDict.lookup("surfaceCellSizeFunction"); + const dictionary& scsDict = + shapeDict.subDict(scsFuncName + "Coeffs"); + + const scalar surfaceCellSize = + readScalar(scsDict.lookup("surfaceCellSizeCoeff")); + + globalMinLevel[surfI] = label(1.0/surfaceCellSize); + globalMaxLevel[surfI] = label(1.0/surfaceCellSize); + globalLevelIncr[surfI] = shapeDict.lookupOrDefault + ( + "gapLevelIncrement", + 0 + ); + } + else + { + FatalErrorIn + ( + "createRefinementSurfaces" + "(const searchableSurfaces&, const dictionary>&)" + ) << "Illegal level specification for surface " + << names[surfI] + << " not found in shapeControlDict" + << exit(FatalError); + } + + if + ( + globalMinLevel[surfI] < 0 + || globalMaxLevel[surfI] < globalMinLevel[surfI] + || globalLevelIncr[surfI] < 0 + ) + { + FatalErrorIn + ( + "createRefinementSurfaces" + "(const searchableSurfaces&, const dictionary>&)" + ) << "Illegal level specification for surface " + << names[surfI] + << " : minLevel:" << globalMinLevel[surfI] + << " maxLevel:" << globalMaxLevel[surfI] + << " levelIncrement:" << globalLevelIncr[surfI] + << exit(FatalError); + } + + + // Global zone names per surface + if (dict.readIfPresent("faceZone", faceZoneNames[surfI])) + { + // Read optional entry to determine inside of faceZone + + word method; + bool hasSide = dict.readIfPresent("cellZoneInside", method); + if (hasSide) + { + zoneInside[surfI] = + refinementSurfaces::areaSelectionAlgoNames[method]; + if (zoneInside[surfI] == refinementSurfaces::INSIDEPOINT) + { + dict.lookup("insidePoint") >> zoneInsidePoints[surfI]; + } + + } + else + { + // Check old syntax + bool inside; + if (dict.readIfPresent("zoneInside", inside)) + { + hasSide = true; + zoneInside[surfI] = + ( + inside + ? refinementSurfaces::INSIDE + : refinementSurfaces::OUTSIDE + ); + } + } + + // Read optional cellZone name + + if (dict.readIfPresent("cellZone", cellZoneNames[surfI])) + { + if + ( + ( + zoneInside[surfI] == refinementSurfaces::INSIDE + || zoneInside[surfI] == refinementSurfaces::OUTSIDE + ) + && !allGeometry[surfaces[surfI]].hasVolumeType() + ) + { + IOWarningIn + ( + "createRefinementSurfaces(..)", + dict + ) << "Illegal entry zoneInside " + << refinementSurfaces::areaSelectionAlgoNames + [ + zoneInside[surfI] + ] + << " for faceZone " + << faceZoneNames[surfI] + << " since surface " << names[surfI] + << " is not closed." << endl; + } + } + else if (hasSide) + { + IOWarningIn + ( + "createRefinementSurfaces(..)", + dict + ) << "Unused entry zoneInside for faceZone " + << faceZoneNames[surfI] + << " since no cellZone specified." + << endl; + } + + // How to handle faces on faceZone + word faceTypeMethod; + if (dict.readIfPresent("faceType", faceTypeMethod)) + { + faceType[surfI] = + refinementSurfaces::faceZoneTypeNames[faceTypeMethod]; + } + } + + + + // Global perpendicular angle + if (dict.found("patchInfo")) + { + globalPatchInfo.set + ( + surfI, + dict.subDict("patchInfo").clone() + ); + } + dict.readIfPresent("perpendicularAngle", globalAngle[surfI]); + + if (dict.found("regions")) + { + const dictionary& regionsDict = dict.subDict("regions"); + const wordList& regionNames = + allGeometry[surfaces[surfI]].regions(); + + forAll(regionNames, regionI) + { + if (regionsDict.found(regionNames[regionI])) + { + // Get the dictionary for region + const dictionary& regionDict = regionsDict.subDict + ( + regionNames[regionI] + ); + + const dictionary& shapeDict = + shapeControlDict.subDict(geomName); + + const dictionary& shapeControlRegionsDict = + shapeDict.subDict("regions"); + + if (shapeControlRegionsDict.found(regionNames[regionI])) + { + const dictionary& shapeControlRegionDict = + shapeControlRegionsDict.subDict + ( + regionNames[regionI] + ); + + const word scsFuncName = + shapeControlRegionDict.lookup + ( + "surfaceCellSizeFunction" + ); + const dictionary& scsDict = + shapeControlRegionDict.subDict + ( + scsFuncName + "Coeffs" + ); + + const scalar surfaceCellSize = + readScalar + ( + scsDict.lookup("surfaceCellSizeCoeff") + ); + + globalMinLevel[surfI] = label(1.0/surfaceCellSize); + globalMaxLevel[surfI] = label(1.0/surfaceCellSize); + globalLevelIncr[surfI] = + shapeControlRegionDict.lookupOrDefault + ( + "gapLevelIncrement", + 0 + ); + } + else + { + FatalErrorIn + ( + "createRefinementSurfaces" + "(const searchableSurfaces&, const dictionary&)" + ) << "Illegal level specification for surface " + << regionNames[regionI] + << " not found in shapeControlDict" + << exit(FatalError); + } + + const labelPair refLevel(regionDict.lookup("level")); + + regionMinLevel[surfI].insert(regionI, refLevel[0]); + regionMaxLevel[surfI].insert(regionI, refLevel[1]); + label levelIncr = regionDict.lookupOrDefault + ( + "gapLevelIncrement", + 0 + ); + regionLevelIncr[surfI].insert(regionI, levelIncr); + + if + ( + refLevel[0] < 0 + || refLevel[1] < refLevel[0] + || levelIncr < 0 + ) + { + FatalErrorIn + ( + "createRefinementSurfaces" + "(const searchableSurfaces&, const dictionary&)" + ) << "Illegal level specification for surface " + << names[surfI] << " region " + << regionNames[regionI] + << " : minLevel:" << refLevel[0] + << " maxLevel:" << refLevel[1] + << " levelIncrement:" << levelIncr + << exit(FatalError); + } + + if (regionDict.found("perpendicularAngle")) + { + regionAngle[surfI].insert + ( + regionI, + readScalar + ( + regionDict.lookup("perpendicularAngle") + ) + ); + } + + if (regionDict.found("patchInfo")) + { + regionPatchInfo[surfI].insert + ( + regionI, + regionDict.subDict("patchInfo").clone() + ); + } + } + } + } + surfI++; + } + } + + // Calculate local to global region offset + label nRegions = 0; + + forAll(surfaces, surfI) + { + regionOffset[surfI] = nRegions; + nRegions += allGeometry[surfaces[surfI]].regions().size(); + } + + // Rework surface specific information into information per global region + labelList minLevel(nRegions, 0); + labelList maxLevel(nRegions, 0); + labelList gapLevel(nRegions, -1); + scalarField perpendicularAngle(nRegions, -GREAT); + PtrList patchInfo(nRegions); + + forAll(globalMinLevel, surfI) + { + label nRegions = allGeometry[surfaces[surfI]].regions().size(); + + // Initialise to global (i.e. per surface) + for (label i = 0; i < nRegions; i++) + { + label globalRegionI = regionOffset[surfI] + i; + minLevel[globalRegionI] = globalMinLevel[surfI]; + maxLevel[globalRegionI] = globalMaxLevel[surfI]; + gapLevel[globalRegionI] = + maxLevel[globalRegionI] + + globalLevelIncr[surfI]; + + perpendicularAngle[globalRegionI] = globalAngle[surfI]; + if (globalPatchInfo.set(surfI)) + { + patchInfo.set + ( + globalRegionI, + globalPatchInfo[surfI].clone() + ); + } + } + + // Overwrite with region specific information + forAllConstIter(Map