changed dictionary

This commit is contained in:
mattijs
2008-06-03 23:52:11 +01:00
parent 1021661f5a
commit d2bb8ce337
9 changed files with 1183 additions and 387 deletions

View File

@ -34,9 +34,6 @@ Description
#include "Time.H" #include "Time.H"
#include "fvMesh.H" #include "fvMesh.H"
#include "autoHexMeshDriver.H" #include "autoHexMeshDriver.H"
#include "pointMesh.H"
#include "motionSmoother.H"
#include "mapDistributePolyMesh.H"
using namespace Foam; using namespace Foam;
@ -52,6 +49,18 @@ int main(int argc, char *argv[])
Info<< "Read mesh in = " Info<< "Read mesh in = "
<< runTime.cpuTimeIncrement() << " s" << endl; << runTime.cpuTimeIncrement() << " s" << endl;
// Read decomposePar dictionary
IOdictionary decomposeDict
(
IOobject
(
"decomposeParDict",
runTime.system(),
mesh,
IOobject::MUST_READ,
IOobject::NO_WRITE
)
);
// Read meshing dictionary // Read meshing dictionary
IOdictionary meshDict IOdictionary meshDict
@ -66,24 +75,46 @@ int main(int argc, char *argv[])
) )
); );
// Read decomposePar dictionary // refinement parameters
IOdictionary decomposeDict const dictionary& refineDict = meshDict.subDict("refineDict");
// snap-to-surface parameters
const dictionary& snapDict = meshDict.subDict("snapDict");
// mesh motion and mesh quality parameters
const dictionary& motionDict = meshDict.subDict("motionDict");
// layer addition parameters
const dictionary& layerDict = meshDict.subDict("layerDict");
// Main meshing driver. Read surfaces. Determine initial intersections.
autoHexMeshDriver meshEngine
( (
IOobject mesh,
( meshDict, // global control parameters
"decomposeParDict", refineDict, // refinement parameters
runTime.system(), decomposeDict
mesh,
IOobject::MUST_READ,
IOobject::NO_WRITE
)
); );
// Main meshing driver. Read surfaces. Determine intersections. Switch wantRefine(meshDict.lookup("doRefine"));
autoHexMeshDriver meshEngine(mesh, meshDict, decomposeDict); Switch wantSnap(meshDict.lookup("doSnap"));
Switch wantLayers(meshDict.lookup("doLayers"));
// Do all: refine, snap, add layers if (wantRefine)
meshEngine.doMesh(); {
meshEngine.doRefine(refineDict, wantSnap);
}
if (wantSnap)
{
meshEngine.doSnap(snapDict, motionDict);
}
if (wantLayers)
{
meshEngine.doLayers(layerDict, motionDict);
}
Info<< "Finished meshing in = " Info<< "Finished meshing in = "
<< runTime.elapsedCpuTime() << " s." << endl; << runTime.elapsedCpuTime() << " s." << endl;

View File

@ -0,0 +1,314 @@
/*---------------------------------------------------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: 1.0 |
| \\ / A nd | Web: http://www.openfoam.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
root "/home/penfold/mattijs/foam/mattijs2.1/run/icoFoam";
case "cavity";
instance "system";
local "";
class dictionary;
object autoHexMeshDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Which phases to run.
doRefine true;
doSnap true;
doLayers true; // includes autoMergeFaces
// Whether to dump intermediate meshes and print lots
// 1 : write mesh
// 2 : write volScalarField with cellLevel for postprocessing
// 4 : write current intersections as .obj files
debug 0;
refineDict
{
// Which part to keep.
// NOTE: This point should never be on a face, always inside a cell, even
// after refinement.
keepPoints ((3 0.28 0.43));
// Whether to remove/split cells likely to give problems when snapping
handleSnapProblems on;
// Merge tolerance. Is fraction of overall bounding box of initial mesh
mergeTolerance 1E-6;
// While refining maximum number of cells per processor. This is basically
// the number of cells that fit on a processor. If you choose this too small
// it will do just more refinement iterations to obtain a similar mesh.
procCellLimit 1000000;
// Overall cell limit (approximately). Refinement will stop immediately
// upon reaching this number so a refinement level might not complete.
// Note that this is the number of cells before removing the part which
// is not 'visible' from the keepPoint. The final number of cells might actually
// be a lot less.
cellLimit 2000000;
// The surface refinement loop might spend lots of iterations refining just a
// few cells. This setting will cause refinement to stop if <= minimumRefine
// are selected for refinement. Note: it will at least do one iteration
// (unless the number of cells to refine is 0)
minimumRefine 0;
// Number of buffer layers between different levels.
// 1 means normal 2:1 refinement restriction, larger means slower
// refinement.
nBufferLayers 1;
// Feature Edge Refinement
// ~~~~~~~~~~~~~~~~~~~~~~~
// External feature file. Read from constant/triSurface for now.
// Limitations:
// - either start or edge of any feature line has to be inside domain
// and be visible from keepPoint on starting mesh.
// - refining cells containing features is separate phase before refining
// based on surface.
// - no load balancing, no check for cellLimit is done while doing this.
features
(
// {
// file "someLine.eMesh";
// level 2;
// }
);
// Internal Mesh Refinement
// ~~~~~~~~~~~~~~~~~~~~~~~~
// Specifies the areas where the refinement has to be a certain level.
// These surfaces have to be closed. Refinement is either inside
// (refineInside = true) or outside. (note:insideness or outsideness
// is with respect to far away)
// Note:that even using these the transition can never be faster than
// nBufferLayers!
// Note:the refinement level can never be higher than any of the surfaces
// they overlap with. See below for the surface refinement level specification.
refinementShells
(
{
//type triSurfaceMesh;
//name cube1x1x1.stl;
type searchableBox;
name box1x1x1;
min (2.5 -0.5 -0.5);
max (3.5 0.5 0.5);
level 4;
refineInside true;
}
);
// Surface based refinement
// ~~~~~~~~~~~~~~~~~~~~~~~~
// Curvature. Cosine of angle between two neighbouring surface intersections.
// Only used if cell level > minLevel and < maxLevel.
curvature 0.5;
// Overall the refinement is according to the following rules:
// - if the cell-cell vector intersects a surface any cell that
// is less refined than the minRefinementLevel of the surface gets refined.
// - else if the refinement level of the cell is between the
// minRefinementLevel and maxRefinementLevel the cell gets refined if
// - the normal of neighbouring surface intersections differ by more
// than above curvature
// - or if neighbouring surface intersections are on different surfaces or
// different surface regions.
// surfaces
surfaces
(
{
name sphere;
file "sphere.stl";
// Surface wide refinement level
minRefinementLevel 1;
maxRefinementLevel 1;
// Layers
surfaceLayers 1;
// Region specific refinement level
regions
(
{
name firstSolid;
minRefinementLevel 3;
maxRefinementLevel 3;
surfaceLayers 2;
}
{
name secondSolid;
minRefinementLevel 1;
maxRefinementLevel 1;
surfaceLayers 1;
}
);
}
);
}
// For snapping
snapDict
{
//- Number of patch smoothing iterations before finding correspondence
// to surface
nSmoothPatch 3;
//- Relative distance for points to be attracted by surface feature point
// or edge. True distance is this factor times local
// maximum edge length.
snapTol 4.0;
//- Whether to move internal mesh as well as boundary
smoothMesh true;
//- Number of mesh displacement smoothing iterations.
nSmoothDispl 30;
//- Maximum number of snapping relaxation iterations. Should stop
// before upon reaching a correct mesh.
nSnap 5;
}
// For cell layers
layerDict
{
//- When not to extrude surface. 0 is flat surface, 90 is when two faces
// make straight angle.
featureAngle 60;
//- Maximum number of snapping relaxation iterations. Should stop
// before upon reaching a correct mesh.
nSnap 5;
//- Minimum thickness of cell layer. If for any reason layer cannot be
// above minThickness do not add layer if thickness below minThickNess.
// Relative to undistorted cell size
minThickness 0.25;
//- If points get not extruded do nGrow layers of connected faces that are
// not grown. Is used to not do layers at all close to features.
nGrow 1;
// Expansion factor for layer mesh
expansionRatio 1.3;
// Ratio of cell size in final added cell layer to cell size
// outside layer
finalLayerRatio 0.3;
// Number of smoothing iterations of surface normals
nSmoothSurfaceNormals 1;
// Number of smoothing iterations of interior mesh movement direction
nSmoothNormals 3;
// Smooth layer thickness over surface patches
nSmoothThickness 10;
// Stop layer growth on highly warped cells
maxFaceThicknessRatio 0.5;
// Reduce layer growth where ratio thickness to medial
// distance is large
maxThicknessToMedialRatio 0.3;
// Angle used to pick up medial axis points
minMedianAxisAngle 130;
// Create buffer region for new layer terminations
nBufferCellsNoExtrude 0;
thickness 0.5;
nSmoothDispl 4;
}
// For mesh motion
motionDict
{
//
// Mesh Quality Parameters. Decide when mesh is good enough to stop
// smoothing.
//
//- Maximum non-orthogonality allowed. Set to 180 to disable.
maxNonOrtho 65;
//- Max skewness allowed. Set to <0 to disable.
maxBoundarySkewness 20;
maxInternalSkewness 4;
//- Max concaveness allowed. Is angle (in degrees) below which concavity
// is allowed. 0 is straight face, <0 would be convex face.
// Set to 180 to disable.
maxConcave 80;
//- Minimum projected area v.s. actual area. Set to -1 to disable.
minFlatness 0.5;
//- Minimum pyramid volume. Is absolute volume of cell pyramid.
// Set to very negative number (e.g. -1E30) to disable.
minVol 1e-13;
//- Minimum face area. Set to <0 to disable.
minArea -1;
//- Minimum face twist. Set to <-1 to disable. dot product of face normal
//- and face centre triangles normal
minTwist 0.05;
//- minimum normalised cell determinant
//- 1 = hex, <= 0 = folded or flattened illegal cell
minDeterminant 0.001;
//- minFaceWeight (0 -> 0.5)
minFaceWeight 0.05;
//- minVolRatio (0 -> 1)
minVolRatio 0.01;
//must be >0 for Fluent compatibility
minTriangleTwist -1;
// Advanced
//- Number of error distribution iterations
nSmoothScale 4;
//- amount to scale back displacement at error points
errorReduction 0.75;
}
// ************************************************************************* //

View File

@ -52,9 +52,9 @@ defineTypeNameAndDebug(autoHexMeshDriver, 0);
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
// Check writing tolerance before doing any serious work // Check writing tolerance before doing any serious work
Foam::scalar Foam::autoHexMeshDriver::getMergeDistance() const Foam::scalar Foam::autoHexMeshDriver::getMergeDistance(const scalar mergeTol)
const
{ {
const scalar mergeTol = readScalar(dict_.lookup("mergeTolerance"));
const boundBox& meshBb = mesh_.bounds(); const boundBox& meshBb = mesh_.bounds();
scalar mergeDist = mergeTol*mag(meshBb.max() - meshBb.min()); scalar mergeDist = mergeTol*mag(meshBb.max() - meshBb.min());
scalar writeTol = std::pow scalar writeTol = std::pow
@ -70,7 +70,7 @@ Foam::scalar Foam::autoHexMeshDriver::getMergeDistance() const
if (mesh_.time().writeFormat() == IOstream::ASCII && mergeTol < writeTol) if (mesh_.time().writeFormat() == IOstream::ASCII && mergeTol < writeTol)
{ {
FatalErrorIn("autoHexMeshDriver::getMergeDistance() const") FatalErrorIn("autoHexMeshDriver::getMergeDistance(const scalar) const")
<< "Your current settings specify ASCII writing with " << "Your current settings specify ASCII writing with "
<< IOstream::defaultPrecision() << " digits precision." << endl << IOstream::defaultPrecision() << " digits precision." << endl
<< "Your merging tolerance (" << mergeTol << ") is finer than this." << "Your merging tolerance (" << mergeTol << ") is finer than this."
@ -306,9 +306,8 @@ Foam::autoHexMeshDriver::autoHexMeshDriver
curvature_(readScalar(dict_.lookup("curvature"))), curvature_(readScalar(dict_.lookup("curvature"))),
nBufferLayers_(readLabel(dict_.lookup("nBufferLayers"))), nBufferLayers_(readLabel(dict_.lookup("nBufferLayers"))),
keepPoints_(dict_.lookup("keepPoints")), keepPoints_(dict_.lookup("keepPoints")),
mergeDist_(getMergeDistance()) mergeDist_(getMergeDistance(readScalar(dict_.lookup("mergeTolerance"))))
{ {
if (debug_ > 0) if (debug_ > 0)
{ {
meshRefinement::debug = debug_; meshRefinement::debug = debug_;
@ -471,17 +470,34 @@ Foam::autoHexMeshDriver::autoHexMeshDriver
{ {
if (nTrisPerRegion[i] > 0) if (nTrisPerRegion[i] > 0)
{ {
label globalRegionI = surfaces().globalRegion(surfI, i);
// Use optionally specified patch type and name
word patchType = surfaces().patchType()[globalRegionI];
if (patchType == "")
{
patchType = wallPolyPatch::typeName;
}
word patchName = surfaces().patchName()[globalRegionI];
if (patchName == "")
{
patchName =
surfaces().names()[surfI]
+ '_'
+ regions[i].name();
}
label patchI = meshRefinement::addPatch label patchI = meshRefinement::addPatch
( (
mesh, mesh,
//s.searchableSurface::name() + '_' + regions[i].name(), patchName,
surfaces().names()[surfI] + '_' + regions[i].name(), patchType
wallPolyPatch::typeName
); );
Info<< patchI << '\t' << regions[i].name() << nl; Info<< patchI << '\t' << regions[i].name() << nl;
globalToPatch_[surfaces().globalRegion(surfI, i)] = patchI; globalToPatch_[globalRegionI] = patchI;
} }
} }
@ -593,15 +609,283 @@ Foam::autoHexMeshDriver::autoHexMeshDriver
} }
// Construct from separate dictionaries.
Foam::autoHexMeshDriver::autoHexMeshDriver
(
fvMesh& mesh,
const dictionary& controlDict,
const dictionary& refineDict,
const dictionary& decomposeDict
)
:
mesh_(mesh),
dict_(controlDict),
debug_(readLabel(controlDict.lookup("debug"))),
maxGlobalCells_(readLabel(refineDict.lookup("cellLimit"))),
maxLocalCells_(readLabel(refineDict.lookup("procCellLimit"))),
minRefineCells_(readLabel(refineDict.lookup("minimumRefine"))),
curvature_(readScalar(refineDict.lookup("curvature"))),
nBufferLayers_(readLabel(refineDict.lookup("nBufferLayers"))),
keepPoints_(refineDict.lookup("keepPoints")),
mergeDist_
(
getMergeDistance(readScalar(refineDict.lookup("mergeTolerance")))
)
{
if (debug_ > 0)
{
meshRefinement::debug = debug_;
autoHexMeshDriver::debug = debug_;
}
Info<< "Overall cell limit : " << maxGlobalCells_
<< endl;
Info<< "Per processor cell limit : " << maxLocalCells_
<< endl;
Info<< "Minimum number of cells to refine : " << minRefineCells_
<< endl;
Info<< "Curvature : " << curvature_
<< nl << endl;
Info<< "Layers between different refinement levels : " << nBufferLayers_
<< endl;
// Check keepPoints are sensible
findCells(keepPoints_);
// Read refinement shells
// ~~~~~~~~~~~~~~~~~~~~~~
{
Info<< "Reading refinement shells." << endl;
PtrList<dictionary> shellDicts(refineDict.lookup("refinementShells"));
shells_.setSize(shellDicts.size());
shellLevels_.setSize(shellDicts.size());
shellRefineInside_.setSize(shellDicts.size());
forAll(shellDicts, i)
{
const dictionary& dict = shellDicts[i];
shells_.set
(
i,
searchableSurface::New
(
dict.lookup("type"),
dict.lookup("name"),
mesh_.time(),
dict
)
);
shellLevels_[i] = readLabel(dict.lookup("level"));
shellRefineInside_[i] = Switch(dict.lookup("refineInside"));
if (shellRefineInside_[i])
{
Info<< "Refinement level " << shellLevels_[i]
<< " for all cells inside " << shells_[i].name() << endl;
}
else
{
Info<< "Refinement level " << shellLevels_[i]
<< " for all cells outside " << shells_[i].name() << endl;
}
}
Info<< "Read refinement shells in = "
<< mesh_.time().cpuTimeIncrement() << " s" << endl;
// Orient shell surfaces before any searching is done.
Info<< "Orienting triSurface shells so point far away is outside."
<< endl;
orientOutside(shells_);
Info<< "Oriented shells in = "
<< mesh_.time().cpuTimeIncrement() << " s" << endl;
}
// Read refinement surfaces
// ~~~~~~~~~~~~~~~~~~~~~~~~
{
Info<< "Reading surfaces and constructing search trees." << endl;
surfacesPtr_.reset
(
new refinementSurfaces
(
IOobject
(
"", // dummy name
mesh_.time().constant(), // directory
"triSurface", // instance
mesh_.time(), // registry
IOobject::MUST_READ,
IOobject::NO_WRITE
),
refineDict.lookup("surfaces")
)
);
Info<< "Read surfaces in = "
<< mesh_.time().cpuTimeIncrement() << " s" << endl;
// Orient surfaces (if they're closed) before any searching is done.
Info<< "Orienting (closed) surfaces so keepPoint is outside." << endl;
forAll(surfaces(), i)
{
if (refinementSurfaces::isSurfaceClosed(surfaces()[i]))
{
refinementSurfaces::orientSurface
(
keepPoints_[0],
surfacesPtr_()[i]
);
}
}
Info<< "Oriented closed surfaces in = "
<< mesh_.time().cpuTimeIncrement() << " s" << endl;
Info<< "Setting refinement level of surface to be consistent"
<< " with shells." << endl;
surfacesPtr_().setMinLevelFields
(
shells_,
shellLevels_,
shellRefineInside_
);
Info<< "Checked shell refinement in = "
<< mesh_.time().cpuTimeIncrement() << " s" << endl;
}
// Check faceZones are synchronised
checkCoupledFaceZones();
// Add all the surface regions as patches
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{
Info<< nl
<< "Adding patches for surface regions" << nl
<< "----------------------------------" << nl
<< endl;
// From global region number to mesh patch.
globalToPatch_.setSize(surfaces().nRegions(), -1);
Info<< "Patch\tRegion" << nl
<< "-----\t------"
<< endl;
forAll(surfaces(), surfI)
{
const triSurfaceMesh& s = surfaces()[surfI];
Info<< surfaces().names()[surfI] << ':' << nl << nl;
const geometricSurfacePatchList& regions = s.patches();
labelList nTrisPerRegion(surfaces().countRegions(s));
forAll(regions, i)
{
if (nTrisPerRegion[i] > 0)
{
label patchI = meshRefinement::addPatch
(
mesh,
//s.searchableSurface::name() + '_' + regions[i].name(),
surfaces().names()[surfI] + '_' + regions[i].name(),
wallPolyPatch::typeName
);
Info<< patchI << '\t' << regions[i].name() << nl;
globalToPatch_[surfaces().globalRegion(surfI, i)] = patchI;
}
}
Info<< nl;
}
Info<< "Added patches in = "
<< mesh_.time().cpuTimeIncrement() << " s" << endl;
}
// Parallel
// ~~~~~~~~
{
// Decomposition
decomposerPtr_ = decompositionMethod::New
(
decomposeDict,
mesh_
);
decompositionMethod& decomposer = decomposerPtr_();
if (Pstream::parRun() && !decomposer.parallelAware())
{
FatalErrorIn("autoHexMeshDriver::autoHexMeshDriver(const IOobject&, fvMesh&)")
<< "You have selected decomposition method "
<< decomposer.typeName
<< " which is not parallel aware." << endl
<< "Please select one that is (parMetis, hierarchical)"
<< exit(FatalError);
}
// Mesh distribution engine (uses tolerance to reconstruct meshes)
distributorPtr_.reset(new fvMeshDistribute(mesh_, mergeDist_));
}
// Refinement engine
// ~~~~~~~~~~~~~~~~~
{
Info<< nl
<< "Determining initial surface intersections" << nl
<< "-----------------------------------------" << nl
<< endl;
// Main refinement engine
meshRefinerPtr_.reset
(
new meshRefinement
(
mesh,
mergeDist_, // tolerance used in sorting coordinates
surfaces()
)
);
Info<< "Calculated surface intersections in = "
<< mesh_.time().cpuTimeIncrement() << " s" << endl;
// Some stats
meshRefinerPtr_().printMeshInfo(debug_, "Initial mesh");
meshRefinerPtr_().write
(
debug_&meshRefinement::OBJINTERSECTIONS,
mesh_.time().path()/mesh_.time().timeName()
);
}
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
// Read explicit feature edges // Read explicit feature edges
Foam::label Foam::autoHexMeshDriver::readFeatureEdges() Foam::label Foam::autoHexMeshDriver::readFeatureEdges
(
const PtrList<dictionary>& featDicts
)
{ {
Info<< "Reading external feature lines." << endl; Info<< "Reading external feature lines." << endl;
PtrList<dictionary> featDicts(dict_.lookup("features"));
featureMeshes_.setSize(featDicts.size()); featureMeshes_.setSize(featDicts.size());
featureLevels_.setSize(featDicts.size()); featureLevels_.setSize(featDicts.size());
@ -647,13 +931,13 @@ Foam::label Foam::autoHexMeshDriver::readFeatureEdges()
Foam::label Foam::autoHexMeshDriver::featureEdgeRefine Foam::label Foam::autoHexMeshDriver::featureEdgeRefine
( (
const PtrList<dictionary>& featDicts,
const label maxIter, const label maxIter,
const label minRefine const label minRefine
) )
{ {
// Read explicit feature edges // Read explicit feature edges
readFeatureEdges(); readFeatureEdges(featDicts);
meshRefinement& meshRefiner = meshRefinerPtr_(); meshRefinement& meshRefiner = meshRefinerPtr_();
@ -1359,122 +1643,232 @@ void Foam::autoHexMeshDriver::writeMesh(const string& msg) const
} }
void Foam::autoHexMeshDriver::doMesh()
{
Switch doRefine(dict_.lookup("doRefine"));
Switch doSnap(dict_.lookup("doSnap"));
Switch doLayers(dict_.lookup("doLayers"));
Info<< "Do refinement : " << doRefine << nl
<< "Do snapping : " << doSnap << nl void Foam::autoHexMeshDriver::doRefine
<< "Do layers : " << doLayers << nl (
const dictionary& refineDict,
const bool prepareForSnapping
)
{
Info<< nl
<< "Refinement phase" << nl
<< "----------------" << nl
<< endl; << endl;
if (doRefine) const_cast<Time&>(mesh_.time())++;
PtrList<dictionary> featDicts(refineDict.lookup("features"));
// Refine around feature edges
featureEdgeRefine
(
featDicts,
100, // maxIter
0 // min cells to refine
);
// Refine based on surface
surfaceOnlyRefine
(
100 // maxIter
);
// Remove cells (a certain distance) beyond surface intersections
removeInsideCells
(
1 // nBufferLayers
);
// Internal mesh refinement
shellRefine
(
100 // maxIter
);
// Introduce baffles at surface intersections
baffleAndSplitMesh(prepareForSnapping);
// Mesh is at its finest. Do optional zoning.
zonify();
// Pull baffles apart
splitAndMergeBaffles(prepareForSnapping);
// Do something about cells with refined faces on the boundary
if (prepareForSnapping)
{ {
Info<< nl mergePatchFaces();
<< "Refinement phase" << nl
<< "----------------" << nl
<< endl;
const_cast<Time&>(mesh_.time())++;
// Refine around feature edges
featureEdgeRefine
(
100, // maxIter
0 // min cells to refine
);
// Refine based on surface
surfaceOnlyRefine
(
100 // maxIter
);
// Remove cells (a certain distance) beyond surface intersections
removeInsideCells
(
1 // nBufferLayers
);
// Internal mesh refinement
shellRefine
(
100 // maxIter
);
// Introduce baffles at surface intersections
baffleAndSplitMesh(doSnap);
// Mesh is at its finest. Do optional zoning.
zonify();
// Pull baffles apart
splitAndMergeBaffles(doSnap);
// Do something about cells with refined faces on the boundary
if (doSnap)
{
mergePatchFaces();
}
// Do final balancing. Keep zoned faces on one processor.
balance(true, false);
// Write mesh
writeMesh("Refined mesh");
} }
// Do final balancing. Keep zoned faces on one processor.
balance(true, false);
// Write mesh
writeMesh("Refined mesh");
}
void Foam::autoHexMeshDriver::doSnap
(
const dictionary& snapDict,
const dictionary& motionDict
)
{
Info<< nl
<< "Morphing phase" << nl
<< "--------------" << nl
<< endl;
const_cast<Time&>(mesh_.time())++;
// Get the labels of added patches.
labelList adaptPatchIDs(getSurfacePatches());
// Create baffles (pairs of faces that share the same points)
// Baffles stored as owner and neighbour face that have been created.
List<labelPair> baffles;
createZoneBaffles(baffles);
if (doSnap)
{ {
Info<< nl autoPtr<indirectPrimitivePatch> ppPtr
<< "Morphing phase" << nl (
<< "--------------" << nl meshRefinement::makePatch
(
mesh_,
adaptPatchIDs
)
);
indirectPrimitivePatch& pp = ppPtr();
// Distance to attact to nearest feature on surface
const scalarField snapDist(calcSnapDistance(snapDict, pp));
// Construct iterative mesh mover.
Info<< "Constructing mesh displacer ..." << endl;
Info<< "Using mesh parameters " << motionDict << nl << endl;
pointMesh pMesh(mesh_);
motionSmoother meshMover
(
mesh_,
pp,
adaptPatchIDs,
meshRefinement::makeDisplacementField(pMesh, adaptPatchIDs),
motionDict
);
// Check initial mesh
Info<< "Checking initial mesh ..." << endl;
labelHashSet wrongFaces(mesh_.nFaces()/100);
motionSmoother::checkMesh(false, mesh_, motionDict, wrongFaces);
const label nInitErrors = returnReduce
(
wrongFaces.size(),
sumOp<label>()
);
Info<< "Detected " << nInitErrors << " illegal faces"
<< " (concave, zero area or negative cell pyramid volume)"
<< endl; << endl;
const_cast<Time&>(mesh_.time())++;
// Get the labels of added patches. Info<< "Checked initial mesh in = "
labelList adaptPatchIDs(getSurfacePatches()); << mesh_.time().cpuTimeIncrement() << " s\n" << nl << endl;
// Create baffles (pairs of faces that share the same points) // Pre-smooth patch vertices (so before determining nearest)
// Baffles stored as owner and neighbour face that have been created. preSmoothPatch(snapDict, nInitErrors, baffles, meshMover);
List<labelPair> baffles;
createZoneBaffles(baffles); // Calculate displacement at every patch point. Insert into
// meshMover.
calcNearestSurface(snapDist, meshMover);
// Get smoothly varying internal displacement field.
smoothDisplacement(snapDict, meshMover);
// Apply internal displacement to mesh.
scaleMesh(snapDict, nInitErrors, baffles, meshMover);
}
// Merge any introduced baffles.
mergeZoneBaffles(baffles);
// Write mesh.
writeMesh("Snapped mesh");
}
void Foam::autoHexMeshDriver::doLayers
(
const dictionary& shrinkDict,
const dictionary& motionDict
)
{
Info<< nl
<< "Shrinking and layer addition phase" << nl
<< "----------------------------------" << nl
<< endl;
const_cast<Time&>(mesh_.time())++;
Info<< "Using mesh parameters " << motionDict << nl << endl;
// Merge coplanar boundary faces
mergePatchFacesUndo(shrinkDict, motionDict);
// Per global region the number of layers (0 if no layer)
const labelList& numLayers = surfaces().numLayers();
// Patches that need to get a layer
DynamicList<label> patchIDs(numLayers.size());
label nFacesWithLayers = 0;
forAll(numLayers, region)
{
if (numLayers[region] > 0 && globalToPatch()[region] != -1)
{
label patchI = globalToPatch()[region];
patchIDs.append(patchI);
nFacesWithLayers += mesh_.boundaryMesh()[patchI].size();
}
}
patchIDs.shrink();
if (returnReduce(nFacesWithLayers, sumOp<label>()) == 0)
{
Info<< nl << "No layers to generate ..." << endl;
}
else
{
autoPtr<indirectPrimitivePatch> ppPtr
(
meshRefinement::makePatch
(
mesh_,
patchIDs
)
);
indirectPrimitivePatch& pp = ppPtr();
// Construct iterative mesh mover.
Info<< "Constructing mesh displacer ..." << endl;
{ {
autoPtr<indirectPrimitivePatch> ppPtr
(
meshRefinement::makePatch
(
mesh_,
adaptPatchIDs
)
);
indirectPrimitivePatch& pp = ppPtr();
// Distance to attact to nearest feature on surface
const scalarField snapDist(calcSnapDistance(pp));
// Construct iterative mesh mover.
Info<< "Constructing mesh displacer ..." << endl;
const dictionary& motionDict = dict_.subDict("motionDict");
Info<< "Using mesh parameters " << motionDict << nl << endl;
pointMesh pMesh(mesh_); pointMesh pMesh(mesh_);
motionSmoother meshMover motionSmoother meshMover
( (
mesh_, mesh_,
pp, pp,
adaptPatchIDs, patchIDs,
meshRefinement::makeDisplacementField(pMesh, adaptPatchIDs), meshRefinement::makeDisplacementField(pMesh, patchIDs),
motionDict motionDict
); );
// Check that outside of mesh is not multiply connected.
checkMeshManifold();
// Check initial mesh // Check initial mesh
Info<< "Checking initial mesh ..." << endl; Info<< "Checking initial mesh ..." << endl;
@ -1490,119 +1884,46 @@ void Foam::autoHexMeshDriver::doMesh()
<< " (concave, zero area or negative cell pyramid volume)" << " (concave, zero area or negative cell pyramid volume)"
<< endl; << endl;
// Do all topo changes
Info<< "Checked initial mesh in = " addLayers(shrinkDict, motionDict, nInitErrors, meshMover);
<< mesh_.time().cpuTimeIncrement() << " s\n" << nl << endl;
// Pre-smooth patch vertices (so before determining nearest)
preSmoothPatch(nInitErrors, baffles, meshMover);
// Calculate displacement at every patch point. Insert into
// meshMover.
calcNearestSurface(snapDist, meshMover);
// Get smoothly varying internal displacement field.
smoothDisplacement(meshMover);
// Apply internal displacement to mesh.
scaleMesh(nInitErrors, baffles, meshMover);
} }
// Merge any introduced baffles.
mergeZoneBaffles(baffles);
// Write mesh. // Write mesh.
writeMesh("Snapped mesh"); writeMesh("Layer mesh");
}
}
void Foam::autoHexMeshDriver::doMesh()
{
Switch wantRefine(dict_.lookup("doRefine"));
Switch wantSnap(dict_.lookup("doSnap"));
Switch wantLayers(dict_.lookup("doLayers"));
Info<< "Do refinement : " << wantRefine << nl
<< "Do snapping : " << wantSnap << nl
<< "Do layers : " << wantLayers << nl
<< endl;
if (wantRefine)
{
doRefine(dict_, wantSnap);
} }
if (wantSnap)
if (doLayers)
{ {
Info<< nl const dictionary& snapDict = dict_.subDict("snapDict");
<< "Shrinking and layer addition phase" << nl const dictionary& motionDict = dict_.subDict("motionDict");
<< "----------------------------------" << nl
<< endl;
const_cast<Time&>(mesh_.time())++; doSnap(snapDict, motionDict);
}
// Merge coplanar boundary faces if (wantLayers)
mergePatchFacesUndo(); {
const dictionary& motionDict = dict_.subDict("motionDict");
const dictionary& shrinkDict = dict_.subDict("shrinkDict");
// Per global region the number of layers (0 if no layer) doLayers(shrinkDict, motionDict);
labelList nLayers(readNumLayers());
// Patches that need to get a layer
DynamicList<label> patchIDs(nLayers.size());
label nFacesWithLayers = 0;
forAll(nLayers, region)
{
if (nLayers[region] > 0 && globalToPatch()[region] != -1)
{
label patchI = globalToPatch()[region];
patchIDs.append(patchI);
nFacesWithLayers += mesh_.boundaryMesh()[patchI].size();
}
}
patchIDs.shrink();
if (returnReduce(nFacesWithLayers, sumOp<label>()) == 0)
{
Info<< nl << "No layers to generate ..." << endl;
}
else
{
autoPtr<indirectPrimitivePatch> ppPtr
(
meshRefinement::makePatch
(
mesh_,
patchIDs
)
);
indirectPrimitivePatch& pp = ppPtr();
// Construct iterative mesh mover.
Info<< "Constructing mesh displacer ..." << endl;
const dictionary& motionDict = dict_.subDict("motionDict");
Info<< "Using mesh parameters " << motionDict << nl << endl;
{
pointMesh pMesh(mesh_);
motionSmoother meshMover
(
mesh_,
pp,
patchIDs,
meshRefinement::makeDisplacementField(pMesh, patchIDs),
motionDict
);
// Check that outside of mesh is not multiply connected.
checkMeshManifold();
// Check initial mesh
Info<< "Checking initial mesh ..." << endl;
labelHashSet wrongFaces(mesh_.nFaces()/100);
motionSmoother::checkMesh(false, mesh_, motionDict, wrongFaces);
const label nInitErrors = returnReduce
(
wrongFaces.size(),
sumOp<label>()
);
Info<< "Detected " << nInitErrors << " illegal faces"
<< " (concave, zero area or negative cell pyramid volume)"
<< endl;
// Do all topo changes
addLayers(nInitErrors, meshMover);
}
// Write mesh.
writeMesh("Layer mesh");
}
} }
} }

View File

@ -135,7 +135,7 @@ class autoHexMeshDriver
//- Reference to mesh //- Reference to mesh
fvMesh& mesh_; fvMesh& mesh_;
//- Input dictionarys //- Input dictionary
const dictionary dict_; const dictionary dict_;
//- Debug level //- Debug level
@ -164,7 +164,6 @@ class autoHexMeshDriver
//- Explicit features //- Explicit features
PtrList<featureEdgeMesh> featureMeshes_; PtrList<featureEdgeMesh> featureMeshes_;
//- Per feature the refinement level //- Per feature the refinement level
@ -183,10 +182,6 @@ class autoHexMeshDriver
//- Per refinement surface region the patch //- Per refinement surface region the patch
labelList globalToPatch_; labelList globalToPatch_;
////- Per refinement surface with a valid faceZone the cyclicpatch
//// (or -1)
//labelList surfaceToCyclicPatch_;
//- Mesh refinement engine //- Mesh refinement engine
autoPtr<meshRefinement> meshRefinerPtr_; autoPtr<meshRefinement> meshRefinerPtr_;
@ -197,12 +192,13 @@ class autoHexMeshDriver
autoPtr<fvMeshDistribute> distributorPtr_; autoPtr<fvMeshDistribute> distributorPtr_;
// Private Member Functions // Private Member Functions
// Refinement // Refinement
//- Get merge tolerance. Check against writing tolerance. //- Calculate merge distance. Check against writing tolerance.
scalar getMergeDistance() const; scalar getMergeDistance(const scalar mergeTol) const;
// Return per keeppoint -1 or the local cell label the point is in. // Return per keeppoint -1 or the local cell label the point is in.
// Guaranteed to be only on one processor. // Guaranteed to be only on one processor.
@ -211,7 +207,7 @@ class autoHexMeshDriver
static void orientOutside(PtrList<searchableSurface>&); static void orientOutside(PtrList<searchableSurface>&);
//- Read feature edges //- Read feature edges
label readFeatureEdges(); label readFeatureEdges(const PtrList<dictionary>&);
// Snapping // Snapping
@ -375,7 +371,6 @@ class autoHexMeshDriver
// layers per surface. // layers per surface.
void setNumLayers void setNumLayers
( (
const labelList& nLayers,
const labelList& patchIDs, const labelList& patchIDs,
const indirectPrimitivePatch& pp, const indirectPrimitivePatch& pp,
pointField& patchDisp, pointField& patchDisp,
@ -651,6 +646,16 @@ public:
const dictionary& decomposeDict const dictionary& decomposeDict
); );
//- Alternative constructor from top-level controldictionary and
// refinement specific dictionary
autoHexMeshDriver
(
fvMesh& mesh,
const dictionary& controlDict,
const dictionary& refineDict,
const dictionary& decomposeDict
);
// Member Functions // Member Functions
@ -684,6 +689,7 @@ public:
//- Refine around explicit feature edges //- Refine around explicit feature edges
label featureEdgeRefine label featureEdgeRefine
( (
const PtrList<dictionary>& featDicts,
const label maxIter, const label maxIter,
const label minRefine const label minRefine
); );
@ -734,7 +740,11 @@ public:
autoPtr<mapPolyMesh> mergeZoneBaffles(const List<labelPair>&); autoPtr<mapPolyMesh> mergeZoneBaffles(const List<labelPair>&);
//- Calculate edge length per patch point. //- Calculate edge length per patch point.
scalarField calcSnapDistance(const indirectPrimitivePatch&) const; scalarField calcSnapDistance
(
const dictionary& snapDict,
const indirectPrimitivePatch&
) const;
//- Get patches generated for surfaces. //- Get patches generated for surfaces.
labelList getSurfacePatches() const; labelList getSurfacePatches() const;
@ -743,6 +753,7 @@ public:
// of surface points (on castellated mesh) w.r.t. surface. // of surface points (on castellated mesh) w.r.t. surface.
void preSmoothPatch void preSmoothPatch
( (
const dictionary& snapDict,
const label nInitErrors, const label nInitErrors,
const List<labelPair>& baffles, const List<labelPair>& baffles,
motionSmoother& motionSmoother&
@ -758,12 +769,17 @@ public:
) const; ) const;
//- Smooth the displacement field to the internal. //- Smooth the displacement field to the internal.
void smoothDisplacement(motionSmoother&) const; void smoothDisplacement
(
const dictionary& snapDict,
motionSmoother&
) const;
//- Do the hard work: move the mesh according to displacement, //- Do the hard work: move the mesh according to displacement,
// locally relax the displacement. // locally relax the displacement.
void scaleMesh void scaleMesh
( (
const dictionary& snapDict,
const label nInitErrors, const label nInitErrors,
const List<labelPair>& baffles, const List<labelPair>& baffles,
motionSmoother& motionSmoother&
@ -773,23 +789,50 @@ public:
// Layers // Layers
//- Merge patch faces on same cell. //- Merge patch faces on same cell.
void mergePatchFacesUndo(); void mergePatchFacesUndo
(
//- Read layer per region const dictionary& shrinkDict,
labelList readNumLayers() const; const dictionary& motionDict
);
//- Check that mesh outside is not multiply connected. //- Check that mesh outside is not multiply connected.
void checkMeshManifold() const; void checkMeshManifold() const;
//- Add cell layers //- Add cell layers
void addLayers(const scalar nAllowableErrors, motionSmoother&); void addLayers
(
const dictionary& shrinkDict,
const dictionary& motionDict,
const scalar nAllowableErrors,
motionSmoother&
);
// Other // Other
//- Do all refinement.
void doRefine
(
const dictionary& refineDict,
const bool prepareForSnapping
);
//- Do all snapping.
void doSnap
(
const dictionary& snapDict,
const dictionary& motionDict
);
//- Do alllayer addition.
void doLayers
(
const dictionary& shrinkDict,
const dictionary& motionDict
);
//- Do all : refine, snap, layers //- Do all : refine, snap, layers
void doMesh(); void doMesh();
}; };

View File

@ -61,6 +61,30 @@ Foam::label Foam::autoHexMeshDriver::mergePatchFacesUndo
// Patch face merging engine // Patch face merging engine
combineFaces faceCombiner(mesh_, true); combineFaces faceCombiner(mesh_, true);
// Pick up all candidate cells on boundary
labelHashSet boundaryCells(mesh_.nFaces()-mesh_.nInternalFaces());
{
labelList patchIDs(meshRefinement::addedPatches(globalToPatch_));
const polyBoundaryMesh& patches = mesh_.boundaryMesh();
forAll(patchIDs, i)
{
label patchI = patchIDs[i];
const polyPatch& patch = patches[patchI];
if (!patch.coupled())
{
forAll(patch, i)
{
boundaryCells.insert(mesh_.faceOwner()[patch.start()+i]);
}
}
}
}
// Get all sets of faces that can be merged // Get all sets of faces that can be merged
labelListList allFaceSets labelListList allFaceSets
( (
@ -68,7 +92,7 @@ Foam::label Foam::autoHexMeshDriver::mergePatchFacesUndo
( (
minCos, minCos,
concaveCos, concaveCos,
meshRefinement::addedPatches(globalToPatch_) boundaryCells
) )
); );
@ -1164,91 +1188,9 @@ void Foam::autoHexMeshDriver::handleWarpedFaces
//} //}
Foam::labelList Foam::autoHexMeshDriver::readNumLayers() const
{
// Read dictionary information
// (could already be extracted in refinementSurfaces?)
const PtrList<dictionary>& surfaceDicts = dict_.lookup("surfaces");
labelList globalSurfLayers(surfaceDicts.size());
List<HashTable<label> > regionSurfLayers(surfaceDicts.size());
forAll(surfaceDicts, surfI)
{
const dictionary& dict = surfaceDicts[surfI];
globalSurfLayers[surfI] = readLabel(dict.lookup("surfaceLayers"));
if (dict.found("regions"))
{
// Per-region layer information
PtrList<dictionary> regionDicts(dict.lookup("regions"));
forAll(regionDicts, dictI)
{
const dictionary& regionDict = regionDicts[dictI];
const word regionName(regionDict.lookup("name"));
label nLayers = readLabel(regionDict.lookup("surfaceLayers"));
Info<< " region " << regionName << ':'<< nl
<< " surface layers:" << nLayers << nl;
regionSurfLayers[surfI].insert(regionName, nLayers);
}
}
}
// Transfer per surface/region information into global region info
labelList nLayers(surfaces().minLevel().size(), 0);
forAll(surfaces(), surfI)
{
const geometricSurfacePatchList& regions = surfaces()[surfI].patches();
forAll(regions, regionI)
{
label global = surfaces().globalRegion(surfI, regionI);
// Initialise to surface-wise layers
nLayers[global] = globalSurfLayers[surfI];
// Override with region specific data if available
HashTable<label>::const_iterator iter =
regionSurfLayers[surfI].find(regions[regionI].name());
if (iter != regionSurfLayers[surfI].end())
{
nLayers[global] = iter();
}
// Check
if (nLayers[global] < 0)
{
FatalErrorIn
(
"autoHexMeshDriver::readNumLayers()"
) << "Illegal number of layers " << nLayers[global]
<< " for surface "
<< surfaces().names()[surfI]
<< " region " << regions[regionI].name() << endl
<< exit(FatalError);
}
}
}
return nLayers;
}
// No extrusion on faces with differing number of layers for points // No extrusion on faces with differing number of layers for points
void Foam::autoHexMeshDriver::setNumLayers void Foam::autoHexMeshDriver::setNumLayers
( (
const labelList& nLayers,
const labelList& patchIDs, const labelList& patchIDs,
const indirectPrimitivePatch& pp, const indirectPrimitivePatch& pp,
pointField& patchDisp, pointField& patchDisp,
@ -1259,13 +1201,15 @@ void Foam::autoHexMeshDriver::setNumLayers
Info<< nl << "Handling points with inconsistent layer specification ..." Info<< nl << "Handling points with inconsistent layer specification ..."
<< endl; << endl;
const labelList& nSurfLayers = surfaces().numLayers();
// Build map from patch to layers // Build map from patch to layers
Map<label> patchToNLayers(nLayers.size()); Map<label> patchToNLayers(nSurfLayers.size());
forAll(nLayers, region) forAll(nSurfLayers, region)
{ {
if (globalToPatch_[region] != -1) if (globalToPatch_[region] != -1)
{ {
patchToNLayers.insert(globalToPatch_[region], nLayers[region]); patchToNLayers.insert(globalToPatch_[region], nSurfLayers[region]);
} }
} }
@ -2363,10 +2307,12 @@ void Foam::autoHexMeshDriver::getLayerCellsFaces
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::autoHexMeshDriver::mergePatchFacesUndo() void Foam::autoHexMeshDriver::mergePatchFacesUndo
(
const dictionary& shrinkDict,
const dictionary& motionDict
)
{ {
const dictionary& shrinkDict = dict_.subDict("shrinkDict");
const scalar featureAngle(readScalar(shrinkDict.lookup("featureAngle"))); const scalar featureAngle(readScalar(shrinkDict.lookup("featureAngle")));
scalar minCos = Foam::cos(featureAngle*mathematicalConstant::pi/180.0); scalar minCos = Foam::cos(featureAngle*mathematicalConstant::pi/180.0);
@ -2390,9 +2336,6 @@ void Foam::autoHexMeshDriver::mergePatchFacesUndo()
<< concaveAngle << " degrees (0=straight, 180=fully concave)" << nl << concaveAngle << " degrees (0=straight, 180=fully concave)" << nl
<< endl; << endl;
const dictionary& motionDict = dict_.subDict("motionDict");
label nChanged = mergePatchFacesUndo(minCos, concaveCos, motionDict); label nChanged = mergePatchFacesUndo(minCos, concaveCos, motionDict);
nChanged += mergeEdgesUndo(minCos, motionDict); nChanged += mergeEdgesUndo(minCos, motionDict);
@ -2401,6 +2344,8 @@ void Foam::autoHexMeshDriver::mergePatchFacesUndo()
void Foam::autoHexMeshDriver::addLayers void Foam::autoHexMeshDriver::addLayers
( (
const dictionary& shrinkDict,
const dictionary& motionDict,
const scalar nAllowableErrors, const scalar nAllowableErrors,
motionSmoother& meshMover motionSmoother& meshMover
) )
@ -2408,8 +2353,6 @@ void Foam::autoHexMeshDriver::addLayers
// Read some more dictionary settings // Read some more dictionary settings
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
const dictionary& shrinkDict = dict_.subDict("shrinkDict");
// Min thickness per cell // Min thickness per cell
const scalar relMinThickness(readScalar(shrinkDict.lookup("minThickness"))); const scalar relMinThickness(readScalar(shrinkDict.lookup("minThickness")));
@ -2506,7 +2449,6 @@ void Foam::autoHexMeshDriver::addLayers
setNumLayers setNumLayers
( (
readNumLayers(),
meshMover.adaptPatchIDs(), meshMover.adaptPatchIDs(),
pp, pp,
@ -2923,7 +2865,7 @@ void Foam::autoHexMeshDriver::addLayers
label nTotChanged = checkAndUnmark label nTotChanged = checkAndUnmark
( (
addLayer, addLayer,
dict_.subDict("motionDict"), motionDict,
pp, pp,
newMesh, newMesh,

View File

@ -755,10 +755,10 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::autoHexMeshDriver::mergeZoneBaffles
Foam::scalarField Foam::autoHexMeshDriver::calcSnapDistance Foam::scalarField Foam::autoHexMeshDriver::calcSnapDistance
( (
const dictionary& snapDict,
const indirectPrimitivePatch& pp const indirectPrimitivePatch& pp
) const ) const
{ {
const dictionary& snapDict = dict_.subDict("snapDict");
// When to snap // When to snap
scalar snapTol(readScalar(snapDict.lookup("snapTol"))); scalar snapTol(readScalar(snapDict.lookup("snapTol")));
@ -826,12 +826,12 @@ Foam::labelList Foam::autoHexMeshDriver::getSurfacePatches() const
void Foam::autoHexMeshDriver::preSmoothPatch void Foam::autoHexMeshDriver::preSmoothPatch
( (
const dictionary& snapDict,
const label nInitErrors, const label nInitErrors,
const List<labelPair>& baffles, const List<labelPair>& baffles,
motionSmoother& meshMover motionSmoother& meshMover
) const ) const
{ {
const dictionary& snapDict = dict_.subDict("snapDict");
// Smoothing iterations // Smoothing iterations
label nSmoothPatch(readLabel(snapDict.lookup("nSmoothPatch"))); label nSmoothPatch(readLabel(snapDict.lookup("nSmoothPatch")));
// Snapping iterations // Snapping iterations
@ -1076,15 +1076,17 @@ Foam::vectorField Foam::autoHexMeshDriver::calcNearestSurface
} }
void Foam::autoHexMeshDriver::smoothDisplacement(motionSmoother& meshMover) void Foam::autoHexMeshDriver::smoothDisplacement
const (
const dictionary& snapDict,
motionSmoother& meshMover
) const
{ {
const pointMesh& pMesh = meshMover.pMesh(); const pointMesh& pMesh = meshMover.pMesh();
const indirectPrimitivePatch& pp = meshMover.patch(); const indirectPrimitivePatch& pp = meshMover.patch();
Info<< "Smoothing displacement ..." << endl; Info<< "Smoothing displacement ..." << endl;
const dictionary& snapDict = dict_.subDict("snapDict");
// Smoothing iterations // Smoothing iterations
label nSmoothDisp(readLabel(snapDict.lookup("nSmoothDispl"))); label nSmoothDisp(readLabel(snapDict.lookup("nSmoothDispl")));
@ -1138,12 +1140,12 @@ void Foam::autoHexMeshDriver::smoothDisplacement(motionSmoother& meshMover)
void Foam::autoHexMeshDriver::scaleMesh void Foam::autoHexMeshDriver::scaleMesh
( (
const dictionary& snapDict,
const label nInitErrors, const label nInitErrors,
const List<labelPair>& baffles, const List<labelPair>& baffles,
motionSmoother& meshMover motionSmoother& meshMover
) )
{ {
const dictionary& snapDict = dict_.subDict("snapDict");
// Snapping iterations // Snapping iterations
label nSnap(readLabel(snapDict.lookup("nSnap"))); label nSnap(readLabel(snapDict.lookup("nSnap")));

View File

@ -57,7 +57,7 @@ Foam::label Foam::meshRefinement::mergePatchFaces
const polyBoundaryMesh& patches = mesh_.boundaryMesh(); const polyBoundaryMesh& patches = mesh_.boundaryMesh();
// Pick up all cells on boundary // Pick up all candidate cells on boundary
labelHashSet boundaryCells(mesh_.nFaces()-mesh_.nInternalFaces()); labelHashSet boundaryCells(mesh_.nFaces()-mesh_.nInternalFaces());
forAll(patchIDs, i) forAll(patchIDs, i)

View File

@ -73,38 +73,41 @@ Foam::refinementSurfaces::refinementSurfaces
List<HashTable<label> > regionMinLevel(surfaceDicts.size()); List<HashTable<label> > regionMinLevel(surfaceDicts.size());
List<HashTable<label> > regionMaxLevel(surfaceDicts.size()); List<HashTable<label> > regionMaxLevel(surfaceDicts.size());
forAll(surfaceDicts, i) labelList globalSurfLayers(surfaceDicts.size());
List<HashTable<label> > regionSurfLayers(surfaceDicts.size());
wordList globalPatchType(surfaceDicts.size());
List<HashTable<word> > regionPatchType(surfaceDicts.size());
List<HashTable<word> > regionPatchName(surfaceDicts.size());
forAll(surfaceDicts, surfI)
{ {
const dictionary& dict = surfaceDicts[i]; const dictionary& dict = surfaceDicts[surfI];
names_[i] = word(dict.lookup("name")); names_[surfI] = word(dict.lookup("name"));
globalMinLevel[i] = readLabel(dict.lookup("minRefinementLevel")); // Global refinement level
globalMaxLevel[i] = readLabel(dict.lookup("maxRefinementLevel")); globalMinLevel[surfI] = readLabel(dict.lookup("minRefinementLevel"));
globalMaxLevel[surfI] = readLabel(dict.lookup("maxRefinementLevel"));
if // Global number of layers
( globalSurfLayers[surfI] = readLabel(dict.lookup("surfaceLayers"));
globalMinLevel[i] < 0
|| globalMaxLevel[i] < globalMinLevel[i]
)
{
FatalErrorIn
(
"refinementSurfaces::refinementSurfaces"
"(const IOobject&, const PtrList<dictionary>&)"
) << "Illegal level specification for surface " << names_[i]
<< " : minLevel:" << globalMinLevel[i]
<< " maxLevel:" << globalMaxLevel[i]
<< exit(FatalError);
}
// Global zone names per surface
if (dict.found("faceZone")) if (dict.found("faceZone"))
{ {
dict.lookup("faceZone") >> faceZoneNames_[i]; dict.lookup("faceZone") >> faceZoneNames_[surfI];
dict.lookup("cellZone") >> cellZoneNames_[i]; dict.lookup("cellZone") >> cellZoneNames_[surfI];
dict.lookup("zoneInside") >> zoneInside_[i]; dict.lookup("zoneInside") >> zoneInside_[surfI];
} }
// Global patch name per surface
if (dict.found("patchType"))
{
dict.lookup("patchType") >> globalPatchType[surfI];
}
if (dict.found("regions")) if (dict.found("regions"))
{ {
PtrList<dictionary> regionDicts(dict.lookup("regions")); PtrList<dictionary> regionDicts(dict.lookup("regions"));
@ -117,12 +120,72 @@ Foam::refinementSurfaces::refinementSurfaces
label min = readLabel(regionDict.lookup("minRefinementLevel")); label min = readLabel(regionDict.lookup("minRefinementLevel"));
label max = readLabel(regionDict.lookup("maxRefinementLevel")); label max = readLabel(regionDict.lookup("maxRefinementLevel"));
regionMinLevel[i].insert(regionName, min); regionMinLevel[surfI].insert(regionName, min);
regionMaxLevel[i].insert(regionName, max); regionMaxLevel[surfI].insert(regionName, max);
label nLayers = readLabel(regionDict.lookup("surfaceLayers"));
regionSurfLayers[surfI].insert(regionName, nLayers);
if (regionDict.found("patchType"))
{
regionPatchType[surfI].insert
(
regionName,
regionDict.lookup("patchType")
);
regionPatchName[surfI].insert
(
regionName,
regionDict.lookup("patchName")
);
}
} }
} }
} }
// Check for duplicate surface or region names
{
HashTable<label> surfaceNames(names_.size());
forAll(names_, surfI)
{
if (!surfaceNames.insert(names_[surfI], surfI))
{
FatalErrorIn
(
"refinementSurfaces::refinementSurfaces"
"(const IOobject&, const PtrList<dictionary>&)"
) << "Duplicate surface name " << names_[surfI] << endl
<< "Previous occurrence of name at surface "
<< surfaceNames[names_[surfI]]
<< exit(FatalError);
}
// Check for duplicate region names
const geometricSurfacePatchList& patches =
operator[](surfI).patches();
HashTable<label> regionNames(patches.size());
forAll(patches, i)
{
if (!regionNames.insert(patches[i].name(), i))
{
FatalErrorIn
(
"refinementSurfaces::refinementSurfaces"
"(const IOobject&, const PtrList<dictionary>&)"
) << "Duplicate region name " << patches[i].name()
<< " on surface " << names_[surfI] << endl
<< "Previous occurrence of region at index "
<< regionNames[patches[i].name()]
<< exit(FatalError);
}
}
}
}
// Calculate closedness // Calculate closedness
forAll(closed_, surfI) forAll(closed_, surfI)
{ {
@ -151,37 +214,89 @@ Foam::refinementSurfaces::refinementSurfaces
nRegions += operator[](surfI).patches().size(); nRegions += operator[](surfI).patches().size();
} }
// From global region number to refinement level // Rework surface specific information into information per global region
minLevel_.setSize(nRegions); minLevel_.setSize(nRegions);
minLevel_ = 0; minLevel_ = 0;
maxLevel_.setSize(nRegions); maxLevel_.setSize(nRegions);
maxLevel_ = 0; maxLevel_ = 0;
numLayers_.setSize(nRegions);
numLayers_ = 0;
patchName_.setSize(nRegions);
patchType_.setSize(nRegions);
forAll(surfaceDicts, surfI) forAll(surfaceDicts, surfI)
{ {
const geometricSurfacePatchList& regions = operator[](surfI).patches(); const geometricSurfacePatchList& regions = operator[](surfI).patches();
// Initialise to global (i.e. per surface)
forAll(regions, i) forAll(regions, i)
{ {
minLevel_[regionOffset_[surfI] + i] = globalMinLevel[surfI]; minLevel_[regionOffset_[surfI] + i] = globalMinLevel[surfI];
maxLevel_[regionOffset_[surfI] + i] = globalMaxLevel[surfI]; maxLevel_[regionOffset_[surfI] + i] = globalMaxLevel[surfI];
numLayers_[regionOffset_[surfI] + i] = globalSurfLayers[surfI];
patchType_[regionOffset_[surfI] + i] = globalPatchType[surfI];
} }
// Get the region names
wordList regionNames(regions.size());
forAll(regions, regionI)
{
regionNames[regionI] = regions[regionI].name();
}
// Overwrite with region specific information
forAllConstIter(HashTable<label>, regionMinLevel[surfI], iter) forAllConstIter(HashTable<label>, regionMinLevel[surfI], iter)
{ {
// Find the patch // Find the local region number.
forAll(regions, regionI) label regionI = findIndex(regionNames, iter.key());
{
if (regions[regionI].name() == iter.key())
{
label globalRegionI = regionOffset_[surfI] + regionI;
minLevel_[globalRegionI] = iter(); if (regionI == -1)
maxLevel_[globalRegionI] = {
regionMaxLevel[surfI][iter.key()]; FatalErrorIn
break; (
} "refinementSurfaces::refinementSurfaces"
"(const IOobject&, const PtrList<dictionary>&)"
) << "Cannot find region " << iter.key()
<< " in surface " << names_[surfI]
<< " which has regions " << regionNames
<< abort(FatalError);
} }
label globalRegionI = regionOffset_[surfI] + regionI;
minLevel_[globalRegionI] = iter();
maxLevel_[globalRegionI] = regionMaxLevel[surfI][iter.key()];
numLayers_[globalRegionI] = regionSurfLayers[surfI][iter.key()];
// Check validity
if
(
minLevel_[globalRegionI] < 0
|| maxLevel_[globalRegionI] < minLevel_[globalRegionI]
|| numLayers_[globalRegionI] < 0
)
{
FatalErrorIn
(
"refinementSurfaces::refinementSurfaces"
"(const IOobject&, const PtrList<dictionary>&)"
) << "Illegal level or layer specification for surface "
<< names_[surfI]
<< " : minLevel:" << minLevel_[globalRegionI]
<< " maxLevel:" << maxLevel_[globalRegionI]
<< " numLayers:" << numLayers_[globalRegionI]
<< exit(FatalError);
}
}
// Optional patch names and patch types
forAllConstIter(HashTable<word>, regionPatchName[surfI], iter)
{
label regionI = findIndex(regionNames, iter.key());
label globalRegionI = regionOffset_[surfI] + regionI;
patchName_[globalRegionI] = iter();
patchType_[globalRegionI] = regionPatchType[surfI][iter.key()];
} }
} }
} }

View File

@ -60,7 +60,7 @@ class refinementSurfaces
{ {
// Private data // Private data
//- Name (word) //- Surface name (word)
wordList names_; wordList names_;
//- Per surface whether is closed //- Per surface whether is closed
@ -86,6 +86,16 @@ class refinementSurfaces
//- From global region number to refinement level //- From global region number to refinement level
labelList maxLevel_; labelList maxLevel_;
//- From global region number to added layers
labelList numLayers_;
//- From global region number to patch name
wordList patchName_;
//- From global region number to patch name
wordList patchType_;
//- Per surface refinement level adapted for shells. //- Per surface refinement level adapted for shells.
PtrList<triSurfaceLabelField> minLevelFields_; PtrList<triSurfaceLabelField> minLevelFields_;
@ -169,6 +179,24 @@ public:
return maxLevel_; return maxLevel_;
} }
//- From global region number to added layers
const labelList& numLayers() const
{
return numLayers_;
}
//- From global region number to patch name. Patchnames can be empty
const wordList& patchName() const
{
return patchName_;
}
//- From global region number to patch name
const wordList& patchType() const
{
return patchType_;
}
// Helper // Helper