triSurfaceMesh.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-2024 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 \*---------------------------------------------------------------------------*/
25 
26 #include "triSurfaceMesh.H"
27 #include "randomGenerator.H"
29 #include "EdgeMap.H"
30 #include "triSurfaceFields.H"
31 #include "Time.H"
32 #include "PatchTools.H"
33 
34 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
35 
36 namespace Foam
37 {
40 }
41 
42 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
43 
44 Foam::fileName Foam::triSurfaceMesh::checkFile
45 (
46  const regIOobject& io,
47  const bool isGlobal
48 )
49 {
50  const fileName fName(io.filePath(typeName, isGlobal));
51 
52  if (fName.empty())
53  {
55  << "Cannot find triSurfaceMesh file starting from "
56  << io.objectPath() << exit(FatalError);
57  }
58 
59  return fName;
60 }
61 
62 
63 Foam::fileName Foam::triSurfaceMesh::relativeFilePath
64 (
65  const regIOobject& io,
66  const fileName& f,
67  const bool isGlobal
68 )
69 {
70  fileName fName(f);
71  fName.expand();
72  if (!fName.isAbsolute())
73  {
74  // Is the specified file:
75  // - local to the cwd?
76  // - local to the case dir?
77  // - or just another name?
78  fName = fileHandler().filePath
79  (
80  isGlobal,
81  IOobject(io, fName),
83  );
84  }
85  return fName;
86 }
87 
88 
89 Foam::fileName Foam::triSurfaceMesh::checkFile
90 (
91  const regIOobject& io,
92  const dictionary& dict,
93  const bool isGlobal
94 )
95 {
96  fileName dictFName, fName;
97 
98  if (dict.readIfPresent("file", dictFName, false, false))
99  {
100  fName = relativeFilePath(io, dictFName, isGlobal);
101 
102  if (!exists(fName))
103  {
105  << "Cannot find triSurfaceMesh file " << io.path()/dictFName
106  << exit(FatalError);
107  }
108  }
109  else
110  {
111  fName = io.filePath(typeName, isGlobal);
112 
113  if (!exists(fName))
114  {
116  << "Cannot find triSurfaceMesh file starting from "
117  << io.objectPath() << exit(FatalError);
118  }
119  }
120 
121  return fName;
122 }
123 
124 
125 bool Foam::triSurfaceMesh::addFaceToEdge
126 (
127  const edge& e,
128  EdgeMap<label>& facesPerEdge
129 )
130 {
131  EdgeMap<label>::iterator eFnd = facesPerEdge.find(e);
132  if (eFnd != facesPerEdge.end())
133  {
134  if (eFnd() == 2)
135  {
136  return false;
137  }
138  eFnd()++;
139  }
140  else
141  {
142  facesPerEdge.insert(e, 1);
143  }
144  return true;
145 }
146 
147 
148 bool Foam::triSurfaceMesh::isSurfaceClosed() const
149 {
150  const pointField& pts = triSurface::points();
151 
152  // Construct pointFaces. Let's hope surface has compact point
153  // numbering ...
154  labelListList pointFaces;
155  invertManyToMany(pts.size(), *this, pointFaces);
156 
157  // Loop over all faces surrounding point. Count edges emanating from point.
158  // Every edge should be used by two faces exactly.
159  // To prevent doing work twice per edge only look at edges to higher
160  // point
161  EdgeMap<label> facesPerEdge(100);
162  forAll(pointFaces, pointi)
163  {
164  const labelList& pFaces = pointFaces[pointi];
165 
166  facesPerEdge.clear();
167  forAll(pFaces, i)
168  {
170  label fp = findIndex(f, pointi);
171 
172  // Something weird: if I expand the code of addFaceToEdge in both
173  // below instances it gives a segmentation violation on some
174  // surfaces. Compiler (4.3.2) problem?
175 
176 
177  // Forward edge
178  label nextPointi = f[f.fcIndex(fp)];
179 
180  if (nextPointi > pointi)
181  {
182  bool okFace = addFaceToEdge
183  (
184  edge(pointi, nextPointi),
185  facesPerEdge
186  );
187 
188  if (!okFace)
189  {
190  return false;
191  }
192  }
193  // Reverse edge
194  label prevPointi = f[f.rcIndex(fp)];
195 
196  if (prevPointi > pointi)
197  {
198  bool okFace = addFaceToEdge
199  (
200  edge(pointi, prevPointi),
201  facesPerEdge
202  );
203 
204  if (!okFace)
205  {
206  return false;
207  }
208  }
209  }
210 
211  // Check for any edges used only once.
212  forAllConstIter(EdgeMap<label>, facesPerEdge, iter)
213  {
214  if (iter() != 2)
215  {
216  return false;
217  }
218  }
219  }
220 
221  return true;
222 }
223 
224 
225 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
226 
228 :
229  searchableSurface(io),
231  (
232  IOobject
233  (
234  io.name(),
235  io.instance(),
236  io.local(),
237  io.db(),
238  io.readOpt(),
239  io.writeOpt(),
240  false // searchableSurface already registered under name
241  )
242  ),
243  triSurface(s),
245  minQuality_(-1),
246  surfaceClosed_(-1)
247 {
248  const pointField& pts = triSurface::points();
249 
250  bounds() = boundBox(pts);
251 }
252 
253 
255 :
256  // Find instance for triSurfaceMesh
257  searchableSurface(io),
258  // Reused found instance in objectRegistry
260  (
261  IOobject
262  (
263  io.name(),
264  searchableSurface::instance(),
265  io.local(),
266  io.db(),
267  io.readOpt(),
268  io.writeOpt(),
269  false // searchableSurface already registered under name
270  )
271  ),
272  triSurface(checkFile(static_cast<const searchableSurface&>(*this), true)),
273  triSurfaceRegionSearch(static_cast<const triSurface&>(*this)),
274  minQuality_(-1),
275  surfaceClosed_(-1)
276 {
277  const pointField& pts = triSurface::points();
278 
279  bounds() = boundBox(pts);
280 }
281 
282 
284 (
285  const IOobject& io,
286  const dictionary& dict
287 )
288 :
289  searchableSurface(io),
290  // Reused found instance in objectRegistry
292  (
293  IOobject
294  (
295  io.name(),
296  searchableSurface::instance(),
297  io.local(),
298  io.db(),
299  io.readOpt(),
300  io.writeOpt(),
301  false // searchableSurface already registered under name
302  )
303  ),
304  triSurface
305  (
306  checkFile(static_cast<const searchableSurface&>(*this), dict, true)
307  ),
308  triSurfaceRegionSearch(static_cast<const triSurface&>(*this), dict),
309  fName_
310  (
311  relativeFilePath
312  (
313  static_cast<const searchableSurface&>(*this),
314  dict.lookup("file", false, false),
315  true
316  )
317  ),
318  minQuality_(-1),
319  surfaceClosed_(-1)
320 {
321  scalar scaleFactor = 0;
322 
323  // Allow rescaling of the surface points
324  // eg, CAD geometries are often done in millimeters
325  if (dict.readIfPresent("scale", scaleFactor) && scaleFactor > 0)
326  {
327  Info<< searchableSurface::name() << " : using scale " << scaleFactor
328  << endl;
329  triSurface::scalePoints(scaleFactor);
330  }
331 
332  const pointField& pts = triSurface::points();
333 
334  bounds() = boundBox(pts);
335 
336  // Have optional minimum quality for normal calculation
337  if (dict.readIfPresent("minQuality", minQuality_) && minQuality_ > 0)
338  {
340  << " : ignoring triangles with quality < "
341  << minQuality_ << " for normals calculation." << endl;
342  }
343 }
344 
345 
346 Foam::triSurfaceMesh::triSurfaceMesh(const IOobject& io, const bool isGlobal)
347 :
348  // Find instance for triSurfaceMesh
349  searchableSurface(io),
350  // Reused found instance in objectRegistry
352  (
353  IOobject
354  (
355  io.name(),
356  searchableSurface::instance(),
357  io.local(),
358  io.db(),
359  io.readOpt(),
360  io.writeOpt(),
361  false // searchableSurface already registered under name
362  )
363  ),
364  triSurface
365  (
366  checkFile(static_cast<const searchableSurface&>(*this), isGlobal)
367  ),
368  triSurfaceRegionSearch(static_cast<const triSurface&>(*this)),
369  minQuality_(-1),
370  surfaceClosed_(-1)
371 {
372  const pointField& pts = triSurface::points();
373 
374  bounds() = boundBox(pts);
375 }
376 
377 
379 (
380  const IOobject& io,
381  const dictionary& dict,
382  const bool isGlobal
383 )
384 :
385  searchableSurface(io),
386  // Reused found instance in objectRegistry
388  (
389  IOobject
390  (
391  io.name(),
392  searchableSurface::instance(),
393  io.local(),
394  io.db(),
395  io.readOpt(),
396  io.writeOpt(),
397  false // searchableSurface already registered under name
398  )
399  ),
400  triSurface
401  (
402  checkFile(static_cast<const searchableSurface&>(*this), dict, isGlobal)
403  ),
404  triSurfaceRegionSearch(static_cast<const triSurface&>(*this), dict),
405  minQuality_(-1),
406  surfaceClosed_(-1)
407 {
408  // Reading from supplied file name instead of objectPath/filePath
409  if (dict.readIfPresent("file", fName_, false, false))
410  {
411  fName_ = relativeFilePath
412  (
413  static_cast<const searchableSurface&>(*this),
414  fName_,
415  isGlobal
416  );
417  }
418 
419  scalar scaleFactor = 0;
420 
421  // Allow rescaling of the surface points
422  // eg, CAD geometries are often done in millimeters
423  if (dict.readIfPresent("scale", scaleFactor) && scaleFactor > 0)
424  {
425  Info<< searchableSurface::name() << " : using scale " << scaleFactor
426  << endl;
427  triSurface::scalePoints(scaleFactor);
428  }
429 
430  const pointField& pts = triSurface::points();
431 
432  bounds() = boundBox(pts);
433 
434  // Have optional minimum quality for normal calculation
435  if (dict.readIfPresent("minQuality", minQuality_) && minQuality_ > 0)
436  {
438  << " : ignoring triangles with quality < "
439  << minQuality_ << " for normals calculation." << endl;
440  }
441 }
442 
443 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
444 
446 {
447  clearOut();
448 }
449 
450 
452 {
454  edgeTree_.clear();
456 }
457 
458 
459 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
460 
462 {
463  tmp<pointField> tPts(new pointField(8));
464  pointField& pt = tPts.ref();
465 
466  // Use copy to calculate face centres so they don't get stored
468  (
471  ).faceCentres();
472 
473  return tPts;
474 }
475 
476 
478 (
479  pointField& centres,
480  scalarField& radiusSqr
481 ) const
482 {
483  centres = coordinates();
484  radiusSqr.setSize(size());
485  radiusSqr = 0.0;
486 
487  const pointField& pts = triSurface::points();
488 
489  forAll(*this, facei)
490  {
491  const labelledTri& f = triSurface::operator[](facei);
492  const point& fc = centres[facei];
493  forAll(f, fp)
494  {
495  const point& pt = pts[f[fp]];
496  radiusSqr[facei] = max(radiusSqr[facei], Foam::magSqr(fc-pt));
497  }
498  }
499 
500  // Add a bit to make sure all points are tested inside
501  radiusSqr += Foam::sqr(small);
502 }
503 
504 
506 {
507  return triSurface::points();
508 }
509 
510 
512 {
513  const indexedOctree<treeDataTriSurface>& octree = tree();
514 
515  labelList indices = octree.findBox(treeBoundBox(bb));
516 
517  return !indices.empty();
518 }
519 
520 
522 {
524  edgeTree_.clear();
525  triSurface::setPoints(newPoints);
526 }
527 
528 
531 {
532  if (edgeTree_.empty())
533  {
534  // Boundary edges
535  labelList bEdges
536  (
538  (
539  nEdges()
540  -nInternalEdges()
541  )
542  + nInternalEdges()
543  );
544 
545  treeBoundBox bb(Zero, Zero);
546 
547  if (bEdges.size())
548  {
549  label nPoints;
551  (
552  *this,
553  bb,
554  nPoints
555  );
556 
557  // Slightly extended bb. Slightly off-centred just so on symmetric
558  // geometry there are less face/edge aligned items.
559  bb = bb.extend(1e-4);
560  }
561 
562  scalar oldTol = indexedOctree<treeDataEdge>::perturbTol();
564 
565  edgeTree_.reset
566  (
568  (
570  (
571  false, // cachebb
572  edges(), // edges
573  localPoints(), // points
574  bEdges // selected edges
575  ),
576  bb, // bb
577  maxTreeDepth(), // maxLevel
578  10, // leafsize
579  3.0 // duplicity
580  )
581  );
582 
584  }
585  return edgeTree_();
586 }
587 
588 
590 {
591  if (regions_.empty())
592  {
593  regions_.setSize(patches().size());
594  forAll(regions_, regionI)
595  {
596  regions_[regionI] = patches()[regionI].name();
597  }
598  }
599  return regions_;
600 }
601 
602 
604 {
605  if (surfaceClosed_ == -1)
606  {
607  if (isSurfaceClosed())
608  {
609  surfaceClosed_ = 1;
610  }
611  else
612  {
613  surfaceClosed_ = 0;
614  }
615  }
616 
617  return surfaceClosed_ == 1;
618 }
619 
620 
622 (
623  const pointField& samples,
624  const scalarField& nearestDistSqr,
625  List<pointIndexHit>& info
626 ) const
627 {
628  triSurfaceSearch::findNearest(samples, nearestDistSqr, info);
629 }
630 
631 
633 (
634  const pointField& samples,
635  const scalarField& nearestDistSqr,
636  const labelList& regionIndices,
637  List<pointIndexHit>& info
638 ) const
639 {
641  (
642  samples,
643  nearestDistSqr,
644  regionIndices,
645  info
646  );
647 }
648 
649 
651 (
652  const pointField& start,
653  const pointField& end,
654  List<pointIndexHit>& info
655 ) const
656 {
657  triSurfaceSearch::findLine(start, end, info);
658 }
659 
660 
662 (
663  const pointField& start,
664  const pointField& end,
665  List<pointIndexHit>& info
666 ) const
667 {
668  triSurfaceSearch::findLineAny(start, end, info);
669 }
670 
671 
673 (
674  const pointField& start,
675  const pointField& end,
677 ) const
678 {
679  triSurfaceSearch::findLineAll(start, end, info);
680 }
681 
682 
684 (
685  const List<pointIndexHit>& info,
686  labelList& region
687 ) const
688 {
689  region.setSize(info.size());
690  forAll(info, i)
691  {
692  if (info[i].hit())
693  {
694  region[i] = triSurface::operator[](info[i].index()).region();
695  }
696  else
697  {
698  region[i] = -1;
699  }
700  }
701 }
702 
703 
705 (
706  const List<pointIndexHit>& info,
707  vectorField& normal
708 ) const
709 {
710  const triSurface& s = *this;
711  const pointField& pts = s.points();
712 
713  normal.setSize(info.size());
714 
715  if (minQuality_ >= 0)
716  {
717  // Make sure we don't use triangles with low quality since
718  // normal is not reliable.
719 
720  const labelListList& faceFaces = s.faceFaces();
721 
722  forAll(info, i)
723  {
724  if (info[i].hit())
725  {
726  label facei = info[i].index();
727  normal[i] = s[facei].area(pts);
728 
729  scalar qual = s[facei].tri(pts).quality();
730 
731  if (qual < minQuality_)
732  {
733  // Search neighbouring triangles
734  const labelList& fFaces = faceFaces[facei];
735 
736  forAll(fFaces, j)
737  {
738  label nbrI = fFaces[j];
739  scalar nbrQual = s[nbrI].tri(pts).quality();
740  if (nbrQual > qual)
741  {
742  qual = nbrQual;
743  normal[i] = s[nbrI].area(pts);
744  }
745  }
746  }
747 
748  normal[i] /= mag(normal[i]) + vSmall;
749  }
750  else
751  {
752  // Set to what?
753  normal[i] = Zero;
754  }
755  }
756  }
757  else
758  {
759  forAll(info, i)
760  {
761  if (info[i].hit())
762  {
763  label facei = info[i].index();
764  // Cached:
765  // normal[i] = faceNormals()[facei];
766 
767  // Uncached
768  normal[i] = s[facei].normal(pts);
769  }
770  else
771  {
772  // Set to what?
773  normal[i] = Zero;
774  }
775  }
776  }
777 }
778 
779 
781 (
782  const pointField& points,
783  List<volumeType>& volType
784 ) const
785 {
786  volType.setSize(points.size());
787 
790 
791  forAll(points, pointi)
792  {
793  const point& pt = points[pointi];
794 
795  if (!tree().bb().contains(pt))
796  {
797  // Have to calculate directly as outside the octree
798  volType[pointi] = tree().shapes().getVolumeType(tree(), pt);
799  }
800  else
801  {
802  // - use cached volume type per each tree node
803  volType[pointi] = tree().getVolumeType(pt);
804  }
805  }
806 
808 }
809 
810 
812 {
814  (
816  (
817  IOobject
818  (
819  "values",
822  *this,
825  ),
826  *this,
827  dimless,
828  labelField(values)
829  )
830  );
831 
832  // Store field on triMesh
833  fldPtr.ptr()->store();
834 }
835 
836 
838 (
839  const List<pointIndexHit>& info,
840  labelList& values
841 ) const
842 {
843  if (foundObject<triSurfaceLabelField>("values"))
844  {
845  values.setSize(info.size());
846 
847  const triSurfaceLabelField& fld = lookupObject<triSurfaceLabelField>
848  (
849  "values"
850  );
851 
852  forAll(info, i)
853  {
854  if (info[i].hit())
855  {
856  values[i] = fld[info[i].index()];
857  }
858  }
859  }
860 }
861 
862 
864 (
868  const bool write
869 ) const
870 {
871  fileName fullPath;
872  if (fName_.size())
873  {
874  // Override file name
875 
876  fullPath = fName_;
877 
878  fullPath.expand();
879  if (!fullPath.isAbsolute())
880  {
881  // Add directory from regIOobject
882  fullPath = searchableSurface::objectPath().path()/fullPath;
883  }
884  }
885  else
886  {
887  fullPath = searchableSurface::objectPath();
888  }
889 
890  if (!mkDir(fullPath.path()))
891  {
892  return false;
893  }
894 
895  triSurface::write(fullPath);
896 
897  if (!isFile(fullPath))
898  {
899  return false;
900  }
901 
902  return true;
903 }
904 
905 
906 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:477
Macros for easy insertion into run-time selection tables.
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
friend class iterator
Declare friendship with the iterator.
Definition: HashTable.H:194
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
const word & name() const
Return name.
Definition: IOobject.H:310
Version number type.
Definition: IOstream.H:97
streamFormat
Enumeration for the format of data in the stream.
Definition: IOstream.H:87
compressionType
Enumeration for the format of data in the stream.
Definition: IOstream.H:194
label size() const
Return the number of elements in the UList.
Definition: ListI.H:171
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
void setSize(const label)
Reset size of List.
Definition: List.C:281
static void calcBounds(const PrimitivePatch< FaceList, PointField > &p, boundBox &bb, label &nPoints)
A list of faces which address into the list of points.
const Field< PointType > & points() const
Return reference to global points.
std::remove_reference< ::Foam::List< labelledTri > >::type::value_type FaceType
A List obtained as a section of another List.
Definition: SubList.H:56
label rcIndex(const label i) const
Return the reverse circular index, i.e. the previous index.
Definition: UListI.H:65
label fcIndex(const label i) const
Return the forward circular index, i.e. the next index.
Definition: UListI.H:58
bool empty() const
Return true if the UList is empty (ie, size() is zero)
Definition: UListI.H:325
T & operator[](const label)
Return element of UList.
Definition: UListI.H:167
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: autoPtr.H:51
T * ptr()
Return object pointer for reuse.
Definition: autoPtrI.H:90
A bounding box defined in terms of the points at its extremities.
Definition: boundBox.H:59
A list of keyword definitions, which are a keyword followed by any number of values (e....
Definition: dictionary.H:162
bool readIfPresent(const word &, T &, bool recursive=false, bool patternMatch=true) const
Find an entry if present, and assign to T.
A class for handling file names.
Definition: fileName.H:82
bool isAbsolute() const
Return true if file name is absolute.
Definition: fileName.C:73
fileName path() const
Return directory path name (part before last /)
Definition: fileName.C:265
virtual fileName filePath(const bool globalFile, const IOobject &, const word &typeName) const =0
Search for an object. globalFile : also check undecomposed case.
Non-pointer based hierarchical recursive searching.
Definition: indexedOctree.H:72
static scalar & perturbTol()
Get the perturbation tolerance.
Triangle with additional region number.
Definition: labelledTri.H:60
Registry of regIOobjects.
const Time & time() const
Return time.
fileName objectPath() const
Return complete path + object name.
Definition: regIOobject.H:158
Base class of (analytical or triangulated) surface. Encapsulates all the search routines....
static const word & geometryDir()
Return the geometry directory name.
const boundBox & bounds() const
Return const reference to boundBox.
string & expand(const bool allowEmpty=false)
Expand initial tildes and all occurrences of environment variables.
Definition: string.C:125
A class for managing temporary objects.
Definition: tmp.H:55
T & ref() const
Return non-const reference or generate a fatal error.
Definition: tmpI.H:181
Standard boundBox + extra functionality for use in octree.
Definition: treeBoundBox.H:90
treeBoundBox extend(const scalar s) const
Return asymmetrically extended bounding box, with guaranteed.
Holds data for octree to work on an edges subset.
Definition: treeDataEdge.H:54
A surface geometry formed of discrete facets, e.g. triangles and/or quadrilaterals,...
triSurfaceMesh(const IOobject &, const triSurface &)
Construct from triSurface.
virtual void getVolumeType(const pointField &, List< volumeType > &) const
Determine type (inside/outside/mixed) for point. unknown if.
virtual ~triSurfaceMesh()
Destructor.
virtual void findLine(const pointField &start, const pointField &end, List< pointIndexHit > &) const
Find first intersection on segment from start to end.
virtual bool overlaps(const boundBox &bb) const
Does any part of the surface overlap the supplied bound box?
const indexedOctree< treeDataEdge > & edgeTree() const
Demand driven construction of octree for boundary edges.
virtual void findLineAny(const pointField &start, const pointField &end, List< pointIndexHit > &) const
Return any intersection on segment from start to end.
virtual void boundingSpheres(pointField &centres, scalarField &radiusSqr) const
Get bounding spheres (centre and radius squared). Any point.
virtual void setField(const labelList &values)
WIP. Store element-wise field.
virtual void getField(const List< pointIndexHit > &, labelList &) const
WIP. From a set of hits (points and.
virtual bool writeObject(IOstream::streamFormat fmt, IOstream::versionNumber ver, IOstream::compressionType cmp, const bool write=true) const
Write using given format, version and compression.
virtual void getNormal(const List< pointIndexHit > &, vectorField &normal) const
From a set of points and indices get the normal.
virtual void getRegion(const List< pointIndexHit > &, labelList &region) const
From a set of points and indices get the region.
virtual const wordList & regions() const
Names of regions.
virtual bool hasVolumeType() const
Whether supports volume type below. I.e. whether is closed.
virtual void findNearest(const pointField &sample, const scalarField &nearestDistSqr, List< pointIndexHit > &) const
virtual tmp< pointField > coordinates() const
Get representative set of element coordinates.
virtual void findLineAll(const pointField &start, const pointField &end, List< List< pointIndexHit >> &) const
Get all intersections in order from start to end.
void clearOut()
Clear storage.
virtual void setPoints(const pointField &)
Move points.
virtual tmp< pointField > points() const
Get the points that define the surface.
Helper class to search on triSurface. Creates an octree for each region of the surface and only searc...
void findNearest(const pointField &samples, const scalarField &nearestDistSqr, const labelList &regionIndices, List< pointIndexHit > &info) const
Find the nearest point on the surface out of the regions.
void findLineAll(const pointField &start, const pointField &end, List< List< pointIndexHit >> &info) const
Calculate all intersections from start to end.
void findLine(const pointField &start, const pointField &end, List< pointIndexHit > &info) const
void findLineAny(const pointField &start, const pointField &end, List< pointIndexHit > &info) const
void findNearest(const pointField &samples, const scalarField &nearestDistSqr, List< pointIndexHit > &info) const
Triangulated surface description with patch information.
Definition: triSurface.H:69
virtual void scalePoints(const scalar)
Scale points. A non-positive factor is ignored.
Definition: triSurface.C:750
virtual void setPoints(const pointField &)
Move points.
Definition: triSurface.C:737
static const word null
An empty word.
Definition: word.H:77
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
const pointField & points
label nPoints
gmvFile<< "tracers "<< particles.size()<< nl;{ pointField positions(particles.size());label particlei=0;forAllConstIter(Cloud< passiveParticle >, particles, iter) { positions[particlei++]=iter().position(mesh);} for(i=0;i< pTraits< point >::nComponents;i++) { forAll(positions, particlei) { gmvFile<< component(positions[particlei], i)<< ' ';} gmvFile<< nl;}}forAll(lagrangianScalarNames, i){ const word &name=lagrangianScalarNames[i];IOField< scalar > fld(IOobject(name, runTime.name(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
gmvFile<< "tracers "<< particles.size()<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().x()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().y()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.name(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
const fvPatchList & patches
void write(std::ostream &os, const bool binary, List< floatScalar > &fField)
Write floats ascii or binary.
Namespace for OpenFOAM.
bool isFile(const fileName &, const bool checkVariants=true, const bool followLink=true)
Does the name exist as a file in the file system?
Definition: POSIX.C:555
const fileOperation & fileHandler()
Get current file handler.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
static const zero Zero
Definition: zero.H:97
const doubleScalar e
Definition: doubleScalar.H:106
List< label > labelList
A List of labels.
Definition: labelList.H:56
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
addToRunTimeSelectionTable(polyPatch, mergedCyclicPolyPatch, word)
dimensionedSymmTensor sqr(const dimensionedVector &dv)
bool mkDir(const fileName &, mode_t=0777)
Make a directory and return an error if it could not be created.
Definition: POSIX.C:290
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:257
word name(const bool)
Return a word representation of a bool.
Definition: boolIO.C:39
const dimensionSet dimless
bool exists(const fileName &, const bool checkVariants=true, const bool followLink=true)
Does the name exist (as directory or file) in the file system?
Definition: POSIX.C:520
messageStream Info
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:57
dimensioned< scalar > mag(const dimensioned< Type > &)
defineTypeNameAndDebug(combustionModel, 0)
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
Field< label > labelField
Specialisation of Field<T> for label.
Definition: labelField.H:49
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurrence of given element and return index,.
error FatalError
labelList identityMap(const label len)
Create identity map (map[i] == i) of given length.
Definition: ListOps.C:104
dimensioned< scalar > magSqr(const dimensioned< Type > &)
void invertManyToMany(const label len, const UList< InList > &, List< OutList > &)
Invert many-to-many.
labelList f(nPoints)
Info<< "Finished reading KIVA file"<< endl;cellShapeList cellShapes(nPoints);labelList cellZoning(nPoints, -1);const cellModel &hex=*(cellModeller::lookup("hex"));labelList hexLabels(8);label activeCells=0;labelList pointMap(nPoints);forAll(pointMap, i){ pointMap[i]=i;}for(label i=0;i< nPoints;i++){ if(f[i] > 0.0) { hexLabels[0]=i;hexLabels[1]=i1tab[i];hexLabels[2]=i3tab[i1tab[i]];hexLabels[3]=i3tab[i];hexLabels[4]=i8tab[i];hexLabels[5]=i1tab[i8tab[i]];hexLabels[6]=i3tab[i1tab[i8tab[i]]];hexLabels[7]=i3tab[i8tab[i]];cellShapes[activeCells]=cellShape(hex, hexLabels);edgeList edges=cellShapes[activeCells].edges();forAll(edges, ei) { if(edges[ei].mag(points)< small) { label start=pointMap[edges[ei].start()];while(start !=pointMap[start]) { start=pointMap[start];} label end=pointMap[edges[ei].end()];while(end !=pointMap[end]) { end=pointMap[end];} label minLabel=min(start, end);pointMap[start]=pointMap[end]=minLabel;} } cellZoning[activeCells]=idreg[i];activeCells++;}}cellShapes.setSize(activeCells);cellZoning.setSize(activeCells);forAll(cellShapes, celli){ cellShape &cs=cellShapes[celli];forAll(cs, i) { cs[i]=pointMap[cs[i]];} cs.collapse();}label bcIDs[11]={-1, 0, 2, 4, -1, 5, -1, 6, 7, 8, 9};const label nBCs=12;const word *kivaPatchTypes[nBCs]={ &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &symmetryPolyPatch::typeName, &wedgePolyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &symmetryPolyPatch::typeName, &mergedCyclicPolyPatch::typeName};enum patchTypeNames{ PISTON, VALVE, LINER, CYLINDERHEAD, AXIS, WEDGE, INFLOW, OUTFLOW, PRESIN, PRESOUT, SYMMETRYPLANE, CYCLIC};const char *kivaPatchNames[nBCs]={ "piston", "valve", "liner", "cylinderHead", "axis", "wedge", "inflow", "outflow", "presin", "presout", "symmetryPlane", "cyclic"};List< SLList< face > > pFaces[nBCs]
Definition: readKivaGrid.H:229
dictionary dict
Fields for triSurface.
scalarField samples(nIntervals, 0)