/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation \\/ M anipulation | Copyright 2015 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 . Application snappyHexMesh Description Automatic split hex mesher. Refines and snaps to surface. \*---------------------------------------------------------------------------*/ #include "argList.H" #include "Time.H" #include "fvMesh.H" #include "autoRefineDriver.H" #include "autoSnapDriver.H" #include "autoLayerDriver.H" #include "searchableSurfaces.H" #include "refinementSurfaces.H" #include "refinementFeatures.H" #include "shellSurfaces.H" #include "decompositionMethod.H" #include "noDecomp.H" #include "fvMeshDistribute.H" #include "wallPolyPatch.H" #include "refinementParameters.H" #include "snapParameters.H" #include "layerParameters.H" #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" #include "IOmanip.H" #include "decompositionModel.H" #include "fvMeshTools.H" using namespace Foam; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // Convert size (as fraction of defaultCellSize) to refinement level label sizeCoeffToRefinement ( const scalar level0Coeff, // ratio of hex cell size v.s. defaultCellSize const scalar sizeCoeff ) { return round(::log(level0Coeff/sizeCoeff)/::log(2)); } autoPtr createRefinementSurfaces ( const searchableSurfaces& allGeometry, const dictionary& surfacesDict, const dictionary& shapeControlDict, const label gapLevelIncrement, const scalar level0Coeff ) { 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); PtrList surfZones(surfI); labelList regionOffset(surfI); labelList globalMinLevel(surfI, 0); labelList globalMaxLevel(surfI, 0); labelList globalLevelIncr(surfI, 0); PtrList globalPatchInfo(surfI); List > regionMinLevel(surfI); List > regionMaxLevel(surfI); List > regionLevelIncr(surfI); List > regionAngle(surfI); List > > regionPatchInfo(surfI); HashSet unmatchedKeys(surfacesDict.toc()); surfI = 0; forAll(allGeometry.names(), geomI) { const word& geomName = allGeometry.names()[geomI]; const entry* ePtr = surfacesDict.lookupEntryPtr(geomName, false, true); if (ePtr) { const dictionary& shapeDict = ePtr->dict(); unmatchedKeys.erase(ePtr->keyword()); names[surfI] = geomName; surfaces[surfI] = geomI; const searchableSurface& surface = allGeometry[geomI]; // Find the index in shapeControlDict // Invert surfaceCellSize to get the refinementLevel const word scsFuncName = shapeDict.lookup("surfaceCellSizeFunction"); const dictionary& scsDict = shapeDict.subDict(scsFuncName + "Coeffs"); const scalar surfaceCellSize = readScalar(scsDict.lookup("surfaceCellSizeCoeff")); const label refLevel = sizeCoeffToRefinement ( level0Coeff, surfaceCellSize ); globalMinLevel[surfI] = refLevel; globalMaxLevel[surfI] = refLevel; globalLevelIncr[surfI] = gapLevelIncrement; // Surface zones surfZones.set(surfI, new surfaceZonesInfo(surface, shapeDict)); // Global perpendicular angle if (shapeDict.found("patchInfo")) { globalPatchInfo.set ( surfI, shapeDict.subDict("patchInfo").clone() ); } // Per region override of patchInfo if (shapeDict.found("regions")) { const dictionary& regionsDict = shapeDict.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] ); if (regionDict.found("patchInfo")) { regionPatchInfo[surfI].insert ( regionI, regionDict.subDict("patchInfo").clone() ); } } } } // Per region override of cellSize if (shapeDict.found("regions")) { const dictionary& shapeControlRegionsDict = shapeDict.subDict("regions"); const wordList& regionNames = allGeometry[surfaces[surfI]].regions(); forAll(regionNames, regionI) { 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") ); const label refLevel = sizeCoeffToRefinement ( level0Coeff, surfaceCellSize ); regionMinLevel[surfI].insert(regionI, refLevel); regionMaxLevel[surfI].insert(regionI, refLevel); regionLevelIncr[surfI].insert(regionI, 0); } } } 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); 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]; if (globalPatchInfo.set(surfI)) { patchInfo.set ( globalRegionI, globalPatchInfo[surfI].clone() ); } } // Overwrite with region specific information forAllConstIter(Map