mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
changed dictionary
This commit is contained in:
@ -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;
|
||||||
|
|||||||
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -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");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -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,
|
||||||
|
|
||||||
|
|||||||
@ -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")));
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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()];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user