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-2024 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"
37 
38 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
39 
40 namespace Foam
41 {
42  defineTypeNameAndDebug(surfaceToCell, 0);
43  addToRunTimeSelectionTable(topoSetSource, surfaceToCell, word);
44  addToRunTimeSelectionTable(topoSetSource, surfaceToCell, istream);
45  addToRunTimeSelectionTable(topoSetCellSource, surfaceToCell, word);
46  addToRunTimeSelectionTable(topoSetCellSource, surfaceToCell, istream);
47 }
48 
49 
50 Foam::topoSetSource::addToUsageTable Foam::surfaceToCell::usage_
51 (
52  surfaceToCell::typeName,
53  "\n Usage: surfaceToCell"
54  "<surface> <outsidePoints> <cut> <inside> <outside> <near> <curvature>\n\n"
55  " <surface> name of triSurface\n"
56  " <outsidePoints> list of points that define outside\n"
57  " <cut> boolean whether to include cells cut by surface\n"
58  " <inside> ,, ,, inside surface\n"
59  " <outside> ,, ,, outside surface\n"
60  " <near> scalar; include cells with centre <= near to surface\n"
61  " <curvature> scalar; include cells close to strong curvature"
62  " on surface\n"
63  " (curvature defined as difference in surface normal at nearest"
64  " point on surface for each vertex of cell)\n\n"
65 );
66 
67 
68 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
69 
70 Foam::label Foam::surfaceToCell::getNearest
71 (
72  const triSurfaceSearch& querySurf,
73  const label pointi,
74  const point& pt,
75  const vector& span,
76  Map<label>& cache
77 )
78 {
79  const auto iter = cache.cfind(pointi);
80 
81  if (iter.good())
82  {
83  return iter.val(); // Return cached value
84  }
85 
86  pointIndexHit inter = querySurf.nearest(pt, span);
87 
88  // Triangle label (can be -1)
89  const label trii = inter.index();
90 
91  // Store triangle on point
92  cache.insert(pointi, trii);
93 
94  return trii;
95 }
96 
97 
98 bool Foam::surfaceToCell::differingPointNormals
99 (
100  const triSurfaceSearch& querySurf,
101 
102  const vector& span, // Current search span
103  const label celli,
104  const label cellTriI, // Nearest (to cell centre) surface triangle
105 
106  Map<label>& pointToNearest // Cache for nearest triangle to point
107 ) const
108 {
109  const triSurface& surf = querySurf.surface();
110  const vectorField& normals = surf.faceNormals();
111 
112  const faceList& faces = mesh().faces();
113  const pointField& points = mesh().points();
114 
115  const labelList& cFaces = mesh().cells()[celli];
116 
117  for (const label facei : cFaces)
118  {
119  const face& f = faces[facei];
120 
121  for (const label pointi : f)
122  {
123  label pointTriI =
124  getNearest
125  (
126  querySurf,
127  pointi,
128  points[pointi],
129  span,
130  pointToNearest
131  );
132 
133  if (pointTriI != -1 && pointTriI != cellTriI)
134  {
135  scalar cosAngle = normals[pointTriI] & normals[cellTriI];
136 
137  if (cosAngle < 0.9)
138  {
139  return true;
140  }
141  }
142  }
143  }
144  return false;
145 }
146 
147 
148 void Foam::surfaceToCell::combine(topoSet& set, const bool add) const
149 {
150  cpuTime timer;
151 
152  if (useSurfaceOrientation_ && (includeInside_ || includeOutside_))
153  {
154  const meshSearch queryMesh(mesh_);
155 
156  //- Calculate for each searchPoint inside/outside status.
157  boolList isInside(querySurf().calcInside(mesh_.cellCentres()));
158 
159  if (verbose_)
160  {
161  Info<< " Marked inside/outside using surface orientation in = "
162  << timer.cpuTimeIncrement() << " s" << nl << endl;
163  }
164 
165  forAll(isInside, celli)
166  {
167  if (isInside[celli] ? includeInside_ : includeOutside_)
168  {
169  addOrDelete(set, celli, add);
170  }
171  }
172  }
173  else if (includeCut_ || includeInside_ || includeOutside_)
174  {
175  //
176  // Cut cells with surface and classify cells
177  //
178 
179 
180  // Construct search engine on mesh
181 
182  const meshSearch queryMesh(mesh_);
183 
184 
185  // Check all 'outside' points
186  for (const point& outsidePoint : outsidePoints_)
187  {
188  // Find cell point is in. Linear search.
189  label celli = queryMesh.findCell(outsidePoint, -1, false);
190 
191  if (returnReduceAnd(celli < 0))
192  {
194  << "outsidePoint " << outsidePoint
195  << " is not inside any cell" << nl
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() && inter.point().dist(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() && inter.point().dist(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 {
393  checkSettings();
394 }
396 
398 (
399  const polyMesh& mesh,
400  const fileName& surfName,
401  const triSurface& surf,
402  const triSurfaceSearch& querySurf,
403  const pointField& outsidePoints,
404  const bool includeCut,
405  const bool includeInside,
406  const bool includeOutside,
407  const bool useSurfaceOrientation,
408  const scalar nearDist,
409  const scalar curvature
410 )
411 :
413  surfName_(surfName),
414  outsidePoints_(outsidePoints),
415  includeCut_(includeCut),
416  includeInside_(includeInside),
417  includeOutside_(includeOutside),
418  useSurfaceOrientation_(useSurfaceOrientation),
419  nearDist_(nearDist),
420  curvature_(curvature),
421  surfPtr_(surf),
422  querySurfPtr_(querySurf)
423 {
424  checkSettings();
425 }
427 
429 (
430  const polyMesh& mesh,
431  const dictionary& dict
432 )
433 :
435  surfName_(dict.get<fileName>("file").expand()),
436  outsidePoints_(dict.get<pointField>("outsidePoints")),
437  includeCut_(dict.get<bool>("includeCut")),
438  includeInside_(dict.get<bool>("includeInside")),
439  includeOutside_(dict.get<bool>("includeOutside")),
440  useSurfaceOrientation_
441  (
442  dict.getOrDefault("useSurfaceOrientation", false)
443  ),
444  nearDist_(dict.get<scalar>("nearDistance")),
445  curvature_(dict.get<scalar>("curvature")),
446  surfPtr_
447  (
448  new triSurface
449  (
450  surfName_,
451  dict.getOrDefault<word>("fileType", word::null),
452  dict.getOrDefault<scalar>("scale", -1)
453  )
454  ),
455  querySurfPtr_(new triSurfaceSearch(*surfPtr_))
456 {
457  checkSettings();
458 }
460 
462 (
463  const polyMesh& mesh,
464  Istream& is
465 )
466 :
468  surfName_(checkIs(is)),
469  outsidePoints_(checkIs(is)),
470  includeCut_(readBool(checkIs(is))),
471  includeInside_(readBool(checkIs(is))),
472  includeOutside_(readBool(checkIs(is))),
473  useSurfaceOrientation_(false),
474  nearDist_(readScalar(checkIs(is))),
475  curvature_(readScalar(checkIs(is))),
476  surfPtr_(new triSurface(surfName_)),
477  querySurfPtr_(new triSurfaceSearch(*surfPtr_))
478 {
479  checkSettings();
480 }
481 
483 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
484 
486 {} // Define here (incomplete type in header)
487 
488 
489 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
490 
492 (
493  const topoSetSource::setAction action,
494  topoSet& set
495 ) const
496 {
497  if (action == topoSetSource::ADD || action == topoSetSource::NEW)
498  {
499  if (verbose_)
500  {
501  Info<< " Adding cells in relation to surface " << surfName_
502  << " ..." << endl;
503  }
504 
505  combine(set, true);
506  }
507  else if (action == topoSetSource::SUBTRACT)
508  {
509  if (verbose_)
510  {
511  Info<< " Removing cells in relation to surface " << surfName_
512  << " ..." << endl;
513  }
514 
515  combine(set, false);
516  }
517 }
518 
519 
520 // ************************************************************************* //
List< ReturnType > get(const UPtrList< T > &list, const AccessOp &aop)
List of values generated by applying the access operation to each list item.
cellType
Equivalent to enumeration in "vtkCellType.h" (should be uint8_t)
Definition: foamVtkCore.H:96
dictionary dict
A class for handling file names.
Definition: fileName.H:72
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:600
Create a new set and ADD elements to it.
Add elements to current set.
An Istream is an abstract base class for all input systems (streams, files, token lists etc)...
Definition: Istream.H:57
virtual void applyToSet(const topoSetSource::setAction action, topoSet &) const
Apply specified action to the topoSet.
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:529
PointIndexHit< point > pointIndexHit
A PointIndexHit with a 3D point.
Definition: pointIndexHit.H:58
string expand(const std::string &s, const HashTable< string > &mapping, const char sigil='$')
Expand occurrences of variables according to the mapping and return the expanded string.
const cellList & cells() const
The topoSetCellSource is a intermediate class for handling topoSet sources for selecting cells...
virtual ~surfaceToCell()
Destructor.
Macros for easy insertion into run-time selection tables.
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1063
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:286
List< face > faceList
List of faces.
Definition: faceListFwd.H:39
Helper class to search on triSurface.
AccessType combine(const UList< T > &lists, AccessOp aop=accessOp< T >())
Combines sub-lists into a single list.
Definition: ListListOps.C:62
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
dynamicFvMesh & mesh
const pointField & points
A class for handling words, derived from Foam::string.
Definition: word.H:63
bool returnReduceAnd(const bool value, const int communicator=UPstream::worldComm)
Perform logical (and) MPI Allreduce on a copy. Uses UPstream::reduceAnd.
setAction
Enumeration defining various actions.
Vector< scalar > vector
Definition: vector.H:57
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1088
void add(FieldField< Field1, typename typeOfSum< Type1, Type2 >::type > &f, const FieldField< Field1, Type1 > &f1, const FieldField< Field2, Type2 > &f2)
defineTypeNameAndDebug(combustionModel, 0)
labelList f(nPoints)
General set of labels of mesh quantity (points, cells, faces).
Definition: topoSet.H:59
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.
Subtract elements from current set.
vector point
Point is a vector.
Definition: point.H:37
cpuTimePosix cpuTime
Selection of preferred clock mechanism for the elapsed cpu time.
Definition: cpuTimeFwd.H:36
Class with constructor to add usage string to table.
const dimensionedScalar c
Speed of light in a vacuum.
messageStream Info
Information stream (stdout output on master, null elsewhere)
Field< vector > vectorField
Specialisation of Field<T> for vector.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:75
List< label > labelList
A List of labels.
Definition: List.H:61
Triangulated surface description with patch information.
Definition: triSurface.H:71
List< bool > boolList
A List of bools.
Definition: List.H:59
bool readBool(Istream &is)
Read bool from stream using Foam::Switch(Istream&)
Definition: bool.C:62
Namespace for OpenFOAM.
addToRunTimeSelectionTable(functionObject, pointHistory, dictionary)