Commit 4d1159e6 authored by mattijs's avatar mattijs
Browse files

ENH: snappyHexMesh: various improvements. See below or the default snappyHexMeshDict.

Refinement:
-----------
// Optionally avoid patch merging - keeps hexahedral cells
// (to be used with automatic refinement/unrefinement)
//mergePatchFaces off;

// Optional multiple locationsInMesh with corresponding optional cellZone
// (automatically generates faceZones inbetween)
locationsInMesh
(
    ((-0.09 -0.039 -0.049)  bottomAir)  // cellZone bottomAir
    ((-0.09 0.009 -0.049)   topAir)     // cellZone topAir
);

// Optional faceType and patchType specification for these faceZones
faceZoneControls
{
    bottomAir_to_topAir
    {
        faceType baffle;
    }
}

/ Optional checking of 'bleeding' of mesh through a specifying a locations
// outside the mesh
locationsOutsideMesh ((0 0 0)(12.3 101.17 3.98));

// Improved refinement: refine all cells with all (or all but one) sides refined

// Improved refinement: refine all cells with opposing faces with different
// refinement level. These cells can happen on multiply curved surfaces.
// Default on, can be switched off with
//interfaceRefine false;

Snapping
--------
// Optional smoothing of points at refinement interfaces. This will reduce
// the non-orthogonality at refinement interfaces.
//nSmoothInternal $nSmoothPatch;

Layering
--------

// Layers can be added to patches or to any side of a faceZone.
// (Any faceZone internally gets represented as two patches)

// The angle to merge patch faces can be set independently of the
// featureAngle. This is especially useful for large feature angles
// Default is the same as the featureAngle.
//mergePatchFacesAngle 45;

// Optional mesh shrinking type 'displacementMotionSolver'. It uses any
// displacementMotionSolver, e.g. displacementSBRStress
// (default is the medial-axis algorithm, 'displacementMedialAxis')
//meshShrinker displacementMotionSolver;
parent 9c8492eb
......@@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -493,21 +493,30 @@ int main(int argc, char *argv[])
// new patchID to neighbour processor)
// - number of new patches (nPatches)
labelList sidePatchID;
labelList edgePatchID;
labelList edgeZoneID;
boolList edgeFlip;
labelList inflateFaceID;
label nPatches;
Map<label> nbrProcToPatch;
Map<label> patchToNbrProc;
addPatchCellLayer::calcSidePatch
addPatchCellLayer::calcExtrudeInfo
(
true, // for internal edges get zone info from any face
mesh,
globalFaces,
edgeGlobalFaces,
extrudePatch,
sidePatchID,
edgePatchID,
nPatches,
nbrProcToPatch,
patchToNbrProc
patchToNbrProc,
edgeZoneID,
edgeFlip,
inflateFaceID
);
......@@ -659,7 +668,12 @@ int main(int argc, char *argv[])
ratio, // expansion ratio
extrudePatch, // patch faces to extrude
sidePatchID, // if boundary edge: patch to use
edgePatchID, // if boundary edge: patch for extruded face
edgeZoneID, // optional zone for extruded face
edgeFlip,
inflateFaceID, // mesh face that zone/patch info is from
exposedPatchID, // if new mesh: patches for exposed faces
nFaceLayers,
nPointLayers,
......
......@@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -1121,6 +1121,38 @@ int main(int argc, char *argv[])
);
// Refinement parameters
const refinementParameters refineParams(refineDict);
// Snap parameters
const snapParameters snapParams(snapDict);
// Add all the cellZones and faceZones
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 1. cellZones relating to surface (faceZones added later)
const labelList namedSurfaces
(
surfaceZonesInfo::getNamedSurfaces(surfaces.surfZones())
);
labelList surfaceToCellZone = surfaceZonesInfo::addCellZonesToMesh
(
surfaces.surfZones(),
namedSurfaces,
mesh
);
// 2. cellZones relating to locations
refineParams.addCellZonesToMesh(mesh);
// Add all the surface regions as patches
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
......@@ -1128,6 +1160,8 @@ int main(int argc, char *argv[])
// (faceZone surfaces)
labelList globalToMasterPatch;
labelList globalToSlavePatch;
{
Info<< nl
<< "Adding patches for surface regions" << nl
......@@ -1148,6 +1182,7 @@ int main(int argc, char *argv[])
const labelList& surfaceGeometry = surfaces.surfaces();
const PtrList<dictionary>& surfacePatchInfo = surfaces.patchInfo();
const polyBoundaryMesh& pbm = mesh.boundaryMesh();
forAll(surfaceGeometry, surfI)
{
......@@ -1157,7 +1192,9 @@ int main(int argc, char *argv[])
Info<< surfaces.names()[surfI] << ':' << nl << nl;
if (surfaces.surfZones()[surfI].faceZoneName().empty())
const word& fzName = surfaces.surfZones()[surfI].faceZoneName();
if (fzName.empty())
{
// 'Normal' surface
forAll(regNames, i)
......@@ -1188,7 +1225,7 @@ int main(int argc, char *argv[])
Info<< setf(ios_base::left)
<< setw(6) << patchI
<< setw(20) << mesh.boundaryMesh()[patchI].type()
<< setw(20) << pbm[patchI].type()
<< setw(30) << regNames[i] << nl;
globalToMasterPatch[globalRegionI] = patchI;
......@@ -1228,7 +1265,7 @@ int main(int argc, char *argv[])
Info<< setf(ios_base::left)
<< setw(6) << patchI
<< setw(20) << mesh.boundaryMesh()[patchI].type()
<< setw(20) << pbm[patchI].type()
<< setw(30) << regNames[i] << nl;
globalToMasterPatch[globalRegionI] = patchI;
......@@ -1260,12 +1297,27 @@ int main(int argc, char *argv[])
Info<< setf(ios_base::left)
<< setw(6) << patchI
<< setw(20) << mesh.boundaryMesh()[patchI].type()
<< setw(20) << pbm[patchI].type()
<< setw(30) << slaveName << nl;
globalToSlavePatch[globalRegionI] = patchI;
}
}
// For now: have single faceZone per surface. Use first
// region in surface for patch for zoneing
if (regNames.size())
{
label globalRegionI = surfaces.globalRegion(surfI, 0);
meshRefiner.addFaceZone
(
fzName,
pbm[globalToMasterPatch[globalRegionI]].name(),
pbm[globalToSlavePatch[globalRegionI]].name(),
surfaces.surfZones()[surfI].faceType()
);
}
}
Info<< nl;
......@@ -1275,10 +1327,85 @@ int main(int argc, char *argv[])
}
// Add all information for all the remaining faceZones
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
HashTable<Pair<word> > faceZoneToPatches;
forAll(mesh.faceZones(), zoneI)
{
const word& fzName = mesh.faceZones()[zoneI].name();
label mpI, spI;
surfaceZonesInfo::faceZoneType fzType;
bool hasInfo = meshRefiner.getFaceZoneInfo(fzName, mpI, spI, fzType);
if (!hasInfo)
{
// faceZone does not originate from a surface but presumably
// from a cellZone pair instead
string::size_type i = fzName.find("_to_");
if (i != string::npos)
{
word cz0 = fzName.substr(0, i);
word cz1 = fzName.substr(i+4, fzName.size()-i+4);
word slaveName(cz1 + "_to_" + cz0);
faceZoneToPatches.insert(fzName, Pair<word>(fzName, slaveName));
}
else
{
// Add as fzName + fzName_slave
const word slaveName = fzName + "_slave";
faceZoneToPatches.insert(fzName, Pair<word>(fzName, slaveName));
}
}
}
if (faceZoneToPatches.size())
{
autoRefineDriver::addFaceZones
(
meshRefiner,
refineParams,
faceZoneToPatches
);
}
// Re-do intersections on meshed boundaries since they use an extrapolated
// other side
{
const labelList adaptPatchIDs(meshRefiner.meshedPatches());
const polyBoundaryMesh& pbm = mesh.boundaryMesh();
label nFaces = 0;
forAll(adaptPatchIDs, i)
{
nFaces += pbm[adaptPatchIDs[i]].size();
}
labelList faceLabels(nFaces);
nFaces = 0;
forAll(adaptPatchIDs, i)
{
const polyPatch& pp = pbm[adaptPatchIDs[i]];
forAll(pp, i)
{
faceLabels[nFaces++] = pp.start()+i;
}
}
meshRefiner.updateIntersections(faceLabels);
}
// Parallel
// ~~~~~~~~
// Decomposition
// Construct decomposition engine. Note: cannot use decompositionModel
// MeshObject since we're clearing out the mesh inside the mesh generation.
autoPtr<decompositionMethod> decomposerPtr
(
decompositionMethod::New
......@@ -1312,14 +1439,17 @@ int main(int argc, char *argv[])
const Switch wantSnap(meshDict.lookup("snap"));
const Switch wantLayers(meshDict.lookup("addLayers"));
// Refinement parameters
const refinementParameters refineParams(refineDict);
// Snap parameters
const snapParameters snapParams(snapDict);
const Switch mergePatchFaces
(
meshDict.lookupOrDefault("mergePatchFaces", true)
);
// Layer addition parameters
const layerParameters layerParams(layerDict, mesh.boundaryMesh());
if (!mergePatchFaces)
{
Info<< "Not merging patch-faces of cell to preserve"
<< " (split)hex cell shape."
<< nl << endl;
}
if (wantRefine)
......@@ -1348,6 +1478,7 @@ int main(int argc, char *argv[])
refineParams,
snapParams,
refineParams.handleSnapProblems(),
mergePatchFaces, // merge co-planar faces
motionDict
);
......@@ -1387,6 +1518,7 @@ int main(int argc, char *argv[])
(
snapDict,
motionDict,
mergePatchFaces,
curvature,
planarAngle,
snapParams
......@@ -1408,6 +1540,9 @@ int main(int argc, char *argv[])
{
cpuTime timer;
// Layer addition parameters
const layerParameters layerParams(layerDict, mesh.boundaryMesh());
autoLayerDriver layerDriver
(
meshRefiner,
......@@ -1433,6 +1568,7 @@ int main(int argc, char *argv[])
layerDict,
motionDict,
layerParams,
mergePatchFaces,
preBalance,
decomposer,
distributor
......
......@@ -71,6 +71,11 @@ geometry
}
};
// Optional: avoid patch-face merging. Allows mesh to be used for
// refinement/unrefinement
//mergePatchFaces off; // default on
// Settings for the castellatedMesh generation.
castellatedMeshControls
{
......@@ -177,7 +182,7 @@ castellatedMeshControls
// how to select the cells that are in the cellZone
// (inside / outside / specified insidePoint)
// The orientation of the faceZone is
// - if on cellZone(s) : point out of (maximum) cellZone
// - if on cellZone(s) : point out of (minimum) cellZone
// - if freestanding : oriented according to surface
//faceZone sphere;
......@@ -249,16 +254,70 @@ castellatedMeshControls
// After refinement patches get added for all refinementSurfaces and
// all cells intersecting the surfaces get put into these patches. The
// section reachable from the locationInMesh is kept.
// section reachable from the location(s)InMesh is kept.
// NOTE: This point should never be on a face, always inside a cell, even
// after refinement.
locationInMesh (5 0.28 0.43);
//
// There are two different ways of specifying the regions to keep:
// 1. a single locationInMesh. All the 'zoned' surfaces are marked as such
// in the refinementSurfaces with the faceZone and cellZone keywords.
//
// or
//
// 2. multiple locationsInMesh, with per location the name of the cellZone.
// This uses walking to determine zones and automatically creates
// faceZones on the outside of cellZones.
// Ad 1. Specify a single location and how to treat faces inbetween
// cellZones
locationInMesh (5 0.28 0.43);
// Whether any faceZones (as specified in the refinementSurfaces)
// are only on the boundary of corresponding cellZones or also allow
// free-standing zone faces. Not used if there are no faceZones.
allowFreeStandingZoneFaces true;
// 2. Specify multiple locations with optional cellZones for the
// regions. faceZones are automatically constructed from the
// names of the cellZones: <cellZoneA> _to_ <cellZoneB>
// where the cellZoneA is the lowest numbered cellZone (non-cellZone
// cells are in a special region called "none" which is always
// last).
locationsInMesh
(
((-0.09 -0.039 -0.049) bottomAir) // cellZone 0
((-0.09 0.009 -0.049) topAir) // cellZone 1
((-0.09 0.001 -0.049) leftSolid) // cellZone 2
((0.02 0.001 -0.049) rightSolid) // cellZone 3
((-0.001 -0.039 0.0015) heater) // cellZone 4
);
// Per synthesised faceZone name the faceType and type of baffles to
// create
faceZoneControls
{
bottomAir_to_heater
{
// Optional specification of patch type (default is wall). No
// constraint types (cyclic, symmetry) etc. are allowed.
patchInfo
{
type patch;
inGroups (patchPatches);
}
faceType baffle;
}
}
// Whether any faceZones (as specified in the refinementSurfaces)
// are only on the boundary of corresponding cellZones or also allow
// free-standing zone faces. Not used if there are no faceZones.
allowFreeStandingZoneFaces true;
// Optional locations that should not be reachable from
// location(s)InMesh
locationsOutsideMesh ((100 100 100));
// Optional: do not remove cells likely to give snapping problems
// handleSnapProblems false;
......@@ -266,6 +325,10 @@ castellatedMeshControls
// Optional: switch off topological test for cells to-be-squashed
// and use geometric test instead
//useTopologicalSnapDetection false;
// Optional: do not refine surface cells with opposite faces of
// differing refinement levels
//interfaceRefine false;
}
// Settings for the snapping.
......@@ -275,6 +338,11 @@ snapControls
// to surface
nSmoothPatch 3;
// Optional: number of smoothing iterations for internal points on
// refinement interfaces. This will reduce non-orthogonality on
// refinement interfaces.
//nSmoothInternal $nSmoothPatch;
// Maximum relative distance for points to be attracted by surface.
// True distance is this factor times local maximum edge length.
// Note: changed(corrected) w.r.t 17x! (17x used 2* tolerance)
......@@ -287,6 +355,11 @@ snapControls
// before upon reaching a correct mesh.
nRelaxIter 5;
// (wip) disable snapping to opposite near surfaces (revert to 22x
// behaviour)
// detectNearSurfacesSnap false;
// Feature snapping
// Number of feature edge snapping iterations.
......@@ -305,8 +378,28 @@ snapControls
multiRegionFeatureSnap false;
// wip: disable snapping to opposite near surfaces (revert to 22x behaviour)
// detectNearSurfacesSnap false;
//- When to run face splitting (never at first iteration, always
// at last iteration). Is interval. Default -1 (disabled)
//nFaceSplitInterval 5;
// (wip) Optional for explicit feature snapping:
//- Detect baffle edges. Default is true.
//detectBaffles false;
//- Erase attraction close to feature point. Default is false.
//releasePoints true;
//- Walk along feature edges, adding missing ones. Default is true.
//stringFeatures false;
//- If diagonal attraction also attract other face points. Default is
// false
//avoidDiagonal true;
//- When splitting what concave faces to leave intact. Default is 45
// degrees.
//concaveAngle 30;
//- When splitting the minimum area ratio of faces. If face split
// causes ratio of area less than this do not split. Default is 0.3
//minAreaRatio 0.3;
}
// Settings for the layer addition.
......@@ -350,10 +443,10 @@ addLayersControls
// cannot be above minThickness do not add layer.
// If relativeSizes this is relative to undistorted size of cell
// outside layer..
minThickness 0.25;
minThickness 0.1;
// Per final patch (so not geometry!) the layer information
// Per final patch or faceZone (so not geometry!) the layer information
// Note: This behaviour changed after 21x. Any non-mentioned patches
// now slide unless:
// - nSurfaceLayers is explicitly mentioned to be 0.
......@@ -397,6 +490,10 @@ addLayersControls
// are perpendicular
featureAngle 130;
// When to merge patch faces. Default is featureAngle. Useful when
// featureAngle is large.
//mergePatchFacesAngle 45;
// Stop layer growth on highly warped cells
maxFaceThicknessRatio 0.5;
......@@ -433,8 +530,10 @@ addLayersControls
// default is 0.
//nSmoothDisplacement 90;
// (wip)Optional: do not extrude a point if none of the surrounding points is
// not extruded. Default is false.
// (wip)Optional: do not extrude any point where
// (false) : all surrounding faces are not fully extruded
// (true) : all surrounding points are not extruded
// Default is false.
//detectExtrusionIsland true;
......@@ -449,7 +548,8 @@ addLayersControls
// before upon reaching a correct mesh.
nRelaxIter 5;
// Create buffer region for new layer terminations
// Create buffer region for new layer terminations, i.e. gradually
// step down number of layers. Set to <0 to terminate layer in one go.
nBufferCellsNoExtrude 0;
// Overall max number of layer addition iterations. The mesher will
......
......@@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -220,6 +220,9 @@ class addPatchCellLayer
const face& newFace,
const label newPatchID,
const label newZoneI,
const bool newFlip,
const label inflateFaceI,
const label ownFaceI,
const label nbrFaceI,
......@@ -243,6 +246,39 @@ class addPatchCellLayer
bool&
);
//- Extract properties from mesh face in pp edge ordering
static void setFaceProps
(
const polyMesh& mesh,
const indirectPrimitivePatch& pp,
const label ppEdgeI,
const label faceI,
label& patchI,
label& zoneI,
bool& zoneFlip,
label& inflateFaceI
);
//- Find internal or boundary face to get extrude properties
// from. zoneFlip consistent with ppEdge ordering
static void findZoneFace
(
const bool useInternalFaces,
const bool useBoundaryFaces,
const polyMesh& mesh,
const indirectPrimitivePatch& pp,
const label ppEdgeI,
const UIndirectList<label>& excludeFaces,
const labelList& meshFaces,
label& inflateFaceI,
label& patchI,
label& zoneI,
bool& zoneFlip
);
//- Disallow default bitwise copy construct
addPatchCellLayer(const addPatchCellLayer&);
......@@ -303,22 +339,37 @@ public:
const indirectPrimitivePatch& pp
);
//- Boundary edges get extruded into boundary faces. Determine patch
// for these faces. This might be a to-be-created processor patch
// (patchI >= mesh.boundaryMesh().size()) in which case the
// nbrProcToPatch, patchToNbrProc give the correspondence. nPatches
// is the new number of patches.
static void calcSidePatch
//- Determine extrude information per patch edge:
// - zoneID, zoneFlip :
// picks one of the faces that connects to
// the edge. For boundary edge only looks
// at boundary faces. For internal edge it looks at internal
// faces only (zoneFromAnyFace = false) or at any face
// (zoneFromAnyFace = true). zoneFlip is consistent with
// ordering of pp edge.
// Face selected gets stored in inflateFaceID
// - patchID :
// get patch from any boundary face connected to the