diff --git a/src/autoMesh/Make/files b/src/autoMesh/Make/files index c562ee5c6de5bbb273ba95decce1e88dc70eda2e..1c763a316c9c8148ab2bca1b887b9646121d53ae 100644 --- a/src/autoMesh/Make/files +++ b/src/autoMesh/Make/files @@ -1,15 +1,21 @@ autoHexMesh = autoHexMesh +autoHexMeshDriver = $(autoHexMesh)/autoHexMeshDriver + +$(autoHexMeshDriver)/autoHexMeshDriver.C +$(autoHexMeshDriver)/autoHexMeshDriverLayers.C +$(autoHexMeshDriver)/autoHexMeshDriverShrink.C +$(autoHexMeshDriver)/autoHexMeshDriverSnap.C +$(autoHexMeshDriver)/layerParameters/layerParameters.C +$(autoHexMeshDriver)/refinementParameters/refinementParameters.C +$(autoHexMeshDriver)/snapParameters/snapParameters.C +$(autoHexMeshDriver)/pointData/pointData.C -$(autoHexMesh)/autoHexMeshDriver/autoHexMeshDriver.C -$(autoHexMesh)/autoHexMeshDriver/autoHexMeshDriverLayers.C -$(autoHexMesh)/autoHexMeshDriver/autoHexMeshDriverShrink.C -$(autoHexMesh)/autoHexMeshDriver/autoHexMeshDriverSnap.C -$(autoHexMesh)/autoHexMeshDriver/pointData/pointData.C $(autoHexMesh)/meshRefinement/meshRefinementBaffles.C $(autoHexMesh)/meshRefinement/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 diff --git a/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoHexMeshDriver.C b/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoHexMeshDriver.C index a15b4220324da337c72f24b4003735a255f20ede..94c217ebcc94f0997cff83626c1ec2aa81dd9f40 100644 --- a/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoHexMeshDriver.C +++ b/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoHexMeshDriver.C @@ -35,6 +35,9 @@ License #include "syncTools.H" #include "motionSmoother.H" #include "pointMesh.H" +#include "refinementParameters.H" +#include "snapParameters.H" +#include "layerParameters.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // @@ -60,7 +63,8 @@ Foam::scalar Foam::autoHexMeshDriver::getMergeDistance(const scalar mergeTol) -scalar(IOstream::defaultPrecision()) ); - Info<< "Overall mesh bounding box : " << meshBb << nl + Info<< nl + << "Overall mesh bounding box : " << meshBb << nl << "Relative tolerance : " << mergeTol << nl << "Absolute matching distance : " << mergeDist << nl << endl; @@ -82,110 +86,59 @@ Foam::scalar Foam::autoHexMeshDriver::getMergeDistance(const scalar mergeTol) } -// Return per keeppoint -1 or the local cell label the point is in. Guaranteed -// to be only on one processor. -Foam::labelList Foam::autoHexMeshDriver::findCells(const pointField& keepPoints) - 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 - ( - "autoHexMeshDriver::findCells(const pointField&) const" - ) << "Point " << keepPoint << " is not inside the mesh." << nl - << "Bounding box of the mesh:" << mesh_.bounds() - << exit(FatalError); - } - - if (globalCells.isLocal(globalCellI)) - { - cellLabels[i] = localCellI; - } - else - { - cellLabels[i] = -1; - } - } - return cellLabels; -} - - -// Specifically orient using a calculated point outside -void Foam::autoHexMeshDriver::orientOutside(PtrList<searchableSurface>& shells) -{ - // Determine outside point. - boundBox overallBb - ( - point(GREAT, GREAT, GREAT), - point(-GREAT, -GREAT, -GREAT) - ); - - bool hasSurface = false; - - forAll(shells, shellI) - { - if (isA<triSurfaceMesh>(shells[shellI])) - { - const triSurfaceMesh& shell = - refCast<const triSurfaceMesh>(shells[shellI]); - - hasSurface = true; - - boundBox shellBb(shell.localPoints(), false); - - 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) - { - if (isA<triSurfaceMesh>(shells[shellI])) - { - triSurfaceMesh& shell = refCast<triSurfaceMesh>(shells[shellI]); - - if (!refinementSurfaces::isSurfaceClosed(shell)) - { - FatalErrorIn("orientOutside(PtrList<searchableSurface>&)") - << "Refinement shell " - << shell.searchableSurface::name() - << " is not closed." << exit(FatalError); - } - - refinementSurfaces::orientSurface(outsidePt, shell); - } - } - } -} +//// Specifically orient using a calculated point outside +//void Foam::autoHexMeshDriver::orientOutside(PtrList<searchableSurface>& shells) +//{ +// // Determine outside point. +// boundBox overallBb +// ( +// point(GREAT, GREAT, GREAT), +// point(-GREAT, -GREAT, -GREAT) +// ); +// +// bool hasSurface = false; +// +// forAll(shells, shellI) +// { +// if (isA<triSurfaceMesh>(shells[shellI])) +// { +// const triSurfaceMesh& shell = +// refCast<const triSurfaceMesh>(shells[shellI]); +// +// hasSurface = true; +// +// boundBox shellBb(shell.localPoints(), false); +// +// 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) +// { +// if (isA<triSurfaceMesh>(shells[shellI])) +// { +// triSurfaceMesh& shell = refCast<triSurfaceMesh>(shells[shellI]); +// +// if (!refinementSurfaces::isSurfaceClosed(shell)) +// { +// FatalErrorIn("orientOutside(PtrList<searchableSurface>&)") +// << "Refinement shell " +// << shell.searchableSurface::name() +// << " is not closed." << exit(FatalError); +// } +// +// refinementSurfaces::orientSurface(outsidePt, shell); +// } +// } +// } +//} // Check that face zones are synced @@ -286,324 +239,394 @@ void Foam::autoHexMeshDriver::checkCoupledFaceZones() const // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // -// Construct from components -Foam::autoHexMeshDriver::autoHexMeshDriver -( - fvMesh& mesh, - const dictionary& dict, - const dictionary& decomposeDict -) -: - mesh_(mesh), - dict_(dict), - debug_(readLabel(dict_.lookup("debug"))), - 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")), - mergeDist_(getMergeDistance(readScalar(dict_.lookup("mergeTolerance")))) -{ - if (debug_ > 0) - { - meshRefinement::debug = debug_; - autoHexMeshDriver::debug = debug_; - } - - Info<< "Overall cell limit : " << maxGlobalCells_ - << endl; - Info<< "Per processor cell limit : " << maxLocalCells_ - << endl; - Info<< "Minimum number of cells to refine : " << minRefineCells_ - << endl; - Info<< "Curvature : " << curvature_ - << nl << endl; - Info<< "Layers between different refinement levels : " << nBufferLayers_ - << endl; - - // Check keepPoints are sensible - findCells(keepPoints_); - - - // Read refinement shells - // ~~~~~~~~~~~~~~~~~~~~~~ - - { - Info<< "Reading refinement shells." << endl; - - PtrList<dictionary> shellDicts(dict_.lookup("refinementShells")); - - shells_.setSize(shellDicts.size()); - shellLevels_.setSize(shellDicts.size()); - shellRefineInside_.setSize(shellDicts.size()); - - forAll(shellDicts, i) - { - const dictionary& dict = shellDicts[i]; - - shells_.set - ( - i, - searchableSurface::New - ( - dict.lookup("type"), - dict.lookup("name"), - mesh_.time(), - dict - ) - ); - shellLevels_[i] = readLabel(dict.lookup("level")); - shellRefineInside_[i] = Switch(dict.lookup("refineInside")); - - if (shellRefineInside_[i]) - { - Info<< "Refinement level " << shellLevels_[i] - << " for all cells inside " << shells_[i].name() << endl; - } - else - { - Info<< "Refinement level " << shellLevels_[i] - << " for all cells outside " << shells_[i].name() << endl; - } - } - - Info<< "Read refinement shells in = " - << mesh_.time().cpuTimeIncrement() << " s" << endl; - - // Orient shell surfaces before any searching is done. - Info<< "Orienting triSurface shells so point far away is outside." - << endl; - orientOutside(shells_); - Info<< "Oriented shells in = " - << mesh_.time().cpuTimeIncrement() << " s" << endl; - } - - - // Read refinement surfaces - // ~~~~~~~~~~~~~~~~~~~~~~~~ - - { - Info<< "Reading surfaces and constructing search trees." << endl; - - surfacesPtr_.reset - ( - new refinementSurfaces - ( - IOobject - ( - "", // dummy name - mesh_.time().constant(), // directory - "triSurface", // instance - mesh_.time(), // registry - IOobject::MUST_READ, - IOobject::NO_WRITE - ), - dict_.lookup("surfaces") - ) - ); - Info<< "Read surfaces in = " - << mesh_.time().cpuTimeIncrement() << " s" << endl; - - // Orient surfaces (if they're closed) before any searching is done. - Info<< "Orienting (closed) surfaces so keepPoint is outside." << endl; - forAll(surfaces(), i) - { - if (refinementSurfaces::isSurfaceClosed(surfaces()[i])) - { - refinementSurfaces::orientSurface - ( - keepPoints_[0], - surfacesPtr_()[i] - ); - } - } - Info<< "Oriented closed surfaces in = " - << mesh_.time().cpuTimeIncrement() << " s" << endl; - - Info<< "Setting refinement level of surface to be consistent" - << " with shells." << endl; - surfacesPtr_().setMinLevelFields - ( - shells_, - shellLevels_, - shellRefineInside_ - ); - Info<< "Checked shell refinement in = " - << mesh_.time().cpuTimeIncrement() << " s" << endl; - } - - // Check faceZones are synchronised - checkCoupledFaceZones(); - - - // Add all the surface regions as patches - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - { - Info<< nl - << "Adding patches for surface regions" << nl - << "----------------------------------" << nl - << endl; - - // From global region number to mesh patch. - globalToPatch_.setSize(surfaces().nRegions(), -1); - - Info<< "Patch\tRegion" << nl - << "-----\t------" - << endl; - - forAll(surfaces(), surfI) - { - const triSurfaceMesh& s = surfaces()[surfI]; - - Info<< surfaces().names()[surfI] << ':' << nl << nl; - - const geometricSurfacePatchList& regions = s.patches(); - - labelList nTrisPerRegion(surfaces().countRegions(s)); - - forAll(regions, i) - { - if (nTrisPerRegion[i] > 0) - { - label globalRegionI = surfaces().globalRegion(surfI, i); - - // Use optionally specified patch type and name - word patchType = surfaces().patchType()[globalRegionI]; - if (patchType == "") - { - patchType = wallPolyPatch::typeName; - } - - word patchName = surfaces().patchName()[globalRegionI]; - if (patchName == "") - { - patchName = - surfaces().names()[surfI] - + '_' - + regions[i].name(); - } - - label patchI = meshRefinement::addPatch - ( - mesh, - patchName, - patchType - ); - - Info<< patchI << '\t' << regions[i].name() << nl; - - globalToPatch_[globalRegionI] = patchI; - } - } - - Info<< nl; - } - Info<< "Added patches in = " - << mesh_.time().cpuTimeIncrement() << " s" << endl; - } - - - //// Add cyclics for any named faceZones - //// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - //// (these cyclics are used later on to temporarily put the faceZones - //// in when snapping) - // - //labelList namedSurfaces(surfaces().getNamedSurfaces()); - //if (namedSurfaces.size() > 0) - //{ - // Info<< nl - // << "Introducing cyclics for faceZones" << nl - // << "---------------------------------" << nl - // << endl; - // - // // From surface to cyclic patch - // surfaceToCyclicPatch_.setSize(surfaces().size(), -1); - // - // Info<< "Patch\tZone" << nl - // << "----\t-----" - // << endl; - // - // forAll(namedSurfaces, i) - // { - // label surfI = namedSurfaces[i]; - // - // surfaceToCyclicPatch_[surfI] = meshRefinement::addPatch - // ( - // mesh, - // surfaces().faceZoneNames()[surfI], - // cyclicPolyPatch::typeName - // ); - // - // Info<< surfaceToCyclicPatch_[surfI] << '\t' - // << surfaces().faceZoneNames()[surfI] << nl << endl; - // } - // Info<< "Added cyclic patches in = " - // << mesh_.time().cpuTimeIncrement() << " s" << endl; - //} - - - // Parallel - // ~~~~~~~~ - - { - // Decomposition - decomposerPtr_ = decompositionMethod::New - ( - decomposeDict, - mesh_ - ); - decompositionMethod& decomposer = decomposerPtr_(); - - - if (Pstream::parRun() && !decomposer.parallelAware()) - { - FatalErrorIn("autoHexMeshDriver::autoHexMeshDriver(const IOobject&, fvMesh&)") - << "You have selected decomposition method " - << decomposer.typeName - << " which is not parallel aware." << endl - << "Please select one that is (parMetis, hierarchical)" - << exit(FatalError); - } - - // Mesh distribution engine (uses tolerance to reconstruct meshes) - distributorPtr_.reset(new fvMeshDistribute(mesh_, mergeDist_)); - } - - - // Refinement engine - // ~~~~~~~~~~~~~~~~~ - - { - Info<< nl - << "Determining initial surface intersections" << nl - << "-----------------------------------------" << nl - << endl; - - // Main refinement engine - meshRefinerPtr_.reset - ( - new meshRefinement - ( - mesh, - mergeDist_, // tolerance used in sorting coordinates - surfaces() - ) - ); - Info<< "Calculated surface intersections in = " - << mesh_.time().cpuTimeIncrement() << " s" << endl; - - // Some stats - meshRefinerPtr_().printMeshInfo(debug_, "Initial mesh"); - - meshRefinerPtr_().write - ( - debug_&meshRefinement::OBJINTERSECTIONS, - mesh_.time().path()/mesh_.time().timeName() - ); - } -} +//// Construct from components +//Foam::autoHexMeshDriver::autoHexMeshDriver +//( +// fvMesh& mesh, +// const dictionary& dict, +// const dictionary& decomposeDict +//) +//: +// mesh_(mesh), +// dict_(dict), +// debug_(readLabel(dict_.lookup("debug"))), +// mergeDist_(getMergeDistance(readScalar(dict_.lookup("mergeTolerance")))) +//{ +// if (debug_ > 0) +// { +// meshRefinement::debug = debug_; +// autoHexMeshDriver::debug = debug_; +// } +// +// refinementParameters refineParams(dict); +// +// Info<< "Overall cell limit : " +// << refineParams.maxGlobalCells() << endl; +// Info<< "Per processor cell limit : " +// << refineParams.maxLocalCells() << endl; +// Info<< "Minimum number of cells to refine : " +// << refineParams.minRefineCells() << endl; +// Info<< "Curvature : " +// << refineParams.curvature() << nl << endl; +// Info<< "Layers between different refinement levels : " +// << refineParams.nBufferLayers() << endl; +// +////XXXXX +// PtrList<dictionary> shellsDict(dict_.lookup("refinementShells")); +// +// PtrList<dictionary> surfacesDict(dict_.lookup("surfaces")); +// +// +// // Read geometry +// // ~~~~~~~~~~~~~ +// +// { +// Info<< "Reading all geometry." << endl; +// +// // Construct dictionary with all shells and all refinement surfaces +// dictionary geometryDict; +// +// forAll(shellsDict, shellI) +// { +// dictionary shellDict = shellsDict[shellI]; +// const word name(shellDict.lookup("name")); +// shellDict.remove("name"); +// shellDict.remove("level"); +// shellDict.remove("refineInside"); +// geometryDict.add(name, shellDict); +// } +// +// forAll(surfacesDict, surfI) +// { +// dictionary surfDict = surfacesDict[shellI]; +// const word name(string::validate<word>(surfDict.lookup("file"))); +// surfDict.remove("file"); +// if (!surfDict.found("name")) +// { +// surfDict.add("name", name); +// } +// geometryDict.add(name, iter()); +// } +// +// allGeometryPtr_.reset +// ( +// new searchableSurfaces +// ( +// IOobject +// ( +// "abc", // dummy name +// mesh_.time().constant(), // directory +// "triSurface", // instance +// mesh_.time(), // registry +// IOobject::MUST_READ, +// IOobject::NO_WRITE +// ), +// geometryDict +// ) +// ); +// +// Info<< "Read geometry in = " +// << mesh_.time().cpuTimeIncrement() << " s" << nl << endl; +// } +// +// +// // Read refinement surfaces +// // ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// { +// Info<< "Reading surfaces and constructing search trees." << endl; +// +// surfacesPtr_.reset +// ( +// new refinementSurfaces +// ( +// allGeometryPtr_(), +// surfacesDict +// ) +// ); +// Info<< "Read surfaces in = " +// << mesh_.time().cpuTimeIncrement() << " s" << endl; +// } +// +// // Read refinement shells +// // ~~~~~~~~~~~~~~~~~~~~~~ +// +// { +// Info<< "Reading refinement shells." << endl; +// +// PtrList<dictionary> shellDicts(dict_.lookup("refinementShells")); +// +// shells_.setSize(shellDicts.size()); +// shellLevels_.setSize(shellDicts.size()); +// shellRefineInside_.setSize(shellDicts.size()); +// +// forAll(shellDicts, i) +// { +// const dictionary& dict = shellDicts[i]; +// +// shells_.set +// ( +// i, +// searchableSurface::New +// ( +// dict.lookup("type"), +// dict.lookup("name"), +// mesh_.time(), +// dict +// ) +// ); +// shellLevels_[i] = readLabel(dict.lookup("level")); +// shellRefineInside_[i] = Switch(dict.lookup("refineInside")); +// +// if (shellRefineInside_[i]) +// { +// Info<< "Refinement level " << shellLevels_[i] +// << " for all cells inside " << shells_[i].name() << endl; +// } +// else +// { +// Info<< "Refinement level " << shellLevels_[i] +// << " for all cells outside " << shells_[i].name() << endl; +// } +// } +// +// Info<< "Read refinement shells in = " +// << mesh_.time().cpuTimeIncrement() << " s" << endl; +// +// // Orient shell surfaces before any searching is done. +// Info<< "Orienting triSurface shells so point far away is outside." +// << endl; +// orientOutside(shells_); +// Info<< "Oriented shells in = " +// << mesh_.time().cpuTimeIncrement() << " s" << endl; +// } +// +// +// // Read refinement surfaces +// // ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// { +// Info<< "Reading surfaces and constructing search trees." << endl; +// +// surfacesPtr_.reset +// ( +// new refinementSurfaces +// ( +// IOobject +// ( +// "", // dummy name +// mesh_.time().constant(), // directory +// "triSurface", // instance +// mesh_.time(), // registry +// IOobject::MUST_READ, +// IOobject::NO_WRITE +// ), +// dict_.lookup("surfaces") +// ) +// ); +// Info<< "Read surfaces in = " +// << mesh_.time().cpuTimeIncrement() << " s" << endl; +// +// // Orient surfaces (if they're closed) before any searching is done. +// Info<< "Orienting (closed) surfaces so keepPoint is outside." << endl; +// forAll(surfaces(), i) +// { +// if (refinementSurfaces::isSurfaceClosed(surfaces()[i])) +// { +// refinementSurfaces::orientSurface +// ( +// keepPoints_[0], +// surfacesPtr_()[i] +// ); +// } +// } +// Info<< "Oriented closed surfaces in = " +// << mesh_.time().cpuTimeIncrement() << " s" << endl; +// +// Info<< "Setting refinement level of surface to be consistent" +// << " with shells." << endl; +// surfacesPtr_().setMinLevelFields +// ( +// shells_, +// shellLevels_, +// shellRefineInside_ +// ); +// Info<< "Checked shell refinement in = " +// << mesh_.time().cpuTimeIncrement() << " s" << endl; +// } +// +// // Check faceZones are synchronised +// checkCoupledFaceZones(); +// +// +// // Add all the surface regions as patches +// // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// { +// Info<< nl +// << "Adding patches for surface regions" << nl +// << "----------------------------------" << nl +// << endl; +// +// // From global region number to mesh patch. +// globalToPatch_.setSize(surfaces().nRegions(), -1); +// +// Info<< "Patch\tRegion" << nl +// << "-----\t------" +// << endl; +// +// forAll(surfaces(), surfI) +// { +// const triSurfaceMesh& s = surfaces()[surfI]; +// +// Info<< surfaces().names()[surfI] << ':' << nl << nl; +// +// const geometricSurfacePatchList& regions = s.patches(); +// +// labelList nTrisPerRegion(surfaces().countRegions(s)); +// +// forAll(regions, i) +// { +// if (nTrisPerRegion[i] > 0) +// { +// label globalRegionI = surfaces().globalRegion(surfI, i); +// +// // Use optionally specified patch type and name +// word patchType = surfaces().patchType()[globalRegionI]; +// if (patchType == "") +// { +// patchType = wallPolyPatch::typeName; +// } +// +// word patchName = surfaces().patchName()[globalRegionI]; +// if (patchName == "") +// { +// patchName = +// surfaces().names()[surfI] +// + '_' +// + regions[i].name(); +// } +// +// label patchI = meshRefinement::addPatch +// ( +// mesh, +// patchName, +// patchType +// ); +// +// Info<< patchI << '\t' << regions[i].name() << nl; +// +// globalToPatch_[globalRegionI] = patchI; +// } +// } +// +// Info<< nl; +// } +// Info<< "Added patches in = " +// << mesh_.time().cpuTimeIncrement() << " s" << endl; +// } +// +// +// //// Add cyclics for any named faceZones +// //// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// //// (these cyclics are used later on to temporarily put the faceZones +// //// in when snapping) +// // +// //labelList namedSurfaces(surfaces().getNamedSurfaces()); +// //if (namedSurfaces.size() > 0) +// //{ +// // Info<< nl +// // << "Introducing cyclics for faceZones" << nl +// // << "---------------------------------" << nl +// // << endl; +// // +// // // From surface to cyclic patch +// // surfaceToCyclicPatch_.setSize(surfaces().size(), -1); +// // +// // Info<< "Patch\tZone" << nl +// // << "----\t-----" +// // << endl; +// // +// // forAll(namedSurfaces, i) +// // { +// // label surfI = namedSurfaces[i]; +// // +// // surfaceToCyclicPatch_[surfI] = meshRefinement::addPatch +// // ( +// // mesh, +// // surfaces().faceZoneNames()[surfI], +// // cyclicPolyPatch::typeName +// // ); +// // +// // Info<< surfaceToCyclicPatch_[surfI] << '\t' +// // << surfaces().faceZoneNames()[surfI] << nl << endl; +// // } +// // Info<< "Added cyclic patches in = " +// // << mesh_.time().cpuTimeIncrement() << " s" << endl; +// //} +// +// +// // Parallel +// // ~~~~~~~~ +// +// { +// // Decomposition +// decomposerPtr_ = decompositionMethod::New +// ( +// decomposeDict, +// mesh_ +// ); +// decompositionMethod& decomposer = decomposerPtr_(); +// +// +// if (Pstream::parRun() && !decomposer.parallelAware()) +// { +// FatalErrorIn("autoHexMeshDriver::autoHexMeshDriver" +// "(const IOobject&, fvMesh&)") +// << "You have selected decomposition method " +// << decomposer.typeName +// << " which is not parallel aware." << endl +// << "Please select one that is (parMetis, hierarchical)" +// << exit(FatalError); +// } +// +// // Mesh distribution engine (uses tolerance to reconstruct meshes) +// distributorPtr_.reset(new fvMeshDistribute(mesh_, mergeDist_)); +// } +// +// +// // Refinement engine +// // ~~~~~~~~~~~~~~~~~ +// +// { +// Info<< nl +// << "Determining initial surface intersections" << nl +// << "-----------------------------------------" << nl +// << endl; +// +// // Main refinement engine +// meshRefinerPtr_.reset +// ( +// new meshRefinement +// ( +// mesh, +// mergeDist_, // tolerance used in sorting coordinates +// surfaces() +// ) +// ); +// Info<< "Calculated surface intersections in = " +// << mesh_.time().cpuTimeIncrement() << " s" << endl; +// +// // Some stats +// meshRefinerPtr_().printMeshInfo(debug_, "Initial mesh"); +// +// meshRefinerPtr_().write +// ( +// debug_&meshRefinement::OBJINTERSECTIONS, +// mesh_.time().path()/mesh_.time().timeName() +// ); +// } +//} // Construct from separate dictionaries. @@ -611,6 +634,7 @@ Foam::autoHexMeshDriver::autoHexMeshDriver ( fvMesh& mesh, const dictionary& controlDict, + const dictionary& geometryDict, const dictionary& refineDict, const dictionary& decomposeDict ) @@ -618,15 +642,9 @@ Foam::autoHexMeshDriver::autoHexMeshDriver mesh_(mesh), dict_(controlDict), debug_(readLabel(controlDict.lookup("debug"))), - maxGlobalCells_(readLabel(refineDict.lookup("cellLimit"))), - maxLocalCells_(readLabel(refineDict.lookup("procCellLimit"))), - minRefineCells_(readLabel(refineDict.lookup("minimumRefine"))), - curvature_(readScalar(refineDict.lookup("curvature"))), - nBufferLayers_(readLabel(refineDict.lookup("nBufferLayers"))), - keepPoints_(refineDict.lookup("keepPoints")), mergeDist_ ( - getMergeDistance(readScalar(refineDict.lookup("mergeTolerance"))) + getMergeDistance(readScalar(controlDict.lookup("mergeTolerance"))) ) { if (debug_ > 0) @@ -635,127 +653,69 @@ Foam::autoHexMeshDriver::autoHexMeshDriver autoHexMeshDriver::debug = debug_; } - Info<< "Overall cell limit : " << maxGlobalCells_ - << endl; - Info<< "Per processor cell limit : " << maxLocalCells_ - << endl; - Info<< "Minimum number of cells to refine : " << minRefineCells_ - << endl; - Info<< "Curvature : " << curvature_ - << nl << endl; - Info<< "Layers between different refinement levels : " << nBufferLayers_ - << endl; - - // Check keepPoints are sensible - findCells(keepPoints_); - - - // Read refinement shells - // ~~~~~~~~~~~~~~~~~~~~~~ - - { - Info<< "Reading refinement shells." << endl; - - PtrList<dictionary> shellDicts(refineDict.lookup("refinementShells")); - - shells_.setSize(shellDicts.size()); - shellLevels_.setSize(shellDicts.size()); - shellRefineInside_.setSize(shellDicts.size()); + // Read geometry + // ~~~~~~~~~~~~~ - forAll(shellDicts, i) - { - const dictionary& dict = shellDicts[i]; - - shells_.set + Info<< "Reading all geometry." << endl; + allGeometryPtr_.reset + ( + new searchableSurfaces + ( + IOobject ( - i, - searchableSurface::New - ( - dict.lookup("type"), - dict.lookup("name"), - mesh_.time(), - dict - ) - ); - shellLevels_[i] = readLabel(dict.lookup("level")); - shellRefineInside_[i] = Switch(dict.lookup("refineInside")); - - if (shellRefineInside_[i]) - { - Info<< "Refinement level " << shellLevels_[i] - << " for all cells inside " << shells_[i].name() << endl; - } - else - { - Info<< "Refinement level " << shellLevels_[i] - << " for all cells outside " << shells_[i].name() << endl; - } - } - - Info<< "Read refinement shells in = " - << mesh_.time().cpuTimeIncrement() << " s" << endl; - - // Orient shell surfaces before any searching is done. - Info<< "Orienting triSurface shells so point far away is outside." - << endl; - orientOutside(shells_); - Info<< "Oriented shells in = " - << mesh_.time().cpuTimeIncrement() << " s" << endl; - } + "abc", // dummy name + mesh_.time().constant(), // directory + "triSurface", // instance + mesh_.time(), // registry + IOobject::MUST_READ, + IOobject::NO_WRITE + ), + geometryDict + ) + ); + Info<< "Read geometry in = " + << mesh_.time().cpuTimeIncrement() << " s" << nl << endl; // Read refinement surfaces // ~~~~~~~~~~~~~~~~~~~~~~~~ - { - Info<< "Reading surfaces and constructing search trees." << endl; - - surfacesPtr_.reset + Info<< "Reading refinement surfaces." << endl; + surfacesPtr_.reset + ( + new refinementSurfaces ( - new refinementSurfaces - ( - IOobject - ( - "", // dummy name - mesh_.time().constant(), // directory - "triSurface", // instance - mesh_.time(), // registry - IOobject::MUST_READ, - IOobject::NO_WRITE - ), - refineDict.lookup("surfaces") - ) - ); - Info<< "Read surfaces in = " - << mesh_.time().cpuTimeIncrement() << " s" << endl; + allGeometryPtr_(), + refineDict.subDict("refinementSurfaces") + ) + ); + Info<< "Read refinement surfaces in = " + << mesh_.time().cpuTimeIncrement() << " s" << nl << endl; - // Orient surfaces (if they're closed) before any searching is done. - Info<< "Orienting (closed) surfaces so keepPoint is outside." << endl; - forAll(surfaces(), i) - { - if (refinementSurfaces::isSurfaceClosed(surfaces()[i])) - { - refinementSurfaces::orientSurface - ( - keepPoints_[0], - surfacesPtr_()[i] - ); - } - } - Info<< "Oriented closed surfaces in = " - << mesh_.time().cpuTimeIncrement() << " s" << endl; - Info<< "Setting refinement level of surface to be consistent" - << " with shells." << endl; - surfacesPtr_().setMinLevelFields + // Read refinement shells + // ~~~~~~~~~~~~~~~~~~~~~~ + + Info<< "Reading refinement shells." << endl; + shellsPtr_.reset + ( + new shellSurfaces ( - shells_, - shellLevels_, - shellRefineInside_ - ); - Info<< "Checked shell refinement in = " - << mesh_.time().cpuTimeIncrement() << " s" << endl; - } + allGeometryPtr_(), + 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; + surfacesPtr_().setMinLevelFields(shells()); + Info<< "Checked shell refinement in = " + << mesh_.time().cpuTimeIncrement() << " s" << nl << endl; + + // Check faceZones are synchronised checkCoupledFaceZones(); @@ -777,38 +737,41 @@ Foam::autoHexMeshDriver::autoHexMeshDriver << "-----\t------" << endl; - forAll(surfaces(), surfI) + const labelList& surfaceGeometry = surfaces().surfaces(); + forAll(surfaceGeometry, surfI) { - const triSurfaceMesh& s = surfaces()[surfI]; + label geomI = surfaceGeometry[surfI]; - Info<< surfaces().names()[surfI] << ':' << nl << nl; + const wordList& regNames = allGeometryPtr_().regionNames()[geomI]; - const geometricSurfacePatchList& regions = s.patches(); + Info<< surfaces().names()[surfI] << ':' << nl << nl; - labelList nTrisPerRegion(surfaces().countRegions(s)); + //const triSurfaceMesh& s = surfaces()[surfI]; + //const geometricSurfacePatchList& regions = s.patches(); + //labelList nTrisPerRegion(surfaces().countRegions(s)); - forAll(regions, i) + forAll(regNames, i) { - if (nTrisPerRegion[i] > 0) - { + //if (nTrisPerRegion[i] > 0) + //{ label patchI = meshRefinement::addPatch ( mesh, //s.searchableSurface::name() + '_' + regions[i].name(), - surfaces().names()[surfI] + '_' + regions[i].name(), + regNames[i], wallPolyPatch::typeName ); - Info<< patchI << '\t' << regions[i].name() << nl; + Info<< patchI << '\t' << regNames[i] << nl; globalToPatch_[surfaces().globalRegion(surfI, i)] = patchI; - } + //} } Info<< nl; } Info<< "Added patches in = " - << mesh_.time().cpuTimeIncrement() << " s" << endl; + << mesh_.time().cpuTimeIncrement() << " s" << nl << endl; } // Parallel @@ -855,11 +818,12 @@ Foam::autoHexMeshDriver::autoHexMeshDriver ( mesh, mergeDist_, // tolerance used in sorting coordinates - surfaces() + surfaces(), // for surface intersection refinement + shells() // for volume (inside/outside) refinement ) ); Info<< "Calculated surface intersections in = " - << mesh_.time().cpuTimeIncrement() << " s" << endl; + << mesh_.time().cpuTimeIncrement() << " s" << nl << endl; // Some stats meshRefinerPtr_().printMeshInfo(debug_, "Initial mesh"); @@ -920,7 +884,7 @@ Foam::label Foam::autoHexMeshDriver::readFeatureEdges } Info<< "Read feature lines in = " - << mesh_.time().cpuTimeIncrement() << " s" << endl; + << mesh_.time().cpuTimeIncrement() << " s" << nl << endl; return featureMeshes_.size(); } @@ -928,6 +892,7 @@ Foam::label Foam::autoHexMeshDriver::readFeatureEdges Foam::label Foam::autoHexMeshDriver::featureEdgeRefine ( + const refinementParameters& refineParams, const PtrList<dictionary>& featDicts, const label maxIter, const label minRefine @@ -953,23 +918,18 @@ Foam::label Foam::autoHexMeshDriver::featureEdgeRefine ( meshRefiner.refineCandidates ( - keepPoints_[0], // For now only use one. - globalToPatch_, - curvature_, + refineParams.keepPoints()[0], // For now only use one. + refineParams.curvature(), featureMeshes_, featureLevels_, - shells_, - shellLevels_, - shellRefineInside_, - true, // featureRefinement false, // internalRefinement false, // surfaceRefinement false, // curvatureRefinement - maxGlobalCells_, - maxLocalCells_ + refineParams.maxGlobalCells(), + refineParams.maxLocalCells() ) ); labelList cellsToRefine @@ -1018,7 +978,11 @@ Foam::label Foam::autoHexMeshDriver::featureEdgeRefine } -Foam::label Foam::autoHexMeshDriver::surfaceOnlyRefine(const label maxIter) +Foam::label Foam::autoHexMeshDriver::surfaceOnlyRefine +( + const refinementParameters& refineParams, + const label maxIter +) { meshRefinement& meshRefiner = meshRefinerPtr_(); @@ -1044,23 +1008,18 @@ Foam::label Foam::autoHexMeshDriver::surfaceOnlyRefine(const label maxIter) ( meshRefiner.refineCandidates ( - keepPoints_[0], - globalToPatch_, - curvature_, + refineParams.keepPoints()[0], + refineParams.curvature(), featureMeshes_, featureLevels_, - shells_, - shellLevels_, - shellRefineInside_, - false, // featureRefinement false, // internalRefinement true, // surfaceRefinement true, // curvatureRefinement - maxGlobalCells_, - maxLocalCells_ + refineParams.maxGlobalCells(), + refineParams.maxLocalCells() ) ); labelList cellsToRefine @@ -1089,7 +1048,7 @@ Foam::label Foam::autoHexMeshDriver::surfaceOnlyRefine(const label maxIter) nCellsToRefine == 0 || ( iter >= overallMaxLevel - && nCellsToRefine <= minRefineCells_ + && nCellsToRefine <= refineParams.minRefineCells() ) ) { @@ -1116,7 +1075,11 @@ Foam::label Foam::autoHexMeshDriver::surfaceOnlyRefine(const label maxIter) } -void Foam::autoHexMeshDriver::removeInsideCells(const label nBufferLayers) +void Foam::autoHexMeshDriver::removeInsideCells +( + const refinementParameters& refineParams, + const label nBufferLayers +) { meshRefinement& meshRefiner = meshRefinerPtr_(); @@ -1135,7 +1098,7 @@ void Foam::autoHexMeshDriver::removeInsideCells(const label nBufferLayers) ( nBufferLayers, // nBufferLayers globalToPatch_, - keepPoints_[0] + refineParams.keepPoints()[0] ); if (debug_) @@ -1149,7 +1112,11 @@ void Foam::autoHexMeshDriver::removeInsideCells(const label nBufferLayers) } -Foam::label Foam::autoHexMeshDriver::shellRefine(const label maxIter) +Foam::label Foam::autoHexMeshDriver::shellRefine +( + const refinementParameters& refineParams, + const label maxIter +) { meshRefinement& meshRefiner = meshRefinerPtr_(); @@ -1170,15 +1137,7 @@ Foam::label Foam::autoHexMeshDriver::shellRefine(const label maxIter) // Determine the maximum refinement level over all volume refinement // regions. This determines the minumum number of shell refinement // iterations. - label overallMaxShellLevel; - if (shellLevels_.size() == 0) - { - overallMaxShellLevel = 0; - } - else - { - overallMaxShellLevel = max(shellLevels_); - } + label overallMaxShellLevel = shells().maxLevel(); label iter; for (iter = 0; iter < maxIter; iter++) @@ -1192,23 +1151,18 @@ Foam::label Foam::autoHexMeshDriver::shellRefine(const label maxIter) ( meshRefiner.refineCandidates ( - keepPoints_[0], - globalToPatch_, - curvature_, + refineParams.keepPoints()[0], + refineParams.curvature(), featureMeshes_, featureLevels_, - shells_, - shellLevels_, - shellRefineInside_, - false, // featureRefinement true, // internalRefinement false, // surfaceRefinement false, // curvatureRefinement - maxGlobalCells_, - maxLocalCells_ + refineParams.maxGlobalCells(), + refineParams.maxLocalCells() ) ); @@ -1232,16 +1186,16 @@ Foam::label Foam::autoHexMeshDriver::shellRefine(const label maxIter) findIndices(meshRefiner.userFaceData()[0].second(), 0) ); - Info<< "Collected boundary faces : " - << returnReduce(bFaces.size(), sumOp<label>()) << endl; + //Info<< "Collected boundary faces : " + // << returnReduce(bFaces.size(), sumOp<label>()) << endl; labelList cellsToRefine; - if (nBufferLayers_ <= 2) + if (refineParams.nBufferLayers() <= 2) { cellsToRefine = meshRefiner.meshCutter().consistentSlowRefinement ( - nBufferLayers_, + refineParams.nBufferLayers(), candidateCells, // cells to refine bFaces, // faces for nBufferLayers 1, // point difference @@ -1252,7 +1206,7 @@ Foam::label Foam::autoHexMeshDriver::shellRefine(const label maxIter) { cellsToRefine = meshRefiner.meshCutter().consistentSlowRefinement2 ( - nBufferLayers_, + refineParams.nBufferLayers(), candidateCells, // cells to refine bFaces // faces for nBufferLayers ); @@ -1276,7 +1230,7 @@ Foam::label Foam::autoHexMeshDriver::shellRefine(const label maxIter) nCellsToRefine == 0 || ( iter >= overallMaxShellLevel - && nCellsToRefine <= minRefineCells_ + && nCellsToRefine <= refineParams.minRefineCells() ) ) { @@ -1305,7 +1259,11 @@ Foam::label Foam::autoHexMeshDriver::shellRefine(const label maxIter) } -void Foam::autoHexMeshDriver::baffleAndSplitMesh(const bool handleSnapProblems) +void Foam::autoHexMeshDriver::baffleAndSplitMesh +( + const refinementParameters& refineParams, + const bool handleSnapProblems +) { meshRefinement& meshRefiner = meshRefinerPtr_(); @@ -1323,12 +1281,15 @@ void Foam::autoHexMeshDriver::baffleAndSplitMesh(const bool handleSnapProblems) !handleSnapProblems, // merge free standing baffles? const_cast<Time&>(mesh_.time()), globalToPatch_, - keepPoints_[0] + refineParams.keepPoints()[0] ); } -void Foam::autoHexMeshDriver::zonify() +void Foam::autoHexMeshDriver::zonify +( + const refinementParameters& refineParams +) { // Mesh is at its finest. Do zoning // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1351,7 +1312,7 @@ void Foam::autoHexMeshDriver::zonify() const_cast<Time&>(mesh_.time())++; } - meshRefiner.zonify(keepPoints_[0]); + meshRefiner.zonify(refineParams.keepPoints()[0]); if (debug_) { @@ -1372,6 +1333,7 @@ void Foam::autoHexMeshDriver::zonify() void Foam::autoHexMeshDriver::splitAndMergeBaffles ( + const refinementParameters& refineParams, const bool handleSnapProblems ) { @@ -1394,7 +1356,7 @@ void Foam::autoHexMeshDriver::splitAndMergeBaffles false, // merge free standing baffles? const_cast<Time&>(mesh_.time()), globalToPatch_, - keepPoints_[0] + refineParams.keepPoints()[0] ); if (debug_) @@ -1447,7 +1409,10 @@ void Foam::autoHexMeshDriver::splitAndMergeBaffles } -void Foam::autoHexMeshDriver::mergePatchFaces() +void Foam::autoHexMeshDriver::mergePatchFaces +( + const refinementParameters& refineParams +) { Info<< nl << "Merge refined boundary faces" << nl @@ -1536,8 +1501,8 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::autoHexMeshDriver::balance const wordList& fzNames = surfaces().faceZoneNames(); const faceZoneMesh& fZones = mesh_.faceZones(); - // Get faces whose owner and neighbour should stay together, i.e. - // they are not 'blocked'. + // Get faces whose owner and neighbour should stay together, + // i.e. they are not 'blocked'. label nZoned = 0; @@ -1655,11 +1620,18 @@ void Foam::autoHexMeshDriver::doRefine const_cast<Time&>(mesh_.time())++; + // Get all the refinement specific params + refinementParameters refineParams(refineDict); + + // 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 @@ -1668,34 +1640,37 @@ void Foam::autoHexMeshDriver::doRefine // 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(prepareForSnapping); + baffleAndSplitMesh(refineParams, prepareForSnapping); // Mesh is at its finest. Do optional zoning. - zonify(); + zonify(refineParams); // Pull baffles apart - splitAndMergeBaffles(prepareForSnapping); + splitAndMergeBaffles(refineParams, prepareForSnapping); // Do something about cells with refined faces on the boundary if (prepareForSnapping) { - mergePatchFaces(); + mergePatchFaces(refineParams); } // Do final balancing. Keep zoned faces on one processor. @@ -1719,6 +1694,9 @@ void Foam::autoHexMeshDriver::doSnap const_cast<Time&>(mesh_.time())++; + // Get all the snapping specific params + snapParameters snapParams(snapDict); + // Get the labels of added patches. labelList adaptPatchIDs(getSurfacePatches()); @@ -1739,7 +1717,7 @@ void Foam::autoHexMeshDriver::doSnap indirectPrimitivePatch& pp = ppPtr(); // Distance to attact to nearest feature on surface - const scalarField snapDist(calcSnapDistance(snapDict, pp)); + const scalarField snapDist(calcSnapDistance(snapParams, pp)); // Construct iterative mesh mover. @@ -1777,17 +1755,17 @@ void Foam::autoHexMeshDriver::doSnap << mesh_.time().cpuTimeIncrement() << " s\n" << nl << endl; // Pre-smooth patch vertices (so before determining nearest) - preSmoothPatch(snapDict, nInitErrors, baffles, meshMover); + preSmoothPatch(snapParams, nInitErrors, baffles, meshMover); // Calculate displacement at every patch point. Insert into // meshMover. calcNearestSurface(snapDist, meshMover); // Get smoothly varying internal displacement field. - smoothDisplacement(snapDict, meshMover); + smoothDisplacement(snapParams, meshMover); // Apply internal displacement to mesh. - scaleMesh(snapDict, nInitErrors, baffles, meshMover); + scaleMesh(snapParams, nInitErrors, baffles, meshMover); } // Merge any introduced baffles. @@ -1811,22 +1789,24 @@ void Foam::autoHexMeshDriver::doLayers const_cast<Time&>(mesh_.time())++; + // Get all the layer specific params + layerParameters layerParams(shrinkDict, mesh_.boundaryMesh()); + Info<< "Using mesh parameters " << motionDict << nl << endl; // Merge coplanar boundary faces - mergePatchFacesUndo(shrinkDict, motionDict); + mergePatchFacesUndo(layerParams, motionDict); - // Per global region the number of layers (0 if no layer) - const labelList& numLayers = surfaces().numLayers(); + // Per patch the number of layers (0 if no layer) + const labelList& numLayers = layerParams.numLayers(); // Patches that need to get a layer DynamicList<label> patchIDs(numLayers.size()); label nFacesWithLayers = 0; - forAll(numLayers, region) + forAll(numLayers, patchI) { - if (numLayers[region] > 0 && globalToPatch()[region] != -1) + if (numLayers[patchI] > 0) { - label patchI = globalToPatch()[region]; patchIDs.append(patchI); nFacesWithLayers += mesh_.boundaryMesh()[patchI].size(); } @@ -1882,7 +1862,7 @@ void Foam::autoHexMeshDriver::doLayers << endl; // Do all topo changes - addLayers(shrinkDict, motionDict, nInitErrors, meshMover); + addLayers(layerParams, motionDict, nInitErrors, meshMover); } // Write mesh. diff --git a/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoHexMeshDriver.H b/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoHexMeshDriver.H index 28a4845b9a81090d778dd8df172844fc53a7aaf5..06d377a2778a89faf535f30933aab0f85fad94b0 100644 --- a/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoHexMeshDriver.H +++ b/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoHexMeshDriver.H @@ -49,8 +49,9 @@ SourceFiles #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" @@ -70,6 +71,9 @@ class pointData; class faceSet; class addPatchCellLayer; class mapDistributePolyMesh; +class snapParameters; +class layerParameters; +class refinementParameters; /*---------------------------------------------------------------------------*\ Class autoHexMeshDriver Declaration @@ -79,15 +83,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 +143,24 @@ 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_; + // Refinement only + + //- Explicit features + PtrList<featureEdgeMesh> featureMeshes_; + //- Per feature the refinement level + labelList featureLevels_; - //- Explicit features - PtrList<featureEdgeMesh> featureMeshes_; - //- Per feature the refinement level - labelList featureLevels_; + //- All surface based geometry + autoPtr<searchableSurfaces> allGeometryPtr_; - //- Shells - PtrList<searchableSurface> shells_; - //- Per shell the refinement level - labelList shellLevels_; - //- Per shell whether to refine inside or outside - boolList shellRefineInside_; + //- Shells (geometry for inside/outside refinement) + autoPtr<shellSurfaces> shellsPtr_; - //- Surfaces with refinement levels built-in + //- Surfaces (geometry for intersection based refinement) autoPtr<refinementSurfaces> surfacesPtr_; //- Per refinement surface region the patch @@ -200,10 +184,6 @@ class autoHexMeshDriver //- 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 @@ -371,6 +351,7 @@ class autoHexMeshDriver // layers per surface. void setNumLayers ( + const labelList& patchToNLayers, const labelList& patchIDs, const indirectPrimitivePatch& pp, pointField& patchDisp, @@ -390,17 +371,22 @@ class autoHexMeshDriver //- 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 scalar expansionRatio, - const scalar finalLayerRatio, - const scalar relMinThickness, 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& minThickness, + scalarField& expansionRatio ) const; @@ -638,13 +624,13 @@ public: // Constructors - //- Construct from dictionary and mesh to modify - autoHexMeshDriver - ( - fvMesh& mesh, - const dictionary& meshDict, - const dictionary& decomposeDict - ); +// //- Construct from dictionary and mesh to modify +// autoHexMeshDriver +// ( +// fvMesh& mesh, +// const dictionary& meshDict, +// const dictionary& decomposeDict +// ); //- Alternative constructor from top-level controldictionary and // refinement specific dictionary @@ -652,6 +638,7 @@ public: ( fvMesh& mesh, const dictionary& controlDict, + const dictionary& geometryDict, const dictionary& refineDict, const dictionary& decomposeDict ); @@ -677,6 +664,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 { @@ -689,32 +682,53 @@ public: //- Refine around explicit feature edges label featureEdgeRefine ( + const refinementParameters& refineParams, const PtrList<dictionary>& featDicts, const label maxIter, const label minRefine ); //- Refine at surface intersections - label surfaceOnlyRefine(const label maxIter); + label surfaceOnlyRefine + ( + const refinementParameters& refineParams, + const label maxIter + ); //- Remove cells not reachable from keep points - void removeInsideCells(const label nBufferLayers); + void removeInsideCells + ( + const refinementParameters& refineParams, + const label nBufferLayers + ); //- Refine volume regions (interior of shells) - label shellRefine(const label maxIter); + label shellRefine + ( + const refinementParameters& refineParams, + const label maxIter + ); //- Introduce baffles; remove unreachable mesh parts // handleSnapProblems : whether to remove free floating cells - void baffleAndSplitMesh(const bool handleSnapProblems); + void baffleAndSplitMesh + ( + const refinementParameters& refineParams, + const bool handleSnapProblems + ); //- Move cells to zones - void zonify(); + void zonify(const refinementParameters&); //- Split and recombine baffles to get rid of single face baffles. - void splitAndMergeBaffles(const bool handleSnapProblems); + void splitAndMergeBaffles + ( + const refinementParameters& refineParams, + const bool handleSnapProblems + ); //- Merge multiple boundary faces on single cell - void mergePatchFaces(); + void mergePatchFaces(const refinementParameters&); //- Redecompose according to cell count // keepZoneFaces : find all faceZones from zoned surfaces and keep @@ -742,7 +756,7 @@ public: //- Calculate edge length per patch point. scalarField calcSnapDistance ( - const dictionary& snapDict, + const snapParameters& snapParams, const indirectPrimitivePatch& ) const; @@ -753,12 +767,19 @@ public: // of surface points (on castellated mesh) w.r.t. surface. void preSmoothPatch ( - const dictionary& snapDict, + 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. @@ -771,7 +792,7 @@ public: //- Smooth the displacement field to the internal. void smoothDisplacement ( - const dictionary& snapDict, + const snapParameters& snapParams, motionSmoother& ) const; @@ -779,7 +800,7 @@ public: // locally relax the displacement. void scaleMesh ( - const dictionary& snapDict, + const snapParameters& snapParams, const label nInitErrors, const List<labelPair>& baffles, motionSmoother& @@ -791,7 +812,7 @@ public: //- Merge patch faces on same cell. void mergePatchFacesUndo ( - const dictionary& shrinkDict, + const layerParameters& layerParams, const dictionary& motionDict ); @@ -801,7 +822,7 @@ public: //- Add cell layers void addLayers ( - const dictionary& shrinkDict, + const layerParameters& layerParams, const dictionary& motionDict, const label nAllowableErrors, motionSmoother& diff --git a/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoHexMeshDriverLayers.C b/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoHexMeshDriverLayers.C index 0615d504765172caa43557661955fb7b88cd09f7..3ebf41390cbb3c52986e2b41bdb4e8647b06ee3e 100644 --- a/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoHexMeshDriverLayers.C +++ b/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoHexMeshDriverLayers.C @@ -27,7 +27,6 @@ Description \*----------------------------------------------------------------------------*/ -#include "ListOps.H" #include "autoHexMeshDriver.H" #include "fvMesh.H" #include "Time.H" @@ -43,11 +42,8 @@ Description #include "mapPolyMesh.H" #include "addPatchCellLayer.H" #include "mapDistributePolyMesh.H" - -// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // - -const Foam::scalar Foam::autoHexMeshDriver::defaultConcaveAngle = 90; - +#include "OFstream.H" +#include "layerParameters.H" // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // @@ -1191,6 +1187,7 @@ void Foam::autoHexMeshDriver::handleWarpedFaces // No extrusion on faces with differing number of layers for points void Foam::autoHexMeshDriver::setNumLayers ( + const labelList& patchToNLayers, const labelList& patchIDs, const indirectPrimitivePatch& pp, pointField& patchDisp, @@ -1201,18 +1198,6 @@ void Foam::autoHexMeshDriver::setNumLayers Info<< nl << "Handling points with inconsistent layer specification ..." << endl; - const labelList& nSurfLayers = surfaces().numLayers(); - - // Build map from patch to layers - Map<label> patchToNLayers(nSurfLayers.size()); - forAll(nSurfLayers, region) - { - if (globalToPatch_[region] != -1) - { - patchToNLayers.insert(globalToPatch_[region], nSurfLayers[region]); - } - } - // Get for every point (really only nessecary on patch external points) // the max and min of any patch faces using it. labelList maxLayers(patchNLayers.size(), labelMin); @@ -1257,7 +1242,7 @@ void Foam::autoHexMeshDriver::setNumLayers // Unmark any point with different min and max // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - label nConflicts = 0; + //label nConflicts = 0; forAll(maxLayers, i) { @@ -1294,11 +1279,11 @@ void Foam::autoHexMeshDriver::setNumLayers } } - reduce(nConflicts, sumOp<label>()); - - Info<< "Set displacement to zero for " << nConflicts - << " points due to points being on multiple regions" - << " with inconsistent nLayers specification." << endl; + //reduce(nConflicts, sumOp<label>()); + // + //Info<< "Set displacement to zero for " << nConflicts + // << " points due to points being on multiple regions" + // << " with inconsistent nLayers specification." << endl; } @@ -1369,60 +1354,138 @@ void Foam::autoHexMeshDriver::growNoExtrusion } - -// Calculate pointwise wanted and minimum thickness. -// thickness: wanted thickness per point void Foam::autoHexMeshDriver::calculateLayerThickness ( - const scalar expansionRatio, - const scalar finalLayerRatio, - const scalar relMinThickness, 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& minThickness, + scalarField& expansionRatio ) const { - if (relMinThickness < 0 || relMinThickness > 2) + const polyBoundaryMesh& patches = mesh_.boundaryMesh(); + + if (min(patchRelMinThickness) < 0 || max(patchRelMinThickness) > 2) { FatalErrorIn("calculateLayerThickness(..)") << "Thickness should be factor of local undistorted cell size." << " Valid values are [0..2]." << nl - << " minThickness:" << relMinThickness + << " minThickness:" << patchRelMinThickness << exit(FatalError); } - thickness.setSize(pp.nPoints()); - minThickness.setSize(pp.nPoints()); // Per point the max cell level of connected cells + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + labelList maxPointLevel(pp.nPoints(), labelMin); - forAll(pp, i) { - label ownLevel = cellLevel[mesh_.faceOwner()[pp.addressing()[i]]]; + forAll(pp, i) + { + label ownLevel = cellLevel[mesh_.faceOwner()[pp.addressing()[i]]]; - const face& f = pp.localFaces()[i]; + const face& f = pp.localFaces()[i]; - forAll(f, fp) + forAll(f, fp) + { + maxPointLevel[f[fp]] = max(maxPointLevel[f[fp]], ownLevel); + } + } + + syncTools::syncPointList + ( + mesh_, + pp.meshPoints(), + maxPointLevel, + maxEqOp<label>(), + labelMin, // null value + false // no separation + ); + } + + + // Rework patch-wise layer parameters into minimum per point + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + expansionRatio.setSize(pp.nPoints()); + expansionRatio = GREAT; + scalarField finalLayerRatio(pp.nPoints(), GREAT); + scalarField relMinThickness(pp.nPoints(), GREAT); + + { + forAll(patchIDs, i) { - maxPointLevel[f[fp]] = max(maxPointLevel[f[fp]], ownLevel); + label patchI = patchIDs[i]; + + const labelList& meshPoints = patches[patchI].meshPoints(); + + forAll(meshPoints, patchPointI) + { + label ppPointI = pp.meshPointMap()[meshPoints[patchPointI]]; + + expansionRatio[ppPointI] = min + ( + expansionRatio[ppPointI], + patchExpansionRatio[patchI] + ); + finalLayerRatio[ppPointI] = min + ( + finalLayerRatio[ppPointI], + patchFinalLayerRatio[patchI] + ); + relMinThickness[ppPointI] = min + ( + relMinThickness[ppPointI], + patchRelMinThickness[patchI] + ); + } } + + syncTools::syncPointList + ( + mesh_, + pp.meshPoints(), + expansionRatio, + minEqOp<scalar>(), + GREAT, // null value + false // no separation + ); + syncTools::syncPointList + ( + mesh_, + pp.meshPoints(), + finalLayerRatio, + minEqOp<scalar>(), + GREAT, // null value + false // no separation + ); + syncTools::syncPointList + ( + mesh_, + pp.meshPoints(), + relMinThickness, + minEqOp<scalar>(), + GREAT, // null value + false // no separation + ); } - syncTools::syncPointList - ( - mesh_, - pp.meshPoints(), - maxPointLevel, - maxEqOp<label>(), - labelMin, // null value - false // no separation - ); + // Per mesh point the expansion parameters + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + thickness.setSize(pp.nPoints()); + minThickness.setSize(pp.nPoints()); + forAll(maxPointLevel, pointI) { // Find undistorted edge size for this level. @@ -1430,19 +1493,24 @@ void Foam::autoHexMeshDriver::calculateLayerThickness // Calculate layer thickness based on expansion ratio // and final layer height - if (expansionRatio == 1) + if (expansionRatio[pointI] == 1) { - thickness[pointI] = finalLayerRatio*patchNLayers[pointI]*edgeLen; - minThickness[pointI] = relMinThickness*edgeLen; + thickness[pointI] = + finalLayerRatio[pointI] + * patchNLayers[pointI] + * edgeLen; + minThickness[pointI] = relMinThickness[pointI]*edgeLen; } else { - scalar invExpansion = 1.0 / expansionRatio; + scalar invExpansion = 1.0 / expansionRatio[pointI]; label nLay = patchNLayers[pointI]; - thickness[pointI] = finalLayerRatio*edgeLen - * (1.0 - pow(invExpansion, nLay)) - / (1.0 - invExpansion); - minThickness[pointI] = relMinThickness*edgeLen; + thickness[pointI] = + finalLayerRatio[pointI] + * edgeLen + * (1.0 - pow(invExpansion, nLay)) + / (1.0 - invExpansion); + minThickness[pointI] = relMinThickness[pointI]*edgeLen; } } @@ -2309,31 +2377,34 @@ void Foam::autoHexMeshDriver::getLayerCellsFaces void Foam::autoHexMeshDriver::mergePatchFacesUndo ( - const dictionary& shrinkDict, + const layerParameters& layerParams, const dictionary& motionDict ) { - const scalar featureAngle(readScalar(shrinkDict.lookup("featureAngle"))); - scalar minCos = Foam::cos(featureAngle*mathematicalConstant::pi/180.0); - - scalar concaveAngle = defaultConcaveAngle; + scalar minCos = Foam::cos + ( + layerParams.featureAngle() + * mathematicalConstant::pi/180.0 + ); - if (shrinkDict.found("concaveAngle")) - { - concaveAngle = readScalar(shrinkDict.lookup("concaveAngle")); - } - scalar concaveCos = Foam::cos(concaveAngle*mathematicalConstant::pi/180.0); + scalar concaveCos = Foam::cos + ( + layerParams.concaveAngle() + * mathematicalConstant::pi/180.0 + ); Info<< nl << "Merging all faces of a cell" << nl << "---------------------------" << nl << " - which are on the same patch" << nl - << " - which make an angle < " << featureAngle << " degrees" + << " - which make an angle < " << layerParams.featureAngle() + << " degrees" << nl << " (cos:" << minCos << ')' << nl << " - as long as the resulting face doesn't become concave" << " by more than " - << concaveAngle << " degrees (0=straight, 180=fully concave)" << nl + << layerParams.concaveAngle() + << " degrees (0=straight, 180=fully concave)" << nl << endl; label nChanged = mergePatchFacesUndo(minCos, concaveCos, motionDict); @@ -2344,80 +2415,18 @@ void Foam::autoHexMeshDriver::mergePatchFacesUndo void Foam::autoHexMeshDriver::addLayers ( - const dictionary& shrinkDict, + const layerParameters& layerParams, const dictionary& motionDict, const label nAllowableErrors, motionSmoother& meshMover ) { - // Read some more dictionary settings - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - // Min thickness per cell - const scalar relMinThickness(readScalar(shrinkDict.lookup("minThickness"))); - - // Warped faces recoginition - const scalar maxFaceThicknessRatio - ( - readScalar(shrinkDict.lookup("maxFaceThicknessRatio")) - ); - const scalar featureAngle(readScalar(shrinkDict.lookup("featureAngle"))); - - // Feature angle - const scalar minCos = Foam::cos(featureAngle*mathematicalConstant::pi/180.); - - // Number of layers for to grow non-extrusion region by - const label nGrow(readLabel(shrinkDict.lookup("nGrow"))); - - //const label nSmoothDisp(readLabel(shrinkDict.lookup("nSmoothDispl"))); - // Snapping iterations - const label nSnap(readLabel(shrinkDict.lookup("nSnap"))); - - // Mesh termination and medial axis smoothing quantities - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - const scalar minCosLayerTermination = - Foam::cos(0.5*featureAngle*mathematicalConstant::pi/180.); - const scalar expansionRatio - ( - readScalar(shrinkDict.lookup("expansionRatio")) - ); - const scalar finalLayerRatio - ( - readScalar(shrinkDict.lookup("finalLayerRatio")) - ); - const label nBufferCellsNoExtrude - ( - readLabel(shrinkDict.lookup("nBufferCellsNoExtrude")) - ); - const label nSmoothSurfaceNormals - ( - readLabel(shrinkDict.lookup("nSmoothSurfaceNormals")) - ); - const label nSmoothNormals(readLabel(shrinkDict.lookup("nSmoothNormals"))); - const label nSmoothThickness - ( - readLabel(shrinkDict.lookup("nSmoothThickness")) - ); - const scalar maxThicknessToMedialRatio - ( - readScalar(shrinkDict.lookup("maxThicknessToMedialRatio")) - ); - - // Medial axis setup - - const scalar minMedianAxisAngle - ( - readScalar(shrinkDict.lookup("minMedianAxisAngle")) - ); - const scalar minMedianAxisAngleCos = - Foam::cos(minMedianAxisAngle*mathematicalConstant::pi/180.); - - - // Precalculate mesh edge labels for patch edges const indirectPrimitivePatch& pp = meshMover.patch(); const labelList& meshPoints = pp.meshPoints(); + // Precalculate mesh edge labels for patch edges + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + labelList meshEdges(pp.nEdges()); forAll(pp.edges(), edgeI) { @@ -2449,8 +2458,9 @@ void Foam::autoHexMeshDriver::addLayers setNumLayers ( - meshMover.adaptPatchIDs(), - pp, + layerParams.numLayers(), // per patch the num layers + meshMover.adaptPatchIDs(), // patches that are being moved + pp, // indirectpatch for all faces moving patchDisp, patchNLayers, @@ -2477,7 +2487,7 @@ void Foam::autoHexMeshDriver::addLayers ( pp, meshEdges, - minCos, + layerParams.featureAngle()*mathematicalConstant::pi/180.0, patchDisp, patchNLayers, @@ -2494,7 +2504,7 @@ void Foam::autoHexMeshDriver::addLayers handleWarpedFaces ( pp, - maxFaceThicknessRatio, + layerParams.maxFaceThicknessRatio(), edge0Len, cellLevel, @@ -2517,7 +2527,7 @@ void Foam::autoHexMeshDriver::addLayers // Grow out region of non-extrusion - for (label i = 0; i < nGrow; i++) + for (label i = 0; i < layerParams.nGrow(); i++) { growNoExtrusion ( @@ -2528,21 +2538,24 @@ void Foam::autoHexMeshDriver::addLayers ); } - // Determine point-wise layer thickness + // Determine (wanted) point-wise layer thickness and expansion ratio scalarField thickness(pp.nPoints()); scalarField minThickness(pp.nPoints()); + scalarField expansionRatio(pp.nPoints()); calculateLayerThickness ( - expansionRatio, - finalLayerRatio, - relMinThickness, pp, + meshMover.adaptPatchIDs(), + layerParams.expansionRatio(), + layerParams.finalLayerRatio(), + layerParams.minThickness(), cellLevel, patchNLayers, edge0Len, thickness, - minThickness + minThickness, + expansionRatio ); // Calculate wall to medial axis distance for smoothing displacement @@ -2602,9 +2615,9 @@ void Foam::autoHexMeshDriver::addLayers medialAxisSmoothingInfo ( meshMover, - nSmoothNormals, - nSmoothSurfaceNormals, - minMedianAxisAngleCos, + layerParams.nSmoothNormals(), + layerParams.nSmoothSurfaceNormals(), + layerParams.minMedianAxisAngleCos(), dispVec, medialRatio, @@ -2657,8 +2670,8 @@ void Foam::autoHexMeshDriver::addLayers // debug, // meshMover, // -patchDisp, // Shrink in opposite direction of addedPoints - // nSmoothDisp, - // nSnap + // layerParams.nSmoothDisp(), + // layerParams.nSnap() //); // Medial axis based shrinking @@ -2666,11 +2679,11 @@ void Foam::autoHexMeshDriver::addLayers ( meshMover, - nSmoothThickness, - maxThicknessToMedialRatio, + layerParams.nSmoothThickness(), + layerParams.maxThicknessToMedialRatio(), nAllowableErrors, - nSnap, - minCosLayerTermination, + layerParams.nSnap(), + layerParams.layerTerminationCos(), thickness, minThickness, @@ -2735,7 +2748,7 @@ void Foam::autoHexMeshDriver::addLayers meshMover, patchNLayers, extrudeStatus, - nBufferCellsNoExtrude, + layerParams.nBufferCellsNoExtrude(), nPatchPointLayers, nPatchFaceLayers ); @@ -2747,7 +2760,7 @@ void Foam::autoHexMeshDriver::addLayers { if (patchNLayers[i] > 0) { - if (expansionRatio == 1.0) + if (expansionRatio[i] == 1.0) { firstDisp[i] = patchDisp[i]/nPatchPointLayers[i]; } @@ -2755,15 +2768,15 @@ void Foam::autoHexMeshDriver::addLayers { label nLay = nPatchPointLayers[i]; scalar h = - pow(expansionRatio,nLay - 1) - * (mag(patchDisp[i])*(1.0 - expansionRatio)) - / (1.0 - pow(expansionRatio, nLay)); + pow(expansionRatio[i], nLay - 1) + * (mag(patchDisp[i])*(1.0 - expansionRatio[i])) + / (1.0 - pow(expansionRatio[i], nLay)); firstDisp[i] = h/mag(patchDisp[i])*patchDisp[i]; } } } - scalar invExpansionRatio = 1.0 / expansionRatio; + scalarField invExpansionRatio = 1.0 / expansionRatio; // Add topo regardless of whether extrudeStatus is extruderemove. // Not add layer if patchDisp is zero. diff --git a/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoHexMeshDriverSnap.C b/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoHexMeshDriverSnap.C index d4c72ea4dadfef698cf8ab40debe7e6b2dbed864..8e074cd05e2506da9f76c2fa877cbda00ce1246e 100644 --- a/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoHexMeshDriverSnap.C +++ b/src/autoMesh/autoHexMesh/autoHexMeshDriver/autoHexMeshDriverSnap.C @@ -37,6 +37,7 @@ Description #include "pointEdgePoint.H" #include "PointEdgeWave.H" #include "mergePoints.H" +#include "snapParameters.H" // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // @@ -95,8 +96,7 @@ Foam::Map<Foam::label> Foam::autoHexMeshDriver::getZoneBafflePatches 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() << endl; @@ -712,8 +712,8 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::autoHexMeshDriver::createZoneBaffles if (debug_) { const_cast<Time&>(mesh_.time())++; - Pout<< "Writing baffled mesh to time " << mesh_.time().timeName() - << endl; + Pout<< "Writing baffled mesh to time " + << mesh_.time().timeName() << endl; mesh_.write(); } } @@ -755,14 +755,10 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::autoHexMeshDriver::mergeZoneBaffles Foam::scalarField Foam::autoHexMeshDriver::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(); @@ -793,7 +789,7 @@ Foam::scalarField Foam::autoHexMeshDriver::calcSnapDistance false // no separation ); - return snapTol*maxEdgeLen; + return snapParams.snapTol()*maxEdgeLen; } @@ -801,7 +797,7 @@ Foam::scalarField Foam::autoHexMeshDriver::calcSnapDistance Foam::labelList Foam::autoHexMeshDriver::getSurfacePatches() const { // Set of patches originating from surface - labelHashSet surfacePatchSet(surfaces().size()); + labelHashSet surfacePatchSet(globalToPatch_.size()); forAll(globalToPatch_, i) { @@ -826,21 +822,21 @@ Foam::labelList Foam::autoHexMeshDriver::getSurfacePatches() const void Foam::autoHexMeshDriver::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"))); - 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()); @@ -857,11 +853,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; @@ -901,6 +897,56 @@ void Foam::autoHexMeshDriver::preSmoothPatch } +// Get (pp-local) indices of points that are both on zone and on patched surface +Foam::labelList Foam::autoHexMeshDriver::getZoneSurfacePoints +( + const indirectPrimitivePatch& pp, + const word& zoneName +) const +{ + label zoneI = mesh_.faceZones().findZoneID(zoneName); + + if (zoneI == -1) + { + FatalErrorIn + ( + "autoHexMeshDriver::getZoneSurfacePoints" + "(const indirectPrimitivePatch&, const word&)" + ) << "Cannot find zone " << zoneName + << exit(FatalError); + } + + const faceZone& fZone = mesh_.faceZones()[zoneI]; + + + // Could use PrimitivePatch & localFaces to extract points but might just + // as well do it ourselves. + + boolList pointOnZone(pp.nPoints(), false); + + forAll(fZone, i) + { + const face& f = mesh_.faces()[fZone[i]]; + + forAll(f, fp) + { + label meshPointI = f[fp]; + + Map<label>::const_iterator iter = + pp.meshPointMap().find(meshPointI); + + if (iter != pp.meshPointMap().end()) + { + label pointI = iter(); + pointOnZone[pointI] = true; + } + } + } + + return findIndices(pointOnZone, true); +} + + Foam::vectorField Foam::autoHexMeshDriver::calcNearestSurface ( const scalarField& snapDist, @@ -925,33 +971,40 @@ 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(..)") + // << "For point:" << pointI + // << " coordinate:" << localPoints[pointI] + // << " did not find any surface within:" + // << 4*snapDist[pointI] + // << " meter." << endl; + //} } - //else - //{ - // WarningIn("autoHexMeshDriver::calcNearestSurface(..)") - // << "For point:" << pointI - // << " coordinate:" << localPoints[pointI] - // << " did not find any surface within:" << 4*snapDist[pointI] - // << " meter." << endl; - //} } + // 2. All points on zones to their respective surface // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -964,50 +1017,50 @@ Foam::vectorField Foam::autoHexMeshDriver::calcNearestSurface const labelList surfacesToTest(1, zoneSurfI); - label zoneI = mesh_.faceZones().findZoneID(faceZoneNames[zoneSurfI]); - - const faceZone& fZone = mesh_.faceZones()[zoneI]; + // Get indices of points both on faceZone and on pp. + labelList zonePointIndices + ( + getZoneSurfacePoints + ( + pp, + faceZoneNames[zoneSurfI] + ) + ); - forAll(fZone, i) + pointField zonePoints(zonePointIndices.size()); + forAll(zonePointIndices, 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; + zonePoints[i] = localPoints[zonePointIndices[i]]; + } - label surfI = surfaces().findNearest - ( - surfacesToTest, - localPoints[pointI], - sqr(4*snapDist[pointI]), // sqr of attract distance - pHit - ); + // 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 + ); - if (surfI != -1) - { - patchDisp[pointI] = - pHit.hitPoint() - localPoints[pointI]; - } - else - { - WarningIn("autoHexMeshDriver::calcNearestSurface(..)") - << "For point:" << pointI - << " coordinate:" << localPoints[pointI] - << " did not find any surface within:" - << 4*snapDist[pointI] - << " meter." << endl; - } - } + forAll(hitInfo, pointI) + { + if (hitInfo[pointI].hit()) + { + patchDisp[pointI] = + hitInfo[pointI].hitPoint() + - localPoints[pointI]; + } + else + { + WarningIn("autoHexMeshDriver::calcNearestSurface(..)") + << "For point:" << pointI + << " coordinate:" << localPoints[pointI] + << " did not find any surface within:" + << 4*snapDist[pointI] + << " meter." << endl; } } } @@ -1078,7 +1131,7 @@ Foam::vectorField Foam::autoHexMeshDriver::calcNearestSurface void Foam::autoHexMeshDriver::smoothDisplacement ( - const dictionary& snapDict, + const snapParameters& snapParams, motionSmoother& meshMover ) const { @@ -1087,9 +1140,6 @@ void Foam::autoHexMeshDriver::smoothDisplacement 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); @@ -1098,7 +1148,7 @@ void Foam::autoHexMeshDriver::smoothDisplacement // 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) { @@ -1140,16 +1190,12 @@ void Foam::autoHexMeshDriver::smoothDisplacement void Foam::autoHexMeshDriver::scaleMesh ( - const dictionary& snapDict, + const snapParameters& snapParams, const label nInitErrors, const List<labelPair>& baffles, motionSmoother& meshMover ) { - // Snapping iterations - label nSnap(readLabel(snapDict.lookup("nSnap"))); - - // Relax displacement until correct mesh // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ labelList checkFaces(identity(mesh_.nFaces())); @@ -1157,11 +1203,11 @@ void Foam::autoHexMeshDriver::scaleMesh 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); diff --git a/src/autoMesh/autoHexMesh/autoHexMeshDriver/layerParameters/layerParameters.C b/src/autoMesh/autoHexMesh/autoHexMeshDriver/layerParameters/layerParameters.C new file mode 100644 index 0000000000000000000000000000000000000000..1d3a18714a0510dc70a15f85eb1e26df440f4eba --- /dev/null +++ b/src/autoMesh/autoHexMesh/autoHexMeshDriver/layerParameters/layerParameters.C @@ -0,0 +1,213 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*---------------------------------------------------------------------------*/ + +#include "layerParameters.H" +#include "polyBoundaryMesh.H" +#include "mathematicalConstants.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +const Foam::scalar Foam::layerParameters::defaultConcaveAngle = 90; + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +// Construct from dictionary +Foam::layerParameters::layerParameters +( + const dictionary& dict, + const labelList& numLayers +) +: + numLayers_(numLayers), + expansionRatio_ + ( + numLayers_.size(), + readScalar(dict.lookup("expansionRatio")) + ), + finalLayerRatio_ + ( + numLayers_.size(), + readScalar(dict.lookup("finalLayerRatio")) + ), + minThickness_ + ( + numLayers_.size(), + readScalar(dict.lookup("minThickness")) + ), + featureAngle_(readScalar(dict.lookup("featureAngle"))), + concaveAngle_ + ( + dict.found("concaveAngle") + ? readScalar(dict.lookup("concaveAngle")) + : defaultConcaveAngle + ), + nGrow_(readLabel(dict.lookup("nGrow"))), + nSmoothSurfaceNormals_ + ( + readLabel(dict.lookup("nSmoothSurfaceNormals")) + ), + nSmoothNormals_(readLabel(dict.lookup("nSmoothNormals"))), + nSmoothThickness_(readLabel(dict.lookup("nSmoothThickness"))), + maxFaceThicknessRatio_ + ( + readScalar(dict.lookup("maxFaceThicknessRatio")) + ), + layerTerminationCos_ + ( + Foam::cos + ( + 0.5 + * featureAngle_ + * mathematicalConstant::pi/180. + ) + ), + maxThicknessToMedialRatio_ + ( + readScalar(dict.lookup("maxThicknessToMedialRatio")) + ), + minMedianAxisAngleCos_ + ( + Foam::cos(readScalar(dict.lookup("minMedianAxisAngle"))) + * mathematicalConstant::pi/180. + ), + nBufferCellsNoExtrude_ + ( + readLabel(dict.lookup("nBufferCellsNoExtrude")) + ), + nSnap_(readLabel(dict.lookup("nSnap"))) +{} + + +// Construct from dictionary +Foam::layerParameters::layerParameters +( + const dictionary& dict, + const polyBoundaryMesh& boundaryMesh +) +: + numLayers_(boundaryMesh.size(), 0), + expansionRatio_ + ( + boundaryMesh.size(), + readScalar(dict.lookup("expansionRatio")) + ), + finalLayerRatio_ + ( + boundaryMesh.size(), + readScalar(dict.lookup("finalLayerRatio")) + ), + minThickness_ + ( + boundaryMesh.size(), + readScalar(dict.lookup("minThickness")) + ), + featureAngle_(readScalar(dict.lookup("featureAngle"))), + concaveAngle_ + ( + dict.found("concaveAngle") + ? readScalar(dict.lookup("concaveAngle")) + : defaultConcaveAngle + ), + nGrow_(readLabel(dict.lookup("nGrow"))), + nSmoothSurfaceNormals_ + ( + readLabel(dict.lookup("nSmoothSurfaceNormals")) + ), + nSmoothNormals_(readLabel(dict.lookup("nSmoothNormals"))), + nSmoothThickness_(readLabel(dict.lookup("nSmoothThickness"))), + maxFaceThicknessRatio_ + ( + readScalar(dict.lookup("maxFaceThicknessRatio")) + ), + layerTerminationCos_ + ( + Foam::cos + ( + 0.5 + * featureAngle_ + * mathematicalConstant::pi/180. + ) + ), + maxThicknessToMedialRatio_ + ( + readScalar(dict.lookup("maxThicknessToMedialRatio")) + ), + minMedianAxisAngleCos_ + ( + Foam::cos(readScalar(dict.lookup("minMedianAxisAngle"))) + * mathematicalConstant::pi/180. + ), + nBufferCellsNoExtrude_ + ( + readLabel(dict.lookup("nBufferCellsNoExtrude")) + ), + nSnap_(readLabel(dict.lookup("nRelaxIter"))) +{ + const dictionary& layersDict = dict.subDict("layers"); + + forAllConstIter(dictionary, layersDict, iter) + { + const word& key = iter().keyword(); + + if (layersDict.isDict(key)) + { + label patchI = boundaryMesh.findPatchID(key); + + if (patchI == -1) + { + FatalErrorIn + ( + "layerParameters::layerParameters" + "(const dictionary&, const polyBoundaryMesh&)" + ) << "Specified illegal patch " << key + << " in layer dictionary." << endl + << "Valid patch names are " << boundaryMesh.names() + << exit(FatalError); + } + + const dictionary& layerDict = layersDict.subDict(key); + + numLayers_[patchI] = + readLabel(layerDict.lookup("nSurfaceLayers")); + + //- Patch-wise layer parameters disabled for now. Just remove + // settings in initialiser list and uncomment below. + //expansionRatio_[patchI] = + // readScalar(layerDict.lookup("expansionRatio")); + //finalLayerRatio_[patchI] = + // readScalar(layerDict.lookup("finalLayerRatio")); + //minThickness_[patchI] = + // readScalar(layerDict.lookup("minThickness")); + } + } +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + + +// ************************************************************************* // diff --git a/src/autoMesh/autoHexMesh/autoHexMeshDriver/layerParameters/layerParameters.H b/src/autoMesh/autoHexMesh/autoHexMeshDriver/layerParameters/layerParameters.H new file mode 100644 index 0000000000000000000000000000000000000000..9c16e271161f31320b5347adaac64a8aec6fb4ba --- /dev/null +++ b/src/autoMesh/autoHexMesh/autoHexMeshDriver/layerParameters/layerParameters.H @@ -0,0 +1,246 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Class + Foam::layerParameters + +Description + Simple container to keep together layer specific information. + +SourceFiles + layerParameters.C + +\*---------------------------------------------------------------------------*/ + +#ifndef layerParameters_H +#define layerParameters_H + +#include "dictionary.H" +#include "scalarField.H" +#include "labelList.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Class forward declarations +class polyBoundaryMesh; + +/*---------------------------------------------------------------------------*\ + Class layerParameters Declaration +\*---------------------------------------------------------------------------*/ + +class layerParameters +{ + // Static data members + + //- Default angle for faces to be convcave + static const scalar defaultConcaveAngle; + + + // Private data + + // Per patch (not region!) information + + //- How many layers to add. + labelList numLayers_; + + scalarField expansionRatio_; + + //- Wanted thickness of final added cell layer. If multiple layers + // is the thickness of the layer furthest away from the wall. + // Relative to undistorted size of cell outside layer. + scalarField finalLayerRatio_; + + //- Minimum thickness of cell layer. If for any reason layer + // cannot be above minThickness do not add layer. + // Relative to undistorted size of cell outside layer. + scalarField minThickness_; + + + scalar featureAngle_; + + scalar concaveAngle_; + + label nGrow_; + + label nSmoothSurfaceNormals_; + + label nSmoothNormals_; + + label nSmoothThickness_; + + scalar maxFaceThicknessRatio_; + + scalar layerTerminationCos_; + + scalar maxThicknessToMedialRatio_; + + scalar minMedianAxisAngleCos_; + + label nBufferCellsNoExtrude_; + + label nSnap_; + + + // Private Member Functions + + //- Disallow default bitwise copy construct + layerParameters(const layerParameters&); + + //- Disallow default bitwise assignment + void operator=(const layerParameters&); + + +public: + + // Constructors + + //- Construct from dictionary - old syntax + layerParameters(const dictionary& dict, const labelList& numLayers); + + //- Construct from dictionary - new syntax + layerParameters(const dictionary& dict, const polyBoundaryMesh&); + + + // Member Functions + + // Access + + // Per patch information + + //- How many layers to add. + const labelList& numLayers() const + { + return numLayers_; + } + + // Expansion factor for layer mesh + const scalarField& expansionRatio() const + { + return expansionRatio_; + } + + //- Wanted thickness of final added cell layer. If multiple + // layers + // is the thickness of the layer furthest away from the wall. + // Relative to undistorted size of cell outside layer. + const scalarField& finalLayerRatio() const + { + return finalLayerRatio_; + } + + //- Minimum thickness of cell layer. If for any reason layer + // cannot be above minThickness do not add layer. + // Relative to undistorted size of cell outside layer. + const scalarField& minThickness() const + { + return minThickness_; + } + + + scalar featureAngle() const + { + return featureAngle_; + } + + scalar concaveAngle() const + { + return concaveAngle_; + } + + //- If points get not extruded do nGrow layers of connected faces + // that are not grown. Is used to not do layers at all close to + // features. + label nGrow() const + { + return nGrow_; + } + + // Number of smoothing iterations of surface normals + label nSmoothSurfaceNormals() const + { + return nSmoothSurfaceNormals_; + } + + // Number of smoothing iterations of interior mesh movement + // direction + label nSmoothNormals() const + { + return nSmoothNormals_; + } + + // Smooth layer thickness over surface patches + label nSmoothThickness() const + { + return nSmoothThickness_; + } + + // Stop layer growth on highly warped cells + scalar maxFaceThicknessRatio() const + { + return maxFaceThicknessRatio_; + } + + scalar layerTerminationCos() const + { + return layerTerminationCos_; + } + + // Reduce layer growth where ratio thickness to medial + // distance is large + scalar maxThicknessToMedialRatio() const + { + return maxThicknessToMedialRatio_; + } + + // Angle used to pick up medial axis points + scalar minMedianAxisAngleCos() const + { + return minMedianAxisAngleCos_; + } + + // Create buffer region for new layer terminations + label nBufferCellsNoExtrude() const + { + return nBufferCellsNoExtrude_; + } + + label nSnap() const + { + return nSnap_; + } +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/autoMesh/autoHexMesh/autoHexMeshDriver/refinementParameters/refinementParameters.C b/src/autoMesh/autoHexMesh/autoHexMeshDriver/refinementParameters/refinementParameters.C new file mode 100644 index 0000000000000000000000000000000000000000..7912279e017eefb0d30f3a56af5a7526d112abf3 --- /dev/null +++ b/src/autoMesh/autoHexMesh/autoHexMeshDriver/refinementParameters/refinementParameters.C @@ -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; +} + + +// ************************************************************************* // diff --git a/src/autoMesh/autoHexMesh/autoHexMeshDriver/refinementParameters/refinementParameters.H b/src/autoMesh/autoHexMesh/autoHexMeshDriver/refinementParameters/refinementParameters.H new file mode 100644 index 0000000000000000000000000000000000000000..25b97af0346fa6afb41d8e90297502a69493232d --- /dev/null +++ b/src/autoMesh/autoHexMesh/autoHexMeshDriver/refinementParameters/refinementParameters.H @@ -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 + +// ************************************************************************* // diff --git a/src/autoMesh/autoHexMesh/autoHexMeshDriver/snapParameters/snapParameters.C b/src/autoMesh/autoHexMesh/autoHexMeshDriver/snapParameters/snapParameters.C new file mode 100644 index 0000000000000000000000000000000000000000..253826c38fddfdb52c106951353469ee46f21c3c --- /dev/null +++ b/src/autoMesh/autoHexMesh/autoHexMeshDriver/snapParameters/snapParameters.C @@ -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 * * * * * * * * * * * * * // + + +// ************************************************************************* // diff --git a/src/autoMesh/autoHexMesh/autoHexMeshDriver/snapParameters/snapParameters.H b/src/autoMesh/autoHexMesh/autoHexMeshDriver/snapParameters/snapParameters.H new file mode 100644 index 0000000000000000000000000000000000000000..2a173578b0c5e336e8fe888d2b63c35b8346287c --- /dev/null +++ b/src/autoMesh/autoHexMesh/autoHexMeshDriver/snapParameters/snapParameters.H @@ -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 + +// ************************************************************************* // diff --git a/src/autoMesh/autoHexMesh/meshRefinement/meshRefinement.C b/src/autoMesh/autoHexMesh/meshRefinement/meshRefinement.C index 8b9869ad57f0b28b9cf0a8a7df5ce2940ead8d73..a60e7758da89da4ce2da8b00b86515e1225f8195 100644 --- a/src/autoMesh/autoHexMesh/meshRefinement/meshRefinement.C +++ b/src/autoMesh/autoHexMesh/meshRefinement/meshRefinement.C @@ -24,9 +24,7 @@ License \*----------------------------------------------------------------------------*/ -#include "Pstream.H" #include "meshRefinement.H" - #include "volMesh.H" #include "volFields.H" #include "surfaceMesh.H" @@ -34,7 +32,6 @@ License #include "Time.H" #include "refinementHistory.H" #include "refinementSurfaces.H" -#include "cellSet.H" #include "decompositionMethod.H" #include "regionSplit.H" #include "fvMeshDistribute.H" @@ -50,8 +47,9 @@ License #include "globalPointPatchFields.H" #include "calculatedPointPatchFields.H" #include "processorPointPatch.H" -#include "featureEdgeMesh.H" #include "globalIndex.H" +#include "meshTools.H" +#include "OFstream.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // @@ -117,90 +115,6 @@ void Foam::meshRefinement::calcNeighbourData } -//void Foam::meshRefinement::calcCanonicalBoundaryData -//( -// labelList& leftLevel, -// pointField& leftCc, -// labelList& rightLevel, -// pointField& rightCc -//) const -//{ -// const labelList& cellLevel = meshCutter_.cellLevel(); -// const pointField& cellCentres = mesh_.cellCentres(); -// const polyBoundaryMesh& patches = mesh_.boundaryMesh(); -// -// // Get boundary face centre and level. Coupled aware. -// calcNeighbourData(rightLevel, rightCc); -// -// // Get owner face centre and level. Canonical sort for coupled faces. -// forAll(patches, patchI) -// { -// const polyPatch& pp = patches[patchI]; -// -// const unallocLabelList& faceCells = pp.faceCells(); -// const vectorField::subField faceCentres = pp.faceCentres(); -// -// if (isA<processorPolyPatch>(pp)) -// { -// const processorPolyPatch& procPp = -// refCast<const processorPolyPatch>(patches[patchI]); -// -// label bFaceI = pp.start()-mesh_.nInternalFaces(); -// forAll(faceCells, i) -// { -// leftLevel[bFaceI] = cellLevel[faceCells[i]]; -// leftCc[bFaceI] = cellCentres[faceCells[i]]; -// bFaceI++; -// } -// -// // Swap if on neighbour so both sides have same values -// if (!procPp.owner()) -// { -// forAll(leftLevel, i) -// { -// Swap(leftLevel[i], rightLevel[i]); -// Swap(leftCc[i], rightCc[i]); -// } -// } -// } -// else if (isA<cyclicPolyPatch>(pp)) -// { -// const processorPolyPatch& cycPp = -// refCast<const processorPolyPatch>(patches[patchI]); -// -// label bFaceI = pp.start()-mesh_.nInternalFaces(); -// forAll(faceCells, i) -// { -// leftLevel[bFaceI] = cellLevel[faceCells[i]]; -// leftCc[bFaceI] = cellCentres[faceCells[i]]; -// bFaceI++; -// } -// -// // First half has data in normal order: owner in leftLevel,leftCc -// // and coupled data in rightLevel, rightCc. Second half has it -// // swapped: -// bFaceI = pp.start()+cycPp.size()/2-mesh_.nInternalFaces(); -// for (label i = 0; i < cycPp.size()/2; i++) -// { -// Swap(leftLevel[bFaceI], rightLevel[bFaceI]); -// Swap(leftCc[bFaceI], rightCc[bFaceI]); -// bFaceI++; -// } -// } -// else -// { -// label bFaceI = pp.start()-mesh_.nInternalFaces(); -// forAll(faceCells, i) -// { -// leftLevel[bFaceI] = cellLevel[faceCells[i]]; -// leftCc[bFaceI] = cellCentres[faceCells[i]]; -// bFaceI++; -// } -// } -// } -//} - - // Find intersections of edges (given by their two endpoints) with surfaces. // Returns first intersection if there are more than one. void Foam::meshRefinement::updateIntersections(const labelList& changedFaces) @@ -220,33 +134,46 @@ void Foam::meshRefinement::updateIntersections(const labelList& changedFaces) pointField neiCc(mesh_.nFaces()-mesh_.nInternalFaces()); calcNeighbourData(neiLevel, neiCc); + // Collect segments we want to test for + pointField start(changedFaces.size()); + pointField end(changedFaces.size()); + forAll(changedFaces, i) { label faceI = changedFaces[i]; label own = mesh_.faceOwner()[faceI]; - pointIndexHit surfaceHitInfo; - + start[i] = cellCentres[own]; if (mesh_.isInternalFace(faceI)) { - surfaceIndex_[faceI] = surfaces_.findAnyIntersection - ( - cellCentres[own], - cellCentres[mesh_.faceNeighbour()[faceI]], - surfaceHitInfo - ); + end[i] = cellCentres[mesh_.faceNeighbour()[faceI]]; } else { - surfaceIndex_[faceI] = surfaces_.findAnyIntersection - ( - cellCentres[own], - neiCc[faceI-mesh_.nInternalFaces()], - surfaceHitInfo - ); + end[i] = neiCc[faceI-mesh_.nInternalFaces()]; } } + // Do tests in one go + labelList surfaceHit; + { + labelList surfaceLevel; + surfaces_.findHigherIntersection + ( + start, + end, + labelList(start.size(), -1), // accept any intersection + surfaceHit, + surfaceLevel + ); + } + + // Keep just surface hit + forAll(surfaceHit, i) + { + surfaceIndex_[changedFaces[i]] = surfaceHit[i]; + } + // Make sure both sides have same information. This should be // case in general since same vectors but just to make sure. syncTools::syncFaceList(mesh_, surfaceIndex_, maxEqOp<label>(), false); @@ -305,67 +232,72 @@ void Foam::meshRefinement::checkData() } // Check meshRefinement { - for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++) - { - label own = mesh_.faceOwner()[faceI]; - label nei = mesh_.faceNeighbour()[faceI]; - const point& ownCc = mesh_.cellCentres()[own]; - const point& neiCc = mesh_.cellCentres()[nei]; - - pointIndexHit surfaceHitInfo; - label surfI = surfaces_.findAnyIntersection - ( - ownCc, - neiCc, - surfaceHitInfo - ); - - if (surfI != surfaceIndex_[faceI]) - { - WarningIn("meshRefinement::checkData()") - << "Internal face:" << faceI - << " fc:" << mesh_.faceCentres()[faceI] - << " cached surfaceIndex_:" << surfaceIndex_[faceI] - << " current:" << surfI - << " ownCc:" << ownCc << " neiCc:" << neiCc - << endl; - } - } - // Get boundary face centre and level. Coupled aware. labelList neiLevel(mesh_.nFaces()-mesh_.nInternalFaces()); pointField neiCc(mesh_.nFaces()-mesh_.nInternalFaces()); calcNeighbourData(neiLevel, neiCc); - for - ( - label faceI = mesh_.nInternalFaces(); - faceI < mesh_.nFaces(); - faceI++ - ) + // Collect segments we want to test for + pointField start(mesh_.nFaces()); + pointField end(mesh_.nFaces()); + + forAll(start, faceI) { - label own = mesh_.faceOwner()[faceI]; - const point& ownCc = mesh_.cellCentres()[own]; + start[faceI] = mesh_.cellCentres()[mesh_.faceOwner()[faceI]]; - pointIndexHit surfaceHitInfo; - label surfI = surfaces_.findAnyIntersection + if (mesh_.isInternalFace(faceI)) + { + end[faceI] = mesh_.cellCentres()[mesh_.faceNeighbour()[faceI]]; + } + else + { + end[faceI] = neiCc[faceI-mesh_.nInternalFaces()]; + } + } + + // Do tests in one go + labelList surfaceHit; + { + labelList surfaceLevel; + surfaces_.findHigherIntersection ( - ownCc, - neiCc[faceI-mesh_.nInternalFaces()], - surfaceHitInfo + start, + end, + labelList(start.size(), -1), // accept any intersection + surfaceHit, + surfaceLevel ); + } - if (surfI != surfaceIndex_[faceI]) + // Check + forAll(surfaceHit, faceI) + { + if (surfaceHit[faceI] != surfaceIndex_[faceI]) { - WarningIn("meshRefinement::checkData()") - << "Boundary face:" << faceI - << " patch:" << mesh_.boundaryMesh().whichPatch(faceI) - << " fc:" << mesh_.faceCentres()[faceI] - << " cached surfaceIndex_:" << surfaceIndex_[faceI] - << " current:" << surfI - << " ownCc:" << ownCc - << " neiCc:" << neiCc[faceI-mesh_.nInternalFaces()] - << endl; + if (mesh_.isInternalFace(faceI)) + { + WarningIn("meshRefinement::checkData()") + << "Internal face:" << faceI + << " fc:" << mesh_.faceCentres()[faceI] + << " cached surfaceIndex_:" << surfaceIndex_[faceI] + << " current:" << surfaceHit[faceI] + << " ownCc:" + << mesh_.cellCentres()[mesh_.faceOwner()[faceI]] + << " neiCc:" + << mesh_.cellCentres()[mesh_.faceNeighbour()[faceI]] + << endl; + } + else + { + WarningIn("meshRefinement::checkData()") + << "Boundary face:" << faceI + << " fc:" << mesh_.faceCentres()[faceI] + << " cached surfaceIndex_:" << surfaceIndex_[faceI] + << " current:" << surfaceHit[faceI] + << " ownCc:" + << mesh_.cellCentres()[mesh_.faceOwner()[faceI]] + << endl; + } } } } @@ -492,283 +424,6 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::doRemoveCells } -// Get which are inside any closed surface. Note that all closed surfaces -// will have already been oriented to have keepPoint outside. -Foam::labelList Foam::meshRefinement::getInsideCells -( - const word& postfix -) const -{ - const pointField& points = mesh_.points(); - - // This test can be done in various ways. The ultimate is the intersection - // of any edge of the mesh with any surface and intersection of any edge - // of any surface of the mesh with any mesh face. - // For now: - // - none of the edges of a cell intersects any surface - // - any point of the cell is inside. - - - // Is point inside any closed surface? - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - PackedList<1> pointIsInside; - label nPointInside = surfaces_.markInsidePoints - ( - points, - pointIsInside - ); - - if (debug) - { - Pout<< "getInsideCells : Points internal to closed surfaces :" - << " local:" << nPointInside - << " global:" << returnReduce(nPointInside, sumOp<label>()) - << endl; - } - - - // Find cells with all points inside closed surface - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - PackedList<1> cellIsInside(mesh_.nCells(), 1u); - label nCellInside = mesh_.nCells(); - - // Unmark cells with any point outside - forAll(points, pointI) - { - if (pointIsInside.get(pointI) == 0u) - { - // Outside point. Unmark cells. - const labelList& pCells = mesh_.pointCells()[pointI]; - - forAll(pCells, i) - { - label cellI = pCells[i]; - - if (cellIsInside.get(cellI) == 1u) - { - cellIsInside.set(cellI, 0u); - nCellInside--; - } - } - } - } - - label totNCellInside = nCellInside; - reduce(totNCellInside, sumOp<label>()); - if (debug) - { - Pout<< "getInsideCells : Cells using inside points only :" - << " local:" << nCellInside << " global:" << totNCellInside - << endl; - } - - // Filter any cells with cc-cc edge intersection - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - const cellList& cells = mesh_.cells(); - - cellSet insidePoints(mesh_, "insidePoints_"+postfix, mesh_.nCells()/100); - cellSet insidePointsButCut - ( - mesh_, - "insidePointsButCut_"+postfix, - mesh_.nCells()/100 - ); - - forAll(cells, cellI) - { - if (cellIsInside.get(cellI) == 1u) - { - insidePoints.insert(cellI); - - const cell& cFaces = cells[cellI]; - - forAll(cFaces, i) - { - if (surfaceIndex_[cFaces[i]] != -1) - { - cellIsInside.set(cellI, 0u); - nCellInside--; - - insidePointsButCut.insert(cellI); - - break; - } - } - } - } - - if (debug) - { - Pout<< "getInsideCells : cells with all points inside : " - << insidePoints.objectPath() << endl; - insidePoints.write(); - Pout<< "getInsideCells : cells with all points inside" - << " but intersecting (cc) surface : " - << insidePointsButCut.objectPath() << endl; - insidePointsButCut.write(); - } - - totNCellInside = nCellInside; - reduce(totNCellInside, sumOp<label>()); - if (debug) - { - Pout<< "getInsideCells : After filtering cc-cc intersections :" - << " local:" << nCellInside << " global:" << totNCellInside - << endl; - } - - - // Filter cells with any normal edge intersection - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - cellSet insidePointsButEdge - ( - mesh_, - "insidePointsButEdge_"+postfix, - mesh_.nCells()/100 - ); - - const labelListList& edgeCells = mesh_.edgeCells(); - - forAll(edgeCells, edgeI) - { - const labelList& eCells = edgeCells[edgeI]; - - // Does edge use any inside cells? Prefilter since edge intersection - // test expensive. - bool edgeHasInsideCells = false; - - forAll(eCells, i) - { - if (cellIsInside.get(eCells[i]) == 1u) - { - edgeHasInsideCells = true; - break; - } - } - - if (edgeHasInsideCells) - { - const edge& e = mesh_.edges()[edgeI]; - - // Find any pierces of surface by mesh edge. - pointIndexHit hit; - label surfI = surfaces().findHigherIntersection - ( - points[e[0]], - points[e[1]], - -1, // minimum level. - hit - ); - - if (surfI != -1) - { - // This edge intersects some surface. Unmark all cells - // using this edge. - - forAll(eCells, i) - { - if (cellIsInside.get(eCells[i]) == 1u) - { - cellIsInside.set(eCells[i], 0u); - nCellInside--; - - insidePointsButEdge.insert(eCells[i]); - } - } - } - } - } - - if (debug) - { - Pout<< "getInsideCells : cells with all points inside" - << " but intersecting (edges) surface : " - << insidePointsButEdge.objectPath() << endl; - insidePointsButEdge.write(); - } - - totNCellInside = nCellInside; - reduce(totNCellInside, sumOp<label>()); - if (debug) - { - Pout<< "getInsideCells : After filtering edge interesections :" - << " local:" << nCellInside << " global:" << totNCellInside - << endl; - } - - - // Collect cells - // ~~~~~~~~~~~~~ - - DynamicList<label> cellsToRemove(nCellInside); - - forAll(cellIsInside, cellI) - { - if (cellIsInside.get(cellI) == 1u) - { - cellsToRemove.append(cellI); - } - } - return cellsToRemove.shrink(); -} - - -// Do all to remove inside cells -Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::removeInsideCells -( - const string& msg, - const label exposedPatchI -) -{ - labelList insideCells - ( - getInsideCells - ( - string::validate<word>(msg) - ) - ); - - Info<< "Removing inside cells : " - << returnReduce(insideCells.size(), sumOp<label>()) - << '.' << endl; - - removeCells cellRemover(mesh_); - - labelList exposedFaces(cellRemover.getExposedFaces(insideCells)); - - // Debug check - forAll(exposedFaces, i) - { - label faceI = exposedFaces[i]; - - if (surfaceIndex_[faceI] != -1) - { - FatalErrorIn - ( - "removeInsideCells" - "(const label, const string&, const label)" - ) << "Face:" << faceI - << " fc:" << mesh_.faceCentres()[faceI] - << " is actually cutting the surface and should never have been" - << " included in the cells to remove." - << abort(FatalError); - } - } - - return doRemoveCells - ( - insideCells, - exposedFaces, - labelList(exposedFaces.size(), exposedPatchI), - cellRemover - ); -} - - // Determine for multi-processor regions the lowest numbered cell on the lowest // numbered processor. void Foam::meshRefinement::getRegionMaster @@ -835,12 +490,14 @@ Foam::meshRefinement::meshRefinement ( fvMesh& mesh, const scalar tol, - const refinementSurfaces& surfaces + const refinementSurfaces& surfaces, + const shellSurfaces& shells ) : mesh_(mesh), tol_(tol), surfaces_(surfaces), + shells_(shells), meshCutter_ ( mesh, @@ -926,109 +583,6 @@ Foam::label Foam::meshRefinement::countHits() const } -//// Determine distribution to keep baffles together -//Foam::labelList Foam::meshRefinement::decomposePreserveBaffles -//( -// decompositionMethod& decomposer -//) const -//{ -// // Find duplicate faces -// labelList duplicateFace -// ( -// localPointRegion::findDuplicateFaces -// ( -// mesh_, -// identity(mesh_.nFaces()-mesh_.nInternalFaces()) -// + mesh_.nInternalFaces() -// ) -// ); -// -// -// // Agglomerate cells on both sides of duplicate face pair -// -// const pointField& cellCentres = mesh_.cellCentres(); -// const labelList& faceOwner = mesh_.faceOwner(); -// -// labelList toAgglom(mesh_.nCells(), -1); -// pointField agglomCellCentres(mesh_.nCells()); -// labelList nAgglomCellCentres(mesh_.nCells(), 0); -// -// label agglomI = 0; -// -// // Do all baffle cells -// forAll(duplicateFace, i) -// { -// if (duplicateFace[i] != -1) -// { -// label own = faceOwner[i+mesh_.nInternalFaces()]; -// label otherOwn = -// faceOwner[duplicateFace[i]+mesh_.nInternalFaces()]; -// -// if (toAgglom[own] == -1 && toAgglom[otherOwn] == -1) -// { -// // Allocate new agglomeration -// agglomCellCentres[agglomI] = -// cellCentres[own] -// + cellCentres[otherOwn]; -// nAgglomCellCentres[agglomI] = 2; -// toAgglom[own] = agglomI; -// toAgglom[otherOwn] = agglomI; -// agglomI++; -// } -// else if (toAgglom[own] != -1) -// { -// // Owner already part of agglomeration. Add otherOwn to it. -// label destAgglom = toAgglom[own]; -// agglomCellCentres[destAgglom] += cellCentres[otherOwn]; -// nAgglomCellCentres[destAgglom]++; -// toAgglom[otherOwn] = destAgglom; -// } -// else if (toAgglom[otherOwn] != -1) -// { -// // otherOwn already part of agglomeration. Add own to it. -// label destAgglom = toAgglom[otherOwn]; -// agglomCellCentres[destAgglom] += cellCentres[own]; -// nAgglomCellCentres[destAgglom]++; -// toAgglom[own] = destAgglom; -// } -// } -// } -// -// // Do all other cells -// forAll(toAgglom, cellI) -// { -// if (toAgglom[cellI] == -1) -// { -// agglomCellCentres[agglomI] = cellCentres[cellI]; -// nAgglomCellCentres[agglomI] = 1; -// toAgglom[cellI] = agglomI; -// agglomI++; -// } -// } -// -// // Average -// agglomCellCentres.setSize(agglomI); -// -// forAll(agglomCellCentres, i) -// { -// agglomCellCentres[i] /= nAgglomCellCentres[i]; -// } -// -// // Decompose based on agglomerated cell centres -// labelList agglomDistribution(decomposer.decompose(agglomCellCentres)); -// -// // Rework back into decomposition for original mesh_ -// labelList distribution(mesh_.nCells()); -// -// forAll(toAgglom, cellI) -// { -// distribution[cellI] = agglomDistribution[toAgglom[cellI]]; -// } -// -// return distribution; -//} - - // Determine distribution to move connected regions onto one processor. Foam::labelList Foam::meshRefinement::decomposeCombineRegions ( @@ -1213,9 +767,8 @@ Foam::labelList Foam::meshRefinement::intersectedPoints forAll(f, fp) { - if (isBoundaryPoint.get(f[fp]) == 0u) + if (isBoundaryPoint.set(f[fp], 1u)) { - isBoundaryPoint.set(f[fp], 1u); nBoundaryPoints++; } } @@ -1239,9 +792,7 @@ Foam::labelList Foam::meshRefinement::intersectedPoints // // forAll(f, fp) // { - // if (isBoundaryPoint.get(f[fp]) == 0u) - // { - // isBoundaryPoint.set(f[fp], 1u); + // if (isBoundaryPoint.set(f[fp], 1u)) // nBoundaryPoints++; // } // } @@ -1910,53 +1461,56 @@ void Foam::meshRefinement::dumpIntersections(const fileName& prefix) const << " Writing cellcentre-cellcentre intersections to file " << str.name() << endl; - // Internal faces - for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++) - { - if (surfaceIndex_[faceI] != -1) - { - const point& ownCc = cellCentres[mesh_.faceOwner()[faceI]]; - const point& neiCc = cellCentres[mesh_.faceNeighbour()[faceI]]; - // Re-intersect to get position - pointIndexHit surfaceHitInfo; - surfaces_.findAnyIntersection(ownCc, neiCc, surfaceHitInfo); - - meshTools::writeOBJ(str, ownCc); - vertI++; - meshTools::writeOBJ(str, surfaceHitInfo.hitPoint()); - vertI++; - meshTools::writeOBJ(str, neiCc); - vertI++; - str << "l " << vertI-2 << ' ' << vertI-1 << nl - << "l " << vertI-1 << ' ' << vertI << nl; - } - } - - // Boundary faces + // Redo all intersections + // ~~~~~~~~~~~~~~~~~~~~~~ // Get boundary face centre and level. Coupled aware. labelList neiLevel(mesh_.nFaces()-mesh_.nInternalFaces()); pointField neiCc(mesh_.nFaces()-mesh_.nInternalFaces()); calcNeighbourData(neiLevel, neiCc); - forAll(neiCc, i) + labelList intersectionFaces(intersectedFaces()); + + // Collect segments we want to test for + pointField start(intersectionFaces.size()); + pointField end(intersectionFaces.size()); + + forAll(intersectionFaces, i) { - label faceI = i + mesh_.nInternalFaces(); + label faceI = intersectionFaces[i]; + start[i] = cellCentres[mesh_.faceOwner()[faceI]]; - if (surfaceIndex_[faceI] != -1) + if (mesh_.isInternalFace(faceI)) + { + end[i] = cellCentres[mesh_.faceNeighbour()[faceI]]; + } + else { - const point& ownCc = cellCentres[mesh_.faceOwner()[faceI]]; + end[i] = neiCc[faceI-mesh_.nInternalFaces()]; + } + } - // Re-intersect to get position - pointIndexHit surfaceHitInfo; - surfaces_.findAnyIntersection(ownCc, neiCc[i], surfaceHitInfo); + // Do tests in one go + labelList surfaceHit; + List<pointIndexHit> surfaceHitInfo; + surfaces_.findAnyIntersection + ( + start, + end, + surfaceHit, + surfaceHitInfo + ); - meshTools::writeOBJ(str, ownCc); + forAll(intersectionFaces, i) + { + if (surfaceHit[i] != -1) + { + meshTools::writeOBJ(str, start[i]); vertI++; - meshTools::writeOBJ(str, surfaceHitInfo.hitPoint()); + meshTools::writeOBJ(str, surfaceHitInfo[i].hitPoint()); vertI++; - meshTools::writeOBJ(str, neiCc[i]); + meshTools::writeOBJ(str, end[i]); vertI++; str << "l " << vertI-2 << ' ' << vertI-1 << nl << "l " << vertI-1 << ' ' << vertI << nl; @@ -1996,13 +1550,4 @@ void Foam::meshRefinement::write } -// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // - - -// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * // - - -// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * // - - // ************************************************************************* // diff --git a/src/autoMesh/autoHexMesh/meshRefinement/meshRefinement.H b/src/autoMesh/autoHexMesh/meshRefinement/meshRefinement.H index 78fed5349306a3f57daf6a6fe10d17f4c84cbc30..e8e633bfef02cd7acbfcf7bcaa4418cb5d5bcd20 100644 --- a/src/autoMesh/autoHexMesh/meshRefinement/meshRefinement.H +++ b/src/autoMesh/autoHexMesh/meshRefinement/meshRefinement.H @@ -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; @@ -107,8 +108,12 @@ private: //- tolerance used for sorting coordinates (used in 'less' routine) const scalar tol_; + //- 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, @@ -381,7 +384,8 @@ public: ( fvMesh& mesh, const scalar tol, - const refinementSurfaces& + const refinementSurfaces&, + const shellSurfaces& ); @@ -482,22 +486,18 @@ public: const labelList& adaptPatchIDs ); + // 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, diff --git a/src/autoMesh/autoHexMesh/meshRefinement/meshRefinementBaffles.C b/src/autoMesh/autoHexMesh/meshRefinement/meshRefinementBaffles.C index 17eaaeaa275cce90b0802adcef1712f934a4c154..c9c2d14c1306b16c67eee7cdc9e3436c44f92b06 100644 --- a/src/autoMesh/autoHexMesh/meshRefinement/meshRefinementBaffles.C +++ b/src/autoMesh/autoHexMesh/meshRefinement/meshRefinementBaffles.C @@ -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]; + 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; - surfaces_.findNearestIntersection - ( - surfacesToBaffle, - cellCentres[own], - end, - surface1, - hit1, - surface2, - hit2 - ); + // Do test for intersections + // ~~~~~~~~~~~~~~~~~~~~~~~~~ + labelList surface1; + List<pointIndexHit> hit1; + labelList region1; + labelList surface2; + List<pointIndexHit> hit2; + labelList region2; + surfaces_.findNearestIntersection + ( + surfacesToBaffle, + start, + end, - if (hit1.hit() && hit2.hit()) - { - if (str.valid()) - { - meshTools::writeOBJ(str(), cellCentres[own]); - vertI++; - meshTools::writeOBJ(str(), hit1.rawPoint()); - vertI++; - meshTools::writeOBJ(str(), hit2.rawPoint()); - vertI++; - meshTools::writeOBJ(str(), end); - vertI++; - str()<< "l " << vertI-3 << ' ' << vertI-2 << nl; - str()<< "l " << vertI-2 << ' ' << vertI-1 << nl; - str()<< "l " << vertI-1 << ' ' << vertI << nl; - } + surface1, + hit1, + region1, + surface2, + hit2, + region2 + ); - // Pick up the patches - ownPatch[faceI] = globalToPatch - [ - surfaces_.triangleRegion(surface1, hit1.index()) - ]; - neiPatch[faceI] = globalToPatch - [ - surfaces_.triangleRegion(surface2, hit2.index()) - ]; + forAll(testFaces, i) + { + label faceI = testFaces[i]; - if (ownPatch[faceI] == -1 || neiPatch[faceI] == -1) - { - FatalErrorIn("getBafflePatches()") << abort(FatalError); - } + if (hit1[i].hit() && hit2[i].hit()) + { + if (str.valid()) + { + meshTools::writeOBJ(str(), start[i]); + vertI++; + meshTools::writeOBJ(str(), hit1[i].rawPoint()); + vertI++; + meshTools::writeOBJ(str(), hit2[i].rawPoint()); + vertI++; + 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_.globalRegion(surface1[i], region1[i]) + ]; + neiPatch[faceI] = globalToPatch + [ + surfaces_.globalRegion(surface2[i], region2[i]) + ]; + + if (ownPatch[faceI] == -1 || neiPatch[faceI] == -1) + { + 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,55 +1293,65 @@ void Foam::meshRefinement::findCellZoneGeometric { label nei = faceNeighbour[faceI]; const point& neiCc = cellCentres[nei]; - + // Perturbed cc const vector d = 1E-4*(neiCc - ownCc); + candidatePoints[nCandidates++] = ownCc-d; + candidatePoints[nCandidates++] = neiCc+d; + } + else + { + const point& neiFc = mesh_.faceCentres()[faceI]; + // Perturbed cc + const vector d = 1E-4*(neiFc - ownCc); + candidatePoints[nCandidates++] = ownCc-d; + } + } + } - // Test perturbed owner - { - label ownSurfI = surfaces_.insideZone - ( - closedNamedSurfaces, - ownCc-d - ); - if (ownSurfI != -1) - { - cellToZone[own] = surfaceToCellZone[ownSurfI]; - } + // 2. Test points for inside + + surfaces_.findInside + ( + closedNamedSurfaces, + candidatePoints, + insideSurfaces + ); + + + // 3. Update zone information + + nCandidates = 0; + forAll(namedSurfaceIndex, faceI) + { + label surfI = namedSurfaceIndex[faceI]; + + if (surfI != -1) + { + label own = faceOwner[faceI]; + + if (mesh_.isInternalFace(faceI)) + { + label ownSurfI = insideSurfaces[nCandidates++]; + if (ownSurfI != -1) + { + cellToZone[own] = surfaceToCellZone[ownSurfI]; } - // Test perturbed neighbour + label neiSurfI = insideSurfaces[nCandidates++]; + if (neiSurfI != -1) { - label neiSurfI = surfaces_.insideZone - ( - closedNamedSurfaces, - neiCc+d - ); + label nei = faceNeighbour[faceI]; - if (neiSurfI != -1) - { - cellToZone[nei] = surfaceToCellZone[neiSurfI]; - } + cellToZone[nei] = surfaceToCellZone[neiSurfI]; } } else { - const point& neiCc = mesh_.faceCentres()[faceI]; - - const vector d = 1E-4*(neiCc - ownCc); - - // Test perturbed owner + label ownSurfI = insideSurfaces[nCandidates++]; + if (ownSurfI != -1) { - label ownSurfI = surfaces_.insideZone - ( - closedNamedSurfaces, - ownCc-d - ); - - if (ownSurfI != -1) - { - cellToZone[own] = surfaceToCellZone[ownSurfI]; - } + cellToZone[own] = surfaceToCellZone[ownSurfI]; } } } @@ -2291,7 +2358,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 +2396,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 +2454,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 +2510,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) + // do zonify baffle faces anyway (they are normal boundary faces). + + // Collect candidate faces + // ~~~~~~~~~~~~~~~~~~~~~~~ + + labelList testFaces(intersectedFaces()); + + // Collect segments + // ~~~~~~~~~~~~~~~~ + + pointField start(testFaces.size()); + pointField end(testFaces.size()); + + forAll(testFaces, i) { - label surfI = surfaceIndex_[faceI]; + label faceI = testFaces[i]; - if - ( - surfI != -1 - && ( - mesh_.isInternalFace(faceI) - || patches[patches.whichPatch(faceI)].coupled() - ) - ) + label own = mesh_.faceOwner()[faceI]; + + if (mesh_.isInternalFace(faceI)) { - if (isNamedSurface[surfI]) - { - namedSurfaceIndex[faceI] = surfI; - nSurfFaces[surfI]++; - } - else - { - // Test more accurately for whether intersection is at - // zoneable surface + 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; - if (mesh_.isInternalFace(faceI)) - { - surfaces_.findNearestIntersection - ( - namedSurfaces, - cellCentres[faceOwner[faceI]], - cellCentres[faceNeighbour[faceI]], - - surface1, - hit1, - surface2, - hit2 - ); - } - else - { - surfaces_.findNearestIntersection - ( - namedSurfaces, - cellCentres[faceOwner[faceI]], - neiCc[faceI-mesh_.nInternalFaces()], - - surface1, - hit1, - surface2, - hit2 - ); - } + // Do test for intersections + // ~~~~~~~~~~~~~~~~~~~~~~~~~ + // Note that we intersect all intersected faces again. Could reuse + // the information already in surfaceIndex_. - if (hit1.hit()) - { - // If both hit should probably choose nearest. For - // later. - namedSurfaceIndex[faceI] = surface1; - nSurfFaces[surface1]++; - } - else if (hit2.hit()) - { - namedSurfaceIndex[faceI] = surface2; - nSurfFaces[surface2]++; - } - } + labelList surface1; + labelList surface2; + { + List<pointIndexHit> hit1; + labelList region1; + List<pointIndexHit> hit2; + labelList region2; + surfaces_.findNearestIntersection + ( + namedSurfaces, + start, + end, + + surface1, + hit1, + region1, + surface2, + hit2, + region2 + ); + } + + forAll(testFaces, i) + { + label faceI = testFaces[i]; + + if (surface1[i] != -1) + { + // If both hit should probably choose nearest. For later. + namedSurfaceIndex[faceI] = surface1[i]; + nSurfFaces[surface1[i]]++; + } + else if (surface2[i] != -1) + { + namedSurfaceIndex[faceI] = surface2[i]; + nSurfFaces[surface2[i]]++; } } + // surfaceIndex migh have different surfaces on both sides if // there happen to be a (obviously thin) surface with different // regions between the cell centres. If one is on a named surface @@ -2534,7 +2605,7 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::zonify forAll(nSurfFaces, surfI) { Pout<< "Surface:" - << surfaces_[surfI].searchableSurface::name() + << surfaces_.names()[surfI] << " nZoneFaces:" << nSurfFaces[surfI] << nl; } Pout<< endl; @@ -2591,7 +2662,7 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::zonify ( mesh_.faces()[faceI], // modified face faceI, // label of face - faceOwner[faceI], // owner + faceOwner[faceI], // owner -1, // neighbour false, // face flip patchI, // patch for face @@ -2609,20 +2680,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 +2763,4 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::zonify } -// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // - - -// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * // - - -// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * // - - // ************************************************************************* // diff --git a/src/autoMesh/autoHexMesh/meshRefinement/meshRefinementMerge.C b/src/autoMesh/autoHexMesh/meshRefinement/meshRefinementMerge.C index 14c3304979b41030960405291825a04bdcfe79c4..d8ddb69bcece7841e39e71751245cc21efd5d5ee 100644 --- a/src/autoMesh/autoHexMesh/meshRefinement/meshRefinementMerge.C +++ b/src/autoMesh/autoHexMesh/meshRefinement/meshRefinementMerge.C @@ -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 * * * * * * * * * * * * * // - - // ************************************************************************* // diff --git a/src/autoMesh/autoHexMesh/meshRefinement/meshRefinementRefine.C b/src/autoMesh/autoHexMesh/meshRefinement/meshRefinementRefine.C index bc65921bf5aa74179e90972f61eba7c71b831228..9a5f6cf63379293e884c8c74fa59fa48b981c203 100644 --- a/src/autoMesh/autoHexMesh/meshRefinement/meshRefinementRefine.C +++ b/src/autoMesh/autoHexMesh/meshRefinement/meshRefinementRefine.C @@ -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,94 +460,113 @@ 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) + { + if (refineCell[cellI] == -1) + { + if (maxLevel[testI] > testLevels[testI]) { - // 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 = + bool reachedLimit = !markForRefine ( - shellRefineInside[shellI] - ? searchableSurface::INSIDE - : searchableSurface::OUTSIDE + maxLevel[testI], // mark with any positive value + nAllowRefine, + refineCell[cellI], + nRefine ); - if (t == refSide && cellLevel[cellI] < shellLevels[shellI]) + if (reachedLimit) { - // Cell is inside shell with higher refinement level. Mark - // for refinement. - - reachedLimit = !markForRefine - ( - labelMax, - nAllowRefine, - refineCell[cellI], - nRefine - ); - - if (reachedLimit) - { - if (debug) - { - Pout<< "Stopped refining internal cells" - << " since reaching my cell limit of " - << mesh_.nCells()+7*nRefine << endl; - } - break; - } - else + if (debug) { - // Cell successfully marked for refinement - nCellsPerShell[shellI]++; + Pout<< "Stopped refining internal cells" + << " since reaching my cell limit of " + << mesh_.nCells()+7*nRefine << endl; } + break; } } - - if (reachedLimit) - { - break; - } + testI++; } } - Pstream::listCombineGather(nCellsPerShell, plusEqOp<label>()); - Pstream::listCombineScatter(nCellsPerShell); - - Info<< "Marked for refinement per shell :" << endl; - forAll(nCellsPerShell, shellI) + if + ( + returnReduce(nRefine, sumOp<label>()) + > returnReduce(nAllowRefine, sumOp<label>()) + ) { - 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,156 +586,149 @@ 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++) + // Collect candidate faces + // ~~~~~~~~~~~~~~~~~~~~~~~ + + labelList testFaces(getRefineCandidateFaces(refineCell)); + + // Collect segments + // ~~~~~~~~~~~~~~~~ + + pointField start(testFaces.size()); + pointField end(testFaces.size()); + labelList minLevel(testFaces.size()); + + forAll(testFaces, i) { - if (surfaceIndex_[faceI] != -1) + label faceI = testFaces[i]; + + label own = mesh_.faceOwner()[faceI]; + + if (mesh_.isInternalFace(faceI)) { - label own = mesh_.faceOwner()[faceI]; + label nei = mesh_.faceNeighbour()[faceI]; - if (mesh_.isInternalFace(faceI)) - { - label nei = mesh_.faceNeighbour()[faceI]; + start[i] = cellCentres[own]; + end[i] = cellCentres[nei]; + minLevel[i] = min(cellLevel[own], cellLevel[nei]); + } + else + { + label bFaceI = faceI - mesh_.nInternalFaces(); - // Test if not both sides already marked for refinement. - if (refineCell[own] == -1 || refineCell[nei] == -1) - { - pointIndexHit hit; - label surfI = surfaces_.findHigherIntersection - ( - cellCentres[own], - cellCentres[nei], - min(cellLevel[own], cellLevel[nei]), - hit - ); + start[i] = cellCentres[own]; + end[i] = neiCc[bFaceI]; + minLevel[i] = min(cellLevel[own], neiLevel[bFaceI]); + } + } - 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? - - label surfaceMinLevel = - surfaces_.minLevelField(surfI)[hit.index()]; - - if (surfaceMinLevel > cellLevel[own]) - { - // Owner needs refining - if - ( - !markForRefine - ( - surfI, - nAllowRefine, - refineCell[own], - nRefine - ) - ) - { - break; - } - } - if (surfaceMinLevel > cellLevel[nei]) - { - // Neighbour needs refining - if - ( - !markForRefine - ( - surfI, - nAllowRefine, - refineCell[nei], - nRefine - ) - ) - { - break; - } - } - } - } - } - else if (refineCell[own] == -1) - { - // boundary face with unmarked owner + // Do test for higher intersections + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + labelList surfaceHit; + labelList surfaceMinLevel; + surfaces_.findHigherIntersection + ( + start, + end, + minLevel, + + surfaceHit, + surfaceMinLevel + ); + + + // Mark cells for refinement + // ~~~~~~~~~~~~~~~~~~~~~~~~~ + + forAll(testFaces, i) + { + label faceI = testFaces[i]; + + label surfI = surfaceHit[i]; - label bFaceI = faceI - mesh_.nInternalFaces(); + if (surfI != -1) + { + // Found intersection with surface with higher wanted + // 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 own = mesh_.faceOwner()[faceI]; - pointIndexHit hit; - label surfI = surfaces_.findHigherIntersection + if (surfaceMinLevel[i] > cellLevel[own]) + { + // Owner needs refining + if ( - cellCentres[own], - neiCc[bFaceI], - min(cellLevel[own], neiLevel[bFaceI]), - hit - ); + !markForRefine + ( + surfI, + nAllowRefine, + refineCell[own], + nRefine + ) + ) + { + break; + } + } - if (surfI != -1) + if (mesh_.isInternalFace(faceI)) + { + label nei = mesh_.faceNeighbour()[faceI]; + if (surfaceMinLevel[i] > cellLevel[nei]) { - // Make sure it is my side that wants refinement. - label surfaceMinLevel = - surfaces_.minLevelField(surfI)[hit.index()]; - - if (surfaceMinLevel > cellLevel[own]) - { - if + // Neighbour needs refining + if + ( + !markForRefine ( - !markForRefine - ( - surfI, - nAllowRefine, - refineCell[own], - nRefine - ) + surfI, + nAllowRefine, + refineCell[nei], + nRefine ) - { - break; - } + ) + { + break; } } } } } - if (faceI < surfaceIndex_.size()) + if + ( + returnReduce(nRefine, sumOp<label>()) + > returnReduce(nAllowRefine, sumOp<label>()) + ) { - 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) - { - // First visit of cell. Store - maxCellSurfI = newSurfI; - maxCellTriI = newTriI; - } - else + // Test if surface applicable + if (surfaceLevel > cellLevel[cellI]) { - // 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) + if (cellMaxLevel == -1) { - maxCellSurfI = newSurfI; - maxCellTriI = newTriI; - maxLevel = surfaces_.maxLevel()[newRegion]; + // First visit of cell. Store + cellMaxLevel = surfaceLevel; + cellMaxNormal = surfaceNormal; } - - - // Check if cell is candidate for refinement - if (cellLevel[cellI] < maxLevel) + else { - // 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) - - // 2. Any cell on only one surface with a neighbour on a different surface - // gets refined (if its current level etc.) + // 1. local test: any cell on more than one surface gets refined + // (if its current level is < max of the surface max level) + // 2. 'global' test: any cell on only one surface with a neighbour + // on a different surface gets refined (if its current level etc.) - // 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 candidate faces (i.e. intersecting any surface and + // owner/neighbour not yet refined. + labelList testFaces(getRefineCandidateFaces(refineCell)); - // 1. + // Collect segments + pointField start(testFaces.size()); + pointField end(testFaces.size()); + labelList minLevel(testFaces.size()); - forAll(surfaceIndex_, faceI) + forAll(testFaces, i) { - if (surfaceIndex_[faceI] != -1) + label faceI = testFaces[i]; + + label own = mesh_.faceOwner()[faceI]; + + if (mesh_.isInternalFace(faceI)) { - label own = mesh_.faceOwner()[faceI]; + label nei = mesh_.faceNeighbour()[faceI]; - // There is an intersection. Do more accurate test to get all - // intersections - labelList surfaceIndices; - List<pointIndexHit> hits; + start[i] = cellCentres[own]; + end[i] = cellCentres[nei]; + minLevel[i] = min(cellLevel[own], cellLevel[nei]); + } + else + { + label bFaceI = faceI - mesh_.nInternalFaces(); - if (mesh_.isInternalFace(faceI)) - { - label nei = mesh_.faceNeighbour()[faceI]; + start[i] = cellCentres[own]; + end[i] = neiCc[bFaceI]; + minLevel[i] = min(cellLevel[own], neiLevel[bFaceI]); + } + } - surfaces_.findAllIntersections - ( - cellCentres[own], - cellCentres[nei], - surfaceIndices, - hits - ); - } - else - { - label bFaceI = faceI - mesh_.nInternalFaces(); + // 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()); - surfaces_.findAllIntersections - ( - cellCentres[own], - neiCc[bFaceI], - surfaceIndices, - hits - ); - } + { + // 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(); - // See if intersection adds any new information to the owner or - // neighbour cell. + // Extract per cell information on the surface with the highest max + forAll(testFaces, i) + { + label faceI = testFaces[i]; + label own = mesh_.faceOwner()[faceI]; - forAll(surfaceIndices, i) - { - label surfI = surfaceIndices[i]; - label triI = hits[i].index(); + 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]; + 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); - - // 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]; + labelList neiBndMaxLevel(mesh_.nFaces()-mesh_.nInternalFaces()); + vectorField neiBndMaxNormal(mesh_.nFaces()-mesh_.nInternalFaces()); - if (cellMaxSurface[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++) { + label bFaceI = faceI-mesh_.nInternalFaces(); 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]; - } + neiBndMaxLevel[bFaceI] = cellMaxLevel[own]; + neiBndMaxNormal[bFaceI] = cellMaxNormal[own]; } + syncTools::swapBoundaryFaceList(mesh_, neiBndMaxLevel, false); + syncTools::swapBoundaryFaceList(mesh_, neiBndMaxNormal, false); - syncTools::swapFaceList(mesh_, neiRegion, false); - syncTools::swapFaceList(mesh_, neiNormal, false); + // Loop over all faces. Could only be checkFaces.. except if they're coupled - for (label faceI = 0; faceI < mesh_.nFaces(); faceI++) + // Internal faces + for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++) { - if (ownRegion[faceI] != -1 && neiRegion[faceI] != -1) + label own = mesh_.faceOwner()[faceI]; + label nei = mesh_.faceNeighbour()[faceI]; + + if (cellMaxLevel[own] != -1 && cellMaxLevel[nei] != -1) { - if - ( - (markDifferingRegions && (ownRegion[faceI] != neiRegion[faceI])) - || ((ownNormal[faceI] & neiNormal[faceI]) < curvature) - ) + // Have valid data on both sides. Check curvature. + if ((cellMaxNormal[own] & cellMaxNormal[nei]) < 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,46 +963,77 @@ Foam::label Foam::meshRefinement::markSurfaceCurvatureRefinement } break; } - } - if (mesh_.isInternalFace(faceI)) + if (cellLevel[nei] < cellMaxLevel[nei]) { - label nei = mesh_.faceNeighbour()[faceI]; - - if (cellLevel[nei] < surfaces_.maxLevel()[neiRegion[faceI]]) - { - if + if + ( + !markForRefine ( - !markForRefine - ( - globalToPatch[neiRegion[faceI]], - nAllowRefine, - - refineCell[nei], - nRefine - ) + cellMaxLevel[nei], + nAllowRefine, + refineCell[nei], + nRefine ) + ) + { + if (debug) { - if (debug) - { - Pout<< "Stopped refining since reaching my cell" - << " limit of " << mesh_.nCells()+7*nRefine - << endl; - } - break; + Pout<< "Stopped refining since reaching my cell" + << " limit of " << mesh_.nCells()+7*nRefine + << endl; } + break; } } } } } + // 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; + } + } + } + } - return returnReduce(nRefine-oldNRefine, sumOp<label>()); - label totNRefined = returnReduce(totNRefined, sumOp<label>()); + if + ( + returnReduce(nRefine, sumOp<label>()) + > returnReduce(nAllowRefine, sumOp<label>()) + ) + { + Info<< "Reached refinement limit." << endl; + } - return totNRefined; + return returnReduce(nRefine-oldNRefine, sumOp<label>()); } @@ -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 // ~~~~~~~~~~~~~~ diff --git a/src/autoMesh/autoHexMesh/refinementSurfaces/refinementSurfaces.C b/src/autoMesh/autoHexMesh/refinementSurfaces/refinementSurfaces.C index 83816314a7cdc674876b41d03f47239bd831b171..ce09e597e2480c80f1583778639ff7899aac5b57 100644 --- a/src/autoMesh/autoHexMesh/refinementSurfaces/refinementSurfaces.C +++ b/src/autoMesh/autoHexMesh/refinementSurfaces/refinementSurfaces.C @@ -27,25 +27,17 @@ License #include "refinementSurfaces.H" #include "orientedSurface.H" #include "Time.H" -#include "searchableSurface.H" +#include "searchableSurfaces.H" +#include "shellSurfaces.H" +#include "triSurfaceMesh.H" +#include "labelPair.H" +#include "searchableSurfacesQueries.H" + // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // -// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // -Foam::fileNameList Foam::refinementSurfaces::extractFileNames -( - const PtrList<dictionary>& surfaceDicts -) -{ - fileNameList surfaceFileNames(surfaceDicts.size()); - - forAll(surfaceDicts, i) - { - surfaceFileNames[i] = fileName(surfaceDicts[i].lookup("file")); - } - return surfaceFileNames; -} +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // @@ -53,13 +45,13 @@ Foam::fileNameList Foam::refinementSurfaces::extractFileNames // Construct from components Foam::refinementSurfaces::refinementSurfaces ( - const IOobject& io, + const searchableSurfaces& allGeometry, const PtrList<dictionary>& surfaceDicts ) : - triSurfaceMeshes(io, extractFileNames(surfaceDicts)), + allGeometry_(allGeometry), + surfaces_(surfaceDicts.size()), names_(surfaceDicts.size()), - closed_(surfaceDicts.size(), true), faceZoneNames_(surfaceDicts.size()), cellZoneNames_(surfaceDicts.size()), zoneInside_(surfaceDicts.size()), @@ -67,29 +59,25 @@ Foam::refinementSurfaces::refinementSurfaces { labelList globalMinLevel(surfaceDicts.size(), 0); labelList globalMaxLevel(surfaceDicts.size(), 0); - List<HashTable<label> > regionMinLevel(surfaceDicts.size()); - List<HashTable<label> > regionMaxLevel(surfaceDicts.size()); + List<Map<label> > regionMinLevel(surfaceDicts.size()); + List<Map<label> > regionMaxLevel(surfaceDicts.size()); - labelList globalSurfLayers(surfaceDicts.size()); - List<HashTable<label> > regionSurfLayers(surfaceDicts.size()); - - wordList globalPatchType(surfaceDicts.size()); - List<HashTable<word> > regionPatchType(surfaceDicts.size()); - List<HashTable<word> > regionPatchName(surfaceDicts.size()); + //wordList globalPatchType(surfaceDicts.size()); + //List<HashTable<word> > regionPatchType(surfaceDicts.size()); + //List<HashTable<word> > regionPatchName(surfaceDicts.size()); forAll(surfaceDicts, surfI) { const dictionary& dict = surfaceDicts[surfI]; - names_[surfI] = word(dict.lookup("name")); + dict.lookup("name") >> names_[surfI]; + + surfaces_[surfI] = allGeometry_.findSurfaceID(names_[surfI]); // Global refinement level globalMinLevel[surfI] = readLabel(dict.lookup("minRefinementLevel")); globalMaxLevel[surfI] = readLabel(dict.lookup("maxRefinementLevel")); - // Global number of layers - globalSurfLayers[surfI] = readLabel(dict.lookup("surfaceLayers")); - // Global zone names per surface if (dict.found("faceZone")) { @@ -98,50 +86,62 @@ Foam::refinementSurfaces::refinementSurfaces dict.lookup("zoneInside") >> zoneInside_[surfI]; } - // Global patch name per surface - if (dict.found("patchType")) - { - dict.lookup("patchType") >> globalPatchType[surfI]; - } + //// Global patch name per surface + //if (dict.found("patchType")) + //{ + // dict.lookup("patchType") >> globalPatchType[surfI]; + //} if (dict.found("regions")) { PtrList<dictionary> regionDicts(dict.lookup("regions")); + const wordList& regionNames = + allGeometry_[surfaces_[surfI]].regions(); + forAll(regionDicts, dictI) { const dictionary& regionDict = regionDicts[dictI]; const word regionName(regionDict.lookup("name")); - label min = readLabel(regionDict.lookup("minRefinementLevel")); - label max = readLabel(regionDict.lookup("maxRefinementLevel")); - regionMinLevel[surfI].insert(regionName, min); - regionMaxLevel[surfI].insert(regionName, max); + label regionI = findIndex(regionNames, regionName); - label nLayers = readLabel(regionDict.lookup("surfaceLayers")); - regionSurfLayers[surfI].insert(regionName, nLayers); - - if (regionDict.found("patchType")) + if (regionI == -1) { - regionPatchType[surfI].insert + FatalErrorIn ( - regionName, - regionDict.lookup("patchType") - ); - regionPatchName[surfI].insert + "refinementSurfaces::refinementSurfaces" + "(const IOobject&, const PtrList<dictionary>&)" + ) << "No region called " << regionName << " on surface " + << allGeometry_[surfaces_[surfI]].name() << endl + << "Valid regions are " << regionNames + << exit(FatalError); + } + + + label min = readLabel(regionDict.lookup("minRefinementLevel")); + label max = readLabel(regionDict.lookup("maxRefinementLevel")); + + bool hasInserted = regionMinLevel[surfI].insert(regionI, min); + if (!hasInserted) + { + FatalErrorIn ( - regionName, - regionDict.lookup("patchName") - ); + "refinementSurfaces::refinementSurfaces" + "(const IOobject&, const PtrList<dictionary>&)" + ) << "Duplicate region name " << regionName + << " on surface " << names_[surfI] + << exit(FatalError); } + regionMaxLevel[surfI].insert(regionI, max); } } } - // Check for duplicate surface or region names + // Check for duplicate surface names { HashTable<label> surfaceNames(names_.size()); @@ -158,57 +158,173 @@ Foam::refinementSurfaces::refinementSurfaces << surfaceNames[names_[surfI]] << exit(FatalError); } + } + } + + // Calculate local to global region offset + label nRegions = 0; + + forAll(surfaceDicts, surfI) + { + regionOffset_[surfI] = nRegions; + + nRegions += allGeometry_[surfaces_[surfI]].regions().size(); + } + + // Rework surface specific information into information per global region + minLevel_.setSize(nRegions); + minLevel_ = 0; + maxLevel_.setSize(nRegions); + maxLevel_ = 0; + //patchName_.setSize(nRegions); + //patchType_.setSize(nRegions); + + forAll(surfaceDicts, surfI) + { + label nRegions = allGeometry_[surfaces_[surfI]].regions().size(); + + // Initialise to global (i.e. per surface) + for (label i = 0; i < nRegions; i++) + { + minLevel_[regionOffset_[surfI] + i] = globalMinLevel[surfI]; + maxLevel_[regionOffset_[surfI] + i] = globalMaxLevel[surfI]; + } - // Check for duplicate region names - const geometricSurfacePatchList& patches = - operator[](surfI).patches(); + // Overwrite with region specific information + forAllConstIter(Map<label>, regionMinLevel[surfI], iter) + { + label globalRegionI = regionOffset_[surfI] + iter.key(); - HashTable<label> regionNames(patches.size()); - forAll(patches, i) + minLevel_[globalRegionI] = iter(); + maxLevel_[globalRegionI] = regionMaxLevel[surfI][iter.key()]; + + // Check validity + if + ( + minLevel_[globalRegionI] < 0 + || maxLevel_[globalRegionI] < minLevel_[globalRegionI] + ) { - if (!regionNames.insert(patches[i].name(), i)) - { - FatalErrorIn - ( - "refinementSurfaces::refinementSurfaces" - "(const IOobject&, const PtrList<dictionary>&)" - ) << "Duplicate region name " << patches[i].name() - << " on surface " << names_[surfI] << endl - << "Previous occurrence of region at index " - << regionNames[patches[i].name()] - << exit(FatalError); - } + FatalErrorIn + ( + "refinementSurfaces::refinementSurfaces" + "(const IOobject&, const PtrList<dictionary>&)" + ) << "Illegal level or layer specification for surface " + << names_[surfI] + << " : minLevel:" << minLevel_[globalRegionI] + << " maxLevel:" << maxLevel_[globalRegionI] + << exit(FatalError); } } + + //// Optional patch names and patch types + //forAllConstIter(HashTable<word>, regionPatchName[surfI], iter) + //{ + // label regionI = findIndex(regionNames, iter.key()); + // label globalRegionI = regionOffset_[surfI] + regionI; + // + // patchName_[globalRegionI] = iter(); + // patchType_[globalRegionI] = regionPatchType[surfI][iter.key()]; + //} } +} + +Foam::refinementSurfaces::refinementSurfaces +( + const searchableSurfaces& allGeometry, + const dictionary& surfacesDict +) +: + allGeometry_(allGeometry), + surfaces_(surfacesDict.size()), + names_(surfacesDict.size()), + faceZoneNames_(surfacesDict.size()), + cellZoneNames_(surfacesDict.size()), + zoneInside_(surfacesDict.size()), + regionOffset_(surfacesDict.size()) +{ + labelList globalMinLevel(surfacesDict.size(), 0); + labelList globalMaxLevel(surfacesDict.size(), 0); + List<Map<label> > regionMinLevel(surfacesDict.size()); + List<Map<label> > regionMaxLevel(surfacesDict.size()); - // Calculate closedness - forAll(closed_, surfI) + label surfI = 0; + forAllConstIter(dictionary, surfacesDict, iter) { - const triSurface& s = operator[](surfI); + names_[surfI] = iter().keyword(); + + surfaces_[surfI] = allGeometry_.findSurfaceID(names_[surfI]); - const labelListList& edgeFaces = s.edgeFaces(); + if (surfaces_[surfI] == -1) + { + FatalErrorIn + ( + "refinementSurfaces::refinementSurfaces" + "(const searchableSurfaces&, const dictionary>&" + ) << "No surface called " << iter().keyword() << endl + << "Valid surfaces are " << allGeometry_.names() + << exit(FatalError); + } + const dictionary& dict = surfacesDict.subDict(iter().keyword()); + + const labelPair refLevel(dict.lookup("level")); + globalMinLevel[surfI] = refLevel[0]; + globalMaxLevel[surfI] = refLevel[1]; + + // Global zone names per surface + if (dict.found("faceZone")) + { + dict.lookup("faceZone") >> faceZoneNames_[surfI]; + dict.lookup("cellZone") >> cellZoneNames_[surfI]; + dict.lookup("zoneInside") >> zoneInside_[surfI]; + } - forAll(edgeFaces, edgeI) + if (dict.found("regions")) { - if (edgeFaces[edgeI].size() != 2) + const dictionary& regionsDict = dict.subDict("regions"); + const wordList& regionNames = + allGeometry_[surfaces_[surfI]].regions(); + + forAllConstIter(dictionary, regionsDict, iter) { - closed_[surfI] = false; - break; + const word& key = iter().keyword(); + + if (regionsDict.isDict(key)) + { + // Get the dictionary for region iter.keyword() + const dictionary& regionDict = regionsDict.subDict(key); + + label regionI = findIndex(regionNames, key); + if (regionI == -1) + { + FatalErrorIn + ( + "refinementSurfaces::refinementSurfaces" + "(const searchableSurfaces&, const dictionary>&" + ) << "No region called " << key << " on surface " + << allGeometry_[surfaces_[surfI]].name() << endl + << "Valid regions are " << regionNames + << exit(FatalError); + } + + const labelPair refLevel(regionDict.lookup("level")); + + regionMinLevel[surfI].insert(regionI, refLevel[0]); + regionMaxLevel[surfI].insert(regionI, refLevel[1]); + } } } + surfI++; } - // Calculate local to global region offset label nRegions = 0; - forAll(surfaceDicts, surfI) + forAll(surfacesDict, surfI) { regionOffset_[surfI] = nRegions; - - nRegions += operator[](surfI).patches().size(); + nRegions += allGeometry_[surfaces_[surfI]].regions().size(); } // Rework surface specific information into information per global region @@ -216,92 +332,52 @@ Foam::refinementSurfaces::refinementSurfaces minLevel_ = 0; maxLevel_.setSize(nRegions); maxLevel_ = 0; - numLayers_.setSize(nRegions); - numLayers_ = 0; - patchName_.setSize(nRegions); - patchType_.setSize(nRegions); - forAll(surfaceDicts, surfI) + + forAll(globalMinLevel, surfI) { - const geometricSurfacePatchList& regions = operator[](surfI).patches(); + label nRegions = allGeometry_[surfaces_[surfI]].regions().size(); // Initialise to global (i.e. per surface) - forAll(regions, i) + for (label i = 0; i < nRegions; i++) { minLevel_[regionOffset_[surfI] + i] = globalMinLevel[surfI]; maxLevel_[regionOffset_[surfI] + i] = globalMaxLevel[surfI]; - numLayers_[regionOffset_[surfI] + i] = globalSurfLayers[surfI]; - patchType_[regionOffset_[surfI] + i] = globalPatchType[surfI]; - } - - // Get the region names - wordList regionNames(regions.size()); - forAll(regions, regionI) - { - regionNames[regionI] = regions[regionI].name(); } // Overwrite with region specific information - forAllConstIter(HashTable<label>, regionMinLevel[surfI], iter) + forAllConstIter(Map<label>, regionMinLevel[surfI], iter) { - // Find the local region number. - label regionI = findIndex(regionNames, iter.key()); - - if (regionI == -1) - { - FatalErrorIn - ( - "refinementSurfaces::refinementSurfaces" - "(const IOobject&, const PtrList<dictionary>&)" - ) << "Cannot find region " << iter.key() - << " in surface " << names_[surfI] - << " which has regions " << regionNames - << abort(FatalError); - } - - label globalRegionI = regionOffset_[surfI] + regionI; + label globalRegionI = regionOffset_[surfI] + iter.key(); minLevel_[globalRegionI] = iter(); maxLevel_[globalRegionI] = regionMaxLevel[surfI][iter.key()]; - numLayers_[globalRegionI] = regionSurfLayers[surfI][iter.key()]; // Check validity if ( minLevel_[globalRegionI] < 0 || maxLevel_[globalRegionI] < minLevel_[globalRegionI] - || numLayers_[globalRegionI] < 0 ) { FatalErrorIn ( "refinementSurfaces::refinementSurfaces" - "(const IOobject&, const PtrList<dictionary>&)" + "(const searchableSurfaces&, const dictionary>&" ) << "Illegal level or layer specification for surface " << names_[surfI] << " : minLevel:" << minLevel_[globalRegionI] << " maxLevel:" << maxLevel_[globalRegionI] - << " numLayers:" << numLayers_[globalRegionI] << exit(FatalError); } } - - // Optional patch names and patch types - forAllConstIter(HashTable<word>, regionPatchName[surfI], iter) - { - label regionI = findIndex(regionNames, iter.key()); - label globalRegionI = regionOffset_[surfI] + regionI; - - patchName_[globalRegionI] = iter(); - patchType_[globalRegionI] = regionPatchType[surfI][iter.key()]; - } } } // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // -//- Get indices of named surfaces (surfaces with cellZoneNam) +// Get indices of named surfaces (surfaces with cellZoneName) Foam::labelList Foam::refinementSurfaces::getNamedSurfaces() const { labelList namedSurfaces(cellZoneNames_.size()); @@ -320,16 +396,26 @@ Foam::labelList Foam::refinementSurfaces::getNamedSurfaces() const } -bool Foam::refinementSurfaces::isSurfaceClosed(const triSurface& s) +// Get indices of closed named surfaces +Foam::labelList Foam::refinementSurfaces::getClosedNamedSurfaces() const { - if (s.nEdges() == s.nInternalEdges()) - { - return true; - } - else + labelList named(getNamedSurfaces()); + + labelList closed(named.size()); + label closedI = 0; + + forAll(named, i) { - return false; + label surfI = named[i]; + + if (allGeometry_[surfaces_[surfI]].hasVolumeType()) + { + closed[closedI++] = surfI; + } } + closed.setSize(closedI); + + return closed; } @@ -373,238 +459,475 @@ Foam::labelList Foam::refinementSurfaces::countRegions(const triSurface& s) } -// Find intersections of edge. Return -1 or first surface with higher minLevel -// number. -Foam::label Foam::refinementSurfaces::findHigherIntersection +// Precalculate the refinement level for every element of the searchable +// surface. This is currently hardcoded for triSurfaceMesh only. +void Foam::refinementSurfaces::setMinLevelFields ( - const point& start, - const point& end, - const label currentLevel, // current cell refinement level - - pointIndexHit& hit -) const + const shellSurfaces& shells +) { - forAll(*this, surfI) + minLevelFields_.setSize(surfaces_.size()); + + forAll(surfaces_, surfI) { - hit = operator[](surfI).findLineAny(start, end); + const searchableSurface& geom = allGeometry_[surfaces_[surfI]]; - if (hit.hit()) + if (isA<triSurfaceMesh>(geom)) { - if (currentLevel == -1) + const triSurfaceMesh& triMesh = refCast<const triSurfaceMesh>(geom); + + minLevelFields_.set + ( + surfI, + new triSurfaceLabelField + ( + IOobject + ( + triMesh.searchableSurface::name(), + triMesh.objectRegistry::time().constant(),// directory + "triSurface", // instance + triMesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE, + false + ), + triMesh, + dimless + ) + ); + triSurfaceLabelField& minLevelField = minLevelFields_[surfI]; + + const triSurface& s = static_cast<const triSurface&>(triMesh); + + // Initialise fields to region wise minLevel + forAll(s, triI) { - // Return any. - return surfI; + minLevelField[triI] = minLevel(surfI, s[triI].region()); } - else + + // Find out if triangle inside shell with higher level + pointField fc(s.size()); + forAll(s, triI) { - //const triSurface& s = trees()[surfI].shapes().surface(); - //label region = globalRegion(surfI, s[hit.index()].region()); - //if (minLevel_[region] > currentLevel) - if (minLevelFields_[surfI][hit.index()] > currentLevel) - { - return surfI; - } + fc[triI] = s[triI].centre(s.points()); + } + // What level does shell want to refine fc to? + labelList shellLevel; + shells.findHigherLevel(fc, minLevelField, shellLevel); + + forAll(minLevelField, triI) + { + minLevelField[triI] = max + ( + minLevelField[triI], + shellLevel[triI] + ); } } } - - hit.setMiss(); - - return -1; } -// Find intersection with max of edge. Return -1 or the surface -// with the highest maxLevel above currentLevel -Foam::label Foam::refinementSurfaces::findHighestIntersection +// Find intersections of edge. Return -1 or first surface with higher minLevel +// number. +void Foam::refinementSurfaces::findHigherIntersection ( - const point& start, - const point& end, - const label currentLevel, // current cell refinement level + const pointField& start, + const pointField& end, + const labelList& currentLevel, // current cell refinement level - pointIndexHit& maxHit + labelList& surfaces, + labelList& surfaceLevel ) const { - // surface with highest maxlevel - label maxSurface = -1; - // maxLevel of maxSurface - label maxLevel = currentLevel; + surfaces.setSize(start.size()); + surfaces = -1; + surfaceLevel.setSize(start.size()); + surfaceLevel = -1; + + if (surfaces_.size() == 0) + { + return; + } + + // Work arrays + labelList hitMap(identity(start.size())); + pointField p0(start); + pointField p1(end); + List<pointIndexHit> hitInfo(start.size()); - forAll(*this, surfI) + + forAll(surfaces_, surfI) { - pointIndexHit hit = operator[](surfI).findLineAny(start, end); + allGeometry_[surfaces_[surfI]].findLineAny(p0, p1, hitInfo); - if (hit.hit()) + // Copy all hits into arguments, continue with misses + label newI = 0; + forAll(hitInfo, hitI) { - const triSurface& s = operator[](surfI); + // Get the minLevel for the point + label minLocalLevel = -1; + + if (hitInfo[hitI].hit()) + { + // Check if minLevelField for this surface. + if + ( + minLevelFields_.set(surfI) + && minLevelFields_[surfI].size() > 0 + ) + { + minLocalLevel = + minLevelFields_[surfI][hitInfo[hitI].index()]; + } + else + { + // Use the min level for the surface instead. Assume + // single region 0. + minLocalLevel = minLevel(surfI, 0); + } + } - label region = globalRegion(surfI, s[hit.index()].region()); + label pointI = hitMap[hitI]; - if (maxLevel_[region] > maxLevel) + if (minLocalLevel > currentLevel[pointI]) + { + surfaces[pointI] = surfI; + surfaceLevel[pointI] = minLocalLevel; + } + else { - maxSurface = surfI; - maxLevel = maxLevel_[region]; - maxHit = hit; + if (hitI != newI) + { + hitMap[newI] = hitMap[hitI]; + p0[newI] = p0[hitI]; + p1[newI] = p1[hitI]; + } + newI++; } } - } - if (maxSurface == -1) - { - // maxLevel unchanged. No interesting surface hit. - maxHit.setMiss(); - } + // All done? Note that this decision should be synchronised + if (newI == 0) + { + break; + } - return maxSurface; + // Trim and continue + hitMap.setSize(newI); + p0.setSize(newI); + p1.setSize(newI); + hitInfo.setSize(newI); + } } -Foam::label Foam::refinementSurfaces::insideZone +void Foam::refinementSurfaces::findAllHigherIntersections ( - const labelList& surfaces, - const point& pt + const pointField& start, + const pointField& end, + const labelList& currentLevel, // current cell refinement level + + List<vectorList>& surfaceNormal, + labelListList& surfaceLevel ) const { - forAll(surfaces, i) + surfaceLevel.setSize(start.size()); + surfaceNormal.setSize(start.size()); + + if (surfaces_.size() == 0) { - label surfI = surfaces[i]; + return; + } + + // Work arrays + List<List<pointIndexHit> > hitInfo; + labelList pRegions; + vectorField pNormals; + + forAll(surfaces_, surfI) + { + allGeometry_[surfaces_[surfI]].findLineAll(start, end, hitInfo); - if (closed_[surfI]) + forAll(hitInfo, pointI) { - const triSurfaceMesh& s = operator[](surfI); + const List<pointIndexHit>& pHits = hitInfo[pointI]; + allGeometry_[surfaces_[surfI]].getRegion(pHits, pRegions); + allGeometry_[surfaces_[surfI]].getNormal(pHits, pNormals); - triSurfaceMesh::volumeType t = s.getVolumeType(pt); + // Extract those hits that are on higher levelled surfaces. + // Note: should move extraction of region, normal outside of loop + // below for if getRegion/getNormal have high overhead. - if - ( - (t == triSurfaceMesh::INSIDE && zoneInside_[surfI]) - || (t == triSurfaceMesh::OUTSIDE && !zoneInside_[surfI]) - ) + forAll(pHits, pHitI) { - return surfI; + label region = globalRegion(surfI, pRegions[pHitI]); + + if (maxLevel_[region] > currentLevel[pointI]) + { + // Append to pointI info + label sz = surfaceNormal[pointI].size(); + surfaceNormal[pointI].setSize(sz+1); + surfaceNormal[pointI][sz] = pNormals[pHitI]; + + surfaceLevel[pointI].setSize(sz+1); + surfaceLevel[pointI][sz] = maxLevel_[region]; + } } } } - return -1; } -Foam::label Foam::refinementSurfaces::markInsidePoints +void Foam::refinementSurfaces::findNearestIntersection ( - const pointField& points, - PackedList<1>& isInside + const labelList& surfacesToTest, + const pointField& start, + const pointField& end, + + labelList& surface1, + List<pointIndexHit>& hit1, + labelList& region1, + labelList& surface2, + List<pointIndexHit>& hit2, + labelList& region2 ) const { - isInside.setSize(points.size()); - isInside = 0u; + // 1. intersection from start to end + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + // Initialize arguments + surface1.setSize(start.size()); + surface1 = -1; + hit1.setSize(start.size()); + region1.setSize(start.size()); + + // Current end of segment to test. + pointField nearest(end); + // Work array + List<pointIndexHit> nearestInfo(start.size()); + labelList region; + + forAll(surfacesToTest, testI) + { + label surfI = surfacesToTest[testI]; - label nPointInside = 0; + // See if any intersection between start and current nearest + allGeometry_[surfaces_[surfI]].findLine + ( + start, + nearest, + nearestInfo + ); + allGeometry_[surfaces_[surfI]].getRegion + ( + nearestInfo, + region + ); - forAll(points, pointI) - { - forAll(*this, surfI) + forAll(nearestInfo, pointI) { - if (closed()[surfI]) + if (nearestInfo[pointI].hit()) { - const triSurfaceMesh& s = operator[](surfI); - - triSurfaceMesh::volumeType t = s.getVolumeType(points[pointI]); - - if (t == triSurfaceMesh::INSIDE) - { - isInside.set(pointI, 1u); - nPointInside++; - break; - } + hit1[pointI] = nearestInfo[pointI]; + surface1[pointI] = surfI; + region1[pointI] = region[pointI]; + nearest[pointI] = hit1[pointI].hitPoint(); } } } - return nPointInside; -} + // 2. intersection from end to last intersection + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -void Foam::refinementSurfaces::setMinLevelFields -( - const PtrList<searchableSurface>& shells, - const labelList& shellLevels, - const boolList& shellRefineInside -) -{ - typedef Foam::DimensionedField<label, triSurfaceGeoMesh> - triSurfaceLabelField; + // Find the nearest intersection from end to start. Note that we initialize + // to the first intersection (if any). + surface2 = surface1; + hit2 = hit1; + region2 = region1; - minLevelFields_.setSize(size()); + // 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(*this, surfI) + forAll(surfacesToTest, testI) { - const triSurfaceMesh& surfMesh = operator[](surfI); + label surfI = surfacesToTest[testI]; - minLevelFields_.set + // See if any intersection between end and current nearest + allGeometry_[surfaces_[surfI]].findLine ( - surfI, - new triSurfaceLabelField - ( - IOobject - ( - surfMesh.IOobject::name(), - surfMesh.time().constant(), // directory - "triSurface", // instance - surfMesh, - IOobject::NO_READ, - IOobject::AUTO_WRITE, - false - ), - surfMesh, - dimless - ) + end, + nearest, + nearestInfo + ); + allGeometry_[surfaces_[surfI]].getRegion + ( + nearestInfo, + region ); + + forAll(nearestInfo, pointI) + { + if (nearestInfo[pointI].hit()) + { + hit2[pointI] = nearestInfo[pointI]; + surface2[pointI] = surfI; + region2[pointI] = region[pointI]; + nearest[pointI] = hit2[pointI].hitPoint(); + } + } } +} - // Initialise fields to region wise minLevel - forAll(*this, surfI) - { - const triSurface& s = operator[](surfI); - triSurfaceLabelField& minLevelField = minLevelFields_[surfI]; +void Foam::refinementSurfaces::findAnyIntersection +( + const pointField& start, + const pointField& end, + + labelList& hitSurface, + List<pointIndexHit>& hitInfo +) const +{ + searchableSurfacesQueries::findAnyIntersection + ( + allGeometry_, + surfaces_, + start, + end, + hitSurface, + hitInfo + ); +} + - forAll(s, i) +void Foam::refinementSurfaces::findNearest +( + const labelList& surfacesToTest, + const pointField& samples, + const scalarField& nearestDistSqr, + labelList& hitSurface, + List<pointIndexHit>& hitInfo +) const +{ + labelList geometries(IndirectList<label>(surfaces_, surfacesToTest)); + + // Do the tests. Note that findNearest returns index in geometries. + searchableSurfacesQueries::findNearest + ( + allGeometry_, + geometries, + samples, + nearestDistSqr, + hitSurface, + hitInfo + ); + + // Rework the hitSurface to be surface (i.e. index into surfaces_) + forAll(hitSurface, pointI) + { + if (hitSurface[pointI] != -1) { - minLevelField[i] = minLevel_[globalRegion(surfI, s[i].region())]; + hitSurface[pointI] = surfacesToTest[hitSurface[pointI]]; } } +} + - // Adapt for triangles inside shells - forAll(*this, surfI) +//// Find intersection with max of edge. Return -1 or the surface +//// with the highest maxLevel above currentLevel +//Foam::label Foam::refinementSurfaces::findHighestIntersection +//( +// const point& start, +// const point& end, +// const label currentLevel, // current cell refinement level +// +// pointIndexHit& maxHit +//) const +//{ +// // surface with highest maxlevel +// label maxSurface = -1; +// // maxLevel of maxSurface +// label maxLevel = currentLevel; +// +// forAll(*this, surfI) +// { +// pointIndexHit hit = operator[](surfI).findLineAny(start, end); +// +// if (hit.hit()) +// { +// const triSurface& s = operator[](surfI); +// +// label region = globalRegion(surfI, s[hit.index()].region()); +// +// if (maxLevel_[region] > maxLevel) +// { +// maxSurface = surfI; +// maxLevel = maxLevel_[region]; +// maxHit = hit; +// } +// } +// } +// +// if (maxSurface == -1) +// { +// // maxLevel unchanged. No interesting surface hit. +// maxHit.setMiss(); +// } +// +// return maxSurface; +//} + + +void Foam::refinementSurfaces::findInside +( + const labelList& testSurfaces, + const pointField& pt, + labelList& insideSurfaces +) const +{ + insideSurfaces.setSize(pt.size()); + insideSurfaces = -1; + + forAll(testSurfaces, i) { - const triSurface& s = operator[](surfI); - triSurfaceLabelField& minLevelField = minLevelFields_[surfI]; + label surfI = testSurfaces[i]; - forAll(s, i) + if (allGeometry_[surfaces_[surfI]].hasVolumeType()) { - point fc = s[i].centre(s.points()); + List<searchableSurface::volumeType> volType; + allGeometry_[surfaces_[surfI]].getVolumeType(pt, volType); - forAll(shells, shellI) + forAll(volType, pointI) { - // Which side of shell is to be refined - searchableSurface::volumeType refSide = - ( - shellRefineInside[shellI] - ? searchableSurface::INSIDE - : searchableSurface::OUTSIDE - ); - - // Find whether point is inside or outside shell - searchableSurface::volumeType t = - shells[shellI].getVolumeType(fc); - - if (t == refSide) + if (insideSurfaces[pointI] == -1) { - minLevelField[i] = max + if ( - minLevelField[i], - shellLevels[shellI] - ); + ( + volType[pointI] == triSurfaceMesh::INSIDE + && zoneInside_[surfI] + ) + || ( + volType[pointI] == triSurfaceMesh::OUTSIDE + && !zoneInside_[surfI] + ) + ) + { + insideSurfaces[pointI] = surfI; + } } } } diff --git a/src/autoMesh/autoHexMesh/refinementSurfaces/refinementSurfaces.H b/src/autoMesh/autoHexMesh/refinementSurfaces/refinementSurfaces.H index dc5bd0adfb6122f66f61830575c5aedf6c2c8d25..b7cbc91696f25f7e800d4d17596fa53fb55e55fb 100644 --- a/src/autoMesh/autoHexMesh/refinementSurfaces/refinementSurfaces.H +++ b/src/autoMesh/autoHexMesh/refinementSurfaces/refinementSurfaces.H @@ -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,28 +107,34 @@ 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 - //- Names of surfaces - const wordList& names() const + const labelList& surfaces() const { - return names_; + return surfaces_; } - //- Per surface whether is closed - const boolList& closed() const + //- Names of surfaces + const wordList& names() const { - return closed_; + return names_; } //- Per 'interface' surface : name of faceZone to put faces into @@ -151,15 +149,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 +173,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 +182,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 +199,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 +220,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; + //- Used for debugging only: find intersection of edge. + void findAnyIntersection + ( + const pointField& start, + const pointField& end, + labelList& surfaces, + List<pointIndexHit>& + ) 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; + //- 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; }; diff --git a/src/autoMesh/autoHexMesh/shellSurfaces/shellSurfaces.C b/src/autoMesh/autoHexMesh/shellSurfaces/shellSurfaces.C new file mode 100644 index 0000000000000000000000000000000000000000..fe64ea81c3d86d8f57b661ac0b24c4d694d76696 --- /dev/null +++ b/src/autoMesh/autoHexMesh/shellSurfaces/shellSurfaces.C @@ -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); + } +} + + +// ************************************************************************* // diff --git a/src/autoMesh/autoHexMesh/shellSurfaces/shellSurfaces.H b/src/autoMesh/autoHexMesh/shellSurfaces/shellSurfaces.H new file mode 100644 index 0000000000000000000000000000000000000000..b996e98e8972f76544c73d032babc2a73ffd5778 --- /dev/null +++ b/src/autoMesh/autoHexMesh/shellSurfaces/shellSurfaces.H @@ -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 + +// ************************************************************************* // diff --git a/src/autoMesh/autoHexMesh/trackedParticle/ExactParticle.C b/src/autoMesh/autoHexMesh/trackedParticle/ExactParticle.C index 508143aaf9729a6ccd63648325f06bacc16fa353..cebb6597c217c15bdcdf5a9780e7dfe365b5f787 100644 --- a/src/autoMesh/autoHexMesh/trackedParticle/ExactParticle.C +++ b/src/autoMesh/autoHexMesh/trackedParticle/ExactParticle.C @@ -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)); } diff --git a/src/dynamicMesh/polyTopoChange/polyTopoChange/addPatchCellLayer.C b/src/dynamicMesh/polyTopoChange/polyTopoChange/addPatchCellLayer.C index c1c0e4f316edb9801cf722a14e11417bb5afade5..0742fd44b50fd83ec1c3f03b563e08c17a6f0e6e 100644 --- a/src/dynamicMesh/polyTopoChange/polyTopoChange/addPatchCellLayer.C +++ b/src/dynamicMesh/polyTopoChange/polyTopoChange/addPatchCellLayer.C @@ -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]; } } } diff --git a/src/dynamicMesh/polyTopoChange/polyTopoChange/addPatchCellLayer.H b/src/dynamicMesh/polyTopoChange/polyTopoChange/addPatchCellLayer.H index 0e47acb7eaeec67dbdec4334e19b0cc337db57b8..0b5caaba86f8d2b84c6f1605809ecb5925937d0b 100644 --- a/src/dynamicMesh/polyTopoChange/polyTopoChange/addPatchCellLayer.H +++ b/src/dynamicMesh/polyTopoChange/polyTopoChange/addPatchCellLayer.H @@ -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), diff --git a/src/meshTools/Make/files b/src/meshTools/Make/files index 3a3d2aff830ff305ddb6e6057dc244bcfa7e93f6..90f9de250e298142d18b889e8be63a8bf86dac96 100644 --- a/src/meshTools/Make/files +++ b/src/meshTools/Make/files @@ -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 diff --git a/src/meshTools/searchableSurface/searchableBox.C b/src/meshTools/searchableSurface/searchableBox.C new file mode 100644 index 0000000000000000000000000000000000000000..be3969d6f4061569bb73103f2c7e9a93ba82d339 --- /dev/null +++ b/src/meshTools/searchableSurface/searchableBox.C @@ -0,0 +1,541 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*---------------------------------------------------------------------------*/ + +#include "searchableBox.H" +#include "addToRunTimeSelectionTable.H" +#include "SortableList.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ + +defineTypeNameAndDebug(searchableBox, 0); +addToRunTimeSelectionTable(searchableSurface, searchableBox, dict); + +} + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::searchableBox::projectOntoCoordPlane +( + const direction dir, + const point& planePt, + pointIndexHit& info +) const +{ + // Set point + info.rawPoint()[dir] = planePt[dir]; + // Set face + if (planePt[dir] == min()[dir]) + { + info.setIndex(dir*2); + } + else if (planePt[dir] == max()[dir]) + { + info.setIndex(dir*2+1); + } + else + { + FatalErrorIn("searchableBox::projectOntoCoordPlane(..)") + << "Point on plane " << planePt + << " is not on coordinate " << min()[dir] + << " nor " << max()[dir] << abort(FatalError); + } +} + + +// Returns miss or hit with face (0..5) and region(always 0) +Foam::pointIndexHit Foam::searchableBox::findNearest +( + const point& bbMid, + const point& sample, + const scalar nearestDistSqr +) const +{ + // Point can be inside or outside. For every component direction can be + // left of min, right of max or inbetween. + // - outside points: project first one x plane (either min().x() + // or max().x()), then onto y plane and finally z. You should be left + // with intersection point + // - inside point: find nearest side (compare to mid point). Project onto + // that. + + // The face is set to the last projected face. + + + // Outside point projected onto cube. Assume faces 0..5. + pointIndexHit info(true, sample, -1); + bool outside = false; + + // (for internal points) per direction what nearest cube side is + point near; + + for (direction dir = 0; dir < vector::nComponents; dir++) + { + if (info.rawPoint()[dir] < min()[dir]) + { + projectOntoCoordPlane(dir, min(), info); + outside = true; + } + else if (info.rawPoint()[dir] > max()[dir]) + { + projectOntoCoordPlane(dir, max(), info); + outside = true; + } + else if (info.rawPoint()[dir] > bbMid[dir]) + { + near[dir] = max()[dir]; + } + else + { + near[dir] = min()[dir]; + } + } + + + // For outside points the info will be correct now. Handle inside points + // using the three near distances. Project onto the nearest plane. + if (!outside) + { + vector dist(cmptMag(info.rawPoint() - near)); + + if (dist.x() < dist.y()) + { + if (dist.x() < dist.z()) + { + // Project onto x plane + projectOntoCoordPlane(vector::X, near, info); + } + else + { + projectOntoCoordPlane(vector::Z, near, info); + } + } + else + { + if (dist.y() < dist.z()) + { + projectOntoCoordPlane(vector::Y, near, info); + } + else + { + projectOntoCoordPlane(vector::Z, near, info); + } + } + } + + + // Check if outside. Optimisation: could do some checks on distance already + // on components above + if (magSqr(info.rawPoint() - sample) > nearestDistSqr) + { + info.setMiss(); + info.setIndex(-1); + } + + return info; +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::searchableBox::searchableBox +( + const IOobject& io, + const treeBoundBox& bb +) +: + searchableSurface(io), + treeBoundBox(bb) +{} + + +Foam::searchableBox::searchableBox +( + const IOobject& io, + const dictionary& dict +) +: + searchableSurface(io), + treeBoundBox(dict.lookup("min"), dict.lookup("max")) +{} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::searchableBox::~searchableBox() +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +const Foam::wordList& Foam::searchableBox::regions() const +{ + if (regions_.size() == 0) + { + regions_.setSize(1); + regions_[0] = "region0"; + } + return regions_; +} + + +Foam::pointIndexHit Foam::searchableBox::findNearest +( + const point& sample, + const scalar nearestDistSqr +) const +{ + return findNearest(mid(), sample, nearestDistSqr); +} + + +Foam::pointIndexHit Foam::searchableBox::findNearestOnEdge +( + const point& sample, + const scalar nearestDistSqr +) const +{ + const point bbMid(mid()); + + // Outside point projected onto cube. Assume faces 0..5. + pointIndexHit info(true, sample, -1); + bool outside = false; + + // (for internal points) per direction what nearest cube side is + point near; + + for (direction dir = 0; dir < vector::nComponents; dir++) + { + if (info.rawPoint()[dir] < min()[dir]) + { + projectOntoCoordPlane(dir, min(), info); + outside = true; + } + else if (info.rawPoint()[dir] > max()[dir]) + { + projectOntoCoordPlane(dir, max(), info); + outside = true; + } + else if (info.rawPoint()[dir] > bbMid[dir]) + { + near[dir] = max()[dir]; + } + else + { + near[dir] = min()[dir]; + } + } + + + // For outside points the info will be correct now. Handle inside points + // using the three near distances. Project onto the nearest two planes. + if (!outside) + { + // Get the per-component distance to nearest wall + vector dist(cmptMag(info.rawPoint() - near)); + + SortableList<scalar> sortedDist(3); + sortedDist[0] = dist[0]; + sortedDist[1] = dist[1]; + sortedDist[2] = dist[2]; + sortedDist.sort(); + + // Project onto nearest + projectOntoCoordPlane(sortedDist.indices()[0], near, info); + // Project onto second nearest + projectOntoCoordPlane(sortedDist.indices()[1], near, info); + } + + + // Check if outside. Optimisation: could do some checks on distance already + // on components above + if (magSqr(info.rawPoint() - sample) > nearestDistSqr) + { + info.setMiss(); + info.setIndex(-1); + } + + return info; +} + + +Foam::pointIndexHit Foam::searchableBox::findNearest +( + const linePointRef& ln, + treeBoundBox& tightest, + point& linePoint +) const +{ + notImplemented + ( + "searchableBox::findNearest" + "(const linePointRef&, treeBoundBox&, point&)" + ); + return pointIndexHit(); +} + + +Foam::pointIndexHit Foam::searchableBox::findLine +( + const point& start, + const point& end +) const +{ + pointIndexHit info(false, start, -1); + + bool foundInter; + + if (posBits(start) == 0) + { + if (posBits(end) == 0) + { + // Both start and end inside. + foundInter = false; + } + else + { + // end is outside. Clip to bounding box. + foundInter = intersects(end, start, info.rawPoint()); + } + } + else + { + // start is outside. Clip to bounding box. + foundInter = intersects(start, end, info.rawPoint()); + } + + + // Classify point + if (foundInter) + { + info.setHit(); + + for (direction dir = 0; dir < vector::nComponents; dir++) + { + if (info.rawPoint()[dir] == min()[dir]) + { + info.setIndex(2*dir); + break; + } + else if (info.rawPoint()[dir] == max()[dir]) + { + info.setIndex(2*dir+1); + break; + } + } + + if (info.index() == -1) + { + FatalErrorIn("searchableBox::findLine(const point&, const point&)") + << "point " << info.rawPoint() + << " on segment " << start << end + << " should be on face of " << *this + << " but it isn't." << abort(FatalError); + } + } + + return info; +} + + +Foam::pointIndexHit Foam::searchableBox::findLineAny +( + const point& start, + const point& end +) const +{ + return findLine(start, end); +} + + +void Foam::searchableBox::findNearest +( + const pointField& samples, + const scalarField& nearestDistSqr, + List<pointIndexHit>& info +) const +{ + info.setSize(samples.size()); + + const point bbMid(mid()); + + forAll(samples, i) + { + info[i] = findNearest(bbMid, samples[i], nearestDistSqr[i]); + } +} + + +void Foam::searchableBox::findLine +( + const pointField& start, + const pointField& end, + List<pointIndexHit>& info +) const +{ + info.setSize(start.size()); + + forAll(start, i) + { + info[i] = findLine(start[i], end[i]); + } +} + + +void Foam::searchableBox::findLineAny +( + const pointField& start, + const pointField& end, + List<pointIndexHit>& info +) const +{ + info.setSize(start.size()); + + forAll(start, i) + { + info[i] = findLineAny(start[i], end[i]); + } +} + + +void Foam::searchableBox::findLineAll +( + const pointField& start, + const pointField& end, + List<List<pointIndexHit> >& info +) const +{ + info.setSize(start.size()); + + // Work array + DynamicList<pointIndexHit, 1, 1> hits; + + // Tolerances + const vectorField dirVec(end-start); + const scalarField magSqrDirVec(magSqr(dirVec)); + const vectorField smallVec + ( + Foam::sqrt(SMALL)*dirVec + + vector(ROOTVSMALL,ROOTVSMALL,ROOTVSMALL) + ); + + forAll(start, pointI) + { + hits.clear(); + + // Current starting point of ray. + point pt = start[pointI]; + + while (true) + { + // See if any intersection between pt and end + pointIndexHit inter = findLine(pt, end[pointI]); + + if (!inter.hit()) + { + break; + } + hits.append(inter); + + pt = inter.hitPoint() + smallVec[pointI]; + + if (((pt-start[pointI])&dirVec[pointI]) > magSqrDirVec[pointI]) + { + // Adding smallVec has taken us beyond end + break; + } + } + + hits.shrink(); + info[pointI].transfer(hits); + hits.clear(); + } +} + + +void Foam::searchableBox::getRegion +( + const List<pointIndexHit>& info, + labelList& region +) const +{ + region.setSize(info.size()); + region = 0; +} + + +void Foam::searchableBox::getNormal +( + const List<pointIndexHit>& info, + vectorField& normal +) const +{ + normal.setSize(info.size()); + normal = vector::zero; + + forAll(info, i) + { + if (info[i].hit()) + { + normal[i] = treeBoundBox::faceNormals[info[i].index()]; + } + else + { + // Set to what? + } + } +} + + +void Foam::searchableBox::getVolumeType +( + const pointField& points, + List<volumeType>& volType +) const +{ + volType.setSize(points.size()); + volType = INSIDE; + + forAll(points, pointI) + { + const point& pt = points[pointI]; + + for (direction dir = 0; dir < vector::nComponents; dir++) + { + if (pt[dir] < min()[dir] || pt[dir] > max()[dir]) + { + volType[pointI] = OUTSIDE; + break; + } + } + } +} + + +// ************************************************************************* // diff --git a/src/meshTools/searchableSurface/searchableBox.H b/src/meshTools/searchableSurface/searchableBox.H new file mode 100644 index 0000000000000000000000000000000000000000..f606f83e1ef77f7184e9dfa6220aa92715d199e6 --- /dev/null +++ b/src/meshTools/searchableSurface/searchableBox.H @@ -0,0 +1,249 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Class + Foam::searchableBox + +Description + Searching on bounding box + +SourceFiles + searchableBox.C + +\*---------------------------------------------------------------------------*/ + +#ifndef searchableBox_H +#define searchableBox_H + +#include "searchableSurface.H" +#include "treeBoundBox.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward declaration of classes + +/*---------------------------------------------------------------------------*\ + Class searchableBox Declaration +\*---------------------------------------------------------------------------*/ + +class searchableBox +: + public searchableSurface, + public treeBoundBox +{ +private: + + // Private Member Data + + mutable wordList regions_; + + + // Private Member Functions + + //- Project onto component dir of planePt and update index() (=face) + void projectOntoCoordPlane + ( + const direction dir, + const point& planePt, + pointIndexHit& info + ) const; + + //- Returns miss or hit with face (0..5) + pointIndexHit findNearest + ( + const point& bbMid, + const point& sample, + const scalar nearestDistSqr + ) const; + + + //- Disallow default bitwise copy construct + searchableBox(const searchableBox&); + + //- Disallow default bitwise assignment + void operator=(const searchableBox&); + + +public: + + //- Runtime type information + TypeName("searchableBox"); + + + // Constructors + + //- Construct from components + searchableBox(const IOobject& io, const treeBoundBox& bb); + + //- Construct from dictionary (used by searchableSurface) + searchableBox + ( + const IOobject& io, + const dictionary& dict + ); + + // Destructor + + virtual ~searchableBox(); + + + // Member Functions + + virtual const wordList& regions() const; + + //- Whether supports volume type below + virtual bool hasVolumeType() const + { + return true; + } + + + // Single point queries. + + //- Calculate nearest point on surface. Returns + // - bool : any point found nearer than nearestDistSqr + // - label: relevant index in surface (=face 0..5) + // - point: actual nearest point found + pointIndexHit findNearest + ( + const point& sample, + const scalar nearestDistSqr + ) const; + + //- Calculate nearest point on edge. Returns + // - bool : any point found nearer than nearestDistSqr + // - label: relevant index in surface(=?) + // - point: actual nearest point found + pointIndexHit findNearestOnEdge + ( + const point& sample, + const scalar nearestDistSqr + ) const; + + //- Find nearest to segment. Returns + // - bool : any point found? + // - label: relevant index in shapes (=face 0..5) + // - point: actual nearest point found + // sets: + // - tightest : bounding box + // - linePoint : corresponding nearest point on line + pointIndexHit findNearest + ( + const linePointRef& ln, + treeBoundBox& tightest, + point& linePoint + ) const; + + //- Find nearest intersection of line between start and end. + pointIndexHit findLine + ( + const point& start, + const point& end + ) const; + + //- Find any intersection of line between start and end. + pointIndexHit findLineAny + ( + const point& start, + const point& end + ) const; + + + // Multiple point queries. + + virtual void findNearest + ( + const pointField& sample, + const scalarField& nearestDistSqr, + List<pointIndexHit>& + ) const; + + virtual void findLine + ( + const pointField& start, + const pointField& end, + List<pointIndexHit>& + ) const; + + virtual void findLineAny + ( + const pointField& start, + const pointField& end, + List<pointIndexHit>& + ) const; + + //- Get all intersections in order from start to end. + virtual void findLineAll + ( + const pointField& start, + const pointField& end, + List<List<pointIndexHit> >& + ) const; + + //- From a set of points and indices get the region + virtual void getRegion + ( + const List<pointIndexHit>&, + labelList& region + ) const; + + //- From a set of points and indices get the normal + virtual void getNormal + ( + const List<pointIndexHit>&, + vectorField& normal + ) const; + + //- Determine type (inside/outside/mixed) for point. unknown if + // cannot be determined (e.g. non-manifold surface) + virtual void getVolumeType + ( + const pointField&, + List<volumeType>& + ) const; + + + // regIOobject implementation + + bool writeData(Ostream&) const + { + notImplemented("searchableBox::writeData(Ostream&) const"); + return false; + } + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/meshTools/searchableSurface/searchableSphere.C b/src/meshTools/searchableSurface/searchableSphere.C new file mode 100644 index 0000000000000000000000000000000000000000..eb16e2731887040f7adc57c89d05b6f82146fbc2 --- /dev/null +++ b/src/meshTools/searchableSurface/searchableSphere.C @@ -0,0 +1,328 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*---------------------------------------------------------------------------*/ + +#include "searchableSphere.H" +#include "addToRunTimeSelectionTable.H" +#include "SortableList.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ + +defineTypeNameAndDebug(searchableSphere, 0); +addToRunTimeSelectionTable(searchableSurface, searchableSphere, dict); + +} + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +Foam::pointIndexHit Foam::searchableSphere::findNearest +( + const point& sample, + const scalar nearestDistSqr +) const +{ + pointIndexHit info(false, sample, -1); + + const vector n(sample-centre_); + scalar magN = mag(n); + + if (nearestDistSqr > sqr(magN-radius_)) + { + info.rawPoint() = centre_ + n/magN*radius_; + info.setHit(); + info.setIndex(0); + } + + return info; +} + + +// From Graphics Gems - intersection of sphere with ray +void Foam::searchableSphere::findLineAll +( + const point& start, + const point& end, + pointIndexHit& near, + pointIndexHit& far +) const +{ + near.setMiss(); + far.setMiss(); + + vector dir(end-start); + scalar magSqrDir = magSqr(dir); + + if (magSqrDir > ROOTVSMALL) + { + const vector toCentre(centre_-start); + scalar magSqrToCentre = magSqr(toCentre); + + dir /= Foam::sqrt(magSqrDir); + + scalar v = (toCentre & dir); + + scalar disc = sqr(radius_) - (magSqrToCentre - sqr(v)); + + if (disc >= 0) + { + scalar d = Foam::sqrt(disc); + + scalar nearParam = v-d; + + if (nearParam >= 0 && sqr(nearParam) <= magSqrDir) + { + near.setHit(); + near.setPoint(start + nearParam*dir); + near.setIndex(0); + } + + scalar farParam = v+d; + + if (farParam >= 0 && sqr(farParam) <= magSqrDir) + { + far.setHit(); + far.setPoint(start + farParam*dir); + far.setIndex(0); + } + } + } +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::searchableSphere::searchableSphere +( + const IOobject& io, + const point& centre, + const scalar radius +) +: + searchableSurface(io), + centre_(centre), + radius_(radius) +{} + + +Foam::searchableSphere::searchableSphere +( + const IOobject& io, + const dictionary& dict +) +: + searchableSurface(io), + centre_(dict.lookup("centre")), + radius_(readScalar(dict.lookup("radius"))) +{} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::searchableSphere::~searchableSphere() +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +const Foam::wordList& Foam::searchableSphere::regions() const +{ + if (regions_.size() == 0) + { + regions_.setSize(1); + regions_[0] = "region0"; + } + return regions_; +} + + + +void Foam::searchableSphere::findNearest +( + const pointField& samples, + const scalarField& nearestDistSqr, + List<pointIndexHit>& info +) const +{ + info.setSize(samples.size()); + + forAll(samples, i) + { + info[i] = findNearest(samples[i], nearestDistSqr[i]); + } +} + + +void Foam::searchableSphere::findLine +( + const pointField& start, + const pointField& end, + List<pointIndexHit>& info +) const +{ + info.setSize(start.size()); + + pointIndexHit b; + + forAll(start, i) + { + // Pick nearest intersection. If none intersected take second one. + findLineAll(start[i], end[i], info[i], b); + if (!info[i].hit() && b.hit()) + { + info[i] = b; + } + } +} + + +void Foam::searchableSphere::findLineAny +( + const pointField& start, + const pointField& end, + List<pointIndexHit>& info +) const +{ + info.setSize(start.size()); + + pointIndexHit b; + + forAll(start, i) + { + // Discard far intersection + findLineAll(start[i], end[i], info[i], b); + if (!info[i].hit() && b.hit()) + { + info[i] = b; + } + } +} + + +void Foam::searchableSphere::findLineAll +( + const pointField& start, + const pointField& end, + List<List<pointIndexHit> >& info +) const +{ + info.setSize(start.size()); + + pointIndexHit near, far; + + forAll(start, i) + { + findLineAll(start[i], end[i], near, far); + + if (near.hit()) + { + if (far.hit()) + { + info[i].setSize(2); + info[i][0] = near; + info[i][1] = far; + } + else + { + info[i].setSize(1); + info[i][0] = near; + } + } + else + { + if (far.hit()) + { + info[i].setSize(1); + info[i][0] = far; + } + } + } +} + + +void Foam::searchableSphere::getRegion +( + const List<pointIndexHit>& info, + labelList& region +) const +{ + region.setSize(info.size()); + region = 0; +} + + +void Foam::searchableSphere::getNormal +( + const List<pointIndexHit>& info, + vectorField& normal +) const +{ + normal.setSize(info.size()); + normal = vector::zero; + + forAll(info, i) + { + if (info[i].hit()) + { + normal[i] = info[i].hitPoint() - centre_; + normal[i] /= mag(normal[i]); + } + else + { + // Set to what? + } + } +} + + +void Foam::searchableSphere::getVolumeType +( + const pointField& points, + List<volumeType>& volType +) const +{ + volType.setSize(points.size()); + volType = INSIDE; + + forAll(points, pointI) + { + const point& pt = points[pointI]; + + if (magSqr(pt - centre_) <= sqr(radius_)) + { + volType[pointI] = INSIDE; + } + else + { + volType[pointI] = OUTSIDE; + } + } +} + + +// ************************************************************************* // diff --git a/src/meshTools/searchableSurface/searchableSphere.H b/src/meshTools/searchableSurface/searchableSphere.H new file mode 100644 index 0000000000000000000000000000000000000000..7b3f4856ac72d1a1d1da3cc32e79d2b3ce93385a --- /dev/null +++ b/src/meshTools/searchableSurface/searchableSphere.H @@ -0,0 +1,204 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Class + Foam::searchableSphere + +Description + Searching on sphere + +SourceFiles + searchableSphere.C + +\*---------------------------------------------------------------------------*/ + +#ifndef searchableSphere_H +#define searchableSphere_H + +#include "searchableSurface.H" +#include "treeBoundBox.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward declaration of classes + +/*---------------------------------------------------------------------------*\ + Class searchableSphere Declaration +\*---------------------------------------------------------------------------*/ + +class searchableSphere +: + public searchableSurface +{ +private: + + // Private Member Data + + //- Centre point + const point centre_; + + //- Radius squared + const scalar radius_; + + //- Names of regions + mutable wordList regions_; + + + // Private Member Functions + + //- Find nearest point on sphere. + pointIndexHit findNearest + ( + const point& sample, + const scalar nearestDistSqr + ) const; + + //- Find intersection with sphere + void findLineAll + ( + const point& start, + const point& end, + pointIndexHit& near, + pointIndexHit& far + ) const; + + + //- Disallow default bitwise copy construct + searchableSphere(const searchableSphere&); + + //- Disallow default bitwise assignment + void operator=(const searchableSphere&); + + +public: + + //- Runtime type information + TypeName("searchableSphere"); + + + // Constructors + + //- Construct from components + searchableSphere(const IOobject& io, const point&, const scalar radius); + + //- Construct from dictionary (used by searchableSurface) + searchableSphere + ( + const IOobject& io, + const dictionary& dict + ); + + // Destructor + + virtual ~searchableSphere(); + + + // Member Functions + + virtual const wordList& regions() const; + + //- Whether supports volume type below + virtual bool hasVolumeType() const + { + return true; + } + + + // Multiple point queries. + + virtual void findNearest + ( + const pointField& sample, + const scalarField& nearestDistSqr, + List<pointIndexHit>& + ) const; + + virtual void findLine + ( + const pointField& start, + const pointField& end, + List<pointIndexHit>& + ) const; + + virtual void findLineAny + ( + const pointField& start, + const pointField& end, + List<pointIndexHit>& + ) const; + + //- Get all intersections in order from start to end. + virtual void findLineAll + ( + const pointField& start, + const pointField& end, + List<List<pointIndexHit> >& + ) const; + + //- From a set of points and indices get the region + virtual void getRegion + ( + const List<pointIndexHit>&, + labelList& region + ) const; + + //- From a set of points and indices get the normal + virtual void getNormal + ( + const List<pointIndexHit>&, + vectorField& normal + ) const; + + //- Determine type (inside/outside/mixed) for point. unknown if + // cannot be determined (e.g. non-manifold surface) + virtual void getVolumeType + ( + const pointField&, + List<volumeType>& + ) const; + + + // regIOobject implementation + + bool writeData(Ostream&) const + { + notImplemented("searchableSphere::writeData(Ostream&) const"); + return false; + } + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/meshTools/triSurface/searchableSurface/searchableSurface.C b/src/meshTools/searchableSurface/searchableSurface.C similarity index 65% rename from src/meshTools/triSurface/searchableSurface/searchableSurface.C rename to src/meshTools/searchableSurface/searchableSurface.C index 11996e75341d3cdae108fb2bd57b65089e90f287..9e6cffa315de7720e11d0ce5cf8706a8fa3f5688 100644 --- a/src/meshTools/triSurface/searchableSurface/searchableSurface.C +++ b/src/meshTools/searchableSurface/searchableSurface.C @@ -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 @@ -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) {} diff --git a/src/meshTools/searchableSurface/searchableSurface.H b/src/meshTools/searchableSurface/searchableSurface.H new file mode 100644 index 0000000000000000000000000000000000000000..43e008ca50421b03393f688f1407ea9655e7cf70 --- /dev/null +++ b/src/meshTools/searchableSurface/searchableSurface.H @@ -0,0 +1,322 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Class + Foam::searchableSurface + +Description + Base class of (analytical or triangulated) surface. + Encapsulates all the search routines. WIP. + + Information returned is usually a pointIndexHit: + - bool : was intersection/nearest found? + - point : intersection point or nearest point + - index : unique index on surface (e.g. triangle for triSurfaceMesh) + +SourceFiles + searchableSurface.C + +\*---------------------------------------------------------------------------*/ + +#ifndef searchableSurface_H +#define searchableSurface_H + +#include "pointField.H" +#include "typeInfo.H" +#include "runTimeSelectionTables.H" +#include "pointIndexHit.H" +#include "linePointRef.H" +#include "objectRegistry.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward declaration of classes +class objectRegistry; +class treeBoundBox; + +/*---------------------------------------------------------------------------*\ + Class searchableSurface Declaration +\*---------------------------------------------------------------------------*/ + +class searchableSurface +: + public regIOobject +{ +public: + + // Data types + + //- volume types + enum volumeType + { + UNKNOWN = 0, + MIXED = 1, // not used. only here to maintain consistency with + // indexedOctree volumeType. + INSIDE = 2, + OUTSIDE = 3 + }; + +private: + + // Private data + + const word name_; + + + // Private Member Functions + + //- Disallow default bitwise copy construct + searchableSurface(const searchableSurface&); + + //- Disallow default bitwise assignment + void operator=(const searchableSurface&); + + +public: + + //- Runtime type information + TypeName("searchableSurface"); + + // Declare run-time constructor selection table + + // For the dictionary constructor + declareRunTimeSelectionTable + ( + autoPtr, + searchableSurface, + dict, + ( + const IOobject& io, + const dictionary& dict + ), + (io, dict) + ); + + + //- Class used for the read-construction of + // PtrLists of searchableSurface. + class iNew + { + IOobject& io_; + + public: + + iNew(IOobject& io) + : + io_(io) + {} + + autoPtr<searchableSurface> operator()(Istream& is) const + { + word surfaceType(is); + word readName(is); + dictionary dict(is); + + autoPtr<IOobject> namedIO(io_.clone()); + namedIO().rename(readName); + return searchableSurface::New(surfaceType, namedIO(), dict); + } + }; + + + // Constructors + + searchableSurface(const IOobject& io); + + //- Clone + virtual autoPtr<searchableSurface> clone() const + { + notImplemented("autoPtr<searchableSurface> clone() const"); + return autoPtr<searchableSurface>(NULL); + } + + + // Selectors + + //- Return a reference to the selected searchableSurface + static autoPtr<searchableSurface> New + ( + const word& surfaceType, + const IOobject& io, + const dictionary& dict + ); + + + // Destructor + + virtual ~searchableSurface(); + + + // Member Functions + + + //- Names of regions. + virtual const wordList& regions() const = 0; + + //- Whether supports volume type below. + virtual bool hasVolumeType() const = 0; + + + // Single point queries. + + ////- Calculate nearest point on surface. Returns + //// - bool : any point found nearer than nearestDistSqr + //// - label: relevant index in surface + //// - label: region in surface + //// - point: actual nearest point found + //virtual pointIndexHit findNearest + //( + // const point& sample, + // const scalar nearestDistSqr + //) const = 0; + // + ////- Calculate nearest point on edge. Returns + //// - bool : any point found nearer than nearestDistSqr + //// - label: relevant index in surface + //// - label: region in surface + //// - point: actual nearest point found + //virtual pointIndexHit findNearestOnEdge + //( + // const point& sample, + // const scalar nearestDistSqr + //) const = 0; + // + ////- Find nearest to segment. Returns + //// - bool : any point found? + //// - label: relevant index in shapes + //// - label: region in surface + //// - point: actual nearest point found + //// sets: + //// - tightest : bounding box + //// - linePoint : corresponding nearest point on line + //virtual pointIndexHit findNearest + //( + // const linePointRef& ln, + // treeBoundBox& tightest, + // point& linePoint + //) const = 0; + // + ////- Find nearest intersection of line between start and end. + //virtual pointIndexHit findLine + //( + // const point& start, + // const point& end + //) const = 0; + // + ////- Find any intersection of line between start and end. + //virtual pointIndexHit findLineAny + //( + // const point& start, + // const point& end + //) const = 0; + + + // Multiple point queries. When surface is distributed the index + // should be a global index. Not done yet. + + virtual void findNearest + ( + const pointField& sample, + const scalarField& nearestDistSqr, + List<pointIndexHit>& + ) const = 0; + + //- Find first intersection on segment from start to end. + // Note: searchableSurfacesQueries expects no + // intersection to be found if start==end. Is problem? + virtual void findLine + ( + const pointField& start, + const pointField& end, + List<pointIndexHit>& + ) const = 0; + + //- Return any intersection on segment from start to end. + virtual void findLineAny + ( + const pointField& start, + const pointField& end, + List<pointIndexHit>& + ) const = 0; + + //- Get all intersections in order from start to end. + virtual void findLineAll + ( + const pointField& start, + const pointField& end, + List<List<pointIndexHit> >& + ) const = 0; + + //- From a set of points and indices get the region + virtual void getRegion + ( + const List<pointIndexHit>&, + labelList& region + ) const = 0; + + //- From a set of points and indices get the normal + virtual void getNormal + ( + const List<pointIndexHit>&, + vectorField& normal + ) const = 0; + + //- Determine type (inside/outside) for point. unknown if + // cannot be determined (e.g. non-manifold surface) + virtual void getVolumeType + ( + const pointField&, + List<volumeType>& + ) const = 0; + + + // Other + + ////- Get bounding box. + //const boundBox& bounds() const = 0; + + ////- Set bounding box. + //void setBounds + //( + // const boundBox&, + // autoPtr<mapDistribute>& faceMap, + // autoPtr<mapDistribute>& pointMap + //) = 0; + + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/meshTools/searchableSurface/searchableSurfaces.C b/src/meshTools/searchableSurface/searchableSurfaces.C new file mode 100644 index 0000000000000000000000000000000000000000..8fbb4678e77f300f18ce39bee1d6781c134f6141 --- /dev/null +++ b/src/meshTools/searchableSurface/searchableSurfaces.C @@ -0,0 +1,355 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*----------------------------------------------------------------------------*/ + +#include "searchableSurfaces.H" +#include "searchableSurfacesQueries.H" +#include "ListOps.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +defineTypeNameAndDebug(searchableSurfaces, 0); + +} + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +// Construct with length. +Foam::searchableSurfaces::searchableSurfaces(const label size) +: + PtrList<searchableSurface>(size), + regionNames_(size), + allSurfaces_(identity(size)) +{} + + +//Foam::searchableSurfaces::searchableSurfaces +//( +// const IOobject& io, +// const PtrList<dictionary>& dicts +//) +//: +// PtrList<searchableSurface>(dicts.size()), +// regionNames_(dicts.size()), +// allSurfaces_(identity(dicts.size())) +//{ +// forAll(dicts, surfI) +// { +// const dictionary& dict = dicts[surfI]; +// +// // Make IOobject with correct name +// autoPtr<IOobject> namedIO(io.clone()); +// namedIO().rename(dict.lookup("name")); +// +// // Create and hook surface +// set +// ( +// surfI, +// searchableSurface::New +// ( +// dict.lookup("type"), +// namedIO(), +// dict +// ) +// ); +// const searchableSurface& s = operator[](surfI); +// +// // Construct default region names by prepending surface name +// // to region name. +// const wordList& localNames = s.regions(); +// +// wordList globalNames(localNames.size()); +// forAll(localNames, regionI) +// { +// globalNames[regionI] = s.name() + '_' + localNames[regionI]; +// } +// +// // See if dictionary provides any global region names. +// if (dict.found("regions")) +// { +// const dictionary& regionsDict = dict.subDict("regions"); +// +// forAllConstIter(dictionary, regionsDict, iter) +// { +// const word& key = iter().keyword(); +// +// if (regionsDict.isDict(key)) +// { +// // Get the dictionary for region iter.key() +// const dictionary& regionDict = regionsDict.subDict(key); +// +// label index = findIndex(localNames, key); +// +// if (index == -1) +// { +// FatalErrorIn +// ( +// "searchableSurfaces::searchableSurfaces" +// "( const IOobject&, const dictionary&)" +// ) << "Unknown region name " << key +// << " for surface " << s.name() << endl +// << "Valid region names are " << localNames +// << exit(FatalError); +// } +// +// globalNames[index] = word(regionDict.lookup("name")); +// } +// } +// } +// +// // Now globalNames contains the names of the regions. +// Info<< "Surface:" << s.name() << " has regions:" +// << endl; +// forAll(globalNames, regionI) +// { +// Info<< " " << globalNames[regionI] << endl; +// } +// +// // Create reverse lookup +// forAll(globalNames, regionI) +// { +// regionNames_.insert +// ( +// globalNames[regionI], +// labelPair(surfI, regionI) +// ); +// } +// } +//} + + +Foam::searchableSurfaces::searchableSurfaces +( + const IOobject& io, + const dictionary& topDict +) +: + PtrList<searchableSurface>(topDict.size()), + names_(topDict.size()), + regionNames_(topDict.size()), + allSurfaces_(identity(topDict.size())) +{ + label surfI = 0; + forAllConstIter(dictionary, topDict, iter) + { + const word& key = iter().keyword(); + + if (!topDict.isDict(key)) + { + FatalErrorIn + ( + "searchableSurfaces::searchableSurfaces" + "( const IOobject&, const dictionary&)" + ) << "Found non-dictionary entry " << iter() + << " in top-level dictionary " << topDict + << exit(FatalError); + } + + const dictionary& dict = topDict.subDict(key); + + names_[surfI] = key; + + if (dict.found("name")) + { + dict.lookup("name") >> names_[surfI]; + } + + + // Make IOobject with correct name + autoPtr<IOobject> namedIO(io.clone()); + // Note: we would like to e.g. register triSurface 'sphere.stl' as + // 'sphere'. Unfortunately + // no support for having object read from different location than + // their object name. Maybe have stlTriSurfaceMesh which appends .stl + // when reading/writing? + namedIO().rename(key); // names_[surfI] + + // Create and hook surface + set + ( + surfI, + searchableSurface::New + ( + dict.lookup("type"), + namedIO(), + dict + ) + ); + const searchableSurface& s = operator[](surfI); + + // Construct default region names by prepending surface name + // to region name. + const wordList& localNames = s.regions(); + + wordList& rNames = regionNames_[surfI]; + rNames.setSize(localNames.size()); + + forAll(localNames, regionI) + { + rNames[regionI] = names_[surfI] + '_' + localNames[regionI]; + } + + // See if dictionary provides any global region names. + if (dict.found("regions")) + { + const dictionary& regionsDict = dict.subDict("regions"); + + forAllConstIter(dictionary, regionsDict, iter) + { + const word& key = iter().keyword(); + + if (regionsDict.isDict(key)) + { + // Get the dictionary for region iter.keyword() + const dictionary& regionDict = regionsDict.subDict(key); + + label index = findIndex(localNames, key); + + if (index == -1) + { + FatalErrorIn + ( + "searchableSurfaces::searchableSurfaces" + "( const IOobject&, const dictionary&)" + ) << "Unknown region name " << key + << " for surface " << s.name() << endl + << "Valid region names are " << localNames + << exit(FatalError); + } + + rNames[index] = word(regionDict.lookup("name")); + } + } + } + + surfI++; + } + + // Trim (not really necessary since we don't allow non-dictionary entries) + PtrList<searchableSurface>::setSize(surfI); + names_.setSize(surfI); + regionNames_.setSize(surfI); + allSurfaces_.setSize(surfI); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +Foam::label Foam::searchableSurfaces::findSurfaceID(const word& wantedName) + const +{ + return findIndex(names_, wantedName); +} + + +// Find any intersection +void Foam::searchableSurfaces::findAnyIntersection +( + const pointField& start, + const pointField& end, + labelList& hitSurfaces, + List<pointIndexHit>& hitInfo +) const +{ + searchableSurfacesQueries::findAnyIntersection + ( + *this, + allSurfaces_, + start, + end, + hitSurfaces, + hitInfo + ); +} + + +// Find intersections of edge nearest to both endpoints. +void Foam::searchableSurfaces::findAllIntersections +( + const pointField& start, + const pointField& end, + labelListList& hitSurfaces, + List<List<pointIndexHit> >& hitInfo +) const +{ + searchableSurfacesQueries::findAllIntersections + ( + *this, + allSurfaces_, + start, + end, + hitSurfaces, + hitInfo + ); +} + + +// Find nearest. Return -1 or nearest point +void Foam::searchableSurfaces::findNearest +( + const pointField& samples, + const scalarField& nearestDistSqr, + labelList& nearestSurfaces, + List<pointIndexHit>& nearestInfo +) const +{ + return searchableSurfacesQueries::findNearest + ( + *this, + allSurfaces_, + samples, + nearestDistSqr, + nearestSurfaces, + nearestInfo + ); +} + + +//- Calculate point which is on a set of surfaces. +Foam::pointIndexHit Foam::searchableSurfaces::facesIntersection +( + const scalar initDistSqr, + const scalar convergenceDistSqr, + const point& start +) const +{ + return searchableSurfacesQueries::facesIntersection + ( + *this, + allSurfaces_, + initDistSqr, + convergenceDistSqr, + start + ); +} + + +// ************************************************************************* // diff --git a/src/meshTools/searchableSurface/searchableSurfaces.H b/src/meshTools/searchableSurface/searchableSurfaces.H new file mode 100644 index 0000000000000000000000000000000000000000..acb02572e635e36774be6483ad21f498a8b2c3ae --- /dev/null +++ b/src/meshTools/searchableSurface/searchableSurfaces.H @@ -0,0 +1,187 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Class + Foam::searchableSurfaces + +Description + Container for searchableSurfaces. + +SourceFiles + searchableSurfaces.C + +\*---------------------------------------------------------------------------*/ + +#ifndef searchableSurfaces_H +#define searchableSurfaces_H + +#include "searchableSurface.H" +#include "labelPair.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward declaration of classes + +/*---------------------------------------------------------------------------*\ + Class searchableSurfaces Declaration +\*---------------------------------------------------------------------------*/ + +class searchableSurfaces +: + public PtrList<searchableSurface> +{ + // Private data + + //- Surface names + wordList names_; + + //- Region names per surface + List<wordList> regionNames_; + + ////- From global region name to surface and region on surface + //HashTable<labelPair> regionNames_; + + //- Indices of all surfaces. Precalculated and stored. + labelList allSurfaces_; + + + //- Disallow default bitwise copy construct + searchableSurfaces(const searchableSurfaces&); + + //- Disallow default bitwise assignment + void operator=(const searchableSurfaces&); + + +public: + + ClassName("searchableSurfaces"); + + // Constructors + + //- Construct with length specified. Fill later. + explicit searchableSurfaces(const label); + + + ////- Construct from list of dictionaries + //searchableSurfaces(const IOobject&, const PtrList<dictionary>&); + + //- Construct from dictionary + searchableSurfaces(const IOobject&, const dictionary&); + + + // Member Functions + + const wordList& names() const + { + return names_; + } + wordList& names() + { + return names_; + } + + const List<wordList>& regionNames() const + { + return regionNames_; + } + List<wordList>& regionNames() + { + return regionNames_; + } + + + ////- If adding surfaces 'by hand' + //HashTable<labelPair>& regionNames() + //{ + // return regionNames_; + //} + ////- Get surface and region for a name + //const labelPair& surfaceRegion(const word& globalRegion) const + //{ + // return regionNames_[globalRegion]; + //} + + //- Find index of surface. Return -1 if not found. + label findSurfaceID(const word& name) const; + + + // Multiple point queries. + + //- Find any intersection. Return hit point information and + // surface number. If multiple surfaces hit the first surface + // is returned, not necessarily the nearest (to start). + void findAnyIntersection + ( + const pointField& start, + const pointField& end, + labelList& surfaces, + List<pointIndexHit>& + ) const; + + //- Find all intersections in order from start to end. Returns for + // every hit the surface and the hit info. + void findAllIntersections + ( + const pointField& start, + const pointField& end, + labelListList& surfaces, + List<List<pointIndexHit> >& surfaceHits + ) const; + + //- Find nearest. Return -1 (and a miss()) or surface and nearest + // point. + void findNearest + ( + const pointField&, + const scalarField& nearestDistSqr, + labelList& surfaces, + List<pointIndexHit>& + ) const; + + + // Single point queries + + //- Calculate point which is on a set of surfaces. + pointIndexHit facesIntersection + ( + const scalar initialDistSqr, + const scalar convergenceDistSqr, + const point& start + ) const; + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/meshTools/searchableSurface/searchableSurfacesQueries.C b/src/meshTools/searchableSurface/searchableSurfacesQueries.C new file mode 100644 index 0000000000000000000000000000000000000000..7d7c6c2c1b09de2d59cadb67fc0f3e86b9118b41 --- /dev/null +++ b/src/meshTools/searchableSurface/searchableSurfacesQueries.C @@ -0,0 +1,822 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*----------------------------------------------------------------------------*/ + +#include "searchableSurfacesQueries.H" +#include "SortableList.H" +#include "OFstream.H" +#include "meshTools.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +defineTypeNameAndDebug(searchableSurfacesQueries, 0); + +} + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +Foam::pointIndexHit Foam::searchableSurfacesQueries::tempFindNearest +( + const searchableSurface& surf, + const point& pt, + const scalar initDistSqr +) +{ + pointField onePoint(1, pt); + scalarField oneDist(1, initDistSqr); + List<pointIndexHit> oneHit(1); + surf.findNearest(onePoint, oneDist, oneHit); + return oneHit[0]; +} + + +// Calculate sum of distance to surfaces. +Foam::scalar Foam::searchableSurfacesQueries::sumDistSqr +( + const PtrList<searchableSurface>& allSurfaces, + const labelList& surfacesToTest, + const scalar initDistSqr, + const point& pt +) +{ + scalar sum = 0; + + forAll(surfacesToTest, testI) + { + label surfI = surfacesToTest[testI]; + + pointIndexHit hit + ( + tempFindNearest(allSurfaces[surfI], pt, initDistSqr) + ); + + // Note: make it fall over if not hit. + sum += magSqr(hit.hitPoint()-pt); + } + return sum; +} + + +// Reflects the point furthest away around the triangle centre by a factor fac. +// (triangle centre is the average of all points but the ihi. pSum is running +// sum of all points) +Foam::scalar Foam::searchableSurfacesQueries::tryMorphTet +( + const PtrList<searchableSurface>& allSurfaces, + const labelList& surfacesToTest, + const scalar initDistSqr, + List<vector>& p, + List<scalar>& y, + vector& pSum, + const label ihi, + const scalar fac +) +{ + scalar fac1 = (1.0-fac)/vector::nComponents; + scalar fac2 = fac1-fac; + + vector ptry = pSum*fac1-p[ihi]*fac2; + + scalar ytry = sumDistSqr(allSurfaces, surfacesToTest, initDistSqr, ptry); + + if (ytry < y[ihi]) + { + y[ihi] = ytry; + pSum += ptry - p[ihi]; + p[ihi] = ptry; + } + return ytry; +} + + +bool Foam::searchableSurfacesQueries::morphTet +( + const PtrList<searchableSurface>& allSurfaces, + const labelList& surfacesToTest, + const scalar initDistSqr, + const scalar convergenceDistSqr, + const label maxIter, + List<vector>& p, + List<scalar>& y +) +{ + vector pSum = sum(p); + + autoPtr<OFstream> str; + label vertI = 0; + if (debug) + { + wordList names(surfacesToTest.size()); + forAll(surfacesToTest, i) + { + names[i] = allSurfaces[surfacesToTest[i]].name(); + } + Pout<< "searchableSurfacesQueries::morphTet : intersection of " + << names << " starting from points:" << p << endl; + str.reset(new OFstream("track.obj")); + meshTools::writeOBJ(str(), p[0]); + vertI++; + } + + for (label iter = 0; iter < maxIter; iter++) + { + // Get the indices of highest, second-highest and lowest values. + label ihi, inhi, ilo; + { + SortableList<scalar> sortedY(y); + ilo = sortedY.indices()[0]; + ihi = sortedY.indices()[sortedY.size()-1]; + inhi = sortedY.indices()[sortedY.size()-2]; + } + + if (debug) + { + Pout<< "Iteration:" << iter + << " lowest:" << y[ilo] << " highest:" << y[ihi] + << " points:" << p << endl; + + meshTools::writeOBJ(str(), p[ilo]); + vertI++; + str()<< "l " << vertI-1 << ' ' << vertI << nl; + } + + if (y[ihi] < convergenceDistSqr) + { + // Get point on 0th surface. + Swap(p[0], p[ilo]); + Swap(y[0], y[ilo]); + return true; + } + + // Reflection: point furthest away gets reflected. + scalar ytry = tryMorphTet + ( + allSurfaces, + surfacesToTest, + 10*y[ihi], // search box. + p, + y, + pSum, + ihi, + -1.0 + ); + + if (ytry <= y[ilo]) + { + // If in right direction (y lower) expand by two. + ytry = tryMorphTet + ( + allSurfaces, + surfacesToTest, + 10*y[ihi], + p, + y, + pSum, + ihi, + 2.0 + ); + } + else if (ytry >= y[inhi]) + { + // If inside tet try contraction. + + scalar ysave = y[ihi]; + + ytry = tryMorphTet + ( + allSurfaces, + surfacesToTest, + 10*y[ihi], + p, + y, + pSum, + ihi, + 0.5 + ); + + if (ytry >= ysave) + { + // Contract around lowest point. + forAll(p, i) + { + if (i != ilo) + { + p[i] = 0.5*(p[i] + p[ilo]); + y[i] = sumDistSqr + ( + allSurfaces, + surfacesToTest, + y[ihi], + p[i] + ); + } + } + pSum = sum(p); + } + } + } + + if (debug) + { + meshTools::writeOBJ(str(), p[0]); + vertI++; + str()<< "l " << vertI-1 << ' ' << vertI << nl; + } + + // Failure to converge. Return best guess so far. + label ilo = findMin(y); + Swap(p[0], p[ilo]); + Swap(y[0], y[ilo]); + return false; +} + + +//// Get all intersections (in order) for single surface. +//void Foam::searchableSurfacesQueries::findAllIntersections +//( +// const searchableSurface& s, +// const pointField& start, +// const pointField& end, +// const vectorField& smallVec, +// List<List<pointIndexHit> >& surfaceHitInfo +//) +//{ +// surfaceHitInfo.setSize(start.size()); +// +// // Current start point of vector +// pointField p0(start); +// +// List<pointIndexHit> intersectInfo(start.size()); +// +// // For test whether finished doing vector. +// const vectorField dirVec(end-start); +// const scalarField magSqrDirVec(magSqr(dirVec)); +// +// while (true) +// { +// // Find first intersection. Synced. +// s.findLine(p0, end, intersectInfo); +// +// label nHits = 0; +// +// forAll(intersectInfo, i) +// { +// if (intersectInfo[i].hit()) +// { +// nHits++; +// +// label sz = surfaceHitInfo[i].size(); +// surfaceHitInfo[i].setSize(sz+1); +// surfaceHitInfo[i][sz] = intersectInfo[i]; +// +// p0[i] = intersectInfo[i].hitPoint() + smallVec[i]; +// +// // If beyond endpoint set to endpoint so as not to pick up +// // any intersections. Could instead just filter out hits. +// if (((p0[i]-start[i])&dirVec[i]) > magSqrDirVec[i]) +// { +// p0[i] = end[i]; +// } +// } +// else +// { +// // Set to endpoint to stop intersection test. See above. +// p0[i] = end[i]; +// } +// } +// +// // returnReduce(nHits) ? +// if (nHits == 0) +// { +// break; +// } +// } +//} + + +// Given current set of hits (allSurfaces, allInfo) merge in those coming from +// surface surfI. +void Foam::searchableSurfacesQueries::mergeHits +( + const point& start, + const scalar mergeDist, + + const label testI, // index of surface + const List<pointIndexHit>& surfHits, // hits on surface + + labelList& allSurfaces, + List<pointIndexHit>& allInfo, + scalarList& allDistSqr +) +{ + // Precalculate distances + scalarList surfDistSqr(surfHits.size()); + forAll(surfHits, i) + { + surfDistSqr[i] = magSqr(surfHits[i].hitPoint()-start); + } + + forAll(surfDistSqr, i) + { + label index = findLower(allDistSqr, surfDistSqr[i]); + + // Check if equal to lower. + if + ( + index >= 0 + && (mag(allDistSqr[index]-surfDistSqr[i]) < mergeDist) + ) + { + // Same. Do not count. + //Pout<< "point:" << surfHits[i].hitPoint() + // << " considered same as:" << allInfo[index].hitPoint() + // << " within tol:" << mergeDist + // << endl; + } + else + { + // Check if equal to higher + label next = index+1; + if + ( + next < allDistSqr.size() + && (mag(allDistSqr[next]-surfDistSqr[i]) < mergeDist) + ) + { + //Pout<< "point:" << surfHits[i].hitPoint() + // << " considered same as:" << allInfo[next].hitPoint() + // << " within tol:" << mergeDist + // << endl; + } + else + { + // Insert after index + label sz = allSurfaces.size(); + allSurfaces.setSize(sz+1); + allInfo.setSize(allSurfaces.size()); + allDistSqr.setSize(allSurfaces.size()); + // Make space. + for (label j = sz-1; j > index; --j) + { + allSurfaces[j+1] = allSurfaces[j]; + allInfo[j+1] = allInfo[j]; + allDistSqr[j+1] = allDistSqr[j]; + } + // Insert new value + allSurfaces[index+1] = testI; + allInfo[index+1] = surfHits[i]; + allDistSqr[index+1] = surfDistSqr[i]; + } + } + } +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +// Find any intersection +void Foam::searchableSurfacesQueries::findAnyIntersection +( + const PtrList<searchableSurface>& allSurfaces, + const labelList& surfacesToTest, + const pointField& start, + const pointField& end, + labelList& hitSurfaces, + List<pointIndexHit>& hitInfo +) +{ + hitSurfaces.setSize(start.size()); + hitSurfaces = -1; + hitInfo.setSize(start.size()); + + // Work arrays + labelList hitMap(identity(start.size())); + pointField p0(start); + pointField p1(end); + List<pointIndexHit> intersectInfo(start.size()); + + forAll(surfacesToTest, testI) + { + // Do synchronised call to all surfaces. + allSurfaces[surfacesToTest[testI]].findLineAny(p0, p1, intersectInfo); + + // Copy all hits into arguments, continue with misses + label newI = 0; + forAll(intersectInfo, i) + { + if (intersectInfo[i].hit()) + { + hitInfo[hitMap[i]] = intersectInfo[i]; + hitSurfaces[hitMap[i]] = testI; + } + else + { + if (i != newI) + { + hitMap[newI] = hitMap[i]; + p0[newI] = p0[i]; + p1[newI] = p1[i]; + } + newI++; + } + } + + // All done? Note that this decision should be synchronised + if (newI == 0) + { + break; + } + + // Trim and continue + hitMap.setSize(newI); + p0.setSize(newI); + p1.setSize(newI); + intersectInfo.setSize(newI); + } +} + + +void Foam::searchableSurfacesQueries::findAllIntersections +( + const PtrList<searchableSurface>& allSurfaces, + const labelList& surfacesToTest, + const pointField& start, + const pointField& end, + labelListList& hitSurfaces, + List<List<pointIndexHit> >& hitInfo +) +{ + // Note: maybe move the single-surface all intersections test into + // searchable surface? Some of the tolerance issues might be + // lessened. + + // 2. Currently calling searchableSurface::findLine with start==end + // is expected to find no intersection. Problem if it does. + + hitSurfaces.setSize(start.size()); + hitInfo.setSize(start.size()); + + if (surfacesToTest.size() == 0) + { + return; + } + + // Test first surface + allSurfaces[surfacesToTest[0]].findLineAll(start, end, hitInfo); + + // Set hitSurfaces and distance + List<scalarList> hitDistSqr(hitInfo.size()); + forAll(hitInfo, pointI) + { + const List<pointIndexHit>& pHits = hitInfo[pointI]; + + labelList& pSurfaces = hitSurfaces[pointI]; + pSurfaces.setSize(pHits.size()); + pSurfaces = 0; + + scalarList& pDistSqr = hitDistSqr[pointI]; + pDistSqr.setSize(pHits.size()); + forAll(pHits, i) + { + pDistSqr[i] = magSqr(pHits[i].hitPoint() - start[pointI]); + } + } + + + if (surfacesToTest.size() > 1) + { + // Small vector to increment start vector by to find next intersection + // along line. Constant factor added to make sure that start==end still + // ends iteration in findAllIntersections. Also SMALL is just slightly + // too small. + const vectorField smallVec + ( + 1E2*SMALL*(end-start) + + vector(ROOTVSMALL,ROOTVSMALL,ROOTVSMALL) + ); + + // Tolerance used to check whether points are equal. Note: used to + // compare distance^2. Note that we use the maximum possible tolerance + // (reached at intersections close to the end point) + const scalarField mergeDist(2*mag(smallVec)*mag(end-start)); + + // Test the other surfaces and merge (according to distance from start). + for (label testI = 1; testI < surfacesToTest.size(); testI++) + { + List<List<pointIndexHit> > surfHits; + allSurfaces[surfacesToTest[testI]].findLineAll + ( + start, + end, + surfHits + ); + + forAll(surfHits, pointI) + { + mergeHits + ( + start[pointI], // Current segment + mergeDist[pointI], + + testI, // Surface and its hits + surfHits[pointI], + + hitSurfaces[pointI], // Merge into overall hit info + hitInfo[pointI], + hitDistSqr[pointI] + ); + } + } + } +} + + +//// Find intersections of edge nearest to both endpoints. +//void Foam::searchableSurfacesQueries::findNearestIntersection +//( +// const PtrList<searchableSurface>& allSurfaces, +// const labelList& surfacesToTest, +// const pointField& start, +// const pointField& end, +// +// labelList& surface1, +// List<pointIndexHit>& hit1, +// labelList& surface2, +// List<pointIndexHit>& hit2 +//) +//{ +// // 1. intersection from start to end +// // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// // Initialize arguments +// surface1.setSize(start.size()); +// surface1 = -1; +// hit1.setSize(start.size()); +// +// // Current end of segment to test. +// pointField nearest(end); +// // Work array +// List<pointIndexHit> nearestInfo(start.size()); +// +// forAll(surfacesToTest, testI) +// { +// // See if any intersection between start and current nearest +// allSurfaces[surfacesToTest[testI]].findLine +// ( +// start, +// nearest, +// nearestInfo +// ); +// +// forAll(nearestInfo, pointI) +// { +// if (nearestInfo[pointI].hit()) +// { +// hit1[pointI] = nearestInfo[pointI]; +// surface1[pointI] = testI; +// nearest[pointI] = hit1[pointI].hitPoint(); +// } +// } +// } +// +// +// // 2. intersection from end to last intersection +// // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// // Find the nearest intersection from end to start. Note that we +// // initialize to the first intersection (if any). +// surface2 = surface1; +// hit2 = hit1; +// +// // Set current end of segment to test. +// forAll(nearest, pointI) +// { +// if (hit1[pointI].hit()) +// { +// nearest[pointI] = hit1[pointI].hitPoint(); +// } +// else +// { +// // Disable testing by setting to end. +// nearest[pointI] = end[pointI]; +// } +// } +// +// forAll(surfacesToTest, testI) +// { +// // See if any intersection between end and current nearest +// allSurfaces[surfacesToTest[i]].findLine(end, nearest, nearestInfo); +// +// forAll(nearestInfo, pointI) +// { +// if (nearestInfo[pointI].hit()) +// { +// hit2[pointI] = nearestInfo[pointI]; +// surface2[pointI] = testI; +// nearest[pointI] = hit2[pointI].hitPoint(); +// } +// } +// } +//} + + +// Find nearest. Return -1 or nearest point +void Foam::searchableSurfacesQueries::findNearest +( + const PtrList<searchableSurface>& allSurfaces, + const labelList& surfacesToTest, + const pointField& samples, + const scalarField& nearestDistSqr, + labelList& nearestSurfaces, + List<pointIndexHit>& nearestInfo +) +{ + // Initialise + nearestSurfaces.setSize(samples.size()); + nearestSurfaces = -1; + nearestInfo.setSize(samples.size()); + + // Work arrays + scalarField minDistSqr(nearestDistSqr); + List<pointIndexHit> hitInfo(samples.size()); + + forAll(surfacesToTest, testI) + { + allSurfaces[surfacesToTest[testI]].findNearest + ( + samples, + minDistSqr, + hitInfo + ); + + // Update minDistSqr and arguments + forAll(hitInfo, pointI) + { + if (hitInfo[pointI].hit()) + { + minDistSqr[pointI] = magSqr + ( + hitInfo[pointI].hitPoint() + - samples[pointI] + ); + nearestInfo[pointI] = hitInfo[pointI]; + nearestSurfaces[pointI] = testI; + } + } + } +} + + +//- Calculate point which is on a set of surfaces. +Foam::pointIndexHit Foam::searchableSurfacesQueries::facesIntersection +( + const PtrList<searchableSurface>& allSurfaces, + const labelList& surfacesToTest, + const scalar initDistSqr, + const scalar convergenceDistSqr, + const point& start +) +{ + // Get four starting points. Take these as the projection of the + // starting point onto the surfaces and the mid point + List<point> nearest(surfacesToTest.size()+1); + + point sumNearest = vector::zero; + + forAll(surfacesToTest, i) + { + pointIndexHit hit + ( + tempFindNearest(allSurfaces[surfacesToTest[i]], start, initDistSqr) + ); + + if (hit.hit()) + { + nearest[i] = hit.hitPoint(); + sumNearest += nearest[i]; + } + else + { + FatalErrorIn + ( + "searchableSurfacesQueries::facesIntersection" + "(const labelList&, const scalar, const scalar, const point&)" + ) << "Did not find point within distance " + << initDistSqr << " of starting point " << start + << " on surface " + << allSurfaces[surfacesToTest[i]].IOobject::name() + << abort(FatalError); + } + } + + nearest[nearest.size()-1] = sumNearest / surfacesToTest.size(); + + + // Get the sum of distances (initial evaluation) + List<scalar> nearestDist(nearest.size()); + + forAll(nearestDist, i) + { + nearestDist[i] = sumDistSqr + ( + allSurfaces, + surfacesToTest, + initDistSqr, + nearest[i] + ); + } + + + //- Downhill Simplex method + + bool converged = morphTet + ( + allSurfaces, + surfacesToTest, + initDistSqr, + convergenceDistSqr, + 2000, + nearest, + nearestDist + ); + + + pointIndexHit intersection; + + if (converged) + { + // Project nearest onto 0th surface. + intersection = tempFindNearest + ( + allSurfaces[surfacesToTest[0]], + nearest[0], + nearestDist[0] + ); + } + + //if (!intersection.hit()) + //{ + // // Restart + // scalar smallDist = Foam::sqr(convergenceDistSqr); + // nearest[0] = intersection.hitPoint(); + // nearest[1] = nearest[0]; + // nearest[1].x() += smallDist; + // nearest[2] = nearest[0]; + // nearest[2].y() += smallDist; + // nearest[3] = nearest[0]; + // nearest[3].z() += smallDist; + // + // forAll(nearestDist, i) + // { + // nearestDist[i] = sumDistSqr + // ( + // surfacesToTest, + // initDistSqr, + // nearest[i] + // ); + // } + // + // intersection = morphTet + // ( + // allSurfaces, + // surfacesToTest, + // initDistSqr, + // convergenceDistSqr, + // 1000, + // nearest, + // nearestDist + // ); + //} + + return intersection; +} + + + +// ************************************************************************* // diff --git a/src/meshTools/searchableSurface/searchableSurfacesQueries.H b/src/meshTools/searchableSurface/searchableSurfacesQueries.H new file mode 100644 index 0000000000000000000000000000000000000000..dcb84050a6f56bbf6399262c55650ea7196d0eb2 --- /dev/null +++ b/src/meshTools/searchableSurface/searchableSurfacesQueries.H @@ -0,0 +1,198 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Class + Foam::searchableSurfacesQueries + +Description + A collection of tools for searchableSurfaces. + +SourceFiles + searchableSurfacesQueries.C + +\*---------------------------------------------------------------------------*/ + +#ifndef searchableSurfacesQueries_H +#define searchableSurfacesQueries_H + +#include "searchableSurface.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward declaration of classes +class plane; + +/*---------------------------------------------------------------------------*\ + Class searchableSurfacesQueries Declaration +\*---------------------------------------------------------------------------*/ + +class searchableSurfacesQueries +{ + // Private data + + // Private Member Functions + + //- Temporary wrapper around findNearest. Used in facesIntersection only + static pointIndexHit tempFindNearest + ( + const searchableSurface&, + const point& pt, + const scalar initDistSqr + ); + + //- Calculate sum of distances to nearest point on surfaces. Is used + // in minimisation to find intersection. Returns sum of (square of) + // distances to the surfaces. + static scalar sumDistSqr + ( + const PtrList<searchableSurface>&, + const labelList& surfacesToTest, + const scalar initialDistSqr, // search box + const point& pt + ); + + //- Takes the tet (points p) and reflects the point with the + // highest value around the centre (pSum). Checks if it gets closer + // and updates p, y if so. + static scalar tryMorphTet + ( + const PtrList<searchableSurface>&, + const labelList& surfacesToTest, + const scalar initialDistSqr, + List<vector>& p, + List<scalar>& y, + vector& pSum, + const label ihi, + const scalar fac + ); + + //- Downhill simplex method: find the point with min cumulative + // distance to all surfaces. Does so by morphing a tet (points p). + // Returns the point on the 0th surface or hit if not reached within + // maxIters iterations. + static bool morphTet + ( + const PtrList<searchableSurface>&, + const labelList& surfacesToTest, + const scalar initialDistSqr, + const scalar convergenceDistSqr, + const label maxIter, + List<vector>& p, + List<scalar>& y + ); + + //static void findAllIntersections + //( + // const searchableSurface& s, + // const pointField& start, + // const pointField& end, + // const vectorField& smallVec, + // List<List<pointIndexHit> >& + //); + + static void mergeHits + ( + const point& start, + const scalar mergeDist, + + const label surfI, + const List<pointIndexHit>& surfHits, + + labelList& allSurfaces, + List<pointIndexHit>& allInfo, + scalarList& allDistSqr + ); + +public: + + // Declare name of the class and its debug switch + ClassName("searchableSurfacesQueries"); + + + // Multiple point queries. + + //- Find any intersection. Return hit point information and + // index in surfacesToTest. If multiple surfaces hit the first + // surface is returned, not necessarily the nearest (to start). + static void findAnyIntersection + ( + const PtrList<searchableSurface>&, + const labelList& surfacesToTest, + const pointField& start, + const pointField& end, + labelList& surfaces, + List<pointIndexHit>& + ); + + //- Find all intersections in order from start to end. Returns for + // every hit the index in surfacesToTest and the hit info. + static void findAllIntersections + ( + const PtrList<searchableSurface>&, + const labelList& surfacesToTest, + const pointField& start, + const pointField& end, + labelListList& surfaces, + List<List<pointIndexHit> >& surfaceHits + ); + + //- Find nearest. Return -1 (and a miss()) or surface and nearest + // point. + static void findNearest + ( + const PtrList<searchableSurface>&, + const labelList& surfacesToTest, + const pointField&, + const scalarField& nearestDistSqr, + labelList& surfaces, + List<pointIndexHit>& + ); + + + // Single point queries + + //- Calculate point which is on a set of surfaces. WIP. + static pointIndexHit facesIntersection + ( + const PtrList<searchableSurface>& allSurfaces, + const labelList& surfacesToTest, + const scalar initDistSqr, + const scalar convergenceDistSqr, + const point& start + ); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/meshTools/searchableSurface/triSurfaceMesh.C b/src/meshTools/searchableSurface/triSurfaceMesh.C new file mode 100644 index 0000000000000000000000000000000000000000..526646c01460b5d6ec4014efb316cb2bd44104a1 --- /dev/null +++ b/src/meshTools/searchableSurface/triSurfaceMesh.C @@ -0,0 +1,552 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*---------------------------------------------------------------------------*/ + +#include "triSurfaceMesh.H" +#include "Random.H" +#include "addToRunTimeSelectionTable.H" +#include "EdgeMap.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ + +defineTypeNameAndDebug(triSurfaceMesh, 0); +addToRunTimeSelectionTable(searchableSurface, triSurfaceMesh, dict); + +} + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +//- Check file existence +const Foam::fileName& Foam::triSurfaceMesh::checkFile +( + const fileName& fName, + const fileName& objectName +) +{ + if (fName == fileName::null) + { + FatalErrorIn + ( + "triSurfaceMesh::checkFile(const fileName&, const fileName&)" + ) << "Cannot find triSurfaceMesh starting from " + << objectName << exit(FatalError); + } + return fName; +} + + +bool Foam::triSurfaceMesh::isSurfaceClosed() const +{ + // Construct pointFaces. Let's hope surface has compact point + // numbering ... + labelListList pointFaces; + invertManyToMany(points().size(), *this, pointFaces); + + // Loop over all faces surrounding point. Count edges emanating from point. + // Every edge should be used by two faces exactly. + // To prevent doing work twice per edge only look at edges to higher + // point + EdgeMap<label> facesPerEdge(100); + forAll(pointFaces, pointI) + { + const labelList& pFaces = pointFaces[pointI]; + + facesPerEdge.clear(); + forAll(pFaces, i) + { + const labelledTri& f = triSurface::operator[](pFaces[i]); + label fp = findIndex(f, pointI); + + // Forward edge + { + label p1 = f[f.fcIndex(fp)]; + + if (p1 > pointI) + { + const edge e(pointI, p1); + EdgeMap<label>::iterator eFnd = facesPerEdge.find(e); + if (eFnd != facesPerEdge.end()) + { + if (eFnd() == 2) + { + return false; + } + eFnd()++; + } + else + { + facesPerEdge.insert(e, 1); + } + } + } + // Reverse edge + { + label p1 = f[f.rcIndex(fp)]; + + if (p1 > pointI) + { + const edge e(pointI, p1); + EdgeMap<label>::iterator eFnd = facesPerEdge.find(e); + if (eFnd != facesPerEdge.end()) + { + if (eFnd() == 2) + { + return false; + } + eFnd()++; + } + else + { + facesPerEdge.insert(e, 1); + } + } + } + } + + // Check for any edges used only once. + forAllConstIter(EdgeMap<label>, facesPerEdge, iter) + { + if (iter() != 2) + { + return false; + } + } + } + + return true; +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::triSurfaceMesh::triSurfaceMesh(const IOobject& io, const triSurface& s) +: + searchableSurface(io), + objectRegistry(io), + triSurface(s), + surfaceClosed_(-1) +{} + + +Foam::triSurfaceMesh::triSurfaceMesh(const IOobject& io) +: + searchableSurface(io), + objectRegistry(io), + triSurface + ( + checkFile + ( + searchableSurface::filePath(), + searchableSurface::objectPath() + ) + ), + surfaceClosed_(-1) +{} + + +Foam::triSurfaceMesh::triSurfaceMesh +( + const IOobject& io, + const dictionary& dict +) +: + searchableSurface(io), + objectRegistry(io), + triSurface + ( + checkFile + ( + searchableSurface::filePath(), + searchableSurface::objectPath() + ) + ), + surfaceClosed_(-1) +{} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::triSurfaceMesh::~triSurfaceMesh() +{ + clearOut(); +} + + +void Foam::triSurfaceMesh::clearOut() +{ + tree_.clear(); + edgeTree_.clear(); + triSurface::clearOut(); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::triSurfaceMesh::movePoints(const pointField& newPoints) +{ + tree_.clear(); + edgeTree_.clear(); + triSurface::movePoints(newPoints); +} + + +const Foam::indexedOctree<Foam::treeDataTriSurface>& + Foam::triSurfaceMesh::tree() const +{ + if (!tree_.valid()) + { + treeBoundBox bb(points(), meshPoints()); + + // Random number generator. Bit dodgy since not exactly random ;-) + Random rndGen(65431); + + tree_.reset + ( + new indexedOctree<treeDataTriSurface> + ( + treeDataTriSurface(*this), + bb.extend(rndGen, 1E-3), // slightly randomize bb + 10, // maxLevel + 10, // leafsize + 3.0 // duplicity + ) + ); + } + + return tree_(); +} + + +const Foam::indexedOctree<Foam::treeDataEdge>& + Foam::triSurfaceMesh::edgeTree() const +{ + if (!edgeTree_.valid()) + { + treeBoundBox bb(localPoints()); + + // Boundary edges + labelList bEdges + ( + identity + ( + nEdges() + -nInternalEdges() + ) + + nInternalEdges() + ); + + // Random number generator. Bit dodgy since not exactly random ;-) + Random rndGen(65431); + + edgeTree_.reset + ( + new indexedOctree<treeDataEdge> + ( + treeDataEdge + ( + false, // cachebb + edges(), // edges + localPoints(), // points + bEdges // selected edges + ), + bb.extend(rndGen, 1E-3), // slightly randomize bb + 8, // maxLevel + 10, // leafsize + 3.0 // duplicity + ) + ); + } + return edgeTree_(); +} + + +const Foam::wordList& Foam::triSurfaceMesh::regions() const +{ + if (regions_.size() == 0) + { + regions_.setSize(patches().size()); + forAll(regions_, regionI) + { + regions_[regionI] = patches()[regionI].name(); + } + } + return regions_; +} + + +//Foam::pointIndexHit Foam::triSurfaceMesh::findNearest +//( +// const point& sample, +// const scalar nearestDistSqr +//) const +//{ +// return tree().findNearest(sample, nearestDistSqr); +//} +// +// +//Foam::pointIndexHit Foam::triSurfaceMesh::findNearestOnEdge +//( +// const point& sample, +// const scalar nearestDistSqr +//) const +//{ +// return = edgeTree().findNearest(sample, nearestDistSqr); +//} +// +// +//Foam::pointIndexHit Foam::triSurfaceMesh::findNearest +//( +// const linePointRef& ln, +// treeBoundBox& tightest, +// point& linePoint +//) const +//{ +// return tree().findNearest(ln, tightest, linePoint); +//} +// +// +//Foam::pointIndexHit Foam::triSurfaceMesh::findLine +//( +// const point& start, +// const point& end +//) const +//{ +// return tree().findLine(start, end); +//} +// +// +//Foam::pointIndexHit Foam::triSurfaceMesh::findLineAny +//( +// const point& start, +// const point& end +//) const +//{ +// return tree().findLineAny(start, end); +//} + + +// Find out if surface is closed. +bool Foam::triSurfaceMesh::hasVolumeType() const +{ + if (surfaceClosed_ == -1) + { + if (isSurfaceClosed()) + { + surfaceClosed_ = 1; + } + else + { + surfaceClosed_ = 0; + } + } + + return surfaceClosed_ == 1; +} + + +void Foam::triSurfaceMesh::findNearest +( + const pointField& samples, + const scalarField& nearestDistSqr, + List<pointIndexHit>& info +) const +{ + const indexedOctree<treeDataTriSurface>& octree = tree(); + + info.setSize(samples.size()); + + forAll(samples, i) + { + static_cast<pointIndexHit&>(info[i]) = + octree.findNearest(samples[i], nearestDistSqr[i]); + } +} + + +void Foam::triSurfaceMesh::findLine +( + const pointField& start, + const pointField& end, + List<pointIndexHit>& info +) const +{ + const indexedOctree<treeDataTriSurface>& octree = tree(); + + info.setSize(start.size()); + + forAll(start, i) + { + static_cast<pointIndexHit&>(info[i]) = octree.findLine + ( + start[i], + end[i] + ); + } +} + + +void Foam::triSurfaceMesh::findLineAny +( + const pointField& start, + const pointField& end, + List<pointIndexHit>& info +) const +{ + const indexedOctree<treeDataTriSurface>& octree = tree(); + + info.setSize(start.size()); + + forAll(start, i) + { + static_cast<pointIndexHit&>(info[i]) = + octree.findLineAny(start[i], end[i]); + } +} + + +void Foam::triSurfaceMesh::findLineAll +( + const pointField& start, + const pointField& end, + List<List<pointIndexHit> >& info +) const +{ + const indexedOctree<treeDataTriSurface>& octree = tree(); + + info.setSize(start.size()); + + // Work array + DynamicList<pointIndexHit, 1, 1> hits; + + // Tolerances + const vectorField dirVec(end-start); + const scalarField magSqrDirVec(magSqr(dirVec)); + const vectorField smallVec + ( + Foam::sqrt(SMALL)*dirVec + + vector(ROOTVSMALL,ROOTVSMALL,ROOTVSMALL) + ); + + forAll(start, pointI) + { + hits.clear(); + + // Current starting point of ray. + point pt = start[pointI]; + + while (true) + { + // See if any intersection between pt and end + pointIndexHit inter = octree.findLine(pt, end[pointI]); + + if (!inter.hit()) + { + break; + } + hits.append(inter); + + pt = inter.hitPoint() + smallVec[pointI]; + + if (((pt-start[pointI])&dirVec[pointI]) > magSqrDirVec[pointI]) + { + // Adding smallVec has taken us beyond end + break; + } + } + + hits.shrink(); + info[pointI].transfer(hits); + hits.clear(); + } +} + + +void Foam::triSurfaceMesh::getRegion +( + const List<pointIndexHit>& info, + labelList& region +) const +{ + region.setSize(info.size()); + forAll(info, i) + { + if (info[i].hit()) + { + region[i] = triSurface::operator[](info[i].index()).region(); + } + else + { + region[i] = -1; + } + } +} + + +void Foam::triSurfaceMesh::getNormal +( + const List<pointIndexHit>& info, + vectorField& normal +) const +{ + normal.setSize(info.size()); + + forAll(info, i) + { + if (info[i].hit()) + { + normal[i] = faceNormals()[info[i].index()]; + } + else + { + // Set to what? + normal[i] = vector::zero; + } + } +} + + +void Foam::triSurfaceMesh::getVolumeType +( + const pointField& points, + List<volumeType>& volType +) const +{ + volType.setSize(points.size()); + + forAll(points, pointI) + { + const point& pt = points[pointI]; + + // - use cached volume type per each tree node + // - cheat conversion since same values + volType[pointI] = static_cast<volumeType>(tree().getVolumeType(pt)); + } +} + + +// ************************************************************************* // diff --git a/src/meshTools/triSurface/searchableSurface/triSurfaceMesh.H b/src/meshTools/searchableSurface/triSurfaceMesh.H similarity index 64% rename from src/meshTools/triSurface/searchableSurface/triSurfaceMesh.H rename to src/meshTools/searchableSurface/triSurfaceMesh.H index 453b4daa6127456e0077e03568b8688212d6bb3a..1b9fa0c945838efc572700f15515aa51592c72b6 100644 --- a/src/meshTools/triSurface/searchableSurface/triSurfaceMesh.H +++ b/src/meshTools/searchableSurface/triSurfaceMesh.H @@ -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 @@ -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; + } }; diff --git a/src/meshTools/triSurface/searchableSurface/searchableBox.C b/src/meshTools/triSurface/searchableSurface/searchableBox.C deleted file mode 100644 index 77e48c3a8ee80f863675c3a4bb22e68fcc13dc30..0000000000000000000000000000000000000000 --- a/src/meshTools/triSurface/searchableSurface/searchableBox.C +++ /dev/null @@ -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 * * * * * * * * * * * * * // - - -// ************************************************************************* // diff --git a/src/meshTools/triSurface/searchableSurface/searchableBox.H b/src/meshTools/triSurface/searchableSurface/searchableBox.H deleted file mode 100644 index 4a347af46a9761629d4c2985392e0043320ce340..0000000000000000000000000000000000000000 --- a/src/meshTools/triSurface/searchableSurface/searchableBox.H +++ /dev/null @@ -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 - -// ************************************************************************* // diff --git a/src/meshTools/triSurface/searchableSurface/searchableSurface.H b/src/meshTools/triSurface/searchableSurface/searchableSurface.H deleted file mode 100644 index 83f7aaf929cd706ce97ae11560f2804c346018bd..0000000000000000000000000000000000000000 --- a/src/meshTools/triSurface/searchableSurface/searchableSurface.H +++ /dev/null @@ -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 - -// ************************************************************************* // diff --git a/src/meshTools/triSurface/searchableSurface/triSurfaceMesh.C b/src/meshTools/triSurface/searchableSurface/triSurfaceMesh.C deleted file mode 100644 index ec17352f99c0b27c3edaad00648b2b8eb290ac41..0000000000000000000000000000000000000000 --- a/src/meshTools/triSurface/searchableSurface/triSurfaceMesh.C +++ /dev/null @@ -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 * * * * * * * * * * * * * // - - -// ************************************************************************* // diff --git a/src/meshTools/triSurface/triSurfaceMeshes/triSurfaceMeshes.C b/src/meshTools/triSurface/triSurfaceMeshes/triSurfaceMeshes.C deleted file mode 100644 index e96c61885437063e78de33697f102120c08673fc..0000000000000000000000000000000000000000 --- a/src/meshTools/triSurface/triSurfaceMeshes/triSurfaceMeshes.C +++ /dev/null @@ -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; -} - - - -// ************************************************************************* // diff --git a/src/meshTools/triSurface/triSurfaceMeshes/triSurfaceMeshes.H b/src/meshTools/triSurface/triSurfaceMeshes/triSurfaceMeshes.H deleted file mode 100644 index 4269dba6a7bb4593adb7bc39d009e7d4fde7a38b..0000000000000000000000000000000000000000 --- a/src/meshTools/triSurface/triSurfaceMeshes/triSurfaceMeshes.H +++ /dev/null @@ -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 - -// ************************************************************************* //