searchableSurfaces.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-2017 OpenFOAM Foundation
9  Copyright (C) 2015-2022 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 "searchableSurfaces.H"
31 #include "ListOps.H"
32 #include "Time.H"
33 #include "DynamicField.H"
34 #include "PatchTools.H"
35 #include "coordSetWriter.H"
36 #include "triSurfaceMesh.H"
37 
38 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
39 
40 namespace Foam
41 {
42  defineTypeNameAndDebug(searchableSurfaces, 0);
43 }
44 
45 
46 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
47 
48 bool Foam::searchableSurfaces::connected
49 (
50  const triSurface& s,
51  const label edgeI,
52  const pointIndexHit& hit
53 )
54 {
55  const edge& e = s.edges()[edgeI];
56  const labelList& mp = s.meshPoints();
57  const edge meshE(mp[e[0]], mp[e[1]]);
58 
59  const triFace& f = s[hit.index()];
60 
61  forAll(f, i)
62  {
63  if (meshE.otherVertex(f[i]) != -1)
64  {
65  return true;
66  }
67  }
68 
69  // Account for triangle intersection routine going wrong for
70  // lines in same plane as triangle. Tbd!
71 
72  vector eVec(meshE.vec(s.points()));
73  scalar magEVec(mag(eVec));
74  if (magEVec > ROOTVSMALL)
75  {
76  vector n(f.areaNormal(s.points()));
77  scalar magArea(mag(n));
78  if (magArea > ROOTVSMALL)
79  {
80  n /= magArea;
81  if (mag(n&(eVec/magEVec)) < SMALL)
82  {
83  // Bad intersection
84  return true;
85  }
86  else
87  {
88  return false;
89  }
90  }
91  }
92 
93  return true;
94 }
95 
96 
97 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
98 
99 Foam::searchableSurfaces::searchableSurfaces(const label size)
100 :
101  PtrList<searchableSurface>(size),
102  regionNames_(size),
103  allSurfaces_(identity(size))
104 {}
105 
106 
107 //Foam::searchableSurfaces::searchableSurfaces
108 //(
109 // const IOobject& io,
110 // const PtrList<dictionary>& dicts
111 //)
112 //:
113 // PtrList<searchableSurface>(dicts.size()),
114 // regionNames_(dicts.size()),
115 // allSurfaces_(identity(dicts.size()))
116 //{
117 // forAll(dicts, surfI)
118 // {
119 // const dictionary& dict = dicts[surfI];
120 //
121 // // Make IOobject with correct name
122 // autoPtr<IOobject> namedIO(io.clone());
123 // namedIO().rename(dict.get<word>("name"));
124 //
125 // // Create and hook surface
126 // set
127 // (
128 // surfI,
129 // searchableSurface::New
130 // (
131 // dict.get<word>("type"),
132 // namedIO(),
133 // dict
134 // )
135 // );
136 // const searchableSurface& s = operator[](surfI);
137 //
138 // // Construct default region names by prepending surface name
139 // // to region name.
140 // const wordList& localNames = s.regions();
141 //
142 // wordList globalNames(localNames.size());
143 // forAll(localNames, regionI)
144 // {
145 // globalNames[regionI] = s.name() + '_' + localNames[regionI];
146 // }
147 //
148 // // See if dictionary provides any global region names.
149 // if (dict.found("regions"))
150 // {
151 // const dictionary& regionsDict = dict.subDict("regions");
152 //
153 // for (const entry& dEntry : regionsDict)
154 // {
155 // if (dEntry.isDict())
156 // {
157 // const word& key = dEntry.keyword();
158 // const dictionary& regionDict = dEntry.dict();
159 //
160 // label index = localNames.find(key);
161 //
162 // if (index == -1)
163 // {
164 // FatalErrorInFunction
165 // << "Unknown region name " << key
166 // << " for surface " << s.name() << endl
167 // << "Valid region names are " << localNames
168 // << exit(FatalError);
169 // }
170 //
171 // globalNames[index] = regionDict.get<word>("name");
172 // }
173 // }
174 // }
175 //
176 // // Now globalNames contains the names of the regions.
177 // Info<< "Surface:" << s.name() << " has regions:"
178 // << endl;
179 // forAll(globalNames, regionI)
180 // {
181 // Info<< " " << globalNames[regionI] << endl;
182 // }
183 //
184 // // Create reverse lookup
185 // forAll(globalNames, regionI)
186 // {
187 // regionNames_.insert
188 // (
189 // globalNames[regionI],
190 // labelPair(surfI, regionI)
191 // );
192 // }
193 // }
194 //}
195 
196 
197 Foam::searchableSurfaces::searchableSurfaces
198 (
199  const IOobject& io,
200  const dictionary& topDict,
201  const bool singleRegionName
202 )
203 :
204  PtrList<searchableSurface>(topDict.size()),
205  names_(topDict.size()),
206  regionNames_(topDict.size()),
207  allSurfaces_(identity(topDict.size()))
208 {
209  label surfI = 0;
210 
211  for (const entry& dEntry : topDict)
212  {
213  if (!dEntry.isDict())
214  {
216  << "Found non-dictionary entry " << dEntry
217  << " in top-level dictionary " << topDict
218  << exit(FatalError);
219  }
220 
221  const word& key = dEntry.keyword();
222  const dictionary& dict = topDict.subDict(key);
223 
224  names_[surfI] = dict.getOrDefault<word>("name", key);
225 
226  // Make IOobject with correct name
227  autoPtr<IOobject> namedIO(io.clone());
228  // Note: we would like to e.g. register triSurface 'sphere.stl' as
229  // 'sphere'. Unfortunately
230  // no support for having object read from different location than
231  // their object name. Maybe have stlTriSurfaceMesh which appends .stl
232  // when reading/writing?
233  namedIO().rename(key); // names_[surfI]
234 
235  // Create and hook surface
236  set
237  (
238  surfI,
240  (
241  dict.get<word>("type"),
242  namedIO(),
243  dict
244  )
245  );
246  const searchableSurface& s = operator[](surfI);
247 
248  // Construct default region names by prepending surface name
249  // to region name.
250  const wordList& localNames = s.regions();
251 
252  wordList& rNames = regionNames_[surfI];
253  rNames.setSize(localNames.size());
254 
255  if (singleRegionName && localNames.size() == 1)
256  {
257  rNames[0] = names_[surfI];
258  }
259  else
260  {
261  forAll(localNames, regionI)
262  {
263  rNames[regionI] = names_[surfI] + '_' + localNames[regionI];
264  }
265  }
266 
267  // See if dictionary provides any global region names.
268  if (dict.found("regions"))
269  {
270  const dictionary& regionsDict = dict.subDict("regions");
271 
272  for (const entry& dEntry : regionsDict)
273  {
274  if (dEntry.isDict())
275  {
276  const word& key = dEntry.keyword();
277  const dictionary& regionDict = dEntry.dict();
278 
279  label index = localNames.find(key);
280 
281  if (index == -1)
282  {
284  << "Unknown region name " << key
285  << " for surface " << s.name() << nl
286  << "Valid region names are " << localNames
287  << endl
288  << exit(FatalError);
289  }
290 
291  rNames[index] = regionDict.get<word>("name");
292  }
293  }
294  }
295 
296  surfI++;
297  }
298 
299  // Trim (not really necessary since we don't allow non-dictionary entries)
301  names_.setSize(surfI);
302  regionNames_.setSize(surfI);
303  allSurfaces_.setSize(surfI);
304 }
305 
306 
307 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
308 
310 (
311  const word& wantedName
312 ) const
313 {
314  return names_.find(wantedName);
315 }
316 
317 
319 (
320  const word& surfaceName,
321  const word& regionName
322 ) const
323 {
324  const label surfaceIndex = findSurfaceID(surfaceName);
326  return this->operator[](surfaceIndex).regions().find(regionName);
327 }
328 
329 
330 // Find any intersection
332 (
333  const pointField& start,
334  const pointField& end,
335  labelList& hitSurfaces,
336  List<pointIndexHit>& hitInfo
337 ) const
338 {
340  (
341  *this,
342  allSurfaces_,
343  start,
344  end,
345  hitSurfaces,
346  hitInfo
347  );
348 }
349 
350 
352 (
353  const pointField& start,
354  const pointField& end,
355  labelListList& hitSurfaces,
356  List<List<pointIndexHit>>& hitInfo
357 ) const
358 {
360  (
361  *this,
362  allSurfaces_,
363  start,
364  end,
365  hitSurfaces,
366  hitInfo
367  );
368 }
369 
370 
371 //Find intersections of edge nearest to both endpoints.
373 (
374  const pointField& start,
375  const pointField& end,
376  labelList& surface1,
377  List<pointIndexHit>& hit1,
378  labelList& surface2,
379  List<pointIndexHit>& hit2
380 ) const
381 {
383  (
384  *this,
385  allSurfaces_,
386  start,
387  end,
388  surface1,
389  hit1,
390  surface2,
391  hit2
392  );
393 }
394 
395 
397 (
398  const pointField& samples,
399  const scalarField& nearestDistSqr,
400  labelList& nearestSurfaces,
401  List<pointIndexHit>& nearestInfo
402 ) const
403 {
405  (
406  *this,
407  allSurfaces_,
408  samples,
409  nearestDistSqr,
410  nearestSurfaces,
411  nearestInfo
412  );
413 }
414 
415 
417 (
418  const labelListList& regionIndices,
419  const pointField& samples,
420  const scalarField& nearestDistSqr,
421  labelList& nearestSurfaces,
422  List<pointIndexHit>& nearestInfo
423 ) const
424 {
426  (
427  *this,
428  allSurfaces_,
429  regionIndices,
430 
431  samples,
432  nearestDistSqr,
434  nearestSurfaces,
435  nearestInfo
436  );
437 }
438 
439 
441 {
443  (
444  *this,
445  allSurfaces_
446  );
447 }
448 
449 
450 bool Foam::searchableSurfaces::checkClosed(const bool report) const
451 {
452  if (report)
453  {
454  Info<< "Checking for closedness." << endl;
455  }
456 
457  bool hasError = false;
458 
459  forAll(*this, surfI)
460  {
461  if (!operator[](surfI).hasVolumeType())
462  {
463  hasError = true;
464 
465  if (report)
466  {
467  Info<< " " << names()[surfI]
468  << " : not closed" << endl;
469  }
470 
471  if (isA<triSurface>(operator[](surfI)))
472  {
473  const triSurface& s = dynamic_cast<const triSurface&>
474  (
475  operator[](surfI)
476  );
477  const labelListList& edgeFaces = s.edgeFaces();
478 
479  label nSingleEdges = 0;
480  forAll(edgeFaces, edgeI)
481  {
482  if (edgeFaces[edgeI].size() == 1)
483  {
484  nSingleEdges++;
485  }
486  }
487 
488  label nMultEdges = 0;
489  forAll(edgeFaces, edgeI)
490  {
491  if (edgeFaces[edgeI].size() > 2)
492  {
493  nMultEdges++;
494  }
495  }
496 
497  if (report && (nSingleEdges != 0 || nMultEdges != 0))
498  {
499  Info<< " connected to one face : "
500  << nSingleEdges << nl
501  << " connected to >2 faces : "
502  << nMultEdges << endl;
503  }
504  }
505  }
506  }
507 
508  if (report)
509  {
511  }
512 
513  return returnReduceOr(hasError);
514 }
515 
516 
517 bool Foam::searchableSurfaces::checkNormalOrientation(const bool report) const
518 {
519  if (report)
520  {
521  Info<< "Checking for normal orientation." << endl;
522  }
523 
524  bool hasError = false;
525 
526  forAll(*this, surfI)
527  {
528  if (isA<triSurface>(operator[](surfI)))
529  {
530  const triSurface& s = dynamic_cast<const triSurface&>
531  (
532  operator[](surfI)
533  );
534 
535  labelHashSet borderEdge(s.size()/1000);
536  PatchTools::checkOrientation(s, false, &borderEdge);
537  // Colour all faces into zones using borderEdge
538  labelList normalZone;
539  label nZones = PatchTools::markZones(s, borderEdge, normalZone);
540  if (nZones > 1)
541  {
542  hasError = true;
543 
544  if (report)
545  {
546  Info<< " " << names()[surfI]
547  << " : has multiple orientation zones ("
548  << nZones << ")" << endl;
549  }
550  }
551  }
552  }
553 
554  if (report)
555  {
556  Info<< endl;
557  }
558 
559  return returnReduceOr(hasError);
560 }
561 
562 
564 (
565  const scalar maxRatio,
566  const bool report
567 ) const
568 {
569  if (report)
570  {
571  Info<< "Checking for size." << endl;
572  }
573 
574  bool hasError = false;
575 
576  forAll(*this, i)
577  {
578  const boundBox& bb = operator[](i).bounds();
579 
580  for (label j = i+1; j < size(); j++)
581  {
582  scalar ratio = bb.mag()/operator[](j).bounds().mag();
583 
584  if (ratio > maxRatio || ratio < 1.0/maxRatio)
585  {
586  hasError = true;
587 
588  if (report)
589  {
590  Info<< " " << names()[i]
591  << " bounds differ from " << names()[j]
592  << " by more than a factor 100:" << nl
593  << " bounding box : " << bb << nl
594  << " bounding box : " << operator[](j).bounds()
595  << endl;
596  }
597  break;
598  }
599  }
600  }
601 
602  if (report)
603  {
604  Info<< endl;
605  }
606 
607  return returnReduceOr(hasError);
608 }
609 
610 
612 (
613  const scalar tolerance,
614  autoPtr<coordSetWriter>& setWriter,
615  const bool report
616 ) const
617 {
618  if (report)
619  {
620  Info<< "Checking for intersection." << endl;
621  }
622 
623  //cpuTime timer;
624 
625  bool hasError = false;
626 
627  forAll(*this, i)
628  {
629  if (isA<triSurfaceMesh>(operator[](i)))
630  {
631  const triSurfaceMesh& s0 = dynamic_cast<const triSurfaceMesh&>
632  (
633  operator[](i)
634  );
635  const edgeList& edges0 = s0.edges();
636  const pointField& localPoints0 = s0.localPoints();
637 
638  // Collect all the edge vectors
639  pointField start(edges0.size());
640  pointField end(edges0.size());
641  forAll(edges0, edgeI)
642  {
643  const edge& e = edges0[edgeI];
644  start[edgeI] = localPoints0[e[0]];
645  end[edgeI] = localPoints0[e[1]];
646  }
647 
648  // Test all other surfaces for intersection
649  forAll(*this, j)
650  {
651  List<pointIndexHit> hits;
652 
653  //if (i == j)
654  //{
655  // // Slightly shorten the edges to prevent finding lots of
656  // // intersections. The fast triangle intersection routine
657  // // has problems with rays passing through a point of the
658  // // triangle. Now done in 'connected' routine. Tbd.
659  // vectorField d
660  // (
661  // max(tolerance, 10*s0.tolerance())
662  // *(end-start)
663  // );
664  // start += d;
665  // end -= d;
666  //}
667 
668  operator[](j).findLineAny(start, end, hits);
669 
670  label nHits = 0;
671  DynamicField<point> intersections(edges0.size()/100);
672  DynamicField<label> intersectionEdge(intersections.capacity());
673 
674  forAll(hits, edgeI)
675  {
676  if
677  (
678  hits[edgeI].hit()
679  && (i != j || !connected(s0, edgeI, hits[edgeI]))
680  )
681  {
682  intersections.append(hits[edgeI].point());
683  intersectionEdge.append(edgeI);
684  nHits++;
685  }
686  }
687 
688  // tdb. What about distributedTriSurfaceMesh?
689  //reduce(nHits, sumOp<label>());
690 
691  if (nHits > 0)
692  {
693  if (report)
694  {
695  Info<< " " << names()[i]
696  << " intersects " << names()[j]
697  << " at " << nHits
698  << " locations."
699  << endl;
700 
701  if (setWriter && setWriter->enabled())
702  {
703  scalarField dist(mag(intersections));
704  coordSet track
705  (
706  names()[i] + '_' + names()[j],
707  "xyz",
708  std::move(intersections),
709  std::move(dist)
710  );
711 
712 
713  auto& writer = *setWriter;
714  writer.nFields(1);
715 
716  writer.open
717  (
718  track,
719  (
720  s0.searchableSurface::time().path()
721  / (track.name() + "_edgeIndex")
722  )
723  );
724 
725  fileName fName =
726  writer.write("edgeIndex", intersectionEdge);
727 
728  writer.close(true);
729 
730  Info<< " Wrote intersection locations to "
731  << fName << endl;
732  }
733  }
734 
735  hasError = true;
736  break;
737  }
738  }
739  }
740  }
741 
742  if (report)
743  {
744  Info<< endl;
745  }
746 
747  return returnReduceOr(hasError);
748 }
749 
750 
752 (
753  const scalar minQuality,
754  const bool report
755 ) const
756 {
757  if (report)
758  {
759  Info<< "Checking for triangle quality." << endl;
760  }
761 
762  bool hasError = false;
763 
764  forAll(*this, surfI)
765  {
766  if (isA<triSurface>(operator[](surfI)))
767  {
768  const triSurface& s = dynamic_cast<const triSurface&>
769  (
770  operator[](surfI)
771  );
772 
773  label nBadTris = 0;
774  forAll(s, facei)
775  {
776  const labelledTri& f = s[facei];
777 
778  scalar q = triPointRef
779  (
780  s.points()[f[0]],
781  s.points()[f[1]],
782  s.points()[f[2]]
783  ).quality();
784 
785  if (q < minQuality)
786  {
787  nBadTris++;
788  }
789  }
790 
791  if (nBadTris > 0)
792  {
793  hasError = true;
794 
795  if (report)
796  {
797  Info<< " " << names()[surfI]
798  << " : has " << nBadTris << " bad quality triangles "
799  << " (quality < " << minQuality << ")" << endl;
800  }
801  }
802  }
803  }
804 
805  if (report)
806  {
807  Info<< endl;
808  }
809 
810  return returnReduceOr(hasError);
811 
812 }
813 
814 
815 // Check all surfaces. Return number of failures.
817 (
818  const bool report
819 ) const
820 {
821  label noFailedChecks = 0;
822 
823  if (checkClosed(report))
824  {
825  noFailedChecks++;
826  }
827 
828  if (checkNormalOrientation(report))
829  {
830  noFailedChecks++;
831  }
832  return noFailedChecks;
833 }
834 
835 
837 (
838  const scalar maxRatio,
839  const scalar tol,
840  autoPtr<coordSetWriter>& setWriter,
841  const scalar minQuality,
842  const bool report
843 ) const
844 {
845  label noFailedChecks = 0;
846 
847  if (maxRatio > 0 && checkSizes(maxRatio, report))
848  {
849  noFailedChecks++;
850  }
851 
852  if (checkIntersection(tol, setWriter, report))
853  {
854  noFailedChecks++;
855  }
856 
857  if (checkQuality(minQuality, report))
858  {
859  noFailedChecks++;
860  }
861 
862  return noFailedChecks;
863 }
864 
865 
867 (
868  const List<wordList>& patchTypes,
869  Ostream& os
870 ) const
871 {
872  Info<< "Statistics." << endl;
873  forAll(*this, surfI)
874  {
875  Info<< " " << names()[surfI] << ':' << endl;
876 
877  const searchableSurface& s = operator[](surfI);
878 
879  Info<< " type : " << s.type() << nl
880  << " size : " << s.globalSize() << nl;
881  if (isA<triSurfaceMesh>(s))
882  {
883  const triSurfaceMesh& ts = dynamic_cast<const triSurfaceMesh&>(s);
884  Info<< " edges : " << ts.nEdges() << nl
885  << " points : " << ts.points()().size() << nl;
886  }
887  Info<< " bounds : " << s.bounds() << nl
888  << " closed : " << Switch(s.hasVolumeType()) << endl;
889 
890  if (patchTypes.size() && patchTypes[surfI].size() >= 1)
891  {
892  wordList unique(wordHashSet(patchTypes[surfI]).sortedToc());
893  Info<< " patches : ";
894  forAll(unique, i)
895  {
896  Info<< unique[i];
897  if (i < unique.size()-1)
898  {
899  Info<< ',';
900  }
901  }
902  Info<< endl;
903  }
904  }
906 }
907 
908 
909 // * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * * //
910 
912 (
913  const word& surfName
914 ) const
915 {
916  const label surfI = findSurfaceID(surfName);
917 
918  if (surfI < 0)
919  {
921  << "Surface named " << surfName << " not found." << nl
922  << "Available surface names: " << names_ << endl
923  << abort(FatalError);
924  }
925 
926  return operator[](surfI);
927 }
928 
929 
931 (
932  const word& surfName
933 )
934 {
935  const label surfI = findSurfaceID(surfName);
936 
937  if (surfI < 0)
938  {
940  << "Surface named " << surfName << " not found." << nl
941  << "Available surface names: " << names_ << endl
942  << abort(FatalError);
943  }
944 
945  return operator[](surfI);
946 }
947 
948 
949 // ************************************************************************* //
static bool checkOrientation(const PrimitivePatch< FaceList, PointField > &, const bool report=false, labelHashSet *marked=0)
Check for orientation issues.
dictionary dict
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
List< word > names(const UPtrList< T > &list, const UnaryMatchPredicate &matcher)
List of names generated by calling name() for each list item and filtered for matches.
label checkTopology(const bool report) const
All topological checks. Return number of failed checks.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
vtk::lineWriter writer(edgeCentres, edgeList::null(), fileName(aMesh.time().globalPath()/"finiteArea-edgesCentres"))
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:598
List< edge > edgeList
List of edge.
Definition: edgeList.H:32
static void findNearest(const PtrList< searchableSurface > &, const labelList &surfacesToTest, const pointField &, const scalarField &nearestDistSqr, labelList &surfaces, List< pointIndexHit > &)
Find nearest. Return -1 (and a miss()) or surface and nearest.
void findAnyIntersection(const pointField &start, const pointField &end, labelList &surfaces, List< pointIndexHit > &) const
Find any intersection. Return hit point information and.
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
wordList patchTypes(nPatches)
scalarField samples(nIntervals, Zero)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
PointIndexHit< point > pointIndexHit
A PointIndexHit with a 3D point.
Definition: pointIndexHit.H:58
label findSurfaceID(const word &name) const
Find index of surface. Return -1 if not found.
A bounding box defined in terms of min/max extrema points.
Definition: boundBox.H:63
Base class of (analytical or triangulated) surface. Encapsulates all the search routines. WIP.
static void findAllIntersections(const PtrList< searchableSurface > &, const labelList &surfacesToTest, const pointField &start, const pointField &end, labelListList &surfaces, List< List< pointIndexHit >> &surfaceHits)
Find all intersections in order from start to end. Returns for.
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T. FatalIOError if not found, or if the number of tokens is incorrect.
boundBox bounds() const
Calculate bounding box.
void findNearestIntersection(const pointField &start, const pointField &end, labelList &surface1, List< pointIndexHit > &hit1, labelList &surface2, List< pointIndexHit > &hit2) const
List< labelList > labelListList
List of labelList.
Definition: labelList.H:38
label findSurfaceRegionID(const word &surfaceName, const word &regionName) const
void write(const word &fieldName, const UList< Type > &field)
Write primitive field of CellData (Poly or Line) or PointData values.
bool checkIntersection(const scalar tol, autoPtr< coordSetWriter > &setWriter, const bool report) const
Do surfaces self-intersect or intersect others.
static label markZones(const PrimitivePatch< FaceList, PointField > &, const BoolListType &borderEdge, labelList &faceZone)
Size and fills faceZone with zone of face.
bool checkNormalOrientation(const bool report) const
Are all (triangulated) surfaces consistent normal orientation.
Various functions to operate on Lists.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
Definition: HashSet.H:85
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
void setSize(const label n)
Alias for resize()
Definition: List.H:316
void findNearest(const pointField &, const scalarField &nearestDistSqr, labelList &surfaces, List< pointIndexHit > &) const
Find nearest. Return -1 (and a miss()) or surface and nearest.
static void findNearestIntersection(const PtrList< searchableSurface > &allSurfaces, const labelList &surfacesToTest, const pointField &start, const pointField &end, labelList &surface1, List< pointIndexHit > &hit1, labelList &surface2, List< pointIndexHit > &hit2)
Find intersections of edge nearest to both endpoints.
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i), works like std::iota() but returning a...
Definition: labelLists.C:44
A class for handling words, derived from Foam::string.
Definition: word.H:63
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
face triFace(3)
Vector< scalar > vector
Definition: vector.H:57
HashSet< word, Hash< word > > wordHashSet
A HashSet of words, uses string hasher.
Definition: HashSet.H:73
friend Ostream & operator(Ostream &os, const UPtrList< T > &list)
Write UPtrList to Ostream.
static void findAnyIntersection(const PtrList< searchableSurface > &, const labelList &surfacesToTest, const pointField &start, const pointField &end, labelList &surfaces, List< pointIndexHit > &)
Find any intersection. Return hit point information and.
errorManip< error > abort(error &err)
Definition: errorManip.H:139
label find(const T &val) const
Find index of the first occurrence of the value.
Definition: UList.C:173
constexpr auto end(C &c) -> decltype(c.end())
Return iterator to the end of the container c.
Definition: stdFoam.H:201
OBJstream os(runTime.globalPath()/outputName)
virtual bool open(const fileName &file, bool parallel=UPstream::parRun())
Open file for writing (creates parent directory).
defineTypeNameAndDebug(combustionModel, 0)
labelList f(nPoints)
void setSize(const label newLen)
Same as resize()
Definition: PtrList.H:337
void findAllIntersections(const pointField &start, const pointField &end, labelListList &surfaces, List< List< pointIndexHit >> &) const
Find all intersections in order from start to end. Returns for.
List< word > wordList
List of word.
Definition: fileName.H:59
const searchableSurface & operator[](const word &) const
Return const reference to searchableSurface by name.
vector point
Point is a vector.
Definition: point.H:37
label checkGeometry(const scalar maxRatio, const scalar tolerance, autoPtr< coordSetWriter > &setWriter, const scalar minQuality, const bool report) const
All geometric checks. Return number of failed checks.
Foam::word regionName(args.getOrDefault< word >("region", Foam::polyMesh::defaultRegion))
auto key(const Type &t) -> typename std::enable_if< std::is_enum< Type >::value, typename std::underlying_type< Type >::type >::type
Definition: foamGltfBase.H:103
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers...
Definition: List.H:55
void close()
End the file contents and close the file after writing.
static autoPtr< searchableSurface > New(const word &surfaceType, const IOobject &io, const dictionary &dict)
Return a reference to the selected searchableSurface.
triangle< point, const point & > triPointRef
A triangle using referred points.
Definition: triangleFwd.H:39
List< label > sortedToc(const UList< bool > &bools)
Return the (sorted) values corresponding to &#39;true&#39; entries.
Definition: BitOps.C:195
messageStream Info
Information stream (stdout output on master, null elsewhere)
label n
bool checkQuality(const scalar minQuality, const bool report) const
Check triangle quality.
Pointer management similar to std::unique_ptr, with some additional methods and type checking...
Definition: HashPtrTable.H:48
List< label > labelList
A List of labels.
Definition: List.H:62
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, IOobject::NO_REGISTER)
bool checkClosed(const bool report) const
Are all surfaces closed and manifold.
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
bool returnReduceOr(const bool value, const label comm=UPstream::worldComm)
Perform logical (or) MPI Allreduce on a copy. Uses UPstream::reduceOr.
void writeStats(const List< wordList > &, Ostream &) const
Write some stats.
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:172
bool checkSizes(const scalar maxRatio, const bool report) const
Are all bounding boxes of similar size.
const dimensionedScalar mp
Proton mass.
Namespace for OpenFOAM.
static boundBox bounds(const PtrList< searchableSurface > &allSurfaces, const labelUList &surfacesToTest)
Find the boundBox of the selected surfaces.
A keyword and a list of tokens is an &#39;entry&#39;.
Definition: entry.H:63