FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

surfaceToCell.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2011 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 \*---------------------------------------------------------------------------*/
00025 
00026 #include "surfaceToCell.H"
00027 #include <OpenFOAM/polyMesh.H>
00028 #include <meshTools/meshSearch.H>
00029 #include <triSurface/triSurface.H>
00030 #include <meshTools/triSurfaceSearch.H>
00031 #include <meshTools/cellClassification.H>
00032 
00033 #include <OpenFOAM/addToRunTimeSelectionTable.H>
00034 
00035 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00036 
00037 namespace Foam
00038 {
00039 
00040 defineTypeNameAndDebug(surfaceToCell, 0);
00041 
00042 addToRunTimeSelectionTable(topoSetSource, surfaceToCell, word);
00043 
00044 addToRunTimeSelectionTable(topoSetSource, surfaceToCell, istream);
00045 
00046 }
00047 
00048 
00049 Foam::topoSetSource::addToUsageTable Foam::surfaceToCell::usage_
00050 (
00051     surfaceToCell::typeName,
00052     "\n    Usage: surfaceToCell"
00053     "<surface> <outsidePoints> <cut> <inside> <outside> <near> <curvature>\n\n"
00054     "    <surface> name of triSurface\n"
00055     "    <outsidePoints> list of points that define outside\n"
00056     "    <cut> boolean whether to include cells cut by surface\n"
00057     "    <inside>   ,,                 ,,       inside surface\n"
00058     "    <outside>  ,,                 ,,       outside surface\n"
00059     "    <near> scalar; include cells with centre <= near to surface\n"
00060     "    <curvature> scalar; include cells close to strong curvature"
00061     " on surface\n"
00062     "    (curvature defined as difference in surface normal at nearest"
00063     " point on surface for each vertex of cell)\n\n"
00064 );
00065 
00066 
00067 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00068 
00069 Foam::label Foam::surfaceToCell::getNearest
00070 (
00071     const triSurfaceSearch& querySurf,
00072     const label pointI,
00073     const point& pt,
00074     const vector& span,
00075     Map<label>& cache
00076 )
00077 {
00078     Map<label>::const_iterator iter = cache.find(pointI);
00079 
00080     if (iter != cache.end())
00081     {
00082         // Found cached answer
00083         return iter();
00084     }
00085     else
00086     {
00087         pointIndexHit inter = querySurf.nearest(pt, span);
00088 
00089         // Triangle label (can be -1)
00090         label triI = inter.index();
00091 
00092         // Store triangle on point
00093         cache.insert(pointI, triI);
00094 
00095         return triI;
00096     }
00097 }
00098 
00099 
00100 // Return true if nearest surface to points on cell makes largish angle
00101 // with nearest surface to cell centre. Returns false otherwise. Points visited
00102 // are cached in pointToNearest
00103 bool Foam::surfaceToCell::differingPointNormals
00104 (
00105     const triSurfaceSearch& querySurf,
00106 
00107     const vector& span,         // current search span
00108     const label cellI,
00109     const label cellTriI,       // nearest (to cell centre) surface triangle
00110 
00111     Map<label>& pointToNearest  // cache for nearest triangle to point
00112 ) const
00113 {
00114     const triSurface& surf = querySurf.surface();
00115     const vectorField& normals = surf.faceNormals();
00116 
00117     const faceList& faces = mesh().faces();
00118     const pointField& points = mesh().points();
00119 
00120     const labelList& cFaces = mesh().cells()[cellI];
00121 
00122     forAll(cFaces, cFaceI)
00123     {
00124         const face& f = faces[cFaces[cFaceI]];
00125 
00126         forAll(f, fp)
00127         {
00128             label pointI = f[fp];
00129 
00130             label pointTriI =
00131                 getNearest
00132                 (
00133                     querySurf,
00134                     pointI,
00135                     points[pointI],
00136                     span,
00137                     pointToNearest
00138                 );
00139 
00140             if (pointTriI != -1 && pointTriI != cellTriI)
00141             {
00142                 scalar cosAngle = normals[pointTriI] & normals[cellTriI];
00143 
00144                 if (cosAngle < 0.9)
00145                 {
00146                     return true;
00147                 }
00148             }
00149         }
00150     }
00151     return false;
00152 }
00153 
00154 
00155 void Foam::surfaceToCell::combine(topoSet& set, const bool add) const
00156 {
00157     cpuTime timer;
00158 
00159     if (includeCut_ || includeInside_ || includeOutside_)
00160     {
00161         //
00162         // Cut cells with surface and classify cells
00163         //
00164 
00165 
00166         // Construct search engine on mesh
00167 
00168         meshSearch queryMesh(mesh_, true);
00169 
00170 
00171         // Check all 'outside' points
00172         forAll(outsidePoints_, outsideI)
00173         {
00174             const point& outsidePoint = outsidePoints_[outsideI];
00175 
00176             // Find cell point is in. Linear search.
00177             label cellI = queryMesh.findCell(outsidePoint, -1, false);
00178             if (returnReduce(cellI, maxOp<label>()) == -1)
00179             {
00180                 FatalErrorIn("surfaceToCell::combine(topoSet&, const bool)")
00181                     << "outsidePoint " << outsidePoint
00182                     << " is not inside any cell"
00183                     << exit(FatalError);
00184             }
00185         }
00186 
00187         // Cut faces with surface and classify cells
00188 
00189         cellClassification cellType
00190         (
00191             mesh_,
00192             queryMesh,
00193             querySurf(),
00194             outsidePoints_
00195         );
00196 
00197 
00198         Info<< "    Marked inside/outside in = "
00199             << timer.cpuTimeIncrement() << " s" << endl << endl;
00200 
00201 
00202         forAll(cellType, cellI)
00203         {
00204             label cType = cellType[cellI];
00205 
00206             if
00207             (
00208                 (
00209                     includeCut_
00210                  && (cType == cellClassification::CUT)
00211                 )
00212              || (
00213                     includeInside_
00214                  && (cType == cellClassification::INSIDE)
00215                 )
00216              || (
00217                     includeOutside_
00218                  && (cType == cellClassification::OUTSIDE)
00219                 )
00220             )
00221             {
00222                 addOrDelete(set, cellI, add);
00223             }
00224         }
00225     }
00226 
00227 
00228     if (nearDist_ > 0)
00229     {
00230         //
00231         // Determine distance to surface
00232         //
00233 
00234         const pointField& ctrs = mesh_.cellCentres();
00235 
00236         // Box dimensions to search in octree.
00237         const vector span(nearDist_, nearDist_, nearDist_);
00238 
00239 
00240         if (curvature_ < -1)
00241         {
00242             Info<< "    Selecting cells with cellCentre closer than "
00243                 << nearDist_ << " to surface" << endl;
00244 
00245             // No need to test curvature. Insert near cells into set.
00246 
00247             forAll(ctrs, cellI)
00248             {
00249                 const point& c = ctrs[cellI];
00250 
00251                 pointIndexHit inter = querySurf().nearest(c, span);
00252 
00253                 if (inter.hit() && (mag(inter.hitPoint() - c) < nearDist_))
00254                 {
00255                     addOrDelete(set, cellI, add);
00256                 }
00257             }
00258 
00259             Info<< "    Determined nearest surface point in = "
00260                 << timer.cpuTimeIncrement() << " s" << endl << endl;
00261 
00262         }
00263         else
00264         {
00265             // Test near cells for curvature
00266 
00267             Info<< "    Selecting cells with cellCentre closer than "
00268                 << nearDist_ << " to surface and curvature factor"
00269                 << " less than " << curvature_ << endl;
00270 
00271             // Cache for nearest surface triangle for a point
00272             Map<label> pointToNearest(mesh_.nCells()/10);
00273 
00274             forAll(ctrs, cellI)
00275             {
00276                 const point& c = ctrs[cellI];
00277 
00278                 pointIndexHit inter = querySurf().nearest(c, span);
00279 
00280                 if (inter.hit() && (mag(inter.hitPoint() - c) < nearDist_))
00281                 {
00282                     if
00283                     (
00284                         differingPointNormals
00285                         (
00286                             querySurf(),
00287                             span,
00288                             cellI,
00289                             inter.index(),      // nearest surface triangle
00290                             pointToNearest
00291                         )
00292                     )
00293                     {
00294                         addOrDelete(set, cellI, add);
00295                     }
00296                 }
00297             }
00298 
00299             Info<< "    Determined nearest surface point in = "
00300                 << timer.cpuTimeIncrement() << " s" << endl << endl;
00301         }
00302     }
00303 }
00304 
00305 
00306 void Foam::surfaceToCell::checkSettings() const
00307 {
00308     if
00309     (
00310         (nearDist_ < 0)
00311      && (curvature_ < -1)
00312      && (
00313             (includeCut_ && includeInside_ && includeOutside_)
00314          || (!includeCut_ && !includeInside_ && !includeOutside_)
00315         )
00316     )
00317     {
00318         FatalErrorIn
00319         (
00320             "surfaceToCell:checkSettings()"
00321         )   << "Illegal include cell specification."
00322             << " Result would be either all or no cells." << endl
00323             << "Please set one of includeCut, includeInside, includeOutside"
00324             << " to true, set nearDistance to a value > 0"
00325             << " or set curvature to a value -1 .. 1."
00326             << exit(FatalError);
00327     }
00328 }
00329 
00330 
00331 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00332 
00333 // Construct from components
00334 Foam::surfaceToCell::surfaceToCell
00335 (
00336     const polyMesh& mesh,
00337     const fileName& surfName,
00338     const pointField& outsidePoints,
00339     const bool includeCut,
00340     const bool includeInside,
00341     const bool includeOutside,
00342     const scalar nearDist,
00343     const scalar curvature
00344 )
00345 :
00346     topoSetSource(mesh),
00347     surfName_(surfName),
00348     outsidePoints_(outsidePoints),
00349     includeCut_(includeCut),
00350     includeInside_(includeInside),
00351     includeOutside_(includeOutside),
00352     nearDist_(nearDist),
00353     curvature_(curvature),
00354     surfPtr_(new triSurface(surfName_)),
00355     querySurfPtr_(new triSurfaceSearch(*surfPtr_)),
00356     IOwnPtrs_(true)
00357 {
00358     checkSettings();
00359 }
00360 
00361 
00362 // Construct from components. Externally supplied surface.
00363 Foam::surfaceToCell::surfaceToCell
00364 (
00365     const polyMesh& mesh,
00366     const fileName& surfName,
00367     const triSurface& surf,
00368     const triSurfaceSearch& querySurf,
00369     const pointField& outsidePoints,
00370     const bool includeCut,
00371     const bool includeInside,
00372     const bool includeOutside,
00373     const scalar nearDist,
00374     const scalar curvature
00375 )
00376 :
00377     topoSetSource(mesh),
00378     surfName_(surfName),
00379     outsidePoints_(outsidePoints),
00380     includeCut_(includeCut),
00381     includeInside_(includeInside),
00382     includeOutside_(includeOutside),
00383     nearDist_(nearDist),
00384     curvature_(curvature),
00385     surfPtr_(&surf),
00386     querySurfPtr_(&querySurf),
00387     IOwnPtrs_(false)
00388 {
00389     checkSettings();
00390 }
00391 
00392 
00393 // Construct from dictionary
00394 Foam::surfaceToCell::surfaceToCell
00395 (
00396     const polyMesh& mesh,
00397     const dictionary& dict
00398 )
00399 :
00400     topoSetSource(mesh),
00401     surfName_(dict.lookup("file")),
00402     outsidePoints_(dict.lookup("outsidePoints")),
00403     includeCut_(readBool(dict.lookup("includeCut"))),
00404     includeInside_(readBool(dict.lookup("includeInside"))),
00405     includeOutside_(readBool(dict.lookup("includeOutside"))),
00406     nearDist_(readScalar(dict.lookup("nearDistance"))),
00407     curvature_(readScalar(dict.lookup("curvature"))),
00408     surfPtr_(new triSurface(surfName_)),
00409     querySurfPtr_(new triSurfaceSearch(*surfPtr_)),
00410     IOwnPtrs_(true)
00411 {
00412     checkSettings();
00413 }
00414 
00415 
00416 // Construct from Istream
00417 Foam::surfaceToCell::surfaceToCell
00418 (
00419     const polyMesh& mesh,
00420     Istream& is
00421 )
00422 :
00423     topoSetSource(mesh),
00424     surfName_(checkIs(is)),
00425     outsidePoints_(checkIs(is)),
00426     includeCut_(readBool(checkIs(is))),
00427     includeInside_(readBool(checkIs(is))),
00428     includeOutside_(readBool(checkIs(is))),
00429     nearDist_(readScalar(checkIs(is))),
00430     curvature_(readScalar(checkIs(is))),
00431     surfPtr_(new triSurface(surfName_)),
00432     querySurfPtr_(new triSurfaceSearch(*surfPtr_)),
00433     IOwnPtrs_(true)
00434 {
00435     checkSettings();
00436 }
00437 
00438 
00439 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
00440 
00441 Foam::surfaceToCell::~surfaceToCell()
00442 {
00443     if (IOwnPtrs_)
00444     {
00445         if (surfPtr_)
00446         {
00447             delete surfPtr_;
00448         }
00449         if (querySurfPtr_)
00450         {
00451             delete querySurfPtr_;
00452         }
00453     }
00454 }
00455 
00456 
00457 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00458 
00459 void Foam::surfaceToCell::applyToSet
00460 (
00461     const topoSetSource::setAction action,
00462     topoSet& set
00463 ) const
00464 {
00465     if ( (action == topoSetSource::NEW) || (action == topoSetSource::ADD))
00466     {
00467         Info<< "    Adding cells in relation to surface " << surfName_
00468             << " ..." << endl;
00469 
00470         combine(set, true);
00471     }
00472     else if (action == topoSetSource::DELETE)
00473     {
00474         Info<< "    Removing cells in relation to surface " << surfName_
00475             << " ..." << endl;
00476 
00477         combine(set, false);
00478     }
00479 }
00480 
00481 
00482 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines