mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
Merge branch 'master' of ssh://noisy/home/noisy2/OpenFOAM/OpenFOAM-dev
This commit is contained in:
@ -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;
|
||||
|
||||
|
||||
@ -22,161 +22,171 @@ 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
|
||||
(
|
||||
// {
|
||||
//{
|
||||
// file "someLine.eMesh";
|
||||
// level 2;
|
||||
// }
|
||||
//}
|
||||
);
|
||||
|
||||
|
||||
// Internal Mesh Refinement
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
// Specifies the areas where the refinement has to be a certain level.
|
||||
// These surfaces have to be closed. Refinement is either inside
|
||||
// (refineInside = true) or outside. (note:insideness or outsideness
|
||||
// is with respect to far away)
|
||||
// Note:that even using these the transition can never be faster than
|
||||
// nBufferLayers!
|
||||
// Note:the refinement level can never be higher than any of the surfaces
|
||||
// they overlap with. See below for the surface refinement level specification.
|
||||
refinementShells
|
||||
(
|
||||
{
|
||||
//type triSurfaceMesh;
|
||||
//name cube1x1x1.stl;
|
||||
type searchableBox;
|
||||
name box1x1x1;
|
||||
min (2.5 -0.5 -0.5);
|
||||
max (3.5 0.5 0.5);
|
||||
|
||||
level 4;
|
||||
refineInside true;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
// Surface based refinement
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
// Curvature. Cosine of angle between two neighbouring surface intersections.
|
||||
// Only used if cell level > minLevel and < maxLevel.
|
||||
curvature 0.5;
|
||||
// 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);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// For snapping
|
||||
snapDict
|
||||
|
||||
|
||||
// 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;
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -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 '\@Make[.A-Za-z]*/[^/]*/@d'\
|
||||
-e '\@/platforms/@d' \
|
||||
> $tmpFile
|
||||
|
||||
tar czpf $packFile --files-from $tmpFile
|
||||
|
||||
78
bin/foamPackThirdPartyBin
Executable file
78
bin/foamPackThirdPartyBin
Executable 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
70
bin/foamPackThirdPartyGeneral
Executable 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
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -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
@ -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
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
562
src/autoMesh/autoHexMesh/autoHexMeshDriver/autoLayerDriver.H
Normal file
562
src/autoMesh/autoHexMesh/autoHexMeshDriver/autoLayerDriver.H
Normal 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
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -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
|
||||
);
|
||||
@ -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>(),
|
||||
776
src/autoMesh/autoHexMesh/autoHexMeshDriver/autoRefineDriver.C
Normal file
776
src/autoMesh/autoHexMesh/autoHexMeshDriver/autoRefineDriver.C
Normal 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_
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
179
src/autoMesh/autoHexMesh/autoHexMeshDriver/autoRefineDriver.H
Normal file
179
src/autoMesh/autoHexMesh/autoHexMeshDriver/autoRefineDriver.H
Normal 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
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
236
src/autoMesh/autoHexMesh/autoHexMeshDriver/autoSnapDriver.H
Normal file
236
src/autoMesh/autoHexMesh/autoHexMeshDriver/autoSnapDriver.H
Normal 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
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -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 * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -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
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,123 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "refinementParameters.H"
|
||||
#include "mathematicalConstants.H"
|
||||
#include "polyMesh.H"
|
||||
#include "globalIndex.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
// Construct from dictionary
|
||||
Foam::refinementParameters::refinementParameters
|
||||
(
|
||||
const dictionary& dict,
|
||||
const label dummy
|
||||
)
|
||||
:
|
||||
maxGlobalCells_(readLabel(dict.lookup("cellLimit"))),
|
||||
maxLocalCells_(readLabel(dict.lookup("procCellLimit"))),
|
||||
minRefineCells_(readLabel(dict.lookup("minimumRefine"))),
|
||||
curvature_(readScalar(dict.lookup("curvature"))),
|
||||
nBufferLayers_(readLabel(dict.lookup("nBufferLayers"))),
|
||||
keepPoints_(dict.lookup("keepPoints"))
|
||||
{}
|
||||
|
||||
|
||||
Foam::refinementParameters::refinementParameters(const dictionary& dict)
|
||||
:
|
||||
maxGlobalCells_(readLabel(dict.lookup("maxGlobalCells"))),
|
||||
maxLocalCells_(readLabel(dict.lookup("maxLocalCells"))),
|
||||
minRefineCells_(readLabel(dict.lookup("minRefinementCells"))),
|
||||
nBufferLayers_(readLabel(dict.lookup("nCellsBetweenLevels"))),
|
||||
keepPoints_(pointField(1, dict.lookup("locationInMesh")))
|
||||
{
|
||||
scalar featAngle(readScalar(dict.lookup("resolveFeatureAngle")));
|
||||
|
||||
if (featAngle < 0 || featAngle > 180)
|
||||
{
|
||||
curvature_ = -GREAT;
|
||||
}
|
||||
else
|
||||
{
|
||||
curvature_ = Foam::cos(featAngle*mathematicalConstant::pi/180.0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
Foam::labelList Foam::refinementParameters::findCells(const polyMesh& mesh)
|
||||
const
|
||||
{
|
||||
// Global calculation engine
|
||||
globalIndex globalCells(mesh.nCells());
|
||||
|
||||
// Cell label per point
|
||||
labelList cellLabels(keepPoints_.size());
|
||||
|
||||
forAll(keepPoints_, i)
|
||||
{
|
||||
const point& keepPoint = keepPoints_[i];
|
||||
|
||||
label localCellI = mesh.findCell(keepPoint);
|
||||
|
||||
label globalCellI = -1;
|
||||
|
||||
if (localCellI != -1)
|
||||
{
|
||||
Pout<< "Found point " << keepPoint << " in cell " << localCellI
|
||||
<< " on processor " << Pstream::myProcNo() << endl;
|
||||
globalCellI = globalCells.toGlobal(localCellI);
|
||||
}
|
||||
|
||||
reduce(globalCellI, maxOp<label>());
|
||||
|
||||
if (globalCellI == -1)
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"refinementParameters::findCells(const polyMesh&) const"
|
||||
) << "Point " << keepPoint
|
||||
<< " is not inside the mesh or on a face or edge." << nl
|
||||
<< "Bounding box of the mesh:" << mesh.bounds()
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
if (globalCells.isLocal(globalCellI))
|
||||
{
|
||||
cellLabels[i] = localCellI;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellLabels[i] = -1;
|
||||
}
|
||||
}
|
||||
return cellLabels;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,154 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Class
|
||||
Foam::refinementParameters
|
||||
|
||||
Description
|
||||
Simple container to keep together refinement specific information.
|
||||
|
||||
SourceFiles
|
||||
refinementParameters.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef refinementParameters_H
|
||||
#define refinementParameters_H
|
||||
|
||||
#include "dictionary.H"
|
||||
#include "pointField.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Class forward declarations
|
||||
class polyMesh;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class refinementParameters Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class refinementParameters
|
||||
{
|
||||
// Private data
|
||||
|
||||
//- Total number of cells
|
||||
const label maxGlobalCells_;
|
||||
|
||||
//- Per processor max number of cells
|
||||
const label maxLocalCells_;
|
||||
|
||||
//- When to stop refining
|
||||
const label minRefineCells_;
|
||||
|
||||
//- Curvature
|
||||
scalar curvature_;
|
||||
|
||||
//- Number of layers between different refinement levels
|
||||
const label nBufferLayers_;
|
||||
|
||||
//- Areas to keep
|
||||
const pointField keepPoints_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
refinementParameters(const refinementParameters&);
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const refinementParameters&);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from dictionary - old syntax
|
||||
refinementParameters(const dictionary& dict, const label dummy);
|
||||
|
||||
//- Construct from dictionary - new syntax
|
||||
refinementParameters(const dictionary& dict);
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Access
|
||||
|
||||
//- Total number of cells
|
||||
label maxGlobalCells() const
|
||||
{
|
||||
return maxGlobalCells_;
|
||||
}
|
||||
|
||||
//- Per processor max number of cells
|
||||
label maxLocalCells() const
|
||||
{
|
||||
return maxLocalCells_;
|
||||
}
|
||||
|
||||
//- When to stop refining
|
||||
label minRefineCells() const
|
||||
{
|
||||
return minRefineCells_;
|
||||
}
|
||||
|
||||
//- Curvature
|
||||
scalar curvature() const
|
||||
{
|
||||
return curvature_;
|
||||
}
|
||||
|
||||
//- Number of layers between different refinement levels
|
||||
label nBufferLayers() const
|
||||
{
|
||||
return nBufferLayers_;
|
||||
}
|
||||
|
||||
//- Areas to keep
|
||||
const pointField& keepPoints() const
|
||||
{
|
||||
return keepPoints_;
|
||||
}
|
||||
|
||||
|
||||
// Other
|
||||
|
||||
//- Checks that cells are in mesh. Returns cells they are in.
|
||||
labelList findCells(const polyMesh&) const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,54 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "snapParameters.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
// Construct from dictionary
|
||||
Foam::snapParameters::snapParameters(const dictionary& dict, const label dummy)
|
||||
:
|
||||
nSmoothPatch_(readLabel(dict.lookup("nSmoothPatch"))),
|
||||
snapTol_(readScalar(dict.lookup("snapTol"))),
|
||||
nSmoothDispl_(readLabel(dict.lookup("nSmoothDispl"))),
|
||||
nSnap_(readLabel(dict.lookup("nSnap")))
|
||||
{}
|
||||
|
||||
|
||||
// Construct from dictionary
|
||||
Foam::snapParameters::snapParameters(const dictionary& dict)
|
||||
:
|
||||
nSmoothPatch_(readLabel(dict.lookup("nSmoothPatch"))),
|
||||
snapTol_(readScalar(dict.lookup("tolerance"))),
|
||||
nSmoothDispl_(readLabel(dict.lookup("nSolveIter"))),
|
||||
nSnap_(readLabel(dict.lookup("nRelaxIter")))
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,129 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Class
|
||||
Foam::snapParameters
|
||||
|
||||
Description
|
||||
Simple container to keep together snap specific information.
|
||||
|
||||
SourceFiles
|
||||
snapParameters.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef snapParameters_H
|
||||
#define snapParameters_H
|
||||
|
||||
#include "dictionary.H"
|
||||
#include "scalar.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Class forward declarations
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class snapParameters Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class snapParameters
|
||||
{
|
||||
// Private data
|
||||
|
||||
const label nSmoothPatch_;
|
||||
|
||||
const scalar snapTol_;
|
||||
|
||||
const label nSmoothDispl_;
|
||||
|
||||
const label nSnap_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
snapParameters(const snapParameters&);
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const snapParameters&);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from dictionary - old syntax
|
||||
snapParameters(const dictionary& dict, const label dummy);
|
||||
|
||||
//- Construct from dictionary - new syntax
|
||||
snapParameters(const dictionary& dict);
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Access
|
||||
|
||||
//- Number of patch smoothing iterations before finding
|
||||
// correspondence to surface
|
||||
label nSmoothPatch() const
|
||||
{
|
||||
return nSmoothPatch_;
|
||||
}
|
||||
|
||||
//- Relative distance for points to be attracted by surface
|
||||
// feature point
|
||||
// or edge. True distance is this factor times local
|
||||
// maximum edge length.
|
||||
scalar snapTol() const
|
||||
{
|
||||
return snapTol_;
|
||||
}
|
||||
|
||||
//- Number of mesh displacement smoothing iterations.
|
||||
label nSmoothDispl() const
|
||||
{
|
||||
return nSmoothDispl_;
|
||||
}
|
||||
|
||||
//- Maximum number of snapping relaxation iterations. Should stop
|
||||
// before upon reaching a correct mesh.
|
||||
label nSnap() const
|
||||
{
|
||||
return nSnap_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
File diff suppressed because it is too large
Load Diff
@ -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>&
|
||||
|
||||
@ -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];
|
||||
@ -1288,7 +1356,6 @@ void Foam::meshRefinement::findCellZoneGeometric
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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 * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -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 * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -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
|
||||
// ~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
465
src/autoMesh/autoHexMesh/shellSurfaces/shellSurfaces.C
Normal file
465
src/autoMesh/autoHexMesh/shellSurfaces/shellSurfaces.C
Normal file
@ -0,0 +1,465 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "searchableSurface.H"
|
||||
#include "shellSurfaces.H"
|
||||
#include "boundBox.H"
|
||||
#include "triSurfaceMesh.H"
|
||||
#include "refinementSurfaces.H"
|
||||
#include "searchableSurfaces.H"
|
||||
#include "pointIndexHit.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
template<>
|
||||
const char*
|
||||
NamedEnum<shellSurfaces::refineMode, 3>::
|
||||
names[] =
|
||||
{
|
||||
"inside",
|
||||
"outside",
|
||||
"distance"
|
||||
};
|
||||
|
||||
const NamedEnum<shellSurfaces::refineMode, 3> shellSurfaces::refineModeNames_;
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::shellSurfaces::setAndCheckLevels
|
||||
(
|
||||
const scalar shellI,
|
||||
const List<Tuple2<scalar, label> >& distLevels
|
||||
)
|
||||
{
|
||||
if (modes_[shellI] != DISTANCE && distLevels.size() != 1)
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"shellSurfaces::shellSurfaces"
|
||||
"(const searchableSurfaces&, const dictionary&)"
|
||||
) << "For refinement mode "
|
||||
<< refineModeNames_[modes_[shellI]]
|
||||
<< " specify only one distance+level."
|
||||
<< " (its distance gets discarded)"
|
||||
<< exit(FatalError);
|
||||
}
|
||||
// Extract information into separate distance and level
|
||||
distances_[shellI].setSize(distLevels.size());
|
||||
levels_[shellI].setSize(distLevels.size());
|
||||
|
||||
forAll(distLevels, j)
|
||||
{
|
||||
distances_[shellI][j] = distLevels[j].first();
|
||||
levels_[shellI][j] = distLevels[j].second();
|
||||
|
||||
// Check in incremental order
|
||||
if (j > 0)
|
||||
{
|
||||
if
|
||||
(
|
||||
(distances_[shellI][j] <= distances_[shellI][j-1])
|
||||
|| (levels_[shellI][j] > levels_[shellI][j-1])
|
||||
)
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"shellSurfaces::shellSurfaces"
|
||||
"(const searchableSurfaces&, const dictionary&)"
|
||||
) << "For refinement mode "
|
||||
<< refineModeNames_[modes_[shellI]]
|
||||
<< " : Refinement should be specified in order"
|
||||
<< " of increasing distance"
|
||||
<< " (and decreasing refinement level)." << endl
|
||||
<< "Distance:" << distances_[shellI][j]
|
||||
<< " refinementLevel:" << levels_[shellI][j]
|
||||
<< exit(FatalError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const searchableSurface& shell = allGeometry_[shells_[shellI]];
|
||||
|
||||
if (modes_[shellI] == DISTANCE)
|
||||
{
|
||||
Info<< "Refinement level according to distance to "
|
||||
<< shell.name() << endl;
|
||||
forAll(levels_[shellI], j)
|
||||
{
|
||||
Info<< " level " << levels_[shellI][j]
|
||||
<< " for all cells within " << distances_[shellI][j]
|
||||
<< " meter." << endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!allGeometry_[shells_[shellI]].hasVolumeType())
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"shellSurfaces::shellSurfaces"
|
||||
"(const searchableSurfaces&"
|
||||
", const PtrList<dictionary>&)"
|
||||
) << "Shell " << shell.name()
|
||||
<< " does not support testing for "
|
||||
<< refineModeNames_[modes_[shellI]] << endl
|
||||
<< "Probably it is not closed."
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
if (modes_[shellI] == INSIDE)
|
||||
{
|
||||
Info<< "Refinement level " << levels_[shellI][0]
|
||||
<< " for all cells inside " << shell.name() << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< "Refinement level " << levels_[shellI][0]
|
||||
<< " for all cells outside " << shell.name() << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Specifically orient triSurfaces using a calculated point outside.
|
||||
// Done since quite often triSurfaces not of consistent orientation which
|
||||
// is (currently) necessary for sideness calculation
|
||||
void Foam::shellSurfaces::orient()
|
||||
{
|
||||
// Determine outside point.
|
||||
boundBox overallBb
|
||||
(
|
||||
point(GREAT, GREAT, GREAT),
|
||||
point(-GREAT, -GREAT, -GREAT)
|
||||
);
|
||||
|
||||
bool hasSurface = false;
|
||||
|
||||
forAll(shells_, shellI)
|
||||
{
|
||||
const searchableSurface& s = allGeometry_[shells_[shellI]];
|
||||
|
||||
if (modes_[shellI] != DISTANCE && isA<triSurfaceMesh>(s))
|
||||
{
|
||||
const triSurfaceMesh& shell = refCast<const triSurfaceMesh>(s);
|
||||
|
||||
if (shell.triSurface::size() > 0)
|
||||
{
|
||||
const pointField& points = shell.points();
|
||||
|
||||
hasSurface = true;
|
||||
|
||||
boundBox shellBb(points[0], points[0]);
|
||||
// Assume surface is compact!
|
||||
for (label i = 0; i < points.size(); i++)
|
||||
{
|
||||
const point& pt = points[i];
|
||||
shellBb.min() = min(shellBb.min(), pt);
|
||||
shellBb.max() = max(shellBb.max(), pt);
|
||||
}
|
||||
|
||||
overallBb.min() = min(overallBb.min(), shellBb.min());
|
||||
overallBb.max() = max(overallBb.max(), shellBb.max());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasSurface)
|
||||
{
|
||||
const point outsidePt(2*overallBb.max() - overallBb.min());
|
||||
|
||||
//Info<< "Using point " << outsidePt << " to orient shells" << endl;
|
||||
|
||||
forAll(shells_, shellI)
|
||||
{
|
||||
const searchableSurface& s = allGeometry_[shells_[shellI]];
|
||||
|
||||
if (modes_[shellI] != DISTANCE && isA<triSurfaceMesh>(s))
|
||||
{
|
||||
triSurfaceMesh& shell = const_cast<triSurfaceMesh&>
|
||||
(
|
||||
refCast<const triSurfaceMesh>(s)
|
||||
);
|
||||
|
||||
refinementSurfaces::orientSurface(outsidePt, shell);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Find maximum level of a shell.
|
||||
void Foam::shellSurfaces::findHigherLevel
|
||||
(
|
||||
const pointField& pt,
|
||||
const label shellI,
|
||||
labelList& maxLevel
|
||||
) const
|
||||
{
|
||||
const labelList& levels = levels_[shellI];
|
||||
|
||||
if (modes_[shellI] == DISTANCE)
|
||||
{
|
||||
// Distance mode.
|
||||
|
||||
const scalarField& distances = distances_[shellI];
|
||||
|
||||
// Collect all those points that have a current maxLevel less than
|
||||
// (any of) the shell. Also collect the furthest distance allowable
|
||||
// to any shell with a higher level.
|
||||
|
||||
pointField candidates(pt.size());
|
||||
labelList candidateMap(pt.size());
|
||||
scalarField candidateDistSqr(pt.size());
|
||||
label candidateI = 0;
|
||||
|
||||
forAll(maxLevel, pointI)
|
||||
{
|
||||
forAllReverse(levels, levelI)
|
||||
{
|
||||
if (levels[levelI] > maxLevel[pointI])
|
||||
{
|
||||
candidates[candidateI] = pt[pointI];
|
||||
candidateMap[candidateI] = pointI;
|
||||
candidateDistSqr[candidateI] = sqr(distances[levelI]);
|
||||
candidateI++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
candidates.setSize(candidateI);
|
||||
candidateMap.setSize(candidateI);
|
||||
candidateDistSqr.setSize(candidateI);
|
||||
|
||||
// Do the expensive nearest test only for the candidate points.
|
||||
List<pointIndexHit> nearInfo;
|
||||
allGeometry_[shells_[shellI]].findNearest
|
||||
(
|
||||
candidates,
|
||||
candidateDistSqr,
|
||||
nearInfo
|
||||
);
|
||||
|
||||
// Update maxLevel
|
||||
forAll(nearInfo, candidateI)
|
||||
{
|
||||
if (nearInfo[candidateI].hit())
|
||||
{
|
||||
// Check which level it actually is in.
|
||||
label minDistI = findLower
|
||||
(
|
||||
distances,
|
||||
mag(nearInfo[candidateI].hitPoint()-candidates[candidateI])
|
||||
);
|
||||
|
||||
label pointI = candidateMap[candidateI];
|
||||
|
||||
// pt is inbetween shell[minDistI] and shell[minDistI+1]
|
||||
maxLevel[pointI] = levels[minDistI+1];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Inside/outside mode
|
||||
|
||||
// Collect all those points that have a current maxLevel less than the
|
||||
// shell.
|
||||
|
||||
pointField candidates(pt.size());
|
||||
labelList candidateMap(pt.size());
|
||||
label candidateI = 0;
|
||||
|
||||
forAll(maxLevel, pointI)
|
||||
{
|
||||
if (levels[0] > maxLevel[pointI])
|
||||
{
|
||||
candidates[candidateI] = pt[pointI];
|
||||
candidateMap[candidateI] = pointI;
|
||||
candidateI++;
|
||||
}
|
||||
}
|
||||
candidates.setSize(candidateI);
|
||||
candidateMap.setSize(candidateI);
|
||||
|
||||
// Do the expensive nearest test only for the candidate points.
|
||||
List<searchableSurface::volumeType> volType;
|
||||
allGeometry_[shells_[shellI]].getVolumeType(candidates, volType);
|
||||
|
||||
forAll(volType, i)
|
||||
{
|
||||
label pointI = candidateMap[i];
|
||||
|
||||
if
|
||||
(
|
||||
(
|
||||
modes_[shellI] == INSIDE
|
||||
&& volType[i] == searchableSurface::INSIDE
|
||||
)
|
||||
|| (
|
||||
modes_[shellI] == OUTSIDE
|
||||
&& volType[i] == searchableSurface::OUTSIDE
|
||||
)
|
||||
)
|
||||
{
|
||||
maxLevel[pointI] = levels[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::shellSurfaces::shellSurfaces
|
||||
(
|
||||
const searchableSurfaces& allGeometry,
|
||||
const PtrList<dictionary>& shellDicts
|
||||
)
|
||||
:
|
||||
allGeometry_(allGeometry)
|
||||
{
|
||||
shells_.setSize(shellDicts.size());
|
||||
modes_.setSize(shellDicts.size());
|
||||
distances_.setSize(shellDicts.size());
|
||||
levels_.setSize(shellDicts.size());
|
||||
|
||||
forAll(shellDicts, shellI)
|
||||
{
|
||||
const dictionary& dict = shellDicts[shellI];
|
||||
const word name = dict.lookup("name");
|
||||
const word type = dict.lookup("type");
|
||||
|
||||
shells_[shellI] = allGeometry_.findSurfaceID(name);
|
||||
|
||||
if (shells_[shellI] == -1)
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"shellSurfaces::shellSurfaces"
|
||||
"(const searchableSurfaces&, const PtrList<dictionary>&)"
|
||||
) << "No surface called " << name << endl
|
||||
<< "Valid surfaces are " << allGeometry_.names()
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
modes_[shellI] = refineModeNames_.read(dict.lookup("refineMode"));
|
||||
|
||||
// Read pairs of distance+level
|
||||
setAndCheckLevels(shellI, dict.lookup("levels"));
|
||||
}
|
||||
|
||||
// Orient shell surfaces before any searching is done. Note that this
|
||||
// only needs to be done for inside or outside. Orienting surfaces
|
||||
// constructs lots of addressing which we want to avoid.
|
||||
orient();
|
||||
}
|
||||
|
||||
|
||||
Foam::shellSurfaces::shellSurfaces
|
||||
(
|
||||
const searchableSurfaces& allGeometry,
|
||||
const dictionary& shellsDict
|
||||
)
|
||||
:
|
||||
allGeometry_(allGeometry)
|
||||
{
|
||||
shells_.setSize(shellsDict.size());
|
||||
modes_.setSize(shellsDict.size());
|
||||
distances_.setSize(shellsDict.size());
|
||||
levels_.setSize(shellsDict.size());
|
||||
|
||||
label shellI = 0;
|
||||
forAllConstIter(dictionary, shellsDict, iter)
|
||||
{
|
||||
shells_[shellI] = allGeometry_.findSurfaceID(iter().keyword());
|
||||
|
||||
if (shells_[shellI] == -1)
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"shellSurfaces::shellSurfaces"
|
||||
"(const searchableSurfaces&, const dictionary>&"
|
||||
) << "No surface called " << iter().keyword() << endl
|
||||
<< "Valid surfaces are " << allGeometry_.names()
|
||||
<< exit(FatalError);
|
||||
}
|
||||
const dictionary& dict = shellsDict.subDict(iter().keyword());
|
||||
|
||||
modes_[shellI] = refineModeNames_.read(dict.lookup("mode"));
|
||||
|
||||
// Read pairs of distance+level
|
||||
setAndCheckLevels(shellI, dict.lookup("levels"));
|
||||
|
||||
shellI++;
|
||||
}
|
||||
|
||||
// Orient shell surfaces before any searching is done. Note that this
|
||||
// only needs to be done for inside or outside. Orienting surfaces
|
||||
// constructs lots of addressing which we want to avoid.
|
||||
orient();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
// Highest shell level
|
||||
Foam::label Foam::shellSurfaces::maxLevel() const
|
||||
{
|
||||
label overallMax = 0;
|
||||
forAll(levels_, shellI)
|
||||
{
|
||||
overallMax = max(overallMax, max(levels_[shellI]));
|
||||
}
|
||||
return overallMax;
|
||||
}
|
||||
|
||||
|
||||
void Foam::shellSurfaces::findHigherLevel
|
||||
(
|
||||
const pointField& pt,
|
||||
const labelList& ptLevel,
|
||||
labelList& maxLevel
|
||||
) const
|
||||
{
|
||||
// Maximum level of any shell. Start off with level of point.
|
||||
maxLevel = ptLevel;
|
||||
|
||||
forAll(shells_, shellI)
|
||||
{
|
||||
findHigherLevel(pt, shellI, maxLevel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
182
src/autoMesh/autoHexMesh/shellSurfaces/shellSurfaces.H
Normal file
182
src/autoMesh/autoHexMesh/shellSurfaces/shellSurfaces.H
Normal file
@ -0,0 +1,182 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Class
|
||||
shellSurfaces
|
||||
|
||||
Description
|
||||
Encapsulates queries for volume refinement ('refine all cells within
|
||||
shell').
|
||||
|
||||
SourceFiles
|
||||
shellSurfaces.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef shellSurfaces_H
|
||||
#define shellSurfaces_H
|
||||
|
||||
#include "searchableSurface.H"
|
||||
#include "Tuple2.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
class searchableSurfaces;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class shellSurfaces Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class shellSurfaces
|
||||
{
|
||||
public:
|
||||
|
||||
// Public data types
|
||||
|
||||
//- Volume refinement controls
|
||||
enum refineMode
|
||||
{
|
||||
INSIDE, // Refine all inside shell
|
||||
OUTSIDE, // ,, outside
|
||||
DISTANCE // Refine based on distance to shell
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Private data
|
||||
|
||||
//- Reference to all geometry.
|
||||
const searchableSurfaces& allGeometry_;
|
||||
|
||||
//- Indices of surfaces that are shells
|
||||
labelList shells_;
|
||||
|
||||
//- Per shell whether to refine inside or outside
|
||||
List<refineMode> modes_;
|
||||
|
||||
//- Per shell the list of ranges
|
||||
List<scalarField> distances_;
|
||||
|
||||
//- Per shell per distance the refinement level
|
||||
labelListList levels_;
|
||||
|
||||
|
||||
// Private data
|
||||
|
||||
//- refineMode names
|
||||
static const NamedEnum<refineMode, 3> refineModeNames_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Helper function for initialisation.
|
||||
void setAndCheckLevels
|
||||
(
|
||||
const scalar shellI,
|
||||
const List<Tuple2<scalar, label> >&
|
||||
);
|
||||
|
||||
void orient();
|
||||
|
||||
void findHigherLevel
|
||||
(
|
||||
const pointField& pt,
|
||||
const label shellI,
|
||||
labelList& maxLevel
|
||||
) const;
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
shellSurfaces
|
||||
(
|
||||
const searchableSurfaces& allGeometry,
|
||||
const labelList& shells,
|
||||
const List<refineMode>& modes,
|
||||
const List<scalarField>& distances,
|
||||
const labelListList& levels
|
||||
);
|
||||
|
||||
//- Construct from geometry and dictionaries
|
||||
shellSurfaces
|
||||
(
|
||||
const searchableSurfaces& allGeometry,
|
||||
const PtrList<dictionary>& shellDicts
|
||||
);
|
||||
|
||||
//- Construct from geometry and dictionary
|
||||
shellSurfaces
|
||||
(
|
||||
const searchableSurfaces& allGeometry,
|
||||
const dictionary& shellsDict
|
||||
);
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Access
|
||||
|
||||
//const List<scalarField>& distances() const
|
||||
//{
|
||||
// return distances_;
|
||||
//}
|
||||
//
|
||||
////- Per shell per distance the refinement level
|
||||
//const labelListList& levels() const
|
||||
//{
|
||||
// return levels_;
|
||||
//}
|
||||
|
||||
|
||||
// Query
|
||||
|
||||
//- Highest shell level
|
||||
label maxLevel() const;
|
||||
|
||||
//- Find shell level higher than ptLevel
|
||||
void findHigherLevel
|
||||
(
|
||||
const pointField& pt,
|
||||
const labelList& ptLevel,
|
||||
labelList& maxLevel
|
||||
) const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -256,7 +256,7 @@ Foam::Ostream& Foam::operator<<
|
||||
const ExactParticle<ParticleType>& p
|
||||
)
|
||||
{
|
||||
return operator<<(os, static_cast<Particle<ParticleType> >(p));
|
||||
return operator<<(os, static_cast<const Particle<ParticleType>&>(p));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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"))
|
||||
{
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
541
src/meshTools/searchableSurface/searchableBox.C
Normal file
541
src/meshTools/searchableSurface/searchableBox.C
Normal file
@ -0,0 +1,541 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
249
src/meshTools/searchableSurface/searchableBox.H
Normal file
249
src/meshTools/searchableSurface/searchableBox.H
Normal file
@ -0,0 +1,249 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-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
|
||||
|
||||
// ************************************************************************* //
|
||||
328
src/meshTools/searchableSurface/searchableSphere.C
Normal file
328
src/meshTools/searchableSurface/searchableSphere.C
Normal file
@ -0,0 +1,328 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
204
src/meshTools/searchableSurface/searchableSphere.H
Normal file
204
src/meshTools/searchableSurface/searchableSphere.H
Normal file
@ -0,0 +1,204 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-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
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -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)
|
||||
{}
|
||||
|
||||
|
||||
322
src/meshTools/searchableSurface/searchableSurface.H
Normal file
322
src/meshTools/searchableSurface/searchableSurface.H
Normal file
@ -0,0 +1,322 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-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
|
||||
|
||||
// ************************************************************************* //
|
||||
355
src/meshTools/searchableSurface/searchableSurfaces.C
Normal file
355
src/meshTools/searchableSurface/searchableSurfaces.C
Normal file
@ -0,0 +1,355 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-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
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
187
src/meshTools/searchableSurface/searchableSurfaces.H
Normal file
187
src/meshTools/searchableSurface/searchableSurfaces.H
Normal file
@ -0,0 +1,187 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-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
|
||||
|
||||
// ************************************************************************* //
|
||||
822
src/meshTools/searchableSurface/searchableSurfacesQueries.C
Normal file
822
src/meshTools/searchableSurface/searchableSurfacesQueries.C
Normal file
@ -0,0 +1,822 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
198
src/meshTools/searchableSurface/searchableSurfacesQueries.H
Normal file
198
src/meshTools/searchableSurface/searchableSurfacesQueries.H
Normal file
@ -0,0 +1,198 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-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
|
||||
|
||||
// ************************************************************************* //
|
||||
552
src/meshTools/searchableSurface/triSurfaceMesh.C
Normal file
552
src/meshTools/searchableSurface/triSurfaceMesh.C
Normal file
@ -0,0 +1,552 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -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;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@ -1,247 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "searchableBox.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
defineTypeNameAndDebug(searchableBox, 0);
|
||||
addToRunTimeSelectionTable(searchableSurface, searchableBox, dict);
|
||||
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::searchableBox::searchableBox
|
||||
(
|
||||
const word& name,
|
||||
const treeBoundBox& bb
|
||||
)
|
||||
:
|
||||
searchableSurface(name),
|
||||
treeBoundBox(bb)
|
||||
{}
|
||||
|
||||
|
||||
Foam::searchableBox::searchableBox
|
||||
(
|
||||
const word& name,
|
||||
const objectRegistry& obj,
|
||||
const dictionary& dict
|
||||
)
|
||||
:
|
||||
searchableSurface(name),
|
||||
treeBoundBox(dict.lookup("min"), dict.lookup("max"))
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::searchableBox::~searchableBox()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
Foam::pointIndexHit Foam::searchableBox::findNearest
|
||||
(
|
||||
const point& sample,
|
||||
const scalar nearestDistSqr
|
||||
) const
|
||||
{
|
||||
// Point can be inside or outside. For every component direction can be
|
||||
// left of min, right of max or inbetween.
|
||||
// - outside points: project first one x plane (either min().x()
|
||||
// or max().x()), then onto y plane and finally z. You should be left
|
||||
// with intersection point
|
||||
// - inside point: find nearest side (compare to mid point). Pick any
|
||||
// one of three points.
|
||||
|
||||
const point bbMid(mid());
|
||||
|
||||
// Outside point projected onto cube
|
||||
point interPt(sample);
|
||||
bool outside = false;
|
||||
|
||||
// (for internal points) Per direction what nearest cube side is
|
||||
point near;
|
||||
|
||||
for (direction dir = 0; dir < vector::nComponents; dir++)
|
||||
{
|
||||
if (interPt[dir] < min()[dir])
|
||||
{
|
||||
interPt[dir] = min()[dir];
|
||||
outside = true;
|
||||
}
|
||||
else if (interPt[dir] > max()[dir])
|
||||
{
|
||||
interPt[dir] = max()[dir];
|
||||
outside = true;
|
||||
}
|
||||
else if (interPt[dir] > bbMid[dir])
|
||||
{
|
||||
near[dir] = max()[dir];
|
||||
}
|
||||
else
|
||||
{
|
||||
near[dir] = min()[dir];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// For outside points the interPt will be correct now. Handle inside points
|
||||
// using the three near distances. Project onto the nearest plane.
|
||||
if (!outside)
|
||||
{
|
||||
vector dist(cmptMag(interPt - near));
|
||||
|
||||
if (dist.x() < dist.y())
|
||||
{
|
||||
if (dist.x() < dist.z())
|
||||
{
|
||||
interPt.x() = near.x();
|
||||
}
|
||||
else
|
||||
{
|
||||
interPt.z() = near.z();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dist.y() < dist.z())
|
||||
{
|
||||
interPt.y() = near.y();
|
||||
}
|
||||
else
|
||||
{
|
||||
interPt.z() = near.z();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pointIndexHit(true, interPt, 0);
|
||||
}
|
||||
|
||||
|
||||
Foam::pointIndexHit Foam::searchableBox::findNearestOnEdge
|
||||
(
|
||||
const point& sample,
|
||||
const scalar nearestDistSqr
|
||||
) const
|
||||
{
|
||||
const point bbMid(mid());
|
||||
|
||||
point interPt(sample);
|
||||
|
||||
for (direction dir = 0; dir < vector::nComponents; dir++)
|
||||
{
|
||||
// Project onto left or right depending on mid
|
||||
if (interPt[dir] > bbMid[dir])
|
||||
{
|
||||
interPt[dir] = max()[dir];
|
||||
}
|
||||
else
|
||||
{
|
||||
interPt[dir] = min()[dir];
|
||||
}
|
||||
}
|
||||
|
||||
return pointIndexHit(true, interPt, 0);
|
||||
}
|
||||
|
||||
|
||||
Foam::pointIndexHit Foam::searchableBox::findNearest
|
||||
(
|
||||
const linePointRef& ln,
|
||||
treeBoundBox& tightest,
|
||||
point& linePoint
|
||||
) const
|
||||
{
|
||||
notImplemented
|
||||
(
|
||||
"searchableBox::findNearest"
|
||||
"(const linePointRef&, treeBoundBox&, point&)"
|
||||
);
|
||||
return pointIndexHit();
|
||||
}
|
||||
|
||||
|
||||
Foam::pointIndexHit Foam::searchableBox::findLine
|
||||
(
|
||||
const point& start,
|
||||
const point& end
|
||||
) const
|
||||
{
|
||||
point intPt;
|
||||
bool foundInter = intersects(start, end, intPt);
|
||||
|
||||
return pointIndexHit(foundInter, intPt, 0);
|
||||
}
|
||||
|
||||
|
||||
Foam::pointIndexHit Foam::searchableBox::findLineAny
|
||||
(
|
||||
const point& start,
|
||||
const point& end
|
||||
) const
|
||||
{
|
||||
return findLine(start, end);
|
||||
}
|
||||
|
||||
|
||||
Foam::searchableSurface::volumeType Foam::searchableBox::getVolumeType
|
||||
(
|
||||
const point& pt
|
||||
) const
|
||||
{
|
||||
for (direction dir = 0; dir < vector::nComponents; dir++)
|
||||
{
|
||||
if (pt[dir] < min()[dir] || pt[dir] > max()[dir])
|
||||
{
|
||||
return OUTSIDE;
|
||||
}
|
||||
}
|
||||
|
||||
return INSIDE;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,161 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Class
|
||||
Foam::searchableBox
|
||||
|
||||
Description
|
||||
Searching on bounding box
|
||||
|
||||
SourceFiles
|
||||
searchableBox.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef searchableBox_H
|
||||
#define searchableBox_H
|
||||
|
||||
#include "searchableSurface.H"
|
||||
#include "treeBoundBox.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward declaration of classes
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class searchableBox Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class searchableBox
|
||||
:
|
||||
public searchableSurface,
|
||||
public treeBoundBox
|
||||
{
|
||||
private:
|
||||
|
||||
// Private member data
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
searchableBox(const searchableBox&);
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const searchableBox&);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("searchableBox");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
searchableBox(const word& name, const treeBoundBox& bb);
|
||||
|
||||
searchableBox
|
||||
(
|
||||
const word& name,
|
||||
const objectRegistry& obj,
|
||||
const dictionary& dict
|
||||
);
|
||||
|
||||
// Destructor
|
||||
|
||||
virtual ~searchableBox();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Calculate nearest point on surface. Returns
|
||||
// - bool : any point found nearer than nearestDistSqr
|
||||
// - label: relevant index in surface
|
||||
// - point: actual nearest point found
|
||||
virtual pointIndexHit findNearest
|
||||
(
|
||||
const point& sample,
|
||||
const scalar nearestDistSqr
|
||||
) const;
|
||||
|
||||
//- Calculate nearest point on edge. Returns
|
||||
// - bool : any point found nearer than nearestDistSqr
|
||||
// - label: relevant index in surface
|
||||
// - point: actual nearest point found
|
||||
virtual pointIndexHit findNearestOnEdge
|
||||
(
|
||||
const point& sample,
|
||||
const scalar nearestDistSqr
|
||||
) const;
|
||||
|
||||
//- Find nearest to line. Returns
|
||||
// - bool : any point found?
|
||||
// - label: relevant index in shapes
|
||||
// - point: actual nearest point found
|
||||
// sets:
|
||||
// - tightest : bounding box
|
||||
// - linePoint : corresponding nearest point on line
|
||||
virtual pointIndexHit findNearest
|
||||
(
|
||||
const linePointRef& ln,
|
||||
treeBoundBox& tightest,
|
||||
point& linePoint
|
||||
) const;
|
||||
|
||||
//- Find nearest intersection of line between start and end.
|
||||
virtual pointIndexHit findLine
|
||||
(
|
||||
const point& start,
|
||||
const point& end
|
||||
) const;
|
||||
|
||||
//- Find any intersection of line between start and end.
|
||||
virtual pointIndexHit findLineAny
|
||||
(
|
||||
const point& start,
|
||||
const point& end
|
||||
) const;
|
||||
|
||||
//- Determine type (inside/outside/mixed) for point. unknown if
|
||||
// cannot be determined (e.g. non-manifold surface)
|
||||
virtual volumeType getVolumeType(const point&) const;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,257 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Class
|
||||
Foam::searchableSurface
|
||||
|
||||
Description
|
||||
Base class of (analytical or triangulated) surface.
|
||||
Encapsulates all the search routines.
|
||||
|
||||
SourceFiles
|
||||
searchableSurface.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef searchableSurface_H
|
||||
#define searchableSurface_H
|
||||
|
||||
#include "pointField.H"
|
||||
#include "typeInfo.H"
|
||||
#include "runTimeSelectionTables.H"
|
||||
#include "pointIndexHit.H"
|
||||
#include "linePointRef.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward declaration of classes
|
||||
class objectRegistry;
|
||||
class treeBoundBox;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class searchableSurface Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class searchableSurface
|
||||
{
|
||||
public:
|
||||
|
||||
// Data types
|
||||
|
||||
//- volume types
|
||||
enum volumeType
|
||||
{
|
||||
UNKNOWN = 0,
|
||||
MIXED = 1,
|
||||
INSIDE = 2,
|
||||
OUTSIDE = 3
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
// Private data
|
||||
|
||||
const word name_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
searchableSurface(const searchableSurface&);
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const searchableSurface&);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("searchableSurface");
|
||||
|
||||
// Declare run-time constructor selection table
|
||||
|
||||
// For the dictionary constructor
|
||||
declareRunTimeSelectionTable
|
||||
(
|
||||
autoPtr,
|
||||
searchableSurface,
|
||||
dict,
|
||||
(
|
||||
const word& name,
|
||||
const objectRegistry& obj,
|
||||
const dictionary& dict
|
||||
),
|
||||
(name, obj, dict)
|
||||
);
|
||||
|
||||
//// For the Istream constructor
|
||||
//declareRunTimeSelectionTable
|
||||
//(
|
||||
// autoPtr,
|
||||
// searchableSurface,
|
||||
// istream,
|
||||
// (
|
||||
// const objectRegistry& obj,
|
||||
// Istream& is
|
||||
// ),
|
||||
// (obj, is)
|
||||
//);
|
||||
|
||||
|
||||
//- Class used for the read-construction of
|
||||
// PtrLists of searchableSurface
|
||||
class iNew
|
||||
{
|
||||
const objectRegistry& obj_;
|
||||
|
||||
public:
|
||||
|
||||
iNew(const objectRegistry& obj)
|
||||
:
|
||||
obj_(obj)
|
||||
{}
|
||||
|
||||
autoPtr<searchableSurface> operator()(Istream& is) const
|
||||
{
|
||||
word surfaceType(is);
|
||||
word name(is);
|
||||
dictionary dict(is);
|
||||
return searchableSurface::New(surfaceType, name, obj_, dict);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
searchableSurface(const word& name);
|
||||
|
||||
//- Clone
|
||||
virtual autoPtr<searchableSurface> clone() const
|
||||
{
|
||||
notImplemented("autoPtr<searchableSurface> clone() const");
|
||||
return autoPtr<searchableSurface>(NULL);
|
||||
}
|
||||
|
||||
|
||||
// Selectors
|
||||
|
||||
//- Return a reference to the selected searchableSurface
|
||||
static autoPtr<searchableSurface> New
|
||||
(
|
||||
const word& surfaceType,
|
||||
const word& name,
|
||||
const objectRegistry& obj,
|
||||
const dictionary& dict
|
||||
);
|
||||
|
||||
////- Return a reference to the selected searchableSurface
|
||||
//static autoPtr<searchableSurface> New
|
||||
//(
|
||||
// const word& surfaceType,
|
||||
// const objectRegistry& obj,
|
||||
// Istream& is
|
||||
//);
|
||||
|
||||
|
||||
// Destructor
|
||||
|
||||
virtual ~searchableSurface();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Return name
|
||||
const word& name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
//- Calculate nearest point on surface. Returns
|
||||
// - bool : any point found nearer than nearestDistSqr
|
||||
// - label: relevant index in surface
|
||||
// - point: actual nearest point found
|
||||
virtual pointIndexHit findNearest
|
||||
(
|
||||
const point& sample,
|
||||
const scalar nearestDistSqr
|
||||
) const = 0;
|
||||
|
||||
//- Calculate nearest point on edge. Returns
|
||||
// - bool : any point found nearer than nearestDistSqr
|
||||
// - label: relevant index in surface
|
||||
// - point: actual nearest point found
|
||||
virtual pointIndexHit findNearestOnEdge
|
||||
(
|
||||
const point& sample,
|
||||
const scalar nearestDistSqr
|
||||
) const = 0;
|
||||
|
||||
//- Find nearest to segment. Returns
|
||||
// - bool : any point found?
|
||||
// - label: relevant index in shapes
|
||||
// - point: actual nearest point found
|
||||
// sets:
|
||||
// - tightest : bounding box
|
||||
// - linePoint : corresponding nearest point on line
|
||||
virtual pointIndexHit findNearest
|
||||
(
|
||||
const linePointRef& ln,
|
||||
treeBoundBox& tightest,
|
||||
point& linePoint
|
||||
) const = 0;
|
||||
|
||||
//- Find nearest intersection of line between start and end.
|
||||
virtual pointIndexHit findLine
|
||||
(
|
||||
const point& start,
|
||||
const point& end
|
||||
) const = 0;
|
||||
|
||||
//- Find any intersection of line between start and end.
|
||||
virtual pointIndexHit findLineAny
|
||||
(
|
||||
const point& start,
|
||||
const point& end
|
||||
) const = 0;
|
||||
|
||||
//- Determine type (inside/outside/mixed) for point. unknown if
|
||||
// cannot be determined (e.g. non-manifold surface)
|
||||
virtual volumeType getVolumeType(const point&) const = 0;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,271 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "triSurfaceMesh.H"
|
||||
#include "Random.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
defineTypeNameAndDebug(triSurfaceMesh, 0);
|
||||
addToRunTimeSelectionTable(searchableSurface, triSurfaceMesh, dict);
|
||||
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
//- Check file existence
|
||||
const Foam::fileName& Foam::triSurfaceMesh::checkFile
|
||||
(
|
||||
const fileName& fName,
|
||||
const fileName& objectName
|
||||
)
|
||||
{
|
||||
if (fName == fileName::null)
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"triSurfaceMesh::checkFile(const fileName&, const fileName&)"
|
||||
) << "Cannot find triSurfaceMesh starting from "
|
||||
<< objectName << exit(FatalError);
|
||||
}
|
||||
return fName;
|
||||
}
|
||||
|
||||
|
||||
const Foam::indexedOctree<Foam::treeDataTriSurface>&
|
||||
Foam::triSurfaceMesh::tree() const
|
||||
{
|
||||
if (!tree_.valid())
|
||||
{
|
||||
treeBoundBox bb(points(), meshPoints());
|
||||
|
||||
// Random number generator. Bit dodgy since not exactly random ;-)
|
||||
Random rndGen(65431);
|
||||
|
||||
tree_.reset
|
||||
(
|
||||
new indexedOctree<treeDataTriSurface>
|
||||
(
|
||||
treeDataTriSurface(*this),
|
||||
bb.extend(rndGen, 1E-3), // slightly randomize bb
|
||||
8, // maxLevel
|
||||
10, // leafsize
|
||||
3.0 // duplicity
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return tree_();
|
||||
}
|
||||
|
||||
|
||||
const Foam::indexedOctree<Foam::treeDataEdge>&
|
||||
Foam::triSurfaceMesh::edgeTree() const
|
||||
{
|
||||
if (!edgeTree_.valid())
|
||||
{
|
||||
treeBoundBox bb(localPoints());
|
||||
|
||||
// Boundary edges
|
||||
labelList bEdges
|
||||
(
|
||||
identity
|
||||
(
|
||||
nEdges()
|
||||
-nInternalEdges()
|
||||
)
|
||||
+ nInternalEdges()
|
||||
);
|
||||
|
||||
// Random number generator. Bit dodgy since not exactly random ;-)
|
||||
Random rndGen(65431);
|
||||
|
||||
edgeTree_.reset
|
||||
(
|
||||
new indexedOctree<treeDataEdge>
|
||||
(
|
||||
treeDataEdge
|
||||
(
|
||||
false, // cachebb
|
||||
edges(), // edges
|
||||
localPoints(), // points
|
||||
bEdges // selected edges
|
||||
),
|
||||
bb.extend(rndGen, 1E-3), // slightly randomize bb
|
||||
8, // maxLevel
|
||||
10, // leafsize
|
||||
3.0 // duplicity
|
||||
)
|
||||
);
|
||||
}
|
||||
return edgeTree_();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
//- Construct from triangles, patches, points.
|
||||
Foam::triSurfaceMesh::triSurfaceMesh(const IOobject& io, const triSurface& s)
|
||||
:
|
||||
searchableSurface(io.name()),
|
||||
objectRegistry(io),
|
||||
triSurface(s)
|
||||
{}
|
||||
|
||||
|
||||
Foam::triSurfaceMesh::triSurfaceMesh(const IOobject& io)
|
||||
:
|
||||
searchableSurface(io.name()),
|
||||
objectRegistry(io),
|
||||
triSurface(checkFile(filePath(), objectPath()))
|
||||
{}
|
||||
|
||||
|
||||
Foam::triSurfaceMesh::triSurfaceMesh
|
||||
(
|
||||
const word& name,
|
||||
const objectRegistry& obj,
|
||||
const dictionary& dict
|
||||
)
|
||||
:
|
||||
searchableSurface(name),
|
||||
objectRegistry
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
name,
|
||||
"constant",
|
||||
"triSurface",
|
||||
obj,
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE
|
||||
)
|
||||
),
|
||||
triSurface(checkFile(filePath(), objectPath()))
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::triSurfaceMesh::~triSurfaceMesh()
|
||||
{}
|
||||
|
||||
|
||||
void Foam::triSurfaceMesh::clearOut()
|
||||
{
|
||||
tree_.clear();
|
||||
edgeTree_.clear();
|
||||
triSurface::clearOut();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::triSurfaceMesh::movePoints(const pointField& newPoints)
|
||||
{
|
||||
tree_.clear();
|
||||
edgeTree_.clear();
|
||||
triSurface::movePoints(newPoints);
|
||||
}
|
||||
|
||||
|
||||
Foam::pointIndexHit Foam::triSurfaceMesh::findNearest
|
||||
(
|
||||
const point& sample,
|
||||
const scalar nearestDistSqr
|
||||
) const
|
||||
{
|
||||
return tree().findNearest(sample, nearestDistSqr);
|
||||
}
|
||||
|
||||
|
||||
Foam::pointIndexHit Foam::triSurfaceMesh::findNearestOnEdge
|
||||
(
|
||||
const point& sample,
|
||||
const scalar nearestDistSqr
|
||||
) const
|
||||
{
|
||||
return edgeTree().findNearest(sample, nearestDistSqr);
|
||||
}
|
||||
|
||||
|
||||
Foam::pointIndexHit Foam::triSurfaceMesh::findNearest
|
||||
(
|
||||
const linePointRef& ln,
|
||||
treeBoundBox& tightest,
|
||||
point& linePoint
|
||||
) const
|
||||
{
|
||||
return tree().findNearest(ln, tightest, linePoint);
|
||||
}
|
||||
|
||||
|
||||
Foam::pointIndexHit Foam::triSurfaceMesh::findLine
|
||||
(
|
||||
const point& start,
|
||||
const point& end
|
||||
) const
|
||||
{
|
||||
return tree().findLine(start, end);
|
||||
}
|
||||
|
||||
|
||||
Foam::pointIndexHit Foam::triSurfaceMesh::findLineAny
|
||||
(
|
||||
const point& start,
|
||||
const point& end
|
||||
) const
|
||||
{
|
||||
return tree().findLineAny(start, end);
|
||||
}
|
||||
|
||||
|
||||
Foam::searchableSurface::volumeType
|
||||
Foam::triSurfaceMesh::getVolumeType
|
||||
(
|
||||
const point& pt
|
||||
) const
|
||||
{
|
||||
// - use cached volume type per each tree node
|
||||
// - cheat conversion since same values
|
||||
return static_cast<volumeType>(tree().getVolumeType(pt));
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,916 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
\*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "triSurfaceMeshes.H"
|
||||
#include "Random.H"
|
||||
#include "Time.H"
|
||||
#include "SortableList.H"
|
||||
#include "IOmanip.H"
|
||||
#include "plane.H"
|
||||
#include "SortableList.H"
|
||||
#include "triSurfaceTools.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
defineTypeNameAndDebug(triSurfaceMeshes, 0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
// Calculate sum of distance to surfaces.
|
||||
Foam::scalar Foam::triSurfaceMeshes::sumDistSqr
|
||||
(
|
||||
const labelList& surfacesToTest,
|
||||
const scalar initDistSqr,
|
||||
const point& pt
|
||||
) const
|
||||
{
|
||||
scalar sum = 0;
|
||||
|
||||
forAll(surfacesToTest, i)
|
||||
{
|
||||
label surfI = surfacesToTest[i];
|
||||
|
||||
pointIndexHit hit(operator[](surfI).findNearest(pt, initDistSqr));
|
||||
|
||||
// Note: make it fall over if not hit.
|
||||
sum += magSqr(hit.hitPoint()-pt);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
||||
// Reflects the point furthest away around the triangle centre by a factor fac.
|
||||
// (triangle centre is the average of all points but the ihi. pSum is running
|
||||
// sum of all points)
|
||||
Foam::scalar Foam::triSurfaceMeshes::tryMorphTet
|
||||
(
|
||||
const labelList& surfacesToTest,
|
||||
const scalar initDistSqr,
|
||||
List<vector>& p,
|
||||
List<scalar>& y,
|
||||
vector& pSum,
|
||||
const label ihi,
|
||||
const scalar fac
|
||||
) const
|
||||
{
|
||||
scalar fac1 = (1.0-fac)/vector::nComponents;
|
||||
scalar fac2 = fac1-fac;
|
||||
|
||||
vector ptry = pSum*fac1-p[ihi]*fac2;
|
||||
|
||||
scalar ytry = sumDistSqr(surfacesToTest, initDistSqr, ptry);
|
||||
|
||||
if (ytry < y[ihi])
|
||||
{
|
||||
y[ihi] = ytry;
|
||||
pSum += ptry - p[ihi];
|
||||
p[ihi] = ptry;
|
||||
}
|
||||
return ytry;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::triSurfaceMeshes::morphTet
|
||||
(
|
||||
const labelList& surfacesToTest,
|
||||
const scalar initDistSqr,
|
||||
const scalar convergenceDistSqr,
|
||||
const label maxIter,
|
||||
List<vector>& p,
|
||||
List<scalar>& y
|
||||
) const
|
||||
{
|
||||
vector pSum = sum(p);
|
||||
|
||||
autoPtr<OFstream> str;
|
||||
label vertI = 0;
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "triSurfaceMeshes::morphTet : intersection of "
|
||||
<< IndirectList<fileName>(names(), surfacesToTest)()
|
||||
<< " starting from points:" << p << endl;
|
||||
str.reset(new OFstream("track.obj"));
|
||||
meshTools::writeOBJ(str(), p[0]);
|
||||
vertI++;
|
||||
}
|
||||
|
||||
for (label iter = 0; iter < maxIter; iter++)
|
||||
{
|
||||
// Get the indices of highest, second-highest and lowest values.
|
||||
label ihi, inhi, ilo;
|
||||
{
|
||||
SortableList<scalar> sortedY(y);
|
||||
ilo = sortedY.indices()[0];
|
||||
ihi = sortedY.indices()[sortedY.size()-1];
|
||||
inhi = sortedY.indices()[sortedY.size()-2];
|
||||
}
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "Iteration:" << iter
|
||||
<< " lowest:" << y[ilo] << " highest:" << y[ihi]
|
||||
<< " points:" << p << endl;
|
||||
|
||||
meshTools::writeOBJ(str(), p[ilo]);
|
||||
vertI++;
|
||||
str()<< "l " << vertI-1 << ' ' << vertI << nl;
|
||||
}
|
||||
|
||||
if (y[ihi] < convergenceDistSqr)
|
||||
{
|
||||
// Get point on 0th surface.
|
||||
Swap(p[0], p[ilo]);
|
||||
Swap(y[0], y[ilo]);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Reflection: point furthest away gets reflected.
|
||||
scalar ytry = tryMorphTet
|
||||
(
|
||||
surfacesToTest,
|
||||
10*y[ihi], // search box.
|
||||
p,
|
||||
y,
|
||||
pSum,
|
||||
ihi,
|
||||
-1.0
|
||||
);
|
||||
|
||||
if (ytry <= y[ilo])
|
||||
{
|
||||
// If in right direction (y lower) expand by two.
|
||||
ytry = tryMorphTet(surfacesToTest, 10*y[ihi], p, y, pSum, ihi, 2.0);
|
||||
}
|
||||
else if (ytry >= y[inhi])
|
||||
{
|
||||
// If inside tet try contraction.
|
||||
|
||||
scalar ysave = y[ihi];
|
||||
|
||||
ytry = tryMorphTet(surfacesToTest, 10*y[ihi], p, y, pSum, ihi, 0.5);
|
||||
|
||||
if (ytry >= ysave)
|
||||
{
|
||||
// Contract around lowest point.
|
||||
forAll(p, i)
|
||||
{
|
||||
if (i != ilo)
|
||||
{
|
||||
p[i] = 0.5*(p[i] + p[ilo]);
|
||||
y[i] = sumDistSqr(surfacesToTest, y[ihi], p[i]);
|
||||
}
|
||||
}
|
||||
pSum = sum(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (debug)
|
||||
{
|
||||
meshTools::writeOBJ(str(), p[0]);
|
||||
vertI++;
|
||||
str()<< "l " << vertI-1 << ' ' << vertI << nl;
|
||||
}
|
||||
|
||||
// Failure to converge. Return best guess so far.
|
||||
label ilo = findMin(y);
|
||||
Swap(p[0], p[ilo]);
|
||||
Swap(y[0], y[ilo]);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
// Construct from components
|
||||
Foam::triSurfaceMeshes::triSurfaceMeshes
|
||||
(
|
||||
const IOobject& io,
|
||||
const fileNameList& names
|
||||
)
|
||||
:
|
||||
PtrList<triSurfaceMesh>(names.size()),
|
||||
allSurfaces_(identity(names.size()))
|
||||
{
|
||||
forAll(names, i)
|
||||
{
|
||||
autoPtr<IOobject> surfaceIO = io.clone();
|
||||
surfaceIO().rename(names[i]);
|
||||
|
||||
Info<< "Loading surface " << surfaceIO().name() << endl;
|
||||
|
||||
//fileName fullPath = surfaceIO().filePath();
|
||||
//
|
||||
//if (fullPath.size() == 0)
|
||||
//{
|
||||
// FatalErrorIn
|
||||
// (
|
||||
// "triSurfaceMeshes::triSurfaceMeshes"
|
||||
// "(const IOobject&, const fileNameList&)"
|
||||
// ) << "Cannot load surface " << surfaceIO().name()
|
||||
// << " starting from path " << surfaceIO().path()
|
||||
// << exit(FatalError);
|
||||
//}
|
||||
|
||||
set(i, new triSurfaceMesh(surfaceIO()));
|
||||
|
||||
if (Pstream::master())
|
||||
{
|
||||
string oldPrefix(Pout.prefix());
|
||||
Pout.prefix() += " ";
|
||||
operator[](i).writeStats(Pout);
|
||||
Pout.prefix() = oldPrefix;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
Foam::fileNameList Foam::triSurfaceMeshes::allNames(const IOobject& io)
|
||||
{
|
||||
return readDir(io.path(), fileName::FILE);
|
||||
}
|
||||
|
||||
|
||||
Foam::fileNameList Foam::triSurfaceMeshes::names() const
|
||||
{
|
||||
fileNameList surfNames(size());
|
||||
|
||||
forAll(surfNames, surfI)
|
||||
{
|
||||
surfNames[surfI] = operator[](surfI).IOobject::name();
|
||||
}
|
||||
return surfNames;
|
||||
}
|
||||
|
||||
|
||||
// Find any intersection
|
||||
Foam::label Foam::triSurfaceMeshes::findAnyIntersection
|
||||
(
|
||||
const labelList& surfaces,
|
||||
const point& start,
|
||||
const point& end,
|
||||
pointIndexHit& hitInfo
|
||||
) const
|
||||
{
|
||||
forAll(surfaces, i)
|
||||
{
|
||||
label surfI = surfaces[i];
|
||||
|
||||
hitInfo = operator[](surfI).findLineAny(start, end);
|
||||
|
||||
if (hitInfo.hit())
|
||||
{
|
||||
return surfI;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::triSurfaceMeshes::findAnyIntersection
|
||||
(
|
||||
const point& start,
|
||||
const point& end,
|
||||
pointIndexHit& hitInfo
|
||||
) const
|
||||
{
|
||||
return findAnyIntersection
|
||||
(
|
||||
allSurfaces_,
|
||||
start,
|
||||
end,
|
||||
hitInfo
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Find intersections of edge nearest to both endpoints.
|
||||
void Foam::triSurfaceMeshes::findAllIntersections
|
||||
(
|
||||
const labelList& surfaces,
|
||||
const point& start,
|
||||
const point& end,
|
||||
|
||||
labelList& surfacesIndex,
|
||||
List<pointIndexHit>& surfaceHitInfo
|
||||
) const
|
||||
{
|
||||
DynamicList<label> hitSurfaces(surfaces.size());
|
||||
DynamicList<pointIndexHit> hitInfos(surfaces.size());
|
||||
DynamicList<scalar> hitDistSqr(surfaces.size());
|
||||
|
||||
const vector dirVec(end-start);
|
||||
const scalar magSqrDirVec(magSqr(dirVec));
|
||||
const vector smallVec(Foam::sqrt(SMALL)*dirVec);
|
||||
|
||||
forAll(surfaces, i)
|
||||
{
|
||||
label surfI = surfaces[i];
|
||||
|
||||
// Current starting point of ray.
|
||||
point pt = start;
|
||||
|
||||
while (true)
|
||||
{
|
||||
// See if any intersection between pt and end
|
||||
pointIndexHit inter = operator[](surfI).findLine(pt, end);
|
||||
|
||||
if (!inter.hit())
|
||||
{
|
||||
break;
|
||||
}
|
||||
hitSurfaces.append(surfI);
|
||||
hitInfos.append(inter);
|
||||
hitDistSqr.append(magSqr(inter.hitPoint() - start));
|
||||
|
||||
pt = inter.hitPoint() + smallVec;
|
||||
|
||||
if (((pt-start)&dirVec) > magSqrDirVec)
|
||||
{
|
||||
// Adding smallVec has taken us beyond end
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
surfacesIndex.setSize(hitSurfaces.size());
|
||||
surfaceHitInfo.setSize(hitSurfaces.size());
|
||||
|
||||
if (hitSurfaces.size() > 0)
|
||||
{
|
||||
// Sort and transfer to arguments
|
||||
|
||||
hitSurfaces.shrink();
|
||||
hitInfos.shrink();
|
||||
hitDistSqr.shrink();
|
||||
|
||||
// Sort from start to end.
|
||||
SortableList<scalar> sortedDist(hitDistSqr);
|
||||
|
||||
forAll(sortedDist.indices(), newPos)
|
||||
{
|
||||
label oldPos = sortedDist.indices()[newPos];
|
||||
surfacesIndex[newPos] = hitSurfaces[oldPos];
|
||||
surfaceHitInfo[newPos] = hitInfos[oldPos];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::triSurfaceMeshes::findAllIntersections
|
||||
(
|
||||
const point& start,
|
||||
const point& end,
|
||||
|
||||
labelList& surfacesIndex,
|
||||
List<pointIndexHit>& surfaceHitInfo
|
||||
) const
|
||||
{
|
||||
findAllIntersections
|
||||
(
|
||||
allSurfaces_,
|
||||
start,
|
||||
end,
|
||||
surfacesIndex,
|
||||
surfaceHitInfo
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Find intersections of edge nearest to both endpoints.
|
||||
void Foam::triSurfaceMeshes::findNearestIntersection
|
||||
(
|
||||
const labelList& surfaces,
|
||||
const point& start,
|
||||
const point& end,
|
||||
|
||||
label& surface1,
|
||||
pointIndexHit& hit1,
|
||||
label& surface2,
|
||||
pointIndexHit& hit2
|
||||
) const
|
||||
{
|
||||
surface1 = -1;
|
||||
// Initialize to endpoint
|
||||
hit1 = pointIndexHit(false, end, -1);
|
||||
|
||||
forAll(surfaces, i)
|
||||
{
|
||||
label surfI = surfaces[i];
|
||||
|
||||
if (hit1.rawPoint() == start)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// See if any intersection between start and current nearest
|
||||
pointIndexHit inter = operator[](surfI).findLine
|
||||
(
|
||||
start,
|
||||
hit1.rawPoint()
|
||||
);
|
||||
|
||||
if (inter.hit())
|
||||
{
|
||||
hit1 = inter;
|
||||
surface1 = surfI;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Find the nearest intersection from end to start. Note that we initialize
|
||||
// to the first intersection (if any).
|
||||
surface2 = surface1;
|
||||
hit2 = pointIndexHit(hit1);
|
||||
|
||||
if (hit1.hit())
|
||||
{
|
||||
// Test from the end side.
|
||||
forAll(surfaces, i)
|
||||
{
|
||||
label surfI = surfaces[i];
|
||||
|
||||
if (hit2.rawPoint() == end)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// See if any intersection between end and current nearest
|
||||
pointIndexHit inter = operator[](surfI).findLine
|
||||
(
|
||||
end,
|
||||
hit2.rawPoint()
|
||||
);
|
||||
|
||||
if (inter.hit())
|
||||
{
|
||||
hit2 = inter;
|
||||
surface2 = surfI;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::triSurfaceMeshes::findNearestIntersection
|
||||
(
|
||||
const point& start,
|
||||
const point& end,
|
||||
|
||||
label& surface1,
|
||||
pointIndexHit& hit1,
|
||||
label& surface2,
|
||||
pointIndexHit& hit2
|
||||
) const
|
||||
{
|
||||
findNearestIntersection
|
||||
(
|
||||
allSurfaces_,
|
||||
start,
|
||||
end,
|
||||
surface1,
|
||||
hit1,
|
||||
surface2,
|
||||
hit2
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Find nearest. Return -1 or nearest point
|
||||
Foam::label Foam::triSurfaceMeshes::findNearest
|
||||
(
|
||||
const labelList& surfaces,
|
||||
const point& pt,
|
||||
const scalar nearestDistSqr,
|
||||
pointIndexHit& nearestHit
|
||||
) const
|
||||
{
|
||||
// nearest surface
|
||||
label minSurface = -1;
|
||||
scalar minDistSqr = Foam::sqr(GREAT);
|
||||
|
||||
forAll(surfaces, i)
|
||||
{
|
||||
label surfI = surfaces[i];
|
||||
|
||||
pointIndexHit hit
|
||||
(
|
||||
operator[](surfI).findNearest(pt, nearestDistSqr)
|
||||
);
|
||||
|
||||
if (hit.hit())
|
||||
{
|
||||
scalar distSqr = magSqr(hit.hitPoint()-pt);
|
||||
|
||||
if (distSqr < minDistSqr)
|
||||
{
|
||||
minDistSqr = distSqr;
|
||||
minSurface = surfI;
|
||||
nearestHit = hit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (minSurface == -1)
|
||||
{
|
||||
// maxLevel unchanged. No interesting surface hit.
|
||||
nearestHit.setMiss();
|
||||
}
|
||||
|
||||
return minSurface;
|
||||
}
|
||||
|
||||
|
||||
// Find nearest. Return -1 or nearest point
|
||||
Foam::label Foam::triSurfaceMeshes::findNearest
|
||||
(
|
||||
const point& pt,
|
||||
const scalar nearestDistSqr,
|
||||
pointIndexHit& nearestHit
|
||||
) const
|
||||
{
|
||||
return findNearest
|
||||
(
|
||||
allSurfaces_,
|
||||
pt,
|
||||
nearestDistSqr,
|
||||
nearestHit
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::triSurfaceMeshes::findNearestAndClassify
|
||||
(
|
||||
const labelList& surfacesToTest,
|
||||
const point& pt,
|
||||
const scalar nearestDistSqr,
|
||||
surfaceLocation& nearest
|
||||
) const
|
||||
{
|
||||
pointIndexHit nearestInfo;
|
||||
label surfI = findNearest
|
||||
(
|
||||
surfacesToTest,
|
||||
pt,
|
||||
nearestDistSqr,
|
||||
nearestInfo
|
||||
);
|
||||
|
||||
if (surfI != -1)
|
||||
{
|
||||
nearest = triSurfaceTools::classify
|
||||
(
|
||||
operator[](surfI),
|
||||
nearestInfo.index(), // triangle
|
||||
nearestInfo.rawPoint() // point on edge/inside triangle
|
||||
);
|
||||
}
|
||||
|
||||
return surfI;
|
||||
}
|
||||
|
||||
|
||||
//- Calculate point which is on a set of surfaces.
|
||||
Foam::surfaceLocation Foam::triSurfaceMeshes::facesIntersectionTrack
|
||||
(
|
||||
const labelList& surfacesToTest,
|
||||
const scalar initialDistSqr,
|
||||
const scalar convergenceDistSqr,
|
||||
const point& start
|
||||
) const
|
||||
{
|
||||
autoPtr<OFstream> str;
|
||||
label vertI = 0;
|
||||
|
||||
if (debug)
|
||||
{
|
||||
str.reset(new OFstream("track.obj"));
|
||||
}
|
||||
|
||||
surfaceLocation current
|
||||
(
|
||||
pointIndexHit
|
||||
(
|
||||
false,
|
||||
start,
|
||||
-1
|
||||
),
|
||||
triPointRef::NONE,
|
||||
-1
|
||||
);
|
||||
|
||||
// Dump start point
|
||||
if (str.valid())
|
||||
{
|
||||
Pout<< "Starting at " << current.info()
|
||||
<< " written as point " << vertI
|
||||
<< endl;
|
||||
meshTools::writeOBJ(str(), current.rawPoint());
|
||||
vertI++;
|
||||
}
|
||||
|
||||
// Now slide current along all faces until it settles
|
||||
label iter = 0;
|
||||
|
||||
const label maxIter = 10;
|
||||
|
||||
for (; iter < maxIter; iter++)
|
||||
{
|
||||
// - store old position
|
||||
// - slide it along all faces
|
||||
// - if it hasn't changed position exit loop
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< endl
|
||||
<< "Iteration " << iter << endl
|
||||
<< "-----------" << endl;
|
||||
}
|
||||
|
||||
point oldCurrent = current.rawPoint();
|
||||
|
||||
forAll(surfacesToTest, i)
|
||||
{
|
||||
label surfI = surfacesToTest[i];
|
||||
|
||||
// Project pt onto surf
|
||||
// ~~~~~~~~~~~~~~~~~~~~
|
||||
point copy(current.rawPoint()); // need to work on copy
|
||||
if
|
||||
(
|
||||
findNearestAndClassify
|
||||
(
|
||||
labelList(1, surfI),
|
||||
copy,
|
||||
initialDistSqr, // initialDistSqr
|
||||
current
|
||||
)
|
||||
== -1
|
||||
)
|
||||
{
|
||||
FatalErrorIn("triSurfaceMeshes::facesIntersectionTrack(..)")
|
||||
<< "Did not find a point on surface " << surfI
|
||||
<< " which is within sqrt(" << initialDistSqr
|
||||
<< ") of " << copy
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "Nearest onto surface " << surfI
|
||||
<< ' ' << operator[](surfI).IOobject::name() << " : "
|
||||
<< current.info() << " written as point " << vertI
|
||||
<< endl;
|
||||
}
|
||||
|
||||
// Dump current
|
||||
if (str.valid())
|
||||
{
|
||||
meshTools::writeOBJ(str(), current.rawPoint());
|
||||
vertI++;
|
||||
str()<< "l " << vertI-1 << ' ' << vertI << nl;
|
||||
}
|
||||
|
||||
// Find corresponding point on next surface
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
label nextSurfI = surfacesToTest[surfacesToTest.fcIndex(i)];
|
||||
|
||||
surfaceLocation next;
|
||||
findNearestAndClassify
|
||||
(
|
||||
labelList(1, nextSurfI),
|
||||
point(current.rawPoint()),
|
||||
initialDistSqr, // initialDistSqr
|
||||
next
|
||||
);
|
||||
|
||||
// Since next is on a different surface we cannot compare
|
||||
// indices (like in snapToEnd) so make sure this does not
|
||||
// happen.
|
||||
next.elementType() = triPointRef::NONE;
|
||||
next.setIndex(-123);
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "Nearest onto next surface " << nextSurfI
|
||||
<< ' ' << operator[](nextSurfI).IOobject::name() << " : "
|
||||
<< next.info() << endl;
|
||||
}
|
||||
|
||||
if
|
||||
(
|
||||
magSqr(current.rawPoint() - next.rawPoint())
|
||||
> convergenceDistSqr
|
||||
)
|
||||
{
|
||||
// Track from current to next
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//vector n = current.normal(surfaces[surfI]);
|
||||
|
||||
current = triSurfaceTools::trackToEdge
|
||||
(
|
||||
operator[](surfI),
|
||||
current,
|
||||
next,
|
||||
plane(start, current.rawPoint(), next.rawPoint())
|
||||
);
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "Sliding along surface "
|
||||
<< surfI << ' ' << operator[](surfI).IOobject::name()
|
||||
<< " in direction of "
|
||||
<< nextSurfI << ' '
|
||||
<< operator[](nextSurfI).IOobject::name()
|
||||
<< " stopped at " << current.info()
|
||||
<< " written as point " << vertI << endl;
|
||||
}
|
||||
if (str.valid())
|
||||
{
|
||||
meshTools::writeOBJ(str(), current.rawPoint());
|
||||
vertI++;
|
||||
str()<< "l " << vertI-1 << ' ' << vertI << nl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scalar distSqr = magSqr(oldCurrent - current.rawPoint());
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "distSqr:" << distSqr
|
||||
<< " convergenceDistSqr:" << convergenceDistSqr << endl;
|
||||
}
|
||||
|
||||
if (distSqr < convergenceDistSqr)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (iter == maxIter)
|
||||
{
|
||||
FatalErrorIn("triSurfaceMeshes::facesIntersectionTrack(..)")
|
||||
<< "Did not converge in " << iter
|
||||
<< " iterations to find a point which is on surfaces "
|
||||
<< IndirectList<fileName>(names(), surfacesToTest)() << nl
|
||||
<< "Start point:" << start << nl
|
||||
<< "Current nearest:" << current.info() << nl
|
||||
<< "Please check that your surfaces actually intersect and"
|
||||
<< " that the starting point is close to the intersection point."
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
|
||||
//- Calculate point which is on a set of surfaces.
|
||||
Foam::pointIndexHit Foam::triSurfaceMeshes::facesIntersection
|
||||
(
|
||||
const labelList& surfacesToTest,
|
||||
const scalar initDistSqr,
|
||||
const scalar convergenceDistSqr,
|
||||
const point& start
|
||||
) const
|
||||
{
|
||||
// Get four starting points. Take these as the projection of the
|
||||
// starting point onto the surfaces and the mid point
|
||||
List<point> nearest(surfacesToTest.size()+1);
|
||||
|
||||
point sumNearest = vector::zero;
|
||||
|
||||
forAll(surfacesToTest, i)
|
||||
{
|
||||
label surfI = surfacesToTest[i];
|
||||
|
||||
pointIndexHit hit
|
||||
(
|
||||
operator[](surfI).findNearest(start, initDistSqr)
|
||||
);
|
||||
|
||||
if (hit.hit())
|
||||
{
|
||||
nearest[i] = hit.hitPoint();
|
||||
sumNearest += nearest[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"triSurfaceMeshes::facesIntersection"
|
||||
"(const labelList&, const scalar, const scalar, const point&)"
|
||||
) << "Did not find point within distance "
|
||||
<< initDistSqr << " of starting point " << start
|
||||
<< " on surface " << operator[](surfI).IOobject::name()
|
||||
<< abort(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
nearest[nearest.size()-1] = sumNearest / surfacesToTest.size();
|
||||
|
||||
|
||||
// Get the sum of distances (initial evaluation)
|
||||
List<scalar> nearestDist(nearest.size());
|
||||
|
||||
forAll(nearestDist, i)
|
||||
{
|
||||
nearestDist[i] = sumDistSqr(surfacesToTest, initDistSqr, nearest[i]);
|
||||
}
|
||||
|
||||
|
||||
//- Downhill Simplex method
|
||||
|
||||
bool converged = morphTet
|
||||
(
|
||||
surfacesToTest,
|
||||
initDistSqr,
|
||||
convergenceDistSqr,
|
||||
2000,
|
||||
nearest,
|
||||
nearestDist
|
||||
);
|
||||
|
||||
|
||||
pointIndexHit intersection;
|
||||
|
||||
if (converged)
|
||||
{
|
||||
// Project nearest onto 0th surface.
|
||||
intersection = operator[](surfacesToTest[0]).findNearest
|
||||
(
|
||||
nearest[0],
|
||||
nearestDist[0]
|
||||
);
|
||||
}
|
||||
|
||||
//if (!intersection.hit())
|
||||
//{
|
||||
// // Restart
|
||||
// scalar smallDist = Foam::sqr(convergenceDistSqr);
|
||||
// nearest[0] = intersection.hitPoint();
|
||||
// nearest[1] = nearest[0];
|
||||
// nearest[1].x() += smallDist;
|
||||
// nearest[2] = nearest[0];
|
||||
// nearest[2].y() += smallDist;
|
||||
// nearest[3] = nearest[0];
|
||||
// nearest[3].z() += smallDist;
|
||||
//
|
||||
// forAll(nearestDist, i)
|
||||
// {
|
||||
// nearestDist[i] = sumDistSqr
|
||||
// (
|
||||
// surfacesToTest,
|
||||
// initDistSqr,
|
||||
// nearest[i]
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// intersection = morphTet
|
||||
// (
|
||||
// surfacesToTest,
|
||||
// initDistSqr,
|
||||
// convergenceDistSqr,
|
||||
// 1000,
|
||||
// nearest,
|
||||
// nearestDist
|
||||
// );
|
||||
//}
|
||||
|
||||
return intersection;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,261 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Class
|
||||
Foam::triSurfaceMeshes
|
||||
|
||||
Description
|
||||
Container for triSurfaces read from files.
|
||||
|
||||
SourceFiles
|
||||
triSurfaceMeshes.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef triSurfaceMeshes_H
|
||||
#define triSurfaceMeshes_H
|
||||
|
||||
#include "triSurfaceMesh.H"
|
||||
#include "fileNameList.H"
|
||||
#include "treeDataTriSurface.H"
|
||||
#include "indexedOctree.H"
|
||||
#include "surfaceLocation.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward declaration of classes
|
||||
class plane;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class triSurfaceMeshes Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class triSurfaceMeshes
|
||||
:
|
||||
public PtrList<triSurfaceMesh>
|
||||
{
|
||||
// Private data
|
||||
|
||||
//- Indices of all surfaces. Precalculated and stored.
|
||||
const labelList allSurfaces_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Calculate sum of distances to nearest point on surfaces. Is used
|
||||
// in minimisation to find intersection. Returns sum of (square of)
|
||||
// distances to the surfaces.
|
||||
scalar sumDistSqr
|
||||
(
|
||||
const labelList& surfacesToTest,
|
||||
const scalar initialDistSqr, // search box
|
||||
const point& pt
|
||||
) const;
|
||||
|
||||
//- Takes the tet (points p) and reflects the point with the
|
||||
// highest value around the centre (pSum). Checks if it gets closer
|
||||
// and updates p, y if so.
|
||||
scalar tryMorphTet
|
||||
(
|
||||
const labelList& surfacesToTest,
|
||||
const scalar initialDistSqr,
|
||||
List<vector>& p,
|
||||
List<scalar>& y,
|
||||
vector& pSum,
|
||||
const label ihi,
|
||||
const scalar fac
|
||||
) const;
|
||||
|
||||
//- Downhill simplex method: find the point with min cumulative
|
||||
// distance to all surfaces. Does so by morphing a tet (points p).
|
||||
// Returns the point on the 0th surface or hit if not reached within
|
||||
// maxIters iterations.
|
||||
bool morphTet
|
||||
(
|
||||
const labelList& surfacesToTest,
|
||||
const scalar initialDistSqr,
|
||||
const scalar convergenceDistSqr,
|
||||
const label maxIter,
|
||||
List<vector>& p,
|
||||
List<scalar>& y
|
||||
) const;
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
triSurfaceMeshes(const triSurfaceMeshes&);
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const triSurfaceMeshes&);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
ClassName("triSurfaceMeshes");
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from directory (io.instance()) and list of local filenames
|
||||
triSurfaceMeshes(const IOobject& io, const fileNameList&);
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Get all surfaces in directory
|
||||
static fileNameList allNames(const IOobject&);
|
||||
|
||||
//- Get names of surfaces
|
||||
fileNameList names() const;
|
||||
|
||||
|
||||
//- Find any intersection. Return hit point information and surface
|
||||
// number
|
||||
label findAnyIntersection
|
||||
(
|
||||
const labelList& surfacesToTest,
|
||||
const point& start,
|
||||
const point& end,
|
||||
pointIndexHit&
|
||||
) const;
|
||||
|
||||
label findAnyIntersection
|
||||
(
|
||||
const point& start,
|
||||
const point& end,
|
||||
pointIndexHit&
|
||||
) const;
|
||||
|
||||
|
||||
//- Find all intersections in order from start to end. Returns for
|
||||
// every hit the surface and the hit info.
|
||||
void findAllIntersections
|
||||
(
|
||||
const labelList& surfacesToTest,
|
||||
const point& start,
|
||||
const point& end,
|
||||
labelList& surfaces,
|
||||
List<pointIndexHit>& surfaceHits
|
||||
) const;
|
||||
|
||||
void findAllIntersections
|
||||
(
|
||||
const point& start,
|
||||
const point& end,
|
||||
labelList& surfaces,
|
||||
List<pointIndexHit>& surfaceHits
|
||||
) const;
|
||||
|
||||
|
||||
//- Find intersections of edge nearest to both endpoints.
|
||||
void findNearestIntersection
|
||||
(
|
||||
const labelList& surfacesToTest,
|
||||
const point& start,
|
||||
const point& end,
|
||||
|
||||
label& surface1, // surface index
|
||||
pointIndexHit& hit1, // hit point information
|
||||
label& surface2,
|
||||
pointIndexHit& hit2
|
||||
) const;
|
||||
|
||||
void findNearestIntersection
|
||||
(
|
||||
const point& start,
|
||||
const point& end,
|
||||
|
||||
label& surface1, // surface index
|
||||
pointIndexHit& hit1, // hit point information
|
||||
label& surface2,
|
||||
pointIndexHit& hit2
|
||||
) const;
|
||||
|
||||
|
||||
//- Find nearest. Return -1 (and a miss()) or surface and nearest point.
|
||||
label findNearest
|
||||
(
|
||||
const labelList& surfacesToTest,
|
||||
const point&,
|
||||
const scalar nearestDistSqr,
|
||||
pointIndexHit&
|
||||
) const;
|
||||
|
||||
label findNearest
|
||||
(
|
||||
const point&,
|
||||
const scalar nearestDistSqr,
|
||||
pointIndexHit&
|
||||
) const;
|
||||
|
||||
|
||||
//- Find nearest point (like findNearest) but also return whether
|
||||
// point is on edge or on point. Returns -1 if not found
|
||||
// (within nearestDistSqr) on any of the surfaces.
|
||||
// Returns surfaceLocation
|
||||
// - hit : nearest point is inside triangle
|
||||
// - elementType : none, edge or point
|
||||
// - index : triI, edgeI or localPointI
|
||||
label findNearestAndClassify
|
||||
(
|
||||
const labelList& surfacesToTest,
|
||||
const point& pt,
|
||||
const scalar nearestDistSqr,
|
||||
surfaceLocation& nearest
|
||||
) const;
|
||||
|
||||
//- Calculate point which is on a set of surfaces. Takes
|
||||
// - initialDistSqr : search dimensions to find point on surface
|
||||
// - convergenceDistSqr : when point is converged
|
||||
// Will bomb out if no stable point reached after certain number
|
||||
// of iterations.
|
||||
surfaceLocation facesIntersectionTrack
|
||||
(
|
||||
const labelList& surfacesToTest,
|
||||
const scalar initialDistSqr,
|
||||
const scalar convergenceDistSqr,
|
||||
const point& start
|
||||
) const;
|
||||
|
||||
//- Calculate point which is on a set of surfaces.
|
||||
pointIndexHit facesIntersection
|
||||
(
|
||||
const labelList& surfacesToTest,
|
||||
const scalar initialDistSqr,
|
||||
const scalar convergenceDistSqr,
|
||||
const point& start
|
||||
) const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -2,4 +2,4 @@
|
||||
|
||||
foamCleanTutorials cases
|
||||
rm -rf processor*
|
||||
rm 0/pd.gz 0/alpha1.gz
|
||||
rm -rf 0/pd.gz 0/alpha1.gz
|
||||
|
||||
@ -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 ..
|
||||
|
||||
|
||||
@ -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 ..
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
Reference in New Issue
Block a user