surfaceToCell.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2017-2020 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "surfaceToCell.H"
30 #include "polyMesh.H"
31 #include "meshSearch.H"
32 #include "triSurface.H"
33 #include "triSurfaceSearch.H"
34 #include "cellClassification.H"
35 #include "cpuTime.H"
36 #include "demandDrivenData.H"
38 
39 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
40 
41 namespace Foam
42 {
43  defineTypeNameAndDebug(surfaceToCell, 0);
44  addToRunTimeSelectionTable(topoSetSource, surfaceToCell, word);
45  addToRunTimeSelectionTable(topoSetSource, surfaceToCell, istream);
46  addToRunTimeSelectionTable(topoSetCellSource, surfaceToCell, word);
47  addToRunTimeSelectionTable(topoSetCellSource, surfaceToCell, istream);
48 }
49 
50 
51 Foam::topoSetSource::addToUsageTable Foam::surfaceToCell::usage_
52 (
53  surfaceToCell::typeName,
54  "\n Usage: surfaceToCell"
55  "<surface> <outsidePoints> <cut> <inside> <outside> <near> <curvature>\n\n"
56  " <surface> name of triSurface\n"
57  " <outsidePoints> list of points that define outside\n"
58  " <cut> boolean whether to include cells cut by surface\n"
59  " <inside> ,, ,, inside surface\n"
60  " <outside> ,, ,, outside surface\n"
61  " <near> scalar; include cells with centre <= near to surface\n"
62  " <curvature> scalar; include cells close to strong curvature"
63  " on surface\n"
64  " (curvature defined as difference in surface normal at nearest"
65  " point on surface for each vertex of cell)\n\n"
66 );
67 
68 
69 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
70 
71 Foam::label Foam::surfaceToCell::getNearest
72 (
73  const triSurfaceSearch& querySurf,
74  const label pointi,
75  const point& pt,
76  const vector& span,
77  Map<label>& cache
78 )
79 {
80  const auto iter = cache.cfind(pointi);
81 
82  if (iter.found())
83  {
84  return *iter; // Return cached value
85  }
86 
87  pointIndexHit inter = querySurf.nearest(pt, span);
88 
89  // Triangle label (can be -1)
90  const label trii = inter.index();
91 
92  // Store triangle on point
93  cache.insert(pointi, trii);
94 
95  return trii;
96 }
97 
98 
99 bool Foam::surfaceToCell::differingPointNormals
100 (
101  const triSurfaceSearch& querySurf,
102 
103  const vector& span, // Current search span
104  const label celli,
105  const label cellTriI, // Nearest (to cell centre) surface triangle
106 
107  Map<label>& pointToNearest // Cache for nearest triangle to point
108 ) const
109 {
110  const triSurface& surf = querySurf.surface();
111  const vectorField& normals = surf.faceNormals();
112 
113  const faceList& faces = mesh().faces();
114  const pointField& points = mesh().points();
115 
116  const labelList& cFaces = mesh().cells()[celli];
117 
118  for (const label facei : cFaces)
119  {
120  const face& f = faces[facei];
121 
122  for (const label pointi : f)
123  {
124  label pointTriI =
125  getNearest
126  (
127  querySurf,
128  pointi,
129  points[pointi],
130  span,
131  pointToNearest
132  );
133 
134  if (pointTriI != -1 && pointTriI != cellTriI)
135  {
136  scalar cosAngle = normals[pointTriI] & normals[cellTriI];
137 
138  if (cosAngle < 0.9)
139  {
140  return true;
141  }
142  }
143  }
144  }
145  return false;
146 }
147 
148 
149 void Foam::surfaceToCell::combine(topoSet& set, const bool add) const
150 {
151  cpuTime timer;
152 
153  if (useSurfaceOrientation_ && (includeInside_ || includeOutside_))
154  {
155  const meshSearch queryMesh(mesh_);
156 
157  //- Calculate for each searchPoint inside/outside status.
158  boolList isInside(querySurf().calcInside(mesh_.cellCentres()));
159 
160  if (verbose_)
161  {
162  Info<< " Marked inside/outside using surface orientation in = "
163  << timer.cpuTimeIncrement() << " s" << nl << endl;
164  }
165 
166  forAll(isInside, celli)
167  {
168  if (isInside[celli] ? includeInside_ : includeOutside_)
169  {
170  addOrDelete(set, celli, add);
171  }
172  }
173  }
174  else if (includeCut_ || includeInside_ || includeOutside_)
175  {
176  //
177  // Cut cells with surface and classify cells
178  //
179 
180 
181  // Construct search engine on mesh
182 
183  const meshSearch queryMesh(mesh_);
184 
185 
186  // Check all 'outside' points
187  for (const point& outsidePoint : outsidePoints_)
188  {
189  // Find cell point is in. Linear search.
190  label celli = queryMesh.findCell(outsidePoint, -1, false);
191  if (returnReduce(celli, maxOp<label>()) == -1)
192  {
194  << "outsidePoint " << outsidePoint
195  << " is not inside any cell"
196  << exit(FatalError);
197  }
198  }
199 
200  // Cut faces with surface and classify cells
201 
202  cellClassification cellType
203  (
204  mesh_,
205  queryMesh,
206  querySurf(),
207  outsidePoints_
208  );
209 
210 
211  if (verbose_)
212  {
213  Info<< " Marked inside/outside using surface intersection in = "
214  << timer.cpuTimeIncrement() << " s" << nl << endl;
215  }
216 
217  //- Add/remove cells using set
218  forAll(cellType, celli)
219  {
220  label cType = cellType[celli];
221 
222  if
223  (
224  (
225  includeCut_
226  && (cType == cellClassification::CUT)
227  )
228  || (
229  includeInside_
230  && (cType == cellClassification::INSIDE)
231  )
232  || (
233  includeOutside_
234  && (cType == cellClassification::OUTSIDE)
235  )
236  )
237  {
238  addOrDelete(set, celli, add);
239  }
240  }
241  }
242 
243 
244  if (nearDist_ > 0)
245  {
246  //
247  // Determine distance to surface
248  //
249 
250  const pointField& ctrs = mesh_.cellCentres();
251 
252  // Box dimensions to search in octree.
253  const vector span(nearDist_, nearDist_, nearDist_);
254 
255 
256  if (curvature_ < -1)
257  {
258  if (verbose_)
259  {
260  Info<< " Selecting cells with cellCentre closer than "
261  << nearDist_ << " to surface" << endl;
262  }
263 
264  // No need to test curvature. Insert near cells into set.
265 
266  forAll(ctrs, celli)
267  {
268  const point& c = ctrs[celli];
269 
270  pointIndexHit inter = querySurf().nearest(c, span);
271 
272  if (inter.hit() && (mag(inter.hitPoint() - c) < nearDist_))
273  {
274  addOrDelete(set, celli, add);
275  }
276  }
277 
278  if (verbose_)
279  {
280  Info<< " Determined nearest surface point in = "
281  << timer.cpuTimeIncrement() << " s" << nl << endl;
282  }
283  }
284  else
285  {
286  // Test near cells for curvature
287 
288  if (verbose_)
289  {
290  Info<< " Selecting cells with cellCentre closer than "
291  << nearDist_ << " to surface and curvature factor"
292  << " less than " << curvature_ << endl;
293  }
294 
295  // Cache for nearest surface triangle for a point
296  Map<label> pointToNearest(mesh_.nCells()/10);
297 
298  forAll(ctrs, celli)
299  {
300  const point& c = ctrs[celli];
301 
302  pointIndexHit inter = querySurf().nearest(c, span);
303 
304  if (inter.hit() && (mag(inter.hitPoint() - c) < nearDist_))
305  {
306  if
307  (
308  differingPointNormals
309  (
310  querySurf(),
311  span,
312  celli,
313  inter.index(), // nearest surface triangle
314  pointToNearest
315  )
316  )
317  {
318  addOrDelete(set, celli, add);
319  }
320  }
321  }
322 
323  if (verbose_)
324  {
325  Info<< " Determined nearest surface point in = "
326  << timer.cpuTimeIncrement() << " s" << nl << endl;
327  }
328  }
329  }
330 }
331 
332 
333 void Foam::surfaceToCell::checkSettings() const
334 {
335  if
336  (
337  (nearDist_ < 0)
338  && (curvature_ < -1)
339  && (
340  (includeCut_ && includeInside_ && includeOutside_)
341  || (!includeCut_ && !includeInside_ && !includeOutside_)
342  )
343  )
344  {
346  << "Illegal include cell specification."
347  << " Result would be either all or no cells." << endl
348  << "Please set one of includeCut, includeInside, includeOutside"
349  << " to true, set nearDistance to a value > 0"
350  << " or set curvature to a value -1 .. 1."
351  << exit(FatalError);
352  }
353 
354  if (useSurfaceOrientation_ && includeCut_)
355  {
357  << "Illegal include cell specification."
358  << " You cannot specify both 'useSurfaceOrientation'"
359  << " and 'includeCut'"
360  << " since 'includeCut' specifies a topological split"
361  << exit(FatalError);
362  }
363 }
364 
365 
366 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
367 
369 (
370  const polyMesh& mesh,
371  const fileName& surfName,
372  const pointField& outsidePoints,
373  const bool includeCut,
374  const bool includeInside,
375  const bool includeOutside,
376  const bool useSurfaceOrientation,
377  const scalar nearDist,
378  const scalar curvature
379 )
380 :
382  surfName_(surfName),
383  outsidePoints_(outsidePoints),
384  includeCut_(includeCut),
385  includeInside_(includeInside),
386  includeOutside_(includeOutside),
387  useSurfaceOrientation_(useSurfaceOrientation),
388  nearDist_(nearDist),
389  curvature_(curvature),
390  surfPtr_(new triSurface(surfName_)),
391  querySurfPtr_(new triSurfaceSearch(*surfPtr_)),
392  IOwnPtrs_(true)
393 {
394  checkSettings();
395 }
396 
397 
399 (
400  const polyMesh& mesh,
401  const fileName& surfName,
402  const triSurface& surf,
403  const triSurfaceSearch& querySurf,
404  const pointField& outsidePoints,
405  const bool includeCut,
406  const bool includeInside,
407  const bool includeOutside,
408  const bool useSurfaceOrientation,
409  const scalar nearDist,
410  const scalar curvature
411 )
412 :
414  surfName_(surfName),
415  outsidePoints_(outsidePoints),
416  includeCut_(includeCut),
417  includeInside_(includeInside),
418  includeOutside_(includeOutside),
419  useSurfaceOrientation_(useSurfaceOrientation),
420  nearDist_(nearDist),
421  curvature_(curvature),
422  surfPtr_(&surf),
423  querySurfPtr_(&querySurf),
424  IOwnPtrs_(false)
425 {
426  checkSettings();
427 }
428 
429 
431 (
432  const polyMesh& mesh,
433  const dictionary& dict
434 )
435 :
437  surfName_(dict.get<fileName>("file").expand()),
438  outsidePoints_(dict.get<pointField>("outsidePoints")),
439  includeCut_(dict.get<bool>("includeCut")),
440  includeInside_(dict.get<bool>("includeInside")),
441  includeOutside_(dict.get<bool>("includeOutside")),
442  useSurfaceOrientation_
443  (
444  dict.getOrDefault("useSurfaceOrientation", false)
445  ),
446  nearDist_(dict.get<scalar>("nearDistance")),
447  curvature_(dict.get<scalar>("curvature")),
448  surfPtr_
449  (
450  new triSurface
451  (
452  surfName_,
453  dict.getOrDefault<word>("fileType", word::null),
454  dict.getOrDefault<scalar>("scale", -1)
455  )
456  ),
457  querySurfPtr_(new triSurfaceSearch(*surfPtr_)),
458  IOwnPtrs_(true)
459 {
460  checkSettings();
461 }
462 
463 
465 (
466  const polyMesh& mesh,
467  Istream& is
468 )
469 :
471  surfName_(checkIs(is)),
472  outsidePoints_(checkIs(is)),
473  includeCut_(readBool(checkIs(is))),
474  includeInside_(readBool(checkIs(is))),
475  includeOutside_(readBool(checkIs(is))),
476  useSurfaceOrientation_(false),
477  nearDist_(readScalar(checkIs(is))),
478  curvature_(readScalar(checkIs(is))),
479  surfPtr_(new triSurface(surfName_)),
480  querySurfPtr_(new triSurfaceSearch(*surfPtr_)),
481  IOwnPtrs_(true)
482 {
483  checkSettings();
484 }
485 
486 
487 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
488 
490 {
491  if (IOwnPtrs_)
492  {
493  deleteDemandDrivenData(surfPtr_);
494  deleteDemandDrivenData(querySurfPtr_);
495  }
496 }
497 
498 
499 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
500 
502 (
503  const topoSetSource::setAction action,
504  topoSet& set
505 ) const
506 {
507  if (action == topoSetSource::ADD || action == topoSetSource::NEW)
508  {
509  if (verbose_)
510  {
511  Info<< " Adding cells in relation to surface " << surfName_
512  << " ..." << endl;
513  }
514 
515  combine(set, true);
516  }
517  else if (action == topoSetSource::SUBTRACT)
518  {
519  if (verbose_)
520  {
521  Info<< " Removing cells in relation to surface " << surfName_
522  << " ..." << endl;
523  }
524 
525  combine(set, false);
526  }
527 }
528 
529 
530 // ************************************************************************* //
Foam::addToRunTimeSelectionTable
addToRunTimeSelectionTable(decompositionMethod, kahipDecomp, dictionary)
cellClassification.H
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:67
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
Foam::polyMesh::points
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1069
Foam::topoSetSource::ADD
Add elements to current set.
Definition: topoSetSource.H:103
Foam::BitOps::set
void set(List< bool > &bools, const labelRange &range)
Set the specified range 'on' in a boolList.
Definition: BitOps.C:37
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::fileName
A class for handling file names.
Definition: fileName.H:73
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:94
demandDrivenData.H
Template functions to aid in the implementation of demand driven data.
Foam::topoSetSource::addToUsageTable
Class with constructor to add usage string to table.
Definition: topoSetSource.H:129
Foam::cellClassification::CUT
Definition: cellClassification.H:132
Foam::primitiveMesh::cells
const cellList & cells() const
Definition: primitiveMeshCells.C:138
Foam::boolList
List< bool > boolList
A List of bools.
Definition: List.H:65
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::topoSetSource::setAction
setAction
Enumeration defining the valid actions.
Definition: topoSetSource.H:100
Foam::dictionary::get
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:107
Foam::topoSetSource::NEW
Create a new set and ADD elements to it.
Definition: topoSetSource.H:104
Foam::cellClassification::INSIDE
Definition: cellClassification.H:130
triSurface.H
polyMesh.H
Foam::triSurfaceSearch
Helper class to search on triSurface.
Definition: triSurfaceSearch.H:58
surfaceToCell.H
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:77
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::vectorField
Field< vector > vectorField
Specialisation of Field<T> for vector.
Definition: primitiveFieldsFwd.H:54
Foam::deleteDemandDrivenData
void deleteDemandDrivenData(DataPtr &dataPtr)
Definition: demandDrivenData.H:42
Foam::cpuTime
cpuTimeCxx cpuTime
Selection of preferred clock mechanism for the elapsed cpu time.
Definition: cpuTimeFwd.H:41
Foam::Field< vector >
Foam::triSurface
Triangulated surface description with patch information.
Definition: triSurface.H:76
Foam::Istream
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:61
Foam::Info
messageStream Info
Information stream (stdout output on master, null elsewhere)
Foam::readBool
bool readBool(Istream &is)
Read bool from stream using Foam::Switch(Istream&)
Definition: bool.C:75
Foam::ListListOps::combine
AccessType combine(const UList< T > &lists, AccessOp aop=accessOp< T >())
Combines sub-lists into a single list.
Definition: ListListOps.C:69
Foam::cellClassification::OUTSIDE
Definition: cellClassification.H:131
Foam::topoSet
General set of labels of mesh quantity (points, cells, faces).
Definition: topoSet.H:63
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:123
Foam::add
void add(FieldField< Field1, typename typeOfSum< Type1, Type2 >::type > &f, const FieldField< Field1, Type1 > &f1, const FieldField< Field2, Type2 > &f2)
Definition: FieldFieldFunctions.C:939
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
addToRunTimeSelectionTable.H
Macros for easy insertion into run-time selection tables.
Foam::topoSetSource::SUBTRACT
Subtract elements from current set.
Definition: topoSetSource.H:105
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::vector
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:51
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::polyMesh::faces
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1094
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Foam::pointIndexHit
PointIndexHit< point > pointIndexHit
A PointIndexHit for 3D points.
Definition: pointIndexHit.H:46
meshSearch.H
Foam::nl
constexpr char nl
Definition: Ostream.H:404
f
labelList f(nPoints)
Foam::faceList
List< face > faceList
A List of faces.
Definition: faceListFwd.H:47
Foam::vtk::cellType
cellType
Equivalent to enumeration in "vtkCellType.h".
Definition: foamVtkCore.H:89
Foam::surfaceToCell::surfaceToCell
surfaceToCell(const polyMesh &mesh, const fileName &surfName, const pointField &outsidePoints, const bool includeCut, const bool includeInside, const bool includeOutside, const bool useSurfaceOrientation, const scalar nearDist, const scalar curvature)
Construct from components.
Definition: surfaceToCell.C:369
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::string::expand
string & expand(const bool allowEmpty=false)
Definition: string.C:173
Foam::topoSetCellSource
The topoSetCellSource is a intermediate class for handling topoSet sources for selecting cells.
Definition: topoSetCellSource.H:54
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::word::null
static const word null
An empty word.
Definition: word.H:80
triSurfaceSearch.H
Foam::constant::universal::c
const dimensionedScalar c
Speed of light in a vacuum.
Foam::point
vector point
Point is a vector.
Definition: point.H:43
Foam::dictionary::getOrDefault
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:148
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
Foam::surfaceToCell::~surfaceToCell
virtual ~surfaceToCell()
Destructor.
Definition: surfaceToCell.C:489
Foam::surfaceToCell::applyToSet
virtual void applyToSet(const topoSetSource::setAction action, topoSet &) const
Apply specified action to the topoSet.
Definition: surfaceToCell.C:502