Merge branch 'master' of ssh://noisy/home/noisy2/OpenFOAM/OpenFOAM-dev

This commit is contained in:
andy
2008-07-09 09:30:17 +01:00
65 changed files with 11211 additions and 7076 deletions

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd.
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -33,12 +33,86 @@ Description
#include "argList.H"
#include "Time.H"
#include "fvMesh.H"
#include "autoHexMeshDriver.H"
#include "autoRefineDriver.H"
#include "autoSnapDriver.H"
#include "autoLayerDriver.H"
#include "searchableSurfaces.H"
#include "refinementSurfaces.H"
#include "shellSurfaces.H"
#include "decompositionMethod.H"
#include "fvMeshDistribute.H"
#include "wallPolyPatch.H"
#include "refinementParameters.H"
#include "snapParameters.H"
#include "layerParameters.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Check writing tolerance before doing any serious work
scalar getMergeDistance(const polyMesh& mesh, const scalar mergeTol)
{
const boundBox& meshBb = mesh.bounds();
scalar mergeDist = mergeTol*mag(meshBb.max() - meshBb.min());
scalar writeTol = std::pow
(
scalar(10.0),
-scalar(IOstream::defaultPrecision())
);
Info<< nl
<< "Overall mesh bounding box : " << meshBb << nl
<< "Relative tolerance : " << mergeTol << nl
<< "Absolute matching distance : " << mergeDist << nl
<< endl;
if (mesh.time().writeFormat() == IOstream::ASCII && mergeTol < writeTol)
{
FatalErrorIn("getMergeDistance(const polyMesh&, const scalar)")
<< "Your current settings specify ASCII writing with "
<< IOstream::defaultPrecision() << " digits precision." << endl
<< "Your merging tolerance (" << mergeTol << ") is finer than this."
<< endl
<< "Please change your writeFormat to binary"
<< " or increase the writePrecision" << endl
<< "or adjust the merge tolerance (-mergeTol)."
<< exit(FatalError);
}
return mergeDist;
}
// Write mesh and additional information
void writeMesh
(
const string& msg,
const meshRefinement& meshRefiner,
const label debug
)
{
const fvMesh& mesh = meshRefiner.mesh();
meshRefiner.printMeshInfo(debug, msg);
Info<< "Writing mesh to time " << mesh.time().timeName() << endl;
meshRefiner.write(meshRefinement::MESH|meshRefinement::SCALARLEVELS, "");
if (debug & meshRefinement::OBJINTERSECTIONS)
{
meshRefiner.write
(
meshRefinement::OBJINTERSECTIONS,
mesh.time().path()/mesh.time().timeName()
);
}
Info<< "Written mesh in = "
<< mesh.time().cpuTimeIncrement() << " s." << endl;
}
int main(int argc, char *argv[])
{
# include "setRootCase.H"
@ -49,6 +123,11 @@ int main(int argc, char *argv[])
Info<< "Read mesh in = "
<< runTime.cpuTimeIncrement() << " s" << endl;
// Check patches and faceZones are synchronised
mesh.boundaryMesh().checkParallelSync(true);
meshRefinement::checkCoupledFaceZones(mesh);
// Read decomposePar dictionary
IOdictionary decomposeDict
(
@ -75,47 +154,282 @@ int main(int argc, char *argv[])
)
);
// refinement parameters
const dictionary& refineDict = meshDict.subDict("refineDict");
// all surface geometry
const dictionary& geometryDict = meshDict.subDict("geometry");
// snap-to-surface parameters
const dictionary& snapDict = meshDict.subDict("snapDict");
// refinement parameters
const dictionary& refineDict = meshDict.subDict("castellatedMeshControls");
// mesh motion and mesh quality parameters
const dictionary& motionDict = meshDict.subDict("motionDict");
const dictionary& motionDict = meshDict.subDict("meshQualityControls");
// snap-to-surface parameters
const dictionary& snapDict = meshDict.subDict("snapControls");
// layer addition parameters
const dictionary& layerDict = meshDict.subDict("layerDict");
const dictionary& layerDict = meshDict.subDict("addLayersControls");
// Main meshing driver. Read surfaces. Determine initial intersections.
autoHexMeshDriver meshEngine
// Debug
// ~~~~~
const label debug(readLabel(meshDict.lookup("debug")));
if (debug > 0)
{
meshRefinement::debug = debug;
autoRefineDriver::debug = debug;
autoSnapDriver::debug = debug;
autoLayerDriver::debug = debug;
}
// Read geometry
// ~~~~~~~~~~~~~
searchableSurfaces allGeometry
(
mesh,
meshDict, // global control parameters
refineDict, // refinement parameters
decomposeDict
IOobject
(
"abc", // dummy name
mesh.time().constant(), // directory
"triSurface", // instance
mesh.time(), // registry
IOobject::MUST_READ,
IOobject::NO_WRITE
),
geometryDict
);
Switch wantRefine(meshDict.lookup("doRefine"));
Switch wantSnap(meshDict.lookup("doSnap"));
Switch wantLayers(meshDict.lookup("doLayers"));
// Read refinement surfaces
// ~~~~~~~~~~~~~~~~~~~~~~~~
Info<< "Reading refinement surfaces." << endl;
refinementSurfaces surfaces
(
allGeometry,
refineDict.subDict("refinementSurfaces")
);
Info<< "Read refinement surfaces in = "
<< mesh.time().cpuTimeIncrement() << " s" << nl << endl;
// Read refinement shells
// ~~~~~~~~~~~~~~~~~~~~~~
Info<< "Reading refinement shells." << endl;
shellSurfaces shells
(
allGeometry,
refineDict.subDict("refinementRegions")
);
Info<< "Read refinement shells in = "
<< mesh.time().cpuTimeIncrement() << " s" << nl << endl;
Info<< "Setting refinement level of surface to be consistent"
<< " with shells." << endl;
surfaces.setMinLevelFields(shells);
Info<< "Checked shell refinement in = "
<< mesh.time().cpuTimeIncrement() << " s" << nl << endl;
// Add all the surface regions as patches
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
labelList globalToPatch;
{
Info<< nl
<< "Adding patches for surface regions" << nl
<< "----------------------------------" << nl
<< endl;
// From global region number to mesh patch.
globalToPatch.setSize(surfaces.nRegions(), -1);
Info<< "Patch\tRegion" << nl
<< "-----\t------"
<< endl;
const labelList& surfaceGeometry = surfaces.surfaces();
forAll(surfaceGeometry, surfI)
{
label geomI = surfaceGeometry[surfI];
const wordList& regNames = allGeometry.regionNames()[geomI];
Info<< surfaces.names()[surfI] << ':' << nl << nl;
forAll(regNames, i)
{
label patchI = meshRefinement::addPatch
(
mesh,
regNames[i],
wallPolyPatch::typeName
);
Info<< patchI << '\t' << regNames[i] << nl;
globalToPatch[surfaces.globalRegion(surfI, i)] = patchI;
}
Info<< nl;
}
Info<< "Added patches in = "
<< mesh.time().cpuTimeIncrement() << " s" << nl << endl;
}
// Parallel
// ~~~~~~~~
// Decomposition
autoPtr<decompositionMethod> decomposerPtr
(
decompositionMethod::New
(
decomposeDict,
mesh
)
);
decompositionMethod& decomposer = decomposerPtr();
if (Pstream::parRun() && !decomposer.parallelAware())
{
FatalErrorIn(args.executable())
<< "You have selected decomposition method "
<< decomposer.typeName
<< " which is not parallel aware." << endl
<< "Please select one that is (hierarchical, parMetis)"
<< exit(FatalError);
}
const scalar mergeDist = getMergeDistance
(
mesh,
readScalar(meshDict.lookup("mergeTolerance"))
);
// Mesh distribution engine (uses tolerance to reconstruct meshes)
fvMeshDistribute distributor(mesh, mergeDist);
// Refinement engine
// ~~~~~~~~~~~~~~~~~
Info<< nl
<< "Determining initial surface intersections" << nl
<< "-----------------------------------------" << nl
<< endl;
// Main refinement engine
meshRefinement meshRefiner
(
mesh,
mergeDist, // tolerance used in sorting coordinates
surfaces, // for surface intersection refinement
shells // for volume (inside/outside) refinement
);
Info<< "Calculated surface intersections in = "
<< mesh.time().cpuTimeIncrement() << " s" << nl << endl;
// Some stats
meshRefiner.printMeshInfo(debug, "Initial mesh");
meshRefiner.write
(
debug&meshRefinement::OBJINTERSECTIONS,
mesh.time().path()/mesh.time().timeName()
);
// Now do the real work -refinement -snapping -layers
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Switch wantRefine(meshDict.lookup("castellatedMesh"));
Switch wantSnap(meshDict.lookup("snap"));
Switch wantLayers(meshDict.lookup("addLayers"));
if (wantRefine)
{
meshEngine.doRefine(refineDict, wantSnap);
autoRefineDriver refineDriver
(
meshRefiner,
decomposer,
distributor,
globalToPatch
);
// Refinement parameters
refinementParameters refineParams(refineDict);
refineDriver.doRefine(refineDict, refineParams, wantSnap);
writeMesh
(
"Refined mesh",
meshRefiner,
debug
);
}
if (wantSnap)
{
meshEngine.doSnap(snapDict, motionDict);
autoSnapDriver snapDriver
(
meshRefiner,
globalToPatch
);
// Snap parameters
snapParameters snapParams(snapDict);
snapDriver.doSnap(snapDict, motionDict, snapParams);
writeMesh
(
"Snapped mesh",
meshRefiner,
debug
);
}
if (wantLayers)
{
meshEngine.doLayers(layerDict, motionDict);
autoLayerDriver layerDriver
(
meshRefiner,
globalToPatch
);
// Layer addition parameters
layerParameters layerParams(layerDict, mesh.boundaryMesh());
layerDriver.doLayers
(
layerDict,
motionDict,
layerParams,
decomposer,
distributor
);
writeMesh
(
"Layer mesh",
meshRefiner,
debug
);
}
Info<< "Finished meshing in = "
<< runTime.elapsedCpuTime() << " s." << endl;

View File

@ -22,70 +22,88 @@ FoamFile
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Which phases to run.
doRefine true;
doSnap true;
doLayers true; // includes autoMergeFaces
// Which of the steps to run
castellatedMesh true;
snap true;
addLayers false;
// Whether to dump intermediate meshes and print lots
// 1 : write mesh
// 2 : write volScalarField with cellLevel for postprocessing
// 4 : write current intersections as .obj files
debug 0;
refineDict
// Geometry. Definition of all surfaces. All surfaces are of class
// searchableSurface.
// Surfaces are used
// - to specify refinement for any mesh cell intersecting it
// - to specify refinement for any mesh cell inside/outside/near
// - to 'snap' the mesh boundary to the surface
geometry
{
// Which part to keep.
// NOTE: This point should never be on a face, always inside a cell, even
// after refinement.
keepPoints ((3 0.28 0.43));
box1x1x1
{
type searchableBox;
min (1.5 1 -0.5);
max (3.5 2 0.5);
}
// Whether to remove/split cells likely to give problems when snapping
handleSnapProblems on;
sphere.stl
{
type triSurfaceMesh;
// Merge tolerance. Is fraction of overall bounding box of initial mesh
mergeTolerance 1E-6;
// Per region the patchname. If not provided will be <name>_<region>.
regions
{
secondSolid
{
name mySecondPatch;
}
}
}
sphere2
{
type searchableSphere;
centre (1.5 1.5 1.5);
radius 1.03;
}
};
// Settings for the castellatedMesh generation.
castellatedMeshControls
{
// Refinement parameters
// ~~~~~~~~~~~~~~~~~~~~~
// While refining maximum number of cells per processor. This is basically
// the number of cells that fit on a processor. If you choose this too small
// it will do just more refinement iterations to obtain a similar mesh.
procCellLimit 1000000;
maxLocalCells 1000000;
// Overall cell limit (approximately). Refinement will stop immediately
// upon reaching this number so a refinement level might not complete.
// Note that this is the number of cells before removing the part which
// is not 'visible' from the keepPoint. The final number of cells might actually
// be a lot less.
cellLimit 2000000;
// is not 'visible' from the keepPoint. The final number of cells might
// actually be a lot less.
maxGlobalCells 2000000;
// The surface refinement loop might spend lots of iterations refining just a
// few cells. This setting will cause refinement to stop if <= minimumRefine
// are selected for refinement. Note: it will at least do one iteration
// (unless the number of cells to refine is 0)
minimumRefine 0;
minRefinementCells 0;
// Number of buffer layers between different levels.
// 1 means normal 2:1 refinement restriction, larger means slower
// refinement.
nBufferLayers 1;
nCellsBetweenLevels 1;
// Feature Edge Refinement
// ~~~~~~~~~~~~~~~~~~~~~~~
// External feature file. Read from constant/triSurface for now.
// Limitations:
// - either start or edge of any feature line has to be inside domain
// and be visible from keepPoint on starting mesh.
// - refining cells containing features is separate phase before refining
// based on surface.
// - no load balancing, no check for cellLimit is done while doing this.
// Explicit feature edge refinement
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Specifies a level for any cell intersected by its edges.
// This is a featureEdgeMesh, read from constant/triSurface for now.
features
(
//{
@ -95,88 +113,80 @@ refineDict
);
// Internal Mesh Refinement
// ~~~~~~~~~~~~~~~~~~~~~~~~
// Specifies the areas where the refinement has to be a certain level.
// These surfaces have to be closed. Refinement is either inside
// (refineInside = true) or outside. (note:insideness or outsideness
// is with respect to far away)
// Note:that even using these the transition can never be faster than
// nBufferLayers!
// Note:the refinement level can never be higher than any of the surfaces
// they overlap with. See below for the surface refinement level specification.
refinementShells
(
{
//type triSurfaceMesh;
//name cube1x1x1.stl;
type searchableBox;
name box1x1x1;
min (2.5 -0.5 -0.5);
max (3.5 0.5 0.5);
level 4;
refineInside true;
}
);
// Surface based refinement
// ~~~~~~~~~~~~~~~~~~~~~~~~
// Curvature. Cosine of angle between two neighbouring surface intersections.
// Only used if cell level > minLevel and < maxLevel.
curvature 0.5;
// Specifies two levels for every surface. The first is the minimum level,
// every cell intersecting a surface gets refined up to the minimum level.
// The second level is the maximum level. Cells that 'see' multiple
// intersections where the intersections make an
// angle > resolveFeatureAngle get refined up to the maximum level.
// Overall the refinement is according to the following rules:
// - if the cell-cell vector intersects a surface any cell that
// is less refined than the minRefinementLevel of the surface gets refined.
// - else if the refinement level of the cell is between the
// minRefinementLevel and maxRefinementLevel the cell gets refined if
// - the normal of neighbouring surface intersections differ by more
// than above curvature
// - or if neighbouring surface intersections are on different surfaces or
// different surface regions.
// surfaces
surfaces
(
refinementSurfaces
{
name sphere;
file "sphere.stl";
sphere.stl
{
// Surface-wise min and max refinement level
level (2 2);
// Surface wide refinement level
minRefinementLevel 1;
maxRefinementLevel 1;
// Layers
surfaceLayers 1;
// Region specific refinement level
// Optional region-wise level specification
regions
(
{
name firstSolid;
minRefinementLevel 3;
maxRefinementLevel 3;
surfaceLayers 2;
}
secondSolid
{
name secondSolid;
minRefinementLevel 1;
maxRefinementLevel 1;
surfaceLayers 1;
level (3 3);
}
}
);
}
);
}
// For snapping
snapDict
resolveFeatureAngle 30;
// Region-wise refinement
// ~~~~~~~~~~~~~~~~~~~~~~
// Specifies refinement level for cells in relation to a surface. One of
// three modes
// - distance. 'levels' specifies per distance to the surface the
// wanted refinement level. The distances need to be specified in
// descending order.
// - inside. 'levels' is only one entry and only the level is used. All
// cells inside the surface get refined up to the level. The surface
// needs to be closed for this to be possible.
// - outside. Same but cells outside.
refinementRegions
{
box1x1x1
{
mode inside;
levels ((1.0 4));
}
//sphere.stl
//{
// mode distance;
// levels ((1.0 5) (2.0 3));
//}
}
// Mesh selection
// ~~~~~~~~~~~~~~
// After refinement patches get added for all refinementSurfaces and
// all cells intersecting the surfaces get put into these patches. The
// section reachable from the locationInMesh is kept.
// NOTE: This point should never be on a face, always inside a cell, even
// after refinement.
locationInMesh (5 0.28 0.43);
}
// Settings for the snapping.
snapControls
{
//- Number of patch smoothing iterations before finding correspondence
// to surface
@ -185,47 +195,64 @@ snapDict
//- Relative distance for points to be attracted by surface feature point
// or edge. True distance is this factor times local
// maximum edge length.
snapTol 4.0;
tolerance 4.0;
//- Whether to move internal mesh as well as boundary
smoothMesh true;
//- Number of mesh displacement smoothing iterations.
nSmoothDispl 30;
//- Number of mesh displacement relaxation iterations.
nSolveIter 30;
//- Maximum number of snapping relaxation iterations. Should stop
// before upon reaching a correct mesh.
nSnap 5;
nRelaxIter 5;
}
// For cell layers
layerDict
// Settings for the layer addition.
addLayersControls
{
// Per final patch (so not geometry!) the layer information
layers
{
sphere.stl_firstSolid
{
nSurfaceLayers 1;
}
maxY
{
nSurfaceLayers 1;
}
}
// Expansion factor for layer mesh
expansionRatio 1.0;
//- Wanted thickness of final added cell layer. If multiple layers
// is the
// thickness of the layer furthest away from the wall.
// Relative to undistorted size of cell outside layer.
finalLayerRatio 0.3;
//- 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.
minThickness 0.25;
//- If points get not extruded do nGrow layers of connected faces that are
// also not grown. This helps convergence of the layer addition process
// close to features.
nGrow 1;
// Advanced settings
//- When not to extrude surface. 0 is flat surface, 90 is when two faces
// make straight angle.
featureAngle 60;
//- Maximum number of snapping relaxation iterations. Should stop
// before upon reaching a correct mesh.
nSnap 5;
//- Minimum thickness of cell layer. If for any reason layer cannot be
// above minThickness do not add layer if thickness below minThickNess.
// Relative to undistorted cell size
minThickness 0.25;
//- If points get not extruded do nGrow layers of connected faces that are
// not grown. Is used to not do layers at all close to features.
nGrow 1;
// Expansion factor for layer mesh
expansionRatio 1.3;
// Ratio of cell size in final added cell layer to cell size
// outside layer
finalLayerRatio 0.3;
nRelaxIter 5;
// Number of smoothing iterations of surface normals
nSmoothSurfaceNormals 1;
@ -248,20 +275,14 @@ layerDict
// Create buffer region for new layer terminations
nBufferCellsNoExtrude 0;
thickness 0.5;
nSmoothDispl 4;
}
// For mesh motion
motionDict
{
//
// Mesh Quality Parameters. Decide when mesh is good enough to stop
// smoothing.
//
// Generic mesh quality settings. At any undoable phase these determine
// where to undo.
meshQualityControls
{
//- Maximum non-orthogonality allowed. Set to 180 to disable.
maxNonOrtho 65;
@ -298,10 +319,10 @@ motionDict
//- minVolRatio (0 -> 1)
minVolRatio 0.01;
//must be >0 for Fluent compatibility
minTriangleTwist -1;
// Advanced
//- Number of error distribution iterations
@ -311,4 +332,19 @@ motionDict
}
// Advanced
// Flags for optional output
// 0 : only write final meshes
// 1 : write intermediate meshes
// 2 : write volScalarField with cellLevel for postprocessing
// 4 : write current intersections as .obj files
debug 0;
// Merge tolerance. Is fraction of overall bounding box of initial mesh.
// Note: the write tolerance needs to be higher than this.
mergeTolerance 1E-6;
// ************************************************************************* //

View File

@ -73,13 +73,16 @@ find -H $packDir \
-a ! -name "core" \
-a ! -name "core.[1-9]*" \
-a ! -name "log[0-9]*" \
-a ! -name "libccmio*" \
-a ! -name "\.ebrowse" \
| sed \
-e "\@$packDir/.git/@d" \
-e "\@$packDir/lib/@d" \
-e "\@libccmio.*/@d" \
-e '\@applications/bin/@d' \
-e '\@/t/@d' \
-e '\@Make[.A-Za-z]*/[^/]*/@d'\
-e '\@/platforms/@d' \
> $tmpFile
tar czpf $packFile --files-from $tmpFile

78
bin/foamPackThirdPartyBin Executable file
View File

@ -0,0 +1,78 @@
#!/bin/sh
#------------------------------------------------------------------------------
# ========= |
# \\ / 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
#
# Script
# foamPackThirdPartyBin <archOptions> [outputDir]
#
# Description
# Packs and compresses binary version of OpenFOAM ThirdParty for release
#
#------------------------------------------------------------------------------
if [ $# = 0 ]
then
echo "Error: archOptionsitecture type expected, exiting"
echo
echo "Usage : ${0##*/} <archOptions> [outputDir]"
echo
exit 1
fi
archOptions=$1
arch=${archOptions%%G*}
arch3264=$(echo "$arch" | sed 's@64@-64@')
timeStamp=$(date +%Y-%m-%d)
packDir=ThirdParty
packFile=${packDir}.${archOptions}_${timeStamp}.gtgz
# add optional output directory
if [ -d "$2" ]
then
packFile="$2/$packFile"
fi
if [ -f $packFile ]
then
echo "Error: $packFile already exists"
exit 1
fi
# get list of directories
dirList=`find $packDir -type d -name $arch -o -type d -name $archOptions -o -type l -name $arch3264`
echo
echo "Packing $archOptions port of $packDir into $packFile"
echo
tar czpf $packFile $dirList
if [ $? = 0 ]
then
echo "Finished packing and compressing file $packFile"
else
echo "Error: failure packing $packFile"
rm -f $packFile 2>/dev/null
fi
#------------------------------------------------------------------------------

70
bin/foamPackThirdPartyGeneral Executable file
View File

@ -0,0 +1,70 @@
#!/bin/sh
#------------------------------------------------------------------------------
# ========= |
# \\ / 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
#
# Script
# foamPackThirdPartyGeneral [outputDir]
#
# Description
# Packs and compresses the OpenFOAM ThirdParty directory for release
#
#------------------------------------------------------------------------------
timeStamp=$(date +%Y-%m-%d)
packDir=ThirdParty
packFile=${packDir}.General_${timeStamp}.gtgz
if [ ! -d $packDir ]
then
echo "Error: directory $packDir does not exist"
exit 1
fi
# add optional output directory
if [ -d "$1" ]
then
packFile="$1/$packFile"
fi
if [ -f $packFile ]
then
echo "Error: $packFile already exists"
exit 1
fi
# Create time stamp file
# ~~~~~~~~~~~~~~~~~~~~~~
echo $timeStamp 2>/dev/null > $packDir/.timeStamp
# Pack and compress the packFile
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo
echo "Packing $packDir into $packFile"
echo
foamPackSource $packDir $packFile
#------------------------------------------------------------------------------

View File

@ -26,40 +26,14 @@ License
#include "interpolationTable.H"
#include "IFstream.H"
#include "objectRegistry.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
template<class Type>
Foam::interpolationTable<Type>::interpolationTable()
:
List<Tuple2<scalar, Type> >(),
dict_(dictionary::null),
boundAction_(interpolationTable::WARN),
fileName_("undefined_fileName")
{}
template<class Type>
Foam::interpolationTable<Type>::interpolationTable
(
const objectRegistry& obr,
const dictionary& dict
)
:
List<Tuple2<scalar, Type> >(),
dict_(dict),
boundAction_(wordToBoundAction(dict.lookup("boundAction"))),
fileName_(dict.lookup("fileName"))
void Foam::interpolationTable<Type>::readTable()
{
fileName_.expand();
// Correct for relative path
if (fileName_[0] != '/')
{
fileName_ = obr.db().path()/fileName_;
}
// Read data from file
IFstream(fileName_)() >> *this;
@ -78,6 +52,39 @@ Foam::interpolationTable<Type>::interpolationTable
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class Type>
Foam::interpolationTable<Type>::interpolationTable()
:
List<Tuple2<scalar, Type> >(),
boundAction_(interpolationTable::WARN),
fileName_("undefined_fileName")
{}
template<class Type>
Foam::interpolationTable<Type>::interpolationTable(const fileName& fn)
:
List<Tuple2<scalar, Type> >(),
boundAction_(interpolationTable::WARN),
fileName_(fn)
{
readTable();
}
template<class Type>
Foam::interpolationTable<Type>::interpolationTable(const dictionary& dict)
:
List<Tuple2<scalar, Type> >(),
boundAction_(wordToBoundAction(dict.lookup("boundAction"))),
fileName_(dict.lookup("fileName"))
{
readTable();
}
template<class Type>
Foam::interpolationTable<Type>::interpolationTable
(
@ -85,18 +92,11 @@ Foam::interpolationTable<Type>::interpolationTable
)
:
List<Tuple2<scalar, Type> >(interpTable),
dict_(interpTable.dict_),
boundAction_(interpTable.boundAction_),
fileName_(interpTable.fileName_)
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
template<class Type>
Foam::interpolationTable<Type>::~interpolationTable()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
@ -174,7 +174,7 @@ Foam::interpolationTable<Type>::wordToBoundAction
template<class Type>
void Foam::interpolationTable<Type>::check() const
{
label n = size();
label n = this->size();
scalar prevValue = List<Tuple2<scalar, Type> >::operator[](0).first();
for (label i=1; i<n; ++i)
@ -227,7 +227,7 @@ const Foam::Tuple2<Foam::scalar, Type>&
Foam::interpolationTable<Type>::operator[](const label i) const
{
label ii = i;
label n = size();
label n = this->size();
if (n <= 1)
{
@ -321,7 +321,7 @@ Foam::interpolationTable<Type>::operator[](const label i) const
template<class Type>
Type Foam::interpolationTable<Type>::operator()(const scalar value) const
{
label n = size();
label n = this->size();
if (n <= 1)
{

View File

@ -84,9 +84,6 @@ private:
// Private data
//- Parent dictionary
const dictionary& dict_;
//- Enumeration for handling out-of-bound values
boundActions boundAction_;
@ -94,6 +91,12 @@ private:
fileName fileName_;
// Private Member Functions
//- Read the table of data from file
void readTable();
public:
// Constructors
@ -101,47 +104,37 @@ public:
//- Construct null
interpolationTable();
//- Construct from objectRegistry and dictionary
interpolationTable(const objectRegistry& obr, const dictionary& dict);
//- Construct given the name of the file containing the table of data
interpolationTable(const fileName& fn);
//- Construct by reading the fileName and boundAction from dictionary
// and read the table from that file.
// This is a specialised constructor used by patchFields
interpolationTable(const dictionary& dict);
//- Construct copy
interpolationTable(const interpolationTable& interpTable);
//- Destructor
~interpolationTable();
// Member Functions
// Access
//- Return the size
label size() const
{
return List<Tuple2<scalar, Type> >::size();
}
//- Return the out-of-bounds treatment as a word
word boundActionToWord(const boundActions& bound) const;
//- Return the out-of-bounds treatment as an enumeration
boundActions wordToBoundAction(const word& bound) const;
// Check
//- Check that list is monotonically increasing
// Exit with a FatalError if there is a problem
void check() const;
// Edit
//- Set the out-of-bounds treatment from enum, return previous
// setting
boundActions boundAction(const boundActions& bound);
//- Write
void write(Ostream& os) const;
// Member Operators
@ -150,12 +143,6 @@ public:
//- Return an interpolated value
Type operator()(const scalar) const;
// I-O
//- Write
void write(Ostream& os) const;
};
@ -169,6 +156,8 @@ public:
# include "interpolationTable.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,15 +1,23 @@
autoHexMesh = autoHexMesh
autoHexMeshDriver = $(autoHexMesh)/autoHexMeshDriver
$(autoHexMeshDriver)/autoLayerDriver.C
$(autoHexMeshDriver)/autoLayerDriverShrink.C
$(autoHexMeshDriver)/autoSnapDriver.C
$(autoHexMeshDriver)/autoRefineDriver.C
$(autoHexMeshDriver)/autoHexMeshDriver.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/meshRefinement.C
$(autoHexMesh)/meshRefinement/meshRefinementMerge.C
$(autoHexMesh)/meshRefinement/meshRefinementRefine.C
$(autoHexMesh)/refinementSurfaces/refinementSurfaces.C
$(autoHexMesh)/shellSurfaces/shellSurfaces.C
$(autoHexMesh)/trackedParticle/trackedParticle.C
$(autoHexMesh)/trackedParticle/trackedParticleCloud.C

File diff suppressed because it is too large Load Diff

View File

@ -30,10 +30,6 @@ Description
SourceFiles
autoHexMeshDriver.C
autoHexMeshDriverSnap.C
autoHexMeshDriverLayers.C
autoHexMeshDriverShrink.C
autoHexMeshDriverTemplates.C
\*---------------------------------------------------------------------------*/
@ -44,13 +40,10 @@ SourceFiles
#include "dictionary.H"
#include "pointField.H"
#include "boolList.H"
#include "Switch.H"
#include "PackedList.H"
#include "wallPoint.H"
#include "indirectPrimitivePatch.H"
#include "featureEdgeMesh.H"
#include "searchableSurface.H"
#include "searchableSurfaces.H"
#include "refinementSurfaces.H"
#include "shellSurfaces.H"
#include "meshRefinement.H"
#include "decompositionMethod.H"
#include "fvMeshDistribute.H"
@ -62,14 +55,6 @@ namespace Foam
// Class forward declarations
class fvMesh;
class pointMesh;
class motionSmoother;
class removePoints;
class pointSet;
class pointData;
class faceSet;
class addPatchCellLayer;
class mapDistributePolyMesh;
/*---------------------------------------------------------------------------*\
Class autoHexMeshDriver Declaration
@ -79,15 +64,13 @@ class autoHexMeshDriver
{
// Static data members
//- Default angle for faces to be convcave
static const scalar defaultConcaveAngle;
//- Extrusion controls
enum extrudeMode
{
NOEXTRUDE, /*!< Do not extrude. No layers added. */
EXTRUDE, /*!< Extrude */
EXTRUDEREMOVE /*!< Extrude but afterwards remove added faces locally */
EXTRUDEREMOVE /*!< Extrude but afterwards remove added */
/*!< faces locally */
};
@ -141,42 +124,17 @@ class autoHexMeshDriver
//- Debug level
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
const scalar mergeDist_;
//- All surface based geometry
autoPtr<searchableSurfaces> allGeometryPtr_;
//- Explicit features
PtrList<featureEdgeMesh> featureMeshes_;
//- Per feature the refinement level
labelList featureLevels_;
//- Shells (geometry for inside/outside refinement)
autoPtr<shellSurfaces> shellsPtr_;
//- Shells
PtrList<searchableSurface> shells_;
//- Per shell the refinement level
labelList shellLevels_;
//- Per shell whether to refine inside or outside
boolList shellRefineInside_;
//- Surfaces with refinement levels built-in
//- Surfaces (geometry for intersection based refinement)
autoPtr<refinementSurfaces> surfacesPtr_;
//- Per refinement surface region the patch
@ -195,434 +153,10 @@ class autoHexMeshDriver
// Private Member Functions
// Refinement
//- Calculate merge distance. Check against writing tolerance.
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>&);
//- Read feature edges
label readFeatureEdges(const PtrList<dictionary>&);
// Snapping
//- Split surfaces into non-zoned and zones ones
void getZonedSurfaces(labelList&, labelList&) const;
//- Get faces to repatch. Returns map from face to patch.
Map<label> getZoneBafflePatches(const bool allowBoundary) const;
//- Calculates (geometric) shared points
static label getCollocatedPoints
(
const scalar tol,
const pointField&,
PackedList<1>&
);
//- Calculate displacement per patch point to smooth out patch.
// Quite complicated in determining which points to move where.
pointField smoothPatchDisplacement(const motionSmoother&) const;
//- Check that face zones are synced
void checkCoupledFaceZones() const;
//- Per edge distance to patch
static tmp<scalarField> edgePatchDist
(
const pointMesh&,
const indirectPrimitivePatch&
);
//- Write displacement as .obj file.
static void dumpMove
(
const fileName&,
const pointField&,
const pointField&
);
//- Check displacement is outwards pointing
static bool outwardsDisplacement
(
const indirectPrimitivePatch&,
const vectorField&
);
// Face merging
//- Merge patch faces. Undo until no checkMesh errors.
label mergePatchFacesUndo
(
const scalar minCos,
const scalar concaveCos,
const dictionary&
);
//- Remove points.
autoPtr<mapPolyMesh> doRemovePoints
(
removePoints& pointRemover,
const boolList& pointCanBeDeleted
);
//- Restore faces (which contain removed points)
autoPtr<mapPolyMesh> doRestorePoints
(
removePoints& pointRemover,
const labelList& facesToRestore
);
//- Return candidateFaces that are also in set.
labelList collectFaces
(
const labelList& candidateFaces,
const labelHashSet& set
) const;
//- Pick up faces of cells of faces in set.
labelList growFaceCellFace(const labelHashSet&) const;
//- Remove points not used by any face or points used by only
// two faces where the edges are in line
label mergeEdgesUndo(const scalar minCos, const dictionary&);
// Layers
//- For debugging: Dump displacement to .obj files
static void dumpDisplacement
(
const fileName&,
const indirectPrimitivePatch&,
const vectorField&,
const List<extrudeMode>&
);
//- Check that primitivePatch is not multiply connected.
// Collect non-manifold points in pointSet.
static void checkManifold
(
const indirectPrimitivePatch&,
pointSet& nonManifoldPoints
);
// Static extrusion setup
//- Unset extrusion on point. Returns true if anything unset.
static bool unmarkExtrusion
(
const label patchPointI,
pointField& patchDisp,
labelList& patchNLayers,
List<extrudeMode>& extrudeStatus
);
//- Unset extrusion on face. Returns true if anything unset.
static bool unmarkExtrusion
(
const face& localFace,
pointField& patchDisp,
labelList& patchNLayers,
List<extrudeMode>& extrudeStatus
);
//- No extrusion at non-manifold points.
void handleNonManifolds
(
const indirectPrimitivePatch& pp,
const labelList& meshEdges,
pointField& patchDisp,
labelList& patchNLayers,
List<extrudeMode>& extrudeStatus
) const;
//- No extrusion on feature edges. Assumes non-manifold
// edges already handled.
void handleFeatureAngle
(
const indirectPrimitivePatch& pp,
const labelList& meshEdges,
const scalar minCos,
pointField& patchDisp,
labelList& patchNLayers,
List<extrudeMode>& extrudeStatus
) const;
//- No extrusion on warped faces
void handleWarpedFaces
(
const indirectPrimitivePatch& pp,
const scalar faceRatio,
const scalar edge0Len,
const labelList& cellLevel,
pointField& patchDisp,
labelList& patchNLayers,
List<extrudeMode>& extrudeStatus
) const;
//- Determine the number of layers per point from the number of
// layers per surface.
void setNumLayers
(
const labelList& patchIDs,
const indirectPrimitivePatch& pp,
pointField& patchDisp,
labelList& patchNLayers,
List<extrudeMode>& extrudeStatus
) const;
//- Grow no-extrusion layer.
static void growNoExtrusion
(
const indirectPrimitivePatch& pp,
pointField& patchDisp,
labelList& patchNLayers,
List<extrudeMode>& extrudeStatus
);
//- Calculate pointwise wanted and minimum thickness.
// thickness: wanted thickness
// minthickness: when to give up and not extrude
void calculateLayerThickness
(
const scalar expansionRatio,
const scalar finalLayerRatio,
const scalar relMinThickness,
const indirectPrimitivePatch& pp,
const labelList& cellLevel,
const labelList& patchNLayers,
const scalar edge0Len,
scalarField& thickness,
scalarField& minThickness
) const;
// Extrusion execution
//- Synchronize displacement among coupled patches.
void syncPatchDisplacement
(
const motionSmoother& meshMover,
const scalarField& minThickness,
pointField& patchDisp,
labelList& patchNLayers,
List<extrudeMode>& extrudeStatus
) const;
//- Get nearest point on surface to snap to
void getPatchDisplacement
(
const motionSmoother& meshMover,
const scalarField& thickness,
const scalarField& minThickness,
pointField& patchDisp,
labelList& patchNLayers,
List<extrudeMode>& extrudeStatus
) const;
//- Truncates displacement
// - for all patchFaces in the faceset displacement gets set
// to zero
// - all displacement < minThickness gets set to zero
label truncateDisplacement
(
const motionSmoother& meshMover,
const scalarField& minThickness,
const faceSet& illegalPatchFaces,
pointField& patchDisp,
labelList& patchNLayers,
List<extrudeMode>& extrudeStatus
) const;
//- Setup layer information (at points and faces) to
// modify mesh topology in
// regions where layer mesh terminates. Guarantees an
// optional slow decreasing of the number of layers.
// Returns the number of layers per face and per point
// to go into the actual layer addition engine.
void setupLayerInfoTruncation
(
const motionSmoother& meshMover,
const labelList& patchNLayers,
const List<extrudeMode>& extrudeStatus,
const label nBufferCellsNoExtrude,
labelList& nPatchPointLayers,
labelList& nPatchFaceLayers
) const;
//- Does any of the cells use a face from faces?
static bool cellsUseFace
(
const polyMesh& mesh,
const labelList& cellLabels,
const labelHashSet& faces
);
//- Checks the newly added cells and locally unmarks points
// so they will not get extruded next time round. Returns
// global number of unmarked points (0 if all was fine)
static label checkAndUnmark
(
const addPatchCellLayer& addLayer,
const dictionary& motionDict,
const indirectPrimitivePatch& pp,
const fvMesh&,
pointField& patchDisp,
labelList& patchNLayers,
List<extrudeMode>& extrudeStatus
);
//- Count global number of extruded faces
static label countExtrusion
(
const indirectPrimitivePatch& pp,
const List<extrudeMode>& extrudeStatus
);
//- Collect layer faces and layer cells into bools
// for ease of handling
static void getLayerCellsFaces
(
const polyMesh&,
const addPatchCellLayer&,
boolList&,
boolList&
);
// Mesh shrinking (to create space for layers)
//- Average field (over all subset of mesh points) by
// summing contribution from edges. Global parallel since only
// does master edges for coupled edges.
template<class Type>
void averageNeighbours
(
const PackedList<1>& isMasterEdge,
const labelList& meshEdges,
const labelList& meshPoints,
const edgeList& edges,
const scalarField& invSumWeight,
const Field<Type>& data,
Field<Type>& average
) const;
//- Calculate inverse sum of edge weights (currently always 1.0)
void sumWeights
(
const PackedList<1>& isMasterEdge,
const labelList& meshEdges,
const labelList& meshPoints,
const edgeList& edges,
scalarField& invSumWeight
) const;
//- Smooth scalar field on patch
void smoothField
(
const motionSmoother& meshMover,
const PackedList<1>& isMasterEdge,
const labelList& meshEdges,
const scalarField& fieldMin,
const label& nSmoothDisp,
scalarField& field
) const;
//- Smooth normals on patch.
void smoothPatchNormals
(
const motionSmoother& meshMover,
const PackedList<1>& isMasterEdge,
const labelList& meshEdges,
const label nSmoothDisp,
pointField& normals
) const;
//- Smooth normals in interior.
void smoothNormals
(
const label nSmoothDisp,
const PackedList<1>& isMasterEdge,
const labelList& fixedPoints,
pointVectorField& normals
) const;
bool isMaxEdge
(
const List<pointData>&,
const label edgeI,
const scalar minCos
) const;
//- Stop layer growth where mesh wraps around edge with a
// large feature angle
void handleFeatureAngleLayerTerminations
(
const indirectPrimitivePatch& pp,
const scalar minCos,
List<extrudeMode>& extrudeStatus,
pointField& patchDisp,
labelList& patchNLayers,
label& nPointCounter
) const;
//- Find isolated islands (points, edges and faces and
// layer terminations)
// in the layer mesh and stop any layer growth at these points.
void findIsolatedRegions
(
const indirectPrimitivePatch& pp,
const PackedList<1>& isMasterEdge,
const labelList& meshEdges,
const scalar minCosLayerTermination,
scalarField& field,
List<extrudeMode>& extrudeStatus,
pointField& patchDisp,
labelList& patchNLayers
) const;
// Calculate medial axis fields
void medialAxisSmoothingInfo
(
const motionSmoother& meshMover,
const label nSmoothNormals,
const label nSmoothSurfaceNormals,
const scalar minMedianAxisAngleCos,
pointVectorField& dispVec,
pointScalarField& medialRatio,
pointScalarField& medialDist
) const;
//- Main routine to shrink mesh
void shrinkMeshMedialDistance
(
motionSmoother& meshMover,
const label nSmoothThickness,
const scalar maxThicknessToMedialRatio,
const label nAllowableErrors,
const label nSnap,
const scalar minCosLayerTermination,
const scalarField& layerThickness,
const scalarField& minThickness,
const pointVectorField& dispVec,
const pointScalarField& medialRatio,
const pointScalarField& medialDist,
List<extrudeMode>& extrudeStatus,
pointField& patchDisp,
labelList& patchNLayers
) const;
//static void orientOutside(PtrList<searchableSurface>&);
//- Disallow default bitwise copy construct
autoHexMeshDriver(const autoHexMeshDriver&);
@ -646,16 +180,6 @@ public:
const dictionary& decomposeDict
);
//- Alternative constructor from top-level controldictionary and
// refinement specific dictionary
autoHexMeshDriver
(
fvMesh& mesh,
const dictionary& controlDict,
const dictionary& refineDict,
const dictionary& decomposeDict
);
// Member Functions
@ -677,6 +201,12 @@ public:
return surfacesPtr_();
}
//- Surfaces to volume refinement on
const shellSurfaces& shells() const
{
return shellsPtr_();
}
//- Per refinementsurface, per region the patch
const labelList& globalToPatch() const
{
@ -684,153 +214,11 @@ public:
}
// Refinement
//- Refine around explicit feature edges
label featureEdgeRefine
(
const PtrList<dictionary>& featDicts,
const label maxIter,
const label minRefine
);
//- Refine at surface intersections
label surfaceOnlyRefine(const label maxIter);
//- Remove cells not reachable from keep points
void removeInsideCells(const label nBufferLayers);
//- Refine volume regions (interior of shells)
label shellRefine(const label maxIter);
//- Introduce baffles; remove unreachable mesh parts
// handleSnapProblems : whether to remove free floating cells
void baffleAndSplitMesh(const bool handleSnapProblems);
//- Move cells to zones
void zonify();
//- Split and recombine baffles to get rid of single face baffles.
void splitAndMergeBaffles(const bool handleSnapProblems);
//- Merge multiple boundary faces on single cell
void mergePatchFaces();
//- Redecompose according to cell count
// keepZoneFaces : find all faceZones from zoned surfaces and keep
// owner and neighbour together
// keepBaffles : find all baffles and keep them together
autoPtr<mapDistributePolyMesh> balance
(
const bool keepZoneFaces,
const bool keepBaffles
);
// Meshing
//- Write mesh
void writeMesh(const string&) const;
// Snapping
//- Create baffles for faces straddling zoned surfaces. Return
// baffles.
autoPtr<mapPolyMesh> createZoneBaffles(List<labelPair>&);
//- Merge baffles.
autoPtr<mapPolyMesh> mergeZoneBaffles(const List<labelPair>&);
//- Calculate edge length per patch point.
scalarField calcSnapDistance
(
const dictionary& snapDict,
const indirectPrimitivePatch&
) const;
//- Get patches generated for surfaces.
labelList getSurfacePatches() const;
//- Smooth the mesh (patch and internal) to increase visibility
// of surface points (on castellated mesh) w.r.t. surface.
void preSmoothPatch
(
const dictionary& snapDict,
const label nInitErrors,
const List<labelPair>& baffles,
motionSmoother&
) const;
//- Per patch point calculate point on nearest surface. Set as
// boundary conditions of motionSmoother displacement field. Return
// displacement of patch points.
vectorField calcNearestSurface
(
const scalarField& snapDist,
motionSmoother& meshMover
) const;
//- Smooth the displacement field to the internal.
void smoothDisplacement
(
const dictionary& snapDict,
motionSmoother&
) const;
//- Do the hard work: move the mesh according to displacement,
// locally relax the displacement.
void scaleMesh
(
const dictionary& snapDict,
const label nInitErrors,
const List<labelPair>& baffles,
motionSmoother&
);
// Layers
//- Merge patch faces on same cell.
void mergePatchFacesUndo
(
const dictionary& shrinkDict,
const dictionary& motionDict
);
//- Check that mesh outside is not multiply connected.
void checkMeshManifold() const;
//- Add cell layers
void addLayers
(
const dictionary& shrinkDict,
const dictionary& motionDict,
const label nAllowableErrors,
motionSmoother&
);
// Other
//- Do all refinement.
void doRefine
(
const dictionary& refineDict,
const bool prepareForSnapping
);
//- Do all snapping.
void doSnap
(
const dictionary& snapDict,
const dictionary& motionDict
);
//- Do alllayer addition.
void doLayers
(
const dictionary& shrinkDict,
const dictionary& motionDict
);
//- Do all : refine, snap, layers
void doMesh();
};
@ -842,12 +230,6 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
# include "autoHexMeshDriverTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,562 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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::autoLayerDriver
Description
All to do with adding layers
SourceFiles
autoLayerDriver.C
\*---------------------------------------------------------------------------*/
#ifndef autoLayerDriver_H
#define autoLayerDriver_H
#include "meshRefinement.H"
#include "wallPoint.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declaration of classes
class removePoints;
class pointSet;
class motionSmoother;
class addPatchCellLayer;
class pointData;
class wallPoint;
class faceSet;
class layerParameters;
/*---------------------------------------------------------------------------*\
Class autoLayerDriver Declaration
\*---------------------------------------------------------------------------*/
class autoLayerDriver
{
// Static data members
//- Extrusion controls
enum extrudeMode
{
NOEXTRUDE, /*!< Do not extrude. No layers added. */
EXTRUDE, /*!< Extrude */
EXTRUDEREMOVE /*!< Extrude but afterwards remove added */
/*!< faces locally */
};
// Private classes
//- Combine operator class to combine normal with other normal.
class nomalsCombine
{
public:
void operator()(vector& x, const vector& y) const
{
if (y != wallPoint::greatPoint)
{
if (x == wallPoint::greatPoint)
{
x = y;
}
else
{
x *= (x&y);
}
}
}
};
// Private data
//- Mesh+surface
meshRefinement& meshRefiner_;
//- From surface region to patch
const labelList globalToPatch_;
// Private Member Functions
// Face merging
//- Merge patch faces. Undo until no checkMesh errors.
label mergePatchFacesUndo
(
const scalar minCos,
const scalar concaveCos,
const dictionary&
);
//- Remove points.
autoPtr<mapPolyMesh> doRemovePoints
(
removePoints& pointRemover,
const boolList& pointCanBeDeleted
);
//- Restore faces (which contain removed points)
autoPtr<mapPolyMesh> doRestorePoints
(
removePoints& pointRemover,
const labelList& facesToRestore
);
//- Return candidateFaces that are also in set.
labelList collectFaces
(
const labelList& candidateFaces,
const labelHashSet& set
) const;
//- Pick up faces of cells of faces in set.
labelList growFaceCellFace(const labelHashSet&) const;
//- Remove points not used by any face or points used by only
// two faces where the edges are in line
label mergeEdgesUndo(const scalar minCos, const dictionary&);
// Layers
//- For debugging: Dump displacement to .obj files
static void dumpDisplacement
(
const fileName&,
const indirectPrimitivePatch&,
const vectorField&,
const List<extrudeMode>&
);
//- Check that primitivePatch is not multiply connected.
// Collect non-manifold points in pointSet.
static void checkManifold
(
const indirectPrimitivePatch&,
pointSet& nonManifoldPoints
);
//- Check that mesh outside is not multiply connected.
void checkMeshManifold() const;
// Static extrusion setup
//- Unset extrusion on point. Returns true if anything unset.
static bool unmarkExtrusion
(
const label patchPointI,
pointField& patchDisp,
labelList& patchNLayers,
List<extrudeMode>& extrudeStatus
);
//- Unset extrusion on face. Returns true if anything unset.
static bool unmarkExtrusion
(
const face& localFace,
pointField& patchDisp,
labelList& patchNLayers,
List<extrudeMode>& extrudeStatus
);
//- No extrusion at non-manifold points.
void handleNonManifolds
(
const indirectPrimitivePatch& pp,
const labelList& meshEdges,
pointField& patchDisp,
labelList& patchNLayers,
List<extrudeMode>& extrudeStatus
) const;
//- No extrusion on feature edges. Assumes non-manifold
// edges already handled.
void handleFeatureAngle
(
const indirectPrimitivePatch& pp,
const labelList& meshEdges,
const scalar minCos,
pointField& patchDisp,
labelList& patchNLayers,
List<extrudeMode>& extrudeStatus
) const;
//- No extrusion on warped faces
void handleWarpedFaces
(
const indirectPrimitivePatch& pp,
const scalar faceRatio,
const scalar edge0Len,
const labelList& cellLevel,
pointField& patchDisp,
labelList& patchNLayers,
List<extrudeMode>& extrudeStatus
) const;
//- Determine the number of layers per point from the number of
// layers per surface.
void setNumLayers
(
const labelList& patchToNLayers,
const labelList& patchIDs,
const indirectPrimitivePatch& pp,
pointField& patchDisp,
labelList& patchNLayers,
List<extrudeMode>& extrudeStatus
) const;
//- Grow no-extrusion layer.
static void growNoExtrusion
(
const indirectPrimitivePatch& pp,
pointField& patchDisp,
labelList& patchNLayers,
List<extrudeMode>& extrudeStatus
);
//- Calculate pointwise wanted and minimum thickness.
// thickness: wanted thickness
// minthickness: when to give up and not extrude
// Gets per patch parameters and determine pp pointwise
// parameters.
void calculateLayerThickness
(
const indirectPrimitivePatch& pp,
const labelList& patchIDs,
const scalarField& patchExpansionRatio,
const scalarField& patchFinalLayerRatio,
const scalarField& patchRelMinThickness,
const labelList& cellLevel,
const labelList& patchNLayers,
const scalar edge0Len,
scalarField& thickness,
scalarField& minThickness,
scalarField& expansionRatio
) const;
// Extrusion execution
//- Synchronize displacement among coupled patches.
void syncPatchDisplacement
(
const motionSmoother& meshMover,
const scalarField& minThickness,
pointField& patchDisp,
labelList& patchNLayers,
List<extrudeMode>& extrudeStatus
) const;
//- Get nearest point on surface to snap to
void getPatchDisplacement
(
const motionSmoother& meshMover,
const scalarField& thickness,
const scalarField& minThickness,
pointField& patchDisp,
labelList& patchNLayers,
List<extrudeMode>& extrudeStatus
) const;
//- Truncates displacement
// - for all patchFaces in the faceset displacement gets set
// to zero
// - all displacement < minThickness gets set to zero
label truncateDisplacement
(
const motionSmoother& meshMover,
const scalarField& minThickness,
const faceSet& illegalPatchFaces,
pointField& patchDisp,
labelList& patchNLayers,
List<extrudeMode>& extrudeStatus
) const;
//- Setup layer information (at points and faces) to
// modify mesh topology in
// regions where layer mesh terminates. Guarantees an
// optional slow decreasing of the number of layers.
// Returns the number of layers per face and per point
// to go into the actual layer addition engine.
void setupLayerInfoTruncation
(
const motionSmoother& meshMover,
const labelList& patchNLayers,
const List<extrudeMode>& extrudeStatus,
const label nBufferCellsNoExtrude,
labelList& nPatchPointLayers,
labelList& nPatchFaceLayers
) const;
//- Does any of the cells use a face from faces?
static bool cellsUseFace
(
const polyMesh& mesh,
const labelList& cellLabels,
const labelHashSet& faces
);
//- Checks the newly added cells and locally unmarks points
// so they will not get extruded next time round. Returns
// global number of unmarked points (0 if all was fine)
static label checkAndUnmark
(
const addPatchCellLayer& addLayer,
const dictionary& motionDict,
const indirectPrimitivePatch& pp,
const fvMesh&,
pointField& patchDisp,
labelList& patchNLayers,
List<extrudeMode>& extrudeStatus
);
//- Count global number of extruded faces
static label countExtrusion
(
const indirectPrimitivePatch& pp,
const List<extrudeMode>& extrudeStatus
);
//- Collect layer faces and layer cells into bools
// for ease of handling
static void getLayerCellsFaces
(
const polyMesh&,
const addPatchCellLayer&,
boolList&,
boolList&
);
// Mesh shrinking (to create space for layers)
//- Average field (over all subset of mesh points) by
// summing contribution from edges. Global parallel since only
// does master edges for coupled edges.
template<class Type>
static void averageNeighbours
(
const polyMesh& mesh,
const PackedList<1>& isMasterEdge,
const labelList& meshEdges,
const labelList& meshPoints,
const edgeList& edges,
const scalarField& invSumWeight,
const Field<Type>& data,
Field<Type>& average
);
//- Calculate inverse sum of edge weights (currently always 1.0)
void sumWeights
(
const PackedList<1>& isMasterEdge,
const labelList& meshEdges,
const labelList& meshPoints,
const edgeList& edges,
scalarField& invSumWeight
) const;
//- Smooth scalar field on patch
void smoothField
(
const motionSmoother& meshMover,
const PackedList<1>& isMasterEdge,
const labelList& meshEdges,
const scalarField& fieldMin,
const label& nSmoothDisp,
scalarField& field
) const;
//- Smooth normals on patch.
void smoothPatchNormals
(
const motionSmoother& meshMover,
const PackedList<1>& isMasterEdge,
const labelList& meshEdges,
const label nSmoothDisp,
pointField& normals
) const;
//- Smooth normals in interior.
void smoothNormals
(
const label nSmoothDisp,
const PackedList<1>& isMasterEdge,
const labelList& fixedPoints,
pointVectorField& normals
) const;
bool isMaxEdge
(
const List<pointData>&,
const label edgeI,
const scalar minCos
) const;
//- Stop layer growth where mesh wraps around edge with a
// large feature angle
void handleFeatureAngleLayerTerminations
(
const indirectPrimitivePatch& pp,
const scalar minCos,
List<extrudeMode>& extrudeStatus,
pointField& patchDisp,
labelList& patchNLayers,
label& nPointCounter
) const;
//- Find isolated islands (points, edges and faces and
// layer terminations)
// in the layer mesh and stop any layer growth at these points.
void findIsolatedRegions
(
const indirectPrimitivePatch& pp,
const PackedList<1>& isMasterEdge,
const labelList& meshEdges,
const scalar minCosLayerTermination,
scalarField& field,
List<extrudeMode>& extrudeStatus,
pointField& patchDisp,
labelList& patchNLayers
) const;
// Calculate medial axis fields
void medialAxisSmoothingInfo
(
const motionSmoother& meshMover,
const label nSmoothNormals,
const label nSmoothSurfaceNormals,
const scalar minMedianAxisAngleCos,
pointVectorField& dispVec,
pointScalarField& medialRatio,
pointScalarField& medialDist
) const;
//- Main routine to shrink mesh
void shrinkMeshMedialDistance
(
motionSmoother& meshMover,
const label nSmoothThickness,
const scalar maxThicknessToMedialRatio,
const label nAllowableErrors,
const label nSnap,
const scalar minCosLayerTermination,
const scalarField& layerThickness,
const scalarField& minThickness,
const pointVectorField& dispVec,
const pointScalarField& medialRatio,
const pointScalarField& medialDist,
List<extrudeMode>& extrudeStatus,
pointField& patchDisp,
labelList& patchNLayers
) const;
//- Disallow default bitwise copy construct
autoLayerDriver(const autoLayerDriver&);
//- Disallow default bitwise assignment
void operator=(const autoLayerDriver&);
public:
//- Runtime type information
ClassName("autoLayerDriver");
// Constructors
//- Construct from components
autoLayerDriver
(
meshRefinement& meshRefiner,
const labelList& globalToPatch
);
// Member Functions
//- Merge patch faces on same cell.
void mergePatchFacesUndo
(
const layerParameters& layerParams,
const dictionary& motionDict
);
//- Add cell layers
void addLayers
(
const layerParameters& layerParams,
const dictionary& motionDict,
const label nAllowableErrors,
motionSmoother& meshMover,
decompositionMethod& decomposer,
fvMeshDistribute& distributor
);
//- Add layers according to the dictionary settings
void doLayers
(
const dictionary& shrinkDict,
const dictionary& motionDict,
const layerParameters& layerParams,
decompositionMethod& decomposer,
fvMeshDistribute& distributor
);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
# include "autoLayerDriverTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -27,7 +27,7 @@ Description
\*----------------------------------------------------------------------------*/
#include "autoHexMeshDriver.H"
#include "autoLayerDriver.H"
#include "fvMesh.H"
#include "Time.H"
#include "pointFields.H"
@ -41,7 +41,7 @@ Description
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
// Calculate inverse sum of edge weights (currently always 1.0)
void Foam::autoHexMeshDriver::sumWeights
void Foam::autoLayerDriver::sumWeights
(
const PackedList<1>& isMasterEdge,
const labelList& meshEdges,
@ -67,7 +67,7 @@ void Foam::autoHexMeshDriver::sumWeights
syncTools::syncPointList
(
mesh_,
meshRefiner_.mesh(),
meshPoints,
invSumWeight,
plusEqOp<scalar>(),
@ -88,7 +88,7 @@ void Foam::autoHexMeshDriver::sumWeights
// Smooth field on moving patch
void Foam::autoHexMeshDriver::smoothField
void Foam::autoLayerDriver::smoothField
(
const motionSmoother& meshMover,
const PackedList<1>& isMasterEdge,
@ -120,6 +120,7 @@ void Foam::autoHexMeshDriver::smoothField
scalarField average(pp.nPoints());
averageNeighbours
(
meshMover.mesh(),
isMasterEdge,
meshEdges,
meshPoints,
@ -159,7 +160,7 @@ void Foam::autoHexMeshDriver::smoothField
// Smooth normals on moving patch.
void Foam::autoHexMeshDriver::smoothPatchNormals
void Foam::autoLayerDriver::smoothPatchNormals
(
const motionSmoother& meshMover,
const PackedList<1>& isMasterEdge,
@ -192,6 +193,7 @@ void Foam::autoHexMeshDriver::smoothPatchNormals
vectorField average(pp.nPoints());
averageNeighbours
(
meshMover.mesh(),
isMasterEdge,
meshEdges,
meshPoints,
@ -223,7 +225,7 @@ void Foam::autoHexMeshDriver::smoothPatchNormals
// Smooth normals in interior.
void Foam::autoHexMeshDriver::smoothNormals
void Foam::autoLayerDriver::smoothNormals
(
const label nSmoothDisp,
const PackedList<1>& isMasterEdge,
@ -234,10 +236,11 @@ void Foam::autoHexMeshDriver::smoothNormals
// Get smoothly varying internal normals field.
Info<< "shrinkMeshDistance : Smoothing normals ..." << endl;
const edgeList& edges = mesh_.edges();
const fvMesh& mesh = meshRefiner_.mesh();
const edgeList& edges = mesh.edges();
// Points that do not change.
PackedList<1> isFixedPoint(mesh_.nPoints(), 0);
PackedList<1> isFixedPoint(mesh.nPoints(), 0);
// Internal points that are fixed
forAll(fixedPoints, i)
@ -247,12 +250,12 @@ void Foam::autoHexMeshDriver::smoothNormals
}
// Correspondence between local edges/points and mesh edges/points
const labelList meshEdges(identity(mesh_.nEdges()));
const labelList meshPoints(identity(mesh_.nPoints()));
const labelList meshEdges(identity(mesh.nEdges()));
const labelList meshPoints(identity(mesh.nPoints()));
// Calculate inverse sum of weights
scalarField invSumWeight(mesh_.nPoints(), 0);
scalarField invSumWeight(mesh.nPoints(), 0);
sumWeights
(
isMasterEdge,
@ -266,9 +269,10 @@ void Foam::autoHexMeshDriver::smoothNormals
for (label iter = 0; iter < nSmoothDisp; iter++)
{
vectorField average(mesh_.nPoints());
vectorField average(mesh.nPoints());
averageNeighbours
(
mesh,
isMasterEdge,
meshEdges,
meshPoints,
@ -305,18 +309,19 @@ void Foam::autoHexMeshDriver::smoothNormals
// Tries and find a medial axis point. Done by comparing vectors to nearest
// wall point for both vertices of edge.
bool Foam::autoHexMeshDriver::isMaxEdge
bool Foam::autoLayerDriver::isMaxEdge
(
const List<pointData>& pointWallDist,
const label edgeI,
const scalar minCos
) const
{
const pointField& points = mesh_.points();
const fvMesh& mesh = meshRefiner_.mesh();
const pointField& points = mesh.points();
// Do not mark edges with one side on moving wall.
const edge& e = mesh_.edges()[edgeI];
const edge& e = mesh.edges()[edgeI];
vector v0(points[e[0]] - pointWallDist[e[0]].origin());
scalar magV0(mag(v0));
@ -351,7 +356,7 @@ bool Foam::autoHexMeshDriver::isMaxEdge
// Stop layer growth where mesh wraps around edge with a
// large feature angle
void Foam::autoHexMeshDriver::handleFeatureAngleLayerTerminations
void Foam::autoLayerDriver::handleFeatureAngleLayerTerminations
(
const indirectPrimitivePatch& pp,
const scalar minCos,
@ -444,7 +449,7 @@ void Foam::autoHexMeshDriver::handleFeatureAngleLayerTerminations
// Find isolated islands (points, edges and faces and layer terminations)
// in the layer mesh and stop any layer growth at these points.
void Foam::autoHexMeshDriver::findIsolatedRegions
void Foam::autoLayerDriver::findIsolatedRegions
(
const indirectPrimitivePatch& pp,
const PackedList<1>& isMasterEdge,
@ -456,6 +461,8 @@ void Foam::autoHexMeshDriver::findIsolatedRegions
labelList& patchNLayers
) const
{
const fvMesh& mesh = meshRefiner_.mesh();
Info<< "shrinkMeshDistance : Removing isolated regions ..." << endl;
// Keep count of number of points unextruded
@ -514,7 +521,7 @@ void Foam::autoHexMeshDriver::findIsolatedRegions
syncTools::syncPointList
(
mesh_,
mesh,
pp.meshPoints(),
keptPoints,
orEqOp<bool>(),
@ -582,7 +589,7 @@ void Foam::autoHexMeshDriver::findIsolatedRegions
syncTools::syncPointList
(
mesh_,
mesh,
pp.meshPoints(),
isolatedPoint,
plusEqOp<label>(),
@ -650,7 +657,7 @@ void Foam::autoHexMeshDriver::findIsolatedRegions
// medialDist : distance to medial axis
// medialRatio : ratio of medial distance to wall distance.
// (1 at wall, 0 at medial axis)
void Foam::autoHexMeshDriver::medialAxisSmoothingInfo
void Foam::autoLayerDriver::medialAxisSmoothingInfo
(
const motionSmoother& meshMover,
const label nSmoothNormals,
@ -666,7 +673,8 @@ void Foam::autoHexMeshDriver::medialAxisSmoothingInfo
Info<< "medialAxisSmoothingInfo :"
<< " Calculate distance to Medial Axis ..." << endl;
const pointField& points = mesh_.points();
const polyMesh& mesh = meshMover.mesh();
const pointField& points = mesh.points();
const pointMesh& pMesh = meshMover.pMesh();
const indirectPrimitivePatch& pp = meshMover.patch();
@ -677,7 +685,7 @@ void Foam::autoHexMeshDriver::medialAxisSmoothingInfo
// ~~~~~~~~~~~~~~~~~~~~~~~
// Precalulate master edge (only relevant for shared edges)
PackedList<1> isMasterEdge(syncTools::getMasterEdges(mesh_));
PackedList<1> isMasterEdge(syncTools::getMasterEdges(mesh));
// Precalculate meshEdge per pp edge
labelList meshEdges(pp.nEdges());
@ -689,8 +697,8 @@ void Foam::autoHexMeshDriver::medialAxisSmoothingInfo
label v1 = pp.meshPoints()[e[1]];
meshEdges[patchEdgeI] = meshTools::findEdge
(
mesh_.edges(),
mesh_.pointEdges()[v0],
mesh.edges(),
mesh.pointEdges()[v0],
v0,
v1
);
@ -717,7 +725,7 @@ void Foam::autoHexMeshDriver::medialAxisSmoothingInfo
syncTools::syncPointList
(
mesh_,
mesh,
meshPoints,
pointNormals,
plusEqOp<vector>(),
@ -727,7 +735,7 @@ void Foam::autoHexMeshDriver::medialAxisSmoothingInfo
syncTools::syncPointList
(
mesh_,
mesh,
meshPoints,
nPointFaces,
plusEqOp<label>(),
@ -756,7 +764,7 @@ void Foam::autoHexMeshDriver::medialAxisSmoothingInfo
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Distance to wall
List<pointData> pointWallDist(mesh_.nPoints());
List<pointData> pointWallDist(mesh.nPoints());
// 1. Calculate distance to points where displacement is specified.
@ -777,7 +785,7 @@ void Foam::autoHexMeshDriver::medialAxisSmoothingInfo
}
// Do all calculations
List<pointData> edgeWallDist(mesh_.nEdges());
List<pointData> edgeWallDist(mesh.nEdges());
PointEdgeWave<pointData> wallDistCalc
(
pMesh,
@ -785,15 +793,15 @@ void Foam::autoHexMeshDriver::medialAxisSmoothingInfo
wallInfo,
pointWallDist,
edgeWallDist,
mesh_.nPoints() // max iterations
mesh.nPoints() // max iterations
);
}
// 2. Find points with max distance and transport information back to
// wall.
{
List<pointData> pointMedialDist(mesh_.nPoints());
List<pointData> edgeMedialDist(mesh_.nEdges());
List<pointData> pointMedialDist(mesh.nPoints());
List<pointData> edgeMedialDist(mesh.nEdges());
// Seed point data.
DynamicList<pointData> maxInfo(meshPoints.size());
@ -801,7 +809,7 @@ void Foam::autoHexMeshDriver::medialAxisSmoothingInfo
// 1. Medial axis points
const edgeList& edges = mesh_.edges();
const edgeList& edges = mesh.edges();
forAll(edges, edgeI)
{
@ -836,7 +844,7 @@ void Foam::autoHexMeshDriver::medialAxisSmoothingInfo
// 2. Seed non-adapt patches
const polyBoundaryMesh& patches = mesh_.boundaryMesh();
const polyBoundaryMesh& patches = mesh.boundaryMesh();
labelHashSet adaptPatches(meshMover.adaptPatchIDs());
@ -890,7 +898,7 @@ void Foam::autoHexMeshDriver::medialAxisSmoothingInfo
pointMedialDist,
edgeMedialDist,
mesh_.nPoints() // max iterations
mesh.nPoints() // max iterations
);
// Extract medial axis distance as pointScalarField
@ -925,7 +933,7 @@ void Foam::autoHexMeshDriver::medialAxisSmoothingInfo
}
}
if (debug_)
if (debug)
{
Info<< "medialAxisSmoothingInfo :"
<< " Writing:" << nl
@ -943,7 +951,7 @@ void Foam::autoHexMeshDriver::medialAxisSmoothingInfo
}
void Foam::autoHexMeshDriver::shrinkMeshMedialDistance
void Foam::autoLayerDriver::shrinkMeshMedialDistance
(
motionSmoother& meshMover,
const label nSmoothThickness,
@ -973,7 +981,7 @@ void Foam::autoHexMeshDriver::shrinkMeshMedialDistance
const labelList& meshPoints = pp.meshPoints();
// Precalulate master edge (only relevant for shared edges)
PackedList<1> isMasterEdge(syncTools::getMasterEdges(mesh_));
PackedList<1> isMasterEdge(syncTools::getMasterEdges(mesh));
// Precalculate meshEdge per pp edge
labelList meshEdges(pp.nEdges());
@ -985,8 +993,8 @@ void Foam::autoHexMeshDriver::shrinkMeshMedialDistance
label v1 = pp.meshPoints()[e[1]];
meshEdges[patchEdgeI] = meshTools::findEdge
(
mesh_.edges(),
mesh_.pointEdges()[v0],
mesh.edges(),
mesh.pointEdges()[v0],
v0,
v1
);

View File

@ -24,14 +24,15 @@ License
\*---------------------------------------------------------------------------*/
#include "autoHexMeshDriver.H"
#include "autoLayerDriver.H"
#include "syncTools.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class Type>
void Foam::autoHexMeshDriver::averageNeighbours
void Foam::autoLayerDriver::averageNeighbours
(
const polyMesh& mesh,
const PackedList<1>& isMasterEdge,
const labelList& meshEdges,
const labelList& meshPoints,
@ -39,7 +40,7 @@ void Foam::autoHexMeshDriver::averageNeighbours
const scalarField& invSumWeight,
const Field<Type>& data,
Field<Type>& average
) const
)
{
average = pTraits<Type>::zero;
@ -60,7 +61,7 @@ void Foam::autoHexMeshDriver::averageNeighbours
syncTools::syncPointList
(
mesh_,
mesh,
meshPoints,
average,
plusEqOp<Type>(),

View File

@ -0,0 +1,776 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "autoRefineDriver.H"
#include "fvMesh.H"
#include "Time.H"
#include "boundBox.H"
#include "mapDistributePolyMesh.H"
#include "cellSet.H"
#include "syncTools.H"
#include "refinementParameters.H"
#include "featureEdgeMesh.H"
#include "refinementSurfaces.H"
#include "shellSurfaces.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(autoRefineDriver, 0);
} // End namespace Foam
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
// Read explicit feature edges
Foam::label Foam::autoRefineDriver::readFeatureEdges
(
const PtrList<dictionary>& featDicts,
PtrList<featureEdgeMesh>& featureMeshes,
labelList& featureLevels
) const
{
Info<< "Reading external feature lines." << endl;
const fvMesh& mesh = meshRefiner_.mesh();
featureMeshes.setSize(featDicts.size());
featureLevels.setSize(featDicts.size());
forAll(featDicts, i)
{
const dictionary& dict = featDicts[i];
fileName featFileName(dict.lookup("file"));
featureMeshes.set
(
i,
new featureEdgeMesh
(
IOobject
(
featFileName, // name
mesh.time().constant(), // directory
"triSurface", // instance
mesh.db(), // registry
IOobject::MUST_READ,
IOobject::NO_WRITE,
false
)
)
);
featureMeshes[i].mergePoints(meshRefiner_.mergeDistance());
featureLevels[i] = readLabel(dict.lookup("level"));
Info<< "Refinement level " << featureLevels[i]
<< " for all cells crossed by feature " << featFileName
<< " (" << featureMeshes[i].points().size() << " points, "
<< featureMeshes[i].edges().size() << ")." << endl;
}
Info<< "Read feature lines in = "
<< mesh.time().cpuTimeIncrement() << " s" << nl << endl;
return featureMeshes.size();
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
// Construct from components
Foam::autoRefineDriver::autoRefineDriver
(
meshRefinement& meshRefiner,
decompositionMethod& decomposer,
fvMeshDistribute& distributor,
const labelList& globalToPatch
)
:
meshRefiner_(meshRefiner),
decomposer_(decomposer),
distributor_(distributor),
globalToPatch_(globalToPatch)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::label Foam::autoRefineDriver::featureEdgeRefine
(
const refinementParameters& refineParams,
const PtrList<dictionary>& featDicts,
const label maxIter,
const label minRefine
)
{
const fvMesh& mesh = meshRefiner_.mesh();
// Read explicit feature edges
PtrList<featureEdgeMesh> featureMeshes;
// Per feature the refinement level
labelList featureLevels;
readFeatureEdges(featDicts, featureMeshes, featureLevels);
label iter = 0;
if (featureMeshes.size() > 0 && maxIter > 0)
{
for (; iter < maxIter; iter++)
{
Info<< nl
<< "Feature refinement iteration " << iter << nl
<< "------------------------------" << nl
<< endl;
labelList candidateCells
(
meshRefiner_.refineCandidates
(
refineParams.keepPoints()[0], // For now only use one.
refineParams.curvature(),
featureMeshes,
featureLevels,
true, // featureRefinement
false, // internalRefinement
false, // surfaceRefinement
false, // curvatureRefinement
refineParams.maxGlobalCells(),
refineParams.maxLocalCells()
)
);
labelList cellsToRefine
(
meshRefiner_.meshCutter().consistentRefinement
(
candidateCells,
true
)
);
Info<< "Determined cells to refine in = "
<< mesh.time().cpuTimeIncrement() << " s" << endl;
label nCellsToRefine = cellsToRefine.size();
reduce(nCellsToRefine, sumOp<label>());
Info<< "Selected for feature refinement : " << nCellsToRefine
<< " cells (out of " << mesh.globalData().nTotalCells()
<< ')' << endl;
if (nCellsToRefine <= minRefine)
{
Info<< "Stopping refining since too few cells selected."
<< nl << endl;
break;
}
if (debug > 0)
{
const_cast<Time&>(mesh.time())++;
}
meshRefiner_.refineAndBalance
(
"feature refinement iteration " + name(iter),
decomposer_,
distributor_,
cellsToRefine
);
}
}
return iter;
}
Foam::label Foam::autoRefineDriver::surfaceOnlyRefine
(
const refinementParameters& refineParams,
const label maxIter
)
{
const fvMesh& mesh = meshRefiner_.mesh();
// Determine the maximum refinement level over all surfaces. This
// determines the minumum number of surface refinement iterations.
label overallMaxLevel = max(meshRefiner_.surfaces().maxLevel());
label iter;
for (iter = 0; iter < maxIter; iter++)
{
Info<< nl
<< "Surface refinement iteration " << iter << nl
<< "------------------------------" << nl
<< endl;
// Determine cells to refine
// ~~~~~~~~~~~~~~~~~~~~~~~~~
// Only look at surface intersections (minLevel and surface curvature),
// do not do internal refinement (refinementShells)
labelList candidateCells
(
meshRefiner_.refineCandidates
(
refineParams.keepPoints()[0],
refineParams.curvature(),
PtrList<featureEdgeMesh>(0), // dummy featureMeshes;
labelList(0), // dummy featureLevels;
false, // featureRefinement
false, // internalRefinement
true, // surfaceRefinement
true, // curvatureRefinement
refineParams.maxGlobalCells(),
refineParams.maxLocalCells()
)
);
labelList cellsToRefine
(
meshRefiner_.meshCutter().consistentRefinement
(
candidateCells,
true
)
);
Info<< "Determined cells to refine in = "
<< mesh.time().cpuTimeIncrement() << " s" << endl;
label nCellsToRefine = cellsToRefine.size();
reduce(nCellsToRefine, sumOp<label>());
Info<< "Selected for refinement : " << nCellsToRefine
<< " cells (out of " << mesh.globalData().nTotalCells()
<< ')' << endl;
// Stop when no cells to refine or have done minimum nessecary
// iterations and not enough cells to refine.
if
(
nCellsToRefine == 0
|| (
iter >= overallMaxLevel
&& nCellsToRefine <= refineParams.minRefineCells()
)
)
{
Info<< "Stopping refining since too few cells selected."
<< nl << endl;
break;
}
if (debug)
{
const_cast<Time&>(mesh.time())++;
}
meshRefiner_.refineAndBalance
(
"surface refinement iteration " + name(iter),
decomposer_,
distributor_,
cellsToRefine
);
}
return iter;
}
void Foam::autoRefineDriver::removeInsideCells
(
const refinementParameters& refineParams,
const label nBufferLayers
)
{
Info<< nl
<< "Removing mesh beyond surface intersections" << nl
<< "------------------------------------------" << nl
<< endl;
const fvMesh& mesh = meshRefiner_.mesh();
if (debug)
{
const_cast<Time&>(mesh.time())++;
}
meshRefiner_.splitMesh
(
nBufferLayers, // nBufferLayers
globalToPatch_,
refineParams.keepPoints()[0]
);
if (debug)
{
Pout<< "Writing subsetted mesh to time "
<< mesh.time().timeName() << '.' << endl;
meshRefiner_.write(debug, mesh.time().path()/mesh.time().timeName());
Pout<< "Dumped mesh in = "
<< mesh.time().cpuTimeIncrement() << " s\n" << nl << endl;
}
}
Foam::label Foam::autoRefineDriver::shellRefine
(
const refinementParameters& refineParams,
const label maxIter
)
{
const fvMesh& mesh = meshRefiner_.mesh();
// Mark current boundary faces with 0. Have meshRefiner maintain them.
meshRefiner_.userFaceData().setSize(1);
// mark list to remove any refined faces
meshRefiner_.userFaceData()[0].first() = meshRefinement::REMOVE;
meshRefiner_.userFaceData()[0].second() = createWithValues<labelList>
(
mesh.nFaces(),
-1,
meshRefiner_.intersectedFaces(),
0
);
// Determine the maximum refinement level over all volume refinement
// regions. This determines the minumum number of shell refinement
// iterations.
label overallMaxShellLevel = meshRefiner_.shells().maxLevel();
label iter;
for (iter = 0; iter < maxIter; iter++)
{
Info<< nl
<< "Shell refinement iteration " << iter << nl
<< "----------------------------" << nl
<< endl;
labelList candidateCells
(
meshRefiner_.refineCandidates
(
refineParams.keepPoints()[0],
refineParams.curvature(),
PtrList<featureEdgeMesh>(0), // dummy featureMeshes;
labelList(0), // dummy featureLevels;
false, // featureRefinement
true, // internalRefinement
false, // surfaceRefinement
false, // curvatureRefinement
refineParams.maxGlobalCells(),
refineParams.maxLocalCells()
)
);
if (debug)
{
Pout<< "Dumping " << candidateCells.size()
<< " cells to cellSet candidateCellsFromShells." << endl;
cellSet(mesh, "candidateCellsFromShells", candidateCells).write();
}
// Problem choosing starting faces for bufferlayers (bFaces)
// - we can't use the current intersected boundary faces
// (intersectedFaces) since this grows indefinitely
// - if we use 0 faces we don't satisfy bufferLayers from the
// surface.
// - possibly we want to have bFaces only the initial set of faces
// and maintain the list while doing the refinement.
labelList bFaces
(
findIndices(meshRefiner_.userFaceData()[0].second(), 0)
);
//Info<< "Collected boundary faces : "
// << returnReduce(bFaces.size(), sumOp<label>()) << endl;
labelList cellsToRefine;
if (refineParams.nBufferLayers() <= 2)
{
cellsToRefine = meshRefiner_.meshCutter().consistentSlowRefinement
(
refineParams.nBufferLayers(),
candidateCells, // cells to refine
bFaces, // faces for nBufferLayers
1, // point difference
meshRefiner_.intersectedPoints() // points to check
);
}
else
{
cellsToRefine = meshRefiner_.meshCutter().consistentSlowRefinement2
(
refineParams.nBufferLayers(),
candidateCells, // cells to refine
bFaces // faces for nBufferLayers
);
}
Info<< "Determined cells to refine in = "
<< mesh.time().cpuTimeIncrement() << " s" << endl;
label nCellsToRefine = cellsToRefine.size();
reduce(nCellsToRefine, sumOp<label>());
Info<< "Selected for internal refinement : " << nCellsToRefine
<< " cells (out of " << mesh.globalData().nTotalCells()
<< ')' << endl;
// Stop when no cells to refine or have done minimum nessecary
// iterations and not enough cells to refine.
if
(
nCellsToRefine == 0
|| (
iter >= overallMaxShellLevel
&& nCellsToRefine <= refineParams.minRefineCells()
)
)
{
Info<< "Stopping refining since too few cells selected."
<< nl << endl;
break;
}
if (debug)
{
const_cast<Time&>(mesh.time())++;
}
meshRefiner_.refineAndBalance
(
"shell refinement iteration " + name(iter),
decomposer_,
distributor_,
cellsToRefine
);
}
meshRefiner_.userFaceData().clear();
return iter;
}
void Foam::autoRefineDriver::baffleAndSplitMesh
(
const refinementParameters& refineParams,
const bool handleSnapProblems
)
{
Info<< nl
<< "Splitting mesh at surface intersections" << nl
<< "---------------------------------------" << nl
<< endl;
const fvMesh& mesh = meshRefiner_.mesh();
// Introduce baffles at surface intersections. Note:
// meshRefiment::surfaceIndex() will
// be like boundary face from now on so not coupled anymore.
meshRefiner_.baffleAndSplitMesh
(
handleSnapProblems,
!handleSnapProblems, // merge free standing baffles?
const_cast<Time&>(mesh.time()),
globalToPatch_,
refineParams.keepPoints()[0]
);
}
void Foam::autoRefineDriver::zonify
(
const refinementParameters& refineParams
)
{
// Mesh is at its finest. Do zoning
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// This puts all faces with intersection across a zoneable surface
// into that surface's faceZone. All cells inside faceZone get given the
// same cellZone.
if (meshRefiner_.surfaces().getNamedSurfaces().size() > 0)
{
Info<< nl
<< "Introducing zones for interfaces" << nl
<< "--------------------------------" << nl
<< endl;
const fvMesh& mesh = meshRefiner_.mesh();
if (debug)
{
const_cast<Time&>(mesh.time())++;
}
meshRefiner_.zonify(refineParams.keepPoints()[0]);
if (debug)
{
Pout<< "Writing zoned mesh to time "
<< mesh.time().timeName() << '.' << endl;
meshRefiner_.write
(
debug,
mesh.time().path()/mesh.time().timeName()
);
}
// Check that all faces are synced
meshRefinement::checkCoupledFaceZones(mesh);
}
}
void Foam::autoRefineDriver::splitAndMergeBaffles
(
const refinementParameters& refineParams,
const bool handleSnapProblems
)
{
Info<< nl
<< "Handling cells with snap problems" << nl
<< "---------------------------------" << nl
<< endl;
const fvMesh& mesh = meshRefiner_.mesh();
// Introduce baffles and split mesh
if (debug)
{
const_cast<Time&>(mesh.time())++;
}
meshRefiner_.baffleAndSplitMesh
(
handleSnapProblems,
false, // merge free standing baffles?
const_cast<Time&>(mesh.time()),
globalToPatch_,
refineParams.keepPoints()[0]
);
if (debug)
{
const_cast<Time&>(mesh.time())++;
}
// Duplicate points on baffles that are on more than one cell
// region. This will help snapping pull them to separate surfaces.
meshRefiner_.dupNonManifoldPoints();
// Merge all baffles that are still remaining after duplicating points.
List<labelPair> couples
(
meshRefiner_.getDuplicateFaces // get all baffles
(
identity(mesh.nFaces()-mesh.nInternalFaces())
+ mesh.nInternalFaces()
)
);
label nCouples = returnReduce(couples.size(), sumOp<label>());
Info<< "Detected unsplittable baffles : "
<< nCouples << endl;
if (nCouples > 0)
{
// Actually merge baffles. Note: not exactly parallellized. Should
// convert baffle faces into processor faces if they resulted
// from them.
meshRefiner_.mergeBaffles(couples);
if (debug)
{
// Debug:test all is still synced across proc patches
meshRefiner_.checkData();
}
Info<< "Merged free-standing baffles in = "
<< mesh.time().cpuTimeIncrement() << " s." << endl;
}
if (debug)
{
Pout<< "Writing handleProblemCells mesh to time "
<< mesh.time().timeName() << '.' << endl;
meshRefiner_.write(debug, mesh.time().path()/mesh.time().timeName());
}
}
void Foam::autoRefineDriver::mergePatchFaces
(
const refinementParameters& refineParams
)
{
const fvMesh& mesh = meshRefiner_.mesh();
Info<< nl
<< "Merge refined boundary faces" << nl
<< "----------------------------" << nl
<< endl;
if (debug)
{
const_cast<Time&>(mesh.time())++;
}
meshRefiner_.mergePatchFaces
(
Foam::cos(45*mathematicalConstant::pi/180.0),
Foam::cos(45*mathematicalConstant::pi/180.0),
meshRefinement::addedPatches(globalToPatch_)
);
if (debug)
{
meshRefiner_.checkData();
}
meshRefiner_.mergeEdges(Foam::cos(45*mathematicalConstant::pi/180.0));
if (debug)
{
meshRefiner_.checkData();
}
}
void Foam::autoRefineDriver::doRefine
(
const dictionary& refineDict,
const refinementParameters& refineParams,
const bool prepareForSnapping
)
{
Info<< nl
<< "Refinement phase" << nl
<< "----------------" << nl
<< endl;
const fvMesh& mesh = meshRefiner_.mesh();
const_cast<Time&>(mesh.time())++;
// Check that all the keep points are inside the mesh.
refineParams.findCells(mesh);
PtrList<dictionary> featDicts(refineDict.lookup("features"));
// Refine around feature edges
featureEdgeRefine
(
refineParams,
featDicts,
100, // maxIter
0 // min cells to refine
);
// Refine based on surface
surfaceOnlyRefine
(
refineParams,
100 // maxIter
);
// Remove cells (a certain distance) beyond surface intersections
removeInsideCells
(
refineParams,
1 // nBufferLayers
);
// Internal mesh refinement
shellRefine
(
refineParams,
100 // maxIter
);
// Introduce baffles at surface intersections
baffleAndSplitMesh(refineParams, prepareForSnapping);
// Mesh is at its finest. Do optional zoning.
zonify(refineParams);
// Pull baffles apart
splitAndMergeBaffles(refineParams, prepareForSnapping);
// Do something about cells with refined faces on the boundary
if (prepareForSnapping)
{
mergePatchFaces(refineParams);
}
if (Pstream::parRun())
{
Info<< nl
<< "Doing final balancing" << nl
<< "---------------------" << nl
<< endl;
if (debug)
{
const_cast<Time&>(mesh.time())++;
}
// Do final balancing. Keep zoned faces on one processor.
meshRefiner_.balance
(
true,
false,
decomposer_,
distributor_
);
}
}
// ************************************************************************* //

View File

@ -0,0 +1,179 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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::autoRefineDriver
Description
SourceFiles
autoRefineDriver.C
\*---------------------------------------------------------------------------*/
#ifndef autoRefineDriver_H
#define autoRefineDriver_H
#include "meshRefinement.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declaration of classes
class featureEdgeMesh;
class refinementParameters;
/*---------------------------------------------------------------------------*\
Class autoRefineDriver Declaration
\*---------------------------------------------------------------------------*/
class autoRefineDriver
{
// Private data
//- Mesh+surface
meshRefinement& meshRefiner_;
//- Reference to decomposition method
decompositionMethod& decomposer_;
//- Reference to mesh distribution engine
fvMeshDistribute& distributor_;
//- From surface region to patch
const labelList globalToPatch_;
// Private Member Functions
//- Read explicit feature edges
label readFeatureEdges
(
const PtrList<dictionary>& featDicts,
PtrList<featureEdgeMesh>& featureMeshes,
labelList& featureLevel
) const;
//- Refine all cells pierced by explicit feature edges
label featureEdgeRefine
(
const refinementParameters& refineParams,
const PtrList<dictionary>& featDicts,
const label maxIter,
const label minRefine
);
//- Refine all cells interacting with the surface
label surfaceOnlyRefine
(
const refinementParameters& refineParams,
const label maxIter
);
//- Remove all cells within intersected region
void removeInsideCells
(
const refinementParameters& refineParams,
const label nBufferLayers
);
//- Remove all cells inside/outside shell
label shellRefine
(
const refinementParameters& refineParams,
const label maxIter
);
//- Add baffles and remove unreachable cells
void baffleAndSplitMesh
(
const refinementParameters& refineParams,
const bool handleSnapProblems
);
//- Add zones
void zonify(const refinementParameters& refineParams);
void splitAndMergeBaffles
(
const refinementParameters& refineParams,
const bool handleSnapProblems
);
//- Merge refined boundary faces (from exposing coarser cell)
void mergePatchFaces
(
const refinementParameters& refineParams
);
//- Disallow default bitwise copy construct
autoRefineDriver(const autoRefineDriver&);
//- Disallow default bitwise assignment
void operator=(const autoRefineDriver&);
public:
//- Runtime type information
ClassName("autoRefineDriver");
// Constructors
//- Construct from components
autoRefineDriver
(
meshRefinement& meshRefiner,
decompositionMethod& decomposer,
fvMeshDistribute& distributor,
const labelList& globalToPatch
);
// Member Functions
//- Do all the refinement
void doRefine
(
const dictionary& refineDict,
const refinementParameters& refineParams,
const bool prepareForSnapping
);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -27,7 +27,12 @@ Description
\*----------------------------------------------------------------------------*/
#include "autoHexMeshDriver.H"
#include "autoSnapDriver.H"
#include "Time.H"
#include "pointFields.H"
#include "motionSmoother.H"
#include "polyTopoChange.H"
#include "OFstream.H"
#include "syncTools.H"
#include "fvMesh.H"
#include "Time.H"
@ -37,16 +42,29 @@ Description
#include "pointEdgePoint.H"
#include "PointEdgeWave.H"
#include "mergePoints.H"
#include "snapParameters.H"
#include "refinementSurfaces.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(autoSnapDriver, 0);
} // End namespace Foam
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::autoHexMeshDriver::getZonedSurfaces
void Foam::autoSnapDriver::getZonedSurfaces
(
labelList& zonedSurfaces,
labelList& unzonedSurfaces
) const
{ // Surfaces with zone information
const wordList& faceZoneNames = surfaces().faceZoneNames();
const wordList& faceZoneNames = meshRefiner_.surfaces().faceZoneNames();
zonedSurfaces.setSize(faceZoneNames.size());
label zonedI = 0;
@ -70,15 +88,18 @@ void Foam::autoHexMeshDriver::getZonedSurfaces
// Get faces to repatch. Returns map from face to patch.
Foam::Map<Foam::label> Foam::autoHexMeshDriver::getZoneBafflePatches
Foam::Map<Foam::label> Foam::autoSnapDriver::getZoneBafflePatches
(
const bool allowBoundary
) const
{
Map<label> bafflePatch(mesh_.nFaces()/1000);
const fvMesh& mesh = meshRefiner_.mesh();
const refinementSurfaces& surfaces = meshRefiner_.surfaces();
const wordList& faceZoneNames = surfaces().faceZoneNames();
const faceZoneMesh& fZones = mesh_.faceZones();
Map<label> bafflePatch(mesh.nFaces()/1000);
const wordList& faceZoneNames = surfaces.faceZoneNames();
const faceZoneMesh& fZones = mesh.faceZones();
forAll(faceZoneNames, surfI)
{
@ -92,13 +113,12 @@ Foam::Map<Foam::label> Foam::autoHexMeshDriver::getZoneBafflePatches
//// Get patch allocated for zone
//label patchI = surfaceToCyclicPatch_[surfI];
// Get patch of (first region) of surface
label patchI = globalToPatch_[surfaces().globalRegion(surfI, 0)];
label patchI = globalToPatch_[surfaces.globalRegion(surfI, 0)];
Info<< "For surface "
<< surfaces()[surfI].IOobject::name()
//<< surfaces().names()[surfI]
<< surfaces.names()[surfI]
<< " found faceZone " << fZone.name()
<< " and patch " << mesh_.boundaryMesh()[patchI].name()
<< " and patch " << mesh.boundaryMesh()[patchI].name()
<< endl;
@ -106,7 +126,7 @@ Foam::Map<Foam::label> Foam::autoHexMeshDriver::getZoneBafflePatches
{
label faceI = fZone[i];
if (allowBoundary || mesh_.isInternalFace(faceI))
if (allowBoundary || mesh.isInternalFace(faceI))
{
if (!bafflePatch.insert(faceI, patchI))
{
@ -116,11 +136,11 @@ Foam::Map<Foam::label> Foam::autoHexMeshDriver::getZoneBafflePatches
{
FatalErrorIn("getZoneBafflePatches(const bool)")
<< "Face " << faceI
<< " fc:" << mesh_.faceCentres()[faceI]
<< " fc:" << mesh.faceCentres()[faceI]
<< " is in faceZone "
<< mesh_.boundaryMesh()[oldPatchI].name()
<< mesh.boundaryMesh()[oldPatchI].name()
<< " and in faceZone "
<< mesh_.boundaryMesh()[patchI].name()
<< mesh.boundaryMesh()[patchI].name()
<< abort(FatalError);
}
}
@ -134,7 +154,7 @@ Foam::Map<Foam::label> Foam::autoHexMeshDriver::getZoneBafflePatches
// Calculate geometrically collocated points, Requires PackedList to be
// sizes and initalised!
Foam::label Foam::autoHexMeshDriver::getCollocatedPoints
Foam::label Foam::autoSnapDriver::getCollocatedPoints
(
const scalar tol,
const pointField& points,
@ -196,7 +216,7 @@ Foam::label Foam::autoHexMeshDriver::getCollocatedPoints
// Calculate displacement as average of patch points.
Foam::pointField Foam::autoHexMeshDriver::smoothPatchDisplacement
Foam::pointField Foam::autoSnapDriver::smoothPatchDisplacement
(
const motionSmoother& meshMover
) const
@ -483,7 +503,7 @@ Foam::pointField Foam::autoHexMeshDriver::smoothPatchDisplacement
}
Foam::tmp<Foam::scalarField> Foam::autoHexMeshDriver::edgePatchDist
Foam::tmp<Foam::scalarField> Foam::autoSnapDriver::edgePatchDist
(
const pointMesh& pMesh,
const indirectPrimitivePatch& pp
@ -565,7 +585,7 @@ Foam::tmp<Foam::scalarField> Foam::autoHexMeshDriver::edgePatchDist
}
void Foam::autoHexMeshDriver::dumpMove
void Foam::autoSnapDriver::dumpMove
(
const fileName& fName,
const pointField& meshPts,
@ -596,7 +616,7 @@ void Foam::autoHexMeshDriver::dumpMove
// Check whether all displacement vectors point outwards of patch. Return true
// if so.
bool Foam::autoHexMeshDriver::outwardsDisplacement
bool Foam::autoSnapDriver::outwardsDisplacement
(
const indirectPrimitivePatch& pp,
const vectorField& patchDisp
@ -637,9 +657,22 @@ bool Foam::autoHexMeshDriver::outwardsDisplacement
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::autoSnapDriver::autoSnapDriver
(
meshRefinement& meshRefiner,
const labelList& globalToPatch
)
:
meshRefiner_(meshRefiner),
globalToPatch_(globalToPatch)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::autoPtr<Foam::mapPolyMesh> Foam::autoHexMeshDriver::createZoneBaffles
Foam::autoPtr<Foam::mapPolyMesh> Foam::autoSnapDriver::createZoneBaffles
(
List<labelPair>& baffles
)
@ -653,6 +686,8 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::autoHexMeshDriver::createZoneBaffles
// No need to sync; all processors will have all same zonedSurfaces.
if (zonedSurfaces.size() > 0)
{
fvMesh& mesh = meshRefiner_.mesh();
// Split internal faces on interface surfaces
Info<< "Converting zoned faces into baffles ..." << endl;
@ -664,14 +699,14 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::autoHexMeshDriver::createZoneBaffles
if (nZoneFaces > 0)
{
// Convert into labelLists
labelList ownPatch(mesh_.nFaces(), -1);
labelList ownPatch(mesh.nFaces(), -1);
forAllConstIter(Map<label>, faceToPatch, iter)
{
ownPatch[iter.key()] = iter();
}
// Create baffles. both sides same patch.
map = meshRefinerPtr_().createBaffles(ownPatch, ownPatch);
map = meshRefiner_.createBaffles(ownPatch, ownPatch);
// Get pairs of faces created.
// Just loop over faceMap and store baffle if we encounter a slave
@ -702,29 +737,29 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::autoHexMeshDriver::createZoneBaffles
if (baffleI != faceToPatch.size())
{
FatalErrorIn("autoHexMeshDriver::createZoneBaffles(..)")
FatalErrorIn("autoSnapDriver::createZoneBaffles(..)")
<< "Had " << faceToPatch.size() << " patches to create "
<< " but encountered " << baffleI
<< " slave faces originating from patcheable faces."
<< abort(FatalError);
}
if (debug_)
if (debug)
{
const_cast<Time&>(mesh_.time())++;
Pout<< "Writing baffled mesh to time " << mesh_.time().timeName()
<< endl;
mesh_.write();
const_cast<Time&>(mesh.time())++;
Pout<< "Writing baffled mesh to time "
<< mesh.time().timeName() << endl;
mesh.write();
}
}
Info<< "Created " << nZoneFaces << " baffles in = "
<< mesh_.time().cpuTimeIncrement() << " s\n" << nl << endl;
<< mesh.time().cpuTimeIncrement() << " s\n" << nl << endl;
}
return map;
}
Foam::autoPtr<Foam::mapPolyMesh> Foam::autoHexMeshDriver::mergeZoneBaffles
Foam::autoPtr<Foam::mapPolyMesh> Foam::autoSnapDriver::mergeZoneBaffles
(
const List<labelPair>& baffles
)
@ -743,29 +778,27 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::autoHexMeshDriver::mergeZoneBaffles
Info<< "Converting " << nBaffles << " baffles back into zoned faces ..."
<< endl;
map = meshRefinerPtr_().mergeBaffles(baffles);
map = meshRefiner_.mergeBaffles(baffles);
Info<< "Converted baffles in = "
<< mesh_.time().cpuTimeIncrement() << " s\n" << nl << endl;
<< meshRefiner_.mesh().time().cpuTimeIncrement()
<< " s\n" << nl << endl;
}
return map;
}
Foam::scalarField Foam::autoHexMeshDriver::calcSnapDistance
Foam::scalarField Foam::autoSnapDriver::calcSnapDistance
(
const dictionary& snapDict,
const snapParameters& snapParams,
const indirectPrimitivePatch& pp
) const
{
// When to snap
scalar snapTol(readScalar(snapDict.lookup("snapTol")));
const edgeList& edges = pp.edges();
const labelListList& pointEdges = pp.pointEdges();
const pointField& localPoints = pp.localPoints();
const fvMesh& mesh = meshRefiner_.mesh();
scalarField maxEdgeLen(localPoints.size(), -GREAT);
@ -785,7 +818,7 @@ Foam::scalarField Foam::autoHexMeshDriver::calcSnapDistance
syncTools::syncPointList
(
mesh_,
mesh,
pp.meshPoints(),
maxEdgeLen,
maxEqOp<scalar>(), // combine op
@ -793,57 +826,61 @@ Foam::scalarField Foam::autoHexMeshDriver::calcSnapDistance
false // no separation
);
return snapTol*maxEdgeLen;
return snapParams.snapTol()*maxEdgeLen;
}
// Invert globalToPatch_ to get the patches related to surfaces.
Foam::labelList Foam::autoHexMeshDriver::getSurfacePatches() const
{
// Set of patches originating from surface
labelHashSet surfacePatchSet(surfaces().size());
forAll(globalToPatch_, i)
{
if (globalToPatch_[i] != -1)
{
surfacePatchSet.insert(globalToPatch_[i]);
}
}
DynamicList<label> surfacePatches(surfacePatchSet.size());
for (label patchI = 0; patchI < mesh_.boundaryMesh().size(); patchI++)
{
if (surfacePatchSet.found(patchI))
{
surfacePatches.append(patchI);
}
}
return surfacePatches.shrink();
}
//// Invert globalToPatch_ to get the patches related to surfaces.
//Foam::labelList Foam::autoSnapDriver::getSurfacePatches() const
//{
// // Set of patches originating from surface
// labelHashSet surfacePatchSet(globalToPatch_.size());
//
// forAll(globalToPatch_, i)
// {
// if (globalToPatch_[i] != -1)
// {
// surfacePatchSet.insert(globalToPatch_[i]);
// }
// }
//
// const fvMesh& mesh = meshRefiner_.mesh();
//
// DynamicList<label> surfacePatches(surfacePatchSet.size());
//
// for (label patchI = 0; patchI < mesh.boundaryMesh().size(); patchI++)
// {
// if (surfacePatchSet.found(patchI))
// {
// surfacePatches.append(patchI);
// }
// }
// return surfacePatches.shrink();
//}
void Foam::autoHexMeshDriver::preSmoothPatch
void Foam::autoSnapDriver::preSmoothPatch
(
const dictionary& snapDict,
const snapParameters& snapParams,
const label nInitErrors,
const List<labelPair>& baffles,
motionSmoother& meshMover
) const
{
// Smoothing iterations
label nSmoothPatch(readLabel(snapDict.lookup("nSmoothPatch")));
// Snapping iterations
label nSnap(readLabel(snapDict.lookup("nSnap")));
const fvMesh& mesh = meshRefiner_.mesh();
labelList checkFaces;
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;
checkFaces.setSize(mesh_.nFaces());
checkFaces.setSize(mesh.nFaces());
forAll(checkFaces, faceI)
{
checkFaces[faceI] = faceI;
@ -857,11 +894,11 @@ void Foam::autoHexMeshDriver::preSmoothPatch
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;
if (snapIter == nSnap)
if (snapIter == snapParams.nSnap())
{
Info<< "Displacement scaling for error reduction set to 0."
<< endl;
@ -888,20 +925,72 @@ void Foam::autoHexMeshDriver::preSmoothPatch
// The current mesh is the starting mesh to smooth from.
meshMover.correct();
if (debug_)
if (debug)
{
const_cast<Time&>(mesh_.time())++;
Pout<< "Writing patch smoothed mesh to time " << mesh_.time().timeName()
const_cast<Time&>(mesh.time())++;
Pout<< "Writing patch smoothed mesh to time " << mesh.time().timeName()
<< endl;
mesh_.write();
mesh.write();
}
Info<< "Patch points smoothed in = "
<< mesh_.time().cpuTimeIncrement() << " s\n" << nl << endl;
<< mesh.time().cpuTimeIncrement() << " s\n" << nl << endl;
}
Foam::vectorField Foam::autoHexMeshDriver::calcNearestSurface
// Get (pp-local) indices of points that are both on zone and on patched surface
Foam::labelList Foam::autoSnapDriver::getZoneSurfacePoints
(
const indirectPrimitivePatch& pp,
const word& zoneName
) const
{
const fvMesh& mesh = meshRefiner_.mesh();
label zoneI = mesh.faceZones().findZoneID(zoneName);
if (zoneI == -1)
{
FatalErrorIn
(
"autoSnapDriver::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::autoSnapDriver::calcNearestSurface
(
const scalarField& snapDist,
motionSmoother& meshMover
@ -912,6 +1001,8 @@ Foam::vectorField Foam::autoHexMeshDriver::calcNearestSurface
const indirectPrimitivePatch& pp = meshMover.patch();
const pointField& localPoints = pp.localPoints();
const refinementSurfaces& surfaces = meshRefiner_.surfaces();
const fvMesh& mesh = meshRefiner_.mesh();
// Divide surfaces into zoned and unzoned
labelList zonedSurfaces;
@ -925,38 +1016,45 @@ Foam::vectorField Foam::autoHexMeshDriver::calcNearestSurface
// 1. All points to non-interface surfaces
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
forAll(localPoints, pointI)
{
pointIndexHit pHit;
label surfI = surfaces().findNearest
List<pointIndexHit> hitInfo;
labelList hitSurface;
surfaces.findNearest
(
unzonedSurfaces,
localPoints[pointI],
sqr(4*snapDist[pointI]), // sqr of attract distance
pHit
localPoints,
sqr(4*snapDist), // sqr of attract distance
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(..)")
// WarningIn("autoSnapDriver::calcNearestSurface(..)")
// << "For point:" << pointI
// << " coordinate:" << localPoints[pointI]
// << " did not find any surface within:" << 4*snapDist[pointI]
// << " did not find any surface within:"
// << 4*snapDist[pointI]
// << " meter." << endl;
//}
}
}
// 2. All points on zones to their respective surface
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Surfaces with zone information
const wordList& faceZoneNames = surfaces().faceZoneNames();
const wordList& faceZoneNames = surfaces.faceZoneNames();
forAll(zonedSurfaces, i)
{
@ -964,43 +1062,45 @@ Foam::vectorField Foam::autoHexMeshDriver::calcNearestSurface
const labelList surfacesToTest(1, zoneSurfI);
label zoneI = mesh_.faceZones().findZoneID(faceZoneNames[zoneSurfI]);
const faceZone& fZone = mesh_.faceZones()[zoneI];
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();
pointIndexHit pHit;
label surfI = surfaces().findNearest
// Get indices of points both on faceZone and on pp.
labelList zonePointIndices
(
surfacesToTest,
localPoints[pointI],
sqr(4*snapDist[pointI]), // sqr of attract distance
pHit
getZoneSurfacePoints
(
pp,
faceZoneNames[zoneSurfI]
)
);
if (surfI != -1)
pointField zonePoints(zonePointIndices.size());
forAll(zonePointIndices, i)
{
zonePoints[i] = localPoints[zonePointIndices[i]];
}
// 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())
{
patchDisp[pointI] =
pHit.hitPoint() - localPoints[pointI];
hitInfo[pointI].hitPoint()
- localPoints[pointI];
}
else
{
WarningIn("autoHexMeshDriver::calcNearestSurface(..)")
WarningIn("autoSnapDriver::calcNearestSurface(..)")
<< "For point:" << pointI
<< " coordinate:" << localPoints[pointI]
<< " did not find any surface within:"
@ -1009,8 +1109,6 @@ Foam::vectorField Foam::autoHexMeshDriver::calcNearestSurface
}
}
}
}
}
{
@ -1023,7 +1121,7 @@ Foam::vectorField Foam::autoHexMeshDriver::calcNearestSurface
}
Info<< "Calculated surface displacement in = "
<< mesh_.time().cpuTimeIncrement() << " s\n" << nl << endl;
<< mesh.time().cpuTimeIncrement() << " s\n" << nl << endl;
// Limit amount of movement.
@ -1045,7 +1143,7 @@ Foam::vectorField Foam::autoHexMeshDriver::calcNearestSurface
// will not do condition 2 on all. Sync explicitly.
syncTools::syncPointList
(
mesh_,
mesh,
pp.meshPoints(),
patchDisp,
minMagEqOp(), // combine op
@ -1062,11 +1160,11 @@ Foam::vectorField Foam::autoHexMeshDriver::calcNearestSurface
// pointVectorField.
meshMover.setDisplacement(patchDisp);
if (debug_)
if (debug)
{
dumpMove
(
mesh_.time().path()/"patchDisplacement.obj",
mesh.time().path()/"patchDisplacement.obj",
pp.localPoints(),
pp.localPoints() + patchDisp
);
@ -1076,29 +1174,27 @@ Foam::vectorField Foam::autoHexMeshDriver::calcNearestSurface
}
void Foam::autoHexMeshDriver::smoothDisplacement
void Foam::autoSnapDriver::smoothDisplacement
(
const dictionary& snapDict,
const snapParameters& snapParams,
motionSmoother& meshMover
) const
{
const fvMesh& mesh = meshRefiner_.mesh();
const pointMesh& pMesh = meshMover.pMesh();
const indirectPrimitivePatch& pp = meshMover.patch();
Info<< "Smoothing displacement ..." << endl;
// Smoothing iterations
label nSmoothDisp(readLabel(snapDict.lookup("nSmoothDispl")));
// Set edge diffusivity as inverse of distance to patch
scalarField edgeGamma(1.0/(edgePatchDist(pMesh, pp) + SMALL));
//scalarField edgeGamma(mesh_.nEdges(), 1.0);
//scalarField edgeGamma(mesh.nEdges(), 1.0);
//scalarField edgeGamma(wallGamma(mesh, pp, 10, 1));
// Get displacement field
pointVectorField& disp = meshMover.displacement();
for (label iter = 0; iter < nSmoothDisp; iter++)
for (label iter = 0; iter < snapParams.nSmoothDispl(); iter++)
{
if ((iter % 10) == 0)
{
@ -1109,14 +1205,14 @@ void Foam::autoHexMeshDriver::smoothDisplacement
meshMover.smooth(oldDisp, edgeGamma, false, disp);
}
Info<< "Displacement smoothed in = "
<< mesh_.time().cpuTimeIncrement() << " s\n" << nl << endl;
<< mesh.time().cpuTimeIncrement() << " s\n" << nl << endl;
if (debug_)
if (debug)
{
const_cast<Time&>(mesh_.time())++;
Pout<< "Writing smoothed mesh to time " << mesh_.time().timeName()
const_cast<Time&>(mesh.time())++;
Pout<< "Writing smoothed mesh to time " << mesh.time().timeName()
<< endl;
mesh_.write();
mesh.write();
Pout<< "Writing displacement field ..." << endl;
disp.write();
@ -1130,7 +1226,7 @@ void Foam::autoHexMeshDriver::smoothDisplacement
);
dumpMove
(
mesh_.time().path()/"actualPatchDisplacement.obj",
mesh.time().path()/"actualPatchDisplacement.obj",
pp.localPoints(),
pp.localPoints() + actualPatchDisp
);
@ -1138,30 +1234,28 @@ void Foam::autoHexMeshDriver::smoothDisplacement
}
void Foam::autoHexMeshDriver::scaleMesh
void Foam::autoSnapDriver::scaleMesh
(
const dictionary& snapDict,
const snapParameters& snapParams,
const label nInitErrors,
const List<labelPair>& baffles,
motionSmoother& meshMover
)
{
// Snapping iterations
label nSnap(readLabel(snapDict.lookup("nSnap")));
const fvMesh& mesh = meshRefiner_.mesh();
// Relax displacement until correct mesh
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
labelList checkFaces(identity(mesh_.nFaces()));
labelList checkFaces(identity(mesh.nFaces()));
scalar oldErrorReduction = -1;
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;
if (iter == nSnap)
if (iter == snapParams.nSnap())
{
Info<< "Displacement scaling for error reduction set to 0." << endl;
oldErrorReduction = meshMover.setErrorReduction(0.0);
@ -1173,12 +1267,12 @@ void Foam::autoHexMeshDriver::scaleMesh
break;
}
if (debug_)
if (debug)
{
const_cast<Time&>(mesh_.time())++;
Pout<< "Writing scaled mesh to time " << mesh_.time().timeName()
const_cast<Time&>(mesh.time())++;
Pout<< "Writing scaled mesh to time " << mesh.time().timeName()
<< endl;
mesh_.write();
mesh.write();
Pout<< "Writing displacement field ..." << endl;
meshMover.displacement().write();
@ -1192,7 +1286,99 @@ void Foam::autoHexMeshDriver::scaleMesh
meshMover.setErrorReduction(oldErrorReduction);
}
Info<< "Moved mesh in = "
<< mesh_.time().cpuTimeIncrement() << " s\n" << nl << endl;
<< mesh.time().cpuTimeIncrement() << " s\n" << nl << endl;
}
void Foam::autoSnapDriver::doSnap
(
const dictionary& snapDict,
const dictionary& motionDict,
const snapParameters& snapParams
)
{
fvMesh& mesh = meshRefiner_.mesh();
Info<< nl
<< "Morphing phase" << nl
<< "--------------" << nl
<< endl;
const_cast<Time&>(mesh.time())++;
// Get the labels of added patches.
labelList adaptPatchIDs(meshRefinement::addedPatches(globalToPatch_));
// Create baffles (pairs of faces that share the same points)
// Baffles stored as owner and neighbour face that have been created.
List<labelPair> baffles;
createZoneBaffles(baffles);
{
autoPtr<indirectPrimitivePatch> ppPtr
(
meshRefinement::makePatch
(
mesh,
adaptPatchIDs
)
);
indirectPrimitivePatch& pp = ppPtr();
// Distance to attact to nearest feature on surface
const scalarField snapDist(calcSnapDistance(snapParams, pp));
// Construct iterative mesh mover.
Info<< "Constructing mesh displacer ..." << endl;
Info<< "Using mesh parameters " << motionDict << nl << endl;
pointMesh pMesh(mesh);
motionSmoother meshMover
(
mesh,
pp,
adaptPatchIDs,
meshRefinement::makeDisplacementField(pMesh, adaptPatchIDs),
motionDict
);
// Check initial mesh
Info<< "Checking initial mesh ..." << endl;
labelHashSet wrongFaces(mesh.nFaces()/100);
motionSmoother::checkMesh(false, mesh, motionDict, wrongFaces);
const label nInitErrors = returnReduce
(
wrongFaces.size(),
sumOp<label>()
);
Info<< "Detected " << nInitErrors << " illegal faces"
<< " (concave, zero area or negative cell pyramid volume)"
<< endl;
Info<< "Checked initial mesh in = "
<< mesh.time().cpuTimeIncrement() << " s\n" << nl << endl;
// Pre-smooth patch vertices (so before determining nearest)
preSmoothPatch(snapParams, nInitErrors, baffles, meshMover);
// Calculate displacement at every patch point. Insert into
// meshMover.
calcNearestSurface(snapDist, meshMover);
// Get smoothly varying internal displacement field.
smoothDisplacement(snapParams, meshMover);
// Apply internal displacement to mesh.
scaleMesh(snapParams, nInitErrors, baffles, meshMover);
}
// Merge any introduced baffles.
mergeZoneBaffles(baffles);
}

View File

@ -0,0 +1,236 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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::autoSnapDriver
Description
All to do with snapping to surface
SourceFiles
autoSnapDriver.C
\*---------------------------------------------------------------------------*/
#ifndef autoSnapDriver_H
#define autoSnapDriver_H
#include "meshRefinement.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declaration of classes
class motionSmoother;
class snapParameters;
/*---------------------------------------------------------------------------*\
Class autoSnapDriver Declaration
\*---------------------------------------------------------------------------*/
class autoSnapDriver
{
// Private classes
//- Combine operator class for equalizing displacements.
class minMagEqOp
{
public:
void operator()(vector& x, const vector& y) const
{
if (magSqr(y) < magSqr(x))
{
x = y;
}
}
};
// Private data
//- Mesh+surface
meshRefinement& meshRefiner_;
//- From surface region to patch
const labelList globalToPatch_;
// Private Member Functions
// Snapping
//- Split surfaces into non-zoned and zones ones
void getZonedSurfaces(labelList&, labelList&) const;
//- Get faces to repatch. Returns map from face to patch.
Map<label> getZoneBafflePatches(const bool allowBoundary) const;
//- Calculates (geometric) shared points
static label getCollocatedPoints
(
const scalar tol,
const pointField&,
PackedList<1>&
);
//- Calculate displacement per patch point to smooth out patch.
// Quite complicated in determining which points to move where.
pointField smoothPatchDisplacement(const motionSmoother&) const;
//- Check that face zones are synced
void checkCoupledFaceZones() const;
//- Per edge distance to patch
static tmp<scalarField> edgePatchDist
(
const pointMesh&,
const indirectPrimitivePatch&
);
//- Write displacement as .obj file.
static void dumpMove
(
const fileName&,
const pointField&,
const pointField&
);
//- Check displacement is outwards pointing
static bool outwardsDisplacement
(
const indirectPrimitivePatch&,
const vectorField&
);
//- Disallow default bitwise copy construct
autoSnapDriver(const autoSnapDriver&);
//- Disallow default bitwise assignment
void operator=(const autoSnapDriver&);
public:
//- Runtime type information
ClassName("autoSnapDriver");
// Constructors
//- Construct from components
autoSnapDriver
(
meshRefinement& meshRefiner,
const labelList& globalToPatch
);
// Member Functions
// Snapping
//- Create baffles for faces straddling zoned surfaces. Return
// baffles.
autoPtr<mapPolyMesh> createZoneBaffles(List<labelPair>&);
//- Merge baffles.
autoPtr<mapPolyMesh> mergeZoneBaffles(const List<labelPair>&);
//- Calculate edge length per patch point.
scalarField calcSnapDistance
(
const snapParameters& snapParams,
const indirectPrimitivePatch&
) const;
////- Get patches generated for surfaces.
//labelList getSurfacePatches() const;
//- Smooth the mesh (patch and internal) to increase visibility
// of surface points (on castellated mesh) w.r.t. surface.
void preSmoothPatch
(
const snapParameters& snapParams,
const label nInitErrors,
const List<labelPair>& baffles,
motionSmoother&
) 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
// boundary conditions of motionSmoother displacement field. Return
// displacement of patch points.
vectorField calcNearestSurface
(
const scalarField& snapDist,
motionSmoother& meshMover
) const;
//- Smooth the displacement field to the internal.
void smoothDisplacement
(
const snapParameters& snapParams,
motionSmoother&
) const;
//- Do the hard work: move the mesh according to displacement,
// locally relax the displacement.
void scaleMesh
(
const snapParameters& snapParams,
const label nInitErrors,
const List<labelPair>& baffles,
motionSmoother&
);
void doSnap
(
const dictionary& snapDict,
const dictionary& motionDict,
const snapParameters& snapParams
);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,327 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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"
#include "refinementSurfaces.H"
#include "searchableSurfaces.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
const Foam::scalar Foam::layerParameters::defaultConcaveAngle = 90;
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
// Read the number of layers from dictionary. Per patch 0 or the number
// of layers.
Foam::labelList Foam::layerParameters::readNumLayers
(
const PtrList<dictionary>& surfaceDicts,
const refinementSurfaces& refineSurfaces,
const labelList& globalToPatch,
const polyBoundaryMesh& boundaryMesh
)
{
// Per surface the number of layers
labelList globalSurfLayers(surfaceDicts.size());
// Per surface, per region the number of layers
List<Map<label> > regionSurfLayers(surfaceDicts.size());
const labelList& surfaceIndices = refineSurfaces.surfaces();
forAll(surfaceDicts, surfI)
{
const dictionary& dict = surfaceDicts[surfI];
globalSurfLayers[surfI] = readLabel(dict.lookup("surfaceLayers"));
if (dict.found("regions"))
{
// Per-region layer information
PtrList<dictionary> regionDicts(dict.lookup("regions"));
const wordList& regionNames =
refineSurfaces.geometry()[surfaceIndices[surfI]].regions();
forAll(regionDicts, dictI)
{
const dictionary& regionDict = regionDicts[dictI];
const word regionName(regionDict.lookup("name"));
label regionI = findIndex(regionNames, regionName);
label nLayers = readLabel(regionDict.lookup("surfaceLayers"));
Info<< " region " << regionName << ':'<< nl
<< " surface layers:" << nLayers << nl;
regionSurfLayers[surfI].insert(regionI, nLayers);
}
}
}
// Transfer per surface/region information into patchwise region info
labelList nLayers(boundaryMesh.size(), 0);
forAll(surfaceIndices, surfI)
{
const wordList& regionNames =
refineSurfaces.geometry()[surfaceIndices[surfI]].regions();
forAll(regionNames, regionI)
{
const word& regionName = regionNames[regionI];
label global = refineSurfaces.globalRegion(surfI, regionI);
label patchI = globalToPatch[global];
// Initialise to surface-wise layers
nLayers[patchI] = globalSurfLayers[surfI];
// Override with region specific data if available
Map<label>::const_iterator iter =
regionSurfLayers[surfI].find(regionI);
if (iter != regionSurfLayers[surfI].end())
{
nLayers[patchI] = iter();
}
// Check
if (nLayers[patchI] < 0)
{
FatalErrorIn
(
"layerParameters::readNumLayers(..)"
) << "Illegal number of layers " << nLayers[patchI]
<< " for surface "
<< refineSurfaces.names()[surfI]
<< " region " << regionName << endl
<< exit(FatalError);
}
}
}
return nLayers;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
// Construct from dictionary
Foam::layerParameters::layerParameters
(
const PtrList<dictionary>& surfaceDicts,
const refinementSurfaces& refineSurfaces,
const labelList& globalToPatch,
const dictionary& dict,
const polyBoundaryMesh& boundaryMesh
)
:
numLayers_
(
readNumLayers
(
surfaceDicts,
refineSurfaces,
globalToPatch,
boundaryMesh
)
),
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 * * * * * * * * * * * * * //
// ************************************************************************* //

View File

@ -0,0 +1,263 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 refinementSurfaces;
/*---------------------------------------------------------------------------*\
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
//- Extract patch-wise number of layers
static labelList readNumLayers
(
const PtrList<dictionary>& surfaceDicts,
const refinementSurfaces& refineSurfaces,
const labelList& globalToPatch,
const polyBoundaryMesh& boundaryMesh
);
//- 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 PtrList<dictionary>& surfaceDicts,
const refinementSurfaces& refineSurfaces,
const labelList& globalToPatch,
const dictionary& dict,
const polyBoundaryMesh& boundaryMesh
);
//- 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
// ************************************************************************* //

View File

@ -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;
}
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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 * * * * * * * * * * * * * //
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

File diff suppressed because it is too large Load Diff

View File

@ -30,7 +30,7 @@ Description
(static) surfaces.
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
meshRefinement.C
@ -62,6 +62,7 @@ class fvMesh;
class mapDistributePolyMesh;
class decompositionMethod;
class refinementSurfaces;
class shellSurfaces;
class removeCells;
class featureEdgeMesh;
class fvMeshDistribute;
@ -93,7 +94,7 @@ public:
{
MASTERONLY = 1, /*!< maintain master only */
KEEPALL = 2, /*!< have slaves (upon refinement) from master */
REMOVE = 4 /*!< set value to -1 any face that has been refined */
REMOVE = 4 /*!< set value to -1 any face that was refined */
};
@ -105,10 +106,14 @@ private:
fvMesh& mesh_;
//- tolerance used for sorting coordinates (used in 'less' routine)
const scalar tol_;
const scalar mergeDistance_;
//- All surface-intersection interaction
const refinementSurfaces& surfaces_;
//- All shell-refinement interaction
const shellSurfaces& shells_;
//- refinement engine
hexRef8 meshCutter_;
@ -229,14 +234,18 @@ private:
//- Mark cells for refinement-shells based refinement.
label markInternalRefinement
(
const PtrList<searchableSurface>&,
const labelList& shellLevels,
const boolList& shellRefineInside,
const label nAllowRefine,
labelList& refineCell,
label& nRefine
) 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.
label markSurfaceRefinement
(
@ -252,17 +261,13 @@ private:
// regions.
bool checkCurvature
(
const labelList& globalToPatch,
const scalar curvature,
const bool markDifferingRegions,
const label nAllowRefine,
const label newSurfI,
const label newTriI,
const label surfaceLevel,
const vector& surfaceNormal,
const label cellI,
label& maxCellSurfI,
label& maxCellTriI,
label& cellMaxLevel,
vector& cellMaxNormal,
labelList& refineCell,
label& nRefine
) const;
@ -273,9 +278,7 @@ private:
// (markDifferingRegions)
label markSurfaceCurvatureRefinement
(
const labelList& globalToPatch,
const scalar curvature,
const bool markDifferingRegions,
const label nAllowRefine,
const labelList& neiLevel,
const pointField& neiCc,
@ -380,8 +383,9 @@ public:
meshRefinement
(
fvMesh& mesh,
const scalar tol,
const refinementSurfaces&
const scalar mergeDistance,
const refinementSurfaces&,
const shellSurfaces&
);
@ -399,12 +403,23 @@ public:
return mesh_;
}
scalar mergeDistance() const
{
return mergeDistance_;
}
//- reference to surface search engines
const refinementSurfaces& surfaces() const
{
return surfaces_;
}
//- reference to refinement shells (regions)
const shellSurfaces& shells() const
{
return shells_;
}
//- reference to meshcutting engine
const hexRef8& meshCutter() const
{
@ -454,6 +469,18 @@ public:
decompositionMethod&
) const;
//- Redecompose according to cell count
// keepZoneFaces : find all faceZones from zoned surfaces and keep
// owner and neighbour together
// keepBaffles : find all baffles and keep them together
autoPtr<mapDistributePolyMesh> balance
(
const bool keepZoneFaces,
const bool keepBaffles,
decompositionMethod& decomposer,
fvMeshDistribute& distributor
);
//- Get faces with intersection.
labelList intersectedFaces() const;
@ -482,22 +509,21 @@ public:
const labelList& adaptPatchIDs
);
//- Helper function: check that face zones are synced
static void checkCoupledFaceZones(const polyMesh&);
// Refinement
//- Calculate list of cells to refine.
labelList refineCandidates
(
const point& keepPoint,
const labelList& globalToPatch,
const scalar curvature,
const PtrList<featureEdgeMesh>& featureMeshes,
const labelList& featureLevels,
const PtrList<searchableSurface>&,
const labelList& shellLevels,
const boolList& shellRefineInside,
const bool featureRefinement,
const bool internalRefinement,
const bool surfaceRefinement,
@ -626,7 +652,7 @@ public:
template<class T>
void testSyncBoundaryFaceList
(
const scalar tol,
const scalar mergeDistance,
const string&,
const UList<T>&,
const UList<T>&

View File

@ -249,7 +249,7 @@ void Foam::meshRefinement::getBafflePatches
if (debug)
{
Pout<< "getBafflePatches : Not baffling surface "
<< surfaces_[surfI].searchableSurface::name() << endl;
<< surfaces_.names()[surfI] << endl;
}
}
else
@ -264,69 +264,95 @@ void Foam::meshRefinement::getBafflePatches
neiPatch.setSize(mesh_.nFaces());
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)
{
// Edge between owner and neighbour of face pierces a surface.
// Do closer inspection to find nearest intersection on both sides.
label faceI = testFaces[i];
label own = mesh_.faceOwner()[faceI];
// Cc of neighbouring cell
point end
(
mesh_.isInternalFace(faceI)
? cellCentres[mesh_.faceNeighbour()[faceI]]
: neiCc[faceI-mesh_.nInternalFaces()]
);
if (mesh_.isInternalFace(faceI))
{
start[i] = cellCentres[own];
end[i] = cellCentres[mesh_.faceNeighbour()[faceI]];
}
else
{
start[i] = cellCentres[own];
end[i] = neiCc[faceI-mesh_.nInternalFaces()];
}
}
label surface1, surface2;
pointIndexHit hit1, hit2;
// Do test for intersections
// ~~~~~~~~~~~~~~~~~~~~~~~~~
labelList surface1;
List<pointIndexHit> hit1;
labelList region1;
labelList surface2;
List<pointIndexHit> hit2;
labelList region2;
surfaces_.findNearestIntersection
(
surfacesToBaffle,
cellCentres[own],
start,
end,
surface1,
hit1,
region1,
surface2,
hit2
hit2,
region2
);
if (hit1.hit() && hit2.hit())
forAll(testFaces, i)
{
label faceI = testFaces[i];
if (hit1[i].hit() && hit2[i].hit())
{
if (str.valid())
{
meshTools::writeOBJ(str(), cellCentres[own]);
meshTools::writeOBJ(str(), start[i]);
vertI++;
meshTools::writeOBJ(str(), hit1.rawPoint());
meshTools::writeOBJ(str(), hit1[i].rawPoint());
vertI++;
meshTools::writeOBJ(str(), hit2.rawPoint());
meshTools::writeOBJ(str(), hit2[i].rawPoint());
vertI++;
meshTools::writeOBJ(str(), end);
meshTools::writeOBJ(str(), end[i]);
vertI++;
str()<< "l " << vertI-3 << ' ' << vertI-2 << nl;
str()<< "l " << vertI-2 << ' ' << vertI-1 << nl;
str()<< "l " << vertI-1 << ' ' << vertI << nl;
}
// Pick up the patches
ownPatch[faceI] = globalToPatch
[
surfaces_.triangleRegion(surface1, hit1.index())
surfaces_.globalRegion(surface1[i], region1[i])
];
neiPatch[faceI] = globalToPatch
[
surfaces_.triangleRegion(surface2, hit2.index())
surfaces_.globalRegion(surface2[i], region2[i])
];
if (ownPatch[faceI] == -1 || neiPatch[faceI] == -1)
{
FatalErrorIn("getBafflePatches()") << abort(FatalError);
}
FatalErrorIn("getBafflePatches(..)")
<< "problem." << abort(FatalError);
}
}
}
@ -1203,15 +1229,20 @@ void Foam::meshRefinement::findCellZoneGeometric
const labelList& faceOwner = mesh_.faceOwner();
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)
{
label surfI = surfaces_.insideZone
(
closedNamedSurfaces,
cellCentres[cellI]
);
label surfI = insideSurfaces[cellI];
if (surfI != -1)
{
@ -1223,6 +1254,32 @@ void Foam::meshRefinement::findCellZoneGeometric
// Some cells with cell centres close to surface might have
// 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)
{
label surfI = namedSurfaceIndex[faceI];
@ -1236,51 +1293,62 @@ void Foam::meshRefinement::findCellZoneGeometric
{
label nei = faceNeighbour[faceI];
const point& neiCc = cellCentres[nei];
// Perturbed cc
const vector d = 1E-4*(neiCc - ownCc);
// Test perturbed owner
candidatePoints[nCandidates++] = ownCc-d;
candidatePoints[nCandidates++] = neiCc+d;
}
else
{
label ownSurfI = surfaces_.insideZone
const point& neiFc = mesh_.faceCentres()[faceI];
// Perturbed cc
const vector d = 1E-4*(neiFc - ownCc);
candidatePoints[nCandidates++] = ownCc-d;
}
}
}
// 2. Test points for inside
surfaces_.findInside
(
closedNamedSurfaces,
ownCc-d
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)
{
cellToZone[own] = surfaceToCellZone[ownSurfI];
}
}
// Test perturbed neighbour
{
label neiSurfI = surfaces_.insideZone
(
closedNamedSurfaces,
neiCc+d
);
label neiSurfI = insideSurfaces[nCandidates++];
if (neiSurfI != -1)
{
label nei = faceNeighbour[faceI];
cellToZone[nei] = surfaceToCellZone[neiSurfI];
}
}
}
else
{
const point& neiCc = mesh_.faceCentres()[faceI];
const vector d = 1E-4*(neiCc - ownCc);
// Test perturbed owner
{
label ownSurfI = surfaces_.insideZone
(
closedNamedSurfaces,
ownCc-d
);
label ownSurfI = insideSurfaces[nCandidates++];
if (ownSurfI != -1)
{
cellToZone[own] = surfaceToCellZone[ownSurfI];
@ -1289,7 +1357,6 @@ void Foam::meshRefinement::findCellZoneGeometric
}
}
}
}
// Finds region per cell. Assumes:
@ -1771,7 +1838,11 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::splitMesh
const labelList& faceNeighbour = mesh_.faceNeighbour();
// Patch for exposed faces for lack of anything sensible.
const label defaultPatch = globalToPatch[0];
label defaultPatch = 0;
if (globalToPatch.size() > 0)
{
defaultPatch = globalToPatch[0];
}
for (label i = 0; i < nBufferLayers; i++)
{
@ -2291,7 +2362,7 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::zonify
isNamedSurface[surfI] = true;
Info<< "Surface : " << surfaces_[surfI].searchableSurface::name() << nl
Info<< "Surface : " << surfaces_.names()[surfI] << nl
<< " faceZone : " << faceZoneNames[surfI] << nl
<< " cellZone : " << cellZoneNames[surfI] << endl;
}
@ -2329,7 +2400,7 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::zonify
if (debug)
{
Pout<< "Faces on " << surfaces_[surfI].searchableSurface::name()
Pout<< "Faces on " << surfaces_.names()[surfI]
<< " will go into faceZone " << zoneI << endl;
}
surfaceToFaceZone[surfI] = zoneI;
@ -2387,8 +2458,7 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::zonify
if (debug)
{
Pout<< "Cells inside "
<< surfaces_[surfI].searchableSurface::name()
Pout<< "Cells inside " << surfaces_.names()[surfI]
<< " will go into cellZone " << zoneI << endl;
}
surfaceToCellZone[surfI] = zoneI;
@ -2444,78 +2514,83 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::zonify
// Note: for all internal faces? internal + coupled?
// Since zonify is run after baffling the surfaceIndex_ on baffles is
// not synchronised across both baffle faces. Fortunately we don't
// do zonify baffle faces anyway.
forAll(surfaceIndex_, faceI)
{
label surfI = surfaceIndex_[faceI];
// do zonify baffle faces anyway (they are normal boundary faces).
if
(
surfI != -1
&& (
mesh_.isInternalFace(faceI)
|| patches[patches.whichPatch(faceI)].coupled()
)
)
{
if (isNamedSurface[surfI])
{
namedSurfaceIndex[faceI] = surfI;
nSurfFaces[surfI]++;
}
else
{
// Test more accurately for whether intersection is at
// zoneable surface
// Collect candidate faces
// ~~~~~~~~~~~~~~~~~~~~~~~
label surface1, surface2;
pointIndexHit hit1, hit2;
labelList testFaces(intersectedFaces());
// Collect segments
// ~~~~~~~~~~~~~~~~
pointField start(testFaces.size());
pointField end(testFaces.size());
forAll(testFaces, i)
{
label faceI = testFaces[i];
label own = mesh_.faceOwner()[faceI];
if (mesh_.isInternalFace(faceI))
{
surfaces_.findNearestIntersection
(
namedSurfaces,
cellCentres[faceOwner[faceI]],
cellCentres[faceNeighbour[faceI]],
surface1,
hit1,
surface2,
hit2
);
start[i] = cellCentres[own];
end[i] = cellCentres[mesh_.faceNeighbour()[faceI]];
}
else
{
start[i] = cellCentres[own];
end[i] = neiCc[faceI-mesh_.nInternalFaces()];
}
}
// 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,
cellCentres[faceOwner[faceI]],
neiCc[faceI-mesh_.nInternalFaces()],
start,
end,
surface1,
hit1,
region1,
surface2,
hit2
hit2,
region2
);
}
if (hit1.hit())
forAll(testFaces, i)
{
// If both hit should probably choose nearest. For
// later.
namedSurfaceIndex[faceI] = surface1;
nSurfFaces[surface1]++;
}
else if (hit2.hit())
label faceI = testFaces[i];
if (surface1[i] != -1)
{
namedSurfaceIndex[faceI] = surface2;
nSurfFaces[surface2]++;
}
}
// 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
// there happen to be a (obviously thin) surface with different
// regions between the cell centres. If one is on a named surface
@ -2534,7 +2609,7 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::zonify
forAll(nSurfFaces, surfI)
{
Pout<< "Surface:"
<< surfaces_[surfI].searchableSurface::name()
<< surfaces_.names()[surfI]
<< " nZoneFaces:" << nSurfFaces[surfI] << nl;
}
Pout<< endl;
@ -2609,20 +2684,8 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::zonify
// Put the cells into the correct zone
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
labelList closedNamedSurfaces(namedSurfaces.size());
label nClosed = 0;
forAll(namedSurfaces, i)
{
label surfI = namedSurfaces[i];
if (surfaces_.closed()[surfI])
{
closedNamedSurfaces[nClosed++] = surfI;
}
}
closedNamedSurfaces.setSize(nClosed);
// Closed surfaces with cellZone specified.
labelList closedNamedSurfaces(surfaces_.getClosedNamedSurfaces());
// Zone per cell:
// -2 : unset
@ -2704,13 +2767,4 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::zonify
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
// ************************************************************************* //

View File

@ -30,15 +30,9 @@ License
#include "removePoints.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
// Merge faces that are in-line.
@ -244,13 +238,4 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::mergeEdges
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
// ************************************************************************* //

View File

@ -29,6 +29,7 @@ License
#include "syncTools.H"
#include "Time.H"
#include "refinementSurfaces.H"
#include "shellSurfaces.H"
#include "faceSet.H"
#include "decompositionMethod.H"
#include "fvMeshDistribute.H"
@ -37,9 +38,6 @@ License
#include "featureEdgeMesh.H"
#include "Cloud.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
// Get faces (on the new mesh) that have in some way been affected by the
@ -369,7 +367,7 @@ Foam::label Foam::meshRefinement::markFeatureRefinement
{
label edgeI = pEdges[i];
if (featureEdgeVisited[featI].get(edgeI) == 0)
if (featureEdgeVisited[featI].set(edgeI, 1u))
{
// Unvisited edge. Make the particle go to the other point
// on the edge.
@ -377,7 +375,6 @@ Foam::label Foam::meshRefinement::markFeatureRefinement
const edge& e = featureMesh.edges()[edgeI];
label otherPointI = e.otherVertex(pointI);
featureEdgeVisited[featI].set(edgeI, 1u);
tp.end() = featureMesh.points()[otherPointI];
tp.j() = otherPointI;
keepParticle = true;
@ -438,6 +435,15 @@ Foam::label Foam::meshRefinement::markFeatureRefinement
}
}
if
(
returnReduce(nRefine, sumOp<label>())
> returnReduce(nAllowRefine, sumOp<label>())
)
{
Info<< "Reached refinement limit." << endl;
}
return returnReduce(nRefine-oldNRefine, sumOp<label>());
}
@ -445,9 +451,6 @@ Foam::label Foam::meshRefinement::markFeatureRefinement
// Mark cells for non-surface intersection based refinement.
Foam::label Foam::meshRefinement::markInternalRefinement
(
const PtrList<searchableSurface>& shells,
const labelList& shellLevels,
const boolList& shellRefineInside,
const label nAllowRefine,
labelList& refineCell,
@ -457,50 +460,39 @@ Foam::label Foam::meshRefinement::markInternalRefinement
const labelList& cellLevel = meshCutter_.cellLevel();
const pointField& cellCentres = mesh_.cellCentres();
label oldNRefine = nRefine;
// Number of cells marked for refinement per shell.
labelList nCellsPerShell(shells.size(), 0);
// Collect cells to test
pointField testCc(cellLevel.size()-nRefine);
labelList testLevels(cellLevel.size()-nRefine);
label testI = 0;
forAll(cellLevel, cellI)
{
if (refineCell[cellI] == -1)
{
// Cell not marked for refinement. Check if inside any shell
// with higher refinement level than cell currently has.
testCc[testI] = cellCentres[cellI];
testLevels[testI] = cellLevel[cellI];
testI++;
}
}
bool reachedLimit = false;
// Do test to see whether cells is inside/outside shell with higher level
labelList maxLevel;
shells_.findHigherLevel(testCc, testLevels, maxLevel);
forAll(shells, shellI)
// Mark for refinement. Note that we didn't store the original cellID so
// now just reloop in same order.
testI = 0;
forAll(cellLevel, cellI)
{
// Cached inside-outside from tree
searchableSurface::volumeType t =
shells[shellI].getVolumeType(cellCentres[cellI]);
//// Uncached inside-outside from treeData
//label t = shells[shellI].shapes().getVolumeType
// (
// shells[shellI],
// cellCentres[cellI]
// );
// Which side of shell is to be refined
searchableSurface::volumeType refSide =
(
shellRefineInside[shellI]
? searchableSurface::INSIDE
: searchableSurface::OUTSIDE
);
if (t == refSide && cellLevel[cellI] < shellLevels[shellI])
if (refineCell[cellI] == -1)
{
// Cell is inside shell with higher refinement level. Mark
// for refinement.
reachedLimit = !markForRefine
if (maxLevel[testI] > testLevels[testI])
{
bool reachedLimit = !markForRefine
(
labelMax,
maxLevel[testI], // mark with any positive value
nAllowRefine,
refineCell[cellI],
nRefine
@ -516,35 +508,65 @@ Foam::label Foam::meshRefinement::markInternalRefinement
}
break;
}
else
{
// Cell successfully marked for refinement
nCellsPerShell[shellI]++;
}
testI++;
}
}
if (reachedLimit)
if
(
returnReduce(nRefine, sumOp<label>())
> returnReduce(nAllowRefine, sumOp<label>())
)
{
break;
}
}
}
Pstream::listCombineGather(nCellsPerShell, plusEqOp<label>());
Pstream::listCombineScatter(nCellsPerShell);
Info<< "Marked for refinement per shell :" << endl;
forAll(nCellsPerShell, shellI)
{
Info<< " shell:" << shellI << " nCells:" << nCellsPerShell[shellI]
<< nl;
Info<< "Reached refinement limit." << endl;
}
return returnReduce(nRefine-oldNRefine, sumOp<label>());
}
// Collect faces that are intersected and whose neighbours aren't yet marked
// for refinement.
Foam::labelList Foam::meshRefinement::getRefineCandidateFaces
(
const labelList& refineCell
) const
{
labelList testFaces(mesh_.nCells());
label nTest = 0;
forAll(surfaceIndex_, faceI)
{
if (surfaceIndex_[faceI] != -1)
{
label own = mesh_.faceOwner()[faceI];
if (mesh_.isInternalFace(faceI))
{
label nei = mesh_.faceNeighbour()[faceI];
if (refineCell[own] == -1 || refineCell[nei] == -1)
{
testFaces[nTest++] = faceI;
}
}
else
{
if (refineCell[own] == -1)
{
testFaces[nTest++] = faceI;
}
}
}
}
testFaces.setSize(nTest);
return testFaces;
}
// Mark cells for surface intersection based refinement.
Foam::label Foam::meshRefinement::markSurfaceRefinement
(
@ -564,46 +586,79 @@ Foam::label Foam::meshRefinement::markSurfaceRefinement
// Use cached surfaceIndex_ to detect if any intersection. If so
// re-intersect to determine level wanted.
label faceI;
for (faceI = 0; faceI < surfaceIndex_.size(); faceI++)
{
if (surfaceIndex_[faceI] != -1)
// Collect candidate faces
// ~~~~~~~~~~~~~~~~~~~~~~~
labelList testFaces(getRefineCandidateFaces(refineCell));
// Collect segments
// ~~~~~~~~~~~~~~~~
pointField start(testFaces.size());
pointField end(testFaces.size());
labelList minLevel(testFaces.size());
forAll(testFaces, i)
{
label faceI = testFaces[i];
label own = mesh_.faceOwner()[faceI];
if (mesh_.isInternalFace(faceI))
{
label nei = mesh_.faceNeighbour()[faceI];
// Test if not both sides already marked for refinement.
if (refineCell[own] == -1 || refineCell[nei] == -1)
start[i] = cellCentres[own];
end[i] = cellCentres[nei];
minLevel[i] = min(cellLevel[own], cellLevel[nei]);
}
else
{
pointIndexHit hit;
label surfI = surfaces_.findHigherIntersection
label bFaceI = faceI - mesh_.nInternalFaces();
start[i] = cellCentres[own];
end[i] = neiCc[bFaceI];
minLevel[i] = min(cellLevel[own], neiLevel[bFaceI]);
}
}
// Do test for higher intersections
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
labelList surfaceHit;
labelList surfaceMinLevel;
surfaces_.findHigherIntersection
(
cellCentres[own],
cellCentres[nei],
min(cellLevel[own], cellLevel[nei]),
hit
start,
end,
minLevel,
surfaceHit,
surfaceMinLevel
);
// Mark cells for refinement
// ~~~~~~~~~~~~~~~~~~~~~~~~~
forAll(testFaces, i)
{
label faceI = testFaces[i];
label surfI = surfaceHit[i];
if (surfI != -1)
{
// Found intersection with surface with higher wanted
// refinement. Mark cell for refining.
// Note: could do optimization here and only refine the
// side of the face the intersection actually goes
// through.
// This would require us though to find all
// intersections
// first instead of now only the first higher one. Also
// would need the exact intersection of face with cc-cc
// connection?
// refinement. Check if the level field on that surface
// specifies an even higher level. Note:this is weird. Should
// do the check with the surfaceMinLevel whilst intersecting the
// surfaces?
label surfaceMinLevel =
surfaces_.minLevelField(surfI)[hit.index()];
label own = mesh_.faceOwner()[faceI];
if (surfaceMinLevel > cellLevel[own])
if (surfaceMinLevel[i] > cellLevel[own])
{
// Owner needs refining
if
@ -621,7 +676,10 @@ Foam::label Foam::meshRefinement::markSurfaceRefinement
}
}
if (surfaceMinLevel > cellLevel[nei])
if (mesh_.isInternalFace(faceI))
{
label nei = mesh_.faceNeighbour()[faceI];
if (surfaceMinLevel[i] > cellLevel[nei])
{
// Neighbour needs refining
if
@ -641,79 +699,36 @@ Foam::label Foam::meshRefinement::markSurfaceRefinement
}
}
}
else if (refineCell[own] == -1)
{
// boundary face with unmarked owner
label bFaceI = faceI - mesh_.nInternalFaces();
pointIndexHit hit;
label surfI = surfaces_.findHigherIntersection
(
cellCentres[own],
neiCc[bFaceI],
min(cellLevel[own], neiLevel[bFaceI]),
hit
);
if (surfI != -1)
{
// Make sure it is my side that wants refinement.
label surfaceMinLevel =
surfaces_.minLevelField(surfI)[hit.index()];
if (surfaceMinLevel > cellLevel[own])
{
if
(
!markForRefine
(
surfI,
nAllowRefine,
refineCell[own],
nRefine
)
returnReduce(nRefine, sumOp<label>())
> returnReduce(nAllowRefine, sumOp<label>())
)
{
break;
}
}
}
}
}
}
if (faceI < surfaceIndex_.size())
{
if (debug)
{
Pout<< "Stopped refining since reaching my cell limit of "
<< mesh_.nCells()+7*nRefine << endl;
}
Info<< "Reached refinement limit." << endl;
}
return returnReduce(nRefine-oldNRefine, sumOp<label>());
}
// Given intersection of (face of) cell by newSurfI, newTriI, check whether
// it needs to be refined. Updates maxCellSurf, maxCellTri and
// refineCell,nRefine if it decides to refine the cell. Returns false
// if the nRefine limit has been reached, true otherwise.
// Checks if multiple intersections of a cell (by a surface with a higher
// max than the cell level) and if so if the normals at these intersections
// make a large angle.
// Returns false if the nRefine limit has been reached, true otherwise.
bool Foam::meshRefinement::checkCurvature
(
const labelList& globalToPatch,
const scalar curvature,
const bool markDifferingRegions,
const label nAllowRefine,
const label newSurfI,
const label newTriI,
const label surfaceLevel, // current intersection max level
const vector& surfaceNormal,// current intersection normal
const label cellI,
label& maxCellSurfI,
label& maxCellTriI,
label& cellMaxLevel, // cached max surface level for this cell
vector& cellMaxNormal, // cached surface normal for this cell
labelList& refineCell,
label& nRefine
@ -721,59 +736,35 @@ bool Foam::meshRefinement::checkCurvature
{
const labelList& cellLevel = meshCutter_.cellLevel();
if (maxCellSurfI == -1)
// Test if surface applicable
if (surfaceLevel > cellLevel[cellI])
{
if (cellMaxLevel == -1)
{
// First visit of cell. Store
maxCellSurfI = newSurfI;
maxCellTriI = newTriI;
cellMaxLevel = surfaceLevel;
cellMaxNormal = surfaceNormal;
}
else
{
// Second or more visit.
label cellRegion = surfaces_.triangleRegion(maxCellSurfI, maxCellTriI);
label newRegion = surfaces_.triangleRegion(newSurfI, newTriI);
// Update max
label maxLevel = surfaces_.maxLevel()[cellRegion];
if (surfaces_.maxLevel()[newRegion] > maxLevel)
{
maxCellSurfI = newSurfI;
maxCellTriI = newTriI;
maxLevel = surfaces_.maxLevel()[newRegion];
}
// Check if cell is candidate for refinement
if (cellLevel[cellI] < maxLevel)
{
// Test 1: different regions
if (markDifferingRegions && cellRegion != newRegion)
// Second or more visit. Check curvature.
if ((cellMaxNormal & surfaceNormal) < curvature)
{
return markForRefine
(
globalToPatch[newRegion], // mark with non-neg number.
surfaceLevel, // mark with any non-neg number.
nAllowRefine,
refineCell[cellI],
nRefine
);
}
// Test 2: different normals
const vector& cellN =
surfaces_[maxCellSurfI].faceNormals()[maxCellTriI];
const vector& newN =
surfaces_[newSurfI].faceNormals()[newTriI];
if ((cellN & newN) < curvature)
// Set normal to that of highest surface. Not really necessary
// over here but we reuse cellMax info when doing coupled faces.
if (surfaceLevel > cellMaxLevel)
{
return markForRefine
(
globalToPatch[newRegion], // mark with non-neg number.
nAllowRefine,
refineCell[cellI],
nRefine
);
cellMaxLevel = surfaceLevel;
cellMaxNormal = surfaceNormal;
}
}
}
@ -786,9 +777,7 @@ bool Foam::meshRefinement::checkCurvature
// Mark cells for surface curvature based refinement.
Foam::label Foam::meshRefinement::markSurfaceCurvatureRefinement
(
const labelList& globalToPatch,
const scalar curvature,
const bool markDifferingRegions,
const label nAllowRefine,
const labelList& neiLevel,
const pointField& neiCc,
@ -802,107 +791,117 @@ Foam::label Foam::meshRefinement::markSurfaceCurvatureRefinement
label oldNRefine = nRefine;
// 1. Any cell on more than one surface gets refined (if its current level
// is <= max of the surface max level)
// 1. local test: any cell on more than one surface gets refined
// (if its current level is < max of the surface max level)
// 2. Any cell on only one surface with a neighbour on a different surface
// gets refined (if its current level etc.)
// 2. 'global' test: any cell on only one surface with a neighbour
// on a different surface gets refined (if its current level etc.)
// Collect candidate faces (i.e. intersecting any surface and
// owner/neighbour not yet refined.
labelList testFaces(getRefineCandidateFaces(refineCell));
// Index of surface with the max maxLevel and the actual triangle
// on the surface. We store these and not e.g. global region so we can get
// at:
// - global region
// - global patch
// - face normal
labelList cellMaxSurface(mesh_.nCells(), -1);
labelList cellMaxTriangle(mesh_.nCells(), -1);
// Collect segments
pointField start(testFaces.size());
pointField end(testFaces.size());
labelList minLevel(testFaces.size());
// 1.
forAll(surfaceIndex_, faceI)
{
if (surfaceIndex_[faceI] != -1)
forAll(testFaces, i)
{
label faceI = testFaces[i];
label own = mesh_.faceOwner()[faceI];
// There is an intersection. Do more accurate test to get all
// intersections
labelList surfaceIndices;
List<pointIndexHit> hits;
if (mesh_.isInternalFace(faceI))
{
label nei = mesh_.faceNeighbour()[faceI];
surfaces_.findAllIntersections
(
cellCentres[own],
cellCentres[nei],
surfaceIndices,
hits
);
start[i] = cellCentres[own];
end[i] = cellCentres[nei];
minLevel[i] = min(cellLevel[own], cellLevel[nei]);
}
else
{
label bFaceI = faceI - mesh_.nInternalFaces();
surfaces_.findAllIntersections
(
cellCentres[own],
neiCc[bFaceI],
surfaceIndices,
hits
);
start[i] = cellCentres[own];
end[i] = neiCc[bFaceI];
minLevel[i] = min(cellLevel[own], neiLevel[bFaceI]);
}
}
// Test for all intersections (with surfaces of higher max level than
// minLevel) and cache per cell the max surface level and the local normal
// on that surface.
labelList cellMaxLevel(mesh_.nCells(), -1);
vectorField cellMaxNormal(mesh_.nCells());
// See if intersection adds any new information to the owner or
// neighbour cell.
forAll(surfaceIndices, i)
{
label surfI = surfaceIndices[i];
label triI = hits[i].index();
// Per segment the normals of the surfaces
List<vectorList> surfaceNormal;
// Per segment the list of levels of the surfaces
labelListList surfaceLevel;
surfaces_.findAllHigherIntersections
(
start,
end,
minLevel, // max level of surface has to be bigger
// than min level of neighbouring cells
surfaceNormal,
surfaceLevel
);
// Clear out unnecessary data
start.clear();
end.clear();
minLevel.clear();
// Extract per cell information on the surface with the highest max
forAll(testFaces, i)
{
label faceI = testFaces[i];
label own = mesh_.faceOwner()[faceI];
const vectorList& fNormals = surfaceNormal[i];
const labelList& fLevels = surfaceLevel[i];
forAll(fLevels, hitI)
{
checkCurvature
(
globalToPatch,
curvature,
markDifferingRegions,
nAllowRefine,
surfI,
triI,
fLevels[hitI],
fNormals[hitI],
own,
cellMaxSurface[own],
cellMaxTriangle[own],
cellMaxLevel[own],
cellMaxNormal[own],
refineCell,
nRefine
);
}
if (mesh_.isInternalFace(faceI))
{
label nei = mesh_.faceNeighbour()[faceI];
forAll(fLevels, hitI)
{
checkCurvature
(
globalToPatch,
curvature,
markDifferingRegions,
nAllowRefine,
surfI,
triI,
fLevels[hitI],
fNormals[hitI],
nei,
cellMaxSurface[nei],
cellMaxTriangle[nei],
cellMaxLevel[nei],
cellMaxNormal[nei],
refineCell,
nRefine
@ -910,93 +909,46 @@ Foam::label Foam::meshRefinement::markSurfaceCurvatureRefinement
}
}
}
if (nRefine > nAllowRefine)
{
if (debug)
{
Pout<< "Stopped refining since reaching my cell limit of "
<< mesh_.nCells()+7*nRefine << endl;
}
break;
}
}
// 2. Find out a measure of surface curvature and region edges.
// Send over surface region and surface normal to neighbour cell.
// global region
labelList ownRegion(mesh_.nFaces(), -1);
labelList neiRegion(mesh_.nFaces(), -1);
// local normal at hit
vectorField ownNormal(mesh_.nFaces(), vector::zero);
vectorField neiNormal(mesh_.nFaces(), vector::zero);
labelList neiBndMaxLevel(mesh_.nFaces()-mesh_.nInternalFaces());
vectorField neiBndMaxNormal(mesh_.nFaces()-mesh_.nInternalFaces());
for (label faceI = mesh_.nInternalFaces(); faceI < mesh_.nFaces(); faceI++)
{
label bFaceI = faceI-mesh_.nInternalFaces();
label own = mesh_.faceOwner()[faceI];
neiBndMaxLevel[bFaceI] = cellMaxLevel[own];
neiBndMaxNormal[bFaceI] = cellMaxNormal[own];
}
syncTools::swapBoundaryFaceList(mesh_, neiBndMaxLevel, false);
syncTools::swapBoundaryFaceList(mesh_, neiBndMaxNormal, false);
// Loop over all faces. Could only be checkFaces.. except if they're coupled
// Internal faces
for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
{
label own = mesh_.faceOwner()[faceI];
if (cellMaxSurface[own] != -1)
{
label surfI = cellMaxSurface[own];
label triI = cellMaxTriangle[own];
ownRegion[faceI] = surfaces_.triangleRegion(surfI, triI);
ownNormal[faceI] = surfaces_[surfI].faceNormals()[triI];
}
label nei = mesh_.faceNeighbour()[faceI];
if (cellMaxSurface[nei] != -1)
if (cellMaxLevel[own] != -1 && cellMaxLevel[nei] != -1)
{
label surfI = cellMaxSurface[nei];
label triI = cellMaxTriangle[nei];
neiRegion[faceI] = surfaces_.triangleRegion(surfI, triI);
neiNormal[faceI] = surfaces_[surfI].faceNormals()[triI];
}
}
// Boundary faces
for (label faceI = mesh_.nInternalFaces(); faceI < mesh_.nFaces(); faceI++)
// Have valid data on both sides. Check curvature.
if ((cellMaxNormal[own] & cellMaxNormal[nei]) < curvature)
{
label own = mesh_.faceOwner()[faceI];
if (cellMaxSurface[own] != -1)
{
label surfI = cellMaxSurface[own];
label triI = cellMaxTriangle[own];
ownRegion[faceI] = surfaces_.triangleRegion(surfI, triI);
ownNormal[faceI] = surfaces_[surfI].faceNormals()[triI];
neiRegion[faceI] = ownRegion[faceI];
neiNormal[faceI] = ownNormal[faceI];
}
}
syncTools::swapFaceList(mesh_, neiRegion, false);
syncTools::swapFaceList(mesh_, neiNormal, false);
for (label faceI = 0; faceI < mesh_.nFaces(); faceI++)
{
if (ownRegion[faceI] != -1 && neiRegion[faceI] != -1)
{
if
(
(markDifferingRegions && (ownRegion[faceI] != neiRegion[faceI]))
|| ((ownNormal[faceI] & neiNormal[faceI]) < curvature)
)
{
label own = mesh_.faceOwner()[faceI];
if (cellLevel[own] < surfaces_.maxLevel()[ownRegion[faceI]])
// See which side to refine
if (cellLevel[own] < cellMaxLevel[own])
{
if
(
!markForRefine
(
globalToPatch[ownRegion[faceI]],
cellMaxLevel[own],
nAllowRefine,
refineCell[own],
nRefine
@ -1011,22 +963,16 @@ Foam::label Foam::meshRefinement::markSurfaceCurvatureRefinement
}
break;
}
}
if (mesh_.isInternalFace(faceI))
{
label nei = mesh_.faceNeighbour()[faceI];
if (cellLevel[nei] < surfaces_.maxLevel()[neiRegion[faceI]])
if (cellLevel[nei] < cellMaxLevel[nei])
{
if
(
!markForRefine
(
globalToPatch[neiRegion[faceI]],
cellMaxLevel[nei],
nAllowRefine,
refineCell[nei],
nRefine
)
@ -1044,13 +990,50 @@ Foam::label Foam::meshRefinement::markSurfaceCurvatureRefinement
}
}
}
// Boundary faces
for (label faceI = mesh_.nInternalFaces(); faceI < mesh_.nFaces(); faceI++)
{
label own = mesh_.faceOwner()[faceI];
label bFaceI = faceI - mesh_.nInternalFaces();
if (cellLevel[own] < cellMaxLevel[own] && neiBndMaxLevel[bFaceI] != -1)
{
// Have valid data on both sides. Check curvature.
if ((cellMaxNormal[own] & neiBndMaxNormal[bFaceI]) < curvature)
{
if
(
!markForRefine
(
cellMaxLevel[own],
nAllowRefine,
refineCell[own],
nRefine
)
)
{
if (debug)
{
Pout<< "Stopped refining since reaching my cell"
<< " limit of " << mesh_.nCells()+7*nRefine
<< endl;
}
break;
}
}
}
}
if
(
returnReduce(nRefine, sumOp<label>())
> returnReduce(nAllowRefine, sumOp<label>())
)
{
Info<< "Reached refinement limit." << endl;
}
return returnReduce(nRefine-oldNRefine, sumOp<label>());
label totNRefined = returnReduce(totNRefined, sumOp<label>());
return totNRefined;
}
@ -1064,16 +1047,11 @@ Foam::label Foam::meshRefinement::markSurfaceCurvatureRefinement
Foam::labelList Foam::meshRefinement::refineCandidates
(
const point& keepPoint,
const labelList& globalToPatch,
const scalar curvature,
const PtrList<featureEdgeMesh>& featureMeshes,
const labelList& featureLevels,
const PtrList<searchableSurface>& shells,
const labelList& shellLevels,
const boolList& shellRefineInside,
const bool featureRefinement,
const bool internalRefinement,
const bool surfaceRefinement,
@ -1086,7 +1064,12 @@ Foam::labelList Foam::meshRefinement::refineCandidates
labelList cellsToRefine;
if (totNCells < maxGlobalCells)
if (totNCells >= maxGlobalCells)
{
Info<< "No cells marked for refinement since reached limit "
<< maxGlobalCells << '.' << endl;
}
else
{
// Every cell I refine adds 7 cells. Estimate the number of cells
// I am allowed to refine.
@ -1151,9 +1134,6 @@ Foam::labelList Foam::meshRefinement::refineCandidates
{
label nShell = markInternalRefinement
(
shells,
shellLevels,
shellRefineInside,
nAllowRefine,
refineCell,
@ -1184,13 +1164,11 @@ Foam::labelList Foam::meshRefinement::refineCandidates
// Refinement based on curvature of surface
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (curvatureRefinement)
if (curvatureRefinement && (curvature >= -1 && curvature <= 1))
{
label nCurv = markSurfaceCurvatureRefinement
(
globalToPatch,
curvature,
false, // do not refine at multiple regions
nAllowRefine,
neiLevel,
neiCc,
@ -1287,28 +1265,6 @@ Foam::autoPtr<Foam::mapDistributePolyMesh>
printMeshInfo(debug, "After refinement " + msg);
//// Remove cells which are inside closed surfaces
//// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//if (findIndex(surfaces.closed(), true) != -1)
//{
// Info<< "Removing cells fully inside closed surfaces."
// << endl;
// removeInsideCells
// (
// msg, // refinement iteration for statistics only
// exposedFacesPatch // patch to use for exposed internal faces
// );
// Info<< "Removed inside cells in = "
// << mesh_.time().cpuTimeIncrement() << " s" << endl;
// if (debug)
// {
// // test all is still synced across proc patches
// checkData();
// }
//}
// Load balancing
// ~~~~~~~~~~~~~~

View File

@ -26,8 +26,8 @@ Class
Foam::refinementSurfaces
Description
Container for triSurfaces used for surface-driven refinement.
These contain all the data about the level of refinement needed per
Container for data on surfaces used for surface-driven refinement.
Contains all the data about the level of refinement needed per
surface.
SourceFiles
@ -38,34 +38,38 @@ SourceFiles
#ifndef refinementSurfaces_H
#define refinementSurfaces_H
#include "triSurfaceMeshes.H"
#include "PackedList.H"
#include "triSurfaceGeoMesh.H"
#include "triSurfaceFields.H"
#include "vectorList.H"
#include "pointIndexHit.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
class searchableSurface;
class searchableSurfaces;
class shellSurfaces;
class triSurfaceMesh;
/*---------------------------------------------------------------------------*\
Class refinementSurfaces Declaration
\*---------------------------------------------------------------------------*/
class refinementSurfaces
:
public triSurfaceMeshes
{
// Private data
//- Reference to all geometry.
const searchableSurfaces& allGeometry_;
//- Indices of surfaces that are refinement ones
labelList surfaces_;
//- Surface name (word)
wordList names_;
//- Per surface whether is closed
boolList closed_;
//- Per 'interface' surface : name of faceZone to put faces into
wordList faceZoneNames_;
@ -86,24 +90,12 @@ class refinementSurfaces
//- From global region number to refinement level
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.
PtrList<triSurfaceLabelField> minLevelFields_;
// Private Member Functions
static fileNameList extractFileNames(const PtrList<dictionary>&);
//- Disallow default bitwise copy construct
refinementSurfaces(const refinementSurfaces&);
@ -115,30 +107,41 @@ public:
// Constructors
//- Construct from directory (io.instance()) and dictionaries
//- Construct from surfaces and dictionaries
refinementSurfaces
(
const IOobject& io,
const searchableSurfaces& allGeometry,
const PtrList<dictionary>&
);
//- Construct from surfaces and dictionary
refinementSurfaces
(
const searchableSurfaces& allGeometry,
const dictionary&
);
// Member Functions
// Access
const searchableSurfaces& geometry() const
{
return allGeometry_;
}
const labelList& surfaces() const
{
return surfaces_;
}
//- Names of surfaces
const wordList& names() const
{
return names_;
}
//- Per surface whether is closed
const boolList& closed() const
{
return closed_;
}
//- Per 'interface' surface : name of faceZone to put faces into
const wordList& faceZoneNames() const
{
@ -151,15 +154,11 @@ public:
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)
labelList getNamedSurfaces() const;
//- Get indices of closed named surfaces
labelList getClosedNamedSurfaces() const;
//- From local region number to global region number
const labelList& regionOffset() const
@ -179,24 +178,6 @@ public:
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
@ -206,14 +187,6 @@ public:
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
label minLevel(const label surfI, const label regionI) const
{
@ -231,23 +204,12 @@ public:
return minLevel_.size();
}
//- Minlevel updated for refinement shells
const triSurfaceLabelField& minLevelField(const label surfI) const
{
return minLevelFields_[surfI];
}
//- Calculate minLevelFields
void setMinLevelFields
(
const PtrList<searchableSurface>& shells,
const labelList& shellLevels,
const boolList& shellRefineInside
const shellSurfaces& shells
);
//- Helper: is surface closed?
static bool isSurfaceClosed(const triSurface&);
//- Helper: orient (closed only) surfaces so keepPoint is outside.
static void orientSurface
(
@ -263,36 +225,71 @@ public:
//- Find intersection of edge. Return -1 or first surface
// with higher (than currentLevel) minlevel.
// Return surface number and hit info.
label findHigherIntersection
// Return surface number and level.
void findHigherIntersection
(
const point& start,
const point& end,
const label currentLevel, // current cell refinement level
pointIndexHit&
const pointField& start,
const pointField& end,
const labelList& currentLevel, // current cell refinement level
labelList& surfaces,
labelList& surfaceLevel
) const;
//- Find intersection with max level. Return -1 or the surface
// with the highest maxLevel above currentLevel
label findHighestIntersection
//- Find all intersections of edge. Unsorted order.
void findAllHigherIntersections
(
const point& start,
const point& end,
const label currentLevel, // current cell refinement level
pointIndexHit&
const pointField& start,
const pointField& end,
const labelList& currentLevel, // current cell refinement level
List<vectorList>& surfaceNormal,
labelListList& surfaceLevel
) const;
//- Detect if a point is 'inside' (depending on zoneInside flag) a
// zoneable surface. Returns -1 if not, returns first surface it
// is.
label insideZone(const labelList& surfaces, const point& pt) const;
//- Find intersection nearest to the endpoints. surface1,2 are
// not indices into surfacesToTest but refinement surface indices.
void findNearestIntersection
(
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
// Return number of inside points.
label markInsidePoints(const pointField&, PackedList<1>& isInside)
const;
//- Used for debugging only: find intersection of edge.
void findAnyIntersection
(
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;
};

View 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);
}
}
// ************************************************************************* //

View 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
// ************************************************************************* //

View File

@ -256,7 +256,7 @@ Foam::Ostream& Foam::operator<<
const ExactParticle<ParticleType>& p
)
{
return operator<<(os, static_cast<Particle<ParticleType> >(p));
return operator<<(os, static_cast<const Particle<ParticleType>&>(p));
}

View File

@ -361,7 +361,7 @@ public:
// Member Functions
//- Helper funntion: count cells per processor in wanted distribution
//- Helper function: count cells per processor in wanted distribution
static labelList countCells(const labelList&);
//- Send cells to neighbours according to distribution

View File

@ -553,7 +553,7 @@ Foam::labelListList Foam::addPatchCellLayer::addedCells() const
void Foam::addPatchCellLayer::setRefinement
(
const scalar expansionRatio,
const scalarField& expansionRatio,
const indirectPrimitivePatch& pp,
const labelList& nFaceLayers,
const labelList& nPointLayers,
@ -885,7 +885,7 @@ void Foam::addPatchCellLayer::setRefinement
addedPoints_[patchPointI][i] = addedVertI;
disp *= expansionRatio;
disp *= expansionRatio[patchPointI];
}
}
}

View File

@ -305,7 +305,7 @@ public:
// (instead of e.g. from patch faces)
void setRefinement
(
const scalar expansionRatio,
const scalarField& expansionRatio,
const indirectPrimitivePatch& pp,
const labelList& nFaceLayers,
const labelList& nPointLayers,
@ -325,7 +325,7 @@ public:
{
setRefinement
(
1.0, // expansion ration
scalarField(pp.nPoints(), 1.0), // expansion ration
pp,
labelList(pp.size(), nLayers),
labelList(pp.nPoints(), nLayers),

View File

@ -30,12 +30,10 @@ License
#include "fvPatchFieldMapper.H"
#include "surfaceFields.H"
#include "Time.H"
#include "IFstream.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::
timeVaryingFlowRateInletVelocityFvPatchVectorField::
Foam::timeVaryingFlowRateInletVelocityFvPatchVectorField::
timeVaryingFlowRateInletVelocityFvPatchVectorField
(
const fvPatch& p,
@ -47,8 +45,7 @@ timeVaryingFlowRateInletVelocityFvPatchVectorField
{}
Foam::
timeVaryingFlowRateInletVelocityFvPatchVectorField::
Foam::timeVaryingFlowRateInletVelocityFvPatchVectorField::
timeVaryingFlowRateInletVelocityFvPatchVectorField
(
const timeVaryingFlowRateInletVelocityFvPatchVectorField& ptf,
@ -62,8 +59,7 @@ timeVaryingFlowRateInletVelocityFvPatchVectorField
{}
Foam::
timeVaryingFlowRateInletVelocityFvPatchVectorField::
Foam::timeVaryingFlowRateInletVelocityFvPatchVectorField::
timeVaryingFlowRateInletVelocityFvPatchVectorField
(
const fvPatch& p,
@ -72,12 +68,11 @@ timeVaryingFlowRateInletVelocityFvPatchVectorField
)
:
flowRateInletVelocityFvPatchVectorField(p, iF, dict),
timeSeries_(this->db(), dict)
timeSeries_(dict)
{}
Foam::
timeVaryingFlowRateInletVelocityFvPatchVectorField::
Foam::timeVaryingFlowRateInletVelocityFvPatchVectorField::
timeVaryingFlowRateInletVelocityFvPatchVectorField
(
const timeVaryingFlowRateInletVelocityFvPatchVectorField& ptf
@ -88,8 +83,7 @@ timeVaryingFlowRateInletVelocityFvPatchVectorField
{}
Foam::
timeVaryingFlowRateInletVelocityFvPatchVectorField::
Foam::timeVaryingFlowRateInletVelocityFvPatchVectorField::
timeVaryingFlowRateInletVelocityFvPatchVectorField
(
const timeVaryingFlowRateInletVelocityFvPatchVectorField& ptf,
@ -103,8 +97,7 @@ timeVaryingFlowRateInletVelocityFvPatchVectorField
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::
timeVaryingFlowRateInletVelocityFvPatchVectorField::
void Foam::timeVaryingFlowRateInletVelocityFvPatchVectorField::
updateCoeffs()
{
if (updated())
@ -117,8 +110,7 @@ updateCoeffs()
}
void Foam::
timeVaryingFlowRateInletVelocityFvPatchVectorField::
void Foam::timeVaryingFlowRateInletVelocityFvPatchVectorField::
write(Ostream& os) const
{
flowRateInletVelocityFvPatchVectorField::write(os);

View File

@ -26,7 +26,6 @@ License
#include "timeVaryingUniformFixedValueFvPatchField.H"
#include "Time.H"
#include "IFstream.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
@ -53,7 +52,7 @@ timeVaryingUniformFixedValueFvPatchField
)
:
fixedValueFvPatchField<Type>(p, iF),
timeSeries_(this->db(), dict)
timeSeries_(dict)
{
if (dict.found("value"))
{

View File

@ -29,7 +29,6 @@ License
#include "fvPatchFieldMapper.H"
#include "volFields.H"
#include "surfaceFields.H"
#include "IFstream.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
@ -66,7 +65,7 @@ timeVaryingUniformTotalPressureFvPatchScalarField
psiName_(dict.lookup("psi")),
gamma_(readScalar(dict.lookup("gamma"))),
p0_(readScalar(dict.lookup("p0"))),
totalPressureTimeSeries_(this->db(), dict)
totalPressureTimeSeries_(dict)
{
if (dict.found("value"))
{
@ -215,7 +214,8 @@ void Foam::timeVaryingUniformTotalPressureFvPatchScalarField::updateCoeffs()
}
void Foam::timeVaryingUniformTotalPressureFvPatchScalarField::write(Ostream& os) const
void Foam::timeVaryingUniformTotalPressureFvPatchScalarField::
write(Ostream& os) const
{
fvPatchScalarField::write(os);
os.writeKeyword("U") << UName_ << token::END_STATEMENT << nl;

View File

@ -62,7 +62,6 @@ surfaceSlipDisplacementPointPatchVectorField
)
:
pointPatchVectorField(p, iF),
surfaceNames_(),
projectMode_(NEAREST),
projectDir_(vector::zero),
wedgePlane_(-1)
@ -78,7 +77,7 @@ surfaceSlipDisplacementPointPatchVectorField
)
:
pointPatchVectorField(p, iF, dict),
surfaceNames_(dict.lookup("projectSurfaces")),
surfacesDict_(dict.subDict("geometry")),
projectMode_(followModeNames_.read(dict.lookup("followMode"))),
projectDir_(dict.lookup("projectDirection")),
wedgePlane_(readLabel(dict.lookup("wedgePlane"))),
@ -96,7 +95,7 @@ surfaceSlipDisplacementPointPatchVectorField
)
:
pointPatchVectorField(p, iF),
surfaceNames_(ppf.surfaceNames()),
surfacesDict_(ppf.surfacesDict()),
projectMode_(ppf.projectMode()),
projectDir_(ppf.projectDir()),
wedgePlane_(ppf.wedgePlane()),
@ -111,7 +110,7 @@ surfaceSlipDisplacementPointPatchVectorField
)
:
pointPatchVectorField(ppf),
surfaceNames_(ppf.surfaceNames()),
surfacesDict_(ppf.surfacesDict()),
projectMode_(ppf.projectMode()),
projectDir_(ppf.projectDir()),
wedgePlane_(ppf.wedgePlane()),
@ -127,7 +126,7 @@ surfaceSlipDisplacementPointPatchVectorField
)
:
pointPatchVectorField(ppf, iF),
surfaceNames_(ppf.surfaceNames()),
surfacesDict_(ppf.surfacesDict()),
projectMode_(ppf.projectMode()),
projectDir_(ppf.projectDir()),
wedgePlane_(ppf.wedgePlane()),
@ -137,14 +136,14 @@ surfaceSlipDisplacementPointPatchVectorField
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
const triSurfaceMeshes& surfaceSlipDisplacementPointPatchVectorField::
const searchableSurfaces& surfaceSlipDisplacementPointPatchVectorField::
surfaces() const
{
if (!surfacesPtr_.valid())
{
surfacesPtr_.reset
(
new triSurfaceMeshes
new searchableSurfaces
(
IOobject
(
@ -155,7 +154,7 @@ surfaces() const
IOobject::MUST_READ,
IOobject::NO_WRITE
),
surfaceNames_
surfacesDict_
)
);
}
@ -215,130 +214,182 @@ void surfaceSlipDisplacementPointPatchVectorField::evaluate
);
const pointField& points0 = motionSolver.points0();
forAll(localPoints, i)
//XXXXXX
pointField start(meshPoints.size());
forAll(start, i)
{
start[i] = points0[meshPoints[i]] + displacement[i];
}
if (projectMode_ == NEAREST)
{
List<pointIndexHit> nearest;
labelList hitSurfaces;
surfaces().findNearest
(
start,
scalarField(start.size(), sqr(projectLen)),
hitSurfaces,
nearest
);
forAll(nearest, i)
{
if (zonePtr && (zonePtr->whichPoint(meshPoints[i]) >= 0))
{
// Fixed point. Reset to point0 location.
//Pout<< " Fixed point:" << meshPoints[i]
// << " coord:" << localPoints[i]
// << " should be at:" << points0[meshPoints[i]]
// << endl;
displacement[i] = points0[meshPoints[i]] - localPoints[i];
}
else
else if (nearest[i].hit())
{
point start(points0[meshPoints[i]] + displacement[i]);
scalar offset = 0;
pointIndexHit intersection;
if (projectMode_ == NEAREST)
{
surfaces().findNearest(start, sqr(projectLen), intersection);
displacement[i] =
nearest[i].hitPoint()
- points0[meshPoints[i]];
}
else
{
// Check if already on surface
surfaces().findNearest(start, sqr(SMALL), intersection);
if (!intersection.hit())
Pout<< " point:" << meshPoints[i]
<< " coord:" << localPoints[i]
<< " did not find any surface within " << projectLen
<< endl;
}
}
}
else
{
// No nearest found. Do intersection
// Do tests on all points. Combine later on.
// 1. Check if already on surface
List<pointIndexHit> nearest;
{
labelList nearestSurface;
surfaces().findNearest
(
start,
scalarField(start.size(), sqr(SMALL)),
nearestSurface,
nearest
);
}
// 2. intersection. (combined later on with information from nearest
// above)
vectorField projectVecs(start.size(), projectVec);
if (projectMode_ == POINTNORMAL)
{
projectVec = projectLen*patch().pointNormals()[i];
projectVecs = projectLen*patch().pointNormals();
}
// Knock out any wedge component
scalarField offset(start.size(), 0.0);
if (wedgePlane_ >= 0 && wedgePlane_ <= vector::nComponents)
{
offset = start[wedgePlane_];
start[wedgePlane_] = 0;
projectVec[wedgePlane_] = 0;
forAll(offset, i)
{
offset[i] = start[i][wedgePlane_];
start[i][wedgePlane_] = 0;
projectVecs[i][wedgePlane_] = 0;
}
}
label rightSurf0, rightSurf1;
pointIndexHit rightHit0, rightHit1;
surfaces().findNearestIntersection
(
start,
start+projectVec,
rightSurf0,
rightHit0,
rightSurf1,
rightHit1
);
// Do intersection
label leftSurf0, leftSurf1;
pointIndexHit leftHit0, leftHit1;
surfaces().findNearestIntersection
(
start,
start-projectVec,
leftSurf0,
leftHit0,
leftSurf1,
leftHit1
);
if (rightHit0.hit())
List<pointIndexHit> rightHit;
{
if (leftHit0.hit())
labelList rightSurf;
surfaces().findAnyIntersection
(
start,
start+projectVecs,
rightSurf,
rightHit
);
}
List<pointIndexHit> leftHit;
{
labelList leftSurf;
surfaces().findAnyIntersection
(
start,
start-projectVecs,
leftSurf,
leftHit
);
}
// 3. Choose either -fixed, nearest, right, left.
forAll(displacement, i)
{
if (zonePtr && (zonePtr->whichPoint(meshPoints[i]) >= 0))
{
// Fixed point. Reset to point0 location.
displacement[i] = points0[meshPoints[i]] - localPoints[i];
}
else if (nearest[i].hit())
{
// Found nearest.
displacement[i] =
nearest[i].hitPoint()
- points0[meshPoints[i]];
}
else
{
pointIndexHit interPt;
if (rightHit[i].hit())
{
if (leftHit[i].hit())
{
if
(
magSqr(rightHit0.hitPoint()-start)
< magSqr(leftHit0.hitPoint()-start)
magSqr(rightHit[i].hitPoint()-start[i])
< magSqr(leftHit[i].hitPoint()-start[i])
)
{
intersection = rightHit0;
interPt = rightHit[i];
}
else
{
intersection = leftHit0;
interPt = leftHit[i];
}
}
else
{
intersection = rightHit0;
interPt = rightHit[i];
}
}
else
{
if (leftHit0.hit())
if (leftHit[i].hit())
{
intersection = leftHit0;
}
}
interPt = leftHit[i];
}
}
// Update *this from intersection point
if (intersection.hit())
if (interPt.hit())
{
point interPt = intersection.hitPoint();
if (wedgePlane_ >= 0 && wedgePlane_ <= vector::nComponents)
{
interPt[wedgePlane_] += offset;
interPt.rawPoint()[wedgePlane_] += offset[i];
}
displacement[i] = interPt-points0[meshPoints[i]];
displacement[i] = interPt.rawPoint()-points0[meshPoints[i]];
}
else
{
Pout<< " point:" << meshPoints[i]
<< " coord:" << localPoints[i]
<< " did not find any intersection between ray from "
<< start-projectVec << " to " << start+projectVec
<< start[i]-projectVecs[i]
<< " to " << start[i]+projectVecs[i]
<< endl;
}
}
}
}
// Get internal field to insert values into
Field<vector>& iF = const_cast<Field<vector>&>(this->internalField());
@ -353,7 +404,7 @@ void surfaceSlipDisplacementPointPatchVectorField::evaluate
void surfaceSlipDisplacementPointPatchVectorField::write(Ostream& os) const
{
pointPatchVectorField::write(os);
os.writeKeyword("projectSurfaces") << surfaceNames_
os.writeKeyword("geometry") << surfacesDict_
<< token::END_STATEMENT << nl;
os.writeKeyword("followMode") << followModeNames_[projectMode_]
<< token::END_STATEMENT << nl;

View File

@ -52,7 +52,7 @@ SourceFiles
#define surfaceSlipDisplacementPointPatchVectorField_H
#include "pointPatchFields.H"
#include "triSurfaceMeshes.H"
#include "searchableSurfaces.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -87,7 +87,7 @@ private:
static const NamedEnum<followMode, 3> followModeNames_;
//- names of surfaces
const fileNameList surfaceNames_;
const dictionary surfacesDict_;
//- How to follow/project onto surface
const followMode projectMode_;
@ -102,7 +102,7 @@ private:
const word frozenPointsZone_;
//- Demand driven: surface to follow
mutable autoPtr<triSurfaceMeshes> surfacesPtr_;
mutable autoPtr<searchableSurfaces> surfacesPtr_;
// Private Member Functions
@ -187,13 +187,13 @@ public:
// Member Functions
//- Surfaces to follow
const fileNameList& surfaceNames() const
const dictionary& surfacesDict() const
{
return surfaceNames_;
return surfacesDict_;
}
//- Surface to follow. Demand loads surfaceNames.
const triSurfaceMeshes& surfaces() const;
const searchableSurfaces& surfaces() const;
//- Mode of projection/following
followMode projectMode() const

View File

@ -53,6 +53,14 @@ indexedOctree/treeDataFace.C
indexedOctree/treeDataPoint.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)/cellSet.C
$(topoSets)/topoSet.C
@ -117,20 +125,10 @@ $(intersectedSurface)/intersectedSurface.C
$(intersectedSurface)/edgeSurface.C
triSurface/triSurfaceSearch/triSurfaceSearch.C
triSurface/octreeData/octreeDataTriSurface.C
triSurface/octreeData/octreeDataTriSurfaceTreeLeaf.C
triSurface/triangleFuncs/triangleFuncs.C
triSurface/searchableSurface/searchableSurface.C
triSurface/searchableSurface/triSurfaceMesh.C
triSurface/searchableSurface/searchableBox.C
triSurface/surfaceFeatures/surfaceFeatures.C
triSurface/triSurfaceMeshes/triSurfaceMeshes.C
triSurface/triSurfaceTools/triSurfaceTools.C
triSurface/triSurfaceTools/geompack/geompack.C

View File

@ -0,0 +1,541 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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"
#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;
}
}
}
}
// ************************************************************************* //

View File

@ -0,0 +1,249 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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
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
// ************************************************************************* //

View File

@ -0,0 +1,328 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "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;
}
}
}
// ************************************************************************* //

View File

@ -0,0 +1,204 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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::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
// ************************************************************************* //

View File

@ -34,15 +34,13 @@ namespace Foam
defineTypeNameAndDebug(searchableSurface, 0);
defineRunTimeSelectionTable(searchableSurface, dict);
//defineRunTimeSelectionTable(searchableSurface, istream);
// Construct named object from dictionary
autoPtr<searchableSurface> searchableSurface::New
(
const word& searchableSurfaceType,
const word& name,
const objectRegistry& obj,
const IOobject& io,
const dictionary& dict
)
{
@ -55,7 +53,7 @@ autoPtr<searchableSurface> searchableSurface::New
FatalErrorIn
(
"searchableSurface::New(const word&, const word&"
", const objectRegistry&, const dictionary&)"
", const IOobject&, const dictionary&)"
) << "Unknown searchableSurface type " << searchableSurfaceType
<< endl << endl
<< "Valid searchableSurface types : " << endl
@ -63,44 +61,15 @@ autoPtr<searchableSurface> searchableSurface::New
<< 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 * * * * * * * * * * * * * * //
Foam::searchableSurface::searchableSurface(const word& name)
Foam::searchableSurface::searchableSurface(const IOobject& io)
:
name_(name)
regIOobject(io)
{}

View File

@ -0,0 +1,322 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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. 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
// ************************************************************************* //

View File

@ -0,0 +1,355 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "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
);
}
// ************************************************************************* //

View File

@ -0,0 +1,187 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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::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
// ************************************************************************* //

View File

@ -0,0 +1,822 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "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;
}
// ************************************************************************* //

View File

@ -0,0 +1,198 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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::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
// ************************************************************************* //

View File

@ -0,0 +1,552 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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"
#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));
}
}
// ************************************************************************* //

View File

@ -54,7 +54,7 @@ namespace Foam
class triSurfaceMesh
:
public searchableSurface,
public objectRegistry,
public objectRegistry, // so we can store fields
public triSurface
{
private:
@ -67,6 +67,12 @@ private:
//- Search tree for boundary edges.
mutable autoPtr<indexedOctree<treeDataEdge> > edgeTree_;
//- Names of regions
mutable wordList regions_;
//- Is surface closed
mutable label surfaceClosed_;
// Private Member Functions
//- Check file existence
@ -76,6 +82,10 @@ private:
const fileName& objectName
);
//- Check whether surface is closed without calculating any permanent
// addressing.
bool isSurfaceClosed() const;
//- Disallow default bitwise copy construct
triSurfaceMesh(const triSurfaceMesh&);
@ -97,11 +107,10 @@ public:
//- Construct read
triSurfaceMesh(const IOobject& io);
//- Construct as searchableSurface
//- Construct from dictionary (used by searchableSurface)
triSurfaceMesh
(
const word& name,
const objectRegistry& obj,
const IOobject& io,
const dictionary& dict
);
@ -128,57 +137,73 @@ public:
// searchableSurface implementation
//- 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
virtual const wordList& regions() const;
//- Whether supports volume type below. I.e. whether is closed.
virtual bool hasVolumeType() const;
// Multiple point queries.
virtual void findNearest
(
const point& sample,
const scalar nearestDistSqr
const pointField& sample,
const scalarField& nearestDistSqr,
List<pointIndexHit>&
) 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
virtual void findLine
(
const point& sample,
const scalar nearestDistSqr
const pointField& start,
const pointField& end,
List<pointIndexHit>&
) 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
virtual void findLineAny
(
const linePointRef& ln,
treeBoundBox& tightest,
point& linePoint
const pointField& start,
const pointField& end,
List<pointIndexHit>&
) const;
//- Find nearest intersection of line between start and end.
virtual pointIndexHit findLine
//- Get all intersections in order from start to end.
virtual void findLineAll
(
const point& start,
const point& end
const pointField& start,
const pointField& end,
List<List<pointIndexHit> >&
) const;
//- Find any intersection of line between start and end.
virtual pointIndexHit findLineAny
//- From a set of points and indices get the region
virtual void getRegion
(
const point& start,
const point& end
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 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;
}
};

View File

@ -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 * * * * * * * * * * * * * //
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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 * * * * * * * * * * * * * //
// ************************************************************************* //

View File

@ -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;
}
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -2,4 +2,4 @@
foamCleanTutorials cases
rm -rf processor*
rm 0/pd.gz 0/alpha1.gz
rm -rf 0/pd.gz 0/alpha1.gz

View File

@ -4,16 +4,13 @@
. $WM_PROJECT_DIR/bin/tools/CleanFunctions
cd constrictedChannel
rm -rf 0 > /dev/null 2>&1
rm Ar-Ar Ar-Ne Ne-Ne > /dev/null 2>&1
rm constant/idList
rm -rf 0
rm -rf Ar-Ar Ar-Ne Ne-Ne
rm -rf constant/idList
cleanCase
cd ..
cd nanoNozzle
rm -rf processor[0-9] > /dev/null 2>&1
rm -rf processor[0-9]
cleanCase
cd ..

View File

@ -4,10 +4,8 @@
. $WM_PROJECT_DIR/bin/tools/CleanFunctions
cd periodicCube
rm -rf 0 > /dev/null 2>&1
rm Ar-Ar > /dev/null 2>&1
rm constant/idList
rm -rf 0
rm -rf Ar-Ar
rm -rf constant/idList
cleanCase
cd ..

View File

@ -24,7 +24,7 @@ do
if [ "$case" = "biconic25-55Run35" ]
then
rm $case/constant/polyMesh/boundary
rm -rf $case/constant/polyMesh/boundary
wclean $case/datToFoam
fi
done