surfaceCheck.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2023 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 Application
25  surfaceCheck
26 
27 Description
28  Checks geometric and topological quality of a surface.
29 
30 \*---------------------------------------------------------------------------*/
31 
32 #include "triangle.H"
33 #include "triSurface.H"
34 #include "triSurfaceSearch.H"
35 #include "argList.H"
36 #include "OFstream.H"
37 #include "OBJstream.H"
38 #include "SortableList.H"
39 #include "PatchTools.H"
40 #include "vtkSurfaceWriter.H"
41 
42 using namespace Foam;
43 
44 // Does face use valid vertices?
45 bool validTri
46 (
47  const triSurface& surf,
48  const label facei
49 )
50 {
51  // Simple check on indices ok.
52 
53  const labelledTri& f = surf[facei];
54 
55  forAll(f, fp)
56  {
57  if (f[fp] < 0 || f[fp] >= surf.points().size())
58  {
60  << "triangle " << facei << " vertices " << f
61  << " uses point indices outside point range 0.."
62  << surf.points().size()-1 << endl;
63  return false;
64  }
65  }
66 
67  if ((f[0] == f[1]) || (f[0] == f[2]) || (f[1] == f[2]))
68  {
70  << "triangle " << facei
71  << " uses non-unique vertices " << f
72  << " coords:" << f.points(surf.points())
73  << endl;
74  return false;
75  }
76 
77  // duplicate triangle check
78 
79  const labelList& fFaces = surf.faceFaces()[facei];
80 
81  // Check if faceNeighbours use same points as this face.
82  // Note: discards normal information - sides of baffle are merged.
83  forAll(fFaces, i)
84  {
85  label nbrFacei = fFaces[i];
86 
87  if (nbrFacei <= facei)
88  {
89  // lower numbered faces already checked
90  continue;
91  }
92 
93  const labelledTri& nbrF = surf[nbrFacei];
94 
95  if
96  (
97  ((f[0] == nbrF[0]) || (f[0] == nbrF[1]) || (f[0] == nbrF[2]))
98  && ((f[1] == nbrF[0]) || (f[1] == nbrF[1]) || (f[1] == nbrF[2]))
99  && ((f[2] == nbrF[0]) || (f[2] == nbrF[1]) || (f[2] == nbrF[2]))
100  )
101  {
103  << "triangle " << facei << " vertices " << f
104  << " has the same vertices as triangle " << nbrFacei
105  << " vertices " << nbrF
106  << " coords:" << f.points(surf.points())
107  << endl;
108 
109  return false;
110  }
111  }
112  return true;
113 }
114 
115 
116 labelList countBins
117 (
118  const scalar min,
119  const scalar max,
120  const label nBins,
121  const scalarField& vals
122 )
123 {
124  scalar dist = nBins/(max - min);
125 
126  labelList binCount(nBins, 0);
127 
128  forAll(vals, i)
129  {
130  scalar val = vals[i];
131 
132  label index = -1;
133 
134  if (Foam::mag(val - min) < small)
135  {
136  index = 0;
137  }
138  else if (val >= max - small)
139  {
140  index = nBins - 1;
141  }
142  else
143  {
144  index = label((val - min)*dist);
145 
146  if ((index < 0) || (index >= nBins))
147  {
149  << "value " << val << " at index " << i
150  << " outside range " << min << " .. " << max << endl;
151 
152  if (index < 0)
153  {
154  index = 0;
155  }
156  else
157  {
158  index = nBins - 1;
159  }
160  }
161  }
162  binCount[index]++;
163  }
164 
165  return binCount;
166 }
167 
168 
169 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
170 
171 int main(int argc, char *argv[])
172 {
173  #include "removeCaseOptions.H"
174 
175  argList::validArgs.append("surface file");
177  (
178  "checkSelfIntersection",
179  "also check for self-intersection"
180  );
182  (
183  "splitNonManifold",
184  "split surface along non-manifold edges"
185  " (default split is fully disconnected)"
186  );
188  (
189  "verbose",
190  "verbose operation"
191  );
193  (
194  "blockMesh",
195  "write vertices/blocks for blockMeshDict"
196  );
197 
198  argList args(argc, argv);
199 
200  const fileName surfFileName = args[1];
201  const bool checkSelfIntersect = args.optionFound("checkSelfIntersection");
202  const bool verbose = args.optionFound("verbose");
203  const bool splitNonManifold = args.optionFound("splitNonManifold");
204 
205  Info<< "Reading surface from " << surfFileName << " ..." << nl << endl;
206 
207 
208  // Read
209  // ~~~~
210 
211  triSurface surf(surfFileName);
212 
213 
214  Info<< "Statistics:" << endl;
215  surf.writeStats(Info);
216  Info<< endl;
217 
218  // write bounding box corners
219  if (args.optionFound("blockMesh"))
220  {
221  pointField cornerPts(boundBox(surf.points(), false).points());
222 
223  Info<< "// blockMeshDict info" << nl << nl;
224 
225  Info<< "vertices\n(" << nl;
226  forAll(cornerPts, ptI)
227  {
228  Info<< " " << cornerPts[ptI] << nl;
229  }
230 
231  // number of divisions needs adjustment later
232  Info<< ");\n" << nl
233  << "blocks\n"
234  << "(\n"
235  << " hex (0 1 2 3 4 5 6 7) (10 10 10) simpleGrading (1 1 1)\n"
236  << ");\n" << nl;
237 
238  Info<< "edges\n();" << nl
239  << "patches\n();" << endl;
240 
241  Info<< nl << "// end blockMeshDict info" << nl << endl;
242  }
243 
244  if (verbose)
245  {
246  return 0;
247  }
248 
249  // Region sizes
250  // ~~~~~~~~~~~~
251 
252  {
253  labelList regionSize(surf.patches().size(), 0);
254 
255  forAll(surf, facei)
256  {
257  label region = surf[facei].region();
258 
259  if (region < 0 || region >= regionSize.size())
260  {
262  << "Triangle " << facei << " vertices " << surf[facei]
263  << " has region " << region << " which is outside the range"
264  << " of regions 0.." << surf.patches().size()-1
265  << endl;
266  }
267  else
268  {
269  regionSize[region]++;
270  }
271  }
272 
273  Info<< "Region\tSize" << nl
274  << "------\t----" << nl;
275  forAll(surf.patches(), patchi)
276  {
277  Info<< surf.patches()[patchi].name() << '\t'
278  << regionSize[patchi] << nl;
279  }
280  Info<< nl << endl;
281  }
282 
283 
284  // Check triangles
285  // ~~~~~~~~~~~~~~~
286 
287  {
288  DynamicList<label> illegalFaces(surf.size()/100 + 1);
289 
290  forAll(surf, facei)
291  {
292  if (!validTri(surf, facei))
293  {
294  illegalFaces.append(facei);
295  }
296  }
297 
298  if (illegalFaces.size())
299  {
300  Info<< "Surface has " << illegalFaces.size()
301  << " illegal triangles." << endl;
302 
303  OFstream str("illegalFaces");
304  Info<< "Dumping conflicting face labels to " << str.name() << endl
305  << "Paste this into the input for surfaceSubset" << endl;
306  str << illegalFaces;
307  }
308  else
309  {
310  Info<< "Surface has no illegal triangles." << endl;
311  }
312  Info<< endl;
313  }
314 
315 
316 
317  // Triangle quality
318  // ~~~~~~~~~~~~~~~~
319 
320  {
321  scalarField triQ(surf.size(), 0);
322  forAll(surf, facei)
323  {
324  const labelledTri& f = surf[facei];
325 
326  if (f[0] == f[1] || f[0] == f[2] || f[1] == f[2])
327  {
328  // WarningIn(args.executable())
329  // << "Illegal triangle " << facei << " vertices " << f
330  // << " coords " << f.points(surf.points()) << endl;
331  }
332  else
333  {
334  triQ[facei] = triPointRef
335  (
336  surf.points()[f[0]],
337  surf.points()[f[1]],
338  surf.points()[f[2]]
339  ).quality();
340  }
341  }
342 
343  labelList binCount = countBins(0, 1, 20, triQ);
344 
345  Info<< "Triangle quality (equilateral=1, collapsed=0):"
346  << endl;
347 
348 
349  OSstream& os = Info;
350  os.width(4);
351 
352  scalar dist = (1.0 - 0.0)/20.0;
353  scalar min = 0;
354  forAll(binCount, binI)
355  {
356  Info<< " " << min << " .. " << min+dist << " : "
357  << 1.0/surf.size() * binCount[binI]
358  << endl;
359  min += dist;
360  }
361  Info<< endl;
362 
363  label minIndex = findMin(triQ);
364  label maxIndex = findMax(triQ);
365 
366  Info<< " min " << triQ[minIndex] << " for triangle " << minIndex
367  << nl
368  << " max " << triQ[maxIndex] << " for triangle " << maxIndex
369  << nl
370  << endl;
371 
372 
373  if (triQ[minIndex] < small)
374  {
376  << triQ[minIndex] << ". This might give problems in"
377  << " self-intersection testing later on." << endl;
378  }
379 
380  // Dump for subsetting
381  {
382  DynamicList<label> problemFaces(surf.size()/100+1);
383 
384  forAll(triQ, facei)
385  {
386  if (triQ[facei] < 1e-11)
387  {
388  problemFaces.append(facei);
389  }
390  }
391 
392  if (!problemFaces.empty())
393  {
394  OFstream str("badFaces");
395 
396  Info<< "Dumping bad quality faces to " << str.name() << endl
397  << "Paste this into the input for surfaceSubset" << nl
398  << nl << endl;
399 
400  str << problemFaces;
401  }
402  }
403  }
404 
405 
406 
407  // Edges
408  // ~~~~~
409  {
410  const edgeList& edges = surf.edges();
411  const pointField& localPoints = surf.localPoints();
412 
413  scalarField edgeMag(edges.size());
414 
415  forAll(edges, edgeI)
416  {
417  edgeMag[edgeI] = edges[edgeI].mag(localPoints);
418  }
419 
420  label minEdgeI = findMin(edgeMag);
421  label maxEdgeI = findMax(edgeMag);
422 
423  const edge& minE = edges[minEdgeI];
424  const edge& maxE = edges[maxEdgeI];
425 
426 
427  Info<< "Edges:" << nl
428  << " min " << edgeMag[minEdgeI] << " for edge " << minEdgeI
429  << " points " << localPoints[minE[0]] << localPoints[minE[1]]
430  << nl
431  << " max " << edgeMag[maxEdgeI] << " for edge " << maxEdgeI
432  << " points " << localPoints[maxE[0]] << localPoints[maxE[1]]
433  << nl
434  << endl;
435  }
436 
437 
438 
439  // Close points
440  // ~~~~~~~~~~~~
441  {
442  const edgeList& edges = surf.edges();
443  const pointField& localPoints = surf.localPoints();
444 
445  const boundBox bb(localPoints);
446  scalar smallDim = 1e-6 * bb.mag();
447 
448  Info<< "Checking for points less than 1e-6 of bounding box ("
449  << bb.span() << " metre) apart."
450  << endl;
451 
452  // Sort points
453  SortableList<scalar> sortedMag(mag(localPoints));
454 
455  label nClose = 0;
456 
457  for (label i = 1; i < sortedMag.size(); i++)
458  {
459  label ptI = sortedMag.indices()[i];
460 
461  label prevPtI = sortedMag.indices()[i-1];
462 
463  if (mag(localPoints[ptI] - localPoints[prevPtI]) < smallDim)
464  {
465  // Check if neighbours.
466  const labelList& pEdges = surf.pointEdges()[ptI];
467 
468  label edgeI = -1;
469 
470  forAll(pEdges, i)
471  {
472  const edge& e = edges[pEdges[i]];
473 
474  if (e[0] == prevPtI || e[1] == prevPtI)
475  {
476  // point1 and point0 are connected through edge.
477  edgeI = pEdges[i];
478 
479  break;
480  }
481  }
482 
483  nClose++;
484 
485  if (edgeI == -1)
486  {
487  Info<< " close unconnected points "
488  << ptI << ' ' << localPoints[ptI]
489  << " and " << prevPtI << ' '
490  << localPoints[prevPtI]
491  << " distance:"
492  << mag(localPoints[ptI] - localPoints[prevPtI])
493  << endl;
494  }
495  else
496  {
497  Info<< " small edge between points "
498  << ptI << ' ' << localPoints[ptI]
499  << " and " << prevPtI << ' '
500  << localPoints[prevPtI]
501  << " distance:"
502  << mag(localPoints[ptI] - localPoints[prevPtI])
503  << endl;
504  }
505  }
506  }
507 
508  Info<< "Found " << nClose << " nearby points." << nl
509  << endl;
510  }
511 
512 
513 
514  // Check manifold
515  // ~~~~~~~~~~~~~~
516 
517  DynamicList<label> problemFaces(surf.size()/100 + 1);
518 
519  const labelListList& eFaces = surf.edgeFaces();
520 
521  label nSingleEdges = 0;
522  forAll(eFaces, edgeI)
523  {
524  const labelList& myFaces = eFaces[edgeI];
525 
526  if (myFaces.size() == 1)
527  {
528  problemFaces.append(myFaces[0]);
529 
530  nSingleEdges++;
531  }
532  }
533 
534  label nMultEdges = 0;
535  forAll(eFaces, edgeI)
536  {
537  const labelList& myFaces = eFaces[edgeI];
538 
539  if (myFaces.size() > 2)
540  {
541  forAll(myFaces, myFacei)
542  {
543  problemFaces.append(myFaces[myFacei]);
544  }
545 
546  nMultEdges++;
547  }
548  }
549  problemFaces.shrink();
550 
551  if ((nSingleEdges != 0) || (nMultEdges != 0))
552  {
553  Info<< "Surface is not closed since not all edges connected to "
554  << "two faces:" << endl
555  << " connected to one face : " << nSingleEdges << endl
556  << " connected to >2 faces : " << nMultEdges << endl;
557 
558  Info<< "Conflicting face labels:" << problemFaces.size() << endl;
559 
560  OFstream str("problemFaces");
561 
562  Info<< "Dumping conflicting face labels to " << str.name() << endl
563  << "Paste this into the input for surfaceSubset" << endl;
564 
565  str << problemFaces;
566  }
567  else
568  {
569  Info<< "Surface is closed. All edges connected to two faces." << endl;
570  }
571  Info<< endl;
572 
573 
574 
575  // Check singly connected domain
576  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
577 
578  {
579  boolList borderEdge(surf.nEdges(), false);
580  if (splitNonManifold)
581  {
582  const labelListList& eFaces = surf.edgeFaces();
583  forAll(eFaces, edgeI)
584  {
585  if (eFaces[edgeI].size() > 2)
586  {
587  borderEdge[edgeI] = true;
588  }
589  }
590  }
591 
593  label numZones = surf.markZones(borderEdge, faceZone);
594 
595  Info<< "Number of unconnected parts : " << numZones << endl;
596 
597  if (numZones > 1)
598  {
599  Info<< "Splitting surface into parts ..." << endl << endl;
600 
601  fileName surfFileNameBase(surfFileName.name());
602  const word fileType = surfFileNameBase.ext();
603  // Strip extension
604  surfFileNameBase = surfFileNameBase.lessExt();
605  // If extension was .gz strip original extension
606  if (fileType == "gz")
607  {
608  surfFileNameBase = surfFileNameBase.lessExt();
609  }
610 
611 
612  {
613  Info<< "Writing zoning to "
614  << fileName
615  (
616  "zone_"
617  + surfFileNameBase
618  + '.'
619  + vtkSurfaceWriter::typeName
620  )
621  << "..." << endl << endl;
622 
623  // Convert data
624  scalarField scalarFaceZone(faceZone.size());
625  forAll(faceZone, i)
626  {
627  scalarFaceZone[i] = faceZone[i];
628  }
629  faceList faces(surf.size());
630  forAll(surf, i)
631  {
632  faces[i] = surf[i].triFaceFace();
633  }
634 
636  (
637  surfFileName.path(),
638  "zone_" + surfFileNameBase,
639  surf.points(),
640  faces,
641  false, // face based data
642  "zone",
643  scalarFaceZone
644  );
645  }
646 
647 
648  for (label zone = 0; zone < numZones; zone++)
649  {
650  boolList includeMap(surf.size(), false);
651 
652  forAll(faceZone, facei)
653  {
654  if (faceZone[facei] == zone)
655  {
656  includeMap[facei] = true;
657  }
658  }
659 
660  labelList pointMap;
662 
663  triSurface subSurf
664  (
665  surf.subsetMesh
666  (
667  includeMap,
668  pointMap,
669  faceMap
670  )
671  );
672 
673  fileName subName(surfFileNameBase + "_" + name(zone) + ".obj");
674 
675  Info<< "writing part " << zone << " size " << subSurf.size()
676  << " to " << subName << endl;
677 
678  subSurf.write(subName);
679  }
680  }
681  }
682 
683 
684 
685  // Check orientation
686  // ~~~~~~~~~~~~~~~~~
687 
688  labelHashSet borderEdge(surf.size()/1000);
689  PatchTools::checkOrientation(surf, false, &borderEdge);
690 
691  //
692  // Colour all faces into zones using borderEdge
693  //
694  labelList normalZone;
695  label numNormalZones = PatchTools::markZones(surf, borderEdge, normalZone);
696 
697  Info<< endl
698  << "Number of zones (connected area with consistent normal) : "
699  << numNormalZones << endl;
700 
701  if (numNormalZones > 1)
702  {
703  Info<< "More than one normal orientation." << endl;
704  }
705  Info<< endl;
706 
707 
708 
709  // Check self-intersection
710  // ~~~~~~~~~~~~~~~~~~~~~~~
711 
712  if (checkSelfIntersect)
713  {
714  Info<< "Checking self-intersection." << endl;
715 
716  triSurfaceSearch querySurf(surf);
717 
718  const indexedOctree<treeDataTriSurface>& tree = querySurf.tree();
719 
720  OBJstream intStream("selfInterPoints.obj");
721 
722  label nInt = 0;
723 
724  forAll(surf.edges(), edgeI)
725  {
726  const edge& e = surf.edges()[edgeI];
727 
728  pointIndexHit hitInfo
729  (
730  tree.findLine
731  (
732  surf.points()[surf.meshPoints()[e[0]]],
733  surf.points()[surf.meshPoints()[e[1]]],
735  (
736  tree,
737  edgeI
738  )
739  )
740  );
741 
742  if (hitInfo.hit())
743  {
744  intStream.write(hitInfo.hitPoint());
745  nInt++;
746  }
747  }
748 
749  if (nInt == 0)
750  {
751  Info<< "Surface is not self-intersecting" << endl;
752  }
753  else
754  {
755  Info<< "Surface is self-intersecting at " << nInt
756  << " locations." << endl;
757  Info<< "Writing intersection points to " << intStream.name()
758  << endl;
759  }
760 
761  // surfaceIntersection inter(querySurf);
762  //
763  // if (inter.cutEdges().empty() && inter.cutPoints().empty())
764  //{
765  // Info<< "Surface is not self-intersecting" << endl;
766  //}
767  // else
768  //{
769  // Info<< "Surface is self-intersecting" << endl;
770  // Info<< "Writing edges of intersection to selfInter.obj" << endl;
771  //
772  // OFstream intStream("selfInter.obj");
773  // forAll(inter.cutPoints(), cutPointi)
774  // {
775  // const point& pt = inter.cutPoints()[cutPointi];
776  //
777  // intStream << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z()
778  // << endl;
779  // }
780  // forAll(inter.cutEdges(), cutEdgeI)
781  // {
782  // const edge& e = inter.cutEdges()[cutEdgeI];
783  //
784  // intStream << "l " << e.start()+1 << ' ' << e.end()+1 << endl;
785  // }
786  //}
787  Info<< endl;
788  }
789 
790 
791  Info<< "\nEnd\n" << endl;
792 
793  return 0;
794 }
795 
796 
797 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
void append(const T &)
Append an element at the end of the list.
Definition: ListI.H:178
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
OFstream which keeps track of vertices.
Definition: OBJstream.H:56
Output to file stream.
Definition: OFstream.H:86
Generic output stream.
Definition: OSstream.H:54
virtual int width() const
Get width of output field.
Definition: OSstream.C:234
virtual Ostream & write(const char)=0
Write character.
static bool checkOrientation(const PrimitivePatch< FaceList, PointField > &, const bool report=false, labelHashSet *marked=0)
Check for orientation issues.
static label markZones(const PrimitivePatch< FaceList, PointField > &, const BoolListType &borderEdge, labelList &faceZone)
Size and fills faceZone with zone of face.
This class describes the interaction of (usually) a face and a point. It carries the info of a succes...
Definition: PointIndexHit.H:54
label nEdges() const
Return number of edges in patch.
const labelListList & pointEdges() const
Return point-edge addressing.
const edgeList & edges() const
Return list of edges, address into LOCAL point list.
const labelList & meshPoints() const
Return labelList of mesh points in patch. They are constructed.
const Field< PointType > & points() const
Return reference to global points.
const labelListList & faceFaces() const
Return face-face addressing.
const labelListList & edgeFaces() const
Return edge-face addressing.
const Field< PointType > & localPoints() const
Return pointField of points in patch.
A list that is sorted upon construction or when explicitly requested with the sort() method.
Definition: SortableList.H:55
Extract command arguments and options from the supplied argc and argv parameters.
Definition: argList.H:103
static void addBoolOption(const word &opt, const string &usage="")
Add to a bool option to validOptions with usage information.
Definition: argList.C:118
bool optionFound(const word &opt) const
Return true if the named option is found.
Definition: argListI.H:114
static SLList< string > validArgs
A list of valid (mandatory) arguments.
Definition: argList.H:153
A bounding box defined in terms of the points at its extremities.
Definition: boundBox.H:59
tmp< pointField > points() const
Return corner points in an order corresponding to a 'hex' cell.
Definition: boundBox.C:149
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:61
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:68
A class for handling file names.
Definition: fileName.H:82
word name() const
Return file name (part beyond last /)
Definition: fileName.C:195
fileName path() const
Return directory path name (part before last /)
Definition: fileName.C:265
Non-pointer based hierarchical recursive searching.
Definition: indexedOctree.H:72
Triangle with additional region number.
Definition: labelledTri.H:60
Helper class to search on triSurface.
Triangulated surface description with patch information.
Definition: triSurface.H:69
triSurface subsetMesh(const boolList &include, labelList &pointMap, labelList &faceMap) const
Return new surface. Returns pointMap, faceMap from.
Definition: triSurface.C:1089
label markZones(const boolList &borderEdge, labelList &faceZone) const
(size and) fills faceZone with zone of face. Zone is area
Definition: triSurface.C:998
const geometricSurfacePatchList & patches() const
Definition: triSurface.H:322
void writeStats(Ostream &) const
Write some statistics.
Definition: triSurface.C:1352
A surfaceWriter for VTK legacy format with support for writing ASCII or binary.
virtual void write(const fileName &outputDir, const fileName &surfaceName, const pointField &points, const faceList &faces, const wordList &fieldNames, const bool writePointValues #define FieldTypeValuesConstArg(Type, nullArg)) const
Write fields for a single surface to file.
A class for handling words, derived from string.
Definition: word.H:62
Base class for zones.
Definition: zone.H:60
int main(int argc, char *argv[])
Definition: financialFoam.C:44
label patchi
#define WarningInFunction
Report a warning using Foam::Warning.
Namespace for OpenFOAM.
const doubleScalar e
Definition: doubleScalar.H:105
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
label findMax(const ListType &, const label start=0)
Find index of max element (and larger than given element).
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
word name(const bool)
Return a word representation of a bool.
Definition: boolIO.C:39
messageStream Info
layerAndWeight min(const layerAndWeight &a, const layerAndWeight &b)
dimensioned< scalar > mag(const dimensioned< Type > &)
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
label findMin(const ListType &, const label start=0)
Find index of min element (and less than given element).
fileType
Enumeration of file types.
Definition: fileName.H:67
triangle< point, const point & > triPointRef
Definition: triPointRef.H:44
static const char nl
Definition: Ostream.H:260
labelList f(nPoints)
Foam::argList args(argc, argv)