Merge branch 'feature-snappyHexMesh-gapRefinement' into 'develop'

Feature snappy hex mesh gap refinement

Adding automatic gap refinement capability

See merge request !2
This commit is contained in:
Andrew Heather
2015-11-09 11:48:06 +00:00
39 changed files with 6037 additions and 147 deletions

View File

@ -1075,6 +1075,26 @@ int main(int argc, char *argv[])
<< mesh.time().cpuTimeIncrement() << " s" << nl << endl;
// Optionally read limit shells
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
const dictionary limitDict(refineDict.subOrEmptyDict("limitRegions"));
if (!limitDict.empty())
{
Info<< "Reading limit shells." << endl;
}
shellSurfaces limitShells(allGeometry, limitDict);
if (!limitDict.empty())
{
Info<< "Read refinement shells in = "
<< mesh.time().cpuTimeIncrement() << " s" << nl << endl;
}
// Read feature meshes
// ~~~~~~~~~~~~~~~~~~~
@ -1105,7 +1125,8 @@ int main(int argc, char *argv[])
overwrite, // overwrite mesh files?
surfaces, // for surface intersection refinement
features, // for feature edges/point based refinement
shells // for volume (inside/outside) refinement
shells, // for volume (inside/outside) refinement
limitShells // limit of volume refinement
);
Info<< "Calculated surface intersections in = "
<< mesh.time().cpuTimeIncrement() << " s" << nl << endl;

View File

@ -95,10 +95,10 @@ castellatedMeshControls
// actually be a lot less.
maxGlobalCells 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)
// The surface refinement loop might spend lots of iterations refining just
// a few cells. This setting will cause refinement to stop if
// <= minimumRefine cells are selected for refinement. Note: it will
// at least do one iteration (unless the number of cells to refine is 0)
minRefinementCells 0;
// Allow a certain level of imbalance during refining
@ -244,11 +244,27 @@ castellatedMeshControls
}
//sphere.stl
//{
// mode distance;
// levels ((1.0 5) (2.0 3));
// mode inside;
// levels ((1.0 4));
// // Optional override of uniform refinement level such
// // that in small gaps we're getting more cells.
// // The specification is
// // - numGapCells : minimum number of cells in the gap
// // - minLevel : min refinement level at which to kick in
// // - maxLevel : upper refinement level
// // All three settings can be overridden on a surface by
// // surface basis in the refinementSurfaces section.
// gapLevel (<numGapCells> <minLevel> <maxlevel>);
//}
}
// Limit refinement in geometric region
limitRegions
{
}
// Mesh selection
// ~~~~~~~~~~~~~~

View File

@ -59,6 +59,8 @@ parallel/Allwmake $targetType $*
wmake $targetType ODE
wmake $targetType randomProcesses
wmake $targetType fvMotionSolver
transportModels/Allwmake $targetType $*
thermophysicalModels/Allwmake $targetType $*
TurbulenceModels/Allwmake $targetType $*
@ -69,7 +71,6 @@ mesh/Allwmake $targetType $*
renumber/Allwmake $targetType $*
fvAgglomerationMethods/Allwmake $targetType $*
wmake $targetType fvMotionSolver
wmake $targetType engine
wmake $targetType fvOptions
wmake $targetType regionCoupled

View File

@ -2,8 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation |
\\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -95,6 +95,12 @@ public:
t_(t)
{}
//- Construct from integer
explicit volumeType(const int t)
:
t_(static_cast<volumeType::type>(t))
{}
// Member Functions

View File

@ -15,6 +15,7 @@ $(autoHexMesh)/meshRefinement/meshRefinement.C
$(autoHexMesh)/meshRefinement/meshRefinementMerge.C
$(autoHexMesh)/meshRefinement/meshRefinementProblemCells.C
$(autoHexMesh)/meshRefinement/meshRefinementRefine.C
$(autoHexMesh)/meshRefinement/meshRefinementGapRefine.C
$(autoHexMesh)/meshRefinement/patchFaceOrientation.C
$(autoHexMesh)/refinementFeatures/refinementFeatures.C

View File

@ -105,7 +105,10 @@ Foam::label Foam::autoRefineDriver::featureEdgeRefine
false, // internalRefinement
false, // surfaceRefinement
false, // curvatureRefinement
false, // smallFeatureRefinement
false, // gapRefinement
false, // bigGapRefinement
false, // spreadGapSize
refineParams.maxGlobalCells(),
refineParams.maxLocalCells()
)
@ -179,6 +182,128 @@ Foam::label Foam::autoRefineDriver::featureEdgeRefine
}
Foam::label Foam::autoRefineDriver::smallFeatureRefine
(
const refinementParameters& refineParams,
const label maxIter
)
{
const fvMesh& mesh = meshRefiner_.mesh();
label iter = 0;
// See if any surface has an extendedGapLevel
labelList surfaceMaxLevel(meshRefiner_.surfaces().maxGapLevel());
labelList shellMaxLevel(meshRefiner_.shells().maxGapLevel());
if (max(surfaceMaxLevel) == 0 && max(shellMaxLevel) == 0)
{
return iter;
}
for (; iter < maxIter; iter++)
{
Info<< nl
<< "Small surface feature refinement iteration " << iter << nl
<< "--------------------------------------------" << nl
<< endl;
// Determine cells to refine
// ~~~~~~~~~~~~~~~~~~~~~~~~~
labelList candidateCells
(
meshRefiner_.refineCandidates
(
refineParams.locationsInMesh(),
refineParams.curvature(),
refineParams.planarAngle(),
false, // featureRefinement
false, // featureDistanceRefinement
false, // internalRefinement
false, // surfaceRefinement
false, // curvatureRefinement
true, // smallFeatureRefinement
false, // gapRefinement
false, // bigGapRefinement
false, // spreadGapSize
refineParams.maxGlobalCells(),
refineParams.maxLocalCells()
)
);
labelList cellsToRefine
(
meshRefiner_.meshCutter().consistentRefinement
(
candidateCells,
true
)
);
Info<< "Determined cells to refine in = "
<< mesh.time().cpuTimeIncrement() << " s" << endl;
label nCellsToRefine = cellsToRefine.size();
reduce(nCellsToRefine, sumOp<label>());
Info<< "Selected for refinement : " << nCellsToRefine
<< " cells (out of " << mesh.globalData().nTotalCells()
<< ')' << endl;
// Stop when no cells to refine or have done minimum necessary
// iterations and not enough cells to refine.
if (nCellsToRefine == 0)
{
Info<< "Stopping refining since too few cells selected."
<< nl << endl;
break;
}
if (debug)
{
const_cast<Time&>(mesh.time())++;
}
if
(
returnReduce
(
(mesh.nCells() >= refineParams.maxLocalCells()),
orOp<bool>()
)
)
{
meshRefiner_.balanceAndRefine
(
"small feature refinement iteration " + name(iter),
decomposer_,
distributor_,
cellsToRefine,
refineParams.maxLoadUnbalance()
);
}
else
{
meshRefiner_.refineAndBalance
(
"small feature refinement iteration " + name(iter),
decomposer_,
distributor_,
cellsToRefine,
refineParams.maxLoadUnbalance()
);
}
}
return iter;
}
Foam::label Foam::autoRefineDriver::surfaceOnlyRefine
(
const refinementParameters& refineParams,
@ -218,7 +343,10 @@ Foam::label Foam::autoRefineDriver::surfaceOnlyRefine
false, // internalRefinement
true, // surfaceRefinement
true, // curvatureRefinement
false, // smallFeatureRefinement
false, // gapRefinement
false, // bigGapRefinement
false, // spreadGapSize
refineParams.maxGlobalCells(),
refineParams.maxLocalCells()
)
@ -352,7 +480,10 @@ Foam::label Foam::autoRefineDriver::gapOnlyRefine
false, // internalRefinement
false, // surfaceRefinement
false, // curvatureRefinement
false, // smallFeatureRefinement
true, // gapRefinement
false, // bigGapRefinement
false, // spreadGapSize
refineParams.maxGlobalCells(),
refineParams.maxLocalCells()
)
@ -527,6 +658,148 @@ Foam::label Foam::autoRefineDriver::gapOnlyRefine
}
Foam::label Foam::autoRefineDriver::bigGapOnlyRefine
(
const refinementParameters& refineParams,
const bool spreadGapSize,
const label maxIter
)
{
const fvMesh& mesh = meshRefiner_.mesh();
label iter = 0;
// See if any surface has an extendedGapLevel
labelList surfaceMaxLevel(meshRefiner_.surfaces().maxGapLevel());
labelList shellMaxLevel(meshRefiner_.shells().maxGapLevel());
label overallMaxLevel(max(max(surfaceMaxLevel), max(shellMaxLevel)));
if (overallMaxLevel == 0)
{
return iter;
}
for (; iter < maxIter; iter++)
{
Info<< nl
<< "Big gap refinement iteration " << iter << nl
<< "------------------------------" << nl
<< endl;
// Determine cells to refine
// ~~~~~~~~~~~~~~~~~~~~~~~~~
labelList candidateCells
(
meshRefiner_.refineCandidates
(
refineParams.locationsInMesh(),
refineParams.curvature(),
refineParams.planarAngle(),
false, // featureRefinement
false, // featureDistanceRefinement
false, // internalRefinement
false, // surfaceRefinement
false, // curvatureRefinement
false, // smallFeatureRefinement
false, // gapRefinement
true, // bigGapRefinement
spreadGapSize, // spreadGapSize
refineParams.maxGlobalCells(),
refineParams.maxLocalCells()
)
);
if (debug&meshRefinement::MESH)
{
Pout<< "Dumping " << candidateCells.size()
<< " cells to cellSet candidateCellsFromBigGap." << endl;
cellSet c(mesh, "candidateCellsFromBigGap", candidateCells);
c.instance() = meshRefiner_.timeName();
c.write();
}
labelList cellsToRefine
(
meshRefiner_.meshCutter().consistentRefinement
(
candidateCells,
true
)
);
Info<< "Determined cells to refine in = "
<< mesh.time().cpuTimeIncrement() << " s" << endl;
label nCellsToRefine = cellsToRefine.size();
reduce(nCellsToRefine, sumOp<label>());
Info<< "Selected for refinement : " << nCellsToRefine
<< " cells (out of " << mesh.globalData().nTotalCells()
<< ')' << endl;
// Stop when no cells to refine or have done minimum necessary
// iterations and not enough cells to refine.
if
(
nCellsToRefine == 0
|| (
iter >= overallMaxLevel
&& nCellsToRefine <= refineParams.minRefineCells()
)
)
{
Info<< "Stopping refining since too few cells selected."
<< nl << endl;
break;
}
if (debug)
{
const_cast<Time&>(mesh.time())++;
}
if
(
returnReduce
(
(mesh.nCells() >= refineParams.maxLocalCells()),
orOp<bool>()
)
)
{
meshRefiner_.balanceAndRefine
(
"big gap refinement iteration " + name(iter),
decomposer_,
distributor_,
cellsToRefine,
refineParams.maxLoadUnbalance()
);
}
else
{
meshRefiner_.refineAndBalance
(
"big gap refinement iteration " + name(iter),
decomposer_,
distributor_,
cellsToRefine,
refineParams.maxLoadUnbalance()
);
}
}
return iter;
}
Foam::label Foam::autoRefineDriver::danglingCellRefine
(
const refinementParameters& refineParams,
@ -1108,7 +1381,10 @@ Foam::label Foam::autoRefineDriver::shellRefine
true, // internalRefinement
false, // surfaceRefinement
false, // curvatureRefinement
false, // smallFeatureRefinement
false, // gapRefinement
false, // bigGapRefinement
false, // spreadGapSize
refineParams.maxGlobalCells(),
refineParams.maxLocalCells()
)
@ -1630,6 +1906,13 @@ void Foam::autoRefineDriver::doRefine
0 // min cells to refine
);
// Refine cells that contain a gap
smallFeatureRefine
(
refineParams,
100 // maxIter
);
// Refine based on surface
surfaceOnlyRefine
(
@ -1650,6 +1933,14 @@ void Foam::autoRefineDriver::doRefine
1 // nBufferLayers
);
// Refine consistently across narrow gaps (a form of shell refinement)
bigGapOnlyRefine
(
refineParams,
true, // spreadGapSize
100 // maxIter
);
// Internal mesh refinement
shellRefine
(

View File

@ -84,6 +84,13 @@ class autoRefineDriver
const label minRefine
);
//- Refine all cells containing small surface features
label smallFeatureRefine
(
const refinementParameters& refineParams,
const label maxIter
);
//- Refine all cells interacting with the surface
label surfaceOnlyRefine
(
@ -98,6 +105,14 @@ class autoRefineDriver
const label maxIter
);
//- Refine all cells in large gaps
label bigGapOnlyRefine
(
const refinementParameters& refineParams,
const bool spreadGapSize,
const label maxIter
);
//- Refine cells with almost all sides refined
label danglingCellRefine
(

View File

@ -215,6 +215,55 @@ void Foam::meshRefinement::calcNeighbourData
}
void Foam::meshRefinement::calcCellCellRays
(
const pointField& neiCc,
const labelList& neiLevel,
const labelList& testFaces,
pointField& start,
pointField& end,
labelList& minLevel
) const
{
const labelList& cellLevel = meshCutter_.cellLevel();
const pointField& cellCentres = mesh_.cellCentres();
start.setSize(testFaces.size());
end.setSize(testFaces.size());
minLevel.setSize(testFaces.size());
forAll(testFaces, i)
{
label faceI = testFaces[i];
label own = mesh_.faceOwner()[faceI];
if (mesh_.isInternalFace(faceI))
{
label nei = mesh_.faceNeighbour()[faceI];
start[i] = cellCentres[own];
end[i] = cellCentres[nei];
minLevel[i] = min(cellLevel[own], cellLevel[nei]);
}
else
{
label bFaceI = faceI - mesh_.nInternalFaces();
start[i] = cellCentres[own];
end[i] = neiCc[bFaceI];
minLevel[i] = min(cellLevel[own], neiLevel[bFaceI]);
}
}
// Extend segments a bit
{
const vectorField smallVec(ROOTSMALL*(end-start));
start -= smallVec;
end += smallVec;
}
}
// Find intersections of edges (given by their two endpoints) with surfaces.
// Returns first intersection if there are more than one.
void Foam::meshRefinement::updateIntersections(const labelList& changedFaces)
@ -1187,7 +1236,8 @@ Foam::meshRefinement::meshRefinement
const bool overwrite,
const refinementSurfaces& surfaces,
const refinementFeatures& features,
const shellSurfaces& shells
const shellSurfaces& shells,
const shellSurfaces& limitShells
)
:
mesh_(mesh),
@ -1197,6 +1247,7 @@ Foam::meshRefinement::meshRefinement
surfaces_(surfaces),
features_(features),
shells_(shells),
limitShells_(limitShells),
meshCutter_
(
mesh,

View File

@ -34,6 +34,7 @@ Description
SourceFiles
meshRefinement.C
meshRefinementBaffles.C
meshRefinementGapRefine.C
meshRefinementMerge.C
meshRefinementProblemCells.C
meshRefinementRefine.C
@ -53,6 +54,8 @@ SourceFiles
#include "pointIndexHit.H"
#include "wordPairHashTable.H"
#include "surfaceZonesInfo.H"
#include "volumeType.H"
#include "DynamicField.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -176,6 +179,9 @@ private:
//- All shell-refinement interaction
const shellSurfaces& shells_;
//- All limit-refinement interaction
const shellSurfaces& limitShells_;
//- Refinement engine
hexRef8 meshCutter_;
@ -226,10 +232,18 @@ private:
);
//- Calculate coupled boundary end vector and refinement level
void calcNeighbourData
void calcNeighbourData(labelList& neiLevel, pointField& neiCc) const;
//- Calculate rays from cell-centre to cell-centre and corresponding
// min cell refinement level
void calcCellCellRays
(
labelList& neiLevel,
pointField& neiCc
const pointField& neiCc,
const labelList& neiLevel,
const labelList& testFaces,
pointField& start,
pointField& end,
labelList& minLevel
) const;
//- Remove cells. Put exposedFaces into exposedPatchIDs.
@ -241,12 +255,12 @@ private:
removeCells& cellRemover
);
// Get cells which are inside any closed surface. Note that
//- Get cells which are inside any closed surface. Note that
// all closed surfaces
// will have already been oriented to have keepPoint outside.
labelList getInsideCells(const word&) const;
// Do all to remove inside cells
//- Do all to remove inside cells
autoPtr<mapPolyMesh> removeInsideCells
(
const string& msg,
@ -302,6 +316,14 @@ private:
label& nRefine
) const;
//- Unmark cells for refinement based on limit-shells. Return number
// of limited cells.
label unmarkInternalRefinement
(
labelList& refineCell,
label& nRefine
) const;
//- Collect faces that are intersected and whose neighbours aren't
// yet marked for refinement.
labelList getRefineCandidateFaces
@ -319,6 +341,104 @@ private:
label& nRefine
) const;
//- Mark cells intersected by the surface if they are inside
// close gaps
label markSurfaceGapRefinement
(
const scalar planarCos,
const label nAllowRefine,
const labelList& neiLevel,
const pointField& neiCc,
labelList& refineCell,
label& nRefine
) const;
//- Generate single ray from nearPoint in direction of nearNormal
label generateRays
(
const point& nearPoint,
const vector& nearNormal,
const FixedList<label, 3>& gapInfo,
const volumeType& mode,
const label cLevel,
DynamicField<point>& start,
DynamicField<point>& end
) const;
//- Generate pairs of rays through cell centre
// Each ray pair has start, end, and expected gap size
label generateRays
(
const bool useSurfaceNormal,
const point& nearPoint,
const vector& nearNormal,
const FixedList<label, 3>& gapInfo,
const volumeType& mode,
const point& cc,
const label cLevel,
DynamicField<point>& start,
DynamicField<point>& end,
DynamicField<scalar>& gapSize,
DynamicField<point>& start2,
DynamicField<point>& end2,
DynamicField<scalar>& gapSize2
) const;
//- Select candidate cells (cells inside a shell with gapLevel
// specified)
void selectGapCandidates
(
const labelList& refineCell,
const label nRefine,
labelList& cellMap,
List<FixedList<label, 3> >& shellGapInfo,
List<volumeType>& shellGapMode
) const;
//- Merge gap information coming from shell and from surface
// (surface wins)
void mergeGapInfo
(
const FixedList<label, 3>& shellGapInfo,
const volumeType shellGapMode,
const FixedList<label, 3>& surfGapInfo,
const volumeType surfGapMode,
FixedList<label, 3>& gapInfo,
volumeType& gapMode
) const;
//- Mark cells for non-surface intersection based gap refinement
label markInternalGapRefinement
(
const scalar planarCos,
const bool spreadGapSize,
const label nAllowRefine,
labelList& refineCell,
label& nRefine,
labelList& numGapCells,
scalarField& gapSize
) const;
//- Refine cells containing small gaps
label markSmallFeatureRefinement
(
const scalar planarCos,
const label nAllowRefine,
const labelList& neiLevel,
const pointField& neiCc,
labelList& refineCell,
label& nRefine
) const;
//- Helper: count number of normals1 that are in normals2
label countMatches
(
@ -387,6 +507,7 @@ private:
void getIntersections
(
const labelList& surfacesToTest,
const labelList& neiLevel,
const pointField& neiCc,
const labelList& testFaces,
@ -567,7 +688,7 @@ private:
const labelList& cellToZone,
const labelList& neiCellZone,
const labelList& faceToZone,
const boolList& meshFlipMap,
const PackedBoolList& meshFlipMap,
polyTopoChange& meshMod
) const;
@ -631,7 +752,7 @@ private:
const labelList& nMasterFaces,
const labelList& faceToZone,
const Map<label>& zoneToOrientation,
boolList& meshFlipMap
PackedBoolList& meshFlipMap
) const;
@ -657,6 +778,7 @@ public:
const bool overwrite,
const refinementSurfaces&,
const refinementFeatures&,
const shellSurfaces&,
const shellSurfaces&
);
@ -855,7 +977,10 @@ public:
const bool internalRefinement,
const bool surfaceRefinement,
const bool curvatureRefinement,
const bool smallFeatureRefinement,
const bool gapRefinement,
const bool bigGapRefinement,
const bool spreadGapSize,
const label maxGlobalCells,
const label maxLocalCells
) const;

View File

@ -175,6 +175,7 @@ Foam::label Foam::meshRefinement::createBaffle
void Foam::meshRefinement::getIntersections
(
const labelList& surfacesToTest,
const labelList& neiLevel,
const pointField& neiCc,
const labelList& testFaces,
@ -198,8 +199,6 @@ void Foam::meshRefinement::getIntersections
<< str().name() << nl << endl;
}
const pointField& cellCentres = mesh_.cellCentres();
globalRegion1.setSize(mesh_.nFaces());
globalRegion1 = -1;
@ -213,29 +212,17 @@ void Foam::meshRefinement::getIntersections
pointField start(testFaces.size());
pointField end(testFaces.size());
forAll(testFaces, i)
{
label faceI = testFaces[i];
label own = mesh_.faceOwner()[faceI];
if (mesh_.isInternalFace(faceI))
{
start[i] = cellCentres[own];
end[i] = cellCentres[mesh_.faceNeighbour()[faceI]];
}
else
{
start[i] = cellCentres[own];
end[i] = neiCc[faceI-mesh_.nInternalFaces()];
}
}
// Extend segments a bit
{
const vectorField smallVec(ROOTSMALL*(end-start));
start -= smallVec;
end += smallVec;
labelList minLevel;
calcCellCellRays
(
neiCc,
neiLevel,
testFaces,
start,
end,
minLevel
);
}
@ -319,6 +306,7 @@ void Foam::meshRefinement::getBafflePatches
getIntersections
(
surfaceZonesInfo::getUnnamedSurfaces(surfaces_.surfZones()),
neiLevel,
neiCc,
testFaces,
globalRegion1,
@ -2608,7 +2596,7 @@ void Foam::meshRefinement::consistentOrientation
const labelList& nMasterFacesPerEdge,
const labelList& faceToZone,
const Map<label>& zoneToOrientation,
boolList& meshFlipMap
PackedBoolList& meshFlipMap
) const
{
const polyBoundaryMesh& bm = mesh_.boundaryMesh();
@ -2858,7 +2846,7 @@ void Foam::meshRefinement::zonify
const labelList& cellToZone,
const labelList& neiCellZone,
const labelList& faceToZone,
const boolList& meshFlipMap,
const PackedBoolList& meshFlipMap,
polyTopoChange& meshMod
) const
{
@ -3902,6 +3890,7 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::zonify
getIntersections
(
identity(surfaces_.surfaces().size()), // surfacesToTest,
neiLevel,
neiCc,
intersectedFaces(), // testFaces
globalRegion1,
@ -4297,7 +4286,7 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::zonify
}
// 2. Combine faceZoneNames allocated on different processors
// 2.Combine faceZoneNames allocated on different processors
Pstream::mapCombineGather(zonesToFaceZone, eqOp<word>());
Pstream::mapCombineScatter(zonesToFaceZone);
@ -4438,7 +4427,7 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::zonify
// - do a consistent orientation
// - check number of faces with consistent orientation
// - if <0 flip the whole patch
boolList meshFlipMap(mesh_.nFaces(), false);
PackedBoolList meshFlipMap(mesh_.nFaces(), false);
{
// Collect all data on zone faces without cellZones on either side.
const indirectPrimitivePatch patch

File diff suppressed because it is too large Load Diff

View File

@ -742,7 +742,7 @@ Foam::label Foam::meshRefinement::markInternalDistanceToFeatureRefinement
}
}
// Do test to see whether cells is inside/outside shell with higher level
// Do test to see whether cells are inside/outside shell with higher level
labelList maxLevel;
features_.findHigherLevel(testCc, testLevels, maxLevel);
@ -820,7 +820,7 @@ Foam::label Foam::meshRefinement::markInternalRefinement
}
}
// Do test to see whether cells is inside/outside shell with higher level
// Do test to see whether cells are inside/outside shell with higher level
labelList maxLevel;
shells_.findHigherLevel(testCc, testLevels, maxLevel);
@ -869,6 +869,56 @@ Foam::label Foam::meshRefinement::markInternalRefinement
}
Foam::label Foam::meshRefinement::unmarkInternalRefinement
(
labelList& refineCell,
label& nRefine
) const
{
const labelList& cellLevel = meshCutter_.cellLevel();
const pointField& cellCentres = mesh_.cellCentres();
label oldNRefine = nRefine;
// Collect cells to test
pointField testCc(nRefine);
labelList testLevels(nRefine);
label testI = 0;
forAll(cellLevel, cellI)
{
if (refineCell[cellI] >= 0)
{
testCc[testI] = cellCentres[cellI];
testLevels[testI] = cellLevel[cellI];
testI++;
}
}
// Do test to see whether cells are inside/outside shell with higher level
labelList levelShell;
limitShells_.findLevel(testCc, testLevels, levelShell);
// Mark for refinement. Note that we didn't store the original cellID so
// now just reloop in same order.
testI = 0;
forAll(cellLevel, cellI)
{
if (refineCell[cellI] >= 0)
{
if (levelShell[testI] != -1)
{
refineCell[cellI] = -1;
nRefine--;
}
testI++;
}
}
return returnReduce(oldNRefine-nRefine, sumOp<label>());
}
// Collect faces that are intersected and whose neighbours aren't yet marked
// for refinement.
Foam::labelList Foam::meshRefinement::getRefineCandidateFaces
@ -922,7 +972,6 @@ Foam::label Foam::meshRefinement::markSurfaceRefinement
) const
{
const labelList& cellLevel = meshCutter_.cellLevel();
const pointField& cellCentres = mesh_.cellCentres();
label oldNRefine = nRefine;
@ -941,36 +990,15 @@ Foam::label Foam::meshRefinement::markSurfaceRefinement
pointField end(testFaces.size());
labelList minLevel(testFaces.size());
forAll(testFaces, i)
{
label faceI = testFaces[i];
label own = mesh_.faceOwner()[faceI];
if (mesh_.isInternalFace(faceI))
{
label nei = mesh_.faceNeighbour()[faceI];
start[i] = cellCentres[own];
end[i] = cellCentres[nei];
minLevel[i] = min(cellLevel[own], cellLevel[nei]);
}
else
{
label bFaceI = faceI - mesh_.nInternalFaces();
start[i] = cellCentres[own];
end[i] = neiCc[bFaceI];
minLevel[i] = min(cellLevel[own], neiLevel[bFaceI]);
}
}
// Extend segments a bit
{
const vectorField smallVec(ROOTSMALL*(end-start));
start -= smallVec;
end += smallVec;
}
calcCellCellRays
(
neiCc,
neiLevel,
testFaces,
start,
end,
minLevel
);
// Do test for higher intersections
@ -1130,6 +1158,7 @@ Foam::label Foam::meshRefinement::markSurfaceCurvatureRefinement
pointField end(testFaces.size());
labelList minLevel(testFaces.size());
// Note: uses isMasterFace otherwise could be call to calcCellCellRays
forAll(testFaces, i)
{
label faceI = testFaces[i];
@ -1719,7 +1748,6 @@ Foam::label Foam::meshRefinement::markProximityRefinement
) const
{
const labelList& cellLevel = meshCutter_.cellLevel();
const pointField& cellCentres = mesh_.cellCentres();
label oldNRefine = nRefine;
@ -1739,36 +1767,15 @@ Foam::label Foam::meshRefinement::markProximityRefinement
pointField end(testFaces.size());
labelList minLevel(testFaces.size());
forAll(testFaces, i)
{
label faceI = testFaces[i];
label own = mesh_.faceOwner()[faceI];
if (mesh_.isInternalFace(faceI))
{
label nei = mesh_.faceNeighbour()[faceI];
start[i] = cellCentres[own];
end[i] = cellCentres[nei];
minLevel[i] = min(cellLevel[own], cellLevel[nei]);
}
else
{
label bFaceI = faceI - mesh_.nInternalFaces();
start[i] = cellCentres[own];
end[i] = neiCc[bFaceI];
minLevel[i] = min(cellLevel[own], neiLevel[bFaceI]);
}
}
// Extend segments a bit
{
const vectorField smallVec(ROOTSMALL*(end-start));
start -= smallVec;
end += smallVec;
}
calcCellCellRays
(
neiCc,
neiLevel,
testFaces,
start,
end,
minLevel
);
// Test for all intersections (with surfaces of higher gap level than
@ -2045,7 +2052,10 @@ Foam::labelList Foam::meshRefinement::refineCandidates
const bool internalRefinement,
const bool surfaceRefinement,
const bool curvatureRefinement,
const bool smallFeatureRefinement,
const bool gapRefinement,
const bool bigGapRefinement,
const bool spreadGapSize,
const label maxGlobalCells,
const label maxLocalCells
) const
@ -2096,6 +2106,8 @@ Foam::labelList Foam::meshRefinement::refineCandidates
calcNeighbourData(neiLevel, neiCc);
const scalar planarCos = Foam::cos(degToRad(planarAngle));
// Cells pierced by feature lines
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -2163,6 +2175,30 @@ Foam::labelList Foam::meshRefinement::refineCandidates
);
Info<< "Marked for refinement due to surface intersection "
<< ": " << nSurf << " cells." << endl;
// Refine intersected-cells only inside gaps. See
// markInternalGapRefinement to refine all cells inside gaps.
if
(
planarCos >= -1
&& planarCos <= 1
&& max(shells_.maxGapLevel()) > 0
)
{
label nGapSurf = markSurfaceGapRefinement
(
planarCos,
nAllowRefine,
neiLevel,
neiCc,
refineCell,
nRefine
);
Info<< "Marked for refinement due to surface intersection"
<< " (at gaps)"
<< ": " << nGapSurf << " cells." << endl;
}
}
// Refinement based on curvature of surface
@ -2190,7 +2226,33 @@ Foam::labelList Foam::meshRefinement::refineCandidates
}
const scalar planarCos = Foam::cos(degToRad(planarAngle));
// Refinement based on features smaller than cell size
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if
(
smallFeatureRefinement
&& (planarCos >= -1 && planarCos <= 1)
&& max(shells_.maxGapLevel()) > 0
)
{
label nGap = markSmallFeatureRefinement
(
planarCos,
nAllowRefine,
neiLevel,
neiCc,
refineCell,
nRefine
);
Info<< "Marked for refinement due to close opposite surfaces "
<< ": " << nGap << " cells." << endl;
}
// Refinement based on gap (only neighbouring cells)
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if
(
@ -2217,6 +2279,50 @@ Foam::labelList Foam::meshRefinement::refineCandidates
}
// Refinement based on gaps larger than cell size
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if
(
bigGapRefinement
&& (planarCos >= -1 && planarCos <= 1)
&& max(shells_.maxGapLevel()) > 0
)
{
// Refine based on gap information provided by shell and nearest
// surface
labelList numGapCells;
scalarField gapSize;
label nGap = markInternalGapRefinement
(
planarCos,
spreadGapSize,
nAllowRefine,
refineCell,
nRefine,
numGapCells,
gapSize
);
Info<< "Marked for refinement due to opposite surfaces"
<< " "
<< ": " << nGap << " cells." << endl;
}
// Limit refinement
// ~~~~~~~~~~~~~~~~
{
label nUnmarked = unmarkInternalRefinement(refineCell, nRefine);
if (nUnmarked > 0)
{
Info<< "Unmarked for refinement due to limit shells"
<< " : " << nUnmarked << " cells." << endl;
}
}
// Pack cells-to-refine
// ~~~~~~~~~~~~~~~~~~~~

View File

@ -0,0 +1,172 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::transportData
Description
Holds information (coordinate and distance). Walks out 0.5*distance.
SourceFiles
transportDataI.H
transportData.C
\*---------------------------------------------------------------------------*/
#ifndef transportData_H
#define transportData_H
#include "wallPointData.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declaration of classes
class polyMesh;
/*---------------------------------------------------------------------------*\
Class transportData Declaration
\*---------------------------------------------------------------------------*/
class transportData
:
public wallPointData<scalar>
{
public:
//- Class used to pass additional data in
class trackData
{
public:
//- Per face the index of the surface hit
const labelList& surfaceIndex_;
trackData(const labelList& surfaceIndex)
:
surfaceIndex_(surfaceIndex)
{}
};
private:
// Private Member Functions
//- Evaluate distance to point. Update distSqr, origin from whomever
// is nearer pt. Return true if w2 is closer to point,
// false otherwise.
template<class TrackingData>
inline bool update
(
const point&,
const transportData& w2,
const scalar tol,
TrackingData& td
);
public:
// Constructors
//- Construct null
inline transportData();
//- Construct from origin, gapSize, distance
inline transportData
(
const point& origin,
const scalar gapSize,
const scalar distSqr
);
// Member Functions
// Needed by FaceCellWave
//- Influence of neighbouring face.
// Calls update(...) with cellCentre of cellI
template<class TrackingData>
inline bool updateCell
(
const polyMesh& mesh,
const label thisCellI,
const label neighbourFaceI,
const transportData& neighbourWallInfo,
const scalar tol,
TrackingData& td
);
//- Influence of neighbouring cell.
// Calls update(...) with faceCentre of faceI
template<class TrackingData>
inline bool updateFace
(
const polyMesh& mesh,
const label thisFaceI,
const label neighbourCellI,
const transportData& neighbourWallInfo,
const scalar tol,
TrackingData& td
);
//- Influence of different value on same face.
// Merge new and old info.
// Calls update(...) with faceCentre of faceI
template<class TrackingData>
inline bool updateFace
(
const polyMesh& mesh,
const label thisFaceI,
const transportData& neighbourWallInfo,
const scalar tol,
TrackingData& td
);
};
//- Data associated with transportData type is same as underlying
template<>
inline bool contiguous<transportData>()
{
return contiguous<wallPointData<scalar> >();
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "transportDataI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,180 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "polyMesh.H"
#include "transform.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
// Update this with w2 if w2 nearer to pt.
template<class TrackingData>
inline bool Foam::transportData::update
(
const point& pt,
const transportData& w2,
const scalar tol,
TrackingData& td
)
{
scalar dist2 = magSqr(pt - w2.origin());
if (valid(td))
{
scalar diff = distSqr() - dist2;
if (diff < 0)
{
// Already nearer to pt
return false;
}
if ((diff < SMALL) || ((distSqr() > SMALL) && (diff/distSqr() < tol)))
{
// Don't propagate small changes
return false;
}
}
// Either *this is not yet valid or w2 is closer
{
// current not yet set so use any value
distSqr() = dist2;
origin() = w2.origin();
data() = w2.data();
if (distSqr() > sqr(0.25*data()))
{
// No need to transport gap data since too far away
return false;
}
return true;
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
inline Foam::transportData::transportData()
:
wallPointData<scalar>()
{}
inline Foam::transportData::transportData
(
const point& origin,
const scalar gapSize,
const scalar distSqr
)
:
wallPointData<scalar>(origin, gapSize, distSqr)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class TrackingData>
inline bool Foam::transportData::updateCell
(
const polyMesh& mesh,
const label cellI,
const label faceI,
const transportData& neighbourWallInfo,
const scalar tol,
TrackingData& td
)
{
if (td.surfaceIndex_[faceI] != -1)
{
return false;
}
const vectorField& cellCentres = mesh.primitiveMesh::cellCentres();
bool updated = update
(
cellCentres[cellI],
neighbourWallInfo,
tol,
td
);
return updated;
}
template<class TrackingData>
inline bool Foam::transportData::updateFace
(
const polyMesh& mesh,
const label thisFaceI,
const label neighbourCellI,
const transportData& neighbourWallInfo,
const scalar tol,
TrackingData& td
)
{
if (td.surfaceIndex_[thisFaceI] != -1)
{
return false;
}
return update
(
mesh.faceCentres()[thisFaceI],
neighbourWallInfo,
tol,
td
);
}
template<class TrackingData>
inline bool Foam::transportData::updateFace
(
const polyMesh& mesh,
const label thisFaceI,
const transportData& neighbourWallInfo,
const scalar tol,
TrackingData& td
)
{
if (td.surfaceIndex_[thisFaceI] != -1)
{
return false;
}
return update
(
mesh.faceCentres()[thisFaceI],
neighbourWallInfo,
tol,
td
);
}
// ************************************************************************* //

View File

@ -157,11 +157,22 @@ Foam::refinementSurfaces::refinementSurfaces
labelList globalMinLevel(surfI, 0);
labelList globalMaxLevel(surfI, 0);
labelList globalLevelIncr(surfI, 0);
FixedList<label, 3> nullGapLevel;
nullGapLevel[0] = 0;
nullGapLevel[1] = 0;
nullGapLevel[2] = 0;
List<FixedList<label, 3> > globalGapLevel(surfI);
List<volumeType> globalGapMode(surfI);
scalarField globalAngle(surfI, -GREAT);
PtrList<dictionary> globalPatchInfo(surfI);
List<Map<label> > regionMinLevel(surfI);
List<Map<label> > regionMaxLevel(surfI);
List<Map<label> > regionLevelIncr(surfI);
List<Map<FixedList<label, 3> > > regionGapLevel(surfI);
List<Map<volumeType> > regionGapMode(surfI);
List<Map<scalar> > regionAngle(surfI);
List<Map<autoPtr<dictionary> > > regionPatchInfo(surfI);
@ -212,6 +223,44 @@ Foam::refinementSurfaces::refinementSurfaces
<< exit(FatalIOError);
}
// Optional gapLevel specification
globalGapLevel[surfI] = dict.lookupOrDefault
(
"gapLevel",
nullGapLevel
);
globalGapMode[surfI] = volumeType::names
[
dict.lookupOrDefault<word>
(
"gapMode",
volumeType::names[volumeType::MIXED]
)
];
if
(
globalGapMode[surfI] == volumeType::UNKNOWN
|| globalGapLevel[surfI][0] < 0
|| globalGapLevel[surfI][1] < 0
|| globalGapLevel[surfI][2] < 0
|| globalGapLevel[surfI][1] > globalGapLevel[surfI][2]
)
{
FatalIOErrorIn
(
"refinementSurfaces::refinementSurfaces"
"(const searchableSurfaces&, const dictionary>&",
dict
) << "Illegal gapLevel specification for surface "
<< names_[surfI]
<< " : gapLevel:" << globalGapLevel[surfI]
<< " gapMode:" << volumeType::names[globalGapMode[surfI]]
<< exit(FatalIOError);
}
const searchableSurface& surface = allGeometry_[surfaces_[surfI]];
// Surface zones
@ -275,6 +324,54 @@ Foam::refinementSurfaces::refinementSurfaces
<< exit(FatalIOError);
}
// Optional gapLevel specification
FixedList<label, 3> gapSpec
(
regionDict.lookupOrDefault
(
"gapLevel",
nullGapLevel
)
);
regionGapLevel[surfI].insert(regionI, gapSpec);
volumeType gapModeSpec
(
volumeType::names
[
regionDict.lookupOrDefault<word>
(
"gapMode",
volumeType::names[volumeType::MIXED]
)
]
);
regionGapMode[surfI].insert(regionI, gapModeSpec);
if
(
gapModeSpec == volumeType::UNKNOWN
|| gapSpec[0] < 0
|| gapSpec[1] < 0
|| gapSpec[2] < 0
|| gapSpec[1] > gapSpec[2]
)
{
FatalIOErrorIn
(
"refinementSurfaces::refinementSurfaces"
"(const searchableSurfaces&,"
" const dictionary>&",
dict
) << "Illegal gapLevel specification for surface "
<< names_[surfI]
<< " : gapLevel:" << gapSpec
<< " gapMode:" << volumeType::names[gapModeSpec]
<< exit(FatalIOError);
}
if (regionDict.found("perpendicularAngle"))
{
regionAngle[surfI].insert
@ -331,6 +428,10 @@ Foam::refinementSurfaces::refinementSurfaces
maxLevel_ = 0;
gapLevel_.setSize(nRegions);
gapLevel_ = -1;
extendedGapLevel_.setSize(nRegions);
extendedGapLevel_ = nullGapLevel;
extendedGapMode_.setSize(nRegions);
extendedGapMode_ = volumeType::UNKNOWN;
perpendicularAngle_.setSize(nRegions);
perpendicularAngle_ = -GREAT;
patchInfo_.setSize(nRegions);
@ -349,7 +450,8 @@ Foam::refinementSurfaces::refinementSurfaces
gapLevel_[globalRegionI] =
maxLevel_[globalRegionI]
+ globalLevelIncr[surfI];
extendedGapLevel_[globalRegionI] = globalGapLevel[surfI];
extendedGapMode_[globalRegionI] = globalGapMode[surfI];
perpendicularAngle_[globalRegionI] = globalAngle[surfI];
if (globalPatchInfo.set(surfI))
{
@ -371,6 +473,10 @@ Foam::refinementSurfaces::refinementSurfaces
gapLevel_[globalRegionI] =
maxLevel_[globalRegionI]
+ regionLevelIncr[surfI][iter.key()];
extendedGapLevel_[globalRegionI] =
regionGapLevel[surfI][iter.key()];
extendedGapMode_[globalRegionI] =
regionGapMode[surfI][iter.key()];
}
forAllConstIter(Map<scalar>, regionAngle[surfI], iter)
{
@ -482,12 +588,28 @@ Foam::refinementSurfaces::refinementSurfaces
// }
Foam::labelList Foam::refinementSurfaces::maxGapLevel() const
{
labelList surfaceMax(surfaces_.size(), 0);
forAll(surfaces_, surfI)
{
const wordList& regionNames = allGeometry_[surfaces_[surfI]].regions();
forAll(regionNames, regionI)
{
label globalI = globalRegion(surfI, regionI);
const FixedList<label, 3>& gapInfo = extendedGapLevel_[globalI];
surfaceMax[surfI] = max(surfaceMax[surfI], gapInfo[2]);
}
}
return surfaceMax;
}
// Precalculate the refinement level for every element of the searchable
// surface.
void Foam::refinementSurfaces::setMinLevelFields
(
const shellSurfaces& shells
)
void Foam::refinementSurfaces::setMinLevelFields(const shellSurfaces& shells)
{
forAll(surfaces_, surfI)
{
@ -1208,6 +1330,99 @@ void Foam::refinementSurfaces::findNearestIntersection
}
void Foam::refinementSurfaces::findNearestIntersection
(
const pointField& start,
const pointField& end,
labelList& surface1,
vectorField& normal1
) const
{
// Initialize arguments
surface1.setSize(start.size());
surface1 = -1;
normal1.setSize(start.size());
normal1 = vector::zero;
// Current end of segment to test.
pointField nearest(end);
// Work array
List<pointIndexHit> nearestInfo(start.size());
labelList region;
vectorField normal;
forAll(surfaces_, surfI)
{
const searchableSurface& geom = allGeometry_[surfaces_[surfI]];
// See if any intersection between start and current nearest
geom.findLine(start, nearest, nearestInfo);
geom.getNormal(nearestInfo, normal);
forAll(nearestInfo, pointI)
{
if (nearestInfo[pointI].hit())
{
surface1[pointI] = surfI;
normal1[pointI] = normal[pointI];
nearest[pointI] = nearestInfo[pointI].hitPoint();
}
}
}
}
void Foam::refinementSurfaces::findNearestIntersection
(
const pointField& start,
const pointField& end,
labelList& surface1,
List<pointIndexHit>& hitInfo1,
vectorField& normal1
) const
{
// 1. intersection from start to end
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Initialize arguments
surface1.setSize(start.size());
surface1 = -1;
hitInfo1.setSize(start.size());
hitInfo1 = pointIndexHit();
normal1.setSize(start.size());
normal1 = vector::zero;
// Current end of segment to test.
pointField nearest(end);
// Work array
List<pointIndexHit> nearestInfo(start.size());
labelList region;
vectorField normal;
forAll(surfaces_, surfI)
{
const searchableSurface& geom = allGeometry_[surfaces_[surfI]];
// See if any intersection between start and current nearest
geom.findLine(start, nearest, nearestInfo);
geom.getNormal(nearestInfo, normal);
forAll(nearestInfo, pointI)
{
if (nearestInfo[pointI].hit())
{
surface1[pointI] = surfI;
hitInfo1[pointI] = nearestInfo[pointI];
normal1[pointI] = normal[pointI];
nearest[pointI] = nearestInfo[pointI].hitPoint();
}
}
}
}
void Foam::refinementSurfaces::findAnyIntersection
(
const pointField& start,

View File

@ -42,6 +42,7 @@ SourceFiles
#include "vectorList.H"
#include "pointIndexHit.H"
#include "surfaceZonesInfo.H"
#include "volumeType.H"
#include "pointList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -85,6 +86,12 @@ class refinementSurfaces
//- From global region number to small-gap level
labelList gapLevel_;
//- From global region number to small-gap level specification
List<FixedList<label, 3> > extendedGapLevel_;
//- From global region number to side of surface to detect
List<volumeType> extendedGapMode_;
//- From global region number to perpendicular angle
scalarField perpendicularAngle_;
@ -188,6 +195,23 @@ public:
return gapLevel_;
}
//- From global region number to specification of gap and its
// refinement: 3 labels specifying
// - minimum wanted number of cells in the gap
// - minimum cell level when to start trying to detect gaps
// - maximum cell level to refine to (so do not detect gaps if
// cell >= maximum level)
const List<FixedList<label, 3> >& extendedGapLevel() const
{
return extendedGapLevel_;
}
//- From global region number to side of surface to detect
const List<volumeType>& extendedGapMode() const
{
return extendedGapMode_;
}
//- From global region number to perpendicular angle
const scalarField& perpendicularAngle() const
{
@ -226,6 +250,9 @@ public:
return minLevel_.size();
}
//- Per surface the maximum extendedGapLevel over all its regions
labelList maxGapLevel() const;
//- Calculate minLevelFields
void setMinLevelFields
(
@ -314,6 +341,25 @@ public:
vectorField& normal2
) const;
//- Find nearest (to start only) intersection of edge
void findNearestIntersection
(
const pointField& start,
const pointField& end,
labelList& surfaces,
vectorField& normal
) const;
//- Find nearest (to start only) intersection of edge
void findNearestIntersection
(
const pointField& start,
const pointField& end,
labelList& surfaces,
List<pointIndexHit>&,
vectorField& normal
) const;
//- Used for debugging only: find intersection of edge.
void findAnyIntersection
(

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -124,7 +124,7 @@ void Foam::shellSurfaces::setAndCheckLevels
}
else
{
if (!allGeometry_[shells_[shellI]].hasVolumeType())
if (!shell.hasVolumeType())
{
FatalErrorIn
(
@ -152,6 +152,46 @@ void Foam::shellSurfaces::setAndCheckLevels
}
void Foam::shellSurfaces::checkGapLevels
(
const dictionary& shellDict,
const label shellI,
const List<FixedList<label, 3> >& levels
)
{
const searchableSurface& shell = allGeometry_[shells_[shellI]];
forAll(levels, regionI)
{
const FixedList<label, 3>& info = levels[regionI];
if (info[2] > 0)
{
if (modes_[shellI] == DISTANCE)
{
FatalIOErrorIn
(
"shellSurfaces::shellSurfaces(..)",
shellDict
) << "'gapLevel' specification cannot be used with mode "
<< refineModeNames_[DISTANCE]
<< " for shell " << shell.name()
<< exit(FatalIOError);
}
}
}
// Hardcode for region 0
if (levels[0][0] > 0)
{
Info<< "Refinement level up to " << levels[0][2]
<< " for all cells in gaps for shell "
<< shell.name() << endl;
}
}
// Specifically orient triSurfaces using a calculated point outside.
// Done since quite often triSurfaces not of consistent orientation which
// is (currently) necessary for sideness calculation
@ -288,18 +328,18 @@ void Foam::shellSurfaces::findHigherLevel
);
// Update maxLevel
forAll(nearInfo, candidateI)
forAll(nearInfo, i)
{
if (nearInfo[candidateI].hit())
if (nearInfo[i].hit())
{
// Check which level it actually is in.
label minDistI = findLower
(
distances,
mag(nearInfo[candidateI].hitPoint()-candidates[candidateI])
mag(nearInfo[i].hitPoint()-candidates[i])
);
label pointI = candidateMap[candidateI];
label pointI = candidateMap[i];
// pt is inbetween shell[minDistI] and shell[minDistI+1]
maxLevel[pointI] = levels[minDistI+1];
@ -356,6 +396,197 @@ void Foam::shellSurfaces::findHigherLevel
}
void Foam::shellSurfaces::findHigherGapLevel
(
const pointField& pt,
const labelList& ptLevel,
const label shellI,
labelList& gapShell,
List<FixedList<label, 3> >& gapInfo,
List<volumeType>& gapMode
) const
{
//TBD: hardcoded for region 0 information
const FixedList<label, 3>& info = extendedGapLevel_[shellI][0];
volumeType mode = extendedGapMode_[shellI][0];
if (info[2] == 0)
{
return;
}
// Collect all those points that have a current maxLevel less than the
// shell.
labelList candidateMap(pt.size());
label candidateI = 0;
forAll(ptLevel, pointI)
{
if (ptLevel[pointI] >= info[1] && ptLevel[pointI] < info[2])
{
candidateMap[candidateI++] = pointI;
}
}
candidateMap.setSize(candidateI);
// Do the expensive nearest test only for the candidate points.
List<volumeType> volType;
allGeometry_[shells_[shellI]].getVolumeType
(
pointField(pt, candidateMap),
volType
);
forAll(volType, i)
{
label pointI = candidateMap[i];
bool isInside = (volType[i] == volumeType::INSIDE);
if
(
(
(modes_[shellI] == INSIDE && isInside)
|| (modes_[shellI] == OUTSIDE && !isInside)
)
&& info[2] > gapInfo[pointI][2]
)
{
gapShell[pointI] = shellI;
gapInfo[pointI] = info;
gapMode[pointI] = mode;
}
}
}
void Foam::shellSurfaces::findLevel
(
const pointField& pt,
const label shellI,
labelList& minLevel,
labelList& shell
) const
{
const labelList& levels = levels_[shellI];
if (modes_[shellI] == DISTANCE)
{
// Distance mode.
const scalarField& distances = distances_[shellI];
// Collect all those points that have a current level equal/greater
// (any of) the shell. Also collect the furthest distance allowable
// to any shell with a higher level.
pointField candidates(pt.size());
labelList candidateMap(pt.size());
scalarField candidateDistSqr(pt.size());
label candidateI = 0;
forAll(shell, pointI)
{
if (shell[pointI] == -1)
{
forAllReverse(levels, levelI)
{
if (levels[levelI] <= minLevel[pointI])
{
candidates[candidateI] = pt[pointI];
candidateMap[candidateI] = pointI;
candidateDistSqr[candidateI] = sqr(distances[levelI]);
candidateI++;
break;
}
}
}
}
candidates.setSize(candidateI);
candidateMap.setSize(candidateI);
candidateDistSqr.setSize(candidateI);
// Do the expensive nearest test only for the candidate points.
List<pointIndexHit> nearInfo;
allGeometry_[shells_[shellI]].findNearest
(
candidates,
candidateDistSqr,
nearInfo
);
// Update maxLevel
forAll(nearInfo, i)
{
if (nearInfo[i].hit())
{
// Check which level it actually is in.
label minDistI = findLower
(
distances,
mag(nearInfo[i].hitPoint()-candidates[i])
);
label pointI = candidateMap[i];
// pt is inbetween shell[minDistI] and shell[minDistI+1]
shell[pointI] = shellI;
minLevel[pointI] = levels[minDistI+1];
}
}
}
else
{
// Inside/outside mode
// Collect all those points that have a current maxLevel less than the
// shell.
pointField candidates(pt.size());
labelList candidateMap(pt.size());
label candidateI = 0;
forAll(shell, pointI)
{
if (shell[pointI] == -1 && levels[0] <= minLevel[pointI])
{
candidates[candidateI] = pt[pointI];
candidateMap[candidateI] = pointI;
candidateI++;
}
}
candidates.setSize(candidateI);
candidateMap.setSize(candidateI);
// Do the expensive nearest test only for the candidate points.
List<volumeType> volType;
allGeometry_[shells_[shellI]].getVolumeType(candidates, volType);
forAll(volType, i)
{
if
(
(
modes_[shellI] == INSIDE
&& volType[i] == volumeType::INSIDE
)
|| (
modes_[shellI] == OUTSIDE
&& volType[i] == volumeType::OUTSIDE
)
)
{
label pointI = candidateMap[i];
shell[pointI] = shellI;
minLevel[pointI] = levels[0];
}
}
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::shellSurfaces::shellSurfaces
@ -387,6 +618,15 @@ Foam::shellSurfaces::shellSurfaces
distances_.setSize(shellI);
levels_.setSize(shellI);
extendedGapLevel_.setSize(shellI);
extendedGapMode_.setSize(shellI);
FixedList<label, 3> nullGapLevel;
nullGapLevel[0] = 0;
nullGapLevel[1] = 0;
nullGapLevel[2] = 0;
HashSet<word> unmatchedKeys(shellsDict.toc());
shellI = 0;
@ -407,6 +647,85 @@ Foam::shellSurfaces::shellSurfaces
// Read pairs of distance+level
setAndCheckLevels(shellI, dict.lookup("levels"));
// Gap specification
// ~~~~~~~~~~~~~~~~~
// Shell-wide gap level specification
const searchableSurface& surface = allGeometry_[geomI];
const wordList& regionNames = surface.regions();
FixedList<label, 3> gapSpec
(
dict.lookupOrDefault
(
"gapLevel",
nullGapLevel
)
);
extendedGapLevel_[shellI].setSize(regionNames.size());
extendedGapLevel_[shellI] = gapSpec;
volumeType gapModeSpec
(
volumeType::names
[
dict.lookupOrDefault<word>
(
"gapMode",
volumeType::names[volumeType::MIXED]
)
]
);
extendedGapMode_[shellI].setSize(regionNames.size());
extendedGapMode_[shellI] = gapModeSpec;
// Override on a per-region basis?
if (dict.found("regions"))
{
const dictionary& regionsDict = dict.subDict("regions");
forAll(regionNames, regionI)
{
if (regionsDict.found(regionNames[regionI]))
{
// Get the dictionary for region
const dictionary& regionDict = regionsDict.subDict
(
regionNames[regionI]
);
FixedList<label, 3> gapSpec
(
regionDict.lookupOrDefault
(
"gapLevel",
nullGapLevel
)
);
extendedGapLevel_[shellI][regionI] = gapSpec;
volumeType gapModeSpec
(
volumeType::names
[
regionDict.lookupOrDefault<word>
(
"gapMode",
volumeType::names[volumeType::MIXED]
)
]
);
extendedGapMode_[shellI][regionI] = gapModeSpec;
}
}
}
checkGapLevels(dict, shellI, extendedGapLevel_[shellI]);
shellI++;
}
}
@ -444,6 +763,22 @@ Foam::label Foam::shellSurfaces::maxLevel() const
}
Foam::labelList Foam::shellSurfaces::maxGapLevel() const
{
labelList surfaceMax(extendedGapLevel_.size(), 0);
forAll(extendedGapLevel_, shellI)
{
const List<FixedList<label, 3> >& levels = extendedGapLevel_[shellI];
forAll(levels, i)
{
surfaceMax[shellI] = max(surfaceMax[shellI], levels[i][2]);
}
}
return surfaceMax;
}
void Foam::shellSurfaces::findHigherLevel
(
const pointField& pt,
@ -461,4 +796,66 @@ void Foam::shellSurfaces::findHigherLevel
}
void Foam::shellSurfaces::findHigherGapLevel
(
const pointField& pt,
const labelList& ptLevel,
labelList& gapShell,
List<FixedList<label, 3> >& gapInfo,
List<volumeType>& gapMode
) const
{
gapShell.setSize(pt.size());
gapShell = -1;
FixedList<label, 3> nullGapLevel;
nullGapLevel[0] = 0;
nullGapLevel[1] = 0;
nullGapLevel[2] = 0;
gapInfo.setSize(pt.size());
gapInfo = nullGapLevel;
gapMode.setSize(pt.size());
gapMode = volumeType::MIXED;
forAll(shells_, shellI)
{
findHigherGapLevel(pt, ptLevel, shellI, gapShell, gapInfo, gapMode);
}
}
void Foam::shellSurfaces::findHigherGapLevel
(
const pointField& pt,
const labelList& ptLevel,
List<FixedList<label, 3> >& gapInfo,
List<volumeType>& gapMode
) const
{
labelList gapShell;
findHigherGapLevel(pt, ptLevel, gapShell, gapInfo, gapMode);
}
void Foam::shellSurfaces::findLevel
(
const pointField& pt,
const labelList& ptLevel,
labelList& shell
) const
{
shell.setSize(pt.size());
shell = -1;
labelList minLevel(ptLevel);
forAll(shells_, shellI)
{
findLevel(pt, shellI, minLevel, shell);
}
}
// ************************************************************************* //

View File

@ -2,8 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation
\\/ M anipulation |
\\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -85,6 +85,15 @@ private:
labelListList levels_;
// Gap level refinement
//- Per shell, per region the small-gap level specification
List<List<FixedList<label, 3> > > extendedGapLevel_;
//- Per shell, per region the small-gap level specification
List<List<volumeType> > extendedGapMode_;
// Private data
//- refineMode names
@ -93,15 +102,24 @@ private:
// Private Member Functions
//- Helper function for initialisation.
//- Helper function for initialisation of levels
void setAndCheckLevels
(
const label shellI,
const List<Tuple2<scalar, label> >&
);
//- Helper function for checking of gap information
void checkGapLevels
(
const dictionary&,
const label shellI,
const List<FixedList<label, 3> >& levels
);
void orient();
//- Find first shell with a level higher than maxLevel
void findHigherLevel
(
const pointField& pt,
@ -109,6 +127,27 @@ private:
labelList& maxLevel
) const;
//- Update highest min gap level
void findHigherGapLevel
(
const pointField& pt,
const labelList& ptLevel,
const label shellI,
labelList& gapShell,
List<FixedList<label, 3> >& gapInfo,
List<volumeType>& gapMode
) const;
//- Find first shell with a level lower or equal to minLevel. Update
// minLevel and shell.
void findLevel
(
const pointField& pt,
const label shellI,
labelList& minLevel,
labelList& shell
) const;
public:
// Constructors
@ -125,16 +164,11 @@ public:
// Access
//const List<scalarField>& distances() const
//{
// return distances_;
//}
//
////- Per shell per distance the refinement level
//const labelListList& levels() const
//{
// return levels_;
//}
//- Indices of surfaces that are shells
const labelList& shells() const
{
return shells_;
}
// Query
@ -142,6 +176,9 @@ public:
//- Highest shell level
label maxLevel() const;
//- Highest shell gap level
labelList maxGapLevel() const;
//- Find shell level higher than ptLevel
void findHigherLevel
(
@ -150,6 +187,33 @@ public:
labelList& maxLevel
) const;
//- Find a shell whose minimum gap level is >= ptLevel
void findHigherGapLevel
(
const pointField& pt,
const labelList& ptLevel,
labelList& gapShell,
List<FixedList<label, 3> >& gapInfo,
List<volumeType>& gapMode
) const;
//- Find a shell whose minimum gap level is >= ptLevel. gapInfo
// is (0 0 0) if no shell found
void findHigherGapLevel
(
const pointField& pt,
const labelList& ptLevel,
List<FixedList<label, 3> >& gapInfo,
List<volumeType>& gapMode
) const;
//- Find first shell (or -1) with level equal or lower than ptLevel.
void findLevel
(
const pointField& pt,
const labelList& ptLevel,
labelList& shell
) const;
};

View File

@ -63,7 +63,9 @@ indexedOctree/treeDataTriSurface.C
searchableSurface = searchableSurface
$(searchableSurface)/searchableBox.C
$(searchableSurface)/searchableRotatedBox.C
$(searchableSurface)/searchableCylinder.C
$(searchableSurface)/searchableCone.C
$(searchableSurface)/searchableDisk.C
$(searchableSurface)/searchablePlane.C
$(searchableSurface)/searchablePlate.C
@ -75,6 +77,7 @@ $(searchableSurface)/searchableSurfacesQueries.C
$(searchableSurface)/searchableSurfaceWithGaps.C
$(searchableSurface)/triSurfaceMesh.C
$(searchableSurface)/closedTriSurfaceMesh.C
$(searchableSurface)/subTriSurfaceMesh.C
topoSets = sets/topoSets
$(topoSets)/cellSet.C

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,296 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::searchableCone
Description
Searching on (optionally hollow) cone.
\heading Function object usage
\table
Property | Description | Required | Default value
point1 | coordinate of endpoint | yes |
radius1 | radius at point1 | yes | yes
innerRadius1 | inner radius at point1 | no |
point2 | coordinate of endpoint | yes |
radius2 | radius at point2 | yes | yes
innerRadius2 | inner radius at point2 | no |
\endtable
Note
Initial implementation, might suffer from robustness (e.g. radius1==radius2)
SourceFiles
searchableCone.C
\*---------------------------------------------------------------------------*/
#ifndef searchableCone_H
#define searchableCone_H
#include "searchableSurface.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class searchableCone Declaration
\*---------------------------------------------------------------------------*/
class searchableCone
:
public searchableSurface
{
// Private Member Data
//- 'Left' point
const point point1_;
//- Outer radius at point1
const scalar radius1_;
//- Inner radius at point1
const scalar innerRadius1_;
//- 'Right' point
const point point2_;
//- Outer radius at point2
const scalar radius2_;
//- Inner radius at point2
const scalar innerRadius2_;
//- Length of vector point2-point1
const scalar magDir_;
//- Normalised vector point2-point1
const vector unitDir_;
//- Names of regions
mutable wordList regions_;
// Private Member Functions
//- Find nearest point on cylinder.
void findNearestAndNormal
(
const point& sample,
const scalar nearestDistSqr,
pointIndexHit & nearInfo,
vector& normal
) const;
//- Determine radial coordinate (squared)
static scalar radius2(const searchableCone& cone, const point& pt);
//- Find both intersections with cone. innerRadii supplied externally.
void findLineAll
(
const searchableCone& cone,
const scalar innerRadius1,
const scalar innerRadius2,
const point& start,
const point& end,
pointIndexHit& near,
pointIndexHit& far
) const;
//- Insert a hit if it differs (by a tolerance) from the existing ones
void insertHit
(
const point& start,
const point& end,
List<pointIndexHit>& info,
const pointIndexHit& hit
) const;
//- Return the boundBox of the cylinder
boundBox calcBounds() const;
//- Disallow default bitwise copy construct
searchableCone(const searchableCone&);
//- Disallow default bitwise assignment
void operator=(const searchableCone&);
public:
//- Runtime type information
TypeName("searchableCone");
// Constructors
//- Construct from components
searchableCone
(
const IOobject& io,
const point& point1,
const scalar radius1,
const scalar innerRadius1,
const point& point2,
const scalar radius2,
const scalar innerRadius2
);
//- Construct from dictionary (used by searchableSurface)
searchableCone
(
const IOobject& io,
const dictionary& dict
);
//- Destructor
virtual ~searchableCone();
// Member Functions
virtual const wordList& regions() const;
//- Whether supports volume type below
virtual bool hasVolumeType() const
{
return true;
}
//- Range of local indices that can be returned.
virtual label size() const
{
return 1;
}
//- Get representative set of element coordinates
// Usually the element centres (should be of length size()).
virtual tmp<pointField> coordinates() const;
//- Get bounding spheres (centre and radius squared), one per element.
// Any point on element is guaranteed to be inside.
virtual void boundingSpheres
(
pointField& centres,
scalarField& radiusSqr
) const;
//- Get the points that define the surface.
virtual tmp<pointField> points() const;
//- Does any part of the surface overlap the supplied bound box?
virtual bool overlaps(const boundBox& bb) const
{
notImplemented
(
"searchableCone::overlaps(const boundBox&) const"
);
return false;
}
// Multiple point queries.
//- Find nearest point on cylinder
virtual void findNearest
(
const pointField& sample,
const scalarField& nearestDistSqr,
List<pointIndexHit>&
) const;
//- Find nearest intersection on line from start to end
virtual void findLine
(
const pointField& start,
const pointField& end,
List<pointIndexHit>&
) const;
//- Find all intersections in order from start to end
virtual void findLineAll
(
const pointField& start,
const pointField& end,
List<List<pointIndexHit> >&
) const;
//- Find any intersection on line from start to end
virtual void findLineAny
(
const pointField& start,
const pointField& end,
List<pointIndexHit>&
) const;
//- From a set of points and indices get the region
virtual void getRegion
(
const List<pointIndexHit>&,
labelList& region
) const;
//- From a set of points and indices get the normal
virtual void getNormal
(
const List<pointIndexHit>&,
vectorField& normal
) const;
//- Determine type (inside/outside/mixed) for point. unknown if
// cannot be determined (e.g. non-manifold surface)
virtual void getVolumeType
(
const pointField&,
List<volumeType>&
) const;
// regIOobject implementation
virtual bool writeData(Ostream&) const
{
notImplemented("searchableCone::writeData(Ostream&) const");
return false;
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -43,8 +43,6 @@ SourceFiles
namespace Foam
{
// Forward declaration of classes
/*---------------------------------------------------------------------------*\
Class searchableCylinder Declaration
\*---------------------------------------------------------------------------*/

View File

@ -55,8 +55,7 @@ Foam::searchableRotatedBox::searchableRotatedBox
io.db(),
io.readOpt(),
io.writeOpt(),
false, //io.registerObject(),
io.globalObject()
false //io.registerObject(),
),
treeBoundBox(point::zero, dict.lookup("span"))
),

View File

@ -56,8 +56,6 @@ SourceFiles
namespace Foam
{
// Forward declaration of classes
/*---------------------------------------------------------------------------*\
Class searchableRotatedBox Declaration
\*---------------------------------------------------------------------------*/
@ -145,6 +143,9 @@ public:
// Single point queries.
//- Inherit findNearest from searchableSurface
using searchableSurface::findNearest;
//- Calculate nearest point on surface.
// Returns
// - bool : any point found nearer than nearestDistSqr

View File

@ -0,0 +1,153 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "subTriSurfaceMesh.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(subTriSurfaceMesh, 0);
addToRunTimeSelectionTable(searchableSurface, subTriSurfaceMesh, dict);
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
Foam::wordList Foam::subTriSurfaceMesh::patchNames(const triSurface& s)
{
const geometricSurfacePatchList& patches = s.patches();
wordList names(patches.size());
forAll(patches, patchI)
{
names[patchI] = patches[patchI].name();
}
return names;
}
Foam::labelList Foam::subTriSurfaceMesh::selectedRegions
(
const triSurface& s,
const wordReList& regionNames
)
{
const wordList names(patchNames(s));
labelList regions(names.size());
label compactI = 0;
forAll(names, regionI)
{
const word& name = names[regionI];
forAll(regionNames, i)
{
if (regionNames[i].match(name))
{
regions[compactI++] = regionI;
}
}
}
regions.setSize(compactI);
return regions;
}
Foam::triSurface Foam::subTriSurfaceMesh::subset
(
const IOobject& io,
const dictionary& dict
)
{
const word subGeomName(dict.lookup("surface"));
const triSurfaceMesh& s =
io.db().lookupObject<triSurfaceMesh>(subGeomName);
const wordReList regionNames(dict.lookup("patches"));
labelList regionMap(selectedRegions(s, regionNames));
if (regionMap.size() == 0)
{
FatalIOErrorIn
(
"subTriSurfaceMesh::subset"
"(\n"
" const IOobject&,\n"
" const dictionary&\n"
")",
dict
) << "Found no regions in triSurface matching " << regionNames
<< ". Valid regions are " << patchNames(s)
<< exit(FatalIOError);
}
labelList reverseRegionMap(s.patches().size(), -1);
forAll(regionMap, i)
{
reverseRegionMap[regionMap[i]] = i;
}
boolList isSelected(s.size(), false);
forAll(s, triI)
{
if (reverseRegionMap[s.triSurface::operator[](triI).region()] != -1)
{
isSelected[triI] = true;
}
}
labelList pointMap;
labelList faceMap;
return s.subsetMesh(isSelected, pointMap, faceMap);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::subTriSurfaceMesh::subTriSurfaceMesh
(
const IOobject& io,
const dictionary& dict
)
:
triSurfaceMesh(io, subset(io, dict))
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::subTriSurfaceMesh::~subTriSurfaceMesh()
{}
// ************************************************************************* //

View File

@ -0,0 +1,115 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::subTriSurfaceMesh
Description
On-the-fly subset of triSurfaceMesh (based on selected patches)
Note
Example usage:
\verbatim
spheres.stl
{
type subTriSurfaceMesh;
// Surface to operate on. Avoid duplicate loading
surface spheres.stl;
// Regions to operate on (regular expressions allowed)
patches (solid1);
}
\endverbatim
SourceFiles
subTriSurfaceMesh.C
\*---------------------------------------------------------------------------*/
#ifndef subTriSurfaceMesh_H
#define subTriSurfaceMesh_H
#include "triSurfaceMesh.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class subTriSurfaceMesh Declaration
\*---------------------------------------------------------------------------*/
class subTriSurfaceMesh
:
public triSurfaceMesh
{
// Private member functions
//- Extract patch names of triSurface
static wordList patchNames(const triSurface& s);
//- Select regions by name
static labelList selectedRegions
(
const triSurface& s,
const wordReList& regionNames
);
//- Subset triSurface based on regions
static triSurface subset(const IOobject&, const dictionary&);
public:
//- Runtime type information
TypeName("subTriSurfaceMesh");
// Constructors
//- Construct from IO and dictionary.
subTriSurfaceMesh
(
const IOobject& io,
const dictionary& dict
);
//- Destructor
virtual ~subTriSurfaceMesh();
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -408,9 +408,16 @@ void Foam::hierarchGeomDecomp::sortComponent
{
// No need for binary searching of bin size
localSize = label(current.size()/n_[compI]);
if (leftIndex+localSize < sortedCoord.size())
{
rightCoord = sortedCoord[leftIndex+localSize];
}
else
{
rightCoord = maxCoord;
}
}
else
{
// For the current bin (starting at leftCoord) we want a rightCoord
// such that the sum of all sizes are globalCurrentSize/n_[compI].

View File

@ -12,6 +12,11 @@ cd ${0%/*} || exit 1 # Run from this directory
./Allrun
)
(
cd gap_detection || exit
./Allrun
)
exit 0
# These cases are links to solver test cases and are run when the Allrun

View File

@ -0,0 +1,7 @@
#!/bin/sh
# Source tutorial clean functions
. $WM_PROJECT_DIR/bin/tools/CleanFunctions
\rm -f constant/polyMesh/boundary > /dev/null 2>&1
cleanCase

View File

@ -0,0 +1,15 @@
#!/bin/sh
cd ${0%/*} || exit 1 # Run from this directory
# Source tutorial run functions
. $WM_PROJECT_DIR/bin/tools/RunFunctions
runApplication blockMesh
runApplication decomposePar
runParallel snappyHexMesh 8 -overwrite
runApplication reconstructParMesh -constant
# ----------------------------------------------------------------- end-of-file

View File

@ -0,0 +1,7 @@
Testcase for automatic gap refinement. The geometry is two nested boxes
with a single small pipe between them.
- 1 cell initial mesh
- consistent normal orientation of surface so
specify a 'gapMode' to limit refinement only to
gaps on the 'outside' of the surface

View File

@ -0,0 +1,102 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: dev |
| \\ / A nd | Web: www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object blockMeshDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
convertToMeters 1;
vertices
(
(-400 -100 -400)
( 400 -100 -400)
( 400 700 -400)
(-400 700 -400)
(-400 -100 400)
( 400 -100 400)
( 400 700 400)
(-400 700 400)
);
blocks
(
hex (0 1 2 3 4 5 6 7) (1 1 1) simpleGrading (1 1 1)
);
edges
(
);
boundary
(
maxY
{
type patch;
faces
(
(3 7 6 2)
);
}
minX
{
type patch;
faces
(
(0 4 7 3)
);
}
maxX
{
type patch;
faces
(
(2 6 5 1)
);
}
minY
{
type patch;
faces
(
(1 5 4 0)
);
}
ground
{
type patch;
faces
(
(0 3 2 1)
);
}
maxZ
{
type patch;
faces
(
(4 5 6 7)
);
}
);
mergePatchPairs
(
);
// ************************************************************************* //

View File

@ -0,0 +1,124 @@
# Wavefront OBJ file
# Regions:
# 0 patch0
#
# points : 40
# triangles : 76
#
v 80 20 -20
v -80 20 -20
v 100 0 0
v -100 0 0
v 80 20 -280
v -80 20 -280
v 80 280 -100
v -80 280 -100
v 100 0 -300
v -100 0 -300
v 100 300 -120
v -100 300 -120
v 80 280 -280
v -80 280 -280
v 100 300 -300
v -100 300 -300
v 0 445 0
v 0 445 -20
v 3.53538 446.464 0
v -3.53538 446.464 0
v -3.53538 446.464 -20
v 3.53538 446.464 -20
v 5 450 0
v -5 450 0
v -5 450 -20
v 5 450 -20
v -3.53538 453.536 0
v 3.53538 453.536 0
v -3.53538 453.536 -20
v 3.53538 453.536 -20
v 0 455 0
v 0 455 -20
v 80 580 -20
v -80 580 -20
v 80 580 -100
v -80 580 -100
v 100 600 0
v -100 600 0
v 100 600 -120
v -100 600 -120
g patch0
f 39 37 3
f 4 3 37
f 11 39 3
f 15 11 3
f 9 15 3
f 10 9 3
f 10 3 4
f 40 37 39
f 19 4 37
f 38 37 40
f 27 37 38
f 23 19 37
f 28 23 37
f 31 28 37
f 27 31 37
f 40 39 11
f 16 11 15
f 12 11 16
f 40 11 12
f 16 15 9
f 16 9 10
f 12 10 4
f 38 12 4
f 24 38 4
f 20 24 4
f 17 20 4
f 19 17 4
f 12 16 10
f 38 40 12
f 27 38 24
f 25 24 20
f 29 27 24
f 29 24 25
f 21 20 17
f 21 25 20
f 18 17 19
f 21 17 18
f 22 19 23
f 18 19 22
f 26 23 28
f 22 23 26
f 30 28 31
f 26 28 30
f 32 31 27
f 30 31 32
f 32 27 29
f 7 5 1
f 2 1 5
f 33 7 1
f 26 33 1
f 34 1 2
f 21 1 34
f 22 26 1
f 18 22 1
f 21 18 1
f 7 13 5
f 6 5 13
f 6 2 5
f 14 13 7
f 6 13 14
f 33 35 7
f 8 7 35
f 14 7 8
f 34 35 33
f 36 35 34
f 8 35 36
f 30 34 33
f 26 30 33
f 36 34 2
f 8 36 2
f 14 8 2
f 6 14 2
f 29 25 34
f 21 34 25
f 32 29 34
f 30 32 34

View File

@ -0,0 +1,49 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: dev s |
| \\ / A nd | Web: www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
location "system";
object controlDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
application snappyHexMesh;
startFrom startTime;
startTime 0;
stopAt endTime;
endTime 2000;
deltaT 1;
writeControl timeStep;
writeInterval 100;
purgeWrite 0;
writeFormat binary;
writePrecision 6;
writeCompression off;
timeFormat general;
timePrecision 6;
runTimeModifiable true;
// ************************************************************************* //

View File

@ -0,0 +1,41 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: dev |
| \\ / A nd | Web: www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
location "system";
object decomposeParDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
numberOfSubdomains 8;
method hierarchical;
simpleCoeffs
{
n ( 4 1 1 );
delta 0.001;
}
hierarchicalCoeffs
{
n ( 2 2 2 );
delta 0.001;
order xyz;
}
manualCoeffs
{
dataFile "cellDecomposition";
}
// ************************************************************************* //

View File

@ -0,0 +1,63 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: dev |
| \\ / A nd | Web: www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
location "system";
object fvSchemes;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
ddtSchemes
{
default steadyState;
}
gradSchemes
{
default Gauss linear;
}
divSchemes
{
default none;
div(phi,U) bounded Gauss upwind;
div(phi,T) bounded Gauss upwind;
div(phi,k) bounded Gauss upwind;
div(phi,epsilon) bounded Gauss upwind;
div(phi,R) bounded Gauss upwind;
div(R) Gauss linear;
div((nuEff*dev(T(grad(U))))) Gauss linear;
}
laplacianSchemes
{
default Gauss linear limited corrected 0.333;
}
interpolationSchemes
{
default linear;
}
snGradSchemes
{
default limited corrected 0.333;
}
fluxRequired
{
default no;
p_rgh ;
}
// ************************************************************************* //

View File

@ -0,0 +1,69 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: dev |
| \\ / A nd | Web: www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
location "system";
object fvSolution;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
solvers
{
p_rgh
{
solver PCG;
preconditioner DIC;
tolerance 1e-08;
relTol 0.01;
}
"(U|T|k|epsilon)"
{
solver PBiCG;
preconditioner DILU;
tolerance 1e-07;
relTol 0.1;
}
}
SIMPLE
{
nNonOrthogonalCorrectors 2;
pRefCell 0;
pRefValue 0;
residualControl
{
p_rgh 1e-2;
U 1e-4;
T 1e-3;
// possibly check turbulence fields
"(k|epsilon|omega)" 1e-3;
}
}
relaxationFactors
{
fields
{
p_rgh 0.7;
}
equations
{
U 0.2;
T 0.5;
"(k|epsilon)" 0.7;
}
}
// ************************************************************************* //

View File

@ -0,0 +1,21 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: dev |
| \\ / A nd | Web: www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object meshQualityDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Include defaults parameters from master dictionary
#include "$WM_PROJECT_DIR/etc/caseDicts/meshQualityDict"
// ************************************************************************* //

View File

@ -0,0 +1,297 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: dev |
| \\ / A nd | Web: www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object snappyHexMeshDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Which of the steps to run
castellatedMesh true;
snap false;
addLayers false;
// Geometry. Definition of all surfaces. All surfaces are of class
// searchableSurface.
// Surfaces are used
// - to specify refinement for any mesh cell intersecting it
// - to specify refinement for any mesh cell inside/outside/near
// - to 'snap' the mesh boundary to the surface
geometry
{
mech_test.obj
{
type triSurfaceMesh;
}
all
{
type searchableBox;
min (-1000 -1000 -1000);
max (1000 1000 1000);
}
};
// Settings for the castellatedMesh generation.
castellatedMeshControls
{
// Refinement parameters
// ~~~~~~~~~~~~~~~~~~~~~
// If local number of cells is >= maxLocalCells on any processor
// switches from from refinement followed by balancing
// (current method) to (weighted) balancing before refinement.
maxLocalCells 100000;
// 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.
maxGlobalCells 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)
minRefinementCells 0;
// Number of buffer layers between different levels.
// 1 means normal 2:1 refinement restriction, larger means slower
// refinement.
nCellsBetweenLevels 1;
// Explicit feature edge refinement
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Specifies a level for any cell intersected by its edges.
// This is a featureEdgeMesh, read from constant/triSurface for now.
features
(
);
// Surface based refinement
// ~~~~~~~~~~~~~~~~~~~~~~~~
// Specifies two levels for every surface. The first is the minimum level,
// every cell intersecting a surface gets refined up to the minimum level.
// The second level is the maximum level. Cells that 'see' multiple
// intersections where the intersections make an
// angle > resolveFeatureAngle get refined up to the maximum level.
refinementSurfaces
{
mech_test.obj
{
// Surface-wise min and max refinement level
level (0 0);
}
}
// Resolve sharp angles
resolveFeatureAngle 60;
// Region-wise refinement
// ~~~~~~~~~~~~~~~~~~~~~~
// Specifies refinement level for cells in relation to a surface. One of
// three modes
// - distance. 'levels' specifies per distance to the surface the
// wanted refinement level. The distances need to be specified in
// descending order.
// - inside. 'levels' is only one entry and only the level is used. All
// cells inside the surface get refined up to the level. The surface
// needs to be closed for this to be possible.
// - outside. Same but cells outside.
refinementRegions
{
all
{
mode inside;
// Dummy base level
levels ((10000 0));
// If cells
// - have level 0..9
// - and are in a gap < 3 cell sizes across
// - with the gap on the inside ('inside'), outside ('outside')
// or both ('mixed') of the surface
// refine them
gapLevel (4 0 10);
gapMode outside;
}
}
// Mesh selection
// ~~~~~~~~~~~~~~
// After refinement patches get added for all refinementSurfaces and
// all cells intersecting the surfaces get put into these patches. The
// section reachable from the locationInMesh is kept.
// NOTE: This point should never be on a face, always inside a cell, even
// after refinement.
locationInMesh (-100 -5 -300);
// Whether any faceZones (as specified in the refinementSurfaces)
// are only on the boundary of corresponding cellZones or also allow
// free-standing zone faces. Not used if there are no faceZones.
allowFreeStandingZoneFaces false;
}
// Settings for the snapping.
snapControls
{
//- 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.
tolerance 2.0;
//- Number of mesh displacement relaxation iterations.
nSolveIter 30;
//- Maximum number of snapping relaxation iterations. Should stop
// before upon reaching a correct mesh.
nRelaxIter 5;
// Feature snapping
//- Number of feature edge snapping iterations.
// Leave out altogether to disable.
nFeatureSnapIter 10;
//- Detect (geometric) features by sampling the surface (default=false)
implicitFeatureSnap true;
//- Use castellatedMeshControls::features (default = true)
explicitFeatureSnap false;
}
// Settings for the layer addition.
addLayersControls
{
// Are the thickness parameters below relative to the undistorted
// size of the refined cell outside layer (true) or absolute sizes (false).
relativeSizes true;
// Per final patch (so not geometry!) the layer information
layers
{
}
// Expansion factor for layer mesh
expansionRatio 1.0;
// Wanted thickness of final added cell layer. If multiple layers
// is the thickness of the layer furthest away from the wall.
// Relative to undistorted size of cell outside layer.
// is the thickness of the layer furthest away from the wall.
// See relativeSizes parameter.
finalLayerThickness 0.5;
// Minimum thickness of cell layer. If for any reason layer
// cannot be above minThickness do not add layer.
// Relative to undistorted size of cell outside layer.
// See relativeSizes parameter.
minThickness 0.25;
// If points get not extruded do nGrow layers of connected faces that are
// also not grown. This helps convergence of the layer addition process
// close to features.
// Note: changed(corrected) w.r.t 17x! (didn't do anything in 17x)
nGrow 0;
// Advanced settings
// When not to extrude surface. 0 is flat surface, 90 is when two faces
// are perpendicular
featureAngle 60;
// Maximum number of snapping relaxation iterations. Should stop
// before upon reaching a correct mesh.
nRelaxIter 5;
// 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
// Note: changed(corrected) w.r.t 16x! 90 degrees corresponds to 130 in 16x.
minMedianAxisAngle 90;
// Create buffer region for new layer terminations
nBufferCellsNoExtrude 0;
// Overall max number of layer addition iterations. The mesher will exit
// if it reaches this number of iterations; possibly with an illegal
// mesh.
nLayerIter 50;
}
// Generic mesh quality settings. At any undoable phase these determine
// where to undo.
meshQualityControls
{
#include "meshQualityDict"
// Advanced
//- Number of error distribution iterations
nSmoothScale 4;
//- amount to scale back displacement at error points
errorReduction 0.75;
}
// Advanced
// Merge tolerance. Is fraction of overall bounding box of initial mesh.
// Note: the write tolerance needs to be higher than this.
mergeTolerance 1e-6;
// ************************************************************************* //