mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
mesh driver rewrite; initial distributed surfaces
This commit is contained in:
@ -1,15 +1,21 @@
|
|||||||
autoHexMesh = autoHexMesh
|
autoHexMesh = autoHexMesh
|
||||||
|
autoHexMeshDriver = $(autoHexMesh)/autoHexMeshDriver
|
||||||
|
|
||||||
|
$(autoHexMeshDriver)/autoHexMeshDriver.C
|
||||||
|
$(autoHexMeshDriver)/autoHexMeshDriverLayers.C
|
||||||
|
$(autoHexMeshDriver)/autoHexMeshDriverShrink.C
|
||||||
|
$(autoHexMeshDriver)/autoHexMeshDriverSnap.C
|
||||||
|
$(autoHexMeshDriver)/layerParameters/layerParameters.C
|
||||||
|
$(autoHexMeshDriver)/refinementParameters/refinementParameters.C
|
||||||
|
$(autoHexMeshDriver)/snapParameters/snapParameters.C
|
||||||
|
$(autoHexMeshDriver)/pointData/pointData.C
|
||||||
|
|
||||||
$(autoHexMesh)/autoHexMeshDriver/autoHexMeshDriver.C
|
|
||||||
$(autoHexMesh)/autoHexMeshDriver/autoHexMeshDriverLayers.C
|
|
||||||
$(autoHexMesh)/autoHexMeshDriver/autoHexMeshDriverShrink.C
|
|
||||||
$(autoHexMesh)/autoHexMeshDriver/autoHexMeshDriverSnap.C
|
|
||||||
$(autoHexMesh)/autoHexMeshDriver/pointData/pointData.C
|
|
||||||
$(autoHexMesh)/meshRefinement/meshRefinementBaffles.C
|
$(autoHexMesh)/meshRefinement/meshRefinementBaffles.C
|
||||||
$(autoHexMesh)/meshRefinement/meshRefinement.C
|
$(autoHexMesh)/meshRefinement/meshRefinement.C
|
||||||
$(autoHexMesh)/meshRefinement/meshRefinementMerge.C
|
$(autoHexMesh)/meshRefinement/meshRefinementMerge.C
|
||||||
$(autoHexMesh)/meshRefinement/meshRefinementRefine.C
|
$(autoHexMesh)/meshRefinement/meshRefinementRefine.C
|
||||||
$(autoHexMesh)/refinementSurfaces/refinementSurfaces.C
|
$(autoHexMesh)/refinementSurfaces/refinementSurfaces.C
|
||||||
|
$(autoHexMesh)/shellSurfaces/shellSurfaces.C
|
||||||
$(autoHexMesh)/trackedParticle/trackedParticle.C
|
$(autoHexMesh)/trackedParticle/trackedParticle.C
|
||||||
$(autoHexMesh)/trackedParticle/trackedParticleCloud.C
|
$(autoHexMesh)/trackedParticle/trackedParticleCloud.C
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -49,8 +49,9 @@ SourceFiles
|
|||||||
#include "wallPoint.H"
|
#include "wallPoint.H"
|
||||||
#include "indirectPrimitivePatch.H"
|
#include "indirectPrimitivePatch.H"
|
||||||
#include "featureEdgeMesh.H"
|
#include "featureEdgeMesh.H"
|
||||||
#include "searchableSurface.H"
|
#include "searchableSurfaces.H"
|
||||||
#include "refinementSurfaces.H"
|
#include "refinementSurfaces.H"
|
||||||
|
#include "shellSurfaces.H"
|
||||||
#include "meshRefinement.H"
|
#include "meshRefinement.H"
|
||||||
#include "decompositionMethod.H"
|
#include "decompositionMethod.H"
|
||||||
#include "fvMeshDistribute.H"
|
#include "fvMeshDistribute.H"
|
||||||
@ -70,6 +71,9 @@ class pointData;
|
|||||||
class faceSet;
|
class faceSet;
|
||||||
class addPatchCellLayer;
|
class addPatchCellLayer;
|
||||||
class mapDistributePolyMesh;
|
class mapDistributePolyMesh;
|
||||||
|
class snapParameters;
|
||||||
|
class layerParameters;
|
||||||
|
class refinementParameters;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
/*---------------------------------------------------------------------------*\
|
||||||
Class autoHexMeshDriver Declaration
|
Class autoHexMeshDriver Declaration
|
||||||
@ -79,15 +83,13 @@ class autoHexMeshDriver
|
|||||||
{
|
{
|
||||||
// Static data members
|
// Static data members
|
||||||
|
|
||||||
//- Default angle for faces to be convcave
|
|
||||||
static const scalar defaultConcaveAngle;
|
|
||||||
|
|
||||||
//- Extrusion controls
|
//- Extrusion controls
|
||||||
enum extrudeMode
|
enum extrudeMode
|
||||||
{
|
{
|
||||||
NOEXTRUDE, /*!< Do not extrude. No layers added. */
|
NOEXTRUDE, /*!< Do not extrude. No layers added. */
|
||||||
EXTRUDE, /*!< Extrude */
|
EXTRUDE, /*!< Extrude */
|
||||||
EXTRUDEREMOVE /*!< Extrude but afterwards remove added faces locally */
|
EXTRUDEREMOVE /*!< Extrude but afterwards remove added */
|
||||||
|
/*!< faces locally */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -141,42 +143,24 @@ class autoHexMeshDriver
|
|||||||
//- Debug level
|
//- Debug level
|
||||||
const label debug_;
|
const label debug_;
|
||||||
|
|
||||||
//- Total number of cells
|
|
||||||
const label maxGlobalCells_;
|
|
||||||
|
|
||||||
//- Per processor max number of cells
|
|
||||||
const label maxLocalCells_;
|
|
||||||
|
|
||||||
//- When to stop refining
|
|
||||||
const label minRefineCells_;
|
|
||||||
|
|
||||||
//- Curvature
|
|
||||||
const scalar curvature_;
|
|
||||||
|
|
||||||
//- Number of layers between different refinement levels
|
|
||||||
const label nBufferLayers_;
|
|
||||||
|
|
||||||
//- Areas to keep
|
|
||||||
const pointField keepPoints_;
|
|
||||||
|
|
||||||
//- Merge distance
|
//- Merge distance
|
||||||
const scalar mergeDist_;
|
const scalar mergeDist_;
|
||||||
|
|
||||||
|
|
||||||
|
// Refinement only
|
||||||
|
|
||||||
//- Explicit features
|
//- Explicit features
|
||||||
PtrList<featureEdgeMesh> featureMeshes_;
|
PtrList<featureEdgeMesh> featureMeshes_;
|
||||||
//- Per feature the refinement level
|
//- Per feature the refinement level
|
||||||
labelList featureLevels_;
|
labelList featureLevels_;
|
||||||
|
|
||||||
//- Shells
|
//- All surface based geometry
|
||||||
PtrList<searchableSurface> shells_;
|
autoPtr<searchableSurfaces> allGeometryPtr_;
|
||||||
//- Per shell the refinement level
|
|
||||||
labelList shellLevels_;
|
|
||||||
//- Per shell whether to refine inside or outside
|
|
||||||
boolList shellRefineInside_;
|
|
||||||
|
|
||||||
//- Surfaces with refinement levels built-in
|
//- Shells (geometry for inside/outside refinement)
|
||||||
|
autoPtr<shellSurfaces> shellsPtr_;
|
||||||
|
|
||||||
|
//- Surfaces (geometry for intersection based refinement)
|
||||||
autoPtr<refinementSurfaces> surfacesPtr_;
|
autoPtr<refinementSurfaces> surfacesPtr_;
|
||||||
|
|
||||||
//- Per refinement surface region the patch
|
//- Per refinement surface region the patch
|
||||||
@ -200,10 +184,6 @@ class autoHexMeshDriver
|
|||||||
//- Calculate merge distance. Check against writing tolerance.
|
//- Calculate merge distance. Check against writing tolerance.
|
||||||
scalar getMergeDistance(const scalar mergeTol) const;
|
scalar getMergeDistance(const scalar mergeTol) const;
|
||||||
|
|
||||||
// Return per keeppoint -1 or the local cell label the point is in.
|
|
||||||
// Guaranteed to be only on one processor.
|
|
||||||
labelList findCells(const pointField&) const;
|
|
||||||
|
|
||||||
static void orientOutside(PtrList<searchableSurface>&);
|
static void orientOutside(PtrList<searchableSurface>&);
|
||||||
|
|
||||||
//- Read feature edges
|
//- Read feature edges
|
||||||
@ -371,6 +351,7 @@ class autoHexMeshDriver
|
|||||||
// layers per surface.
|
// layers per surface.
|
||||||
void setNumLayers
|
void setNumLayers
|
||||||
(
|
(
|
||||||
|
const labelList& patchToNLayers,
|
||||||
const labelList& patchIDs,
|
const labelList& patchIDs,
|
||||||
const indirectPrimitivePatch& pp,
|
const indirectPrimitivePatch& pp,
|
||||||
pointField& patchDisp,
|
pointField& patchDisp,
|
||||||
@ -390,17 +371,22 @@ class autoHexMeshDriver
|
|||||||
//- Calculate pointwise wanted and minimum thickness.
|
//- Calculate pointwise wanted and minimum thickness.
|
||||||
// thickness: wanted thickness
|
// thickness: wanted thickness
|
||||||
// minthickness: when to give up and not extrude
|
// minthickness: when to give up and not extrude
|
||||||
|
// Gets per patch parameters and determine pp pointwise
|
||||||
|
// parameters.
|
||||||
void calculateLayerThickness
|
void calculateLayerThickness
|
||||||
(
|
(
|
||||||
const scalar expansionRatio,
|
|
||||||
const scalar finalLayerRatio,
|
|
||||||
const scalar relMinThickness,
|
|
||||||
const indirectPrimitivePatch& pp,
|
const indirectPrimitivePatch& pp,
|
||||||
|
const labelList& patchIDs,
|
||||||
|
const scalarField& patchExpansionRatio,
|
||||||
|
const scalarField& patchFinalLayerRatio,
|
||||||
|
const scalarField& patchRelMinThickness,
|
||||||
const labelList& cellLevel,
|
const labelList& cellLevel,
|
||||||
const labelList& patchNLayers,
|
const labelList& patchNLayers,
|
||||||
const scalar edge0Len,
|
const scalar edge0Len,
|
||||||
|
|
||||||
scalarField& thickness,
|
scalarField& thickness,
|
||||||
scalarField& minThickness
|
scalarField& minThickness,
|
||||||
|
scalarField& expansionRatio
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
|
|
||||||
@ -638,13 +624,13 @@ public:
|
|||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
//- Construct from dictionary and mesh to modify
|
// //- Construct from dictionary and mesh to modify
|
||||||
autoHexMeshDriver
|
// autoHexMeshDriver
|
||||||
(
|
// (
|
||||||
fvMesh& mesh,
|
// fvMesh& mesh,
|
||||||
const dictionary& meshDict,
|
// const dictionary& meshDict,
|
||||||
const dictionary& decomposeDict
|
// const dictionary& decomposeDict
|
||||||
);
|
// );
|
||||||
|
|
||||||
//- Alternative constructor from top-level controldictionary and
|
//- Alternative constructor from top-level controldictionary and
|
||||||
// refinement specific dictionary
|
// refinement specific dictionary
|
||||||
@ -652,6 +638,7 @@ public:
|
|||||||
(
|
(
|
||||||
fvMesh& mesh,
|
fvMesh& mesh,
|
||||||
const dictionary& controlDict,
|
const dictionary& controlDict,
|
||||||
|
const dictionary& geometryDict,
|
||||||
const dictionary& refineDict,
|
const dictionary& refineDict,
|
||||||
const dictionary& decomposeDict
|
const dictionary& decomposeDict
|
||||||
);
|
);
|
||||||
@ -677,6 +664,12 @@ public:
|
|||||||
return surfacesPtr_();
|
return surfacesPtr_();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//- Surfaces to volume refinement on
|
||||||
|
const shellSurfaces& shells() const
|
||||||
|
{
|
||||||
|
return shellsPtr_();
|
||||||
|
}
|
||||||
|
|
||||||
//- Per refinementsurface, per region the patch
|
//- Per refinementsurface, per region the patch
|
||||||
const labelList& globalToPatch() const
|
const labelList& globalToPatch() const
|
||||||
{
|
{
|
||||||
@ -689,32 +682,53 @@ public:
|
|||||||
//- Refine around explicit feature edges
|
//- Refine around explicit feature edges
|
||||||
label featureEdgeRefine
|
label featureEdgeRefine
|
||||||
(
|
(
|
||||||
|
const refinementParameters& refineParams,
|
||||||
const PtrList<dictionary>& featDicts,
|
const PtrList<dictionary>& featDicts,
|
||||||
const label maxIter,
|
const label maxIter,
|
||||||
const label minRefine
|
const label minRefine
|
||||||
);
|
);
|
||||||
|
|
||||||
//- Refine at surface intersections
|
//- Refine at surface intersections
|
||||||
label surfaceOnlyRefine(const label maxIter);
|
label surfaceOnlyRefine
|
||||||
|
(
|
||||||
|
const refinementParameters& refineParams,
|
||||||
|
const label maxIter
|
||||||
|
);
|
||||||
|
|
||||||
//- Remove cells not reachable from keep points
|
//- Remove cells not reachable from keep points
|
||||||
void removeInsideCells(const label nBufferLayers);
|
void removeInsideCells
|
||||||
|
(
|
||||||
|
const refinementParameters& refineParams,
|
||||||
|
const label nBufferLayers
|
||||||
|
);
|
||||||
|
|
||||||
//- Refine volume regions (interior of shells)
|
//- Refine volume regions (interior of shells)
|
||||||
label shellRefine(const label maxIter);
|
label shellRefine
|
||||||
|
(
|
||||||
|
const refinementParameters& refineParams,
|
||||||
|
const label maxIter
|
||||||
|
);
|
||||||
|
|
||||||
//- Introduce baffles; remove unreachable mesh parts
|
//- Introduce baffles; remove unreachable mesh parts
|
||||||
// handleSnapProblems : whether to remove free floating cells
|
// handleSnapProblems : whether to remove free floating cells
|
||||||
void baffleAndSplitMesh(const bool handleSnapProblems);
|
void baffleAndSplitMesh
|
||||||
|
(
|
||||||
|
const refinementParameters& refineParams,
|
||||||
|
const bool handleSnapProblems
|
||||||
|
);
|
||||||
|
|
||||||
//- Move cells to zones
|
//- Move cells to zones
|
||||||
void zonify();
|
void zonify(const refinementParameters&);
|
||||||
|
|
||||||
//- Split and recombine baffles to get rid of single face baffles.
|
//- Split and recombine baffles to get rid of single face baffles.
|
||||||
void splitAndMergeBaffles(const bool handleSnapProblems);
|
void splitAndMergeBaffles
|
||||||
|
(
|
||||||
|
const refinementParameters& refineParams,
|
||||||
|
const bool handleSnapProblems
|
||||||
|
);
|
||||||
|
|
||||||
//- Merge multiple boundary faces on single cell
|
//- Merge multiple boundary faces on single cell
|
||||||
void mergePatchFaces();
|
void mergePatchFaces(const refinementParameters&);
|
||||||
|
|
||||||
//- Redecompose according to cell count
|
//- Redecompose according to cell count
|
||||||
// keepZoneFaces : find all faceZones from zoned surfaces and keep
|
// keepZoneFaces : find all faceZones from zoned surfaces and keep
|
||||||
@ -742,7 +756,7 @@ public:
|
|||||||
//- Calculate edge length per patch point.
|
//- Calculate edge length per patch point.
|
||||||
scalarField calcSnapDistance
|
scalarField calcSnapDistance
|
||||||
(
|
(
|
||||||
const dictionary& snapDict,
|
const snapParameters& snapParams,
|
||||||
const indirectPrimitivePatch&
|
const indirectPrimitivePatch&
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
@ -753,12 +767,19 @@ 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 snapParameters& snapParams,
|
||||||
const label nInitErrors,
|
const label nInitErrors,
|
||||||
const List<labelPair>& baffles,
|
const List<labelPair>& baffles,
|
||||||
motionSmoother&
|
motionSmoother&
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
|
//- Get points both on patch and facezone.
|
||||||
|
labelList getZoneSurfacePoints
|
||||||
|
(
|
||||||
|
const indirectPrimitivePatch&,
|
||||||
|
const word& zoneName
|
||||||
|
) const;
|
||||||
|
|
||||||
//- Per patch point calculate point on nearest surface. Set as
|
//- Per patch point calculate point on nearest surface. Set as
|
||||||
// boundary conditions of motionSmoother displacement field. Return
|
// boundary conditions of motionSmoother displacement field. Return
|
||||||
// displacement of patch points.
|
// displacement of patch points.
|
||||||
@ -771,7 +792,7 @@ public:
|
|||||||
//- Smooth the displacement field to the internal.
|
//- Smooth the displacement field to the internal.
|
||||||
void smoothDisplacement
|
void smoothDisplacement
|
||||||
(
|
(
|
||||||
const dictionary& snapDict,
|
const snapParameters& snapParams,
|
||||||
motionSmoother&
|
motionSmoother&
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
@ -779,7 +800,7 @@ public:
|
|||||||
// locally relax the displacement.
|
// locally relax the displacement.
|
||||||
void scaleMesh
|
void scaleMesh
|
||||||
(
|
(
|
||||||
const dictionary& snapDict,
|
const snapParameters& snapParams,
|
||||||
const label nInitErrors,
|
const label nInitErrors,
|
||||||
const List<labelPair>& baffles,
|
const List<labelPair>& baffles,
|
||||||
motionSmoother&
|
motionSmoother&
|
||||||
@ -791,7 +812,7 @@ public:
|
|||||||
//- Merge patch faces on same cell.
|
//- Merge patch faces on same cell.
|
||||||
void mergePatchFacesUndo
|
void mergePatchFacesUndo
|
||||||
(
|
(
|
||||||
const dictionary& shrinkDict,
|
const layerParameters& layerParams,
|
||||||
const dictionary& motionDict
|
const dictionary& motionDict
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -801,7 +822,7 @@ public:
|
|||||||
//- Add cell layers
|
//- Add cell layers
|
||||||
void addLayers
|
void addLayers
|
||||||
(
|
(
|
||||||
const dictionary& shrinkDict,
|
const layerParameters& layerParams,
|
||||||
const dictionary& motionDict,
|
const dictionary& motionDict,
|
||||||
const label nAllowableErrors,
|
const label nAllowableErrors,
|
||||||
motionSmoother&
|
motionSmoother&
|
||||||
|
|||||||
@ -27,7 +27,6 @@ Description
|
|||||||
|
|
||||||
\*----------------------------------------------------------------------------*/
|
\*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "ListOps.H"
|
|
||||||
#include "autoHexMeshDriver.H"
|
#include "autoHexMeshDriver.H"
|
||||||
#include "fvMesh.H"
|
#include "fvMesh.H"
|
||||||
#include "Time.H"
|
#include "Time.H"
|
||||||
@ -43,11 +42,8 @@ Description
|
|||||||
#include "mapPolyMesh.H"
|
#include "mapPolyMesh.H"
|
||||||
#include "addPatchCellLayer.H"
|
#include "addPatchCellLayer.H"
|
||||||
#include "mapDistributePolyMesh.H"
|
#include "mapDistributePolyMesh.H"
|
||||||
|
#include "OFstream.H"
|
||||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
#include "layerParameters.H"
|
||||||
|
|
||||||
const Foam::scalar Foam::autoHexMeshDriver::defaultConcaveAngle = 90;
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -1191,6 +1187,7 @@ void Foam::autoHexMeshDriver::handleWarpedFaces
|
|||||||
// 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& patchToNLayers,
|
||||||
const labelList& patchIDs,
|
const labelList& patchIDs,
|
||||||
const indirectPrimitivePatch& pp,
|
const indirectPrimitivePatch& pp,
|
||||||
pointField& patchDisp,
|
pointField& patchDisp,
|
||||||
@ -1201,18 +1198,6 @@ 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
|
|
||||||
Map<label> patchToNLayers(nSurfLayers.size());
|
|
||||||
forAll(nSurfLayers, region)
|
|
||||||
{
|
|
||||||
if (globalToPatch_[region] != -1)
|
|
||||||
{
|
|
||||||
patchToNLayers.insert(globalToPatch_[region], nSurfLayers[region]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get for every point (really only nessecary on patch external points)
|
// Get for every point (really only nessecary on patch external points)
|
||||||
// the max and min of any patch faces using it.
|
// the max and min of any patch faces using it.
|
||||||
labelList maxLayers(patchNLayers.size(), labelMin);
|
labelList maxLayers(patchNLayers.size(), labelMin);
|
||||||
@ -1257,7 +1242,7 @@ void Foam::autoHexMeshDriver::setNumLayers
|
|||||||
// Unmark any point with different min and max
|
// Unmark any point with different min and max
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
label nConflicts = 0;
|
//label nConflicts = 0;
|
||||||
|
|
||||||
forAll(maxLayers, i)
|
forAll(maxLayers, i)
|
||||||
{
|
{
|
||||||
@ -1294,11 +1279,11 @@ void Foam::autoHexMeshDriver::setNumLayers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reduce(nConflicts, sumOp<label>());
|
//reduce(nConflicts, sumOp<label>());
|
||||||
|
//
|
||||||
Info<< "Set displacement to zero for " << nConflicts
|
//Info<< "Set displacement to zero for " << nConflicts
|
||||||
<< " points due to points being on multiple regions"
|
// << " points due to points being on multiple regions"
|
||||||
<< " with inconsistent nLayers specification." << endl;
|
// << " with inconsistent nLayers specification." << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1369,59 +1354,137 @@ void Foam::autoHexMeshDriver::growNoExtrusion
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Calculate pointwise wanted and minimum thickness.
|
|
||||||
// thickness: wanted thickness per point
|
|
||||||
void Foam::autoHexMeshDriver::calculateLayerThickness
|
void Foam::autoHexMeshDriver::calculateLayerThickness
|
||||||
(
|
(
|
||||||
const scalar expansionRatio,
|
|
||||||
const scalar finalLayerRatio,
|
|
||||||
const scalar relMinThickness,
|
|
||||||
const indirectPrimitivePatch& pp,
|
const indirectPrimitivePatch& pp,
|
||||||
|
const labelList& patchIDs,
|
||||||
|
const scalarField& patchExpansionRatio,
|
||||||
|
const scalarField& patchFinalLayerRatio,
|
||||||
|
const scalarField& patchRelMinThickness,
|
||||||
const labelList& cellLevel,
|
const labelList& cellLevel,
|
||||||
const labelList& patchNLayers,
|
const labelList& patchNLayers,
|
||||||
const scalar edge0Len,
|
const scalar edge0Len,
|
||||||
|
|
||||||
scalarField& thickness,
|
scalarField& thickness,
|
||||||
scalarField& minThickness
|
scalarField& minThickness,
|
||||||
|
scalarField& expansionRatio
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
if (relMinThickness < 0 || relMinThickness > 2)
|
const polyBoundaryMesh& patches = mesh_.boundaryMesh();
|
||||||
|
|
||||||
|
if (min(patchRelMinThickness) < 0 || max(patchRelMinThickness) > 2)
|
||||||
{
|
{
|
||||||
FatalErrorIn("calculateLayerThickness(..)")
|
FatalErrorIn("calculateLayerThickness(..)")
|
||||||
<< "Thickness should be factor of local undistorted cell size."
|
<< "Thickness should be factor of local undistorted cell size."
|
||||||
<< " Valid values are [0..2]." << nl
|
<< " Valid values are [0..2]." << nl
|
||||||
<< " minThickness:" << relMinThickness
|
<< " minThickness:" << patchRelMinThickness
|
||||||
<< exit(FatalError);
|
<< exit(FatalError);
|
||||||
}
|
}
|
||||||
|
|
||||||
thickness.setSize(pp.nPoints());
|
|
||||||
minThickness.setSize(pp.nPoints());
|
|
||||||
|
|
||||||
// Per point the max cell level of connected cells
|
// Per point the max cell level of connected cells
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
labelList maxPointLevel(pp.nPoints(), labelMin);
|
labelList maxPointLevel(pp.nPoints(), labelMin);
|
||||||
|
|
||||||
forAll(pp, i)
|
|
||||||
{
|
{
|
||||||
label ownLevel = cellLevel[mesh_.faceOwner()[pp.addressing()[i]]];
|
forAll(pp, i)
|
||||||
|
|
||||||
const face& f = pp.localFaces()[i];
|
|
||||||
|
|
||||||
forAll(f, fp)
|
|
||||||
{
|
{
|
||||||
maxPointLevel[f[fp]] = max(maxPointLevel[f[fp]], ownLevel);
|
label ownLevel = cellLevel[mesh_.faceOwner()[pp.addressing()[i]]];
|
||||||
|
|
||||||
|
const face& f = pp.localFaces()[i];
|
||||||
|
|
||||||
|
forAll(f, fp)
|
||||||
|
{
|
||||||
|
maxPointLevel[f[fp]] = max(maxPointLevel[f[fp]], ownLevel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
syncTools::syncPointList
|
||||||
|
(
|
||||||
|
mesh_,
|
||||||
|
pp.meshPoints(),
|
||||||
|
maxPointLevel,
|
||||||
|
maxEqOp<label>(),
|
||||||
|
labelMin, // null value
|
||||||
|
false // no separation
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
syncTools::syncPointList
|
|
||||||
(
|
|
||||||
mesh_,
|
|
||||||
pp.meshPoints(),
|
|
||||||
maxPointLevel,
|
|
||||||
maxEqOp<label>(),
|
|
||||||
labelMin, // null value
|
|
||||||
false // no separation
|
|
||||||
);
|
|
||||||
|
|
||||||
|
// Rework patch-wise layer parameters into minimum per point
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
expansionRatio.setSize(pp.nPoints());
|
||||||
|
expansionRatio = GREAT;
|
||||||
|
scalarField finalLayerRatio(pp.nPoints(), GREAT);
|
||||||
|
scalarField relMinThickness(pp.nPoints(), GREAT);
|
||||||
|
|
||||||
|
{
|
||||||
|
forAll(patchIDs, i)
|
||||||
|
{
|
||||||
|
label patchI = patchIDs[i];
|
||||||
|
|
||||||
|
const labelList& meshPoints = patches[patchI].meshPoints();
|
||||||
|
|
||||||
|
forAll(meshPoints, patchPointI)
|
||||||
|
{
|
||||||
|
label ppPointI = pp.meshPointMap()[meshPoints[patchPointI]];
|
||||||
|
|
||||||
|
expansionRatio[ppPointI] = min
|
||||||
|
(
|
||||||
|
expansionRatio[ppPointI],
|
||||||
|
patchExpansionRatio[patchI]
|
||||||
|
);
|
||||||
|
finalLayerRatio[ppPointI] = min
|
||||||
|
(
|
||||||
|
finalLayerRatio[ppPointI],
|
||||||
|
patchFinalLayerRatio[patchI]
|
||||||
|
);
|
||||||
|
relMinThickness[ppPointI] = min
|
||||||
|
(
|
||||||
|
relMinThickness[ppPointI],
|
||||||
|
patchRelMinThickness[patchI]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
syncTools::syncPointList
|
||||||
|
(
|
||||||
|
mesh_,
|
||||||
|
pp.meshPoints(),
|
||||||
|
expansionRatio,
|
||||||
|
minEqOp<scalar>(),
|
||||||
|
GREAT, // null value
|
||||||
|
false // no separation
|
||||||
|
);
|
||||||
|
syncTools::syncPointList
|
||||||
|
(
|
||||||
|
mesh_,
|
||||||
|
pp.meshPoints(),
|
||||||
|
finalLayerRatio,
|
||||||
|
minEqOp<scalar>(),
|
||||||
|
GREAT, // null value
|
||||||
|
false // no separation
|
||||||
|
);
|
||||||
|
syncTools::syncPointList
|
||||||
|
(
|
||||||
|
mesh_,
|
||||||
|
pp.meshPoints(),
|
||||||
|
relMinThickness,
|
||||||
|
minEqOp<scalar>(),
|
||||||
|
GREAT, // null value
|
||||||
|
false // no separation
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Per mesh point the expansion parameters
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
thickness.setSize(pp.nPoints());
|
||||||
|
minThickness.setSize(pp.nPoints());
|
||||||
|
|
||||||
forAll(maxPointLevel, pointI)
|
forAll(maxPointLevel, pointI)
|
||||||
{
|
{
|
||||||
@ -1430,19 +1493,24 @@ void Foam::autoHexMeshDriver::calculateLayerThickness
|
|||||||
|
|
||||||
// Calculate layer thickness based on expansion ratio
|
// Calculate layer thickness based on expansion ratio
|
||||||
// and final layer height
|
// and final layer height
|
||||||
if (expansionRatio == 1)
|
if (expansionRatio[pointI] == 1)
|
||||||
{
|
{
|
||||||
thickness[pointI] = finalLayerRatio*patchNLayers[pointI]*edgeLen;
|
thickness[pointI] =
|
||||||
minThickness[pointI] = relMinThickness*edgeLen;
|
finalLayerRatio[pointI]
|
||||||
|
* patchNLayers[pointI]
|
||||||
|
* edgeLen;
|
||||||
|
minThickness[pointI] = relMinThickness[pointI]*edgeLen;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
scalar invExpansion = 1.0 / expansionRatio;
|
scalar invExpansion = 1.0 / expansionRatio[pointI];
|
||||||
label nLay = patchNLayers[pointI];
|
label nLay = patchNLayers[pointI];
|
||||||
thickness[pointI] = finalLayerRatio*edgeLen
|
thickness[pointI] =
|
||||||
* (1.0 - pow(invExpansion, nLay))
|
finalLayerRatio[pointI]
|
||||||
/ (1.0 - invExpansion);
|
* edgeLen
|
||||||
minThickness[pointI] = relMinThickness*edgeLen;
|
* (1.0 - pow(invExpansion, nLay))
|
||||||
|
/ (1.0 - invExpansion);
|
||||||
|
minThickness[pointI] = relMinThickness[pointI]*edgeLen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2309,31 +2377,34 @@ void Foam::autoHexMeshDriver::getLayerCellsFaces
|
|||||||
|
|
||||||
void Foam::autoHexMeshDriver::mergePatchFacesUndo
|
void Foam::autoHexMeshDriver::mergePatchFacesUndo
|
||||||
(
|
(
|
||||||
const dictionary& shrinkDict,
|
const layerParameters& layerParams,
|
||||||
const dictionary& motionDict
|
const dictionary& motionDict
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
const scalar featureAngle(readScalar(shrinkDict.lookup("featureAngle")));
|
scalar minCos = Foam::cos
|
||||||
scalar minCos = Foam::cos(featureAngle*mathematicalConstant::pi/180.0);
|
(
|
||||||
|
layerParams.featureAngle()
|
||||||
|
* mathematicalConstant::pi/180.0
|
||||||
|
);
|
||||||
|
|
||||||
scalar concaveAngle = defaultConcaveAngle;
|
scalar concaveCos = Foam::cos
|
||||||
|
(
|
||||||
if (shrinkDict.found("concaveAngle"))
|
layerParams.concaveAngle()
|
||||||
{
|
* mathematicalConstant::pi/180.0
|
||||||
concaveAngle = readScalar(shrinkDict.lookup("concaveAngle"));
|
);
|
||||||
}
|
|
||||||
scalar concaveCos = Foam::cos(concaveAngle*mathematicalConstant::pi/180.0);
|
|
||||||
|
|
||||||
Info<< nl
|
Info<< nl
|
||||||
<< "Merging all faces of a cell" << nl
|
<< "Merging all faces of a cell" << nl
|
||||||
<< "---------------------------" << nl
|
<< "---------------------------" << nl
|
||||||
<< " - which are on the same patch" << nl
|
<< " - which are on the same patch" << nl
|
||||||
<< " - which make an angle < " << featureAngle << " degrees"
|
<< " - which make an angle < " << layerParams.featureAngle()
|
||||||
|
<< " degrees"
|
||||||
<< nl
|
<< nl
|
||||||
<< " (cos:" << minCos << ')' << nl
|
<< " (cos:" << minCos << ')' << nl
|
||||||
<< " - as long as the resulting face doesn't become concave"
|
<< " - as long as the resulting face doesn't become concave"
|
||||||
<< " by more than "
|
<< " by more than "
|
||||||
<< concaveAngle << " degrees (0=straight, 180=fully concave)" << nl
|
<< layerParams.concaveAngle()
|
||||||
|
<< " degrees (0=straight, 180=fully concave)" << nl
|
||||||
<< endl;
|
<< endl;
|
||||||
|
|
||||||
label nChanged = mergePatchFacesUndo(minCos, concaveCos, motionDict);
|
label nChanged = mergePatchFacesUndo(minCos, concaveCos, motionDict);
|
||||||
@ -2344,80 +2415,18 @@ void Foam::autoHexMeshDriver::mergePatchFacesUndo
|
|||||||
|
|
||||||
void Foam::autoHexMeshDriver::addLayers
|
void Foam::autoHexMeshDriver::addLayers
|
||||||
(
|
(
|
||||||
const dictionary& shrinkDict,
|
const layerParameters& layerParams,
|
||||||
const dictionary& motionDict,
|
const dictionary& motionDict,
|
||||||
const label nAllowableErrors,
|
const label nAllowableErrors,
|
||||||
motionSmoother& meshMover
|
motionSmoother& meshMover
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Read some more dictionary settings
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
// Min thickness per cell
|
|
||||||
const scalar relMinThickness(readScalar(shrinkDict.lookup("minThickness")));
|
|
||||||
|
|
||||||
// Warped faces recoginition
|
|
||||||
const scalar maxFaceThicknessRatio
|
|
||||||
(
|
|
||||||
readScalar(shrinkDict.lookup("maxFaceThicknessRatio"))
|
|
||||||
);
|
|
||||||
const scalar featureAngle(readScalar(shrinkDict.lookup("featureAngle")));
|
|
||||||
|
|
||||||
// Feature angle
|
|
||||||
const scalar minCos = Foam::cos(featureAngle*mathematicalConstant::pi/180.);
|
|
||||||
|
|
||||||
// Number of layers for to grow non-extrusion region by
|
|
||||||
const label nGrow(readLabel(shrinkDict.lookup("nGrow")));
|
|
||||||
|
|
||||||
//const label nSmoothDisp(readLabel(shrinkDict.lookup("nSmoothDispl")));
|
|
||||||
// Snapping iterations
|
|
||||||
const label nSnap(readLabel(shrinkDict.lookup("nSnap")));
|
|
||||||
|
|
||||||
// Mesh termination and medial axis smoothing quantities
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
const scalar minCosLayerTermination =
|
|
||||||
Foam::cos(0.5*featureAngle*mathematicalConstant::pi/180.);
|
|
||||||
const scalar expansionRatio
|
|
||||||
(
|
|
||||||
readScalar(shrinkDict.lookup("expansionRatio"))
|
|
||||||
);
|
|
||||||
const scalar finalLayerRatio
|
|
||||||
(
|
|
||||||
readScalar(shrinkDict.lookup("finalLayerRatio"))
|
|
||||||
);
|
|
||||||
const label nBufferCellsNoExtrude
|
|
||||||
(
|
|
||||||
readLabel(shrinkDict.lookup("nBufferCellsNoExtrude"))
|
|
||||||
);
|
|
||||||
const label nSmoothSurfaceNormals
|
|
||||||
(
|
|
||||||
readLabel(shrinkDict.lookup("nSmoothSurfaceNormals"))
|
|
||||||
);
|
|
||||||
const label nSmoothNormals(readLabel(shrinkDict.lookup("nSmoothNormals")));
|
|
||||||
const label nSmoothThickness
|
|
||||||
(
|
|
||||||
readLabel(shrinkDict.lookup("nSmoothThickness"))
|
|
||||||
);
|
|
||||||
const scalar maxThicknessToMedialRatio
|
|
||||||
(
|
|
||||||
readScalar(shrinkDict.lookup("maxThicknessToMedialRatio"))
|
|
||||||
);
|
|
||||||
|
|
||||||
// Medial axis setup
|
|
||||||
|
|
||||||
const scalar minMedianAxisAngle
|
|
||||||
(
|
|
||||||
readScalar(shrinkDict.lookup("minMedianAxisAngle"))
|
|
||||||
);
|
|
||||||
const scalar minMedianAxisAngleCos =
|
|
||||||
Foam::cos(minMedianAxisAngle*mathematicalConstant::pi/180.);
|
|
||||||
|
|
||||||
|
|
||||||
// Precalculate mesh edge labels for patch edges
|
|
||||||
const indirectPrimitivePatch& pp = meshMover.patch();
|
const indirectPrimitivePatch& pp = meshMover.patch();
|
||||||
const labelList& meshPoints = pp.meshPoints();
|
const labelList& meshPoints = pp.meshPoints();
|
||||||
|
|
||||||
|
// Precalculate mesh edge labels for patch edges
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
labelList meshEdges(pp.nEdges());
|
labelList meshEdges(pp.nEdges());
|
||||||
forAll(pp.edges(), edgeI)
|
forAll(pp.edges(), edgeI)
|
||||||
{
|
{
|
||||||
@ -2449,8 +2458,9 @@ void Foam::autoHexMeshDriver::addLayers
|
|||||||
|
|
||||||
setNumLayers
|
setNumLayers
|
||||||
(
|
(
|
||||||
meshMover.adaptPatchIDs(),
|
layerParams.numLayers(), // per patch the num layers
|
||||||
pp,
|
meshMover.adaptPatchIDs(), // patches that are being moved
|
||||||
|
pp, // indirectpatch for all faces moving
|
||||||
|
|
||||||
patchDisp,
|
patchDisp,
|
||||||
patchNLayers,
|
patchNLayers,
|
||||||
@ -2477,7 +2487,7 @@ void Foam::autoHexMeshDriver::addLayers
|
|||||||
(
|
(
|
||||||
pp,
|
pp,
|
||||||
meshEdges,
|
meshEdges,
|
||||||
minCos,
|
layerParams.featureAngle()*mathematicalConstant::pi/180.0,
|
||||||
|
|
||||||
patchDisp,
|
patchDisp,
|
||||||
patchNLayers,
|
patchNLayers,
|
||||||
@ -2494,7 +2504,7 @@ void Foam::autoHexMeshDriver::addLayers
|
|||||||
handleWarpedFaces
|
handleWarpedFaces
|
||||||
(
|
(
|
||||||
pp,
|
pp,
|
||||||
maxFaceThicknessRatio,
|
layerParams.maxFaceThicknessRatio(),
|
||||||
edge0Len,
|
edge0Len,
|
||||||
cellLevel,
|
cellLevel,
|
||||||
|
|
||||||
@ -2517,7 +2527,7 @@ void Foam::autoHexMeshDriver::addLayers
|
|||||||
|
|
||||||
|
|
||||||
// Grow out region of non-extrusion
|
// Grow out region of non-extrusion
|
||||||
for (label i = 0; i < nGrow; i++)
|
for (label i = 0; i < layerParams.nGrow(); i++)
|
||||||
{
|
{
|
||||||
growNoExtrusion
|
growNoExtrusion
|
||||||
(
|
(
|
||||||
@ -2528,21 +2538,24 @@ void Foam::autoHexMeshDriver::addLayers
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine point-wise layer thickness
|
// Determine (wanted) point-wise layer thickness and expansion ratio
|
||||||
scalarField thickness(pp.nPoints());
|
scalarField thickness(pp.nPoints());
|
||||||
scalarField minThickness(pp.nPoints());
|
scalarField minThickness(pp.nPoints());
|
||||||
|
scalarField expansionRatio(pp.nPoints());
|
||||||
calculateLayerThickness
|
calculateLayerThickness
|
||||||
(
|
(
|
||||||
expansionRatio,
|
|
||||||
finalLayerRatio,
|
|
||||||
relMinThickness,
|
|
||||||
pp,
|
pp,
|
||||||
|
meshMover.adaptPatchIDs(),
|
||||||
|
layerParams.expansionRatio(),
|
||||||
|
layerParams.finalLayerRatio(),
|
||||||
|
layerParams.minThickness(),
|
||||||
cellLevel,
|
cellLevel,
|
||||||
patchNLayers,
|
patchNLayers,
|
||||||
edge0Len,
|
edge0Len,
|
||||||
|
|
||||||
thickness,
|
thickness,
|
||||||
minThickness
|
minThickness,
|
||||||
|
expansionRatio
|
||||||
);
|
);
|
||||||
|
|
||||||
// Calculate wall to medial axis distance for smoothing displacement
|
// Calculate wall to medial axis distance for smoothing displacement
|
||||||
@ -2602,9 +2615,9 @@ void Foam::autoHexMeshDriver::addLayers
|
|||||||
medialAxisSmoothingInfo
|
medialAxisSmoothingInfo
|
||||||
(
|
(
|
||||||
meshMover,
|
meshMover,
|
||||||
nSmoothNormals,
|
layerParams.nSmoothNormals(),
|
||||||
nSmoothSurfaceNormals,
|
layerParams.nSmoothSurfaceNormals(),
|
||||||
minMedianAxisAngleCos,
|
layerParams.minMedianAxisAngleCos(),
|
||||||
|
|
||||||
dispVec,
|
dispVec,
|
||||||
medialRatio,
|
medialRatio,
|
||||||
@ -2657,8 +2670,8 @@ void Foam::autoHexMeshDriver::addLayers
|
|||||||
// debug,
|
// debug,
|
||||||
// meshMover,
|
// meshMover,
|
||||||
// -patchDisp, // Shrink in opposite direction of addedPoints
|
// -patchDisp, // Shrink in opposite direction of addedPoints
|
||||||
// nSmoothDisp,
|
// layerParams.nSmoothDisp(),
|
||||||
// nSnap
|
// layerParams.nSnap()
|
||||||
//);
|
//);
|
||||||
|
|
||||||
// Medial axis based shrinking
|
// Medial axis based shrinking
|
||||||
@ -2666,11 +2679,11 @@ void Foam::autoHexMeshDriver::addLayers
|
|||||||
(
|
(
|
||||||
meshMover,
|
meshMover,
|
||||||
|
|
||||||
nSmoothThickness,
|
layerParams.nSmoothThickness(),
|
||||||
maxThicknessToMedialRatio,
|
layerParams.maxThicknessToMedialRatio(),
|
||||||
nAllowableErrors,
|
nAllowableErrors,
|
||||||
nSnap,
|
layerParams.nSnap(),
|
||||||
minCosLayerTermination,
|
layerParams.layerTerminationCos(),
|
||||||
|
|
||||||
thickness,
|
thickness,
|
||||||
minThickness,
|
minThickness,
|
||||||
@ -2735,7 +2748,7 @@ void Foam::autoHexMeshDriver::addLayers
|
|||||||
meshMover,
|
meshMover,
|
||||||
patchNLayers,
|
patchNLayers,
|
||||||
extrudeStatus,
|
extrudeStatus,
|
||||||
nBufferCellsNoExtrude,
|
layerParams.nBufferCellsNoExtrude(),
|
||||||
nPatchPointLayers,
|
nPatchPointLayers,
|
||||||
nPatchFaceLayers
|
nPatchFaceLayers
|
||||||
);
|
);
|
||||||
@ -2747,7 +2760,7 @@ void Foam::autoHexMeshDriver::addLayers
|
|||||||
{
|
{
|
||||||
if (patchNLayers[i] > 0)
|
if (patchNLayers[i] > 0)
|
||||||
{
|
{
|
||||||
if (expansionRatio == 1.0)
|
if (expansionRatio[i] == 1.0)
|
||||||
{
|
{
|
||||||
firstDisp[i] = patchDisp[i]/nPatchPointLayers[i];
|
firstDisp[i] = patchDisp[i]/nPatchPointLayers[i];
|
||||||
}
|
}
|
||||||
@ -2755,15 +2768,15 @@ void Foam::autoHexMeshDriver::addLayers
|
|||||||
{
|
{
|
||||||
label nLay = nPatchPointLayers[i];
|
label nLay = nPatchPointLayers[i];
|
||||||
scalar h =
|
scalar h =
|
||||||
pow(expansionRatio,nLay - 1)
|
pow(expansionRatio[i], nLay - 1)
|
||||||
* (mag(patchDisp[i])*(1.0 - expansionRatio))
|
* (mag(patchDisp[i])*(1.0 - expansionRatio[i]))
|
||||||
/ (1.0 - pow(expansionRatio, nLay));
|
/ (1.0 - pow(expansionRatio[i], nLay));
|
||||||
firstDisp[i] = h/mag(patchDisp[i])*patchDisp[i];
|
firstDisp[i] = h/mag(patchDisp[i])*patchDisp[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scalar invExpansionRatio = 1.0 / expansionRatio;
|
scalarField invExpansionRatio = 1.0 / expansionRatio;
|
||||||
|
|
||||||
// Add topo regardless of whether extrudeStatus is extruderemove.
|
// Add topo regardless of whether extrudeStatus is extruderemove.
|
||||||
// Not add layer if patchDisp is zero.
|
// Not add layer if patchDisp is zero.
|
||||||
|
|||||||
@ -37,6 +37,7 @@ Description
|
|||||||
#include "pointEdgePoint.H"
|
#include "pointEdgePoint.H"
|
||||||
#include "PointEdgeWave.H"
|
#include "PointEdgeWave.H"
|
||||||
#include "mergePoints.H"
|
#include "mergePoints.H"
|
||||||
|
#include "snapParameters.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -95,8 +96,7 @@ Foam::Map<Foam::label> Foam::autoHexMeshDriver::getZoneBafflePatches
|
|||||||
label patchI = globalToPatch_[surfaces().globalRegion(surfI, 0)];
|
label patchI = globalToPatch_[surfaces().globalRegion(surfI, 0)];
|
||||||
|
|
||||||
Info<< "For surface "
|
Info<< "For surface "
|
||||||
<< surfaces()[surfI].IOobject::name()
|
<< surfaces().names()[surfI]
|
||||||
//<< surfaces().names()[surfI]
|
|
||||||
<< " found faceZone " << fZone.name()
|
<< " found faceZone " << fZone.name()
|
||||||
<< " and patch " << mesh_.boundaryMesh()[patchI].name()
|
<< " and patch " << mesh_.boundaryMesh()[patchI].name()
|
||||||
<< endl;
|
<< endl;
|
||||||
@ -712,8 +712,8 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::autoHexMeshDriver::createZoneBaffles
|
|||||||
if (debug_)
|
if (debug_)
|
||||||
{
|
{
|
||||||
const_cast<Time&>(mesh_.time())++;
|
const_cast<Time&>(mesh_.time())++;
|
||||||
Pout<< "Writing baffled mesh to time " << mesh_.time().timeName()
|
Pout<< "Writing baffled mesh to time "
|
||||||
<< endl;
|
<< mesh_.time().timeName() << endl;
|
||||||
mesh_.write();
|
mesh_.write();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -755,14 +755,10 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::autoHexMeshDriver::mergeZoneBaffles
|
|||||||
|
|
||||||
Foam::scalarField Foam::autoHexMeshDriver::calcSnapDistance
|
Foam::scalarField Foam::autoHexMeshDriver::calcSnapDistance
|
||||||
(
|
(
|
||||||
const dictionary& snapDict,
|
const snapParameters& snapParams,
|
||||||
const indirectPrimitivePatch& pp
|
const indirectPrimitivePatch& pp
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
// When to snap
|
|
||||||
scalar snapTol(readScalar(snapDict.lookup("snapTol")));
|
|
||||||
|
|
||||||
|
|
||||||
const edgeList& edges = pp.edges();
|
const edgeList& edges = pp.edges();
|
||||||
const labelListList& pointEdges = pp.pointEdges();
|
const labelListList& pointEdges = pp.pointEdges();
|
||||||
const pointField& localPoints = pp.localPoints();
|
const pointField& localPoints = pp.localPoints();
|
||||||
@ -793,7 +789,7 @@ Foam::scalarField Foam::autoHexMeshDriver::calcSnapDistance
|
|||||||
false // no separation
|
false // no separation
|
||||||
);
|
);
|
||||||
|
|
||||||
return snapTol*maxEdgeLen;
|
return snapParams.snapTol()*maxEdgeLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -801,7 +797,7 @@ Foam::scalarField Foam::autoHexMeshDriver::calcSnapDistance
|
|||||||
Foam::labelList Foam::autoHexMeshDriver::getSurfacePatches() const
|
Foam::labelList Foam::autoHexMeshDriver::getSurfacePatches() const
|
||||||
{
|
{
|
||||||
// Set of patches originating from surface
|
// Set of patches originating from surface
|
||||||
labelHashSet surfacePatchSet(surfaces().size());
|
labelHashSet surfacePatchSet(globalToPatch_.size());
|
||||||
|
|
||||||
forAll(globalToPatch_, i)
|
forAll(globalToPatch_, i)
|
||||||
{
|
{
|
||||||
@ -826,21 +822,21 @@ Foam::labelList Foam::autoHexMeshDriver::getSurfacePatches() const
|
|||||||
|
|
||||||
void Foam::autoHexMeshDriver::preSmoothPatch
|
void Foam::autoHexMeshDriver::preSmoothPatch
|
||||||
(
|
(
|
||||||
const dictionary& snapDict,
|
const snapParameters& snapParams,
|
||||||
const label nInitErrors,
|
const label nInitErrors,
|
||||||
const List<labelPair>& baffles,
|
const List<labelPair>& baffles,
|
||||||
motionSmoother& meshMover
|
motionSmoother& meshMover
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
// Smoothing iterations
|
|
||||||
label nSmoothPatch(readLabel(snapDict.lookup("nSmoothPatch")));
|
|
||||||
// Snapping iterations
|
|
||||||
label nSnap(readLabel(snapDict.lookup("nSnap")));
|
|
||||||
|
|
||||||
labelList checkFaces;
|
labelList checkFaces;
|
||||||
|
|
||||||
Info<< "Smoothing patch points ..." << endl;
|
Info<< "Smoothing patch points ..." << endl;
|
||||||
for (label smoothIter = 0; smoothIter < nSmoothPatch; smoothIter++)
|
for
|
||||||
|
(
|
||||||
|
label smoothIter = 0;
|
||||||
|
smoothIter < snapParams.nSmoothPatch();
|
||||||
|
smoothIter++
|
||||||
|
)
|
||||||
{
|
{
|
||||||
Info<< "Smoothing iteration " << smoothIter << endl;
|
Info<< "Smoothing iteration " << smoothIter << endl;
|
||||||
checkFaces.setSize(mesh_.nFaces());
|
checkFaces.setSize(mesh_.nFaces());
|
||||||
@ -857,11 +853,11 @@ void Foam::autoHexMeshDriver::preSmoothPatch
|
|||||||
|
|
||||||
scalar oldErrorReduction = -1;
|
scalar oldErrorReduction = -1;
|
||||||
|
|
||||||
for (label snapIter = 0; snapIter < 2*nSnap; snapIter++)
|
for (label snapIter = 0; snapIter < 2*snapParams.nSnap(); snapIter++)
|
||||||
{
|
{
|
||||||
Info<< nl << "Scaling iteration " << snapIter << endl;
|
Info<< nl << "Scaling iteration " << snapIter << endl;
|
||||||
|
|
||||||
if (snapIter == nSnap)
|
if (snapIter == snapParams.nSnap())
|
||||||
{
|
{
|
||||||
Info<< "Displacement scaling for error reduction set to 0."
|
Info<< "Displacement scaling for error reduction set to 0."
|
||||||
<< endl;
|
<< endl;
|
||||||
@ -901,6 +897,56 @@ void Foam::autoHexMeshDriver::preSmoothPatch
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Get (pp-local) indices of points that are both on zone and on patched surface
|
||||||
|
Foam::labelList Foam::autoHexMeshDriver::getZoneSurfacePoints
|
||||||
|
(
|
||||||
|
const indirectPrimitivePatch& pp,
|
||||||
|
const word& zoneName
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
label zoneI = mesh_.faceZones().findZoneID(zoneName);
|
||||||
|
|
||||||
|
if (zoneI == -1)
|
||||||
|
{
|
||||||
|
FatalErrorIn
|
||||||
|
(
|
||||||
|
"autoHexMeshDriver::getZoneSurfacePoints"
|
||||||
|
"(const indirectPrimitivePatch&, const word&)"
|
||||||
|
) << "Cannot find zone " << zoneName
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
const faceZone& fZone = mesh_.faceZones()[zoneI];
|
||||||
|
|
||||||
|
|
||||||
|
// Could use PrimitivePatch & localFaces to extract points but might just
|
||||||
|
// as well do it ourselves.
|
||||||
|
|
||||||
|
boolList pointOnZone(pp.nPoints(), false);
|
||||||
|
|
||||||
|
forAll(fZone, i)
|
||||||
|
{
|
||||||
|
const face& f = mesh_.faces()[fZone[i]];
|
||||||
|
|
||||||
|
forAll(f, fp)
|
||||||
|
{
|
||||||
|
label meshPointI = f[fp];
|
||||||
|
|
||||||
|
Map<label>::const_iterator iter =
|
||||||
|
pp.meshPointMap().find(meshPointI);
|
||||||
|
|
||||||
|
if (iter != pp.meshPointMap().end())
|
||||||
|
{
|
||||||
|
label pointI = iter();
|
||||||
|
pointOnZone[pointI] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return findIndices(pointOnZone, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::vectorField Foam::autoHexMeshDriver::calcNearestSurface
|
Foam::vectorField Foam::autoHexMeshDriver::calcNearestSurface
|
||||||
(
|
(
|
||||||
const scalarField& snapDist,
|
const scalarField& snapDist,
|
||||||
@ -925,33 +971,40 @@ Foam::vectorField Foam::autoHexMeshDriver::calcNearestSurface
|
|||||||
// 1. All points to non-interface surfaces
|
// 1. All points to non-interface surfaces
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
forAll(localPoints, pointI)
|
|
||||||
{
|
{
|
||||||
pointIndexHit pHit;
|
List<pointIndexHit> hitInfo;
|
||||||
|
labelList hitSurface;
|
||||||
label surfI = surfaces().findNearest
|
surfaces().findNearest
|
||||||
(
|
(
|
||||||
unzonedSurfaces,
|
unzonedSurfaces,
|
||||||
localPoints[pointI],
|
localPoints,
|
||||||
sqr(4*snapDist[pointI]), // sqr of attract distance
|
sqr(4*snapDist), // sqr of attract distance
|
||||||
pHit
|
hitSurface,
|
||||||
|
hitInfo
|
||||||
);
|
);
|
||||||
|
|
||||||
if (surfI != -1)
|
forAll(hitInfo, pointI)
|
||||||
{
|
{
|
||||||
patchDisp[pointI] = pHit.hitPoint() - localPoints[pointI];
|
if (hitInfo[pointI].hit())
|
||||||
|
{
|
||||||
|
patchDisp[pointI] =
|
||||||
|
hitInfo[pointI].hitPoint()
|
||||||
|
- localPoints[pointI];
|
||||||
|
}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// WarningIn("autoHexMeshDriver::calcNearestSurface(..)")
|
||||||
|
// << "For point:" << pointI
|
||||||
|
// << " coordinate:" << localPoints[pointI]
|
||||||
|
// << " did not find any surface within:"
|
||||||
|
// << 4*snapDist[pointI]
|
||||||
|
// << " meter." << endl;
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// WarningIn("autoHexMeshDriver::calcNearestSurface(..)")
|
|
||||||
// << "For point:" << pointI
|
|
||||||
// << " coordinate:" << localPoints[pointI]
|
|
||||||
// << " did not find any surface within:" << 4*snapDist[pointI]
|
|
||||||
// << " meter." << endl;
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 2. All points on zones to their respective surface
|
// 2. All points on zones to their respective surface
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
@ -964,50 +1017,50 @@ Foam::vectorField Foam::autoHexMeshDriver::calcNearestSurface
|
|||||||
|
|
||||||
const labelList surfacesToTest(1, zoneSurfI);
|
const labelList surfacesToTest(1, zoneSurfI);
|
||||||
|
|
||||||
label zoneI = mesh_.faceZones().findZoneID(faceZoneNames[zoneSurfI]);
|
// Get indices of points both on faceZone and on pp.
|
||||||
|
labelList zonePointIndices
|
||||||
|
(
|
||||||
|
getZoneSurfacePoints
|
||||||
|
(
|
||||||
|
pp,
|
||||||
|
faceZoneNames[zoneSurfI]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
const faceZone& fZone = mesh_.faceZones()[zoneI];
|
pointField zonePoints(zonePointIndices.size());
|
||||||
|
forAll(zonePointIndices, i)
|
||||||
forAll(fZone, i)
|
|
||||||
{
|
{
|
||||||
const face& f = mesh_.faces()[fZone[i]];
|
zonePoints[i] = localPoints[zonePointIndices[i]];
|
||||||
|
}
|
||||||
|
|
||||||
forAll(f, fp)
|
// Find nearest for points both on faceZone and pp.
|
||||||
|
List<pointIndexHit> hitInfo;
|
||||||
|
labelList hitSurface;
|
||||||
|
surfaces().findNearest
|
||||||
|
(
|
||||||
|
labelList(1, zoneSurfI),
|
||||||
|
zonePoints,
|
||||||
|
sqr(4*snapDist),
|
||||||
|
hitSurface,
|
||||||
|
hitInfo
|
||||||
|
);
|
||||||
|
|
||||||
|
forAll(hitInfo, pointI)
|
||||||
|
{
|
||||||
|
if (hitInfo[pointI].hit())
|
||||||
{
|
{
|
||||||
label meshPointI = f[fp];
|
patchDisp[pointI] =
|
||||||
|
hitInfo[pointI].hitPoint()
|
||||||
Map<label>::const_iterator iter =
|
- localPoints[pointI];
|
||||||
pp.meshPointMap().find(meshPointI);
|
}
|
||||||
|
else
|
||||||
if (iter != pp.meshPointMap().end())
|
{
|
||||||
{
|
WarningIn("autoHexMeshDriver::calcNearestSurface(..)")
|
||||||
label pointI = iter();
|
<< "For point:" << pointI
|
||||||
|
<< " coordinate:" << localPoints[pointI]
|
||||||
pointIndexHit pHit;
|
<< " did not find any surface within:"
|
||||||
|
<< 4*snapDist[pointI]
|
||||||
label surfI = surfaces().findNearest
|
<< " meter." << endl;
|
||||||
(
|
|
||||||
surfacesToTest,
|
|
||||||
localPoints[pointI],
|
|
||||||
sqr(4*snapDist[pointI]), // sqr of attract distance
|
|
||||||
pHit
|
|
||||||
);
|
|
||||||
|
|
||||||
if (surfI != -1)
|
|
||||||
{
|
|
||||||
patchDisp[pointI] =
|
|
||||||
pHit.hitPoint() - localPoints[pointI];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
WarningIn("autoHexMeshDriver::calcNearestSurface(..)")
|
|
||||||
<< "For point:" << pointI
|
|
||||||
<< " coordinate:" << localPoints[pointI]
|
|
||||||
<< " did not find any surface within:"
|
|
||||||
<< 4*snapDist[pointI]
|
|
||||||
<< " meter." << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1078,7 +1131,7 @@ Foam::vectorField Foam::autoHexMeshDriver::calcNearestSurface
|
|||||||
|
|
||||||
void Foam::autoHexMeshDriver::smoothDisplacement
|
void Foam::autoHexMeshDriver::smoothDisplacement
|
||||||
(
|
(
|
||||||
const dictionary& snapDict,
|
const snapParameters& snapParams,
|
||||||
motionSmoother& meshMover
|
motionSmoother& meshMover
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
@ -1087,9 +1140,6 @@ void Foam::autoHexMeshDriver::smoothDisplacement
|
|||||||
|
|
||||||
Info<< "Smoothing displacement ..." << endl;
|
Info<< "Smoothing displacement ..." << endl;
|
||||||
|
|
||||||
// Smoothing iterations
|
|
||||||
label nSmoothDisp(readLabel(snapDict.lookup("nSmoothDispl")));
|
|
||||||
|
|
||||||
// Set edge diffusivity as inverse of distance to patch
|
// Set edge diffusivity as inverse of distance to patch
|
||||||
scalarField edgeGamma(1.0/(edgePatchDist(pMesh, pp) + SMALL));
|
scalarField edgeGamma(1.0/(edgePatchDist(pMesh, pp) + SMALL));
|
||||||
//scalarField edgeGamma(mesh_.nEdges(), 1.0);
|
//scalarField edgeGamma(mesh_.nEdges(), 1.0);
|
||||||
@ -1098,7 +1148,7 @@ void Foam::autoHexMeshDriver::smoothDisplacement
|
|||||||
// Get displacement field
|
// Get displacement field
|
||||||
pointVectorField& disp = meshMover.displacement();
|
pointVectorField& disp = meshMover.displacement();
|
||||||
|
|
||||||
for (label iter = 0; iter < nSmoothDisp; iter++)
|
for (label iter = 0; iter < snapParams.nSmoothDispl(); iter++)
|
||||||
{
|
{
|
||||||
if ((iter % 10) == 0)
|
if ((iter % 10) == 0)
|
||||||
{
|
{
|
||||||
@ -1140,16 +1190,12 @@ void Foam::autoHexMeshDriver::smoothDisplacement
|
|||||||
|
|
||||||
void Foam::autoHexMeshDriver::scaleMesh
|
void Foam::autoHexMeshDriver::scaleMesh
|
||||||
(
|
(
|
||||||
const dictionary& snapDict,
|
const snapParameters& snapParams,
|
||||||
const label nInitErrors,
|
const label nInitErrors,
|
||||||
const List<labelPair>& baffles,
|
const List<labelPair>& baffles,
|
||||||
motionSmoother& meshMover
|
motionSmoother& meshMover
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Snapping iterations
|
|
||||||
label nSnap(readLabel(snapDict.lookup("nSnap")));
|
|
||||||
|
|
||||||
|
|
||||||
// Relax displacement until correct mesh
|
// Relax displacement until correct mesh
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
labelList checkFaces(identity(mesh_.nFaces()));
|
labelList checkFaces(identity(mesh_.nFaces()));
|
||||||
@ -1157,11 +1203,11 @@ void Foam::autoHexMeshDriver::scaleMesh
|
|||||||
scalar oldErrorReduction = -1;
|
scalar oldErrorReduction = -1;
|
||||||
|
|
||||||
Info<< "Moving mesh ..." << endl;
|
Info<< "Moving mesh ..." << endl;
|
||||||
for (label iter = 0; iter < 2*nSnap; iter++)
|
for (label iter = 0; iter < 2*snapParams.nSnap(); iter++)
|
||||||
{
|
{
|
||||||
Info<< nl << "Iteration " << iter << endl;
|
Info<< nl << "Iteration " << iter << endl;
|
||||||
|
|
||||||
if (iter == nSnap)
|
if (iter == snapParams.nSnap())
|
||||||
{
|
{
|
||||||
Info<< "Displacement scaling for error reduction set to 0." << endl;
|
Info<< "Displacement scaling for error reduction set to 0." << endl;
|
||||||
oldErrorReduction = meshMover.setErrorReduction(0.0);
|
oldErrorReduction = meshMover.setErrorReduction(0.0);
|
||||||
|
|||||||
@ -0,0 +1,213 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 1991-2008 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 2 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, write to the Free Software Foundation,
|
||||||
|
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "layerParameters.H"
|
||||||
|
#include "polyBoundaryMesh.H"
|
||||||
|
#include "mathematicalConstants.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
const Foam::scalar Foam::layerParameters::defaultConcaveAngle = 90;
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
// Construct from dictionary
|
||||||
|
Foam::layerParameters::layerParameters
|
||||||
|
(
|
||||||
|
const dictionary& dict,
|
||||||
|
const labelList& numLayers
|
||||||
|
)
|
||||||
|
:
|
||||||
|
numLayers_(numLayers),
|
||||||
|
expansionRatio_
|
||||||
|
(
|
||||||
|
numLayers_.size(),
|
||||||
|
readScalar(dict.lookup("expansionRatio"))
|
||||||
|
),
|
||||||
|
finalLayerRatio_
|
||||||
|
(
|
||||||
|
numLayers_.size(),
|
||||||
|
readScalar(dict.lookup("finalLayerRatio"))
|
||||||
|
),
|
||||||
|
minThickness_
|
||||||
|
(
|
||||||
|
numLayers_.size(),
|
||||||
|
readScalar(dict.lookup("minThickness"))
|
||||||
|
),
|
||||||
|
featureAngle_(readScalar(dict.lookup("featureAngle"))),
|
||||||
|
concaveAngle_
|
||||||
|
(
|
||||||
|
dict.found("concaveAngle")
|
||||||
|
? readScalar(dict.lookup("concaveAngle"))
|
||||||
|
: defaultConcaveAngle
|
||||||
|
),
|
||||||
|
nGrow_(readLabel(dict.lookup("nGrow"))),
|
||||||
|
nSmoothSurfaceNormals_
|
||||||
|
(
|
||||||
|
readLabel(dict.lookup("nSmoothSurfaceNormals"))
|
||||||
|
),
|
||||||
|
nSmoothNormals_(readLabel(dict.lookup("nSmoothNormals"))),
|
||||||
|
nSmoothThickness_(readLabel(dict.lookup("nSmoothThickness"))),
|
||||||
|
maxFaceThicknessRatio_
|
||||||
|
(
|
||||||
|
readScalar(dict.lookup("maxFaceThicknessRatio"))
|
||||||
|
),
|
||||||
|
layerTerminationCos_
|
||||||
|
(
|
||||||
|
Foam::cos
|
||||||
|
(
|
||||||
|
0.5
|
||||||
|
* featureAngle_
|
||||||
|
* mathematicalConstant::pi/180.
|
||||||
|
)
|
||||||
|
),
|
||||||
|
maxThicknessToMedialRatio_
|
||||||
|
(
|
||||||
|
readScalar(dict.lookup("maxThicknessToMedialRatio"))
|
||||||
|
),
|
||||||
|
minMedianAxisAngleCos_
|
||||||
|
(
|
||||||
|
Foam::cos(readScalar(dict.lookup("minMedianAxisAngle")))
|
||||||
|
* mathematicalConstant::pi/180.
|
||||||
|
),
|
||||||
|
nBufferCellsNoExtrude_
|
||||||
|
(
|
||||||
|
readLabel(dict.lookup("nBufferCellsNoExtrude"))
|
||||||
|
),
|
||||||
|
nSnap_(readLabel(dict.lookup("nSnap")))
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
// Construct from dictionary
|
||||||
|
Foam::layerParameters::layerParameters
|
||||||
|
(
|
||||||
|
const dictionary& dict,
|
||||||
|
const polyBoundaryMesh& boundaryMesh
|
||||||
|
)
|
||||||
|
:
|
||||||
|
numLayers_(boundaryMesh.size(), 0),
|
||||||
|
expansionRatio_
|
||||||
|
(
|
||||||
|
boundaryMesh.size(),
|
||||||
|
readScalar(dict.lookup("expansionRatio"))
|
||||||
|
),
|
||||||
|
finalLayerRatio_
|
||||||
|
(
|
||||||
|
boundaryMesh.size(),
|
||||||
|
readScalar(dict.lookup("finalLayerRatio"))
|
||||||
|
),
|
||||||
|
minThickness_
|
||||||
|
(
|
||||||
|
boundaryMesh.size(),
|
||||||
|
readScalar(dict.lookup("minThickness"))
|
||||||
|
),
|
||||||
|
featureAngle_(readScalar(dict.lookup("featureAngle"))),
|
||||||
|
concaveAngle_
|
||||||
|
(
|
||||||
|
dict.found("concaveAngle")
|
||||||
|
? readScalar(dict.lookup("concaveAngle"))
|
||||||
|
: defaultConcaveAngle
|
||||||
|
),
|
||||||
|
nGrow_(readLabel(dict.lookup("nGrow"))),
|
||||||
|
nSmoothSurfaceNormals_
|
||||||
|
(
|
||||||
|
readLabel(dict.lookup("nSmoothSurfaceNormals"))
|
||||||
|
),
|
||||||
|
nSmoothNormals_(readLabel(dict.lookup("nSmoothNormals"))),
|
||||||
|
nSmoothThickness_(readLabel(dict.lookup("nSmoothThickness"))),
|
||||||
|
maxFaceThicknessRatio_
|
||||||
|
(
|
||||||
|
readScalar(dict.lookup("maxFaceThicknessRatio"))
|
||||||
|
),
|
||||||
|
layerTerminationCos_
|
||||||
|
(
|
||||||
|
Foam::cos
|
||||||
|
(
|
||||||
|
0.5
|
||||||
|
* featureAngle_
|
||||||
|
* mathematicalConstant::pi/180.
|
||||||
|
)
|
||||||
|
),
|
||||||
|
maxThicknessToMedialRatio_
|
||||||
|
(
|
||||||
|
readScalar(dict.lookup("maxThicknessToMedialRatio"))
|
||||||
|
),
|
||||||
|
minMedianAxisAngleCos_
|
||||||
|
(
|
||||||
|
Foam::cos(readScalar(dict.lookup("minMedianAxisAngle")))
|
||||||
|
* mathematicalConstant::pi/180.
|
||||||
|
),
|
||||||
|
nBufferCellsNoExtrude_
|
||||||
|
(
|
||||||
|
readLabel(dict.lookup("nBufferCellsNoExtrude"))
|
||||||
|
),
|
||||||
|
nSnap_(readLabel(dict.lookup("nRelaxIter")))
|
||||||
|
{
|
||||||
|
const dictionary& layersDict = dict.subDict("layers");
|
||||||
|
|
||||||
|
forAllConstIter(dictionary, layersDict, iter)
|
||||||
|
{
|
||||||
|
const word& key = iter().keyword();
|
||||||
|
|
||||||
|
if (layersDict.isDict(key))
|
||||||
|
{
|
||||||
|
label patchI = boundaryMesh.findPatchID(key);
|
||||||
|
|
||||||
|
if (patchI == -1)
|
||||||
|
{
|
||||||
|
FatalErrorIn
|
||||||
|
(
|
||||||
|
"layerParameters::layerParameters"
|
||||||
|
"(const dictionary&, const polyBoundaryMesh&)"
|
||||||
|
) << "Specified illegal patch " << key
|
||||||
|
<< " in layer dictionary." << endl
|
||||||
|
<< "Valid patch names are " << boundaryMesh.names()
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
const dictionary& layerDict = layersDict.subDict(key);
|
||||||
|
|
||||||
|
numLayers_[patchI] =
|
||||||
|
readLabel(layerDict.lookup("nSurfaceLayers"));
|
||||||
|
|
||||||
|
//- Patch-wise layer parameters disabled for now. Just remove
|
||||||
|
// settings in initialiser list and uncomment below.
|
||||||
|
//expansionRatio_[patchI] =
|
||||||
|
// readScalar(layerDict.lookup("expansionRatio"));
|
||||||
|
//finalLayerRatio_[patchI] =
|
||||||
|
// readScalar(layerDict.lookup("finalLayerRatio"));
|
||||||
|
//minThickness_[patchI] =
|
||||||
|
// readScalar(layerDict.lookup("minThickness"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,246 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 1991-2008 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 2 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, write to the Free Software Foundation,
|
||||||
|
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::layerParameters
|
||||||
|
|
||||||
|
Description
|
||||||
|
Simple container to keep together layer specific information.
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
layerParameters.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef layerParameters_H
|
||||||
|
#define layerParameters_H
|
||||||
|
|
||||||
|
#include "dictionary.H"
|
||||||
|
#include "scalarField.H"
|
||||||
|
#include "labelList.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// Class forward declarations
|
||||||
|
class polyBoundaryMesh;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class layerParameters Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class layerParameters
|
||||||
|
{
|
||||||
|
// Static data members
|
||||||
|
|
||||||
|
//- Default angle for faces to be convcave
|
||||||
|
static const scalar defaultConcaveAngle;
|
||||||
|
|
||||||
|
|
||||||
|
// Private data
|
||||||
|
|
||||||
|
// Per patch (not region!) information
|
||||||
|
|
||||||
|
//- How many layers to add.
|
||||||
|
labelList numLayers_;
|
||||||
|
|
||||||
|
scalarField expansionRatio_;
|
||||||
|
|
||||||
|
//- 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.
|
||||||
|
scalarField finalLayerRatio_;
|
||||||
|
|
||||||
|
//- 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.
|
||||||
|
scalarField minThickness_;
|
||||||
|
|
||||||
|
|
||||||
|
scalar featureAngle_;
|
||||||
|
|
||||||
|
scalar concaveAngle_;
|
||||||
|
|
||||||
|
label nGrow_;
|
||||||
|
|
||||||
|
label nSmoothSurfaceNormals_;
|
||||||
|
|
||||||
|
label nSmoothNormals_;
|
||||||
|
|
||||||
|
label nSmoothThickness_;
|
||||||
|
|
||||||
|
scalar maxFaceThicknessRatio_;
|
||||||
|
|
||||||
|
scalar layerTerminationCos_;
|
||||||
|
|
||||||
|
scalar maxThicknessToMedialRatio_;
|
||||||
|
|
||||||
|
scalar minMedianAxisAngleCos_;
|
||||||
|
|
||||||
|
label nBufferCellsNoExtrude_;
|
||||||
|
|
||||||
|
label nSnap_;
|
||||||
|
|
||||||
|
|
||||||
|
// Private Member Functions
|
||||||
|
|
||||||
|
//- Disallow default bitwise copy construct
|
||||||
|
layerParameters(const layerParameters&);
|
||||||
|
|
||||||
|
//- Disallow default bitwise assignment
|
||||||
|
void operator=(const layerParameters&);
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct from dictionary - old syntax
|
||||||
|
layerParameters(const dictionary& dict, const labelList& numLayers);
|
||||||
|
|
||||||
|
//- Construct from dictionary - new syntax
|
||||||
|
layerParameters(const dictionary& dict, const polyBoundaryMesh&);
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
// Access
|
||||||
|
|
||||||
|
// Per patch information
|
||||||
|
|
||||||
|
//- How many layers to add.
|
||||||
|
const labelList& numLayers() const
|
||||||
|
{
|
||||||
|
return numLayers_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expansion factor for layer mesh
|
||||||
|
const scalarField& expansionRatio() const
|
||||||
|
{
|
||||||
|
return expansionRatio_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- 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.
|
||||||
|
const scalarField& finalLayerRatio() const
|
||||||
|
{
|
||||||
|
return finalLayerRatio_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- 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.
|
||||||
|
const scalarField& minThickness() const
|
||||||
|
{
|
||||||
|
return minThickness_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
scalar featureAngle() const
|
||||||
|
{
|
||||||
|
return featureAngle_;
|
||||||
|
}
|
||||||
|
|
||||||
|
scalar concaveAngle() const
|
||||||
|
{
|
||||||
|
return concaveAngle_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- 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.
|
||||||
|
label nGrow() const
|
||||||
|
{
|
||||||
|
return nGrow_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Number of smoothing iterations of surface normals
|
||||||
|
label nSmoothSurfaceNormals() const
|
||||||
|
{
|
||||||
|
return nSmoothSurfaceNormals_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Number of smoothing iterations of interior mesh movement
|
||||||
|
// direction
|
||||||
|
label nSmoothNormals() const
|
||||||
|
{
|
||||||
|
return nSmoothNormals_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Smooth layer thickness over surface patches
|
||||||
|
label nSmoothThickness() const
|
||||||
|
{
|
||||||
|
return nSmoothThickness_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop layer growth on highly warped cells
|
||||||
|
scalar maxFaceThicknessRatio() const
|
||||||
|
{
|
||||||
|
return maxFaceThicknessRatio_;
|
||||||
|
}
|
||||||
|
|
||||||
|
scalar layerTerminationCos() const
|
||||||
|
{
|
||||||
|
return layerTerminationCos_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reduce layer growth where ratio thickness to medial
|
||||||
|
// distance is large
|
||||||
|
scalar maxThicknessToMedialRatio() const
|
||||||
|
{
|
||||||
|
return maxThicknessToMedialRatio_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Angle used to pick up medial axis points
|
||||||
|
scalar minMedianAxisAngleCos() const
|
||||||
|
{
|
||||||
|
return minMedianAxisAngleCos_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create buffer region for new layer terminations
|
||||||
|
label nBufferCellsNoExtrude() const
|
||||||
|
{
|
||||||
|
return nBufferCellsNoExtrude_;
|
||||||
|
}
|
||||||
|
|
||||||
|
label nSnap() const
|
||||||
|
{
|
||||||
|
return nSnap_;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,123 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 1991-2008 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 2 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, write to the Free Software Foundation,
|
||||||
|
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "refinementParameters.H"
|
||||||
|
#include "mathematicalConstants.H"
|
||||||
|
#include "polyMesh.H"
|
||||||
|
#include "globalIndex.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
// Construct from dictionary
|
||||||
|
Foam::refinementParameters::refinementParameters
|
||||||
|
(
|
||||||
|
const dictionary& dict,
|
||||||
|
const label dummy
|
||||||
|
)
|
||||||
|
:
|
||||||
|
maxGlobalCells_(readLabel(dict.lookup("cellLimit"))),
|
||||||
|
maxLocalCells_(readLabel(dict.lookup("procCellLimit"))),
|
||||||
|
minRefineCells_(readLabel(dict.lookup("minimumRefine"))),
|
||||||
|
curvature_(readScalar(dict.lookup("curvature"))),
|
||||||
|
nBufferLayers_(readLabel(dict.lookup("nBufferLayers"))),
|
||||||
|
keepPoints_(dict.lookup("keepPoints"))
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::refinementParameters::refinementParameters(const dictionary& dict)
|
||||||
|
:
|
||||||
|
maxGlobalCells_(readLabel(dict.lookup("maxGlobalCells"))),
|
||||||
|
maxLocalCells_(readLabel(dict.lookup("maxLocalCells"))),
|
||||||
|
minRefineCells_(readLabel(dict.lookup("minRefinementCells"))),
|
||||||
|
nBufferLayers_(readLabel(dict.lookup("nCellsBetweenLevels"))),
|
||||||
|
keepPoints_(pointField(1, dict.lookup("locationInMesh")))
|
||||||
|
{
|
||||||
|
scalar featAngle(readScalar(dict.lookup("resolveFeatureAngle")));
|
||||||
|
|
||||||
|
if (featAngle < 0 || featAngle > 180)
|
||||||
|
{
|
||||||
|
curvature_ = -GREAT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
curvature_ = Foam::cos(featAngle*mathematicalConstant::pi/180.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::labelList Foam::refinementParameters::findCells(const polyMesh& mesh)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
// Global calculation engine
|
||||||
|
globalIndex globalCells(mesh.nCells());
|
||||||
|
|
||||||
|
// Cell label per point
|
||||||
|
labelList cellLabels(keepPoints_.size());
|
||||||
|
|
||||||
|
forAll(keepPoints_, i)
|
||||||
|
{
|
||||||
|
const point& keepPoint = keepPoints_[i];
|
||||||
|
|
||||||
|
label localCellI = mesh.findCell(keepPoint);
|
||||||
|
|
||||||
|
label globalCellI = -1;
|
||||||
|
|
||||||
|
if (localCellI != -1)
|
||||||
|
{
|
||||||
|
Pout<< "Found point " << keepPoint << " in cell " << localCellI
|
||||||
|
<< " on processor " << Pstream::myProcNo() << endl;
|
||||||
|
globalCellI = globalCells.toGlobal(localCellI);
|
||||||
|
}
|
||||||
|
|
||||||
|
reduce(globalCellI, maxOp<label>());
|
||||||
|
|
||||||
|
if (globalCellI == -1)
|
||||||
|
{
|
||||||
|
FatalErrorIn
|
||||||
|
(
|
||||||
|
"refinementParameters::findCells(const polyMesh&) const"
|
||||||
|
) << "Point " << keepPoint
|
||||||
|
<< " is not inside the mesh or on a face or edge." << nl
|
||||||
|
<< "Bounding box of the mesh:" << mesh.bounds()
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (globalCells.isLocal(globalCellI))
|
||||||
|
{
|
||||||
|
cellLabels[i] = localCellI;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cellLabels[i] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cellLabels;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,154 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 1991-2008 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 2 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, write to the Free Software Foundation,
|
||||||
|
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::refinementParameters
|
||||||
|
|
||||||
|
Description
|
||||||
|
Simple container to keep together refinement specific information.
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
refinementParameters.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef refinementParameters_H
|
||||||
|
#define refinementParameters_H
|
||||||
|
|
||||||
|
#include "dictionary.H"
|
||||||
|
#include "pointField.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// Class forward declarations
|
||||||
|
class polyMesh;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class refinementParameters Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class refinementParameters
|
||||||
|
{
|
||||||
|
// Private data
|
||||||
|
|
||||||
|
//- Total number of cells
|
||||||
|
const label maxGlobalCells_;
|
||||||
|
|
||||||
|
//- Per processor max number of cells
|
||||||
|
const label maxLocalCells_;
|
||||||
|
|
||||||
|
//- When to stop refining
|
||||||
|
const label minRefineCells_;
|
||||||
|
|
||||||
|
//- Curvature
|
||||||
|
scalar curvature_;
|
||||||
|
|
||||||
|
//- Number of layers between different refinement levels
|
||||||
|
const label nBufferLayers_;
|
||||||
|
|
||||||
|
//- Areas to keep
|
||||||
|
const pointField keepPoints_;
|
||||||
|
|
||||||
|
|
||||||
|
// Private Member Functions
|
||||||
|
|
||||||
|
//- Disallow default bitwise copy construct
|
||||||
|
refinementParameters(const refinementParameters&);
|
||||||
|
|
||||||
|
//- Disallow default bitwise assignment
|
||||||
|
void operator=(const refinementParameters&);
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct from dictionary - old syntax
|
||||||
|
refinementParameters(const dictionary& dict, const label dummy);
|
||||||
|
|
||||||
|
//- Construct from dictionary - new syntax
|
||||||
|
refinementParameters(const dictionary& dict);
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
// Access
|
||||||
|
|
||||||
|
//- Total number of cells
|
||||||
|
label maxGlobalCells() const
|
||||||
|
{
|
||||||
|
return maxGlobalCells_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Per processor max number of cells
|
||||||
|
label maxLocalCells() const
|
||||||
|
{
|
||||||
|
return maxLocalCells_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- When to stop refining
|
||||||
|
label minRefineCells() const
|
||||||
|
{
|
||||||
|
return minRefineCells_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Curvature
|
||||||
|
scalar curvature() const
|
||||||
|
{
|
||||||
|
return curvature_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Number of layers between different refinement levels
|
||||||
|
label nBufferLayers() const
|
||||||
|
{
|
||||||
|
return nBufferLayers_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Areas to keep
|
||||||
|
const pointField& keepPoints() const
|
||||||
|
{
|
||||||
|
return keepPoints_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Other
|
||||||
|
|
||||||
|
//- Checks that cells are in mesh. Returns cells they are in.
|
||||||
|
labelList findCells(const polyMesh&) const;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,54 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 1991-2008 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 2 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, write to the Free Software Foundation,
|
||||||
|
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "snapParameters.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
// Construct from dictionary
|
||||||
|
Foam::snapParameters::snapParameters(const dictionary& dict, const label dummy)
|
||||||
|
:
|
||||||
|
nSmoothPatch_(readLabel(dict.lookup("nSmoothPatch"))),
|
||||||
|
snapTol_(readScalar(dict.lookup("snapTol"))),
|
||||||
|
nSmoothDispl_(readLabel(dict.lookup("nSmoothDispl"))),
|
||||||
|
nSnap_(readLabel(dict.lookup("nSnap")))
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
// Construct from dictionary
|
||||||
|
Foam::snapParameters::snapParameters(const dictionary& dict)
|
||||||
|
:
|
||||||
|
nSmoothPatch_(readLabel(dict.lookup("nSmoothPatch"))),
|
||||||
|
snapTol_(readScalar(dict.lookup("tolerance"))),
|
||||||
|
nSmoothDispl_(readLabel(dict.lookup("nSolveIter"))),
|
||||||
|
nSnap_(readLabel(dict.lookup("nRelaxIter")))
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,129 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 1991-2008 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 2 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, write to the Free Software Foundation,
|
||||||
|
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::snapParameters
|
||||||
|
|
||||||
|
Description
|
||||||
|
Simple container to keep together snap specific information.
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
snapParameters.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef snapParameters_H
|
||||||
|
#define snapParameters_H
|
||||||
|
|
||||||
|
#include "dictionary.H"
|
||||||
|
#include "scalar.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// Class forward declarations
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class snapParameters Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class snapParameters
|
||||||
|
{
|
||||||
|
// Private data
|
||||||
|
|
||||||
|
const label nSmoothPatch_;
|
||||||
|
|
||||||
|
const scalar snapTol_;
|
||||||
|
|
||||||
|
const label nSmoothDispl_;
|
||||||
|
|
||||||
|
const label nSnap_;
|
||||||
|
|
||||||
|
|
||||||
|
// Private Member Functions
|
||||||
|
|
||||||
|
//- Disallow default bitwise copy construct
|
||||||
|
snapParameters(const snapParameters&);
|
||||||
|
|
||||||
|
//- Disallow default bitwise assignment
|
||||||
|
void operator=(const snapParameters&);
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct from dictionary - old syntax
|
||||||
|
snapParameters(const dictionary& dict, const label dummy);
|
||||||
|
|
||||||
|
//- Construct from dictionary - new syntax
|
||||||
|
snapParameters(const dictionary& dict);
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
// Access
|
||||||
|
|
||||||
|
//- Number of patch smoothing iterations before finding
|
||||||
|
// correspondence to surface
|
||||||
|
label nSmoothPatch() const
|
||||||
|
{
|
||||||
|
return nSmoothPatch_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Relative distance for points to be attracted by surface
|
||||||
|
// feature point
|
||||||
|
// or edge. True distance is this factor times local
|
||||||
|
// maximum edge length.
|
||||||
|
scalar snapTol() const
|
||||||
|
{
|
||||||
|
return snapTol_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Number of mesh displacement smoothing iterations.
|
||||||
|
label nSmoothDispl() const
|
||||||
|
{
|
||||||
|
return nSmoothDispl_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Maximum number of snapping relaxation iterations. Should stop
|
||||||
|
// before upon reaching a correct mesh.
|
||||||
|
label nSnap() const
|
||||||
|
{
|
||||||
|
return nSnap_;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -24,9 +24,7 @@ License
|
|||||||
|
|
||||||
\*----------------------------------------------------------------------------*/
|
\*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "Pstream.H"
|
|
||||||
#include "meshRefinement.H"
|
#include "meshRefinement.H"
|
||||||
|
|
||||||
#include "volMesh.H"
|
#include "volMesh.H"
|
||||||
#include "volFields.H"
|
#include "volFields.H"
|
||||||
#include "surfaceMesh.H"
|
#include "surfaceMesh.H"
|
||||||
@ -34,7 +32,6 @@ License
|
|||||||
#include "Time.H"
|
#include "Time.H"
|
||||||
#include "refinementHistory.H"
|
#include "refinementHistory.H"
|
||||||
#include "refinementSurfaces.H"
|
#include "refinementSurfaces.H"
|
||||||
#include "cellSet.H"
|
|
||||||
#include "decompositionMethod.H"
|
#include "decompositionMethod.H"
|
||||||
#include "regionSplit.H"
|
#include "regionSplit.H"
|
||||||
#include "fvMeshDistribute.H"
|
#include "fvMeshDistribute.H"
|
||||||
@ -50,8 +47,9 @@ License
|
|||||||
#include "globalPointPatchFields.H"
|
#include "globalPointPatchFields.H"
|
||||||
#include "calculatedPointPatchFields.H"
|
#include "calculatedPointPatchFields.H"
|
||||||
#include "processorPointPatch.H"
|
#include "processorPointPatch.H"
|
||||||
#include "featureEdgeMesh.H"
|
|
||||||
#include "globalIndex.H"
|
#include "globalIndex.H"
|
||||||
|
#include "meshTools.H"
|
||||||
|
#include "OFstream.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -117,90 +115,6 @@ void Foam::meshRefinement::calcNeighbourData
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//void Foam::meshRefinement::calcCanonicalBoundaryData
|
|
||||||
//(
|
|
||||||
// labelList& leftLevel,
|
|
||||||
// pointField& leftCc,
|
|
||||||
// labelList& rightLevel,
|
|
||||||
// pointField& rightCc
|
|
||||||
//) const
|
|
||||||
//{
|
|
||||||
// const labelList& cellLevel = meshCutter_.cellLevel();
|
|
||||||
// const pointField& cellCentres = mesh_.cellCentres();
|
|
||||||
// const polyBoundaryMesh& patches = mesh_.boundaryMesh();
|
|
||||||
//
|
|
||||||
// // Get boundary face centre and level. Coupled aware.
|
|
||||||
// calcNeighbourData(rightLevel, rightCc);
|
|
||||||
//
|
|
||||||
// // Get owner face centre and level. Canonical sort for coupled faces.
|
|
||||||
// forAll(patches, patchI)
|
|
||||||
// {
|
|
||||||
// const polyPatch& pp = patches[patchI];
|
|
||||||
//
|
|
||||||
// const unallocLabelList& faceCells = pp.faceCells();
|
|
||||||
// const vectorField::subField faceCentres = pp.faceCentres();
|
|
||||||
//
|
|
||||||
// if (isA<processorPolyPatch>(pp))
|
|
||||||
// {
|
|
||||||
// const processorPolyPatch& procPp =
|
|
||||||
// refCast<const processorPolyPatch>(patches[patchI]);
|
|
||||||
//
|
|
||||||
// label bFaceI = pp.start()-mesh_.nInternalFaces();
|
|
||||||
// forAll(faceCells, i)
|
|
||||||
// {
|
|
||||||
// leftLevel[bFaceI] = cellLevel[faceCells[i]];
|
|
||||||
// leftCc[bFaceI] = cellCentres[faceCells[i]];
|
|
||||||
// bFaceI++;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Swap if on neighbour so both sides have same values
|
|
||||||
// if (!procPp.owner())
|
|
||||||
// {
|
|
||||||
// forAll(leftLevel, i)
|
|
||||||
// {
|
|
||||||
// Swap(leftLevel[i], rightLevel[i]);
|
|
||||||
// Swap(leftCc[i], rightCc[i]);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else if (isA<cyclicPolyPatch>(pp))
|
|
||||||
// {
|
|
||||||
// const processorPolyPatch& cycPp =
|
|
||||||
// refCast<const processorPolyPatch>(patches[patchI]);
|
|
||||||
//
|
|
||||||
// label bFaceI = pp.start()-mesh_.nInternalFaces();
|
|
||||||
// forAll(faceCells, i)
|
|
||||||
// {
|
|
||||||
// leftLevel[bFaceI] = cellLevel[faceCells[i]];
|
|
||||||
// leftCc[bFaceI] = cellCentres[faceCells[i]];
|
|
||||||
// bFaceI++;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // First half has data in normal order: owner in leftLevel,leftCc
|
|
||||||
// // and coupled data in rightLevel, rightCc. Second half has it
|
|
||||||
// // swapped:
|
|
||||||
// bFaceI = pp.start()+cycPp.size()/2-mesh_.nInternalFaces();
|
|
||||||
// for (label i = 0; i < cycPp.size()/2; i++)
|
|
||||||
// {
|
|
||||||
// Swap(leftLevel[bFaceI], rightLevel[bFaceI]);
|
|
||||||
// Swap(leftCc[bFaceI], rightCc[bFaceI]);
|
|
||||||
// bFaceI++;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// label bFaceI = pp.start()-mesh_.nInternalFaces();
|
|
||||||
// forAll(faceCells, i)
|
|
||||||
// {
|
|
||||||
// leftLevel[bFaceI] = cellLevel[faceCells[i]];
|
|
||||||
// leftCc[bFaceI] = cellCentres[faceCells[i]];
|
|
||||||
// bFaceI++;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
// Find intersections of edges (given by their two endpoints) with surfaces.
|
// Find intersections of edges (given by their two endpoints) with surfaces.
|
||||||
// Returns first intersection if there are more than one.
|
// Returns first intersection if there are more than one.
|
||||||
void Foam::meshRefinement::updateIntersections(const labelList& changedFaces)
|
void Foam::meshRefinement::updateIntersections(const labelList& changedFaces)
|
||||||
@ -220,33 +134,46 @@ void Foam::meshRefinement::updateIntersections(const labelList& changedFaces)
|
|||||||
pointField neiCc(mesh_.nFaces()-mesh_.nInternalFaces());
|
pointField neiCc(mesh_.nFaces()-mesh_.nInternalFaces());
|
||||||
calcNeighbourData(neiLevel, neiCc);
|
calcNeighbourData(neiLevel, neiCc);
|
||||||
|
|
||||||
|
// Collect segments we want to test for
|
||||||
|
pointField start(changedFaces.size());
|
||||||
|
pointField end(changedFaces.size());
|
||||||
|
|
||||||
forAll(changedFaces, i)
|
forAll(changedFaces, i)
|
||||||
{
|
{
|
||||||
label faceI = changedFaces[i];
|
label faceI = changedFaces[i];
|
||||||
label own = mesh_.faceOwner()[faceI];
|
label own = mesh_.faceOwner()[faceI];
|
||||||
|
|
||||||
pointIndexHit surfaceHitInfo;
|
start[i] = cellCentres[own];
|
||||||
|
|
||||||
if (mesh_.isInternalFace(faceI))
|
if (mesh_.isInternalFace(faceI))
|
||||||
{
|
{
|
||||||
surfaceIndex_[faceI] = surfaces_.findAnyIntersection
|
end[i] = cellCentres[mesh_.faceNeighbour()[faceI]];
|
||||||
(
|
|
||||||
cellCentres[own],
|
|
||||||
cellCentres[mesh_.faceNeighbour()[faceI]],
|
|
||||||
surfaceHitInfo
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
surfaceIndex_[faceI] = surfaces_.findAnyIntersection
|
end[i] = neiCc[faceI-mesh_.nInternalFaces()];
|
||||||
(
|
|
||||||
cellCentres[own],
|
|
||||||
neiCc[faceI-mesh_.nInternalFaces()],
|
|
||||||
surfaceHitInfo
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Do tests in one go
|
||||||
|
labelList surfaceHit;
|
||||||
|
{
|
||||||
|
labelList surfaceLevel;
|
||||||
|
surfaces_.findHigherIntersection
|
||||||
|
(
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
labelList(start.size(), -1), // accept any intersection
|
||||||
|
surfaceHit,
|
||||||
|
surfaceLevel
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep just surface hit
|
||||||
|
forAll(surfaceHit, i)
|
||||||
|
{
|
||||||
|
surfaceIndex_[changedFaces[i]] = surfaceHit[i];
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure both sides have same information. This should be
|
// Make sure both sides have same information. This should be
|
||||||
// case in general since same vectors but just to make sure.
|
// case in general since same vectors but just to make sure.
|
||||||
syncTools::syncFaceList(mesh_, surfaceIndex_, maxEqOp<label>(), false);
|
syncTools::syncFaceList(mesh_, surfaceIndex_, maxEqOp<label>(), false);
|
||||||
@ -305,67 +232,72 @@ void Foam::meshRefinement::checkData()
|
|||||||
}
|
}
|
||||||
// Check meshRefinement
|
// Check meshRefinement
|
||||||
{
|
{
|
||||||
for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
|
|
||||||
{
|
|
||||||
label own = mesh_.faceOwner()[faceI];
|
|
||||||
label nei = mesh_.faceNeighbour()[faceI];
|
|
||||||
const point& ownCc = mesh_.cellCentres()[own];
|
|
||||||
const point& neiCc = mesh_.cellCentres()[nei];
|
|
||||||
|
|
||||||
pointIndexHit surfaceHitInfo;
|
|
||||||
label surfI = surfaces_.findAnyIntersection
|
|
||||||
(
|
|
||||||
ownCc,
|
|
||||||
neiCc,
|
|
||||||
surfaceHitInfo
|
|
||||||
);
|
|
||||||
|
|
||||||
if (surfI != surfaceIndex_[faceI])
|
|
||||||
{
|
|
||||||
WarningIn("meshRefinement::checkData()")
|
|
||||||
<< "Internal face:" << faceI
|
|
||||||
<< " fc:" << mesh_.faceCentres()[faceI]
|
|
||||||
<< " cached surfaceIndex_:" << surfaceIndex_[faceI]
|
|
||||||
<< " current:" << surfI
|
|
||||||
<< " ownCc:" << ownCc << " neiCc:" << neiCc
|
|
||||||
<< endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get boundary face centre and level. Coupled aware.
|
// Get boundary face centre and level. Coupled aware.
|
||||||
labelList neiLevel(mesh_.nFaces()-mesh_.nInternalFaces());
|
labelList neiLevel(mesh_.nFaces()-mesh_.nInternalFaces());
|
||||||
pointField neiCc(mesh_.nFaces()-mesh_.nInternalFaces());
|
pointField neiCc(mesh_.nFaces()-mesh_.nInternalFaces());
|
||||||
calcNeighbourData(neiLevel, neiCc);
|
calcNeighbourData(neiLevel, neiCc);
|
||||||
|
|
||||||
for
|
// Collect segments we want to test for
|
||||||
(
|
pointField start(mesh_.nFaces());
|
||||||
label faceI = mesh_.nInternalFaces();
|
pointField end(mesh_.nFaces());
|
||||||
faceI < mesh_.nFaces();
|
|
||||||
faceI++
|
forAll(start, faceI)
|
||||||
)
|
|
||||||
{
|
{
|
||||||
label own = mesh_.faceOwner()[faceI];
|
start[faceI] = mesh_.cellCentres()[mesh_.faceOwner()[faceI]];
|
||||||
const point& ownCc = mesh_.cellCentres()[own];
|
|
||||||
|
|
||||||
pointIndexHit surfaceHitInfo;
|
if (mesh_.isInternalFace(faceI))
|
||||||
label surfI = surfaces_.findAnyIntersection
|
|
||||||
(
|
|
||||||
ownCc,
|
|
||||||
neiCc[faceI-mesh_.nInternalFaces()],
|
|
||||||
surfaceHitInfo
|
|
||||||
);
|
|
||||||
|
|
||||||
if (surfI != surfaceIndex_[faceI])
|
|
||||||
{
|
{
|
||||||
WarningIn("meshRefinement::checkData()")
|
end[faceI] = mesh_.cellCentres()[mesh_.faceNeighbour()[faceI]];
|
||||||
<< "Boundary face:" << faceI
|
}
|
||||||
<< " patch:" << mesh_.boundaryMesh().whichPatch(faceI)
|
else
|
||||||
<< " fc:" << mesh_.faceCentres()[faceI]
|
{
|
||||||
<< " cached surfaceIndex_:" << surfaceIndex_[faceI]
|
end[faceI] = neiCc[faceI-mesh_.nInternalFaces()];
|
||||||
<< " current:" << surfI
|
}
|
||||||
<< " ownCc:" << ownCc
|
}
|
||||||
<< " neiCc:" << neiCc[faceI-mesh_.nInternalFaces()]
|
|
||||||
<< endl;
|
// Do tests in one go
|
||||||
|
labelList surfaceHit;
|
||||||
|
{
|
||||||
|
labelList surfaceLevel;
|
||||||
|
surfaces_.findHigherIntersection
|
||||||
|
(
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
labelList(start.size(), -1), // accept any intersection
|
||||||
|
surfaceHit,
|
||||||
|
surfaceLevel
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check
|
||||||
|
forAll(surfaceHit, faceI)
|
||||||
|
{
|
||||||
|
if (surfaceHit[faceI] != surfaceIndex_[faceI])
|
||||||
|
{
|
||||||
|
if (mesh_.isInternalFace(faceI))
|
||||||
|
{
|
||||||
|
WarningIn("meshRefinement::checkData()")
|
||||||
|
<< "Internal face:" << faceI
|
||||||
|
<< " fc:" << mesh_.faceCentres()[faceI]
|
||||||
|
<< " cached surfaceIndex_:" << surfaceIndex_[faceI]
|
||||||
|
<< " current:" << surfaceHit[faceI]
|
||||||
|
<< " ownCc:"
|
||||||
|
<< mesh_.cellCentres()[mesh_.faceOwner()[faceI]]
|
||||||
|
<< " neiCc:"
|
||||||
|
<< mesh_.cellCentres()[mesh_.faceNeighbour()[faceI]]
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WarningIn("meshRefinement::checkData()")
|
||||||
|
<< "Boundary face:" << faceI
|
||||||
|
<< " fc:" << mesh_.faceCentres()[faceI]
|
||||||
|
<< " cached surfaceIndex_:" << surfaceIndex_[faceI]
|
||||||
|
<< " current:" << surfaceHit[faceI]
|
||||||
|
<< " ownCc:"
|
||||||
|
<< mesh_.cellCentres()[mesh_.faceOwner()[faceI]]
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -492,283 +424,6 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::doRemoveCells
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Get which are inside any closed surface. Note that all closed surfaces
|
|
||||||
// will have already been oriented to have keepPoint outside.
|
|
||||||
Foam::labelList Foam::meshRefinement::getInsideCells
|
|
||||||
(
|
|
||||||
const word& postfix
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
const pointField& points = mesh_.points();
|
|
||||||
|
|
||||||
// This test can be done in various ways. The ultimate is the intersection
|
|
||||||
// of any edge of the mesh with any surface and intersection of any edge
|
|
||||||
// of any surface of the mesh with any mesh face.
|
|
||||||
// For now:
|
|
||||||
// - none of the edges of a cell intersects any surface
|
|
||||||
// - any point of the cell is inside.
|
|
||||||
|
|
||||||
|
|
||||||
// Is point inside any closed surface?
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
PackedList<1> pointIsInside;
|
|
||||||
label nPointInside = surfaces_.markInsidePoints
|
|
||||||
(
|
|
||||||
points,
|
|
||||||
pointIsInside
|
|
||||||
);
|
|
||||||
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
Pout<< "getInsideCells : Points internal to closed surfaces :"
|
|
||||||
<< " local:" << nPointInside
|
|
||||||
<< " global:" << returnReduce(nPointInside, sumOp<label>())
|
|
||||||
<< endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Find cells with all points inside closed surface
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
PackedList<1> cellIsInside(mesh_.nCells(), 1u);
|
|
||||||
label nCellInside = mesh_.nCells();
|
|
||||||
|
|
||||||
// Unmark cells with any point outside
|
|
||||||
forAll(points, pointI)
|
|
||||||
{
|
|
||||||
if (pointIsInside.get(pointI) == 0u)
|
|
||||||
{
|
|
||||||
// Outside point. Unmark cells.
|
|
||||||
const labelList& pCells = mesh_.pointCells()[pointI];
|
|
||||||
|
|
||||||
forAll(pCells, i)
|
|
||||||
{
|
|
||||||
label cellI = pCells[i];
|
|
||||||
|
|
||||||
if (cellIsInside.get(cellI) == 1u)
|
|
||||||
{
|
|
||||||
cellIsInside.set(cellI, 0u);
|
|
||||||
nCellInside--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
label totNCellInside = nCellInside;
|
|
||||||
reduce(totNCellInside, sumOp<label>());
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
Pout<< "getInsideCells : Cells using inside points only :"
|
|
||||||
<< " local:" << nCellInside << " global:" << totNCellInside
|
|
||||||
<< endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter any cells with cc-cc edge intersection
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
const cellList& cells = mesh_.cells();
|
|
||||||
|
|
||||||
cellSet insidePoints(mesh_, "insidePoints_"+postfix, mesh_.nCells()/100);
|
|
||||||
cellSet insidePointsButCut
|
|
||||||
(
|
|
||||||
mesh_,
|
|
||||||
"insidePointsButCut_"+postfix,
|
|
||||||
mesh_.nCells()/100
|
|
||||||
);
|
|
||||||
|
|
||||||
forAll(cells, cellI)
|
|
||||||
{
|
|
||||||
if (cellIsInside.get(cellI) == 1u)
|
|
||||||
{
|
|
||||||
insidePoints.insert(cellI);
|
|
||||||
|
|
||||||
const cell& cFaces = cells[cellI];
|
|
||||||
|
|
||||||
forAll(cFaces, i)
|
|
||||||
{
|
|
||||||
if (surfaceIndex_[cFaces[i]] != -1)
|
|
||||||
{
|
|
||||||
cellIsInside.set(cellI, 0u);
|
|
||||||
nCellInside--;
|
|
||||||
|
|
||||||
insidePointsButCut.insert(cellI);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
Pout<< "getInsideCells : cells with all points inside : "
|
|
||||||
<< insidePoints.objectPath() << endl;
|
|
||||||
insidePoints.write();
|
|
||||||
Pout<< "getInsideCells : cells with all points inside"
|
|
||||||
<< " but intersecting (cc) surface : "
|
|
||||||
<< insidePointsButCut.objectPath() << endl;
|
|
||||||
insidePointsButCut.write();
|
|
||||||
}
|
|
||||||
|
|
||||||
totNCellInside = nCellInside;
|
|
||||||
reduce(totNCellInside, sumOp<label>());
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
Pout<< "getInsideCells : After filtering cc-cc intersections :"
|
|
||||||
<< " local:" << nCellInside << " global:" << totNCellInside
|
|
||||||
<< endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Filter cells with any normal edge intersection
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
cellSet insidePointsButEdge
|
|
||||||
(
|
|
||||||
mesh_,
|
|
||||||
"insidePointsButEdge_"+postfix,
|
|
||||||
mesh_.nCells()/100
|
|
||||||
);
|
|
||||||
|
|
||||||
const labelListList& edgeCells = mesh_.edgeCells();
|
|
||||||
|
|
||||||
forAll(edgeCells, edgeI)
|
|
||||||
{
|
|
||||||
const labelList& eCells = edgeCells[edgeI];
|
|
||||||
|
|
||||||
// Does edge use any inside cells? Prefilter since edge intersection
|
|
||||||
// test expensive.
|
|
||||||
bool edgeHasInsideCells = false;
|
|
||||||
|
|
||||||
forAll(eCells, i)
|
|
||||||
{
|
|
||||||
if (cellIsInside.get(eCells[i]) == 1u)
|
|
||||||
{
|
|
||||||
edgeHasInsideCells = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (edgeHasInsideCells)
|
|
||||||
{
|
|
||||||
const edge& e = mesh_.edges()[edgeI];
|
|
||||||
|
|
||||||
// Find any pierces of surface by mesh edge.
|
|
||||||
pointIndexHit hit;
|
|
||||||
label surfI = surfaces().findHigherIntersection
|
|
||||||
(
|
|
||||||
points[e[0]],
|
|
||||||
points[e[1]],
|
|
||||||
-1, // minimum level.
|
|
||||||
hit
|
|
||||||
);
|
|
||||||
|
|
||||||
if (surfI != -1)
|
|
||||||
{
|
|
||||||
// This edge intersects some surface. Unmark all cells
|
|
||||||
// using this edge.
|
|
||||||
|
|
||||||
forAll(eCells, i)
|
|
||||||
{
|
|
||||||
if (cellIsInside.get(eCells[i]) == 1u)
|
|
||||||
{
|
|
||||||
cellIsInside.set(eCells[i], 0u);
|
|
||||||
nCellInside--;
|
|
||||||
|
|
||||||
insidePointsButEdge.insert(eCells[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
Pout<< "getInsideCells : cells with all points inside"
|
|
||||||
<< " but intersecting (edges) surface : "
|
|
||||||
<< insidePointsButEdge.objectPath() << endl;
|
|
||||||
insidePointsButEdge.write();
|
|
||||||
}
|
|
||||||
|
|
||||||
totNCellInside = nCellInside;
|
|
||||||
reduce(totNCellInside, sumOp<label>());
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
Pout<< "getInsideCells : After filtering edge interesections :"
|
|
||||||
<< " local:" << nCellInside << " global:" << totNCellInside
|
|
||||||
<< endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Collect cells
|
|
||||||
// ~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
DynamicList<label> cellsToRemove(nCellInside);
|
|
||||||
|
|
||||||
forAll(cellIsInside, cellI)
|
|
||||||
{
|
|
||||||
if (cellIsInside.get(cellI) == 1u)
|
|
||||||
{
|
|
||||||
cellsToRemove.append(cellI);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cellsToRemove.shrink();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Do all to remove inside cells
|
|
||||||
Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::removeInsideCells
|
|
||||||
(
|
|
||||||
const string& msg,
|
|
||||||
const label exposedPatchI
|
|
||||||
)
|
|
||||||
{
|
|
||||||
labelList insideCells
|
|
||||||
(
|
|
||||||
getInsideCells
|
|
||||||
(
|
|
||||||
string::validate<word>(msg)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
Info<< "Removing inside cells : "
|
|
||||||
<< returnReduce(insideCells.size(), sumOp<label>())
|
|
||||||
<< '.' << endl;
|
|
||||||
|
|
||||||
removeCells cellRemover(mesh_);
|
|
||||||
|
|
||||||
labelList exposedFaces(cellRemover.getExposedFaces(insideCells));
|
|
||||||
|
|
||||||
// Debug check
|
|
||||||
forAll(exposedFaces, i)
|
|
||||||
{
|
|
||||||
label faceI = exposedFaces[i];
|
|
||||||
|
|
||||||
if (surfaceIndex_[faceI] != -1)
|
|
||||||
{
|
|
||||||
FatalErrorIn
|
|
||||||
(
|
|
||||||
"removeInsideCells"
|
|
||||||
"(const label, const string&, const label)"
|
|
||||||
) << "Face:" << faceI
|
|
||||||
<< " fc:" << mesh_.faceCentres()[faceI]
|
|
||||||
<< " is actually cutting the surface and should never have been"
|
|
||||||
<< " included in the cells to remove."
|
|
||||||
<< abort(FatalError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return doRemoveCells
|
|
||||||
(
|
|
||||||
insideCells,
|
|
||||||
exposedFaces,
|
|
||||||
labelList(exposedFaces.size(), exposedPatchI),
|
|
||||||
cellRemover
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Determine for multi-processor regions the lowest numbered cell on the lowest
|
// Determine for multi-processor regions the lowest numbered cell on the lowest
|
||||||
// numbered processor.
|
// numbered processor.
|
||||||
void Foam::meshRefinement::getRegionMaster
|
void Foam::meshRefinement::getRegionMaster
|
||||||
@ -835,12 +490,14 @@ Foam::meshRefinement::meshRefinement
|
|||||||
(
|
(
|
||||||
fvMesh& mesh,
|
fvMesh& mesh,
|
||||||
const scalar tol,
|
const scalar tol,
|
||||||
const refinementSurfaces& surfaces
|
const refinementSurfaces& surfaces,
|
||||||
|
const shellSurfaces& shells
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
mesh_(mesh),
|
mesh_(mesh),
|
||||||
tol_(tol),
|
tol_(tol),
|
||||||
surfaces_(surfaces),
|
surfaces_(surfaces),
|
||||||
|
shells_(shells),
|
||||||
meshCutter_
|
meshCutter_
|
||||||
(
|
(
|
||||||
mesh,
|
mesh,
|
||||||
@ -926,109 +583,6 @@ Foam::label Foam::meshRefinement::countHits() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//// Determine distribution to keep baffles together
|
|
||||||
//Foam::labelList Foam::meshRefinement::decomposePreserveBaffles
|
|
||||||
//(
|
|
||||||
// decompositionMethod& decomposer
|
|
||||||
//) const
|
|
||||||
//{
|
|
||||||
// // Find duplicate faces
|
|
||||||
// labelList duplicateFace
|
|
||||||
// (
|
|
||||||
// localPointRegion::findDuplicateFaces
|
|
||||||
// (
|
|
||||||
// mesh_,
|
|
||||||
// identity(mesh_.nFaces()-mesh_.nInternalFaces())
|
|
||||||
// + mesh_.nInternalFaces()
|
|
||||||
// )
|
|
||||||
// );
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// // Agglomerate cells on both sides of duplicate face pair
|
|
||||||
//
|
|
||||||
// const pointField& cellCentres = mesh_.cellCentres();
|
|
||||||
// const labelList& faceOwner = mesh_.faceOwner();
|
|
||||||
//
|
|
||||||
// labelList toAgglom(mesh_.nCells(), -1);
|
|
||||||
// pointField agglomCellCentres(mesh_.nCells());
|
|
||||||
// labelList nAgglomCellCentres(mesh_.nCells(), 0);
|
|
||||||
//
|
|
||||||
// label agglomI = 0;
|
|
||||||
//
|
|
||||||
// // Do all baffle cells
|
|
||||||
// forAll(duplicateFace, i)
|
|
||||||
// {
|
|
||||||
// if (duplicateFace[i] != -1)
|
|
||||||
// {
|
|
||||||
// label own = faceOwner[i+mesh_.nInternalFaces()];
|
|
||||||
// label otherOwn =
|
|
||||||
// faceOwner[duplicateFace[i]+mesh_.nInternalFaces()];
|
|
||||||
//
|
|
||||||
// if (toAgglom[own] == -1 && toAgglom[otherOwn] == -1)
|
|
||||||
// {
|
|
||||||
// // Allocate new agglomeration
|
|
||||||
// agglomCellCentres[agglomI] =
|
|
||||||
// cellCentres[own]
|
|
||||||
// + cellCentres[otherOwn];
|
|
||||||
// nAgglomCellCentres[agglomI] = 2;
|
|
||||||
// toAgglom[own] = agglomI;
|
|
||||||
// toAgglom[otherOwn] = agglomI;
|
|
||||||
// agglomI++;
|
|
||||||
// }
|
|
||||||
// else if (toAgglom[own] != -1)
|
|
||||||
// {
|
|
||||||
// // Owner already part of agglomeration. Add otherOwn to it.
|
|
||||||
// label destAgglom = toAgglom[own];
|
|
||||||
// agglomCellCentres[destAgglom] += cellCentres[otherOwn];
|
|
||||||
// nAgglomCellCentres[destAgglom]++;
|
|
||||||
// toAgglom[otherOwn] = destAgglom;
|
|
||||||
// }
|
|
||||||
// else if (toAgglom[otherOwn] != -1)
|
|
||||||
// {
|
|
||||||
// // otherOwn already part of agglomeration. Add own to it.
|
|
||||||
// label destAgglom = toAgglom[otherOwn];
|
|
||||||
// agglomCellCentres[destAgglom] += cellCentres[own];
|
|
||||||
// nAgglomCellCentres[destAgglom]++;
|
|
||||||
// toAgglom[own] = destAgglom;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Do all other cells
|
|
||||||
// forAll(toAgglom, cellI)
|
|
||||||
// {
|
|
||||||
// if (toAgglom[cellI] == -1)
|
|
||||||
// {
|
|
||||||
// agglomCellCentres[agglomI] = cellCentres[cellI];
|
|
||||||
// nAgglomCellCentres[agglomI] = 1;
|
|
||||||
// toAgglom[cellI] = agglomI;
|
|
||||||
// agglomI++;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Average
|
|
||||||
// agglomCellCentres.setSize(agglomI);
|
|
||||||
//
|
|
||||||
// forAll(agglomCellCentres, i)
|
|
||||||
// {
|
|
||||||
// agglomCellCentres[i] /= nAgglomCellCentres[i];
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Decompose based on agglomerated cell centres
|
|
||||||
// labelList agglomDistribution(decomposer.decompose(agglomCellCentres));
|
|
||||||
//
|
|
||||||
// // Rework back into decomposition for original mesh_
|
|
||||||
// labelList distribution(mesh_.nCells());
|
|
||||||
//
|
|
||||||
// forAll(toAgglom, cellI)
|
|
||||||
// {
|
|
||||||
// distribution[cellI] = agglomDistribution[toAgglom[cellI]];
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return distribution;
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
// Determine distribution to move connected regions onto one processor.
|
// Determine distribution to move connected regions onto one processor.
|
||||||
Foam::labelList Foam::meshRefinement::decomposeCombineRegions
|
Foam::labelList Foam::meshRefinement::decomposeCombineRegions
|
||||||
(
|
(
|
||||||
@ -1213,9 +767,8 @@ Foam::labelList Foam::meshRefinement::intersectedPoints
|
|||||||
|
|
||||||
forAll(f, fp)
|
forAll(f, fp)
|
||||||
{
|
{
|
||||||
if (isBoundaryPoint.get(f[fp]) == 0u)
|
if (isBoundaryPoint.set(f[fp], 1u))
|
||||||
{
|
{
|
||||||
isBoundaryPoint.set(f[fp], 1u);
|
|
||||||
nBoundaryPoints++;
|
nBoundaryPoints++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1239,9 +792,7 @@ Foam::labelList Foam::meshRefinement::intersectedPoints
|
|||||||
//
|
//
|
||||||
// forAll(f, fp)
|
// forAll(f, fp)
|
||||||
// {
|
// {
|
||||||
// if (isBoundaryPoint.get(f[fp]) == 0u)
|
// if (isBoundaryPoint.set(f[fp], 1u))
|
||||||
// {
|
|
||||||
// isBoundaryPoint.set(f[fp], 1u);
|
|
||||||
// nBoundaryPoints++;
|
// nBoundaryPoints++;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
@ -1910,53 +1461,56 @@ void Foam::meshRefinement::dumpIntersections(const fileName& prefix) const
|
|||||||
<< " Writing cellcentre-cellcentre intersections to file "
|
<< " Writing cellcentre-cellcentre intersections to file "
|
||||||
<< str.name() << endl;
|
<< str.name() << endl;
|
||||||
|
|
||||||
// Internal faces
|
|
||||||
for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
|
|
||||||
{
|
|
||||||
if (surfaceIndex_[faceI] != -1)
|
|
||||||
{
|
|
||||||
const point& ownCc = cellCentres[mesh_.faceOwner()[faceI]];
|
|
||||||
const point& neiCc = cellCentres[mesh_.faceNeighbour()[faceI]];
|
|
||||||
|
|
||||||
// Re-intersect to get position
|
// Redo all intersections
|
||||||
pointIndexHit surfaceHitInfo;
|
// ~~~~~~~~~~~~~~~~~~~~~~
|
||||||
surfaces_.findAnyIntersection(ownCc, neiCc, surfaceHitInfo);
|
|
||||||
|
|
||||||
meshTools::writeOBJ(str, ownCc);
|
|
||||||
vertI++;
|
|
||||||
meshTools::writeOBJ(str, surfaceHitInfo.hitPoint());
|
|
||||||
vertI++;
|
|
||||||
meshTools::writeOBJ(str, neiCc);
|
|
||||||
vertI++;
|
|
||||||
str << "l " << vertI-2 << ' ' << vertI-1 << nl
|
|
||||||
<< "l " << vertI-1 << ' ' << vertI << nl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Boundary faces
|
|
||||||
|
|
||||||
// Get boundary face centre and level. Coupled aware.
|
// Get boundary face centre and level. Coupled aware.
|
||||||
labelList neiLevel(mesh_.nFaces()-mesh_.nInternalFaces());
|
labelList neiLevel(mesh_.nFaces()-mesh_.nInternalFaces());
|
||||||
pointField neiCc(mesh_.nFaces()-mesh_.nInternalFaces());
|
pointField neiCc(mesh_.nFaces()-mesh_.nInternalFaces());
|
||||||
calcNeighbourData(neiLevel, neiCc);
|
calcNeighbourData(neiLevel, neiCc);
|
||||||
|
|
||||||
forAll(neiCc, i)
|
labelList intersectionFaces(intersectedFaces());
|
||||||
|
|
||||||
|
// Collect segments we want to test for
|
||||||
|
pointField start(intersectionFaces.size());
|
||||||
|
pointField end(intersectionFaces.size());
|
||||||
|
|
||||||
|
forAll(intersectionFaces, i)
|
||||||
{
|
{
|
||||||
label faceI = i + mesh_.nInternalFaces();
|
label faceI = intersectionFaces[i];
|
||||||
|
start[i] = cellCentres[mesh_.faceOwner()[faceI]];
|
||||||
|
|
||||||
if (surfaceIndex_[faceI] != -1)
|
if (mesh_.isInternalFace(faceI))
|
||||||
{
|
{
|
||||||
const point& ownCc = cellCentres[mesh_.faceOwner()[faceI]];
|
end[i] = cellCentres[mesh_.faceNeighbour()[faceI]];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
end[i] = neiCc[faceI-mesh_.nInternalFaces()];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Re-intersect to get position
|
// Do tests in one go
|
||||||
pointIndexHit surfaceHitInfo;
|
labelList surfaceHit;
|
||||||
surfaces_.findAnyIntersection(ownCc, neiCc[i], surfaceHitInfo);
|
List<pointIndexHit> surfaceHitInfo;
|
||||||
|
surfaces_.findAnyIntersection
|
||||||
|
(
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
surfaceHit,
|
||||||
|
surfaceHitInfo
|
||||||
|
);
|
||||||
|
|
||||||
meshTools::writeOBJ(str, ownCc);
|
forAll(intersectionFaces, i)
|
||||||
|
{
|
||||||
|
if (surfaceHit[i] != -1)
|
||||||
|
{
|
||||||
|
meshTools::writeOBJ(str, start[i]);
|
||||||
vertI++;
|
vertI++;
|
||||||
meshTools::writeOBJ(str, surfaceHitInfo.hitPoint());
|
meshTools::writeOBJ(str, surfaceHitInfo[i].hitPoint());
|
||||||
vertI++;
|
vertI++;
|
||||||
meshTools::writeOBJ(str, neiCc[i]);
|
meshTools::writeOBJ(str, end[i]);
|
||||||
vertI++;
|
vertI++;
|
||||||
str << "l " << vertI-2 << ' ' << vertI-1 << nl
|
str << "l " << vertI-2 << ' ' << vertI-1 << nl
|
||||||
<< "l " << vertI-1 << ' ' << vertI << nl;
|
<< "l " << vertI-1 << ' ' << vertI << nl;
|
||||||
@ -1996,13 +1550,4 @@ void Foam::meshRefinement::write
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
|
|||||||
@ -30,7 +30,7 @@ Description
|
|||||||
(static) surfaces.
|
(static) surfaces.
|
||||||
|
|
||||||
Maintains
|
Maintains
|
||||||
- per face any intersections of this edge with any of the surfaces
|
- per face any intersections of the cc-cc segment with any of the surfaces
|
||||||
|
|
||||||
SourceFiles
|
SourceFiles
|
||||||
meshRefinement.C
|
meshRefinement.C
|
||||||
@ -62,6 +62,7 @@ class fvMesh;
|
|||||||
class mapDistributePolyMesh;
|
class mapDistributePolyMesh;
|
||||||
class decompositionMethod;
|
class decompositionMethod;
|
||||||
class refinementSurfaces;
|
class refinementSurfaces;
|
||||||
|
class shellSurfaces;
|
||||||
class removeCells;
|
class removeCells;
|
||||||
class featureEdgeMesh;
|
class featureEdgeMesh;
|
||||||
class fvMeshDistribute;
|
class fvMeshDistribute;
|
||||||
@ -107,8 +108,12 @@ private:
|
|||||||
//- tolerance used for sorting coordinates (used in 'less' routine)
|
//- tolerance used for sorting coordinates (used in 'less' routine)
|
||||||
const scalar tol_;
|
const scalar tol_;
|
||||||
|
|
||||||
|
//- All surface-intersection interaction
|
||||||
const refinementSurfaces& surfaces_;
|
const refinementSurfaces& surfaces_;
|
||||||
|
|
||||||
|
//- All shell-refinement interaction
|
||||||
|
const shellSurfaces& shells_;
|
||||||
|
|
||||||
//- refinement engine
|
//- refinement engine
|
||||||
hexRef8 meshCutter_;
|
hexRef8 meshCutter_;
|
||||||
|
|
||||||
@ -229,14 +234,18 @@ private:
|
|||||||
//- Mark cells for refinement-shells based refinement.
|
//- Mark cells for refinement-shells based refinement.
|
||||||
label markInternalRefinement
|
label markInternalRefinement
|
||||||
(
|
(
|
||||||
const PtrList<searchableSurface>&,
|
|
||||||
const labelList& shellLevels,
|
|
||||||
const boolList& shellRefineInside,
|
|
||||||
const label nAllowRefine,
|
const label nAllowRefine,
|
||||||
labelList& refineCell,
|
labelList& refineCell,
|
||||||
label& nRefine
|
label& nRefine
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
|
//- Collect faces that are intersected and whose neighbours aren't
|
||||||
|
// yet marked for refinement.
|
||||||
|
labelList getRefineCandidateFaces
|
||||||
|
(
|
||||||
|
const labelList& refineCell
|
||||||
|
) const;
|
||||||
|
|
||||||
//- Mark cells for surface intersection based refinement.
|
//- Mark cells for surface intersection based refinement.
|
||||||
label markSurfaceRefinement
|
label markSurfaceRefinement
|
||||||
(
|
(
|
||||||
@ -252,17 +261,13 @@ private:
|
|||||||
// regions.
|
// regions.
|
||||||
bool checkCurvature
|
bool checkCurvature
|
||||||
(
|
(
|
||||||
const labelList& globalToPatch,
|
|
||||||
const scalar curvature,
|
const scalar curvature,
|
||||||
const bool markDifferingRegions,
|
|
||||||
const label nAllowRefine,
|
const label nAllowRefine,
|
||||||
const label newSurfI,
|
const label surfaceLevel,
|
||||||
const label newTriI,
|
const vector& surfaceNormal,
|
||||||
const label cellI,
|
const label cellI,
|
||||||
|
label& cellMaxLevel,
|
||||||
label& maxCellSurfI,
|
vector& cellMaxNormal,
|
||||||
label& maxCellTriI,
|
|
||||||
|
|
||||||
labelList& refineCell,
|
labelList& refineCell,
|
||||||
label& nRefine
|
label& nRefine
|
||||||
) const;
|
) const;
|
||||||
@ -273,9 +278,7 @@ private:
|
|||||||
// (markDifferingRegions)
|
// (markDifferingRegions)
|
||||||
label markSurfaceCurvatureRefinement
|
label markSurfaceCurvatureRefinement
|
||||||
(
|
(
|
||||||
const labelList& globalToPatch,
|
|
||||||
const scalar curvature,
|
const scalar curvature,
|
||||||
const bool markDifferingRegions,
|
|
||||||
const label nAllowRefine,
|
const label nAllowRefine,
|
||||||
const labelList& neiLevel,
|
const labelList& neiLevel,
|
||||||
const pointField& neiCc,
|
const pointField& neiCc,
|
||||||
@ -381,7 +384,8 @@ public:
|
|||||||
(
|
(
|
||||||
fvMesh& mesh,
|
fvMesh& mesh,
|
||||||
const scalar tol,
|
const scalar tol,
|
||||||
const refinementSurfaces&
|
const refinementSurfaces&,
|
||||||
|
const shellSurfaces&
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
@ -482,22 +486,18 @@ public:
|
|||||||
const labelList& adaptPatchIDs
|
const labelList& adaptPatchIDs
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
// Refinement
|
// Refinement
|
||||||
|
|
||||||
//- Calculate list of cells to refine.
|
//- Calculate list of cells to refine.
|
||||||
labelList refineCandidates
|
labelList refineCandidates
|
||||||
(
|
(
|
||||||
const point& keepPoint,
|
const point& keepPoint,
|
||||||
const labelList& globalToPatch,
|
|
||||||
const scalar curvature,
|
const scalar curvature,
|
||||||
|
|
||||||
const PtrList<featureEdgeMesh>& featureMeshes,
|
const PtrList<featureEdgeMesh>& featureMeshes,
|
||||||
const labelList& featureLevels,
|
const labelList& featureLevels,
|
||||||
|
|
||||||
const PtrList<searchableSurface>&,
|
|
||||||
const labelList& shellLevels,
|
|
||||||
const boolList& shellRefineInside,
|
|
||||||
|
|
||||||
const bool featureRefinement,
|
const bool featureRefinement,
|
||||||
const bool internalRefinement,
|
const bool internalRefinement,
|
||||||
const bool surfaceRefinement,
|
const bool surfaceRefinement,
|
||||||
|
|||||||
@ -249,7 +249,7 @@ void Foam::meshRefinement::getBafflePatches
|
|||||||
if (debug)
|
if (debug)
|
||||||
{
|
{
|
||||||
Pout<< "getBafflePatches : Not baffling surface "
|
Pout<< "getBafflePatches : Not baffling surface "
|
||||||
<< surfaces_[surfI].searchableSurface::name() << endl;
|
<< surfaces_.names()[surfI] << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -264,69 +264,95 @@ void Foam::meshRefinement::getBafflePatches
|
|||||||
neiPatch.setSize(mesh_.nFaces());
|
neiPatch.setSize(mesh_.nFaces());
|
||||||
neiPatch = -1;
|
neiPatch = -1;
|
||||||
|
|
||||||
forAll(surfaceIndex_, faceI)
|
|
||||||
|
// Collect candidate faces
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
labelList testFaces(intersectedFaces());
|
||||||
|
|
||||||
|
// Collect segments
|
||||||
|
// ~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
pointField start(testFaces.size());
|
||||||
|
pointField end(testFaces.size());
|
||||||
|
|
||||||
|
forAll(testFaces, i)
|
||||||
{
|
{
|
||||||
if (surfaceIndex_[faceI] != -1)
|
label faceI = testFaces[i];
|
||||||
|
|
||||||
|
label own = mesh_.faceOwner()[faceI];
|
||||||
|
|
||||||
|
if (mesh_.isInternalFace(faceI))
|
||||||
{
|
{
|
||||||
// Edge between owner and neighbour of face pierces a surface.
|
start[i] = cellCentres[own];
|
||||||
// Do closer inspection to find nearest intersection on both sides.
|
end[i] = cellCentres[mesh_.faceNeighbour()[faceI]];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
start[i] = cellCentres[own];
|
||||||
|
end[i] = neiCc[faceI-mesh_.nInternalFaces()];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
label own = mesh_.faceOwner()[faceI];
|
|
||||||
|
|
||||||
// Cc of neighbouring cell
|
// Do test for intersections
|
||||||
point end
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
(
|
labelList surface1;
|
||||||
mesh_.isInternalFace(faceI)
|
List<pointIndexHit> hit1;
|
||||||
? cellCentres[mesh_.faceNeighbour()[faceI]]
|
labelList region1;
|
||||||
: neiCc[faceI-mesh_.nInternalFaces()]
|
labelList surface2;
|
||||||
);
|
List<pointIndexHit> hit2;
|
||||||
|
labelList region2;
|
||||||
|
surfaces_.findNearestIntersection
|
||||||
|
(
|
||||||
|
surfacesToBaffle,
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
|
||||||
label surface1, surface2;
|
surface1,
|
||||||
pointIndexHit hit1, hit2;
|
hit1,
|
||||||
surfaces_.findNearestIntersection
|
region1,
|
||||||
(
|
|
||||||
surfacesToBaffle,
|
|
||||||
cellCentres[own],
|
|
||||||
end,
|
|
||||||
|
|
||||||
surface1,
|
surface2,
|
||||||
hit1,
|
hit2,
|
||||||
surface2,
|
region2
|
||||||
hit2
|
);
|
||||||
);
|
|
||||||
|
|
||||||
if (hit1.hit() && hit2.hit())
|
forAll(testFaces, i)
|
||||||
|
{
|
||||||
|
label faceI = testFaces[i];
|
||||||
|
|
||||||
|
if (hit1[i].hit() && hit2[i].hit())
|
||||||
|
{
|
||||||
|
if (str.valid())
|
||||||
{
|
{
|
||||||
if (str.valid())
|
meshTools::writeOBJ(str(), start[i]);
|
||||||
{
|
vertI++;
|
||||||
meshTools::writeOBJ(str(), cellCentres[own]);
|
meshTools::writeOBJ(str(), hit1[i].rawPoint());
|
||||||
vertI++;
|
vertI++;
|
||||||
meshTools::writeOBJ(str(), hit1.rawPoint());
|
meshTools::writeOBJ(str(), hit2[i].rawPoint());
|
||||||
vertI++;
|
vertI++;
|
||||||
meshTools::writeOBJ(str(), hit2.rawPoint());
|
meshTools::writeOBJ(str(), end[i]);
|
||||||
vertI++;
|
vertI++;
|
||||||
meshTools::writeOBJ(str(), end);
|
str()<< "l " << vertI-3 << ' ' << vertI-2 << nl;
|
||||||
vertI++;
|
str()<< "l " << vertI-2 << ' ' << vertI-1 << nl;
|
||||||
str()<< "l " << vertI-3 << ' ' << vertI-2 << nl;
|
str()<< "l " << vertI-1 << ' ' << vertI << nl;
|
||||||
str()<< "l " << vertI-2 << ' ' << vertI-1 << nl;
|
}
|
||||||
str()<< "l " << vertI-1 << ' ' << vertI << nl;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Pick up the patches
|
||||||
|
ownPatch[faceI] = globalToPatch
|
||||||
|
[
|
||||||
|
surfaces_.globalRegion(surface1[i], region1[i])
|
||||||
|
];
|
||||||
|
neiPatch[faceI] = globalToPatch
|
||||||
|
[
|
||||||
|
surfaces_.globalRegion(surface2[i], region2[i])
|
||||||
|
];
|
||||||
|
|
||||||
// Pick up the patches
|
if (ownPatch[faceI] == -1 || neiPatch[faceI] == -1)
|
||||||
ownPatch[faceI] = globalToPatch
|
{
|
||||||
[
|
FatalErrorIn("getBafflePatches(..)")
|
||||||
surfaces_.triangleRegion(surface1, hit1.index())
|
<< "problem." << abort(FatalError);
|
||||||
];
|
|
||||||
neiPatch[faceI] = globalToPatch
|
|
||||||
[
|
|
||||||
surfaces_.triangleRegion(surface2, hit2.index())
|
|
||||||
];
|
|
||||||
|
|
||||||
if (ownPatch[faceI] == -1 || neiPatch[faceI] == -1)
|
|
||||||
{
|
|
||||||
FatalErrorIn("getBafflePatches()") << abort(FatalError);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1203,15 +1229,20 @@ void Foam::meshRefinement::findCellZoneGeometric
|
|||||||
const labelList& faceOwner = mesh_.faceOwner();
|
const labelList& faceOwner = mesh_.faceOwner();
|
||||||
const labelList& faceNeighbour = mesh_.faceNeighbour();
|
const labelList& faceNeighbour = mesh_.faceNeighbour();
|
||||||
|
|
||||||
forAll(cellToZone, cellI)
|
// Check if cell centre is inside
|
||||||
|
labelList insideSurfaces;
|
||||||
|
surfaces_.findInside
|
||||||
|
(
|
||||||
|
closedNamedSurfaces,
|
||||||
|
cellCentres,
|
||||||
|
insideSurfaces
|
||||||
|
);
|
||||||
|
|
||||||
|
forAll(insideSurfaces, cellI)
|
||||||
{
|
{
|
||||||
if (cellToZone[cellI] == -2)
|
if (cellToZone[cellI] == -2)
|
||||||
{
|
{
|
||||||
label surfI = surfaces_.insideZone
|
label surfI = insideSurfaces[cellI];
|
||||||
(
|
|
||||||
closedNamedSurfaces,
|
|
||||||
cellCentres[cellI]
|
|
||||||
);
|
|
||||||
|
|
||||||
if (surfI != -1)
|
if (surfI != -1)
|
||||||
{
|
{
|
||||||
@ -1223,6 +1254,32 @@ void Foam::meshRefinement::findCellZoneGeometric
|
|||||||
|
|
||||||
// Some cells with cell centres close to surface might have
|
// Some cells with cell centres close to surface might have
|
||||||
// had been put into wrong surface. Recheck with perturbed cell centre.
|
// had been put into wrong surface. Recheck with perturbed cell centre.
|
||||||
|
|
||||||
|
|
||||||
|
// 1. Collect points
|
||||||
|
|
||||||
|
// Count points to test.
|
||||||
|
label nCandidates = 0;
|
||||||
|
forAll(namedSurfaceIndex, faceI)
|
||||||
|
{
|
||||||
|
label surfI = namedSurfaceIndex[faceI];
|
||||||
|
|
||||||
|
if (surfI != -1)
|
||||||
|
{
|
||||||
|
if (mesh_.isInternalFace(faceI))
|
||||||
|
{
|
||||||
|
nCandidates += 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nCandidates += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect points.
|
||||||
|
pointField candidatePoints(nCandidates);
|
||||||
|
nCandidates = 0;
|
||||||
forAll(namedSurfaceIndex, faceI)
|
forAll(namedSurfaceIndex, faceI)
|
||||||
{
|
{
|
||||||
label surfI = namedSurfaceIndex[faceI];
|
label surfI = namedSurfaceIndex[faceI];
|
||||||
@ -1236,55 +1293,65 @@ void Foam::meshRefinement::findCellZoneGeometric
|
|||||||
{
|
{
|
||||||
label nei = faceNeighbour[faceI];
|
label nei = faceNeighbour[faceI];
|
||||||
const point& neiCc = cellCentres[nei];
|
const point& neiCc = cellCentres[nei];
|
||||||
|
// Perturbed cc
|
||||||
const vector d = 1E-4*(neiCc - ownCc);
|
const vector d = 1E-4*(neiCc - ownCc);
|
||||||
|
candidatePoints[nCandidates++] = ownCc-d;
|
||||||
|
candidatePoints[nCandidates++] = neiCc+d;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const point& neiFc = mesh_.faceCentres()[faceI];
|
||||||
|
// Perturbed cc
|
||||||
|
const vector d = 1E-4*(neiFc - ownCc);
|
||||||
|
candidatePoints[nCandidates++] = ownCc-d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Test perturbed owner
|
|
||||||
|
// 2. Test points for inside
|
||||||
|
|
||||||
|
surfaces_.findInside
|
||||||
|
(
|
||||||
|
closedNamedSurfaces,
|
||||||
|
candidatePoints,
|
||||||
|
insideSurfaces
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// 3. Update zone information
|
||||||
|
|
||||||
|
nCandidates = 0;
|
||||||
|
forAll(namedSurfaceIndex, faceI)
|
||||||
|
{
|
||||||
|
label surfI = namedSurfaceIndex[faceI];
|
||||||
|
|
||||||
|
if (surfI != -1)
|
||||||
|
{
|
||||||
|
label own = faceOwner[faceI];
|
||||||
|
|
||||||
|
if (mesh_.isInternalFace(faceI))
|
||||||
|
{
|
||||||
|
label ownSurfI = insideSurfaces[nCandidates++];
|
||||||
|
if (ownSurfI != -1)
|
||||||
{
|
{
|
||||||
label ownSurfI = surfaces_.insideZone
|
cellToZone[own] = surfaceToCellZone[ownSurfI];
|
||||||
(
|
|
||||||
closedNamedSurfaces,
|
|
||||||
ownCc-d
|
|
||||||
);
|
|
||||||
|
|
||||||
if (ownSurfI != -1)
|
|
||||||
{
|
|
||||||
cellToZone[own] = surfaceToCellZone[ownSurfI];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test perturbed neighbour
|
label neiSurfI = insideSurfaces[nCandidates++];
|
||||||
|
if (neiSurfI != -1)
|
||||||
{
|
{
|
||||||
label neiSurfI = surfaces_.insideZone
|
label nei = faceNeighbour[faceI];
|
||||||
(
|
|
||||||
closedNamedSurfaces,
|
|
||||||
neiCc+d
|
|
||||||
);
|
|
||||||
|
|
||||||
if (neiSurfI != -1)
|
cellToZone[nei] = surfaceToCellZone[neiSurfI];
|
||||||
{
|
|
||||||
cellToZone[nei] = surfaceToCellZone[neiSurfI];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const point& neiCc = mesh_.faceCentres()[faceI];
|
label ownSurfI = insideSurfaces[nCandidates++];
|
||||||
|
if (ownSurfI != -1)
|
||||||
const vector d = 1E-4*(neiCc - ownCc);
|
|
||||||
|
|
||||||
// Test perturbed owner
|
|
||||||
{
|
{
|
||||||
label ownSurfI = surfaces_.insideZone
|
cellToZone[own] = surfaceToCellZone[ownSurfI];
|
||||||
(
|
|
||||||
closedNamedSurfaces,
|
|
||||||
ownCc-d
|
|
||||||
);
|
|
||||||
|
|
||||||
if (ownSurfI != -1)
|
|
||||||
{
|
|
||||||
cellToZone[own] = surfaceToCellZone[ownSurfI];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2291,7 +2358,7 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::zonify
|
|||||||
|
|
||||||
isNamedSurface[surfI] = true;
|
isNamedSurface[surfI] = true;
|
||||||
|
|
||||||
Info<< "Surface : " << surfaces_[surfI].searchableSurface::name() << nl
|
Info<< "Surface : " << surfaces_.names()[surfI] << nl
|
||||||
<< " faceZone : " << faceZoneNames[surfI] << nl
|
<< " faceZone : " << faceZoneNames[surfI] << nl
|
||||||
<< " cellZone : " << cellZoneNames[surfI] << endl;
|
<< " cellZone : " << cellZoneNames[surfI] << endl;
|
||||||
}
|
}
|
||||||
@ -2329,7 +2396,7 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::zonify
|
|||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
{
|
{
|
||||||
Pout<< "Faces on " << surfaces_[surfI].searchableSurface::name()
|
Pout<< "Faces on " << surfaces_.names()[surfI]
|
||||||
<< " will go into faceZone " << zoneI << endl;
|
<< " will go into faceZone " << zoneI << endl;
|
||||||
}
|
}
|
||||||
surfaceToFaceZone[surfI] = zoneI;
|
surfaceToFaceZone[surfI] = zoneI;
|
||||||
@ -2387,8 +2454,7 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::zonify
|
|||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
{
|
{
|
||||||
Pout<< "Cells inside "
|
Pout<< "Cells inside " << surfaces_.names()[surfI]
|
||||||
<< surfaces_[surfI].searchableSurface::name()
|
|
||||||
<< " will go into cellZone " << zoneI << endl;
|
<< " will go into cellZone " << zoneI << endl;
|
||||||
}
|
}
|
||||||
surfaceToCellZone[surfI] = zoneI;
|
surfaceToCellZone[surfI] = zoneI;
|
||||||
@ -2444,78 +2510,83 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::zonify
|
|||||||
// Note: for all internal faces? internal + coupled?
|
// Note: for all internal faces? internal + coupled?
|
||||||
// Since zonify is run after baffling the surfaceIndex_ on baffles is
|
// Since zonify is run after baffling the surfaceIndex_ on baffles is
|
||||||
// not synchronised across both baffle faces. Fortunately we don't
|
// not synchronised across both baffle faces. Fortunately we don't
|
||||||
// do zonify baffle faces anyway.
|
// do zonify baffle faces anyway (they are normal boundary faces).
|
||||||
forAll(surfaceIndex_, faceI)
|
|
||||||
|
// Collect candidate faces
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
labelList testFaces(intersectedFaces());
|
||||||
|
|
||||||
|
// Collect segments
|
||||||
|
// ~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
pointField start(testFaces.size());
|
||||||
|
pointField end(testFaces.size());
|
||||||
|
|
||||||
|
forAll(testFaces, i)
|
||||||
{
|
{
|
||||||
label surfI = surfaceIndex_[faceI];
|
label faceI = testFaces[i];
|
||||||
|
|
||||||
if
|
label own = mesh_.faceOwner()[faceI];
|
||||||
(
|
|
||||||
surfI != -1
|
if (mesh_.isInternalFace(faceI))
|
||||||
&& (
|
|
||||||
mesh_.isInternalFace(faceI)
|
|
||||||
|| patches[patches.whichPatch(faceI)].coupled()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (isNamedSurface[surfI])
|
start[i] = cellCentres[own];
|
||||||
{
|
end[i] = cellCentres[mesh_.faceNeighbour()[faceI]];
|
||||||
namedSurfaceIndex[faceI] = surfI;
|
}
|
||||||
nSurfFaces[surfI]++;
|
else
|
||||||
}
|
{
|
||||||
else
|
start[i] = cellCentres[own];
|
||||||
{
|
end[i] = neiCc[faceI-mesh_.nInternalFaces()];
|
||||||
// Test more accurately for whether intersection is at
|
|
||||||
// zoneable surface
|
|
||||||
|
|
||||||
label surface1, surface2;
|
|
||||||
pointIndexHit hit1, hit2;
|
|
||||||
|
|
||||||
if (mesh_.isInternalFace(faceI))
|
|
||||||
{
|
|
||||||
surfaces_.findNearestIntersection
|
|
||||||
(
|
|
||||||
namedSurfaces,
|
|
||||||
cellCentres[faceOwner[faceI]],
|
|
||||||
cellCentres[faceNeighbour[faceI]],
|
|
||||||
|
|
||||||
surface1,
|
|
||||||
hit1,
|
|
||||||
surface2,
|
|
||||||
hit2
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
surfaces_.findNearestIntersection
|
|
||||||
(
|
|
||||||
namedSurfaces,
|
|
||||||
cellCentres[faceOwner[faceI]],
|
|
||||||
neiCc[faceI-mesh_.nInternalFaces()],
|
|
||||||
|
|
||||||
surface1,
|
|
||||||
hit1,
|
|
||||||
surface2,
|
|
||||||
hit2
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hit1.hit())
|
|
||||||
{
|
|
||||||
// If both hit should probably choose nearest. For
|
|
||||||
// later.
|
|
||||||
namedSurfaceIndex[faceI] = surface1;
|
|
||||||
nSurfFaces[surface1]++;
|
|
||||||
}
|
|
||||||
else if (hit2.hit())
|
|
||||||
{
|
|
||||||
namedSurfaceIndex[faceI] = surface2;
|
|
||||||
nSurfFaces[surface2]++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Do test for intersections
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// Note that we intersect all intersected faces again. Could reuse
|
||||||
|
// the information already in surfaceIndex_.
|
||||||
|
|
||||||
|
labelList surface1;
|
||||||
|
labelList surface2;
|
||||||
|
{
|
||||||
|
List<pointIndexHit> hit1;
|
||||||
|
labelList region1;
|
||||||
|
List<pointIndexHit> hit2;
|
||||||
|
labelList region2;
|
||||||
|
surfaces_.findNearestIntersection
|
||||||
|
(
|
||||||
|
namedSurfaces,
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
|
||||||
|
surface1,
|
||||||
|
hit1,
|
||||||
|
region1,
|
||||||
|
surface2,
|
||||||
|
hit2,
|
||||||
|
region2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
forAll(testFaces, i)
|
||||||
|
{
|
||||||
|
label faceI = testFaces[i];
|
||||||
|
|
||||||
|
if (surface1[i] != -1)
|
||||||
|
{
|
||||||
|
// If both hit should probably choose nearest. For later.
|
||||||
|
namedSurfaceIndex[faceI] = surface1[i];
|
||||||
|
nSurfFaces[surface1[i]]++;
|
||||||
|
}
|
||||||
|
else if (surface2[i] != -1)
|
||||||
|
{
|
||||||
|
namedSurfaceIndex[faceI] = surface2[i];
|
||||||
|
nSurfFaces[surface2[i]]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// surfaceIndex migh have different surfaces on both sides if
|
// surfaceIndex migh have different surfaces on both sides if
|
||||||
// there happen to be a (obviously thin) surface with different
|
// there happen to be a (obviously thin) surface with different
|
||||||
// regions between the cell centres. If one is on a named surface
|
// regions between the cell centres. If one is on a named surface
|
||||||
@ -2534,7 +2605,7 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::zonify
|
|||||||
forAll(nSurfFaces, surfI)
|
forAll(nSurfFaces, surfI)
|
||||||
{
|
{
|
||||||
Pout<< "Surface:"
|
Pout<< "Surface:"
|
||||||
<< surfaces_[surfI].searchableSurface::name()
|
<< surfaces_.names()[surfI]
|
||||||
<< " nZoneFaces:" << nSurfFaces[surfI] << nl;
|
<< " nZoneFaces:" << nSurfFaces[surfI] << nl;
|
||||||
}
|
}
|
||||||
Pout<< endl;
|
Pout<< endl;
|
||||||
@ -2591,7 +2662,7 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::zonify
|
|||||||
(
|
(
|
||||||
mesh_.faces()[faceI], // modified face
|
mesh_.faces()[faceI], // modified face
|
||||||
faceI, // label of face
|
faceI, // label of face
|
||||||
faceOwner[faceI], // owner
|
faceOwner[faceI], // owner
|
||||||
-1, // neighbour
|
-1, // neighbour
|
||||||
false, // face flip
|
false, // face flip
|
||||||
patchI, // patch for face
|
patchI, // patch for face
|
||||||
@ -2609,20 +2680,8 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::zonify
|
|||||||
// Put the cells into the correct zone
|
// Put the cells into the correct zone
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
labelList closedNamedSurfaces(namedSurfaces.size());
|
// Closed surfaces with cellZone specified.
|
||||||
label nClosed = 0;
|
labelList closedNamedSurfaces(surfaces_.getClosedNamedSurfaces());
|
||||||
|
|
||||||
forAll(namedSurfaces, i)
|
|
||||||
{
|
|
||||||
label surfI = namedSurfaces[i];
|
|
||||||
|
|
||||||
if (surfaces_.closed()[surfI])
|
|
||||||
{
|
|
||||||
closedNamedSurfaces[nClosed++] = surfI;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
closedNamedSurfaces.setSize(nClosed);
|
|
||||||
|
|
||||||
|
|
||||||
// Zone per cell:
|
// Zone per cell:
|
||||||
// -2 : unset
|
// -2 : unset
|
||||||
@ -2704,13 +2763,4 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::zonify
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
|
|||||||
@ -30,15 +30,9 @@ License
|
|||||||
#include "removePoints.H"
|
#include "removePoints.H"
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
// Merge faces that are in-line.
|
// Merge faces that are in-line.
|
||||||
@ -244,13 +238,4 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::mergeEdges
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -38,34 +38,38 @@ SourceFiles
|
|||||||
#ifndef refinementSurfaces_H
|
#ifndef refinementSurfaces_H
|
||||||
#define refinementSurfaces_H
|
#define refinementSurfaces_H
|
||||||
|
|
||||||
#include "triSurfaceMeshes.H"
|
|
||||||
#include "PackedList.H"
|
#include "PackedList.H"
|
||||||
#include "triSurfaceGeoMesh.H"
|
#include "triSurfaceGeoMesh.H"
|
||||||
#include "triSurfaceFields.H"
|
#include "triSurfaceFields.H"
|
||||||
|
#include "vectorList.H"
|
||||||
|
#include "pointIndexHit.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
namespace Foam
|
namespace Foam
|
||||||
{
|
{
|
||||||
|
|
||||||
class searchableSurface;
|
class searchableSurfaces;
|
||||||
|
class shellSurfaces;
|
||||||
|
class triSurfaceMesh;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
/*---------------------------------------------------------------------------*\
|
||||||
Class refinementSurfaces Declaration
|
Class refinementSurfaces Declaration
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
class refinementSurfaces
|
class refinementSurfaces
|
||||||
:
|
|
||||||
public triSurfaceMeshes
|
|
||||||
{
|
{
|
||||||
// Private data
|
// Private data
|
||||||
|
|
||||||
|
//- Reference to all geometry.
|
||||||
|
const searchableSurfaces& allGeometry_;
|
||||||
|
|
||||||
|
//- Indices of surfaces that are refinement ones
|
||||||
|
labelList surfaces_;
|
||||||
|
|
||||||
//- Surface name (word)
|
//- Surface name (word)
|
||||||
wordList names_;
|
wordList names_;
|
||||||
|
|
||||||
//- Per surface whether is closed
|
|
||||||
boolList closed_;
|
|
||||||
|
|
||||||
//- Per 'interface' surface : name of faceZone to put faces into
|
//- Per 'interface' surface : name of faceZone to put faces into
|
||||||
wordList faceZoneNames_;
|
wordList faceZoneNames_;
|
||||||
|
|
||||||
@ -86,24 +90,12 @@ 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_;
|
||||||
|
|
||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
|
|
||||||
static fileNameList extractFileNames(const PtrList<dictionary>&);
|
|
||||||
|
|
||||||
//- Disallow default bitwise copy construct
|
//- Disallow default bitwise copy construct
|
||||||
refinementSurfaces(const refinementSurfaces&);
|
refinementSurfaces(const refinementSurfaces&);
|
||||||
|
|
||||||
@ -115,30 +107,36 @@ public:
|
|||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
//- Construct from directory (io.instance()) and dictionaries
|
//- Construct from surfaces and dictionaries
|
||||||
refinementSurfaces
|
refinementSurfaces
|
||||||
(
|
(
|
||||||
const IOobject& io,
|
const searchableSurfaces& allGeometry,
|
||||||
const PtrList<dictionary>&
|
const PtrList<dictionary>&
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//- Construct from surfaces and dictionary
|
||||||
|
refinementSurfaces
|
||||||
|
(
|
||||||
|
const searchableSurfaces& allGeometry,
|
||||||
|
const dictionary&
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
|
|
||||||
// Access
|
// Access
|
||||||
|
|
||||||
|
const labelList& surfaces() const
|
||||||
|
{
|
||||||
|
return surfaces_;
|
||||||
|
}
|
||||||
|
|
||||||
//- Names of surfaces
|
//- Names of surfaces
|
||||||
const wordList& names() const
|
const wordList& names() const
|
||||||
{
|
{
|
||||||
return names_;
|
return names_;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Per surface whether is closed
|
|
||||||
const boolList& closed() const
|
|
||||||
{
|
|
||||||
return closed_;
|
|
||||||
}
|
|
||||||
|
|
||||||
//- Per 'interface' surface : name of faceZone to put faces into
|
//- Per 'interface' surface : name of faceZone to put faces into
|
||||||
const wordList& faceZoneNames() const
|
const wordList& faceZoneNames() const
|
||||||
{
|
{
|
||||||
@ -151,15 +149,11 @@ public:
|
|||||||
return cellZoneNames_;
|
return cellZoneNames_;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Per 'interface' surface : if closed: zonify cells inside surface
|
|
||||||
const boolList& zoneInside() const
|
|
||||||
{
|
|
||||||
return zoneInside_;
|
|
||||||
}
|
|
||||||
|
|
||||||
//- Get indices of named surfaces (surfaces with cellZoneName)
|
//- Get indices of named surfaces (surfaces with cellZoneName)
|
||||||
labelList getNamedSurfaces() const;
|
labelList getNamedSurfaces() const;
|
||||||
|
|
||||||
|
//- Get indices of closed named surfaces
|
||||||
|
labelList getClosedNamedSurfaces() const;
|
||||||
|
|
||||||
//- From local region number to global region number
|
//- From local region number to global region number
|
||||||
const labelList& regionOffset() const
|
const labelList& regionOffset() const
|
||||||
@ -179,24 +173,6 @@ 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
|
||||||
|
|
||||||
@ -206,14 +182,6 @@ public:
|
|||||||
return regionOffset_[surfI]+regionI;
|
return regionOffset_[surfI]+regionI;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- From triangle on surface to global region
|
|
||||||
label triangleRegion(const label surfI, const label triI) const
|
|
||||||
{
|
|
||||||
const triSurface& s = operator[](surfI);
|
|
||||||
|
|
||||||
return globalRegion(surfI, s[triI].region());
|
|
||||||
}
|
|
||||||
|
|
||||||
//- Min level for surface and region on surface
|
//- Min level for surface and region on surface
|
||||||
label minLevel(const label surfI, const label regionI) const
|
label minLevel(const label surfI, const label regionI) const
|
||||||
{
|
{
|
||||||
@ -231,23 +199,12 @@ public:
|
|||||||
return minLevel_.size();
|
return minLevel_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Minlevel updated for refinement shells
|
|
||||||
const triSurfaceLabelField& minLevelField(const label surfI) const
|
|
||||||
{
|
|
||||||
return minLevelFields_[surfI];
|
|
||||||
}
|
|
||||||
|
|
||||||
//- Calculate minLevelFields
|
//- Calculate minLevelFields
|
||||||
void setMinLevelFields
|
void setMinLevelFields
|
||||||
(
|
(
|
||||||
const PtrList<searchableSurface>& shells,
|
const shellSurfaces& shells
|
||||||
const labelList& shellLevels,
|
|
||||||
const boolList& shellRefineInside
|
|
||||||
);
|
);
|
||||||
|
|
||||||
//- Helper: is surface closed?
|
|
||||||
static bool isSurfaceClosed(const triSurface&);
|
|
||||||
|
|
||||||
//- Helper: orient (closed only) surfaces so keepPoint is outside.
|
//- Helper: orient (closed only) surfaces so keepPoint is outside.
|
||||||
static void orientSurface
|
static void orientSurface
|
||||||
(
|
(
|
||||||
@ -263,36 +220,71 @@ public:
|
|||||||
|
|
||||||
//- Find intersection of edge. Return -1 or first surface
|
//- Find intersection of edge. Return -1 or first surface
|
||||||
// with higher (than currentLevel) minlevel.
|
// with higher (than currentLevel) minlevel.
|
||||||
// Return surface number and hit info.
|
// Return surface number and level.
|
||||||
label findHigherIntersection
|
void findHigherIntersection
|
||||||
(
|
(
|
||||||
const point& start,
|
const pointField& start,
|
||||||
const point& end,
|
const pointField& end,
|
||||||
const label currentLevel, // current cell refinement level
|
const labelList& currentLevel, // current cell refinement level
|
||||||
pointIndexHit&
|
|
||||||
|
labelList& surfaces,
|
||||||
|
labelList& surfaceLevel
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
//- Find intersection with max level. Return -1 or the surface
|
//- Find all intersections of edge. Unsorted order.
|
||||||
// with the highest maxLevel above currentLevel
|
void findAllHigherIntersections
|
||||||
label findHighestIntersection
|
|
||||||
(
|
(
|
||||||
const point& start,
|
const pointField& start,
|
||||||
const point& end,
|
const pointField& end,
|
||||||
const label currentLevel, // current cell refinement level
|
const labelList& currentLevel, // current cell refinement level
|
||||||
pointIndexHit&
|
|
||||||
|
List<vectorList>& surfaceNormal,
|
||||||
|
labelListList& surfaceLevel
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
//- Detect if a point is 'inside' (depending on zoneInside flag) a
|
//- Find intersection nearest to the endpoints. surface1,2 are
|
||||||
// zoneable surface. Returns -1 if not, returns first surface it
|
// not indices into surfacesToTest but refinement surface indices.
|
||||||
// is.
|
void findNearestIntersection
|
||||||
label insideZone(const labelList& surfaces, const point& pt) const;
|
(
|
||||||
|
const labelList& surfacesToTest,
|
||||||
|
const pointField& start,
|
||||||
|
const pointField& end,
|
||||||
|
|
||||||
|
labelList& surface1,
|
||||||
|
List<pointIndexHit>& hit1,
|
||||||
|
labelList& region1,
|
||||||
|
labelList& surface2,
|
||||||
|
List<pointIndexHit>& hit2,
|
||||||
|
labelList& region2
|
||||||
|
) const;
|
||||||
|
|
||||||
//- Mark for all points whether it is inside any closed surface
|
//- Used for debugging only: find intersection of edge.
|
||||||
// Return number of inside points.
|
void findAnyIntersection
|
||||||
label markInsidePoints(const pointField&, PackedList<1>& isInside)
|
(
|
||||||
const;
|
const pointField& start,
|
||||||
|
const pointField& end,
|
||||||
|
labelList& surfaces,
|
||||||
|
List<pointIndexHit>&
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Find nearest point on surfaces.
|
||||||
|
void findNearest
|
||||||
|
(
|
||||||
|
const labelList& surfacesToTest,
|
||||||
|
const pointField& samples,
|
||||||
|
const scalarField& nearestDistSqr,
|
||||||
|
labelList& surfaces,
|
||||||
|
List<pointIndexHit>&
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Detect if a point is 'inside' (closed) surfaces.
|
||||||
|
// Returns -1 if not, returns first surface it is.
|
||||||
|
void findInside
|
||||||
|
(
|
||||||
|
const labelList& surfacesToTest,
|
||||||
|
const pointField& pt,
|
||||||
|
labelList& insideSurfaces
|
||||||
|
) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
465
src/autoMesh/autoHexMesh/shellSurfaces/shellSurfaces.C
Normal file
465
src/autoMesh/autoHexMesh/shellSurfaces/shellSurfaces.C
Normal file
@ -0,0 +1,465 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 1991-2008 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 2 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, write to the Free Software Foundation,
|
||||||
|
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "searchableSurface.H"
|
||||||
|
#include "shellSurfaces.H"
|
||||||
|
#include "boundBox.H"
|
||||||
|
#include "triSurfaceMesh.H"
|
||||||
|
#include "refinementSurfaces.H"
|
||||||
|
#include "searchableSurfaces.H"
|
||||||
|
#include "pointIndexHit.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
template<>
|
||||||
|
const char*
|
||||||
|
NamedEnum<shellSurfaces::refineMode, 3>::
|
||||||
|
names[] =
|
||||||
|
{
|
||||||
|
"inside",
|
||||||
|
"outside",
|
||||||
|
"distance"
|
||||||
|
};
|
||||||
|
|
||||||
|
const NamedEnum<shellSurfaces::refineMode, 3> shellSurfaces::refineModeNames_;
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::shellSurfaces::setAndCheckLevels
|
||||||
|
(
|
||||||
|
const scalar shellI,
|
||||||
|
const List<Tuple2<scalar, label> >& distLevels
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (modes_[shellI] != DISTANCE && distLevels.size() != 1)
|
||||||
|
{
|
||||||
|
FatalErrorIn
|
||||||
|
(
|
||||||
|
"shellSurfaces::shellSurfaces"
|
||||||
|
"(const searchableSurfaces&, const dictionary&)"
|
||||||
|
) << "For refinement mode "
|
||||||
|
<< refineModeNames_[modes_[shellI]]
|
||||||
|
<< " specify only one distance+level."
|
||||||
|
<< " (its distance gets discarded)"
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
// Extract information into separate distance and level
|
||||||
|
distances_[shellI].setSize(distLevels.size());
|
||||||
|
levels_[shellI].setSize(distLevels.size());
|
||||||
|
|
||||||
|
forAll(distLevels, j)
|
||||||
|
{
|
||||||
|
distances_[shellI][j] = distLevels[j].first();
|
||||||
|
levels_[shellI][j] = distLevels[j].second();
|
||||||
|
|
||||||
|
// Check in incremental order
|
||||||
|
if (j > 0)
|
||||||
|
{
|
||||||
|
if
|
||||||
|
(
|
||||||
|
(distances_[shellI][j] <= distances_[shellI][j-1])
|
||||||
|
|| (levels_[shellI][j] > levels_[shellI][j-1])
|
||||||
|
)
|
||||||
|
{
|
||||||
|
FatalErrorIn
|
||||||
|
(
|
||||||
|
"shellSurfaces::shellSurfaces"
|
||||||
|
"(const searchableSurfaces&, const dictionary&)"
|
||||||
|
) << "For refinement mode "
|
||||||
|
<< refineModeNames_[modes_[shellI]]
|
||||||
|
<< " : Refinement should be specified in order"
|
||||||
|
<< " of increasing distance"
|
||||||
|
<< " (and decreasing refinement level)." << endl
|
||||||
|
<< "Distance:" << distances_[shellI][j]
|
||||||
|
<< " refinementLevel:" << levels_[shellI][j]
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchableSurface& shell = allGeometry_[shells_[shellI]];
|
||||||
|
|
||||||
|
if (modes_[shellI] == DISTANCE)
|
||||||
|
{
|
||||||
|
Info<< "Refinement level according to distance to "
|
||||||
|
<< shell.name() << endl;
|
||||||
|
forAll(levels_[shellI], j)
|
||||||
|
{
|
||||||
|
Info<< " level " << levels_[shellI][j]
|
||||||
|
<< " for all cells within " << distances_[shellI][j]
|
||||||
|
<< " meter." << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!allGeometry_[shells_[shellI]].hasVolumeType())
|
||||||
|
{
|
||||||
|
FatalErrorIn
|
||||||
|
(
|
||||||
|
"shellSurfaces::shellSurfaces"
|
||||||
|
"(const searchableSurfaces&"
|
||||||
|
", const PtrList<dictionary>&)"
|
||||||
|
) << "Shell " << shell.name()
|
||||||
|
<< " does not support testing for "
|
||||||
|
<< refineModeNames_[modes_[shellI]] << endl
|
||||||
|
<< "Probably it is not closed."
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modes_[shellI] == INSIDE)
|
||||||
|
{
|
||||||
|
Info<< "Refinement level " << levels_[shellI][0]
|
||||||
|
<< " for all cells inside " << shell.name() << endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Info<< "Refinement level " << levels_[shellI][0]
|
||||||
|
<< " for all cells outside " << 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
|
||||||
|
void Foam::shellSurfaces::orient()
|
||||||
|
{
|
||||||
|
// Determine outside point.
|
||||||
|
boundBox overallBb
|
||||||
|
(
|
||||||
|
point(GREAT, GREAT, GREAT),
|
||||||
|
point(-GREAT, -GREAT, -GREAT)
|
||||||
|
);
|
||||||
|
|
||||||
|
bool hasSurface = false;
|
||||||
|
|
||||||
|
forAll(shells_, shellI)
|
||||||
|
{
|
||||||
|
const searchableSurface& s = allGeometry_[shells_[shellI]];
|
||||||
|
|
||||||
|
if (modes_[shellI] != DISTANCE && isA<triSurfaceMesh>(s))
|
||||||
|
{
|
||||||
|
const triSurfaceMesh& shell = refCast<const triSurfaceMesh>(s);
|
||||||
|
|
||||||
|
if (shell.triSurface::size() > 0)
|
||||||
|
{
|
||||||
|
const pointField& points = shell.points();
|
||||||
|
|
||||||
|
hasSurface = true;
|
||||||
|
|
||||||
|
boundBox shellBb(points[0], points[0]);
|
||||||
|
// Assume surface is compact!
|
||||||
|
for (label i = 0; i < points.size(); i++)
|
||||||
|
{
|
||||||
|
const point& pt = points[i];
|
||||||
|
shellBb.min() = min(shellBb.min(), pt);
|
||||||
|
shellBb.max() = max(shellBb.max(), pt);
|
||||||
|
}
|
||||||
|
|
||||||
|
overallBb.min() = min(overallBb.min(), shellBb.min());
|
||||||
|
overallBb.max() = max(overallBb.max(), shellBb.max());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasSurface)
|
||||||
|
{
|
||||||
|
const point outsidePt(2*overallBb.max() - overallBb.min());
|
||||||
|
|
||||||
|
//Info<< "Using point " << outsidePt << " to orient shells" << endl;
|
||||||
|
|
||||||
|
forAll(shells_, shellI)
|
||||||
|
{
|
||||||
|
const searchableSurface& s = allGeometry_[shells_[shellI]];
|
||||||
|
|
||||||
|
if (modes_[shellI] != DISTANCE && isA<triSurfaceMesh>(s))
|
||||||
|
{
|
||||||
|
triSurfaceMesh& shell = const_cast<triSurfaceMesh&>
|
||||||
|
(
|
||||||
|
refCast<const triSurfaceMesh>(s)
|
||||||
|
);
|
||||||
|
|
||||||
|
refinementSurfaces::orientSurface(outsidePt, shell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Find maximum level of a shell.
|
||||||
|
void Foam::shellSurfaces::findHigherLevel
|
||||||
|
(
|
||||||
|
const pointField& pt,
|
||||||
|
const label shellI,
|
||||||
|
labelList& maxLevel
|
||||||
|
) 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 maxLevel less than
|
||||||
|
// (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(maxLevel, pointI)
|
||||||
|
{
|
||||||
|
forAllReverse(levels, levelI)
|
||||||
|
{
|
||||||
|
if (levels[levelI] > maxLevel[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, candidateI)
|
||||||
|
{
|
||||||
|
if (nearInfo[candidateI].hit())
|
||||||
|
{
|
||||||
|
// Check which level it actually is in.
|
||||||
|
label minDistI = findLower
|
||||||
|
(
|
||||||
|
distances,
|
||||||
|
mag(nearInfo[candidateI].hitPoint()-candidates[candidateI])
|
||||||
|
);
|
||||||
|
|
||||||
|
label pointI = candidateMap[candidateI];
|
||||||
|
|
||||||
|
// pt is inbetween shell[minDistI] and shell[minDistI+1]
|
||||||
|
maxLevel[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(maxLevel, pointI)
|
||||||
|
{
|
||||||
|
if (levels[0] > maxLevel[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<searchableSurface::volumeType> volType;
|
||||||
|
allGeometry_[shells_[shellI]].getVolumeType(candidates, volType);
|
||||||
|
|
||||||
|
forAll(volType, i)
|
||||||
|
{
|
||||||
|
label pointI = candidateMap[i];
|
||||||
|
|
||||||
|
if
|
||||||
|
(
|
||||||
|
(
|
||||||
|
modes_[shellI] == INSIDE
|
||||||
|
&& volType[i] == searchableSurface::INSIDE
|
||||||
|
)
|
||||||
|
|| (
|
||||||
|
modes_[shellI] == OUTSIDE
|
||||||
|
&& volType[i] == searchableSurface::OUTSIDE
|
||||||
|
)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
maxLevel[pointI] = levels[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::shellSurfaces::shellSurfaces
|
||||||
|
(
|
||||||
|
const searchableSurfaces& allGeometry,
|
||||||
|
const PtrList<dictionary>& shellDicts
|
||||||
|
)
|
||||||
|
:
|
||||||
|
allGeometry_(allGeometry)
|
||||||
|
{
|
||||||
|
shells_.setSize(shellDicts.size());
|
||||||
|
modes_.setSize(shellDicts.size());
|
||||||
|
distances_.setSize(shellDicts.size());
|
||||||
|
levels_.setSize(shellDicts.size());
|
||||||
|
|
||||||
|
forAll(shellDicts, shellI)
|
||||||
|
{
|
||||||
|
const dictionary& dict = shellDicts[shellI];
|
||||||
|
const word name = dict.lookup("name");
|
||||||
|
const word type = dict.lookup("type");
|
||||||
|
|
||||||
|
shells_[shellI] = allGeometry_.findSurfaceID(name);
|
||||||
|
|
||||||
|
if (shells_[shellI] == -1)
|
||||||
|
{
|
||||||
|
FatalErrorIn
|
||||||
|
(
|
||||||
|
"shellSurfaces::shellSurfaces"
|
||||||
|
"(const searchableSurfaces&, const PtrList<dictionary>&)"
|
||||||
|
) << "No surface called " << name << endl
|
||||||
|
<< "Valid surfaces are " << allGeometry_.names()
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
modes_[shellI] = refineModeNames_.read(dict.lookup("refineMode"));
|
||||||
|
|
||||||
|
// Read pairs of distance+level
|
||||||
|
setAndCheckLevels(shellI, dict.lookup("levels"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Orient shell surfaces before any searching is done. Note that this
|
||||||
|
// only needs to be done for inside or outside. Orienting surfaces
|
||||||
|
// constructs lots of addressing which we want to avoid.
|
||||||
|
orient();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::shellSurfaces::shellSurfaces
|
||||||
|
(
|
||||||
|
const searchableSurfaces& allGeometry,
|
||||||
|
const dictionary& shellsDict
|
||||||
|
)
|
||||||
|
:
|
||||||
|
allGeometry_(allGeometry)
|
||||||
|
{
|
||||||
|
shells_.setSize(shellsDict.size());
|
||||||
|
modes_.setSize(shellsDict.size());
|
||||||
|
distances_.setSize(shellsDict.size());
|
||||||
|
levels_.setSize(shellsDict.size());
|
||||||
|
|
||||||
|
label shellI = 0;
|
||||||
|
forAllConstIter(dictionary, shellsDict, iter)
|
||||||
|
{
|
||||||
|
shells_[shellI] = allGeometry_.findSurfaceID(iter().keyword());
|
||||||
|
|
||||||
|
if (shells_[shellI] == -1)
|
||||||
|
{
|
||||||
|
FatalErrorIn
|
||||||
|
(
|
||||||
|
"shellSurfaces::shellSurfaces"
|
||||||
|
"(const searchableSurfaces&, const dictionary>&"
|
||||||
|
) << "No surface called " << iter().keyword() << endl
|
||||||
|
<< "Valid surfaces are " << allGeometry_.names()
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
const dictionary& dict = shellsDict.subDict(iter().keyword());
|
||||||
|
|
||||||
|
modes_[shellI] = refineModeNames_.read(dict.lookup("mode"));
|
||||||
|
|
||||||
|
// Read pairs of distance+level
|
||||||
|
setAndCheckLevels(shellI, dict.lookup("levels"));
|
||||||
|
|
||||||
|
shellI++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Orient shell surfaces before any searching is done. Note that this
|
||||||
|
// only needs to be done for inside or outside. Orienting surfaces
|
||||||
|
// constructs lots of addressing which we want to avoid.
|
||||||
|
orient();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
// Highest shell level
|
||||||
|
Foam::label Foam::shellSurfaces::maxLevel() const
|
||||||
|
{
|
||||||
|
label overallMax = 0;
|
||||||
|
forAll(levels_, shellI)
|
||||||
|
{
|
||||||
|
overallMax = max(overallMax, max(levels_[shellI]));
|
||||||
|
}
|
||||||
|
return overallMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::shellSurfaces::findHigherLevel
|
||||||
|
(
|
||||||
|
const pointField& pt,
|
||||||
|
const labelList& ptLevel,
|
||||||
|
labelList& maxLevel
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
// Maximum level of any shell. Start off with level of point.
|
||||||
|
maxLevel = ptLevel;
|
||||||
|
|
||||||
|
forAll(shells_, shellI)
|
||||||
|
{
|
||||||
|
findHigherLevel(pt, shellI, maxLevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
182
src/autoMesh/autoHexMesh/shellSurfaces/shellSurfaces.H
Normal file
182
src/autoMesh/autoHexMesh/shellSurfaces/shellSurfaces.H
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 1991-2008 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 2 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, write to the Free Software Foundation,
|
||||||
|
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
Class
|
||||||
|
shellSurfaces
|
||||||
|
|
||||||
|
Description
|
||||||
|
Encapsulates queries for volume refinement ('refine all cells within
|
||||||
|
shell').
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
shellSurfaces.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef shellSurfaces_H
|
||||||
|
#define shellSurfaces_H
|
||||||
|
|
||||||
|
#include "searchableSurface.H"
|
||||||
|
#include "Tuple2.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
class searchableSurfaces;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class shellSurfaces Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class shellSurfaces
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Public data types
|
||||||
|
|
||||||
|
//- Volume refinement controls
|
||||||
|
enum refineMode
|
||||||
|
{
|
||||||
|
INSIDE, // Refine all inside shell
|
||||||
|
OUTSIDE, // ,, outside
|
||||||
|
DISTANCE // Refine based on distance to shell
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Private data
|
||||||
|
|
||||||
|
//- Reference to all geometry.
|
||||||
|
const searchableSurfaces& allGeometry_;
|
||||||
|
|
||||||
|
//- Indices of surfaces that are shells
|
||||||
|
labelList shells_;
|
||||||
|
|
||||||
|
//- Per shell whether to refine inside or outside
|
||||||
|
List<refineMode> modes_;
|
||||||
|
|
||||||
|
//- Per shell the list of ranges
|
||||||
|
List<scalarField> distances_;
|
||||||
|
|
||||||
|
//- Per shell per distance the refinement level
|
||||||
|
labelListList levels_;
|
||||||
|
|
||||||
|
|
||||||
|
// Private data
|
||||||
|
|
||||||
|
//- refineMode names
|
||||||
|
static const NamedEnum<refineMode, 3> refineModeNames_;
|
||||||
|
|
||||||
|
|
||||||
|
// Private Member Functions
|
||||||
|
|
||||||
|
//- Helper function for initialisation.
|
||||||
|
void setAndCheckLevels
|
||||||
|
(
|
||||||
|
const scalar shellI,
|
||||||
|
const List<Tuple2<scalar, label> >&
|
||||||
|
);
|
||||||
|
|
||||||
|
void orient();
|
||||||
|
|
||||||
|
void findHigherLevel
|
||||||
|
(
|
||||||
|
const pointField& pt,
|
||||||
|
const label shellI,
|
||||||
|
labelList& maxLevel
|
||||||
|
) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct from components
|
||||||
|
shellSurfaces
|
||||||
|
(
|
||||||
|
const searchableSurfaces& allGeometry,
|
||||||
|
const labelList& shells,
|
||||||
|
const List<refineMode>& modes,
|
||||||
|
const List<scalarField>& distances,
|
||||||
|
const labelListList& levels
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Construct from geometry and dictionaries
|
||||||
|
shellSurfaces
|
||||||
|
(
|
||||||
|
const searchableSurfaces& allGeometry,
|
||||||
|
const PtrList<dictionary>& shellDicts
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Construct from geometry and dictionary
|
||||||
|
shellSurfaces
|
||||||
|
(
|
||||||
|
const searchableSurfaces& allGeometry,
|
||||||
|
const dictionary& shellsDict
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
// Access
|
||||||
|
|
||||||
|
//const List<scalarField>& distances() const
|
||||||
|
//{
|
||||||
|
// return distances_;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
////- Per shell per distance the refinement level
|
||||||
|
//const labelListList& levels() const
|
||||||
|
//{
|
||||||
|
// return levels_;
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
// Query
|
||||||
|
|
||||||
|
//- Highest shell level
|
||||||
|
label maxLevel() const;
|
||||||
|
|
||||||
|
//- Find shell level higher than ptLevel
|
||||||
|
void findHigherLevel
|
||||||
|
(
|
||||||
|
const pointField& pt,
|
||||||
|
const labelList& ptLevel,
|
||||||
|
labelList& maxLevel
|
||||||
|
) const;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -256,7 +256,7 @@ Foam::Ostream& Foam::operator<<
|
|||||||
const ExactParticle<ParticleType>& p
|
const ExactParticle<ParticleType>& p
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return operator<<(os, static_cast<Particle<ParticleType> >(p));
|
return operator<<(os, static_cast<const Particle<ParticleType>&>(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -553,7 +553,7 @@ Foam::labelListList Foam::addPatchCellLayer::addedCells() const
|
|||||||
|
|
||||||
void Foam::addPatchCellLayer::setRefinement
|
void Foam::addPatchCellLayer::setRefinement
|
||||||
(
|
(
|
||||||
const scalar expansionRatio,
|
const scalarField& expansionRatio,
|
||||||
const indirectPrimitivePatch& pp,
|
const indirectPrimitivePatch& pp,
|
||||||
const labelList& nFaceLayers,
|
const labelList& nFaceLayers,
|
||||||
const labelList& nPointLayers,
|
const labelList& nPointLayers,
|
||||||
@ -885,7 +885,7 @@ void Foam::addPatchCellLayer::setRefinement
|
|||||||
|
|
||||||
addedPoints_[patchPointI][i] = addedVertI;
|
addedPoints_[patchPointI][i] = addedVertI;
|
||||||
|
|
||||||
disp *= expansionRatio;
|
disp *= expansionRatio[patchPointI];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -305,7 +305,7 @@ public:
|
|||||||
// (instead of e.g. from patch faces)
|
// (instead of e.g. from patch faces)
|
||||||
void setRefinement
|
void setRefinement
|
||||||
(
|
(
|
||||||
const scalar expansionRatio,
|
const scalarField& expansionRatio,
|
||||||
const indirectPrimitivePatch& pp,
|
const indirectPrimitivePatch& pp,
|
||||||
const labelList& nFaceLayers,
|
const labelList& nFaceLayers,
|
||||||
const labelList& nPointLayers,
|
const labelList& nPointLayers,
|
||||||
@ -325,7 +325,7 @@ public:
|
|||||||
{
|
{
|
||||||
setRefinement
|
setRefinement
|
||||||
(
|
(
|
||||||
1.0, // expansion ration
|
scalarField(pp.nPoints(), 1.0), // expansion ration
|
||||||
pp,
|
pp,
|
||||||
labelList(pp.size(), nLayers),
|
labelList(pp.size(), nLayers),
|
||||||
labelList(pp.nPoints(), nLayers),
|
labelList(pp.nPoints(), nLayers),
|
||||||
|
|||||||
@ -53,6 +53,14 @@ indexedOctree/treeDataFace.C
|
|||||||
indexedOctree/treeDataPoint.C
|
indexedOctree/treeDataPoint.C
|
||||||
indexedOctree/treeDataTriSurface.C
|
indexedOctree/treeDataTriSurface.C
|
||||||
|
|
||||||
|
searchableSurface = searchableSurface
|
||||||
|
$(searchableSurface)/searchableBox.C
|
||||||
|
$(searchableSurface)/searchableSphere.C
|
||||||
|
$(searchableSurface)/searchableSurface.C
|
||||||
|
$(searchableSurface)/searchableSurfaces.C
|
||||||
|
$(searchableSurface)/searchableSurfacesQueries.C
|
||||||
|
$(searchableSurface)/triSurfaceMesh.C
|
||||||
|
|
||||||
topoSets = sets/topoSets
|
topoSets = sets/topoSets
|
||||||
$(topoSets)/cellSet.C
|
$(topoSets)/cellSet.C
|
||||||
$(topoSets)/topoSet.C
|
$(topoSets)/topoSet.C
|
||||||
@ -117,20 +125,10 @@ $(intersectedSurface)/intersectedSurface.C
|
|||||||
$(intersectedSurface)/edgeSurface.C
|
$(intersectedSurface)/edgeSurface.C
|
||||||
|
|
||||||
triSurface/triSurfaceSearch/triSurfaceSearch.C
|
triSurface/triSurfaceSearch/triSurfaceSearch.C
|
||||||
|
|
||||||
triSurface/octreeData/octreeDataTriSurface.C
|
triSurface/octreeData/octreeDataTriSurface.C
|
||||||
triSurface/octreeData/octreeDataTriSurfaceTreeLeaf.C
|
triSurface/octreeData/octreeDataTriSurfaceTreeLeaf.C
|
||||||
|
|
||||||
triSurface/triangleFuncs/triangleFuncs.C
|
triSurface/triangleFuncs/triangleFuncs.C
|
||||||
|
|
||||||
triSurface/searchableSurface/searchableSurface.C
|
|
||||||
triSurface/searchableSurface/triSurfaceMesh.C
|
|
||||||
triSurface/searchableSurface/searchableBox.C
|
|
||||||
|
|
||||||
triSurface/surfaceFeatures/surfaceFeatures.C
|
triSurface/surfaceFeatures/surfaceFeatures.C
|
||||||
|
|
||||||
triSurface/triSurfaceMeshes/triSurfaceMeshes.C
|
|
||||||
|
|
||||||
triSurface/triSurfaceTools/triSurfaceTools.C
|
triSurface/triSurfaceTools/triSurfaceTools.C
|
||||||
triSurface/triSurfaceTools/geompack/geompack.C
|
triSurface/triSurfaceTools/geompack/geompack.C
|
||||||
|
|
||||||
|
|||||||
541
src/meshTools/searchableSurface/searchableBox.C
Normal file
541
src/meshTools/searchableSurface/searchableBox.C
Normal file
@ -0,0 +1,541 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 1991-2007 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 2 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, write to the Free Software Foundation,
|
||||||
|
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "searchableBox.H"
|
||||||
|
#include "addToRunTimeSelectionTable.H"
|
||||||
|
#include "SortableList.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
defineTypeNameAndDebug(searchableBox, 0);
|
||||||
|
addToRunTimeSelectionTable(searchableSurface, searchableBox, dict);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::searchableBox::projectOntoCoordPlane
|
||||||
|
(
|
||||||
|
const direction dir,
|
||||||
|
const point& planePt,
|
||||||
|
pointIndexHit& info
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
// Set point
|
||||||
|
info.rawPoint()[dir] = planePt[dir];
|
||||||
|
// Set face
|
||||||
|
if (planePt[dir] == min()[dir])
|
||||||
|
{
|
||||||
|
info.setIndex(dir*2);
|
||||||
|
}
|
||||||
|
else if (planePt[dir] == max()[dir])
|
||||||
|
{
|
||||||
|
info.setIndex(dir*2+1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FatalErrorIn("searchableBox::projectOntoCoordPlane(..)")
|
||||||
|
<< "Point on plane " << planePt
|
||||||
|
<< " is not on coordinate " << min()[dir]
|
||||||
|
<< " nor " << max()[dir] << abort(FatalError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns miss or hit with face (0..5) and region(always 0)
|
||||||
|
Foam::pointIndexHit Foam::searchableBox::findNearest
|
||||||
|
(
|
||||||
|
const point& bbMid,
|
||||||
|
const point& sample,
|
||||||
|
const scalar nearestDistSqr
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
// Point can be inside or outside. For every component direction can be
|
||||||
|
// left of min, right of max or inbetween.
|
||||||
|
// - outside points: project first one x plane (either min().x()
|
||||||
|
// or max().x()), then onto y plane and finally z. You should be left
|
||||||
|
// with intersection point
|
||||||
|
// - inside point: find nearest side (compare to mid point). Project onto
|
||||||
|
// that.
|
||||||
|
|
||||||
|
// The face is set to the last projected face.
|
||||||
|
|
||||||
|
|
||||||
|
// Outside point projected onto cube. Assume faces 0..5.
|
||||||
|
pointIndexHit info(true, sample, -1);
|
||||||
|
bool outside = false;
|
||||||
|
|
||||||
|
// (for internal points) per direction what nearest cube side is
|
||||||
|
point near;
|
||||||
|
|
||||||
|
for (direction dir = 0; dir < vector::nComponents; dir++)
|
||||||
|
{
|
||||||
|
if (info.rawPoint()[dir] < min()[dir])
|
||||||
|
{
|
||||||
|
projectOntoCoordPlane(dir, min(), info);
|
||||||
|
outside = true;
|
||||||
|
}
|
||||||
|
else if (info.rawPoint()[dir] > max()[dir])
|
||||||
|
{
|
||||||
|
projectOntoCoordPlane(dir, max(), info);
|
||||||
|
outside = true;
|
||||||
|
}
|
||||||
|
else if (info.rawPoint()[dir] > bbMid[dir])
|
||||||
|
{
|
||||||
|
near[dir] = max()[dir];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
near[dir] = min()[dir];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// For outside points the info will be correct now. Handle inside points
|
||||||
|
// using the three near distances. Project onto the nearest plane.
|
||||||
|
if (!outside)
|
||||||
|
{
|
||||||
|
vector dist(cmptMag(info.rawPoint() - near));
|
||||||
|
|
||||||
|
if (dist.x() < dist.y())
|
||||||
|
{
|
||||||
|
if (dist.x() < dist.z())
|
||||||
|
{
|
||||||
|
// Project onto x plane
|
||||||
|
projectOntoCoordPlane(vector::X, near, info);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
projectOntoCoordPlane(vector::Z, near, info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (dist.y() < dist.z())
|
||||||
|
{
|
||||||
|
projectOntoCoordPlane(vector::Y, near, info);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
projectOntoCoordPlane(vector::Z, near, info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Check if outside. Optimisation: could do some checks on distance already
|
||||||
|
// on components above
|
||||||
|
if (magSqr(info.rawPoint() - sample) > nearestDistSqr)
|
||||||
|
{
|
||||||
|
info.setMiss();
|
||||||
|
info.setIndex(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::searchableBox::searchableBox
|
||||||
|
(
|
||||||
|
const IOobject& io,
|
||||||
|
const treeBoundBox& bb
|
||||||
|
)
|
||||||
|
:
|
||||||
|
searchableSurface(io),
|
||||||
|
treeBoundBox(bb)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::searchableBox::searchableBox
|
||||||
|
(
|
||||||
|
const IOobject& io,
|
||||||
|
const dictionary& dict
|
||||||
|
)
|
||||||
|
:
|
||||||
|
searchableSurface(io),
|
||||||
|
treeBoundBox(dict.lookup("min"), dict.lookup("max"))
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::searchableBox::~searchableBox()
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
const Foam::wordList& Foam::searchableBox::regions() const
|
||||||
|
{
|
||||||
|
if (regions_.size() == 0)
|
||||||
|
{
|
||||||
|
regions_.setSize(1);
|
||||||
|
regions_[0] = "region0";
|
||||||
|
}
|
||||||
|
return regions_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::pointIndexHit Foam::searchableBox::findNearest
|
||||||
|
(
|
||||||
|
const point& sample,
|
||||||
|
const scalar nearestDistSqr
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
return findNearest(mid(), sample, nearestDistSqr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::pointIndexHit Foam::searchableBox::findNearestOnEdge
|
||||||
|
(
|
||||||
|
const point& sample,
|
||||||
|
const scalar nearestDistSqr
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
const point bbMid(mid());
|
||||||
|
|
||||||
|
// Outside point projected onto cube. Assume faces 0..5.
|
||||||
|
pointIndexHit info(true, sample, -1);
|
||||||
|
bool outside = false;
|
||||||
|
|
||||||
|
// (for internal points) per direction what nearest cube side is
|
||||||
|
point near;
|
||||||
|
|
||||||
|
for (direction dir = 0; dir < vector::nComponents; dir++)
|
||||||
|
{
|
||||||
|
if (info.rawPoint()[dir] < min()[dir])
|
||||||
|
{
|
||||||
|
projectOntoCoordPlane(dir, min(), info);
|
||||||
|
outside = true;
|
||||||
|
}
|
||||||
|
else if (info.rawPoint()[dir] > max()[dir])
|
||||||
|
{
|
||||||
|
projectOntoCoordPlane(dir, max(), info);
|
||||||
|
outside = true;
|
||||||
|
}
|
||||||
|
else if (info.rawPoint()[dir] > bbMid[dir])
|
||||||
|
{
|
||||||
|
near[dir] = max()[dir];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
near[dir] = min()[dir];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// For outside points the info will be correct now. Handle inside points
|
||||||
|
// using the three near distances. Project onto the nearest two planes.
|
||||||
|
if (!outside)
|
||||||
|
{
|
||||||
|
// Get the per-component distance to nearest wall
|
||||||
|
vector dist(cmptMag(info.rawPoint() - near));
|
||||||
|
|
||||||
|
SortableList<scalar> sortedDist(3);
|
||||||
|
sortedDist[0] = dist[0];
|
||||||
|
sortedDist[1] = dist[1];
|
||||||
|
sortedDist[2] = dist[2];
|
||||||
|
sortedDist.sort();
|
||||||
|
|
||||||
|
// Project onto nearest
|
||||||
|
projectOntoCoordPlane(sortedDist.indices()[0], near, info);
|
||||||
|
// Project onto second nearest
|
||||||
|
projectOntoCoordPlane(sortedDist.indices()[1], near, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Check if outside. Optimisation: could do some checks on distance already
|
||||||
|
// on components above
|
||||||
|
if (magSqr(info.rawPoint() - sample) > nearestDistSqr)
|
||||||
|
{
|
||||||
|
info.setMiss();
|
||||||
|
info.setIndex(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::pointIndexHit Foam::searchableBox::findNearest
|
||||||
|
(
|
||||||
|
const linePointRef& ln,
|
||||||
|
treeBoundBox& tightest,
|
||||||
|
point& linePoint
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
notImplemented
|
||||||
|
(
|
||||||
|
"searchableBox::findNearest"
|
||||||
|
"(const linePointRef&, treeBoundBox&, point&)"
|
||||||
|
);
|
||||||
|
return pointIndexHit();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::pointIndexHit Foam::searchableBox::findLine
|
||||||
|
(
|
||||||
|
const point& start,
|
||||||
|
const point& end
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
pointIndexHit info(false, start, -1);
|
||||||
|
|
||||||
|
bool foundInter;
|
||||||
|
|
||||||
|
if (posBits(start) == 0)
|
||||||
|
{
|
||||||
|
if (posBits(end) == 0)
|
||||||
|
{
|
||||||
|
// Both start and end inside.
|
||||||
|
foundInter = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// end is outside. Clip to bounding box.
|
||||||
|
foundInter = intersects(end, start, info.rawPoint());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// start is outside. Clip to bounding box.
|
||||||
|
foundInter = intersects(start, end, info.rawPoint());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Classify point
|
||||||
|
if (foundInter)
|
||||||
|
{
|
||||||
|
info.setHit();
|
||||||
|
|
||||||
|
for (direction dir = 0; dir < vector::nComponents; dir++)
|
||||||
|
{
|
||||||
|
if (info.rawPoint()[dir] == min()[dir])
|
||||||
|
{
|
||||||
|
info.setIndex(2*dir);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (info.rawPoint()[dir] == max()[dir])
|
||||||
|
{
|
||||||
|
info.setIndex(2*dir+1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.index() == -1)
|
||||||
|
{
|
||||||
|
FatalErrorIn("searchableBox::findLine(const point&, const point&)")
|
||||||
|
<< "point " << info.rawPoint()
|
||||||
|
<< " on segment " << start << end
|
||||||
|
<< " should be on face of " << *this
|
||||||
|
<< " but it isn't." << abort(FatalError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::pointIndexHit Foam::searchableBox::findLineAny
|
||||||
|
(
|
||||||
|
const point& start,
|
||||||
|
const point& end
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
return findLine(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::searchableBox::findNearest
|
||||||
|
(
|
||||||
|
const pointField& samples,
|
||||||
|
const scalarField& nearestDistSqr,
|
||||||
|
List<pointIndexHit>& info
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
info.setSize(samples.size());
|
||||||
|
|
||||||
|
const point bbMid(mid());
|
||||||
|
|
||||||
|
forAll(samples, i)
|
||||||
|
{
|
||||||
|
info[i] = findNearest(bbMid, samples[i], nearestDistSqr[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::searchableBox::findLine
|
||||||
|
(
|
||||||
|
const pointField& start,
|
||||||
|
const pointField& end,
|
||||||
|
List<pointIndexHit>& info
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
info.setSize(start.size());
|
||||||
|
|
||||||
|
forAll(start, i)
|
||||||
|
{
|
||||||
|
info[i] = findLine(start[i], end[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::searchableBox::findLineAny
|
||||||
|
(
|
||||||
|
const pointField& start,
|
||||||
|
const pointField& end,
|
||||||
|
List<pointIndexHit>& info
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
info.setSize(start.size());
|
||||||
|
|
||||||
|
forAll(start, i)
|
||||||
|
{
|
||||||
|
info[i] = findLineAny(start[i], end[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::searchableBox::findLineAll
|
||||||
|
(
|
||||||
|
const pointField& start,
|
||||||
|
const pointField& end,
|
||||||
|
List<List<pointIndexHit> >& info
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
info.setSize(start.size());
|
||||||
|
|
||||||
|
// Work array
|
||||||
|
DynamicList<pointIndexHit, 1, 1> hits;
|
||||||
|
|
||||||
|
// Tolerances
|
||||||
|
const vectorField dirVec(end-start);
|
||||||
|
const scalarField magSqrDirVec(magSqr(dirVec));
|
||||||
|
const vectorField smallVec
|
||||||
|
(
|
||||||
|
Foam::sqrt(SMALL)*dirVec
|
||||||
|
+ vector(ROOTVSMALL,ROOTVSMALL,ROOTVSMALL)
|
||||||
|
);
|
||||||
|
|
||||||
|
forAll(start, pointI)
|
||||||
|
{
|
||||||
|
hits.clear();
|
||||||
|
|
||||||
|
// Current starting point of ray.
|
||||||
|
point pt = start[pointI];
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
// See if any intersection between pt and end
|
||||||
|
pointIndexHit inter = findLine(pt, end[pointI]);
|
||||||
|
|
||||||
|
if (!inter.hit())
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
hits.append(inter);
|
||||||
|
|
||||||
|
pt = inter.hitPoint() + smallVec[pointI];
|
||||||
|
|
||||||
|
if (((pt-start[pointI])&dirVec[pointI]) > magSqrDirVec[pointI])
|
||||||
|
{
|
||||||
|
// Adding smallVec has taken us beyond end
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hits.shrink();
|
||||||
|
info[pointI].transfer(hits);
|
||||||
|
hits.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::searchableBox::getRegion
|
||||||
|
(
|
||||||
|
const List<pointIndexHit>& info,
|
||||||
|
labelList& region
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
region.setSize(info.size());
|
||||||
|
region = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::searchableBox::getNormal
|
||||||
|
(
|
||||||
|
const List<pointIndexHit>& info,
|
||||||
|
vectorField& normal
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
normal.setSize(info.size());
|
||||||
|
normal = vector::zero;
|
||||||
|
|
||||||
|
forAll(info, i)
|
||||||
|
{
|
||||||
|
if (info[i].hit())
|
||||||
|
{
|
||||||
|
normal[i] = treeBoundBox::faceNormals[info[i].index()];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Set to what?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::searchableBox::getVolumeType
|
||||||
|
(
|
||||||
|
const pointField& points,
|
||||||
|
List<volumeType>& volType
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
volType.setSize(points.size());
|
||||||
|
volType = INSIDE;
|
||||||
|
|
||||||
|
forAll(points, pointI)
|
||||||
|
{
|
||||||
|
const point& pt = points[pointI];
|
||||||
|
|
||||||
|
for (direction dir = 0; dir < vector::nComponents; dir++)
|
||||||
|
{
|
||||||
|
if (pt[dir] < min()[dir] || pt[dir] > max()[dir])
|
||||||
|
{
|
||||||
|
volType[pointI] = OUTSIDE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
249
src/meshTools/searchableSurface/searchableBox.H
Normal file
249
src/meshTools/searchableSurface/searchableBox.H
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 1991-2007 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 2 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, write to the Free Software Foundation,
|
||||||
|
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::searchableBox
|
||||||
|
|
||||||
|
Description
|
||||||
|
Searching on bounding box
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
searchableBox.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef searchableBox_H
|
||||||
|
#define searchableBox_H
|
||||||
|
|
||||||
|
#include "searchableSurface.H"
|
||||||
|
#include "treeBoundBox.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// Forward declaration of classes
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class searchableBox Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class searchableBox
|
||||||
|
:
|
||||||
|
public searchableSurface,
|
||||||
|
public treeBoundBox
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Private Member Data
|
||||||
|
|
||||||
|
mutable wordList regions_;
|
||||||
|
|
||||||
|
|
||||||
|
// Private Member Functions
|
||||||
|
|
||||||
|
//- Project onto component dir of planePt and update index() (=face)
|
||||||
|
void projectOntoCoordPlane
|
||||||
|
(
|
||||||
|
const direction dir,
|
||||||
|
const point& planePt,
|
||||||
|
pointIndexHit& info
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Returns miss or hit with face (0..5)
|
||||||
|
pointIndexHit findNearest
|
||||||
|
(
|
||||||
|
const point& bbMid,
|
||||||
|
const point& sample,
|
||||||
|
const scalar nearestDistSqr
|
||||||
|
) const;
|
||||||
|
|
||||||
|
|
||||||
|
//- Disallow default bitwise copy construct
|
||||||
|
searchableBox(const searchableBox&);
|
||||||
|
|
||||||
|
//- Disallow default bitwise assignment
|
||||||
|
void operator=(const searchableBox&);
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Runtime type information
|
||||||
|
TypeName("searchableBox");
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct from components
|
||||||
|
searchableBox(const IOobject& io, const treeBoundBox& bb);
|
||||||
|
|
||||||
|
//- Construct from dictionary (used by searchableSurface)
|
||||||
|
searchableBox
|
||||||
|
(
|
||||||
|
const IOobject& io,
|
||||||
|
const dictionary& dict
|
||||||
|
);
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
|
||||||
|
virtual ~searchableBox();
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
virtual const wordList& regions() const;
|
||||||
|
|
||||||
|
//- Whether supports volume type below
|
||||||
|
virtual bool hasVolumeType() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Single point queries.
|
||||||
|
|
||||||
|
//- Calculate nearest point on surface. Returns
|
||||||
|
// - bool : any point found nearer than nearestDistSqr
|
||||||
|
// - label: relevant index in surface (=face 0..5)
|
||||||
|
// - point: actual nearest point found
|
||||||
|
pointIndexHit findNearest
|
||||||
|
(
|
||||||
|
const point& sample,
|
||||||
|
const scalar nearestDistSqr
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Calculate nearest point on edge. Returns
|
||||||
|
// - bool : any point found nearer than nearestDistSqr
|
||||||
|
// - label: relevant index in surface(=?)
|
||||||
|
// - point: actual nearest point found
|
||||||
|
pointIndexHit findNearestOnEdge
|
||||||
|
(
|
||||||
|
const point& sample,
|
||||||
|
const scalar nearestDistSqr
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Find nearest to segment. Returns
|
||||||
|
// - bool : any point found?
|
||||||
|
// - label: relevant index in shapes (=face 0..5)
|
||||||
|
// - point: actual nearest point found
|
||||||
|
// sets:
|
||||||
|
// - tightest : bounding box
|
||||||
|
// - linePoint : corresponding nearest point on line
|
||||||
|
pointIndexHit findNearest
|
||||||
|
(
|
||||||
|
const linePointRef& ln,
|
||||||
|
treeBoundBox& tightest,
|
||||||
|
point& linePoint
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Find nearest intersection of line between start and end.
|
||||||
|
pointIndexHit findLine
|
||||||
|
(
|
||||||
|
const point& start,
|
||||||
|
const point& end
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Find any intersection of line between start and end.
|
||||||
|
pointIndexHit findLineAny
|
||||||
|
(
|
||||||
|
const point& start,
|
||||||
|
const point& end
|
||||||
|
) const;
|
||||||
|
|
||||||
|
|
||||||
|
// Multiple point queries.
|
||||||
|
|
||||||
|
virtual void findNearest
|
||||||
|
(
|
||||||
|
const pointField& sample,
|
||||||
|
const scalarField& nearestDistSqr,
|
||||||
|
List<pointIndexHit>&
|
||||||
|
) const;
|
||||||
|
|
||||||
|
virtual void findLine
|
||||||
|
(
|
||||||
|
const pointField& start,
|
||||||
|
const pointField& end,
|
||||||
|
List<pointIndexHit>&
|
||||||
|
) const;
|
||||||
|
|
||||||
|
virtual void findLineAny
|
||||||
|
(
|
||||||
|
const pointField& start,
|
||||||
|
const pointField& end,
|
||||||
|
List<pointIndexHit>&
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Get all intersections in order from start to end.
|
||||||
|
virtual void findLineAll
|
||||||
|
(
|
||||||
|
const pointField& start,
|
||||||
|
const pointField& end,
|
||||||
|
List<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
|
||||||
|
|
||||||
|
bool writeData(Ostream&) const
|
||||||
|
{
|
||||||
|
notImplemented("searchableBox::writeData(Ostream&) const");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
328
src/meshTools/searchableSurface/searchableSphere.C
Normal file
328
src/meshTools/searchableSurface/searchableSphere.C
Normal file
@ -0,0 +1,328 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 1991-2007 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 2 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, write to the Free Software Foundation,
|
||||||
|
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "searchableSphere.H"
|
||||||
|
#include "addToRunTimeSelectionTable.H"
|
||||||
|
#include "SortableList.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
defineTypeNameAndDebug(searchableSphere, 0);
|
||||||
|
addToRunTimeSelectionTable(searchableSurface, searchableSphere, dict);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::pointIndexHit Foam::searchableSphere::findNearest
|
||||||
|
(
|
||||||
|
const point& sample,
|
||||||
|
const scalar nearestDistSqr
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
pointIndexHit info(false, sample, -1);
|
||||||
|
|
||||||
|
const vector n(sample-centre_);
|
||||||
|
scalar magN = mag(n);
|
||||||
|
|
||||||
|
if (nearestDistSqr > sqr(magN-radius_))
|
||||||
|
{
|
||||||
|
info.rawPoint() = centre_ + n/magN*radius_;
|
||||||
|
info.setHit();
|
||||||
|
info.setIndex(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// From Graphics Gems - intersection of sphere with ray
|
||||||
|
void Foam::searchableSphere::findLineAll
|
||||||
|
(
|
||||||
|
const point& start,
|
||||||
|
const point& end,
|
||||||
|
pointIndexHit& near,
|
||||||
|
pointIndexHit& far
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
near.setMiss();
|
||||||
|
far.setMiss();
|
||||||
|
|
||||||
|
vector dir(end-start);
|
||||||
|
scalar magSqrDir = magSqr(dir);
|
||||||
|
|
||||||
|
if (magSqrDir > ROOTVSMALL)
|
||||||
|
{
|
||||||
|
const vector toCentre(centre_-start);
|
||||||
|
scalar magSqrToCentre = magSqr(toCentre);
|
||||||
|
|
||||||
|
dir /= Foam::sqrt(magSqrDir);
|
||||||
|
|
||||||
|
scalar v = (toCentre & dir);
|
||||||
|
|
||||||
|
scalar disc = sqr(radius_) - (magSqrToCentre - sqr(v));
|
||||||
|
|
||||||
|
if (disc >= 0)
|
||||||
|
{
|
||||||
|
scalar d = Foam::sqrt(disc);
|
||||||
|
|
||||||
|
scalar nearParam = v-d;
|
||||||
|
|
||||||
|
if (nearParam >= 0 && sqr(nearParam) <= magSqrDir)
|
||||||
|
{
|
||||||
|
near.setHit();
|
||||||
|
near.setPoint(start + nearParam*dir);
|
||||||
|
near.setIndex(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
scalar farParam = v+d;
|
||||||
|
|
||||||
|
if (farParam >= 0 && sqr(farParam) <= magSqrDir)
|
||||||
|
{
|
||||||
|
far.setHit();
|
||||||
|
far.setPoint(start + farParam*dir);
|
||||||
|
far.setIndex(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::searchableSphere::searchableSphere
|
||||||
|
(
|
||||||
|
const IOobject& io,
|
||||||
|
const point& centre,
|
||||||
|
const scalar radius
|
||||||
|
)
|
||||||
|
:
|
||||||
|
searchableSurface(io),
|
||||||
|
centre_(centre),
|
||||||
|
radius_(radius)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::searchableSphere::searchableSphere
|
||||||
|
(
|
||||||
|
const IOobject& io,
|
||||||
|
const dictionary& dict
|
||||||
|
)
|
||||||
|
:
|
||||||
|
searchableSurface(io),
|
||||||
|
centre_(dict.lookup("centre")),
|
||||||
|
radius_(readScalar(dict.lookup("radius")))
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::searchableSphere::~searchableSphere()
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
const Foam::wordList& Foam::searchableSphere::regions() const
|
||||||
|
{
|
||||||
|
if (regions_.size() == 0)
|
||||||
|
{
|
||||||
|
regions_.setSize(1);
|
||||||
|
regions_[0] = "region0";
|
||||||
|
}
|
||||||
|
return regions_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::searchableSphere::findNearest
|
||||||
|
(
|
||||||
|
const pointField& samples,
|
||||||
|
const scalarField& nearestDistSqr,
|
||||||
|
List<pointIndexHit>& info
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
info.setSize(samples.size());
|
||||||
|
|
||||||
|
forAll(samples, i)
|
||||||
|
{
|
||||||
|
info[i] = findNearest(samples[i], nearestDistSqr[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::searchableSphere::findLine
|
||||||
|
(
|
||||||
|
const pointField& start,
|
||||||
|
const pointField& end,
|
||||||
|
List<pointIndexHit>& info
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
info.setSize(start.size());
|
||||||
|
|
||||||
|
pointIndexHit b;
|
||||||
|
|
||||||
|
forAll(start, i)
|
||||||
|
{
|
||||||
|
// Pick nearest intersection. If none intersected take second one.
|
||||||
|
findLineAll(start[i], end[i], info[i], b);
|
||||||
|
if (!info[i].hit() && b.hit())
|
||||||
|
{
|
||||||
|
info[i] = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::searchableSphere::findLineAny
|
||||||
|
(
|
||||||
|
const pointField& start,
|
||||||
|
const pointField& end,
|
||||||
|
List<pointIndexHit>& info
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
info.setSize(start.size());
|
||||||
|
|
||||||
|
pointIndexHit b;
|
||||||
|
|
||||||
|
forAll(start, i)
|
||||||
|
{
|
||||||
|
// Discard far intersection
|
||||||
|
findLineAll(start[i], end[i], info[i], b);
|
||||||
|
if (!info[i].hit() && b.hit())
|
||||||
|
{
|
||||||
|
info[i] = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::searchableSphere::findLineAll
|
||||||
|
(
|
||||||
|
const pointField& start,
|
||||||
|
const pointField& end,
|
||||||
|
List<List<pointIndexHit> >& info
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
info.setSize(start.size());
|
||||||
|
|
||||||
|
pointIndexHit near, far;
|
||||||
|
|
||||||
|
forAll(start, i)
|
||||||
|
{
|
||||||
|
findLineAll(start[i], end[i], near, far);
|
||||||
|
|
||||||
|
if (near.hit())
|
||||||
|
{
|
||||||
|
if (far.hit())
|
||||||
|
{
|
||||||
|
info[i].setSize(2);
|
||||||
|
info[i][0] = near;
|
||||||
|
info[i][1] = far;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
info[i].setSize(1);
|
||||||
|
info[i][0] = near;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (far.hit())
|
||||||
|
{
|
||||||
|
info[i].setSize(1);
|
||||||
|
info[i][0] = far;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::searchableSphere::getRegion
|
||||||
|
(
|
||||||
|
const List<pointIndexHit>& info,
|
||||||
|
labelList& region
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
region.setSize(info.size());
|
||||||
|
region = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::searchableSphere::getNormal
|
||||||
|
(
|
||||||
|
const List<pointIndexHit>& info,
|
||||||
|
vectorField& normal
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
normal.setSize(info.size());
|
||||||
|
normal = vector::zero;
|
||||||
|
|
||||||
|
forAll(info, i)
|
||||||
|
{
|
||||||
|
if (info[i].hit())
|
||||||
|
{
|
||||||
|
normal[i] = info[i].hitPoint() - centre_;
|
||||||
|
normal[i] /= mag(normal[i]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Set to what?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::searchableSphere::getVolumeType
|
||||||
|
(
|
||||||
|
const pointField& points,
|
||||||
|
List<volumeType>& volType
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
volType.setSize(points.size());
|
||||||
|
volType = INSIDE;
|
||||||
|
|
||||||
|
forAll(points, pointI)
|
||||||
|
{
|
||||||
|
const point& pt = points[pointI];
|
||||||
|
|
||||||
|
if (magSqr(pt - centre_) <= sqr(radius_))
|
||||||
|
{
|
||||||
|
volType[pointI] = INSIDE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
volType[pointI] = OUTSIDE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
204
src/meshTools/searchableSurface/searchableSphere.H
Normal file
204
src/meshTools/searchableSurface/searchableSphere.H
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 1991-2007 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 2 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, write to the Free Software Foundation,
|
||||||
|
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::searchableSphere
|
||||||
|
|
||||||
|
Description
|
||||||
|
Searching on sphere
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
searchableSphere.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef searchableSphere_H
|
||||||
|
#define searchableSphere_H
|
||||||
|
|
||||||
|
#include "searchableSurface.H"
|
||||||
|
#include "treeBoundBox.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// Forward declaration of classes
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class searchableSphere Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class searchableSphere
|
||||||
|
:
|
||||||
|
public searchableSurface
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Private Member Data
|
||||||
|
|
||||||
|
//- Centre point
|
||||||
|
const point centre_;
|
||||||
|
|
||||||
|
//- Radius squared
|
||||||
|
const scalar radius_;
|
||||||
|
|
||||||
|
//- Names of regions
|
||||||
|
mutable wordList regions_;
|
||||||
|
|
||||||
|
|
||||||
|
// Private Member Functions
|
||||||
|
|
||||||
|
//- Find nearest point on sphere.
|
||||||
|
pointIndexHit findNearest
|
||||||
|
(
|
||||||
|
const point& sample,
|
||||||
|
const scalar nearestDistSqr
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Find intersection with sphere
|
||||||
|
void findLineAll
|
||||||
|
(
|
||||||
|
const point& start,
|
||||||
|
const point& end,
|
||||||
|
pointIndexHit& near,
|
||||||
|
pointIndexHit& far
|
||||||
|
) const;
|
||||||
|
|
||||||
|
|
||||||
|
//- Disallow default bitwise copy construct
|
||||||
|
searchableSphere(const searchableSphere&);
|
||||||
|
|
||||||
|
//- Disallow default bitwise assignment
|
||||||
|
void operator=(const searchableSphere&);
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Runtime type information
|
||||||
|
TypeName("searchableSphere");
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct from components
|
||||||
|
searchableSphere(const IOobject& io, const point&, const scalar radius);
|
||||||
|
|
||||||
|
//- Construct from dictionary (used by searchableSurface)
|
||||||
|
searchableSphere
|
||||||
|
(
|
||||||
|
const IOobject& io,
|
||||||
|
const dictionary& dict
|
||||||
|
);
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
|
||||||
|
virtual ~searchableSphere();
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
virtual const wordList& regions() const;
|
||||||
|
|
||||||
|
//- Whether supports volume type below
|
||||||
|
virtual bool hasVolumeType() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Multiple point queries.
|
||||||
|
|
||||||
|
virtual void findNearest
|
||||||
|
(
|
||||||
|
const pointField& sample,
|
||||||
|
const scalarField& nearestDistSqr,
|
||||||
|
List<pointIndexHit>&
|
||||||
|
) const;
|
||||||
|
|
||||||
|
virtual void findLine
|
||||||
|
(
|
||||||
|
const pointField& start,
|
||||||
|
const pointField& end,
|
||||||
|
List<pointIndexHit>&
|
||||||
|
) const;
|
||||||
|
|
||||||
|
virtual void findLineAny
|
||||||
|
(
|
||||||
|
const pointField& start,
|
||||||
|
const pointField& end,
|
||||||
|
List<pointIndexHit>&
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Get all intersections in order from start to end.
|
||||||
|
virtual void findLineAll
|
||||||
|
(
|
||||||
|
const pointField& start,
|
||||||
|
const pointField& end,
|
||||||
|
List<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
|
||||||
|
|
||||||
|
bool writeData(Ostream&) const
|
||||||
|
{
|
||||||
|
notImplemented("searchableSphere::writeData(Ostream&) const");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -2,7 +2,7 @@
|
|||||||
========= |
|
========= |
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
\\ / O peration |
|
\\ / O peration |
|
||||||
\\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd.
|
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -34,15 +34,13 @@ namespace Foam
|
|||||||
|
|
||||||
defineTypeNameAndDebug(searchableSurface, 0);
|
defineTypeNameAndDebug(searchableSurface, 0);
|
||||||
defineRunTimeSelectionTable(searchableSurface, dict);
|
defineRunTimeSelectionTable(searchableSurface, dict);
|
||||||
//defineRunTimeSelectionTable(searchableSurface, istream);
|
|
||||||
|
|
||||||
|
|
||||||
// Construct named object from dictionary
|
// Construct named object from dictionary
|
||||||
autoPtr<searchableSurface> searchableSurface::New
|
autoPtr<searchableSurface> searchableSurface::New
|
||||||
(
|
(
|
||||||
const word& searchableSurfaceType,
|
const word& searchableSurfaceType,
|
||||||
const word& name,
|
const IOobject& io,
|
||||||
const objectRegistry& obj,
|
|
||||||
const dictionary& dict
|
const dictionary& dict
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -55,7 +53,7 @@ autoPtr<searchableSurface> searchableSurface::New
|
|||||||
FatalErrorIn
|
FatalErrorIn
|
||||||
(
|
(
|
||||||
"searchableSurface::New(const word&, const word&"
|
"searchableSurface::New(const word&, const word&"
|
||||||
", const objectRegistry&, const dictionary&)"
|
", const IOobject&, const dictionary&)"
|
||||||
) << "Unknown searchableSurface type " << searchableSurfaceType
|
) << "Unknown searchableSurface type " << searchableSurfaceType
|
||||||
<< endl << endl
|
<< endl << endl
|
||||||
<< "Valid searchableSurface types : " << endl
|
<< "Valid searchableSurface types : " << endl
|
||||||
@ -63,44 +61,15 @@ autoPtr<searchableSurface> searchableSurface::New
|
|||||||
<< exit(FatalError);
|
<< exit(FatalError);
|
||||||
}
|
}
|
||||||
|
|
||||||
return autoPtr<searchableSurface>(cstrIter()(name, obj, dict));
|
return autoPtr<searchableSurface>(cstrIter()(io, dict));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//// Construct named object from Istream
|
|
||||||
//autoPtr<searchableSurface> searchableSurface::New
|
|
||||||
//(
|
|
||||||
// const word& searchableSurfaceType,
|
|
||||||
// const objectRegistry& obj,
|
|
||||||
// Istream& is
|
|
||||||
//)
|
|
||||||
//{
|
|
||||||
// istreamConstructorTable::iterator cstrIter =
|
|
||||||
// istreamConstructorTablePtr_
|
|
||||||
// ->find(searchableSurfaceType);
|
|
||||||
//
|
|
||||||
// if (cstrIter == istreamConstructorTablePtr_->end())
|
|
||||||
// {
|
|
||||||
// FatalErrorIn
|
|
||||||
// (
|
|
||||||
// "searchableSurface::New(const word&, const objectRegistry&"
|
|
||||||
// ", Istream&)"
|
|
||||||
// ) << "Unknown searchableSurface type " << searchableSurfaceType
|
|
||||||
// << endl << endl
|
|
||||||
// << "Valid searchableSurface types : " << endl
|
|
||||||
// << istreamConstructorTablePtr_->toc()
|
|
||||||
// << exit(FatalError);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return autoPtr<searchableSurface>(cstrIter()(obj, is));
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::searchableSurface::searchableSurface(const word& name)
|
Foam::searchableSurface::searchableSurface(const IOobject& io)
|
||||||
:
|
:
|
||||||
name_(name)
|
regIOobject(io)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
322
src/meshTools/searchableSurface/searchableSurface.H
Normal file
322
src/meshTools/searchableSurface/searchableSurface.H
Normal file
@ -0,0 +1,322 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 1991-2007 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 2 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, write to the Free Software Foundation,
|
||||||
|
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::searchableSurface
|
||||||
|
|
||||||
|
Description
|
||||||
|
Base class of (analytical or triangulated) surface.
|
||||||
|
Encapsulates all the search routines. WIP.
|
||||||
|
|
||||||
|
Information returned is usually a pointIndexHit:
|
||||||
|
- bool : was intersection/nearest found?
|
||||||
|
- point : intersection point or nearest point
|
||||||
|
- index : unique index on surface (e.g. triangle for triSurfaceMesh)
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
searchableSurface.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef searchableSurface_H
|
||||||
|
#define searchableSurface_H
|
||||||
|
|
||||||
|
#include "pointField.H"
|
||||||
|
#include "typeInfo.H"
|
||||||
|
#include "runTimeSelectionTables.H"
|
||||||
|
#include "pointIndexHit.H"
|
||||||
|
#include "linePointRef.H"
|
||||||
|
#include "objectRegistry.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// Forward declaration of classes
|
||||||
|
class objectRegistry;
|
||||||
|
class treeBoundBox;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class searchableSurface Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class searchableSurface
|
||||||
|
:
|
||||||
|
public regIOobject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Data types
|
||||||
|
|
||||||
|
//- volume types
|
||||||
|
enum volumeType
|
||||||
|
{
|
||||||
|
UNKNOWN = 0,
|
||||||
|
MIXED = 1, // not used. only here to maintain consistency with
|
||||||
|
// indexedOctree volumeType.
|
||||||
|
INSIDE = 2,
|
||||||
|
OUTSIDE = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Private data
|
||||||
|
|
||||||
|
const word name_;
|
||||||
|
|
||||||
|
|
||||||
|
// Private Member Functions
|
||||||
|
|
||||||
|
//- Disallow default bitwise copy construct
|
||||||
|
searchableSurface(const searchableSurface&);
|
||||||
|
|
||||||
|
//- Disallow default bitwise assignment
|
||||||
|
void operator=(const searchableSurface&);
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Runtime type information
|
||||||
|
TypeName("searchableSurface");
|
||||||
|
|
||||||
|
// Declare run-time constructor selection table
|
||||||
|
|
||||||
|
// For the dictionary constructor
|
||||||
|
declareRunTimeSelectionTable
|
||||||
|
(
|
||||||
|
autoPtr,
|
||||||
|
searchableSurface,
|
||||||
|
dict,
|
||||||
|
(
|
||||||
|
const IOobject& io,
|
||||||
|
const dictionary& dict
|
||||||
|
),
|
||||||
|
(io, dict)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
//- Class used for the read-construction of
|
||||||
|
// PtrLists of searchableSurface.
|
||||||
|
class iNew
|
||||||
|
{
|
||||||
|
IOobject& io_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
iNew(IOobject& io)
|
||||||
|
:
|
||||||
|
io_(io)
|
||||||
|
{}
|
||||||
|
|
||||||
|
autoPtr<searchableSurface> operator()(Istream& is) const
|
||||||
|
{
|
||||||
|
word surfaceType(is);
|
||||||
|
word readName(is);
|
||||||
|
dictionary dict(is);
|
||||||
|
|
||||||
|
autoPtr<IOobject> namedIO(io_.clone());
|
||||||
|
namedIO().rename(readName);
|
||||||
|
return searchableSurface::New(surfaceType, namedIO(), dict);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
searchableSurface(const IOobject& io);
|
||||||
|
|
||||||
|
//- Clone
|
||||||
|
virtual autoPtr<searchableSurface> clone() const
|
||||||
|
{
|
||||||
|
notImplemented("autoPtr<searchableSurface> clone() const");
|
||||||
|
return autoPtr<searchableSurface>(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Selectors
|
||||||
|
|
||||||
|
//- Return a reference to the selected searchableSurface
|
||||||
|
static autoPtr<searchableSurface> New
|
||||||
|
(
|
||||||
|
const word& surfaceType,
|
||||||
|
const IOobject& io,
|
||||||
|
const dictionary& dict
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
|
||||||
|
virtual ~searchableSurface();
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
|
||||||
|
//- Names of regions.
|
||||||
|
virtual const wordList& regions() const = 0;
|
||||||
|
|
||||||
|
//- Whether supports volume type below.
|
||||||
|
virtual bool hasVolumeType() const = 0;
|
||||||
|
|
||||||
|
|
||||||
|
// Single point queries.
|
||||||
|
|
||||||
|
////- Calculate nearest point on surface. Returns
|
||||||
|
//// - bool : any point found nearer than nearestDistSqr
|
||||||
|
//// - label: relevant index in surface
|
||||||
|
//// - label: region in surface
|
||||||
|
//// - point: actual nearest point found
|
||||||
|
//virtual pointIndexHit findNearest
|
||||||
|
//(
|
||||||
|
// const point& sample,
|
||||||
|
// const scalar nearestDistSqr
|
||||||
|
//) const = 0;
|
||||||
|
//
|
||||||
|
////- Calculate nearest point on edge. Returns
|
||||||
|
//// - bool : any point found nearer than nearestDistSqr
|
||||||
|
//// - label: relevant index in surface
|
||||||
|
//// - label: region in surface
|
||||||
|
//// - point: actual nearest point found
|
||||||
|
//virtual pointIndexHit findNearestOnEdge
|
||||||
|
//(
|
||||||
|
// const point& sample,
|
||||||
|
// const scalar nearestDistSqr
|
||||||
|
//) const = 0;
|
||||||
|
//
|
||||||
|
////- Find nearest to segment. Returns
|
||||||
|
//// - bool : any point found?
|
||||||
|
//// - label: relevant index in shapes
|
||||||
|
//// - label: region in surface
|
||||||
|
//// - point: actual nearest point found
|
||||||
|
//// sets:
|
||||||
|
//// - tightest : bounding box
|
||||||
|
//// - linePoint : corresponding nearest point on line
|
||||||
|
//virtual pointIndexHit findNearest
|
||||||
|
//(
|
||||||
|
// const linePointRef& ln,
|
||||||
|
// treeBoundBox& tightest,
|
||||||
|
// point& linePoint
|
||||||
|
//) const = 0;
|
||||||
|
//
|
||||||
|
////- Find nearest intersection of line between start and end.
|
||||||
|
//virtual pointIndexHit findLine
|
||||||
|
//(
|
||||||
|
// const point& start,
|
||||||
|
// const point& end
|
||||||
|
//) const = 0;
|
||||||
|
//
|
||||||
|
////- Find any intersection of line between start and end.
|
||||||
|
//virtual pointIndexHit findLineAny
|
||||||
|
//(
|
||||||
|
// const point& start,
|
||||||
|
// const point& end
|
||||||
|
//) const = 0;
|
||||||
|
|
||||||
|
|
||||||
|
// Multiple point queries. When surface is distributed the index
|
||||||
|
// should be a global index. Not done yet.
|
||||||
|
|
||||||
|
virtual void findNearest
|
||||||
|
(
|
||||||
|
const pointField& sample,
|
||||||
|
const scalarField& nearestDistSqr,
|
||||||
|
List<pointIndexHit>&
|
||||||
|
) const = 0;
|
||||||
|
|
||||||
|
//- Find first intersection on segment from start to end.
|
||||||
|
// Note: searchableSurfacesQueries expects no
|
||||||
|
// intersection to be found if start==end. Is problem?
|
||||||
|
virtual void findLine
|
||||||
|
(
|
||||||
|
const pointField& start,
|
||||||
|
const pointField& end,
|
||||||
|
List<pointIndexHit>&
|
||||||
|
) const = 0;
|
||||||
|
|
||||||
|
//- Return any intersection on segment from start to end.
|
||||||
|
virtual void findLineAny
|
||||||
|
(
|
||||||
|
const pointField& start,
|
||||||
|
const pointField& end,
|
||||||
|
List<pointIndexHit>&
|
||||||
|
) const = 0;
|
||||||
|
|
||||||
|
//- Get all intersections in order from start to end.
|
||||||
|
virtual void findLineAll
|
||||||
|
(
|
||||||
|
const pointField& start,
|
||||||
|
const pointField& end,
|
||||||
|
List<List<pointIndexHit> >&
|
||||||
|
) const = 0;
|
||||||
|
|
||||||
|
//- From a set of points and indices get the region
|
||||||
|
virtual void getRegion
|
||||||
|
(
|
||||||
|
const List<pointIndexHit>&,
|
||||||
|
labelList& region
|
||||||
|
) const = 0;
|
||||||
|
|
||||||
|
//- From a set of points and indices get the normal
|
||||||
|
virtual void getNormal
|
||||||
|
(
|
||||||
|
const List<pointIndexHit>&,
|
||||||
|
vectorField& normal
|
||||||
|
) const = 0;
|
||||||
|
|
||||||
|
//- Determine type (inside/outside) for point. unknown if
|
||||||
|
// cannot be determined (e.g. non-manifold surface)
|
||||||
|
virtual void getVolumeType
|
||||||
|
(
|
||||||
|
const pointField&,
|
||||||
|
List<volumeType>&
|
||||||
|
) const = 0;
|
||||||
|
|
||||||
|
|
||||||
|
// Other
|
||||||
|
|
||||||
|
////- Get bounding box.
|
||||||
|
//const boundBox& bounds() const = 0;
|
||||||
|
|
||||||
|
////- Set bounding box.
|
||||||
|
//void setBounds
|
||||||
|
//(
|
||||||
|
// const boundBox&,
|
||||||
|
// autoPtr<mapDistribute>& faceMap,
|
||||||
|
// autoPtr<mapDistribute>& pointMap
|
||||||
|
//) = 0;
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
355
src/meshTools/searchableSurface/searchableSurfaces.C
Normal file
355
src/meshTools/searchableSurface/searchableSurfaces.C
Normal file
@ -0,0 +1,355 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 1991-2007 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 2 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, write to the Free Software Foundation,
|
||||||
|
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
\*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "searchableSurfaces.H"
|
||||||
|
#include "searchableSurfacesQueries.H"
|
||||||
|
#include "ListOps.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
defineTypeNameAndDebug(searchableSurfaces, 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
// Construct with length.
|
||||||
|
Foam::searchableSurfaces::searchableSurfaces(const label size)
|
||||||
|
:
|
||||||
|
PtrList<searchableSurface>(size),
|
||||||
|
regionNames_(size),
|
||||||
|
allSurfaces_(identity(size))
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
//Foam::searchableSurfaces::searchableSurfaces
|
||||||
|
//(
|
||||||
|
// const IOobject& io,
|
||||||
|
// const PtrList<dictionary>& dicts
|
||||||
|
//)
|
||||||
|
//:
|
||||||
|
// PtrList<searchableSurface>(dicts.size()),
|
||||||
|
// regionNames_(dicts.size()),
|
||||||
|
// allSurfaces_(identity(dicts.size()))
|
||||||
|
//{
|
||||||
|
// forAll(dicts, surfI)
|
||||||
|
// {
|
||||||
|
// const dictionary& dict = dicts[surfI];
|
||||||
|
//
|
||||||
|
// // Make IOobject with correct name
|
||||||
|
// autoPtr<IOobject> namedIO(io.clone());
|
||||||
|
// namedIO().rename(dict.lookup("name"));
|
||||||
|
//
|
||||||
|
// // Create and hook surface
|
||||||
|
// set
|
||||||
|
// (
|
||||||
|
// surfI,
|
||||||
|
// searchableSurface::New
|
||||||
|
// (
|
||||||
|
// dict.lookup("type"),
|
||||||
|
// namedIO(),
|
||||||
|
// dict
|
||||||
|
// )
|
||||||
|
// );
|
||||||
|
// const searchableSurface& s = operator[](surfI);
|
||||||
|
//
|
||||||
|
// // Construct default region names by prepending surface name
|
||||||
|
// // to region name.
|
||||||
|
// const wordList& localNames = s.regions();
|
||||||
|
//
|
||||||
|
// wordList globalNames(localNames.size());
|
||||||
|
// forAll(localNames, regionI)
|
||||||
|
// {
|
||||||
|
// globalNames[regionI] = s.name() + '_' + localNames[regionI];
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // See if dictionary provides any global region names.
|
||||||
|
// if (dict.found("regions"))
|
||||||
|
// {
|
||||||
|
// const dictionary& regionsDict = dict.subDict("regions");
|
||||||
|
//
|
||||||
|
// forAllConstIter(dictionary, regionsDict, iter)
|
||||||
|
// {
|
||||||
|
// const word& key = iter().keyword();
|
||||||
|
//
|
||||||
|
// if (regionsDict.isDict(key))
|
||||||
|
// {
|
||||||
|
// // Get the dictionary for region iter.key()
|
||||||
|
// const dictionary& regionDict = regionsDict.subDict(key);
|
||||||
|
//
|
||||||
|
// label index = findIndex(localNames, key);
|
||||||
|
//
|
||||||
|
// if (index == -1)
|
||||||
|
// {
|
||||||
|
// FatalErrorIn
|
||||||
|
// (
|
||||||
|
// "searchableSurfaces::searchableSurfaces"
|
||||||
|
// "( const IOobject&, const dictionary&)"
|
||||||
|
// ) << "Unknown region name " << key
|
||||||
|
// << " for surface " << s.name() << endl
|
||||||
|
// << "Valid region names are " << localNames
|
||||||
|
// << exit(FatalError);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// globalNames[index] = word(regionDict.lookup("name"));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Now globalNames contains the names of the regions.
|
||||||
|
// Info<< "Surface:" << s.name() << " has regions:"
|
||||||
|
// << endl;
|
||||||
|
// forAll(globalNames, regionI)
|
||||||
|
// {
|
||||||
|
// Info<< " " << globalNames[regionI] << endl;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Create reverse lookup
|
||||||
|
// forAll(globalNames, regionI)
|
||||||
|
// {
|
||||||
|
// regionNames_.insert
|
||||||
|
// (
|
||||||
|
// globalNames[regionI],
|
||||||
|
// labelPair(surfI, regionI)
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::searchableSurfaces::searchableSurfaces
|
||||||
|
(
|
||||||
|
const IOobject& io,
|
||||||
|
const dictionary& topDict
|
||||||
|
)
|
||||||
|
:
|
||||||
|
PtrList<searchableSurface>(topDict.size()),
|
||||||
|
names_(topDict.size()),
|
||||||
|
regionNames_(topDict.size()),
|
||||||
|
allSurfaces_(identity(topDict.size()))
|
||||||
|
{
|
||||||
|
label surfI = 0;
|
||||||
|
forAllConstIter(dictionary, topDict, iter)
|
||||||
|
{
|
||||||
|
const word& key = iter().keyword();
|
||||||
|
|
||||||
|
if (!topDict.isDict(key))
|
||||||
|
{
|
||||||
|
FatalErrorIn
|
||||||
|
(
|
||||||
|
"searchableSurfaces::searchableSurfaces"
|
||||||
|
"( const IOobject&, const dictionary&)"
|
||||||
|
) << "Found non-dictionary entry " << iter()
|
||||||
|
<< " in top-level dictionary " << topDict
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
const dictionary& dict = topDict.subDict(key);
|
||||||
|
|
||||||
|
names_[surfI] = key;
|
||||||
|
|
||||||
|
if (dict.found("name"))
|
||||||
|
{
|
||||||
|
dict.lookup("name") >> names_[surfI];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Make IOobject with correct name
|
||||||
|
autoPtr<IOobject> namedIO(io.clone());
|
||||||
|
// Note: we would like to e.g. register triSurface 'sphere.stl' as
|
||||||
|
// 'sphere'. Unfortunately
|
||||||
|
// no support for having object read from different location than
|
||||||
|
// their object name. Maybe have stlTriSurfaceMesh which appends .stl
|
||||||
|
// when reading/writing?
|
||||||
|
namedIO().rename(key); // names_[surfI]
|
||||||
|
|
||||||
|
// Create and hook surface
|
||||||
|
set
|
||||||
|
(
|
||||||
|
surfI,
|
||||||
|
searchableSurface::New
|
||||||
|
(
|
||||||
|
dict.lookup("type"),
|
||||||
|
namedIO(),
|
||||||
|
dict
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const searchableSurface& s = operator[](surfI);
|
||||||
|
|
||||||
|
// Construct default region names by prepending surface name
|
||||||
|
// to region name.
|
||||||
|
const wordList& localNames = s.regions();
|
||||||
|
|
||||||
|
wordList& rNames = regionNames_[surfI];
|
||||||
|
rNames.setSize(localNames.size());
|
||||||
|
|
||||||
|
forAll(localNames, regionI)
|
||||||
|
{
|
||||||
|
rNames[regionI] = names_[surfI] + '_' + localNames[regionI];
|
||||||
|
}
|
||||||
|
|
||||||
|
// See if dictionary provides any global region names.
|
||||||
|
if (dict.found("regions"))
|
||||||
|
{
|
||||||
|
const dictionary& regionsDict = dict.subDict("regions");
|
||||||
|
|
||||||
|
forAllConstIter(dictionary, regionsDict, iter)
|
||||||
|
{
|
||||||
|
const word& key = iter().keyword();
|
||||||
|
|
||||||
|
if (regionsDict.isDict(key))
|
||||||
|
{
|
||||||
|
// Get the dictionary for region iter.keyword()
|
||||||
|
const dictionary& regionDict = regionsDict.subDict(key);
|
||||||
|
|
||||||
|
label index = findIndex(localNames, key);
|
||||||
|
|
||||||
|
if (index == -1)
|
||||||
|
{
|
||||||
|
FatalErrorIn
|
||||||
|
(
|
||||||
|
"searchableSurfaces::searchableSurfaces"
|
||||||
|
"( const IOobject&, const dictionary&)"
|
||||||
|
) << "Unknown region name " << key
|
||||||
|
<< " for surface " << s.name() << endl
|
||||||
|
<< "Valid region names are " << localNames
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
rNames[index] = word(regionDict.lookup("name"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
surfI++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trim (not really necessary since we don't allow non-dictionary entries)
|
||||||
|
PtrList<searchableSurface>::setSize(surfI);
|
||||||
|
names_.setSize(surfI);
|
||||||
|
regionNames_.setSize(surfI);
|
||||||
|
allSurfaces_.setSize(surfI);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::label Foam::searchableSurfaces::findSurfaceID(const word& wantedName)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
return findIndex(names_, wantedName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Find any intersection
|
||||||
|
void Foam::searchableSurfaces::findAnyIntersection
|
||||||
|
(
|
||||||
|
const pointField& start,
|
||||||
|
const pointField& end,
|
||||||
|
labelList& hitSurfaces,
|
||||||
|
List<pointIndexHit>& hitInfo
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
searchableSurfacesQueries::findAnyIntersection
|
||||||
|
(
|
||||||
|
*this,
|
||||||
|
allSurfaces_,
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
hitSurfaces,
|
||||||
|
hitInfo
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Find intersections of edge nearest to both endpoints.
|
||||||
|
void Foam::searchableSurfaces::findAllIntersections
|
||||||
|
(
|
||||||
|
const pointField& start,
|
||||||
|
const pointField& end,
|
||||||
|
labelListList& hitSurfaces,
|
||||||
|
List<List<pointIndexHit> >& hitInfo
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
searchableSurfacesQueries::findAllIntersections
|
||||||
|
(
|
||||||
|
*this,
|
||||||
|
allSurfaces_,
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
hitSurfaces,
|
||||||
|
hitInfo
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Find nearest. Return -1 or nearest point
|
||||||
|
void Foam::searchableSurfaces::findNearest
|
||||||
|
(
|
||||||
|
const pointField& samples,
|
||||||
|
const scalarField& nearestDistSqr,
|
||||||
|
labelList& nearestSurfaces,
|
||||||
|
List<pointIndexHit>& nearestInfo
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
return searchableSurfacesQueries::findNearest
|
||||||
|
(
|
||||||
|
*this,
|
||||||
|
allSurfaces_,
|
||||||
|
samples,
|
||||||
|
nearestDistSqr,
|
||||||
|
nearestSurfaces,
|
||||||
|
nearestInfo
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//- Calculate point which is on a set of surfaces.
|
||||||
|
Foam::pointIndexHit Foam::searchableSurfaces::facesIntersection
|
||||||
|
(
|
||||||
|
const scalar initDistSqr,
|
||||||
|
const scalar convergenceDistSqr,
|
||||||
|
const point& start
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
return searchableSurfacesQueries::facesIntersection
|
||||||
|
(
|
||||||
|
*this,
|
||||||
|
allSurfaces_,
|
||||||
|
initDistSqr,
|
||||||
|
convergenceDistSqr,
|
||||||
|
start
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
187
src/meshTools/searchableSurface/searchableSurfaces.H
Normal file
187
src/meshTools/searchableSurface/searchableSurfaces.H
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 1991-2007 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 2 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, write to the Free Software Foundation,
|
||||||
|
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::searchableSurfaces
|
||||||
|
|
||||||
|
Description
|
||||||
|
Container for searchableSurfaces.
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
searchableSurfaces.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef searchableSurfaces_H
|
||||||
|
#define searchableSurfaces_H
|
||||||
|
|
||||||
|
#include "searchableSurface.H"
|
||||||
|
#include "labelPair.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// Forward declaration of classes
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class searchableSurfaces Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class searchableSurfaces
|
||||||
|
:
|
||||||
|
public PtrList<searchableSurface>
|
||||||
|
{
|
||||||
|
// Private data
|
||||||
|
|
||||||
|
//- Surface names
|
||||||
|
wordList names_;
|
||||||
|
|
||||||
|
//- Region names per surface
|
||||||
|
List<wordList> regionNames_;
|
||||||
|
|
||||||
|
////- From global region name to surface and region on surface
|
||||||
|
//HashTable<labelPair> regionNames_;
|
||||||
|
|
||||||
|
//- Indices of all surfaces. Precalculated and stored.
|
||||||
|
labelList allSurfaces_;
|
||||||
|
|
||||||
|
|
||||||
|
//- Disallow default bitwise copy construct
|
||||||
|
searchableSurfaces(const searchableSurfaces&);
|
||||||
|
|
||||||
|
//- Disallow default bitwise assignment
|
||||||
|
void operator=(const searchableSurfaces&);
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
ClassName("searchableSurfaces");
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct with length specified. Fill later.
|
||||||
|
explicit searchableSurfaces(const label);
|
||||||
|
|
||||||
|
|
||||||
|
////- Construct from list of dictionaries
|
||||||
|
//searchableSurfaces(const IOobject&, const PtrList<dictionary>&);
|
||||||
|
|
||||||
|
//- Construct from dictionary
|
||||||
|
searchableSurfaces(const IOobject&, const dictionary&);
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
const wordList& names() const
|
||||||
|
{
|
||||||
|
return names_;
|
||||||
|
}
|
||||||
|
wordList& names()
|
||||||
|
{
|
||||||
|
return names_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const List<wordList>& regionNames() const
|
||||||
|
{
|
||||||
|
return regionNames_;
|
||||||
|
}
|
||||||
|
List<wordList>& regionNames()
|
||||||
|
{
|
||||||
|
return regionNames_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////- If adding surfaces 'by hand'
|
||||||
|
//HashTable<labelPair>& regionNames()
|
||||||
|
//{
|
||||||
|
// return regionNames_;
|
||||||
|
//}
|
||||||
|
////- Get surface and region for a name
|
||||||
|
//const labelPair& surfaceRegion(const word& globalRegion) const
|
||||||
|
//{
|
||||||
|
// return regionNames_[globalRegion];
|
||||||
|
//}
|
||||||
|
|
||||||
|
//- Find index of surface. Return -1 if not found.
|
||||||
|
label findSurfaceID(const word& name) const;
|
||||||
|
|
||||||
|
|
||||||
|
// Multiple point queries.
|
||||||
|
|
||||||
|
//- Find any intersection. Return hit point information and
|
||||||
|
// surface number. If multiple surfaces hit the first surface
|
||||||
|
// is returned, not necessarily the nearest (to start).
|
||||||
|
void findAnyIntersection
|
||||||
|
(
|
||||||
|
const pointField& start,
|
||||||
|
const pointField& end,
|
||||||
|
labelList& surfaces,
|
||||||
|
List<pointIndexHit>&
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Find all intersections in order from start to end. Returns for
|
||||||
|
// every hit the surface and the hit info.
|
||||||
|
void findAllIntersections
|
||||||
|
(
|
||||||
|
const pointField& start,
|
||||||
|
const pointField& end,
|
||||||
|
labelListList& surfaces,
|
||||||
|
List<List<pointIndexHit> >& surfaceHits
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Find nearest. Return -1 (and a miss()) or surface and nearest
|
||||||
|
// point.
|
||||||
|
void findNearest
|
||||||
|
(
|
||||||
|
const pointField&,
|
||||||
|
const scalarField& nearestDistSqr,
|
||||||
|
labelList& surfaces,
|
||||||
|
List<pointIndexHit>&
|
||||||
|
) const;
|
||||||
|
|
||||||
|
|
||||||
|
// Single point queries
|
||||||
|
|
||||||
|
//- Calculate point which is on a set of surfaces.
|
||||||
|
pointIndexHit facesIntersection
|
||||||
|
(
|
||||||
|
const scalar initialDistSqr,
|
||||||
|
const scalar convergenceDistSqr,
|
||||||
|
const point& start
|
||||||
|
) const;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
822
src/meshTools/searchableSurface/searchableSurfacesQueries.C
Normal file
822
src/meshTools/searchableSurface/searchableSurfacesQueries.C
Normal file
@ -0,0 +1,822 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 1991-2007 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 2 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, write to the Free Software Foundation,
|
||||||
|
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
\*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "searchableSurfacesQueries.H"
|
||||||
|
#include "SortableList.H"
|
||||||
|
#include "OFstream.H"
|
||||||
|
#include "meshTools.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
defineTypeNameAndDebug(searchableSurfacesQueries, 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::pointIndexHit Foam::searchableSurfacesQueries::tempFindNearest
|
||||||
|
(
|
||||||
|
const searchableSurface& surf,
|
||||||
|
const point& pt,
|
||||||
|
const scalar initDistSqr
|
||||||
|
)
|
||||||
|
{
|
||||||
|
pointField onePoint(1, pt);
|
||||||
|
scalarField oneDist(1, initDistSqr);
|
||||||
|
List<pointIndexHit> oneHit(1);
|
||||||
|
surf.findNearest(onePoint, oneDist, oneHit);
|
||||||
|
return oneHit[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Calculate sum of distance to surfaces.
|
||||||
|
Foam::scalar Foam::searchableSurfacesQueries::sumDistSqr
|
||||||
|
(
|
||||||
|
const PtrList<searchableSurface>& allSurfaces,
|
||||||
|
const labelList& surfacesToTest,
|
||||||
|
const scalar initDistSqr,
|
||||||
|
const point& pt
|
||||||
|
)
|
||||||
|
{
|
||||||
|
scalar sum = 0;
|
||||||
|
|
||||||
|
forAll(surfacesToTest, testI)
|
||||||
|
{
|
||||||
|
label surfI = surfacesToTest[testI];
|
||||||
|
|
||||||
|
pointIndexHit hit
|
||||||
|
(
|
||||||
|
tempFindNearest(allSurfaces[surfI], pt, initDistSqr)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Note: make it fall over if not hit.
|
||||||
|
sum += magSqr(hit.hitPoint()-pt);
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Reflects the point furthest away around the triangle centre by a factor fac.
|
||||||
|
// (triangle centre is the average of all points but the ihi. pSum is running
|
||||||
|
// sum of all points)
|
||||||
|
Foam::scalar Foam::searchableSurfacesQueries::tryMorphTet
|
||||||
|
(
|
||||||
|
const PtrList<searchableSurface>& allSurfaces,
|
||||||
|
const labelList& surfacesToTest,
|
||||||
|
const scalar initDistSqr,
|
||||||
|
List<vector>& p,
|
||||||
|
List<scalar>& y,
|
||||||
|
vector& pSum,
|
||||||
|
const label ihi,
|
||||||
|
const scalar fac
|
||||||
|
)
|
||||||
|
{
|
||||||
|
scalar fac1 = (1.0-fac)/vector::nComponents;
|
||||||
|
scalar fac2 = fac1-fac;
|
||||||
|
|
||||||
|
vector ptry = pSum*fac1-p[ihi]*fac2;
|
||||||
|
|
||||||
|
scalar ytry = sumDistSqr(allSurfaces, surfacesToTest, initDistSqr, ptry);
|
||||||
|
|
||||||
|
if (ytry < y[ihi])
|
||||||
|
{
|
||||||
|
y[ihi] = ytry;
|
||||||
|
pSum += ptry - p[ihi];
|
||||||
|
p[ihi] = ptry;
|
||||||
|
}
|
||||||
|
return ytry;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::searchableSurfacesQueries::morphTet
|
||||||
|
(
|
||||||
|
const PtrList<searchableSurface>& allSurfaces,
|
||||||
|
const labelList& surfacesToTest,
|
||||||
|
const scalar initDistSqr,
|
||||||
|
const scalar convergenceDistSqr,
|
||||||
|
const label maxIter,
|
||||||
|
List<vector>& p,
|
||||||
|
List<scalar>& y
|
||||||
|
)
|
||||||
|
{
|
||||||
|
vector pSum = sum(p);
|
||||||
|
|
||||||
|
autoPtr<OFstream> str;
|
||||||
|
label vertI = 0;
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
wordList names(surfacesToTest.size());
|
||||||
|
forAll(surfacesToTest, i)
|
||||||
|
{
|
||||||
|
names[i] = allSurfaces[surfacesToTest[i]].name();
|
||||||
|
}
|
||||||
|
Pout<< "searchableSurfacesQueries::morphTet : intersection of "
|
||||||
|
<< names << " starting from points:" << p << endl;
|
||||||
|
str.reset(new OFstream("track.obj"));
|
||||||
|
meshTools::writeOBJ(str(), p[0]);
|
||||||
|
vertI++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (label iter = 0; iter < maxIter; iter++)
|
||||||
|
{
|
||||||
|
// Get the indices of highest, second-highest and lowest values.
|
||||||
|
label ihi, inhi, ilo;
|
||||||
|
{
|
||||||
|
SortableList<scalar> sortedY(y);
|
||||||
|
ilo = sortedY.indices()[0];
|
||||||
|
ihi = sortedY.indices()[sortedY.size()-1];
|
||||||
|
inhi = sortedY.indices()[sortedY.size()-2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
Pout<< "Iteration:" << iter
|
||||||
|
<< " lowest:" << y[ilo] << " highest:" << y[ihi]
|
||||||
|
<< " points:" << p << endl;
|
||||||
|
|
||||||
|
meshTools::writeOBJ(str(), p[ilo]);
|
||||||
|
vertI++;
|
||||||
|
str()<< "l " << vertI-1 << ' ' << vertI << nl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y[ihi] < convergenceDistSqr)
|
||||||
|
{
|
||||||
|
// Get point on 0th surface.
|
||||||
|
Swap(p[0], p[ilo]);
|
||||||
|
Swap(y[0], y[ilo]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reflection: point furthest away gets reflected.
|
||||||
|
scalar ytry = tryMorphTet
|
||||||
|
(
|
||||||
|
allSurfaces,
|
||||||
|
surfacesToTest,
|
||||||
|
10*y[ihi], // search box.
|
||||||
|
p,
|
||||||
|
y,
|
||||||
|
pSum,
|
||||||
|
ihi,
|
||||||
|
-1.0
|
||||||
|
);
|
||||||
|
|
||||||
|
if (ytry <= y[ilo])
|
||||||
|
{
|
||||||
|
// If in right direction (y lower) expand by two.
|
||||||
|
ytry = tryMorphTet
|
||||||
|
(
|
||||||
|
allSurfaces,
|
||||||
|
surfacesToTest,
|
||||||
|
10*y[ihi],
|
||||||
|
p,
|
||||||
|
y,
|
||||||
|
pSum,
|
||||||
|
ihi,
|
||||||
|
2.0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (ytry >= y[inhi])
|
||||||
|
{
|
||||||
|
// If inside tet try contraction.
|
||||||
|
|
||||||
|
scalar ysave = y[ihi];
|
||||||
|
|
||||||
|
ytry = tryMorphTet
|
||||||
|
(
|
||||||
|
allSurfaces,
|
||||||
|
surfacesToTest,
|
||||||
|
10*y[ihi],
|
||||||
|
p,
|
||||||
|
y,
|
||||||
|
pSum,
|
||||||
|
ihi,
|
||||||
|
0.5
|
||||||
|
);
|
||||||
|
|
||||||
|
if (ytry >= ysave)
|
||||||
|
{
|
||||||
|
// Contract around lowest point.
|
||||||
|
forAll(p, i)
|
||||||
|
{
|
||||||
|
if (i != ilo)
|
||||||
|
{
|
||||||
|
p[i] = 0.5*(p[i] + p[ilo]);
|
||||||
|
y[i] = sumDistSqr
|
||||||
|
(
|
||||||
|
allSurfaces,
|
||||||
|
surfacesToTest,
|
||||||
|
y[ihi],
|
||||||
|
p[i]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pSum = sum(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
meshTools::writeOBJ(str(), p[0]);
|
||||||
|
vertI++;
|
||||||
|
str()<< "l " << vertI-1 << ' ' << vertI << nl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Failure to converge. Return best guess so far.
|
||||||
|
label ilo = findMin(y);
|
||||||
|
Swap(p[0], p[ilo]);
|
||||||
|
Swap(y[0], y[ilo]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//// Get all intersections (in order) for single surface.
|
||||||
|
//void Foam::searchableSurfacesQueries::findAllIntersections
|
||||||
|
//(
|
||||||
|
// const searchableSurface& s,
|
||||||
|
// const pointField& start,
|
||||||
|
// const pointField& end,
|
||||||
|
// const vectorField& smallVec,
|
||||||
|
// List<List<pointIndexHit> >& surfaceHitInfo
|
||||||
|
//)
|
||||||
|
//{
|
||||||
|
// surfaceHitInfo.setSize(start.size());
|
||||||
|
//
|
||||||
|
// // Current start point of vector
|
||||||
|
// pointField p0(start);
|
||||||
|
//
|
||||||
|
// List<pointIndexHit> intersectInfo(start.size());
|
||||||
|
//
|
||||||
|
// // For test whether finished doing vector.
|
||||||
|
// const vectorField dirVec(end-start);
|
||||||
|
// const scalarField magSqrDirVec(magSqr(dirVec));
|
||||||
|
//
|
||||||
|
// while (true)
|
||||||
|
// {
|
||||||
|
// // Find first intersection. Synced.
|
||||||
|
// s.findLine(p0, end, intersectInfo);
|
||||||
|
//
|
||||||
|
// label nHits = 0;
|
||||||
|
//
|
||||||
|
// forAll(intersectInfo, i)
|
||||||
|
// {
|
||||||
|
// if (intersectInfo[i].hit())
|
||||||
|
// {
|
||||||
|
// nHits++;
|
||||||
|
//
|
||||||
|
// label sz = surfaceHitInfo[i].size();
|
||||||
|
// surfaceHitInfo[i].setSize(sz+1);
|
||||||
|
// surfaceHitInfo[i][sz] = intersectInfo[i];
|
||||||
|
//
|
||||||
|
// p0[i] = intersectInfo[i].hitPoint() + smallVec[i];
|
||||||
|
//
|
||||||
|
// // If beyond endpoint set to endpoint so as not to pick up
|
||||||
|
// // any intersections. Could instead just filter out hits.
|
||||||
|
// if (((p0[i]-start[i])&dirVec[i]) > magSqrDirVec[i])
|
||||||
|
// {
|
||||||
|
// p0[i] = end[i];
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// // Set to endpoint to stop intersection test. See above.
|
||||||
|
// p0[i] = end[i];
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // returnReduce(nHits) ?
|
||||||
|
// if (nHits == 0)
|
||||||
|
// {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
// Given current set of hits (allSurfaces, allInfo) merge in those coming from
|
||||||
|
// surface surfI.
|
||||||
|
void Foam::searchableSurfacesQueries::mergeHits
|
||||||
|
(
|
||||||
|
const point& start,
|
||||||
|
const scalar mergeDist,
|
||||||
|
|
||||||
|
const label testI, // index of surface
|
||||||
|
const List<pointIndexHit>& surfHits, // hits on surface
|
||||||
|
|
||||||
|
labelList& allSurfaces,
|
||||||
|
List<pointIndexHit>& allInfo,
|
||||||
|
scalarList& allDistSqr
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Precalculate distances
|
||||||
|
scalarList surfDistSqr(surfHits.size());
|
||||||
|
forAll(surfHits, i)
|
||||||
|
{
|
||||||
|
surfDistSqr[i] = magSqr(surfHits[i].hitPoint()-start);
|
||||||
|
}
|
||||||
|
|
||||||
|
forAll(surfDistSqr, i)
|
||||||
|
{
|
||||||
|
label index = findLower(allDistSqr, surfDistSqr[i]);
|
||||||
|
|
||||||
|
// Check if equal to lower.
|
||||||
|
if
|
||||||
|
(
|
||||||
|
index >= 0
|
||||||
|
&& (mag(allDistSqr[index]-surfDistSqr[i]) < mergeDist)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Same. Do not count.
|
||||||
|
//Pout<< "point:" << surfHits[i].hitPoint()
|
||||||
|
// << " considered same as:" << allInfo[index].hitPoint()
|
||||||
|
// << " within tol:" << mergeDist
|
||||||
|
// << endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Check if equal to higher
|
||||||
|
label next = index+1;
|
||||||
|
if
|
||||||
|
(
|
||||||
|
next < allDistSqr.size()
|
||||||
|
&& (mag(allDistSqr[next]-surfDistSqr[i]) < mergeDist)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
//Pout<< "point:" << surfHits[i].hitPoint()
|
||||||
|
// << " considered same as:" << allInfo[next].hitPoint()
|
||||||
|
// << " within tol:" << mergeDist
|
||||||
|
// << endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Insert after index
|
||||||
|
label sz = allSurfaces.size();
|
||||||
|
allSurfaces.setSize(sz+1);
|
||||||
|
allInfo.setSize(allSurfaces.size());
|
||||||
|
allDistSqr.setSize(allSurfaces.size());
|
||||||
|
// Make space.
|
||||||
|
for (label j = sz-1; j > index; --j)
|
||||||
|
{
|
||||||
|
allSurfaces[j+1] = allSurfaces[j];
|
||||||
|
allInfo[j+1] = allInfo[j];
|
||||||
|
allDistSqr[j+1] = allDistSqr[j];
|
||||||
|
}
|
||||||
|
// Insert new value
|
||||||
|
allSurfaces[index+1] = testI;
|
||||||
|
allInfo[index+1] = surfHits[i];
|
||||||
|
allDistSqr[index+1] = surfDistSqr[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
// Find any intersection
|
||||||
|
void Foam::searchableSurfacesQueries::findAnyIntersection
|
||||||
|
(
|
||||||
|
const PtrList<searchableSurface>& allSurfaces,
|
||||||
|
const labelList& surfacesToTest,
|
||||||
|
const pointField& start,
|
||||||
|
const pointField& end,
|
||||||
|
labelList& hitSurfaces,
|
||||||
|
List<pointIndexHit>& hitInfo
|
||||||
|
)
|
||||||
|
{
|
||||||
|
hitSurfaces.setSize(start.size());
|
||||||
|
hitSurfaces = -1;
|
||||||
|
hitInfo.setSize(start.size());
|
||||||
|
|
||||||
|
// Work arrays
|
||||||
|
labelList hitMap(identity(start.size()));
|
||||||
|
pointField p0(start);
|
||||||
|
pointField p1(end);
|
||||||
|
List<pointIndexHit> intersectInfo(start.size());
|
||||||
|
|
||||||
|
forAll(surfacesToTest, testI)
|
||||||
|
{
|
||||||
|
// Do synchronised call to all surfaces.
|
||||||
|
allSurfaces[surfacesToTest[testI]].findLineAny(p0, p1, intersectInfo);
|
||||||
|
|
||||||
|
// Copy all hits into arguments, continue with misses
|
||||||
|
label newI = 0;
|
||||||
|
forAll(intersectInfo, i)
|
||||||
|
{
|
||||||
|
if (intersectInfo[i].hit())
|
||||||
|
{
|
||||||
|
hitInfo[hitMap[i]] = intersectInfo[i];
|
||||||
|
hitSurfaces[hitMap[i]] = testI;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (i != newI)
|
||||||
|
{
|
||||||
|
hitMap[newI] = hitMap[i];
|
||||||
|
p0[newI] = p0[i];
|
||||||
|
p1[newI] = p1[i];
|
||||||
|
}
|
||||||
|
newI++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// All done? Note that this decision should be synchronised
|
||||||
|
if (newI == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trim and continue
|
||||||
|
hitMap.setSize(newI);
|
||||||
|
p0.setSize(newI);
|
||||||
|
p1.setSize(newI);
|
||||||
|
intersectInfo.setSize(newI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::searchableSurfacesQueries::findAllIntersections
|
||||||
|
(
|
||||||
|
const PtrList<searchableSurface>& allSurfaces,
|
||||||
|
const labelList& surfacesToTest,
|
||||||
|
const pointField& start,
|
||||||
|
const pointField& end,
|
||||||
|
labelListList& hitSurfaces,
|
||||||
|
List<List<pointIndexHit> >& hitInfo
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Note: maybe move the single-surface all intersections test into
|
||||||
|
// searchable surface? Some of the tolerance issues might be
|
||||||
|
// lessened.
|
||||||
|
|
||||||
|
// 2. Currently calling searchableSurface::findLine with start==end
|
||||||
|
// is expected to find no intersection. Problem if it does.
|
||||||
|
|
||||||
|
hitSurfaces.setSize(start.size());
|
||||||
|
hitInfo.setSize(start.size());
|
||||||
|
|
||||||
|
if (surfacesToTest.size() == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test first surface
|
||||||
|
allSurfaces[surfacesToTest[0]].findLineAll(start, end, hitInfo);
|
||||||
|
|
||||||
|
// Set hitSurfaces and distance
|
||||||
|
List<scalarList> hitDistSqr(hitInfo.size());
|
||||||
|
forAll(hitInfo, pointI)
|
||||||
|
{
|
||||||
|
const List<pointIndexHit>& pHits = hitInfo[pointI];
|
||||||
|
|
||||||
|
labelList& pSurfaces = hitSurfaces[pointI];
|
||||||
|
pSurfaces.setSize(pHits.size());
|
||||||
|
pSurfaces = 0;
|
||||||
|
|
||||||
|
scalarList& pDistSqr = hitDistSqr[pointI];
|
||||||
|
pDistSqr.setSize(pHits.size());
|
||||||
|
forAll(pHits, i)
|
||||||
|
{
|
||||||
|
pDistSqr[i] = magSqr(pHits[i].hitPoint() - start[pointI]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (surfacesToTest.size() > 1)
|
||||||
|
{
|
||||||
|
// Small vector to increment start vector by to find next intersection
|
||||||
|
// along line. Constant factor added to make sure that start==end still
|
||||||
|
// ends iteration in findAllIntersections. Also SMALL is just slightly
|
||||||
|
// too small.
|
||||||
|
const vectorField smallVec
|
||||||
|
(
|
||||||
|
1E2*SMALL*(end-start)
|
||||||
|
+ vector(ROOTVSMALL,ROOTVSMALL,ROOTVSMALL)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Tolerance used to check whether points are equal. Note: used to
|
||||||
|
// compare distance^2. Note that we use the maximum possible tolerance
|
||||||
|
// (reached at intersections close to the end point)
|
||||||
|
const scalarField mergeDist(2*mag(smallVec)*mag(end-start));
|
||||||
|
|
||||||
|
// Test the other surfaces and merge (according to distance from start).
|
||||||
|
for (label testI = 1; testI < surfacesToTest.size(); testI++)
|
||||||
|
{
|
||||||
|
List<List<pointIndexHit> > surfHits;
|
||||||
|
allSurfaces[surfacesToTest[testI]].findLineAll
|
||||||
|
(
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
surfHits
|
||||||
|
);
|
||||||
|
|
||||||
|
forAll(surfHits, pointI)
|
||||||
|
{
|
||||||
|
mergeHits
|
||||||
|
(
|
||||||
|
start[pointI], // Current segment
|
||||||
|
mergeDist[pointI],
|
||||||
|
|
||||||
|
testI, // Surface and its hits
|
||||||
|
surfHits[pointI],
|
||||||
|
|
||||||
|
hitSurfaces[pointI], // Merge into overall hit info
|
||||||
|
hitInfo[pointI],
|
||||||
|
hitDistSqr[pointI]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//// Find intersections of edge nearest to both endpoints.
|
||||||
|
//void Foam::searchableSurfacesQueries::findNearestIntersection
|
||||||
|
//(
|
||||||
|
// const PtrList<searchableSurface>& allSurfaces,
|
||||||
|
// const labelList& surfacesToTest,
|
||||||
|
// const pointField& start,
|
||||||
|
// const pointField& end,
|
||||||
|
//
|
||||||
|
// labelList& surface1,
|
||||||
|
// List<pointIndexHit>& hit1,
|
||||||
|
// labelList& surface2,
|
||||||
|
// List<pointIndexHit>& hit2
|
||||||
|
//)
|
||||||
|
//{
|
||||||
|
// // 1. intersection from start to end
|
||||||
|
// // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// // Initialize arguments
|
||||||
|
// surface1.setSize(start.size());
|
||||||
|
// surface1 = -1;
|
||||||
|
// hit1.setSize(start.size());
|
||||||
|
//
|
||||||
|
// // Current end of segment to test.
|
||||||
|
// pointField nearest(end);
|
||||||
|
// // Work array
|
||||||
|
// List<pointIndexHit> nearestInfo(start.size());
|
||||||
|
//
|
||||||
|
// forAll(surfacesToTest, testI)
|
||||||
|
// {
|
||||||
|
// // See if any intersection between start and current nearest
|
||||||
|
// allSurfaces[surfacesToTest[testI]].findLine
|
||||||
|
// (
|
||||||
|
// start,
|
||||||
|
// nearest,
|
||||||
|
// nearestInfo
|
||||||
|
// );
|
||||||
|
//
|
||||||
|
// forAll(nearestInfo, pointI)
|
||||||
|
// {
|
||||||
|
// if (nearestInfo[pointI].hit())
|
||||||
|
// {
|
||||||
|
// hit1[pointI] = nearestInfo[pointI];
|
||||||
|
// surface1[pointI] = testI;
|
||||||
|
// nearest[pointI] = hit1[pointI].hitPoint();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// // 2. intersection from end to last intersection
|
||||||
|
// // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// // Find the nearest intersection from end to start. Note that we
|
||||||
|
// // initialize to the first intersection (if any).
|
||||||
|
// surface2 = surface1;
|
||||||
|
// hit2 = hit1;
|
||||||
|
//
|
||||||
|
// // Set current end of segment to test.
|
||||||
|
// forAll(nearest, pointI)
|
||||||
|
// {
|
||||||
|
// if (hit1[pointI].hit())
|
||||||
|
// {
|
||||||
|
// nearest[pointI] = hit1[pointI].hitPoint();
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// // Disable testing by setting to end.
|
||||||
|
// nearest[pointI] = end[pointI];
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// forAll(surfacesToTest, testI)
|
||||||
|
// {
|
||||||
|
// // See if any intersection between end and current nearest
|
||||||
|
// allSurfaces[surfacesToTest[i]].findLine(end, nearest, nearestInfo);
|
||||||
|
//
|
||||||
|
// forAll(nearestInfo, pointI)
|
||||||
|
// {
|
||||||
|
// if (nearestInfo[pointI].hit())
|
||||||
|
// {
|
||||||
|
// hit2[pointI] = nearestInfo[pointI];
|
||||||
|
// surface2[pointI] = testI;
|
||||||
|
// nearest[pointI] = hit2[pointI].hitPoint();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
// Find nearest. Return -1 or nearest point
|
||||||
|
void Foam::searchableSurfacesQueries::findNearest
|
||||||
|
(
|
||||||
|
const PtrList<searchableSurface>& allSurfaces,
|
||||||
|
const labelList& surfacesToTest,
|
||||||
|
const pointField& samples,
|
||||||
|
const scalarField& nearestDistSqr,
|
||||||
|
labelList& nearestSurfaces,
|
||||||
|
List<pointIndexHit>& nearestInfo
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Initialise
|
||||||
|
nearestSurfaces.setSize(samples.size());
|
||||||
|
nearestSurfaces = -1;
|
||||||
|
nearestInfo.setSize(samples.size());
|
||||||
|
|
||||||
|
// Work arrays
|
||||||
|
scalarField minDistSqr(nearestDistSqr);
|
||||||
|
List<pointIndexHit> hitInfo(samples.size());
|
||||||
|
|
||||||
|
forAll(surfacesToTest, testI)
|
||||||
|
{
|
||||||
|
allSurfaces[surfacesToTest[testI]].findNearest
|
||||||
|
(
|
||||||
|
samples,
|
||||||
|
minDistSqr,
|
||||||
|
hitInfo
|
||||||
|
);
|
||||||
|
|
||||||
|
// Update minDistSqr and arguments
|
||||||
|
forAll(hitInfo, pointI)
|
||||||
|
{
|
||||||
|
if (hitInfo[pointI].hit())
|
||||||
|
{
|
||||||
|
minDistSqr[pointI] = magSqr
|
||||||
|
(
|
||||||
|
hitInfo[pointI].hitPoint()
|
||||||
|
- samples[pointI]
|
||||||
|
);
|
||||||
|
nearestInfo[pointI] = hitInfo[pointI];
|
||||||
|
nearestSurfaces[pointI] = testI;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//- Calculate point which is on a set of surfaces.
|
||||||
|
Foam::pointIndexHit Foam::searchableSurfacesQueries::facesIntersection
|
||||||
|
(
|
||||||
|
const PtrList<searchableSurface>& allSurfaces,
|
||||||
|
const labelList& surfacesToTest,
|
||||||
|
const scalar initDistSqr,
|
||||||
|
const scalar convergenceDistSqr,
|
||||||
|
const point& start
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Get four starting points. Take these as the projection of the
|
||||||
|
// starting point onto the surfaces and the mid point
|
||||||
|
List<point> nearest(surfacesToTest.size()+1);
|
||||||
|
|
||||||
|
point sumNearest = vector::zero;
|
||||||
|
|
||||||
|
forAll(surfacesToTest, i)
|
||||||
|
{
|
||||||
|
pointIndexHit hit
|
||||||
|
(
|
||||||
|
tempFindNearest(allSurfaces[surfacesToTest[i]], start, initDistSqr)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (hit.hit())
|
||||||
|
{
|
||||||
|
nearest[i] = hit.hitPoint();
|
||||||
|
sumNearest += nearest[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FatalErrorIn
|
||||||
|
(
|
||||||
|
"searchableSurfacesQueries::facesIntersection"
|
||||||
|
"(const labelList&, const scalar, const scalar, const point&)"
|
||||||
|
) << "Did not find point within distance "
|
||||||
|
<< initDistSqr << " of starting point " << start
|
||||||
|
<< " on surface "
|
||||||
|
<< allSurfaces[surfacesToTest[i]].IOobject::name()
|
||||||
|
<< abort(FatalError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nearest[nearest.size()-1] = sumNearest / surfacesToTest.size();
|
||||||
|
|
||||||
|
|
||||||
|
// Get the sum of distances (initial evaluation)
|
||||||
|
List<scalar> nearestDist(nearest.size());
|
||||||
|
|
||||||
|
forAll(nearestDist, i)
|
||||||
|
{
|
||||||
|
nearestDist[i] = sumDistSqr
|
||||||
|
(
|
||||||
|
allSurfaces,
|
||||||
|
surfacesToTest,
|
||||||
|
initDistSqr,
|
||||||
|
nearest[i]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//- Downhill Simplex method
|
||||||
|
|
||||||
|
bool converged = morphTet
|
||||||
|
(
|
||||||
|
allSurfaces,
|
||||||
|
surfacesToTest,
|
||||||
|
initDistSqr,
|
||||||
|
convergenceDistSqr,
|
||||||
|
2000,
|
||||||
|
nearest,
|
||||||
|
nearestDist
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
pointIndexHit intersection;
|
||||||
|
|
||||||
|
if (converged)
|
||||||
|
{
|
||||||
|
// Project nearest onto 0th surface.
|
||||||
|
intersection = tempFindNearest
|
||||||
|
(
|
||||||
|
allSurfaces[surfacesToTest[0]],
|
||||||
|
nearest[0],
|
||||||
|
nearestDist[0]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//if (!intersection.hit())
|
||||||
|
//{
|
||||||
|
// // Restart
|
||||||
|
// scalar smallDist = Foam::sqr(convergenceDistSqr);
|
||||||
|
// nearest[0] = intersection.hitPoint();
|
||||||
|
// nearest[1] = nearest[0];
|
||||||
|
// nearest[1].x() += smallDist;
|
||||||
|
// nearest[2] = nearest[0];
|
||||||
|
// nearest[2].y() += smallDist;
|
||||||
|
// nearest[3] = nearest[0];
|
||||||
|
// nearest[3].z() += smallDist;
|
||||||
|
//
|
||||||
|
// forAll(nearestDist, i)
|
||||||
|
// {
|
||||||
|
// nearestDist[i] = sumDistSqr
|
||||||
|
// (
|
||||||
|
// surfacesToTest,
|
||||||
|
// initDistSqr,
|
||||||
|
// nearest[i]
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// intersection = morphTet
|
||||||
|
// (
|
||||||
|
// allSurfaces,
|
||||||
|
// surfacesToTest,
|
||||||
|
// initDistSqr,
|
||||||
|
// convergenceDistSqr,
|
||||||
|
// 1000,
|
||||||
|
// nearest,
|
||||||
|
// nearestDist
|
||||||
|
// );
|
||||||
|
//}
|
||||||
|
|
||||||
|
return intersection;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
198
src/meshTools/searchableSurface/searchableSurfacesQueries.H
Normal file
198
src/meshTools/searchableSurface/searchableSurfacesQueries.H
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 1991-2007 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 2 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, write to the Free Software Foundation,
|
||||||
|
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::searchableSurfacesQueries
|
||||||
|
|
||||||
|
Description
|
||||||
|
A collection of tools for searchableSurfaces.
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
searchableSurfacesQueries.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef searchableSurfacesQueries_H
|
||||||
|
#define searchableSurfacesQueries_H
|
||||||
|
|
||||||
|
#include "searchableSurface.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// Forward declaration of classes
|
||||||
|
class plane;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class searchableSurfacesQueries Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class searchableSurfacesQueries
|
||||||
|
{
|
||||||
|
// Private data
|
||||||
|
|
||||||
|
// Private Member Functions
|
||||||
|
|
||||||
|
//- Temporary wrapper around findNearest. Used in facesIntersection only
|
||||||
|
static pointIndexHit tempFindNearest
|
||||||
|
(
|
||||||
|
const searchableSurface&,
|
||||||
|
const point& pt,
|
||||||
|
const scalar initDistSqr
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Calculate sum of distances to nearest point on surfaces. Is used
|
||||||
|
// in minimisation to find intersection. Returns sum of (square of)
|
||||||
|
// distances to the surfaces.
|
||||||
|
static scalar sumDistSqr
|
||||||
|
(
|
||||||
|
const PtrList<searchableSurface>&,
|
||||||
|
const labelList& surfacesToTest,
|
||||||
|
const scalar initialDistSqr, // search box
|
||||||
|
const point& pt
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Takes the tet (points p) and reflects the point with the
|
||||||
|
// highest value around the centre (pSum). Checks if it gets closer
|
||||||
|
// and updates p, y if so.
|
||||||
|
static scalar tryMorphTet
|
||||||
|
(
|
||||||
|
const PtrList<searchableSurface>&,
|
||||||
|
const labelList& surfacesToTest,
|
||||||
|
const scalar initialDistSqr,
|
||||||
|
List<vector>& p,
|
||||||
|
List<scalar>& y,
|
||||||
|
vector& pSum,
|
||||||
|
const label ihi,
|
||||||
|
const scalar fac
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Downhill simplex method: find the point with min cumulative
|
||||||
|
// distance to all surfaces. Does so by morphing a tet (points p).
|
||||||
|
// Returns the point on the 0th surface or hit if not reached within
|
||||||
|
// maxIters iterations.
|
||||||
|
static bool morphTet
|
||||||
|
(
|
||||||
|
const PtrList<searchableSurface>&,
|
||||||
|
const labelList& surfacesToTest,
|
||||||
|
const scalar initialDistSqr,
|
||||||
|
const scalar convergenceDistSqr,
|
||||||
|
const label maxIter,
|
||||||
|
List<vector>& p,
|
||||||
|
List<scalar>& y
|
||||||
|
);
|
||||||
|
|
||||||
|
//static void findAllIntersections
|
||||||
|
//(
|
||||||
|
// const searchableSurface& s,
|
||||||
|
// const pointField& start,
|
||||||
|
// const pointField& end,
|
||||||
|
// const vectorField& smallVec,
|
||||||
|
// List<List<pointIndexHit> >&
|
||||||
|
//);
|
||||||
|
|
||||||
|
static void mergeHits
|
||||||
|
(
|
||||||
|
const point& start,
|
||||||
|
const scalar mergeDist,
|
||||||
|
|
||||||
|
const label surfI,
|
||||||
|
const List<pointIndexHit>& surfHits,
|
||||||
|
|
||||||
|
labelList& allSurfaces,
|
||||||
|
List<pointIndexHit>& allInfo,
|
||||||
|
scalarList& allDistSqr
|
||||||
|
);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Declare name of the class and its debug switch
|
||||||
|
ClassName("searchableSurfacesQueries");
|
||||||
|
|
||||||
|
|
||||||
|
// Multiple point queries.
|
||||||
|
|
||||||
|
//- Find any intersection. Return hit point information and
|
||||||
|
// index in surfacesToTest. If multiple surfaces hit the first
|
||||||
|
// surface is returned, not necessarily the nearest (to start).
|
||||||
|
static void findAnyIntersection
|
||||||
|
(
|
||||||
|
const PtrList<searchableSurface>&,
|
||||||
|
const labelList& surfacesToTest,
|
||||||
|
const pointField& start,
|
||||||
|
const pointField& end,
|
||||||
|
labelList& surfaces,
|
||||||
|
List<pointIndexHit>&
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Find all intersections in order from start to end. Returns for
|
||||||
|
// every hit the index in surfacesToTest and the hit info.
|
||||||
|
static void findAllIntersections
|
||||||
|
(
|
||||||
|
const PtrList<searchableSurface>&,
|
||||||
|
const labelList& surfacesToTest,
|
||||||
|
const pointField& start,
|
||||||
|
const pointField& end,
|
||||||
|
labelListList& surfaces,
|
||||||
|
List<List<pointIndexHit> >& surfaceHits
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Find nearest. Return -1 (and a miss()) or surface and nearest
|
||||||
|
// point.
|
||||||
|
static void findNearest
|
||||||
|
(
|
||||||
|
const PtrList<searchableSurface>&,
|
||||||
|
const labelList& surfacesToTest,
|
||||||
|
const pointField&,
|
||||||
|
const scalarField& nearestDistSqr,
|
||||||
|
labelList& surfaces,
|
||||||
|
List<pointIndexHit>&
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Single point queries
|
||||||
|
|
||||||
|
//- Calculate point which is on a set of surfaces. WIP.
|
||||||
|
static pointIndexHit facesIntersection
|
||||||
|
(
|
||||||
|
const PtrList<searchableSurface>& allSurfaces,
|
||||||
|
const labelList& surfacesToTest,
|
||||||
|
const scalar initDistSqr,
|
||||||
|
const scalar convergenceDistSqr,
|
||||||
|
const point& start
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
552
src/meshTools/searchableSurface/triSurfaceMesh.C
Normal file
552
src/meshTools/searchableSurface/triSurfaceMesh.C
Normal file
@ -0,0 +1,552 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 1991-2007 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 2 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, write to the Free Software Foundation,
|
||||||
|
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "triSurfaceMesh.H"
|
||||||
|
#include "Random.H"
|
||||||
|
#include "addToRunTimeSelectionTable.H"
|
||||||
|
#include "EdgeMap.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
defineTypeNameAndDebug(triSurfaceMesh, 0);
|
||||||
|
addToRunTimeSelectionTable(searchableSurface, triSurfaceMesh, dict);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
|
//- Check file existence
|
||||||
|
const Foam::fileName& Foam::triSurfaceMesh::checkFile
|
||||||
|
(
|
||||||
|
const fileName& fName,
|
||||||
|
const fileName& objectName
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (fName == fileName::null)
|
||||||
|
{
|
||||||
|
FatalErrorIn
|
||||||
|
(
|
||||||
|
"triSurfaceMesh::checkFile(const fileName&, const fileName&)"
|
||||||
|
) << "Cannot find triSurfaceMesh starting from "
|
||||||
|
<< objectName << exit(FatalError);
|
||||||
|
}
|
||||||
|
return fName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::triSurfaceMesh::isSurfaceClosed() const
|
||||||
|
{
|
||||||
|
// Construct pointFaces. Let's hope surface has compact point
|
||||||
|
// numbering ...
|
||||||
|
labelListList pointFaces;
|
||||||
|
invertManyToMany(points().size(), *this, pointFaces);
|
||||||
|
|
||||||
|
// Loop over all faces surrounding point. Count edges emanating from point.
|
||||||
|
// Every edge should be used by two faces exactly.
|
||||||
|
// To prevent doing work twice per edge only look at edges to higher
|
||||||
|
// point
|
||||||
|
EdgeMap<label> facesPerEdge(100);
|
||||||
|
forAll(pointFaces, pointI)
|
||||||
|
{
|
||||||
|
const labelList& pFaces = pointFaces[pointI];
|
||||||
|
|
||||||
|
facesPerEdge.clear();
|
||||||
|
forAll(pFaces, i)
|
||||||
|
{
|
||||||
|
const labelledTri& f = triSurface::operator[](pFaces[i]);
|
||||||
|
label fp = findIndex(f, pointI);
|
||||||
|
|
||||||
|
// Forward edge
|
||||||
|
{
|
||||||
|
label p1 = f[f.fcIndex(fp)];
|
||||||
|
|
||||||
|
if (p1 > pointI)
|
||||||
|
{
|
||||||
|
const edge e(pointI, p1);
|
||||||
|
EdgeMap<label>::iterator eFnd = facesPerEdge.find(e);
|
||||||
|
if (eFnd != facesPerEdge.end())
|
||||||
|
{
|
||||||
|
if (eFnd() == 2)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
eFnd()++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
facesPerEdge.insert(e, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Reverse edge
|
||||||
|
{
|
||||||
|
label p1 = f[f.rcIndex(fp)];
|
||||||
|
|
||||||
|
if (p1 > pointI)
|
||||||
|
{
|
||||||
|
const edge e(pointI, p1);
|
||||||
|
EdgeMap<label>::iterator eFnd = facesPerEdge.find(e);
|
||||||
|
if (eFnd != facesPerEdge.end())
|
||||||
|
{
|
||||||
|
if (eFnd() == 2)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
eFnd()++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
facesPerEdge.insert(e, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for any edges used only once.
|
||||||
|
forAllConstIter(EdgeMap<label>, facesPerEdge, iter)
|
||||||
|
{
|
||||||
|
if (iter() != 2)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::triSurfaceMesh::triSurfaceMesh(const IOobject& io, const triSurface& s)
|
||||||
|
:
|
||||||
|
searchableSurface(io),
|
||||||
|
objectRegistry(io),
|
||||||
|
triSurface(s),
|
||||||
|
surfaceClosed_(-1)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::triSurfaceMesh::triSurfaceMesh(const IOobject& io)
|
||||||
|
:
|
||||||
|
searchableSurface(io),
|
||||||
|
objectRegistry(io),
|
||||||
|
triSurface
|
||||||
|
(
|
||||||
|
checkFile
|
||||||
|
(
|
||||||
|
searchableSurface::filePath(),
|
||||||
|
searchableSurface::objectPath()
|
||||||
|
)
|
||||||
|
),
|
||||||
|
surfaceClosed_(-1)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::triSurfaceMesh::triSurfaceMesh
|
||||||
|
(
|
||||||
|
const IOobject& io,
|
||||||
|
const dictionary& dict
|
||||||
|
)
|
||||||
|
:
|
||||||
|
searchableSurface(io),
|
||||||
|
objectRegistry(io),
|
||||||
|
triSurface
|
||||||
|
(
|
||||||
|
checkFile
|
||||||
|
(
|
||||||
|
searchableSurface::filePath(),
|
||||||
|
searchableSurface::objectPath()
|
||||||
|
)
|
||||||
|
),
|
||||||
|
surfaceClosed_(-1)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::triSurfaceMesh::~triSurfaceMesh()
|
||||||
|
{
|
||||||
|
clearOut();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::triSurfaceMesh::clearOut()
|
||||||
|
{
|
||||||
|
tree_.clear();
|
||||||
|
edgeTree_.clear();
|
||||||
|
triSurface::clearOut();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::triSurfaceMesh::movePoints(const pointField& newPoints)
|
||||||
|
{
|
||||||
|
tree_.clear();
|
||||||
|
edgeTree_.clear();
|
||||||
|
triSurface::movePoints(newPoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Foam::indexedOctree<Foam::treeDataTriSurface>&
|
||||||
|
Foam::triSurfaceMesh::tree() const
|
||||||
|
{
|
||||||
|
if (!tree_.valid())
|
||||||
|
{
|
||||||
|
treeBoundBox bb(points(), meshPoints());
|
||||||
|
|
||||||
|
// Random number generator. Bit dodgy since not exactly random ;-)
|
||||||
|
Random rndGen(65431);
|
||||||
|
|
||||||
|
tree_.reset
|
||||||
|
(
|
||||||
|
new indexedOctree<treeDataTriSurface>
|
||||||
|
(
|
||||||
|
treeDataTriSurface(*this),
|
||||||
|
bb.extend(rndGen, 1E-3), // slightly randomize bb
|
||||||
|
10, // maxLevel
|
||||||
|
10, // leafsize
|
||||||
|
3.0 // duplicity
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tree_();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Foam::indexedOctree<Foam::treeDataEdge>&
|
||||||
|
Foam::triSurfaceMesh::edgeTree() const
|
||||||
|
{
|
||||||
|
if (!edgeTree_.valid())
|
||||||
|
{
|
||||||
|
treeBoundBox bb(localPoints());
|
||||||
|
|
||||||
|
// Boundary edges
|
||||||
|
labelList bEdges
|
||||||
|
(
|
||||||
|
identity
|
||||||
|
(
|
||||||
|
nEdges()
|
||||||
|
-nInternalEdges()
|
||||||
|
)
|
||||||
|
+ nInternalEdges()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Random number generator. Bit dodgy since not exactly random ;-)
|
||||||
|
Random rndGen(65431);
|
||||||
|
|
||||||
|
edgeTree_.reset
|
||||||
|
(
|
||||||
|
new indexedOctree<treeDataEdge>
|
||||||
|
(
|
||||||
|
treeDataEdge
|
||||||
|
(
|
||||||
|
false, // cachebb
|
||||||
|
edges(), // edges
|
||||||
|
localPoints(), // points
|
||||||
|
bEdges // selected edges
|
||||||
|
),
|
||||||
|
bb.extend(rndGen, 1E-3), // slightly randomize bb
|
||||||
|
8, // maxLevel
|
||||||
|
10, // leafsize
|
||||||
|
3.0 // duplicity
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return edgeTree_();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Foam::wordList& Foam::triSurfaceMesh::regions() const
|
||||||
|
{
|
||||||
|
if (regions_.size() == 0)
|
||||||
|
{
|
||||||
|
regions_.setSize(patches().size());
|
||||||
|
forAll(regions_, regionI)
|
||||||
|
{
|
||||||
|
regions_[regionI] = patches()[regionI].name();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return regions_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Foam::pointIndexHit Foam::triSurfaceMesh::findNearest
|
||||||
|
//(
|
||||||
|
// const point& sample,
|
||||||
|
// const scalar nearestDistSqr
|
||||||
|
//) const
|
||||||
|
//{
|
||||||
|
// return tree().findNearest(sample, nearestDistSqr);
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//Foam::pointIndexHit Foam::triSurfaceMesh::findNearestOnEdge
|
||||||
|
//(
|
||||||
|
// const point& sample,
|
||||||
|
// const scalar nearestDistSqr
|
||||||
|
//) const
|
||||||
|
//{
|
||||||
|
// return = edgeTree().findNearest(sample, nearestDistSqr);
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//Foam::pointIndexHit Foam::triSurfaceMesh::findNearest
|
||||||
|
//(
|
||||||
|
// const linePointRef& ln,
|
||||||
|
// treeBoundBox& tightest,
|
||||||
|
// point& linePoint
|
||||||
|
//) const
|
||||||
|
//{
|
||||||
|
// return tree().findNearest(ln, tightest, linePoint);
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//Foam::pointIndexHit Foam::triSurfaceMesh::findLine
|
||||||
|
//(
|
||||||
|
// const point& start,
|
||||||
|
// const point& end
|
||||||
|
//) const
|
||||||
|
//{
|
||||||
|
// return tree().findLine(start, end);
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//Foam::pointIndexHit Foam::triSurfaceMesh::findLineAny
|
||||||
|
//(
|
||||||
|
// const point& start,
|
||||||
|
// const point& end
|
||||||
|
//) const
|
||||||
|
//{
|
||||||
|
// return tree().findLineAny(start, end);
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
// Find out if surface is closed.
|
||||||
|
bool Foam::triSurfaceMesh::hasVolumeType() const
|
||||||
|
{
|
||||||
|
if (surfaceClosed_ == -1)
|
||||||
|
{
|
||||||
|
if (isSurfaceClosed())
|
||||||
|
{
|
||||||
|
surfaceClosed_ = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
surfaceClosed_ = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return surfaceClosed_ == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::triSurfaceMesh::findNearest
|
||||||
|
(
|
||||||
|
const pointField& samples,
|
||||||
|
const scalarField& nearestDistSqr,
|
||||||
|
List<pointIndexHit>& info
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
const indexedOctree<treeDataTriSurface>& octree = tree();
|
||||||
|
|
||||||
|
info.setSize(samples.size());
|
||||||
|
|
||||||
|
forAll(samples, i)
|
||||||
|
{
|
||||||
|
static_cast<pointIndexHit&>(info[i]) =
|
||||||
|
octree.findNearest(samples[i], nearestDistSqr[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::triSurfaceMesh::findLine
|
||||||
|
(
|
||||||
|
const pointField& start,
|
||||||
|
const pointField& end,
|
||||||
|
List<pointIndexHit>& info
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
const indexedOctree<treeDataTriSurface>& octree = tree();
|
||||||
|
|
||||||
|
info.setSize(start.size());
|
||||||
|
|
||||||
|
forAll(start, i)
|
||||||
|
{
|
||||||
|
static_cast<pointIndexHit&>(info[i]) = octree.findLine
|
||||||
|
(
|
||||||
|
start[i],
|
||||||
|
end[i]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::triSurfaceMesh::findLineAny
|
||||||
|
(
|
||||||
|
const pointField& start,
|
||||||
|
const pointField& end,
|
||||||
|
List<pointIndexHit>& info
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
const indexedOctree<treeDataTriSurface>& octree = tree();
|
||||||
|
|
||||||
|
info.setSize(start.size());
|
||||||
|
|
||||||
|
forAll(start, i)
|
||||||
|
{
|
||||||
|
static_cast<pointIndexHit&>(info[i]) =
|
||||||
|
octree.findLineAny(start[i], end[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::triSurfaceMesh::findLineAll
|
||||||
|
(
|
||||||
|
const pointField& start,
|
||||||
|
const pointField& end,
|
||||||
|
List<List<pointIndexHit> >& info
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
const indexedOctree<treeDataTriSurface>& octree = tree();
|
||||||
|
|
||||||
|
info.setSize(start.size());
|
||||||
|
|
||||||
|
// Work array
|
||||||
|
DynamicList<pointIndexHit, 1, 1> hits;
|
||||||
|
|
||||||
|
// Tolerances
|
||||||
|
const vectorField dirVec(end-start);
|
||||||
|
const scalarField magSqrDirVec(magSqr(dirVec));
|
||||||
|
const vectorField smallVec
|
||||||
|
(
|
||||||
|
Foam::sqrt(SMALL)*dirVec
|
||||||
|
+ vector(ROOTVSMALL,ROOTVSMALL,ROOTVSMALL)
|
||||||
|
);
|
||||||
|
|
||||||
|
forAll(start, pointI)
|
||||||
|
{
|
||||||
|
hits.clear();
|
||||||
|
|
||||||
|
// Current starting point of ray.
|
||||||
|
point pt = start[pointI];
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
// See if any intersection between pt and end
|
||||||
|
pointIndexHit inter = octree.findLine(pt, end[pointI]);
|
||||||
|
|
||||||
|
if (!inter.hit())
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
hits.append(inter);
|
||||||
|
|
||||||
|
pt = inter.hitPoint() + smallVec[pointI];
|
||||||
|
|
||||||
|
if (((pt-start[pointI])&dirVec[pointI]) > magSqrDirVec[pointI])
|
||||||
|
{
|
||||||
|
// Adding smallVec has taken us beyond end
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hits.shrink();
|
||||||
|
info[pointI].transfer(hits);
|
||||||
|
hits.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::triSurfaceMesh::getRegion
|
||||||
|
(
|
||||||
|
const List<pointIndexHit>& info,
|
||||||
|
labelList& region
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
region.setSize(info.size());
|
||||||
|
forAll(info, i)
|
||||||
|
{
|
||||||
|
if (info[i].hit())
|
||||||
|
{
|
||||||
|
region[i] = triSurface::operator[](info[i].index()).region();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
region[i] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::triSurfaceMesh::getNormal
|
||||||
|
(
|
||||||
|
const List<pointIndexHit>& info,
|
||||||
|
vectorField& normal
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
normal.setSize(info.size());
|
||||||
|
|
||||||
|
forAll(info, i)
|
||||||
|
{
|
||||||
|
if (info[i].hit())
|
||||||
|
{
|
||||||
|
normal[i] = faceNormals()[info[i].index()];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Set to what?
|
||||||
|
normal[i] = vector::zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::triSurfaceMesh::getVolumeType
|
||||||
|
(
|
||||||
|
const pointField& points,
|
||||||
|
List<volumeType>& volType
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
volType.setSize(points.size());
|
||||||
|
|
||||||
|
forAll(points, pointI)
|
||||||
|
{
|
||||||
|
const point& pt = points[pointI];
|
||||||
|
|
||||||
|
// - use cached volume type per each tree node
|
||||||
|
// - cheat conversion since same values
|
||||||
|
volType[pointI] = static_cast<volumeType>(tree().getVolumeType(pt));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -2,7 +2,7 @@
|
|||||||
========= |
|
========= |
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
\\ / O peration |
|
\\ / O peration |
|
||||||
\\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd.
|
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -54,7 +54,7 @@ namespace Foam
|
|||||||
class triSurfaceMesh
|
class triSurfaceMesh
|
||||||
:
|
:
|
||||||
public searchableSurface,
|
public searchableSurface,
|
||||||
public objectRegistry,
|
public objectRegistry, // so we can store fields
|
||||||
public triSurface
|
public triSurface
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@ -67,6 +67,12 @@ private:
|
|||||||
//- Search tree for boundary edges.
|
//- Search tree for boundary edges.
|
||||||
mutable autoPtr<indexedOctree<treeDataEdge> > edgeTree_;
|
mutable autoPtr<indexedOctree<treeDataEdge> > edgeTree_;
|
||||||
|
|
||||||
|
//- Names of regions
|
||||||
|
mutable wordList regions_;
|
||||||
|
|
||||||
|
//- Is surface closed
|
||||||
|
mutable label surfaceClosed_;
|
||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
|
|
||||||
//- Check file existence
|
//- Check file existence
|
||||||
@ -76,6 +82,10 @@ private:
|
|||||||
const fileName& objectName
|
const fileName& objectName
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//- Check whether surface is closed without calculating any permanent
|
||||||
|
// addressing.
|
||||||
|
bool isSurfaceClosed() const;
|
||||||
|
|
||||||
//- Disallow default bitwise copy construct
|
//- Disallow default bitwise copy construct
|
||||||
triSurfaceMesh(const triSurfaceMesh&);
|
triSurfaceMesh(const triSurfaceMesh&);
|
||||||
|
|
||||||
@ -97,11 +107,10 @@ public:
|
|||||||
//- Construct read
|
//- Construct read
|
||||||
triSurfaceMesh(const IOobject& io);
|
triSurfaceMesh(const IOobject& io);
|
||||||
|
|
||||||
//- Construct as searchableSurface
|
//- Construct from dictionary (used by searchableSurface)
|
||||||
triSurfaceMesh
|
triSurfaceMesh
|
||||||
(
|
(
|
||||||
const word& name,
|
const IOobject& io,
|
||||||
const objectRegistry& obj,
|
|
||||||
const dictionary& dict
|
const dictionary& dict
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -128,57 +137,73 @@ public:
|
|||||||
|
|
||||||
// searchableSurface implementation
|
// searchableSurface implementation
|
||||||
|
|
||||||
//- Calculate nearest point on surface. Returns
|
virtual const wordList& regions() const;
|
||||||
// - bool : any point found nearer than nearestDistSqr
|
|
||||||
// - label: relevant index in surface
|
//- Whether supports volume type below. I.e. whether is closed.
|
||||||
// - point: actual nearest point found
|
virtual bool hasVolumeType() const;
|
||||||
virtual pointIndexHit findNearest
|
|
||||||
|
|
||||||
|
// Multiple point queries.
|
||||||
|
|
||||||
|
virtual void findNearest
|
||||||
(
|
(
|
||||||
const point& sample,
|
const pointField& sample,
|
||||||
const scalar nearestDistSqr
|
const scalarField& nearestDistSqr,
|
||||||
|
List<pointIndexHit>&
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
//- Calculate nearest point on edge. Returns
|
virtual void findLine
|
||||||
// - bool : any point found nearer than nearestDistSqr
|
|
||||||
// - label: relevant index in surface
|
|
||||||
// - point: actual nearest point found
|
|
||||||
virtual pointIndexHit findNearestOnEdge
|
|
||||||
(
|
(
|
||||||
const point& sample,
|
const pointField& start,
|
||||||
const scalar nearestDistSqr
|
const pointField& end,
|
||||||
|
List<pointIndexHit>&
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
//- Find nearest to line. Returns
|
virtual void findLineAny
|
||||||
// - bool : any point found?
|
|
||||||
// - label: relevant index in shapes
|
|
||||||
// - point: actual nearest point found
|
|
||||||
// sets:
|
|
||||||
// - tightest : bounding box
|
|
||||||
// - linePoint : corresponding nearest point on line
|
|
||||||
virtual pointIndexHit findNearest
|
|
||||||
(
|
(
|
||||||
const linePointRef& ln,
|
const pointField& start,
|
||||||
treeBoundBox& tightest,
|
const pointField& end,
|
||||||
point& linePoint
|
List<pointIndexHit>&
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
//- Find nearest intersection of line between start and end.
|
//- Get all intersections in order from start to end.
|
||||||
virtual pointIndexHit findLine
|
virtual void findLineAll
|
||||||
(
|
(
|
||||||
const point& start,
|
const pointField& start,
|
||||||
const point& end
|
const pointField& end,
|
||||||
|
List<List<pointIndexHit> >&
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
//- Find any intersection of line between start and end.
|
//- From a set of points and indices get the region
|
||||||
virtual pointIndexHit findLineAny
|
virtual void getRegion
|
||||||
(
|
(
|
||||||
const point& start,
|
const List<pointIndexHit>&,
|
||||||
const point& end
|
labelList& region
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- From a set of points and indices get the normal
|
||||||
|
virtual void getNormal
|
||||||
|
(
|
||||||
|
const List<pointIndexHit>&,
|
||||||
|
vectorField& normal
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
//- Determine type (inside/outside/mixed) for point. unknown if
|
//- Determine type (inside/outside/mixed) for point. unknown if
|
||||||
// cannot be determined (e.g. non-manifold surface)
|
// cannot be determined (e.g. non-manifold surface)
|
||||||
virtual volumeType getVolumeType(const point&) const;
|
virtual void getVolumeType
|
||||||
|
(
|
||||||
|
const pointField&,
|
||||||
|
List<volumeType>&
|
||||||
|
) const;
|
||||||
|
|
||||||
|
|
||||||
|
// regIOobject implementation
|
||||||
|
|
||||||
|
bool writeData(Ostream&) const
|
||||||
|
{
|
||||||
|
notImplemented("triSurfaceMesh::writeData(Ostream&) const");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1,247 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | Copyright (C) 1991-2008 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 2 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, write to the Free Software Foundation,
|
|
||||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "searchableBox.H"
|
|
||||||
#include "addToRunTimeSelectionTable.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
namespace Foam
|
|
||||||
{
|
|
||||||
|
|
||||||
defineTypeNameAndDebug(searchableBox, 0);
|
|
||||||
addToRunTimeSelectionTable(searchableSurface, searchableBox, dict);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
Foam::searchableBox::searchableBox
|
|
||||||
(
|
|
||||||
const word& name,
|
|
||||||
const treeBoundBox& bb
|
|
||||||
)
|
|
||||||
:
|
|
||||||
searchableSurface(name),
|
|
||||||
treeBoundBox(bb)
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
Foam::searchableBox::searchableBox
|
|
||||||
(
|
|
||||||
const word& name,
|
|
||||||
const objectRegistry& obj,
|
|
||||||
const dictionary& dict
|
|
||||||
)
|
|
||||||
:
|
|
||||||
searchableSurface(name),
|
|
||||||
treeBoundBox(dict.lookup("min"), dict.lookup("max"))
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
Foam::searchableBox::~searchableBox()
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
Foam::pointIndexHit Foam::searchableBox::findNearest
|
|
||||||
(
|
|
||||||
const point& sample,
|
|
||||||
const scalar nearestDistSqr
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
// Point can be inside or outside. For every component direction can be
|
|
||||||
// left of min, right of max or inbetween.
|
|
||||||
// - outside points: project first one x plane (either min().x()
|
|
||||||
// or max().x()), then onto y plane and finally z. You should be left
|
|
||||||
// with intersection point
|
|
||||||
// - inside point: find nearest side (compare to mid point). Pick any
|
|
||||||
// one of three points.
|
|
||||||
|
|
||||||
const point bbMid(mid());
|
|
||||||
|
|
||||||
// Outside point projected onto cube
|
|
||||||
point interPt(sample);
|
|
||||||
bool outside = false;
|
|
||||||
|
|
||||||
// (for internal points) Per direction what nearest cube side is
|
|
||||||
point near;
|
|
||||||
|
|
||||||
for (direction dir = 0; dir < vector::nComponents; dir++)
|
|
||||||
{
|
|
||||||
if (interPt[dir] < min()[dir])
|
|
||||||
{
|
|
||||||
interPt[dir] = min()[dir];
|
|
||||||
outside = true;
|
|
||||||
}
|
|
||||||
else if (interPt[dir] > max()[dir])
|
|
||||||
{
|
|
||||||
interPt[dir] = max()[dir];
|
|
||||||
outside = true;
|
|
||||||
}
|
|
||||||
else if (interPt[dir] > bbMid[dir])
|
|
||||||
{
|
|
||||||
near[dir] = max()[dir];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
near[dir] = min()[dir];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// For outside points the interPt will be correct now. Handle inside points
|
|
||||||
// using the three near distances. Project onto the nearest plane.
|
|
||||||
if (!outside)
|
|
||||||
{
|
|
||||||
vector dist(cmptMag(interPt - near));
|
|
||||||
|
|
||||||
if (dist.x() < dist.y())
|
|
||||||
{
|
|
||||||
if (dist.x() < dist.z())
|
|
||||||
{
|
|
||||||
interPt.x() = near.x();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
interPt.z() = near.z();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (dist.y() < dist.z())
|
|
||||||
{
|
|
||||||
interPt.y() = near.y();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
interPt.z() = near.z();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pointIndexHit(true, interPt, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Foam::pointIndexHit Foam::searchableBox::findNearestOnEdge
|
|
||||||
(
|
|
||||||
const point& sample,
|
|
||||||
const scalar nearestDistSqr
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
const point bbMid(mid());
|
|
||||||
|
|
||||||
point interPt(sample);
|
|
||||||
|
|
||||||
for (direction dir = 0; dir < vector::nComponents; dir++)
|
|
||||||
{
|
|
||||||
// Project onto left or right depending on mid
|
|
||||||
if (interPt[dir] > bbMid[dir])
|
|
||||||
{
|
|
||||||
interPt[dir] = max()[dir];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
interPt[dir] = min()[dir];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pointIndexHit(true, interPt, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Foam::pointIndexHit Foam::searchableBox::findNearest
|
|
||||||
(
|
|
||||||
const linePointRef& ln,
|
|
||||||
treeBoundBox& tightest,
|
|
||||||
point& linePoint
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
notImplemented
|
|
||||||
(
|
|
||||||
"searchableBox::findNearest"
|
|
||||||
"(const linePointRef&, treeBoundBox&, point&)"
|
|
||||||
);
|
|
||||||
return pointIndexHit();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Foam::pointIndexHit Foam::searchableBox::findLine
|
|
||||||
(
|
|
||||||
const point& start,
|
|
||||||
const point& end
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
point intPt;
|
|
||||||
bool foundInter = intersects(start, end, intPt);
|
|
||||||
|
|
||||||
return pointIndexHit(foundInter, intPt, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Foam::pointIndexHit Foam::searchableBox::findLineAny
|
|
||||||
(
|
|
||||||
const point& start,
|
|
||||||
const point& end
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
return findLine(start, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Foam::searchableSurface::volumeType Foam::searchableBox::getVolumeType
|
|
||||||
(
|
|
||||||
const point& pt
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
for (direction dir = 0; dir < vector::nComponents; dir++)
|
|
||||||
{
|
|
||||||
if (pt[dir] < min()[dir] || pt[dir] > max()[dir])
|
|
||||||
{
|
|
||||||
return OUTSIDE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return INSIDE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -1,161 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | Copyright (C) 1991-2008 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 2 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, write to the Free Software Foundation,
|
|
||||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
Class
|
|
||||||
Foam::searchableBox
|
|
||||||
|
|
||||||
Description
|
|
||||||
Searching on bounding box
|
|
||||||
|
|
||||||
SourceFiles
|
|
||||||
searchableBox.C
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#ifndef searchableBox_H
|
|
||||||
#define searchableBox_H
|
|
||||||
|
|
||||||
#include "searchableSurface.H"
|
|
||||||
#include "treeBoundBox.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
namespace Foam
|
|
||||||
{
|
|
||||||
|
|
||||||
// Forward declaration of classes
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
Class searchableBox Declaration
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
class searchableBox
|
|
||||||
:
|
|
||||||
public searchableSurface,
|
|
||||||
public treeBoundBox
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
|
|
||||||
// Private member data
|
|
||||||
|
|
||||||
|
|
||||||
// Private Member Functions
|
|
||||||
|
|
||||||
//- Disallow default bitwise copy construct
|
|
||||||
searchableBox(const searchableBox&);
|
|
||||||
|
|
||||||
//- Disallow default bitwise assignment
|
|
||||||
void operator=(const searchableBox&);
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
//- Runtime type information
|
|
||||||
TypeName("searchableBox");
|
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
|
||||||
|
|
||||||
//- Construct from components
|
|
||||||
searchableBox(const word& name, const treeBoundBox& bb);
|
|
||||||
|
|
||||||
searchableBox
|
|
||||||
(
|
|
||||||
const word& name,
|
|
||||||
const objectRegistry& obj,
|
|
||||||
const dictionary& dict
|
|
||||||
);
|
|
||||||
|
|
||||||
// Destructor
|
|
||||||
|
|
||||||
virtual ~searchableBox();
|
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
|
||||||
|
|
||||||
//- Calculate nearest point on surface. Returns
|
|
||||||
// - bool : any point found nearer than nearestDistSqr
|
|
||||||
// - label: relevant index in surface
|
|
||||||
// - point: actual nearest point found
|
|
||||||
virtual pointIndexHit findNearest
|
|
||||||
(
|
|
||||||
const point& sample,
|
|
||||||
const scalar nearestDistSqr
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Calculate nearest point on edge. Returns
|
|
||||||
// - bool : any point found nearer than nearestDistSqr
|
|
||||||
// - label: relevant index in surface
|
|
||||||
// - point: actual nearest point found
|
|
||||||
virtual pointIndexHit findNearestOnEdge
|
|
||||||
(
|
|
||||||
const point& sample,
|
|
||||||
const scalar nearestDistSqr
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Find nearest to line. Returns
|
|
||||||
// - bool : any point found?
|
|
||||||
// - label: relevant index in shapes
|
|
||||||
// - point: actual nearest point found
|
|
||||||
// sets:
|
|
||||||
// - tightest : bounding box
|
|
||||||
// - linePoint : corresponding nearest point on line
|
|
||||||
virtual pointIndexHit findNearest
|
|
||||||
(
|
|
||||||
const linePointRef& ln,
|
|
||||||
treeBoundBox& tightest,
|
|
||||||
point& linePoint
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Find nearest intersection of line between start and end.
|
|
||||||
virtual pointIndexHit findLine
|
|
||||||
(
|
|
||||||
const point& start,
|
|
||||||
const point& end
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Find any intersection of line between start and end.
|
|
||||||
virtual pointIndexHit findLineAny
|
|
||||||
(
|
|
||||||
const point& start,
|
|
||||||
const point& end
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Determine type (inside/outside/mixed) for point. unknown if
|
|
||||||
// cannot be determined (e.g. non-manifold surface)
|
|
||||||
virtual volumeType getVolumeType(const point&) const;
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
} // End namespace Foam
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -1,257 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | Copyright (C) 1991-2008 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 2 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, write to the Free Software Foundation,
|
|
||||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
Class
|
|
||||||
Foam::searchableSurface
|
|
||||||
|
|
||||||
Description
|
|
||||||
Base class of (analytical or triangulated) surface.
|
|
||||||
Encapsulates all the search routines.
|
|
||||||
|
|
||||||
SourceFiles
|
|
||||||
searchableSurface.C
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#ifndef searchableSurface_H
|
|
||||||
#define searchableSurface_H
|
|
||||||
|
|
||||||
#include "pointField.H"
|
|
||||||
#include "typeInfo.H"
|
|
||||||
#include "runTimeSelectionTables.H"
|
|
||||||
#include "pointIndexHit.H"
|
|
||||||
#include "linePointRef.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
namespace Foam
|
|
||||||
{
|
|
||||||
|
|
||||||
// Forward declaration of classes
|
|
||||||
class objectRegistry;
|
|
||||||
class treeBoundBox;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
Class searchableSurface Declaration
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
class searchableSurface
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
// Data types
|
|
||||||
|
|
||||||
//- volume types
|
|
||||||
enum volumeType
|
|
||||||
{
|
|
||||||
UNKNOWN = 0,
|
|
||||||
MIXED = 1,
|
|
||||||
INSIDE = 2,
|
|
||||||
OUTSIDE = 3
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
// Private data
|
|
||||||
|
|
||||||
const word name_;
|
|
||||||
|
|
||||||
|
|
||||||
// Private Member Functions
|
|
||||||
|
|
||||||
//- Disallow default bitwise copy construct
|
|
||||||
searchableSurface(const searchableSurface&);
|
|
||||||
|
|
||||||
//- Disallow default bitwise assignment
|
|
||||||
void operator=(const searchableSurface&);
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
//- Runtime type information
|
|
||||||
TypeName("searchableSurface");
|
|
||||||
|
|
||||||
// Declare run-time constructor selection table
|
|
||||||
|
|
||||||
// For the dictionary constructor
|
|
||||||
declareRunTimeSelectionTable
|
|
||||||
(
|
|
||||||
autoPtr,
|
|
||||||
searchableSurface,
|
|
||||||
dict,
|
|
||||||
(
|
|
||||||
const word& name,
|
|
||||||
const objectRegistry& obj,
|
|
||||||
const dictionary& dict
|
|
||||||
),
|
|
||||||
(name, obj, dict)
|
|
||||||
);
|
|
||||||
|
|
||||||
//// For the Istream constructor
|
|
||||||
//declareRunTimeSelectionTable
|
|
||||||
//(
|
|
||||||
// autoPtr,
|
|
||||||
// searchableSurface,
|
|
||||||
// istream,
|
|
||||||
// (
|
|
||||||
// const objectRegistry& obj,
|
|
||||||
// Istream& is
|
|
||||||
// ),
|
|
||||||
// (obj, is)
|
|
||||||
//);
|
|
||||||
|
|
||||||
|
|
||||||
//- Class used for the read-construction of
|
|
||||||
// PtrLists of searchableSurface
|
|
||||||
class iNew
|
|
||||||
{
|
|
||||||
const objectRegistry& obj_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
iNew(const objectRegistry& obj)
|
|
||||||
:
|
|
||||||
obj_(obj)
|
|
||||||
{}
|
|
||||||
|
|
||||||
autoPtr<searchableSurface> operator()(Istream& is) const
|
|
||||||
{
|
|
||||||
word surfaceType(is);
|
|
||||||
word name(is);
|
|
||||||
dictionary dict(is);
|
|
||||||
return searchableSurface::New(surfaceType, name, obj_, dict);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
|
||||||
|
|
||||||
searchableSurface(const word& name);
|
|
||||||
|
|
||||||
//- Clone
|
|
||||||
virtual autoPtr<searchableSurface> clone() const
|
|
||||||
{
|
|
||||||
notImplemented("autoPtr<searchableSurface> clone() const");
|
|
||||||
return autoPtr<searchableSurface>(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Selectors
|
|
||||||
|
|
||||||
//- Return a reference to the selected searchableSurface
|
|
||||||
static autoPtr<searchableSurface> New
|
|
||||||
(
|
|
||||||
const word& surfaceType,
|
|
||||||
const word& name,
|
|
||||||
const objectRegistry& obj,
|
|
||||||
const dictionary& dict
|
|
||||||
);
|
|
||||||
|
|
||||||
////- Return a reference to the selected searchableSurface
|
|
||||||
//static autoPtr<searchableSurface> New
|
|
||||||
//(
|
|
||||||
// const word& surfaceType,
|
|
||||||
// const objectRegistry& obj,
|
|
||||||
// Istream& is
|
|
||||||
//);
|
|
||||||
|
|
||||||
|
|
||||||
// Destructor
|
|
||||||
|
|
||||||
virtual ~searchableSurface();
|
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
|
||||||
|
|
||||||
//- Return name
|
|
||||||
const word& name() const
|
|
||||||
{
|
|
||||||
return name_;
|
|
||||||
}
|
|
||||||
|
|
||||||
//- Calculate nearest point on surface. Returns
|
|
||||||
// - bool : any point found nearer than nearestDistSqr
|
|
||||||
// - label: relevant index in surface
|
|
||||||
// - point: actual nearest point found
|
|
||||||
virtual pointIndexHit findNearest
|
|
||||||
(
|
|
||||||
const point& sample,
|
|
||||||
const scalar nearestDistSqr
|
|
||||||
) const = 0;
|
|
||||||
|
|
||||||
//- Calculate nearest point on edge. Returns
|
|
||||||
// - bool : any point found nearer than nearestDistSqr
|
|
||||||
// - label: relevant index in surface
|
|
||||||
// - point: actual nearest point found
|
|
||||||
virtual pointIndexHit findNearestOnEdge
|
|
||||||
(
|
|
||||||
const point& sample,
|
|
||||||
const scalar nearestDistSqr
|
|
||||||
) const = 0;
|
|
||||||
|
|
||||||
//- Find nearest to segment. Returns
|
|
||||||
// - bool : any point found?
|
|
||||||
// - label: relevant index in shapes
|
|
||||||
// - point: actual nearest point found
|
|
||||||
// sets:
|
|
||||||
// - tightest : bounding box
|
|
||||||
// - linePoint : corresponding nearest point on line
|
|
||||||
virtual pointIndexHit findNearest
|
|
||||||
(
|
|
||||||
const linePointRef& ln,
|
|
||||||
treeBoundBox& tightest,
|
|
||||||
point& linePoint
|
|
||||||
) const = 0;
|
|
||||||
|
|
||||||
//- Find nearest intersection of line between start and end.
|
|
||||||
virtual pointIndexHit findLine
|
|
||||||
(
|
|
||||||
const point& start,
|
|
||||||
const point& end
|
|
||||||
) const = 0;
|
|
||||||
|
|
||||||
//- Find any intersection of line between start and end.
|
|
||||||
virtual pointIndexHit findLineAny
|
|
||||||
(
|
|
||||||
const point& start,
|
|
||||||
const point& end
|
|
||||||
) const = 0;
|
|
||||||
|
|
||||||
//- Determine type (inside/outside/mixed) for point. unknown if
|
|
||||||
// cannot be determined (e.g. non-manifold surface)
|
|
||||||
virtual volumeType getVolumeType(const point&) const = 0;
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
} // End namespace Foam
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -1,271 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | Copyright (C) 1991-2008 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 2 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, write to the Free Software Foundation,
|
|
||||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "triSurfaceMesh.H"
|
|
||||||
#include "Random.H"
|
|
||||||
#include "addToRunTimeSelectionTable.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
namespace Foam
|
|
||||||
{
|
|
||||||
|
|
||||||
defineTypeNameAndDebug(triSurfaceMesh, 0);
|
|
||||||
addToRunTimeSelectionTable(searchableSurface, triSurfaceMesh, dict);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
|
||||||
|
|
||||||
//- Check file existence
|
|
||||||
const Foam::fileName& Foam::triSurfaceMesh::checkFile
|
|
||||||
(
|
|
||||||
const fileName& fName,
|
|
||||||
const fileName& objectName
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (fName == fileName::null)
|
|
||||||
{
|
|
||||||
FatalErrorIn
|
|
||||||
(
|
|
||||||
"triSurfaceMesh::checkFile(const fileName&, const fileName&)"
|
|
||||||
) << "Cannot find triSurfaceMesh starting from "
|
|
||||||
<< objectName << exit(FatalError);
|
|
||||||
}
|
|
||||||
return fName;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const Foam::indexedOctree<Foam::treeDataTriSurface>&
|
|
||||||
Foam::triSurfaceMesh::tree() const
|
|
||||||
{
|
|
||||||
if (!tree_.valid())
|
|
||||||
{
|
|
||||||
treeBoundBox bb(points(), meshPoints());
|
|
||||||
|
|
||||||
// Random number generator. Bit dodgy since not exactly random ;-)
|
|
||||||
Random rndGen(65431);
|
|
||||||
|
|
||||||
tree_.reset
|
|
||||||
(
|
|
||||||
new indexedOctree<treeDataTriSurface>
|
|
||||||
(
|
|
||||||
treeDataTriSurface(*this),
|
|
||||||
bb.extend(rndGen, 1E-3), // slightly randomize bb
|
|
||||||
8, // maxLevel
|
|
||||||
10, // leafsize
|
|
||||||
3.0 // duplicity
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return tree_();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const Foam::indexedOctree<Foam::treeDataEdge>&
|
|
||||||
Foam::triSurfaceMesh::edgeTree() const
|
|
||||||
{
|
|
||||||
if (!edgeTree_.valid())
|
|
||||||
{
|
|
||||||
treeBoundBox bb(localPoints());
|
|
||||||
|
|
||||||
// Boundary edges
|
|
||||||
labelList bEdges
|
|
||||||
(
|
|
||||||
identity
|
|
||||||
(
|
|
||||||
nEdges()
|
|
||||||
-nInternalEdges()
|
|
||||||
)
|
|
||||||
+ nInternalEdges()
|
|
||||||
);
|
|
||||||
|
|
||||||
// Random number generator. Bit dodgy since not exactly random ;-)
|
|
||||||
Random rndGen(65431);
|
|
||||||
|
|
||||||
edgeTree_.reset
|
|
||||||
(
|
|
||||||
new indexedOctree<treeDataEdge>
|
|
||||||
(
|
|
||||||
treeDataEdge
|
|
||||||
(
|
|
||||||
false, // cachebb
|
|
||||||
edges(), // edges
|
|
||||||
localPoints(), // points
|
|
||||||
bEdges // selected edges
|
|
||||||
),
|
|
||||||
bb.extend(rndGen, 1E-3), // slightly randomize bb
|
|
||||||
8, // maxLevel
|
|
||||||
10, // leafsize
|
|
||||||
3.0 // duplicity
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return edgeTree_();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
//- Construct from triangles, patches, points.
|
|
||||||
Foam::triSurfaceMesh::triSurfaceMesh(const IOobject& io, const triSurface& s)
|
|
||||||
:
|
|
||||||
searchableSurface(io.name()),
|
|
||||||
objectRegistry(io),
|
|
||||||
triSurface(s)
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
Foam::triSurfaceMesh::triSurfaceMesh(const IOobject& io)
|
|
||||||
:
|
|
||||||
searchableSurface(io.name()),
|
|
||||||
objectRegistry(io),
|
|
||||||
triSurface(checkFile(filePath(), objectPath()))
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
Foam::triSurfaceMesh::triSurfaceMesh
|
|
||||||
(
|
|
||||||
const word& name,
|
|
||||||
const objectRegistry& obj,
|
|
||||||
const dictionary& dict
|
|
||||||
)
|
|
||||||
:
|
|
||||||
searchableSurface(name),
|
|
||||||
objectRegistry
|
|
||||||
(
|
|
||||||
IOobject
|
|
||||||
(
|
|
||||||
name,
|
|
||||||
"constant",
|
|
||||||
"triSurface",
|
|
||||||
obj,
|
|
||||||
IOobject::MUST_READ,
|
|
||||||
IOobject::NO_WRITE
|
|
||||||
)
|
|
||||||
),
|
|
||||||
triSurface(checkFile(filePath(), objectPath()))
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
Foam::triSurfaceMesh::~triSurfaceMesh()
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
void Foam::triSurfaceMesh::clearOut()
|
|
||||||
{
|
|
||||||
tree_.clear();
|
|
||||||
edgeTree_.clear();
|
|
||||||
triSurface::clearOut();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
void Foam::triSurfaceMesh::movePoints(const pointField& newPoints)
|
|
||||||
{
|
|
||||||
tree_.clear();
|
|
||||||
edgeTree_.clear();
|
|
||||||
triSurface::movePoints(newPoints);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Foam::pointIndexHit Foam::triSurfaceMesh::findNearest
|
|
||||||
(
|
|
||||||
const point& sample,
|
|
||||||
const scalar nearestDistSqr
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
return tree().findNearest(sample, nearestDistSqr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Foam::pointIndexHit Foam::triSurfaceMesh::findNearestOnEdge
|
|
||||||
(
|
|
||||||
const point& sample,
|
|
||||||
const scalar nearestDistSqr
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
return edgeTree().findNearest(sample, nearestDistSqr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Foam::pointIndexHit Foam::triSurfaceMesh::findNearest
|
|
||||||
(
|
|
||||||
const linePointRef& ln,
|
|
||||||
treeBoundBox& tightest,
|
|
||||||
point& linePoint
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
return tree().findNearest(ln, tightest, linePoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Foam::pointIndexHit Foam::triSurfaceMesh::findLine
|
|
||||||
(
|
|
||||||
const point& start,
|
|
||||||
const point& end
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
return tree().findLine(start, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Foam::pointIndexHit Foam::triSurfaceMesh::findLineAny
|
|
||||||
(
|
|
||||||
const point& start,
|
|
||||||
const point& end
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
return tree().findLineAny(start, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Foam::searchableSurface::volumeType
|
|
||||||
Foam::triSurfaceMesh::getVolumeType
|
|
||||||
(
|
|
||||||
const point& pt
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
// - use cached volume type per each tree node
|
|
||||||
// - cheat conversion since same values
|
|
||||||
return static_cast<volumeType>(tree().getVolumeType(pt));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -1,916 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | Copyright (C) 1991-2008 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 2 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, write to the Free Software Foundation,
|
|
||||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
\*----------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "triSurfaceMeshes.H"
|
|
||||||
#include "Random.H"
|
|
||||||
#include "Time.H"
|
|
||||||
#include "SortableList.H"
|
|
||||||
#include "IOmanip.H"
|
|
||||||
#include "plane.H"
|
|
||||||
#include "SortableList.H"
|
|
||||||
#include "triSurfaceTools.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
namespace Foam
|
|
||||||
{
|
|
||||||
|
|
||||||
defineTypeNameAndDebug(triSurfaceMeshes, 0);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
|
||||||
|
|
||||||
// Calculate sum of distance to surfaces.
|
|
||||||
Foam::scalar Foam::triSurfaceMeshes::sumDistSqr
|
|
||||||
(
|
|
||||||
const labelList& surfacesToTest,
|
|
||||||
const scalar initDistSqr,
|
|
||||||
const point& pt
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
scalar sum = 0;
|
|
||||||
|
|
||||||
forAll(surfacesToTest, i)
|
|
||||||
{
|
|
||||||
label surfI = surfacesToTest[i];
|
|
||||||
|
|
||||||
pointIndexHit hit(operator[](surfI).findNearest(pt, initDistSqr));
|
|
||||||
|
|
||||||
// Note: make it fall over if not hit.
|
|
||||||
sum += magSqr(hit.hitPoint()-pt);
|
|
||||||
}
|
|
||||||
return sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Reflects the point furthest away around the triangle centre by a factor fac.
|
|
||||||
// (triangle centre is the average of all points but the ihi. pSum is running
|
|
||||||
// sum of all points)
|
|
||||||
Foam::scalar Foam::triSurfaceMeshes::tryMorphTet
|
|
||||||
(
|
|
||||||
const labelList& surfacesToTest,
|
|
||||||
const scalar initDistSqr,
|
|
||||||
List<vector>& p,
|
|
||||||
List<scalar>& y,
|
|
||||||
vector& pSum,
|
|
||||||
const label ihi,
|
|
||||||
const scalar fac
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
scalar fac1 = (1.0-fac)/vector::nComponents;
|
|
||||||
scalar fac2 = fac1-fac;
|
|
||||||
|
|
||||||
vector ptry = pSum*fac1-p[ihi]*fac2;
|
|
||||||
|
|
||||||
scalar ytry = sumDistSqr(surfacesToTest, initDistSqr, ptry);
|
|
||||||
|
|
||||||
if (ytry < y[ihi])
|
|
||||||
{
|
|
||||||
y[ihi] = ytry;
|
|
||||||
pSum += ptry - p[ihi];
|
|
||||||
p[ihi] = ptry;
|
|
||||||
}
|
|
||||||
return ytry;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool Foam::triSurfaceMeshes::morphTet
|
|
||||||
(
|
|
||||||
const labelList& surfacesToTest,
|
|
||||||
const scalar initDistSqr,
|
|
||||||
const scalar convergenceDistSqr,
|
|
||||||
const label maxIter,
|
|
||||||
List<vector>& p,
|
|
||||||
List<scalar>& y
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
vector pSum = sum(p);
|
|
||||||
|
|
||||||
autoPtr<OFstream> str;
|
|
||||||
label vertI = 0;
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
Pout<< "triSurfaceMeshes::morphTet : intersection of "
|
|
||||||
<< IndirectList<fileName>(names(), surfacesToTest)()
|
|
||||||
<< " starting from points:" << p << endl;
|
|
||||||
str.reset(new OFstream("track.obj"));
|
|
||||||
meshTools::writeOBJ(str(), p[0]);
|
|
||||||
vertI++;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (label iter = 0; iter < maxIter; iter++)
|
|
||||||
{
|
|
||||||
// Get the indices of highest, second-highest and lowest values.
|
|
||||||
label ihi, inhi, ilo;
|
|
||||||
{
|
|
||||||
SortableList<scalar> sortedY(y);
|
|
||||||
ilo = sortedY.indices()[0];
|
|
||||||
ihi = sortedY.indices()[sortedY.size()-1];
|
|
||||||
inhi = sortedY.indices()[sortedY.size()-2];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
Pout<< "Iteration:" << iter
|
|
||||||
<< " lowest:" << y[ilo] << " highest:" << y[ihi]
|
|
||||||
<< " points:" << p << endl;
|
|
||||||
|
|
||||||
meshTools::writeOBJ(str(), p[ilo]);
|
|
||||||
vertI++;
|
|
||||||
str()<< "l " << vertI-1 << ' ' << vertI << nl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (y[ihi] < convergenceDistSqr)
|
|
||||||
{
|
|
||||||
// Get point on 0th surface.
|
|
||||||
Swap(p[0], p[ilo]);
|
|
||||||
Swap(y[0], y[ilo]);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reflection: point furthest away gets reflected.
|
|
||||||
scalar ytry = tryMorphTet
|
|
||||||
(
|
|
||||||
surfacesToTest,
|
|
||||||
10*y[ihi], // search box.
|
|
||||||
p,
|
|
||||||
y,
|
|
||||||
pSum,
|
|
||||||
ihi,
|
|
||||||
-1.0
|
|
||||||
);
|
|
||||||
|
|
||||||
if (ytry <= y[ilo])
|
|
||||||
{
|
|
||||||
// If in right direction (y lower) expand by two.
|
|
||||||
ytry = tryMorphTet(surfacesToTest, 10*y[ihi], p, y, pSum, ihi, 2.0);
|
|
||||||
}
|
|
||||||
else if (ytry >= y[inhi])
|
|
||||||
{
|
|
||||||
// If inside tet try contraction.
|
|
||||||
|
|
||||||
scalar ysave = y[ihi];
|
|
||||||
|
|
||||||
ytry = tryMorphTet(surfacesToTest, 10*y[ihi], p, y, pSum, ihi, 0.5);
|
|
||||||
|
|
||||||
if (ytry >= ysave)
|
|
||||||
{
|
|
||||||
// Contract around lowest point.
|
|
||||||
forAll(p, i)
|
|
||||||
{
|
|
||||||
if (i != ilo)
|
|
||||||
{
|
|
||||||
p[i] = 0.5*(p[i] + p[ilo]);
|
|
||||||
y[i] = sumDistSqr(surfacesToTest, y[ihi], p[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pSum = sum(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
meshTools::writeOBJ(str(), p[0]);
|
|
||||||
vertI++;
|
|
||||||
str()<< "l " << vertI-1 << ' ' << vertI << nl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Failure to converge. Return best guess so far.
|
|
||||||
label ilo = findMin(y);
|
|
||||||
Swap(p[0], p[ilo]);
|
|
||||||
Swap(y[0], y[ilo]);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
// Construct from components
|
|
||||||
Foam::triSurfaceMeshes::triSurfaceMeshes
|
|
||||||
(
|
|
||||||
const IOobject& io,
|
|
||||||
const fileNameList& names
|
|
||||||
)
|
|
||||||
:
|
|
||||||
PtrList<triSurfaceMesh>(names.size()),
|
|
||||||
allSurfaces_(identity(names.size()))
|
|
||||||
{
|
|
||||||
forAll(names, i)
|
|
||||||
{
|
|
||||||
autoPtr<IOobject> surfaceIO = io.clone();
|
|
||||||
surfaceIO().rename(names[i]);
|
|
||||||
|
|
||||||
Info<< "Loading surface " << surfaceIO().name() << endl;
|
|
||||||
|
|
||||||
//fileName fullPath = surfaceIO().filePath();
|
|
||||||
//
|
|
||||||
//if (fullPath.size() == 0)
|
|
||||||
//{
|
|
||||||
// FatalErrorIn
|
|
||||||
// (
|
|
||||||
// "triSurfaceMeshes::triSurfaceMeshes"
|
|
||||||
// "(const IOobject&, const fileNameList&)"
|
|
||||||
// ) << "Cannot load surface " << surfaceIO().name()
|
|
||||||
// << " starting from path " << surfaceIO().path()
|
|
||||||
// << exit(FatalError);
|
|
||||||
//}
|
|
||||||
|
|
||||||
set(i, new triSurfaceMesh(surfaceIO()));
|
|
||||||
|
|
||||||
if (Pstream::master())
|
|
||||||
{
|
|
||||||
string oldPrefix(Pout.prefix());
|
|
||||||
Pout.prefix() += " ";
|
|
||||||
operator[](i).writeStats(Pout);
|
|
||||||
Pout.prefix() = oldPrefix;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
Foam::fileNameList Foam::triSurfaceMeshes::allNames(const IOobject& io)
|
|
||||||
{
|
|
||||||
return readDir(io.path(), fileName::FILE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Foam::fileNameList Foam::triSurfaceMeshes::names() const
|
|
||||||
{
|
|
||||||
fileNameList surfNames(size());
|
|
||||||
|
|
||||||
forAll(surfNames, surfI)
|
|
||||||
{
|
|
||||||
surfNames[surfI] = operator[](surfI).IOobject::name();
|
|
||||||
}
|
|
||||||
return surfNames;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Find any intersection
|
|
||||||
Foam::label Foam::triSurfaceMeshes::findAnyIntersection
|
|
||||||
(
|
|
||||||
const labelList& surfaces,
|
|
||||||
const point& start,
|
|
||||||
const point& end,
|
|
||||||
pointIndexHit& hitInfo
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
forAll(surfaces, i)
|
|
||||||
{
|
|
||||||
label surfI = surfaces[i];
|
|
||||||
|
|
||||||
hitInfo = operator[](surfI).findLineAny(start, end);
|
|
||||||
|
|
||||||
if (hitInfo.hit())
|
|
||||||
{
|
|
||||||
return surfI;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Foam::label Foam::triSurfaceMeshes::findAnyIntersection
|
|
||||||
(
|
|
||||||
const point& start,
|
|
||||||
const point& end,
|
|
||||||
pointIndexHit& hitInfo
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
return findAnyIntersection
|
|
||||||
(
|
|
||||||
allSurfaces_,
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
hitInfo
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Find intersections of edge nearest to both endpoints.
|
|
||||||
void Foam::triSurfaceMeshes::findAllIntersections
|
|
||||||
(
|
|
||||||
const labelList& surfaces,
|
|
||||||
const point& start,
|
|
||||||
const point& end,
|
|
||||||
|
|
||||||
labelList& surfacesIndex,
|
|
||||||
List<pointIndexHit>& surfaceHitInfo
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
DynamicList<label> hitSurfaces(surfaces.size());
|
|
||||||
DynamicList<pointIndexHit> hitInfos(surfaces.size());
|
|
||||||
DynamicList<scalar> hitDistSqr(surfaces.size());
|
|
||||||
|
|
||||||
const vector dirVec(end-start);
|
|
||||||
const scalar magSqrDirVec(magSqr(dirVec));
|
|
||||||
const vector smallVec(Foam::sqrt(SMALL)*dirVec);
|
|
||||||
|
|
||||||
forAll(surfaces, i)
|
|
||||||
{
|
|
||||||
label surfI = surfaces[i];
|
|
||||||
|
|
||||||
// Current starting point of ray.
|
|
||||||
point pt = start;
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
// See if any intersection between pt and end
|
|
||||||
pointIndexHit inter = operator[](surfI).findLine(pt, end);
|
|
||||||
|
|
||||||
if (!inter.hit())
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
hitSurfaces.append(surfI);
|
|
||||||
hitInfos.append(inter);
|
|
||||||
hitDistSqr.append(magSqr(inter.hitPoint() - start));
|
|
||||||
|
|
||||||
pt = inter.hitPoint() + smallVec;
|
|
||||||
|
|
||||||
if (((pt-start)&dirVec) > magSqrDirVec)
|
|
||||||
{
|
|
||||||
// Adding smallVec has taken us beyond end
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
surfacesIndex.setSize(hitSurfaces.size());
|
|
||||||
surfaceHitInfo.setSize(hitSurfaces.size());
|
|
||||||
|
|
||||||
if (hitSurfaces.size() > 0)
|
|
||||||
{
|
|
||||||
// Sort and transfer to arguments
|
|
||||||
|
|
||||||
hitSurfaces.shrink();
|
|
||||||
hitInfos.shrink();
|
|
||||||
hitDistSqr.shrink();
|
|
||||||
|
|
||||||
// Sort from start to end.
|
|
||||||
SortableList<scalar> sortedDist(hitDistSqr);
|
|
||||||
|
|
||||||
forAll(sortedDist.indices(), newPos)
|
|
||||||
{
|
|
||||||
label oldPos = sortedDist.indices()[newPos];
|
|
||||||
surfacesIndex[newPos] = hitSurfaces[oldPos];
|
|
||||||
surfaceHitInfo[newPos] = hitInfos[oldPos];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Foam::triSurfaceMeshes::findAllIntersections
|
|
||||||
(
|
|
||||||
const point& start,
|
|
||||||
const point& end,
|
|
||||||
|
|
||||||
labelList& surfacesIndex,
|
|
||||||
List<pointIndexHit>& surfaceHitInfo
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
findAllIntersections
|
|
||||||
(
|
|
||||||
allSurfaces_,
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
surfacesIndex,
|
|
||||||
surfaceHitInfo
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Find intersections of edge nearest to both endpoints.
|
|
||||||
void Foam::triSurfaceMeshes::findNearestIntersection
|
|
||||||
(
|
|
||||||
const labelList& surfaces,
|
|
||||||
const point& start,
|
|
||||||
const point& end,
|
|
||||||
|
|
||||||
label& surface1,
|
|
||||||
pointIndexHit& hit1,
|
|
||||||
label& surface2,
|
|
||||||
pointIndexHit& hit2
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
surface1 = -1;
|
|
||||||
// Initialize to endpoint
|
|
||||||
hit1 = pointIndexHit(false, end, -1);
|
|
||||||
|
|
||||||
forAll(surfaces, i)
|
|
||||||
{
|
|
||||||
label surfI = surfaces[i];
|
|
||||||
|
|
||||||
if (hit1.rawPoint() == start)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// See if any intersection between start and current nearest
|
|
||||||
pointIndexHit inter = operator[](surfI).findLine
|
|
||||||
(
|
|
||||||
start,
|
|
||||||
hit1.rawPoint()
|
|
||||||
);
|
|
||||||
|
|
||||||
if (inter.hit())
|
|
||||||
{
|
|
||||||
hit1 = inter;
|
|
||||||
surface1 = surfI;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Find the nearest intersection from end to start. Note that we initialize
|
|
||||||
// to the first intersection (if any).
|
|
||||||
surface2 = surface1;
|
|
||||||
hit2 = pointIndexHit(hit1);
|
|
||||||
|
|
||||||
if (hit1.hit())
|
|
||||||
{
|
|
||||||
// Test from the end side.
|
|
||||||
forAll(surfaces, i)
|
|
||||||
{
|
|
||||||
label surfI = surfaces[i];
|
|
||||||
|
|
||||||
if (hit2.rawPoint() == end)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// See if any intersection between end and current nearest
|
|
||||||
pointIndexHit inter = operator[](surfI).findLine
|
|
||||||
(
|
|
||||||
end,
|
|
||||||
hit2.rawPoint()
|
|
||||||
);
|
|
||||||
|
|
||||||
if (inter.hit())
|
|
||||||
{
|
|
||||||
hit2 = inter;
|
|
||||||
surface2 = surfI;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Foam::triSurfaceMeshes::findNearestIntersection
|
|
||||||
(
|
|
||||||
const point& start,
|
|
||||||
const point& end,
|
|
||||||
|
|
||||||
label& surface1,
|
|
||||||
pointIndexHit& hit1,
|
|
||||||
label& surface2,
|
|
||||||
pointIndexHit& hit2
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
findNearestIntersection
|
|
||||||
(
|
|
||||||
allSurfaces_,
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
surface1,
|
|
||||||
hit1,
|
|
||||||
surface2,
|
|
||||||
hit2
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Find nearest. Return -1 or nearest point
|
|
||||||
Foam::label Foam::triSurfaceMeshes::findNearest
|
|
||||||
(
|
|
||||||
const labelList& surfaces,
|
|
||||||
const point& pt,
|
|
||||||
const scalar nearestDistSqr,
|
|
||||||
pointIndexHit& nearestHit
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
// nearest surface
|
|
||||||
label minSurface = -1;
|
|
||||||
scalar minDistSqr = Foam::sqr(GREAT);
|
|
||||||
|
|
||||||
forAll(surfaces, i)
|
|
||||||
{
|
|
||||||
label surfI = surfaces[i];
|
|
||||||
|
|
||||||
pointIndexHit hit
|
|
||||||
(
|
|
||||||
operator[](surfI).findNearest(pt, nearestDistSqr)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (hit.hit())
|
|
||||||
{
|
|
||||||
scalar distSqr = magSqr(hit.hitPoint()-pt);
|
|
||||||
|
|
||||||
if (distSqr < minDistSqr)
|
|
||||||
{
|
|
||||||
minDistSqr = distSqr;
|
|
||||||
minSurface = surfI;
|
|
||||||
nearestHit = hit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (minSurface == -1)
|
|
||||||
{
|
|
||||||
// maxLevel unchanged. No interesting surface hit.
|
|
||||||
nearestHit.setMiss();
|
|
||||||
}
|
|
||||||
|
|
||||||
return minSurface;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Find nearest. Return -1 or nearest point
|
|
||||||
Foam::label Foam::triSurfaceMeshes::findNearest
|
|
||||||
(
|
|
||||||
const point& pt,
|
|
||||||
const scalar nearestDistSqr,
|
|
||||||
pointIndexHit& nearestHit
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
return findNearest
|
|
||||||
(
|
|
||||||
allSurfaces_,
|
|
||||||
pt,
|
|
||||||
nearestDistSqr,
|
|
||||||
nearestHit
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Foam::label Foam::triSurfaceMeshes::findNearestAndClassify
|
|
||||||
(
|
|
||||||
const labelList& surfacesToTest,
|
|
||||||
const point& pt,
|
|
||||||
const scalar nearestDistSqr,
|
|
||||||
surfaceLocation& nearest
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
pointIndexHit nearestInfo;
|
|
||||||
label surfI = findNearest
|
|
||||||
(
|
|
||||||
surfacesToTest,
|
|
||||||
pt,
|
|
||||||
nearestDistSqr,
|
|
||||||
nearestInfo
|
|
||||||
);
|
|
||||||
|
|
||||||
if (surfI != -1)
|
|
||||||
{
|
|
||||||
nearest = triSurfaceTools::classify
|
|
||||||
(
|
|
||||||
operator[](surfI),
|
|
||||||
nearestInfo.index(), // triangle
|
|
||||||
nearestInfo.rawPoint() // point on edge/inside triangle
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return surfI;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//- Calculate point which is on a set of surfaces.
|
|
||||||
Foam::surfaceLocation Foam::triSurfaceMeshes::facesIntersectionTrack
|
|
||||||
(
|
|
||||||
const labelList& surfacesToTest,
|
|
||||||
const scalar initialDistSqr,
|
|
||||||
const scalar convergenceDistSqr,
|
|
||||||
const point& start
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
autoPtr<OFstream> str;
|
|
||||||
label vertI = 0;
|
|
||||||
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
str.reset(new OFstream("track.obj"));
|
|
||||||
}
|
|
||||||
|
|
||||||
surfaceLocation current
|
|
||||||
(
|
|
||||||
pointIndexHit
|
|
||||||
(
|
|
||||||
false,
|
|
||||||
start,
|
|
||||||
-1
|
|
||||||
),
|
|
||||||
triPointRef::NONE,
|
|
||||||
-1
|
|
||||||
);
|
|
||||||
|
|
||||||
// Dump start point
|
|
||||||
if (str.valid())
|
|
||||||
{
|
|
||||||
Pout<< "Starting at " << current.info()
|
|
||||||
<< " written as point " << vertI
|
|
||||||
<< endl;
|
|
||||||
meshTools::writeOBJ(str(), current.rawPoint());
|
|
||||||
vertI++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now slide current along all faces until it settles
|
|
||||||
label iter = 0;
|
|
||||||
|
|
||||||
const label maxIter = 10;
|
|
||||||
|
|
||||||
for (; iter < maxIter; iter++)
|
|
||||||
{
|
|
||||||
// - store old position
|
|
||||||
// - slide it along all faces
|
|
||||||
// - if it hasn't changed position exit loop
|
|
||||||
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
Pout<< endl
|
|
||||||
<< "Iteration " << iter << endl
|
|
||||||
<< "-----------" << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
point oldCurrent = current.rawPoint();
|
|
||||||
|
|
||||||
forAll(surfacesToTest, i)
|
|
||||||
{
|
|
||||||
label surfI = surfacesToTest[i];
|
|
||||||
|
|
||||||
// Project pt onto surf
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~
|
|
||||||
point copy(current.rawPoint()); // need to work on copy
|
|
||||||
if
|
|
||||||
(
|
|
||||||
findNearestAndClassify
|
|
||||||
(
|
|
||||||
labelList(1, surfI),
|
|
||||||
copy,
|
|
||||||
initialDistSqr, // initialDistSqr
|
|
||||||
current
|
|
||||||
)
|
|
||||||
== -1
|
|
||||||
)
|
|
||||||
{
|
|
||||||
FatalErrorIn("triSurfaceMeshes::facesIntersectionTrack(..)")
|
|
||||||
<< "Did not find a point on surface " << surfI
|
|
||||||
<< " which is within sqrt(" << initialDistSqr
|
|
||||||
<< ") of " << copy
|
|
||||||
<< abort(FatalError);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
Pout<< "Nearest onto surface " << surfI
|
|
||||||
<< ' ' << operator[](surfI).IOobject::name() << " : "
|
|
||||||
<< current.info() << " written as point " << vertI
|
|
||||||
<< endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dump current
|
|
||||||
if (str.valid())
|
|
||||||
{
|
|
||||||
meshTools::writeOBJ(str(), current.rawPoint());
|
|
||||||
vertI++;
|
|
||||||
str()<< "l " << vertI-1 << ' ' << vertI << nl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find corresponding point on next surface
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
label nextSurfI = surfacesToTest[surfacesToTest.fcIndex(i)];
|
|
||||||
|
|
||||||
surfaceLocation next;
|
|
||||||
findNearestAndClassify
|
|
||||||
(
|
|
||||||
labelList(1, nextSurfI),
|
|
||||||
point(current.rawPoint()),
|
|
||||||
initialDistSqr, // initialDistSqr
|
|
||||||
next
|
|
||||||
);
|
|
||||||
|
|
||||||
// Since next is on a different surface we cannot compare
|
|
||||||
// indices (like in snapToEnd) so make sure this does not
|
|
||||||
// happen.
|
|
||||||
next.elementType() = triPointRef::NONE;
|
|
||||||
next.setIndex(-123);
|
|
||||||
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
Pout<< "Nearest onto next surface " << nextSurfI
|
|
||||||
<< ' ' << operator[](nextSurfI).IOobject::name() << " : "
|
|
||||||
<< next.info() << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if
|
|
||||||
(
|
|
||||||
magSqr(current.rawPoint() - next.rawPoint())
|
|
||||||
> convergenceDistSqr
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// Track from current to next
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
//vector n = current.normal(surfaces[surfI]);
|
|
||||||
|
|
||||||
current = triSurfaceTools::trackToEdge
|
|
||||||
(
|
|
||||||
operator[](surfI),
|
|
||||||
current,
|
|
||||||
next,
|
|
||||||
plane(start, current.rawPoint(), next.rawPoint())
|
|
||||||
);
|
|
||||||
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
Pout<< "Sliding along surface "
|
|
||||||
<< surfI << ' ' << operator[](surfI).IOobject::name()
|
|
||||||
<< " in direction of "
|
|
||||||
<< nextSurfI << ' '
|
|
||||||
<< operator[](nextSurfI).IOobject::name()
|
|
||||||
<< " stopped at " << current.info()
|
|
||||||
<< " written as point " << vertI << endl;
|
|
||||||
}
|
|
||||||
if (str.valid())
|
|
||||||
{
|
|
||||||
meshTools::writeOBJ(str(), current.rawPoint());
|
|
||||||
vertI++;
|
|
||||||
str()<< "l " << vertI-1 << ' ' << vertI << nl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
scalar distSqr = magSqr(oldCurrent - current.rawPoint());
|
|
||||||
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
Pout<< "distSqr:" << distSqr
|
|
||||||
<< " convergenceDistSqr:" << convergenceDistSqr << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (distSqr < convergenceDistSqr)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iter == maxIter)
|
|
||||||
{
|
|
||||||
FatalErrorIn("triSurfaceMeshes::facesIntersectionTrack(..)")
|
|
||||||
<< "Did not converge in " << iter
|
|
||||||
<< " iterations to find a point which is on surfaces "
|
|
||||||
<< IndirectList<fileName>(names(), surfacesToTest)() << nl
|
|
||||||
<< "Start point:" << start << nl
|
|
||||||
<< "Current nearest:" << current.info() << nl
|
|
||||||
<< "Please check that your surfaces actually intersect and"
|
|
||||||
<< " that the starting point is close to the intersection point."
|
|
||||||
<< abort(FatalError);
|
|
||||||
}
|
|
||||||
|
|
||||||
return current;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//- Calculate point which is on a set of surfaces.
|
|
||||||
Foam::pointIndexHit Foam::triSurfaceMeshes::facesIntersection
|
|
||||||
(
|
|
||||||
const labelList& surfacesToTest,
|
|
||||||
const scalar initDistSqr,
|
|
||||||
const scalar convergenceDistSqr,
|
|
||||||
const point& start
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
// Get four starting points. Take these as the projection of the
|
|
||||||
// starting point onto the surfaces and the mid point
|
|
||||||
List<point> nearest(surfacesToTest.size()+1);
|
|
||||||
|
|
||||||
point sumNearest = vector::zero;
|
|
||||||
|
|
||||||
forAll(surfacesToTest, i)
|
|
||||||
{
|
|
||||||
label surfI = surfacesToTest[i];
|
|
||||||
|
|
||||||
pointIndexHit hit
|
|
||||||
(
|
|
||||||
operator[](surfI).findNearest(start, initDistSqr)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (hit.hit())
|
|
||||||
{
|
|
||||||
nearest[i] = hit.hitPoint();
|
|
||||||
sumNearest += nearest[i];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FatalErrorIn
|
|
||||||
(
|
|
||||||
"triSurfaceMeshes::facesIntersection"
|
|
||||||
"(const labelList&, const scalar, const scalar, const point&)"
|
|
||||||
) << "Did not find point within distance "
|
|
||||||
<< initDistSqr << " of starting point " << start
|
|
||||||
<< " on surface " << operator[](surfI).IOobject::name()
|
|
||||||
<< abort(FatalError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nearest[nearest.size()-1] = sumNearest / surfacesToTest.size();
|
|
||||||
|
|
||||||
|
|
||||||
// Get the sum of distances (initial evaluation)
|
|
||||||
List<scalar> nearestDist(nearest.size());
|
|
||||||
|
|
||||||
forAll(nearestDist, i)
|
|
||||||
{
|
|
||||||
nearestDist[i] = sumDistSqr(surfacesToTest, initDistSqr, nearest[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//- Downhill Simplex method
|
|
||||||
|
|
||||||
bool converged = morphTet
|
|
||||||
(
|
|
||||||
surfacesToTest,
|
|
||||||
initDistSqr,
|
|
||||||
convergenceDistSqr,
|
|
||||||
2000,
|
|
||||||
nearest,
|
|
||||||
nearestDist
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
pointIndexHit intersection;
|
|
||||||
|
|
||||||
if (converged)
|
|
||||||
{
|
|
||||||
// Project nearest onto 0th surface.
|
|
||||||
intersection = operator[](surfacesToTest[0]).findNearest
|
|
||||||
(
|
|
||||||
nearest[0],
|
|
||||||
nearestDist[0]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
//if (!intersection.hit())
|
|
||||||
//{
|
|
||||||
// // Restart
|
|
||||||
// scalar smallDist = Foam::sqr(convergenceDistSqr);
|
|
||||||
// nearest[0] = intersection.hitPoint();
|
|
||||||
// nearest[1] = nearest[0];
|
|
||||||
// nearest[1].x() += smallDist;
|
|
||||||
// nearest[2] = nearest[0];
|
|
||||||
// nearest[2].y() += smallDist;
|
|
||||||
// nearest[3] = nearest[0];
|
|
||||||
// nearest[3].z() += smallDist;
|
|
||||||
//
|
|
||||||
// forAll(nearestDist, i)
|
|
||||||
// {
|
|
||||||
// nearestDist[i] = sumDistSqr
|
|
||||||
// (
|
|
||||||
// surfacesToTest,
|
|
||||||
// initDistSqr,
|
|
||||||
// nearest[i]
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// intersection = morphTet
|
|
||||||
// (
|
|
||||||
// surfacesToTest,
|
|
||||||
// initDistSqr,
|
|
||||||
// convergenceDistSqr,
|
|
||||||
// 1000,
|
|
||||||
// nearest,
|
|
||||||
// nearestDist
|
|
||||||
// );
|
|
||||||
//}
|
|
||||||
|
|
||||||
return intersection;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -1,261 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | Copyright (C) 1991-2008 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 2 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, write to the Free Software Foundation,
|
|
||||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
Class
|
|
||||||
Foam::triSurfaceMeshes
|
|
||||||
|
|
||||||
Description
|
|
||||||
Container for triSurfaces read from files.
|
|
||||||
|
|
||||||
SourceFiles
|
|
||||||
triSurfaceMeshes.C
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#ifndef triSurfaceMeshes_H
|
|
||||||
#define triSurfaceMeshes_H
|
|
||||||
|
|
||||||
#include "triSurfaceMesh.H"
|
|
||||||
#include "fileNameList.H"
|
|
||||||
#include "treeDataTriSurface.H"
|
|
||||||
#include "indexedOctree.H"
|
|
||||||
#include "surfaceLocation.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
namespace Foam
|
|
||||||
{
|
|
||||||
|
|
||||||
// Forward declaration of classes
|
|
||||||
class plane;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
Class triSurfaceMeshes Declaration
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
class triSurfaceMeshes
|
|
||||||
:
|
|
||||||
public PtrList<triSurfaceMesh>
|
|
||||||
{
|
|
||||||
// Private data
|
|
||||||
|
|
||||||
//- Indices of all surfaces. Precalculated and stored.
|
|
||||||
const labelList allSurfaces_;
|
|
||||||
|
|
||||||
|
|
||||||
// Private Member Functions
|
|
||||||
|
|
||||||
//- Calculate sum of distances to nearest point on surfaces. Is used
|
|
||||||
// in minimisation to find intersection. Returns sum of (square of)
|
|
||||||
// distances to the surfaces.
|
|
||||||
scalar sumDistSqr
|
|
||||||
(
|
|
||||||
const labelList& surfacesToTest,
|
|
||||||
const scalar initialDistSqr, // search box
|
|
||||||
const point& pt
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Takes the tet (points p) and reflects the point with the
|
|
||||||
// highest value around the centre (pSum). Checks if it gets closer
|
|
||||||
// and updates p, y if so.
|
|
||||||
scalar tryMorphTet
|
|
||||||
(
|
|
||||||
const labelList& surfacesToTest,
|
|
||||||
const scalar initialDistSqr,
|
|
||||||
List<vector>& p,
|
|
||||||
List<scalar>& y,
|
|
||||||
vector& pSum,
|
|
||||||
const label ihi,
|
|
||||||
const scalar fac
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Downhill simplex method: find the point with min cumulative
|
|
||||||
// distance to all surfaces. Does so by morphing a tet (points p).
|
|
||||||
// Returns the point on the 0th surface or hit if not reached within
|
|
||||||
// maxIters iterations.
|
|
||||||
bool morphTet
|
|
||||||
(
|
|
||||||
const labelList& surfacesToTest,
|
|
||||||
const scalar initialDistSqr,
|
|
||||||
const scalar convergenceDistSqr,
|
|
||||||
const label maxIter,
|
|
||||||
List<vector>& p,
|
|
||||||
List<scalar>& y
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Disallow default bitwise copy construct
|
|
||||||
triSurfaceMeshes(const triSurfaceMeshes&);
|
|
||||||
|
|
||||||
//- Disallow default bitwise assignment
|
|
||||||
void operator=(const triSurfaceMeshes&);
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
ClassName("triSurfaceMeshes");
|
|
||||||
|
|
||||||
// Constructors
|
|
||||||
|
|
||||||
//- Construct from directory (io.instance()) and list of local filenames
|
|
||||||
triSurfaceMeshes(const IOobject& io, const fileNameList&);
|
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
|
||||||
|
|
||||||
//- Get all surfaces in directory
|
|
||||||
static fileNameList allNames(const IOobject&);
|
|
||||||
|
|
||||||
//- Get names of surfaces
|
|
||||||
fileNameList names() const;
|
|
||||||
|
|
||||||
|
|
||||||
//- Find any intersection. Return hit point information and surface
|
|
||||||
// number
|
|
||||||
label findAnyIntersection
|
|
||||||
(
|
|
||||||
const labelList& surfacesToTest,
|
|
||||||
const point& start,
|
|
||||||
const point& end,
|
|
||||||
pointIndexHit&
|
|
||||||
) const;
|
|
||||||
|
|
||||||
label findAnyIntersection
|
|
||||||
(
|
|
||||||
const point& start,
|
|
||||||
const point& end,
|
|
||||||
pointIndexHit&
|
|
||||||
) const;
|
|
||||||
|
|
||||||
|
|
||||||
//- Find all intersections in order from start to end. Returns for
|
|
||||||
// every hit the surface and the hit info.
|
|
||||||
void findAllIntersections
|
|
||||||
(
|
|
||||||
const labelList& surfacesToTest,
|
|
||||||
const point& start,
|
|
||||||
const point& end,
|
|
||||||
labelList& surfaces,
|
|
||||||
List<pointIndexHit>& surfaceHits
|
|
||||||
) const;
|
|
||||||
|
|
||||||
void findAllIntersections
|
|
||||||
(
|
|
||||||
const point& start,
|
|
||||||
const point& end,
|
|
||||||
labelList& surfaces,
|
|
||||||
List<pointIndexHit>& surfaceHits
|
|
||||||
) const;
|
|
||||||
|
|
||||||
|
|
||||||
//- Find intersections of edge nearest to both endpoints.
|
|
||||||
void findNearestIntersection
|
|
||||||
(
|
|
||||||
const labelList& surfacesToTest,
|
|
||||||
const point& start,
|
|
||||||
const point& end,
|
|
||||||
|
|
||||||
label& surface1, // surface index
|
|
||||||
pointIndexHit& hit1, // hit point information
|
|
||||||
label& surface2,
|
|
||||||
pointIndexHit& hit2
|
|
||||||
) const;
|
|
||||||
|
|
||||||
void findNearestIntersection
|
|
||||||
(
|
|
||||||
const point& start,
|
|
||||||
const point& end,
|
|
||||||
|
|
||||||
label& surface1, // surface index
|
|
||||||
pointIndexHit& hit1, // hit point information
|
|
||||||
label& surface2,
|
|
||||||
pointIndexHit& hit2
|
|
||||||
) const;
|
|
||||||
|
|
||||||
|
|
||||||
//- Find nearest. Return -1 (and a miss()) or surface and nearest point.
|
|
||||||
label findNearest
|
|
||||||
(
|
|
||||||
const labelList& surfacesToTest,
|
|
||||||
const point&,
|
|
||||||
const scalar nearestDistSqr,
|
|
||||||
pointIndexHit&
|
|
||||||
) const;
|
|
||||||
|
|
||||||
label findNearest
|
|
||||||
(
|
|
||||||
const point&,
|
|
||||||
const scalar nearestDistSqr,
|
|
||||||
pointIndexHit&
|
|
||||||
) const;
|
|
||||||
|
|
||||||
|
|
||||||
//- Find nearest point (like findNearest) but also return whether
|
|
||||||
// point is on edge or on point. Returns -1 if not found
|
|
||||||
// (within nearestDistSqr) on any of the surfaces.
|
|
||||||
// Returns surfaceLocation
|
|
||||||
// - hit : nearest point is inside triangle
|
|
||||||
// - elementType : none, edge or point
|
|
||||||
// - index : triI, edgeI or localPointI
|
|
||||||
label findNearestAndClassify
|
|
||||||
(
|
|
||||||
const labelList& surfacesToTest,
|
|
||||||
const point& pt,
|
|
||||||
const scalar nearestDistSqr,
|
|
||||||
surfaceLocation& nearest
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Calculate point which is on a set of surfaces. Takes
|
|
||||||
// - initialDistSqr : search dimensions to find point on surface
|
|
||||||
// - convergenceDistSqr : when point is converged
|
|
||||||
// Will bomb out if no stable point reached after certain number
|
|
||||||
// of iterations.
|
|
||||||
surfaceLocation facesIntersectionTrack
|
|
||||||
(
|
|
||||||
const labelList& surfacesToTest,
|
|
||||||
const scalar initialDistSqr,
|
|
||||||
const scalar convergenceDistSqr,
|
|
||||||
const point& start
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Calculate point which is on a set of surfaces.
|
|
||||||
pointIndexHit facesIntersection
|
|
||||||
(
|
|
||||||
const labelList& surfacesToTest,
|
|
||||||
const scalar initialDistSqr,
|
|
||||||
const scalar convergenceDistSqr,
|
|
||||||
const point& start
|
|
||||||
) const;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
} // End namespace Foam
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
Reference in New Issue
Block a user