shellSurfaces.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-2015 OpenFOAM Foundation
9  Copyright (C) 2015-2021 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 "shellSurfaces.H"
30 #include "searchableSurface.H"
31 #include "boundBox.H"
32 #include "triSurfaceMesh.H"
33 #include "refinementSurfaces.H"
34 #include "searchableSurfaces.H"
35 #include "orientedSurface.H"
36 #include "pointIndexHit.H"
37 #include "volumeType.H"
38 
39 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
40 
41 const Foam::Enum
42 <
44 >
45 Foam::shellSurfaces::refineModeNames_
46 ({
47  { refineMode::INSIDE, "inside" },
48  { refineMode::OUTSIDE, "outside" },
49  { refineMode::DISTANCE, "distance" },
50 });
51 
52 
53 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
54 
55 void Foam::shellSurfaces::setAndCheckLevels
56 (
57  const label shellI,
58  const List<Tuple2<scalar, label>>& distLevels
59 )
60 {
61  const searchableSurface& shell = allGeometry_[shells_[shellI]];
62 
63  if (modes_[shellI] != DISTANCE && distLevels.size() != 1)
64  {
66  << "For refinement mode "
67  << refineModeNames_[modes_[shellI]]
68  << " specify only one distance+level."
69  << " (its distance gets discarded)"
70  << exit(FatalError);
71  }
72  // Extract information into separate distance and level
73  distances_[shellI].setSize(distLevels.size());
74  levels_[shellI].setSize(distLevels.size());
75 
76  forAll(distLevels, j)
77  {
78  distances_[shellI][j] = distLevels[j].first();
79  levels_[shellI][j] = distLevels[j].second();
80 
81  if (levels_[shellI][j] < -1)
82  {
84  << "Shell " << shell.name()
85  << " has illegal refinement level "
86  << levels_[shellI][j]
87  << exit(FatalError);
88  }
89 
90 
91  // Check in incremental order
92  if (j > 0)
93  {
94  if
95  (
96  (distances_[shellI][j] <= distances_[shellI][j-1])
97  || (levels_[shellI][j] > levels_[shellI][j-1])
98  )
99  {
101  << "For refinement mode "
102  << refineModeNames_[modes_[shellI]]
103  << " : Refinement should be specified in order"
104  << " of increasing distance"
105  << " (and decreasing refinement level)." << endl
106  << "Distance:" << distances_[shellI][j]
107  << " refinementLevel:" << levels_[shellI][j]
108  << exit(FatalError);
109  }
110  }
111  }
112 
113  if (modes_[shellI] == DISTANCE)
114  {
115  if (!dryRun_)
116  {
117  Info<< "Refinement level according to distance to "
118  << shell.name() << endl;
119  forAll(levels_[shellI], j)
120  {
121  Info<< " level " << levels_[shellI][j]
122  << " for all cells within " << distances_[shellI][j]
123  << " metre." << endl;
124  }
125  }
126  }
127  else
128  {
129  if (!shell.hasVolumeType())
130  {
132  << "Shell " << shell.name()
133  << " does not support testing for "
134  << refineModeNames_[modes_[shellI]] << endl
135  << "Probably it is not closed."
136  << exit(FatalError);
137  }
138 
139  if (!dryRun_)
140  {
141  if (modes_[shellI] == INSIDE)
142  {
143  Info<< "Refinement level " << levels_[shellI][0]
144  << " for all cells inside " << shell.name() << endl;
145  }
146  else
147  {
148  Info<< "Refinement level " << levels_[shellI][0]
149  << " for all cells outside " << shell.name() << endl;
150  }
151  }
152  }
153 }
154 
155 
156 // Specifically orient triSurfaces using a calculated point outside.
157 // Done since quite often triSurfaces not of consistent orientation which
158 // is (currently) necessary for sideness calculation
159 void Foam::shellSurfaces::orient()
160 {
161  // Determine outside point.
162  boundBox overallBb = boundBox::invertedBox;
163 
164  bool hasSurface = false;
165 
166  forAll(shells_, shellI)
167  {
168  const searchableSurface& s = allGeometry_[shells_[shellI]];
169 
170  if (modes_[shellI] != DISTANCE && isA<triSurfaceMesh>(s))
171  {
172  const triSurfaceMesh& shell = refCast<const triSurfaceMesh>(s);
173 
174  if (shell.triSurface::size())
175  {
176  hasSurface = true;
177  // Assume surface is compact!
178  overallBb.add(shell.points());
179  }
180  }
181  }
182 
183  if (hasSurface)
184  {
185  const point outsidePt = overallBb.max() + overallBb.span();
186 
187  //Info<< "Using point " << outsidePt << " to orient shells" << endl;
188 
189  forAll(shells_, shellI)
190  {
191  const searchableSurface& s = allGeometry_[shells_[shellI]];
192 
193  if (modes_[shellI] != DISTANCE && isA<triSurfaceMesh>(s))
194  {
195  triSurfaceMesh& shell = const_cast<triSurfaceMesh&>
196  (
197  refCast<const triSurfaceMesh>(s)
198  );
199 
200  // Flip surface so outsidePt is outside.
201  bool anyFlipped = orientedSurface::orient
202  (
203  shell,
204  outsidePt,
205  true
206  );
207 
208  if (anyFlipped && !dryRun_)
209  {
210  // orientedSurface will have done a clearOut of the surface.
211  // we could do a clearout of the triSurfaceMeshes::trees()
212  // but these aren't affected by orientation
213  // (except for cached
214  // sideness which should not be set at this point.
215  // !!Should check!)
216 
217  Info<< "shellSurfaces : Flipped orientation of surface "
218  << s.name()
219  << " so point " << outsidePt << " is outside." << endl;
220  }
221  }
222  }
223  }
224 }
225 
226 
227 // Find maximum level of a shell.
228 void Foam::shellSurfaces::findHigherLevel
229 (
230  const pointField& pt,
231  const label shellI,
232  labelList& maxLevel
233 ) const
234 {
235  const labelList& levels = levels_[shellI];
236 
237  if (modes_[shellI] == DISTANCE)
238  {
239  // Distance mode.
240 
241  const scalarField& distances = distances_[shellI];
242 
243  // Collect all those points that have a current maxLevel less than
244  // (any of) the shell. Also collect the furthest distance allowable
245  // to any shell with a higher level.
246 
247  labelList candidateMap(pt.size());
248  scalarField candidateDistSqr(pt.size());
249  label candidateI = 0;
250 
251  forAll(maxLevel, pointi)
252  {
253  forAllReverse(levels, levelI)
254  {
255  if (levels[levelI] > maxLevel[pointi])
256  {
257  candidateMap[candidateI] = pointi;
258  candidateDistSqr[candidateI] = sqr(distances[levelI]);
259  candidateI++;
260  break;
261  }
262  }
263  }
264  candidateMap.setSize(candidateI);
265  candidateDistSqr.setSize(candidateI);
266 
267  // Do the expensive nearest test only for the candidate points.
268  List<pointIndexHit> nearInfo;
269  allGeometry_[shells_[shellI]].findNearest
270  (
271  pointField(pt, candidateMap),
272  candidateDistSqr,
273  nearInfo
274  );
275 
276  // Update maxLevel
277  forAll(nearInfo, i)
278  {
279  if (nearInfo[i].hit())
280  {
281  const label pointi = candidateMap[i];
282 
283  // Check which level it actually is in.
284  const label minDistI = findLower
285  (
286  distances,
287  mag(nearInfo[i].hitPoint()-pt[pointi])
288  );
289 
290  // pt is inbetween shell[minDistI] and shell[minDistI+1]
291  maxLevel[pointi] = levels[minDistI+1];
292  }
293  }
294  }
295  else
296  {
297  // Inside/outside mode
298 
299  // Collect all those points that have a current maxLevel less than the
300  // shell.
301 
302  pointField candidates(pt.size());
303  labelList candidateMap(pt.size());
304  label candidateI = 0;
305 
306  forAll(maxLevel, pointi)
307  {
308  if (levels[0] > maxLevel[pointi])
309  {
310  candidates[candidateI] = pt[pointi];
311  candidateMap[candidateI] = pointi;
312  candidateI++;
313  }
314  }
315  candidates.setSize(candidateI);
316  candidateMap.setSize(candidateI);
317 
318  // Do the expensive nearest test only for the candidate points.
319  List<volumeType> volType;
320  allGeometry_[shells_[shellI]].getVolumeType(candidates, volType);
321 
322  forAll(volType, i)
323  {
324  label pointi = candidateMap[i];
325 
326  if
327  (
328  (
329  modes_[shellI] == INSIDE
330  && volType[i] == volumeType::INSIDE
331  )
332  || (
333  modes_[shellI] == OUTSIDE
334  && volType[i] == volumeType::OUTSIDE
335  )
336  )
337  {
338  maxLevel[pointi] = levels[0];
339  }
340  }
341  }
342 }
343 
344 
345 void Foam::shellSurfaces::findHigherGapLevel
346 (
347  const pointField& pt,
348  const labelList& ptLevel,
349  const label shellI,
350  labelList& gapShell,
351  List<FixedList<label, 3>>& gapInfo,
352  List<volumeType>& gapMode
353 ) const
354 {
355  //TBD: hardcoded for region 0 information
356  const FixedList<label, 3>& info = extendedGapLevel_[shellI][0];
357  const volumeType mode = extendedGapMode_[shellI][0];
358 
359  if (info[2] == 0)
360  {
361  return;
362  }
363 
364  if (modes_[shellI] == DISTANCE)
365  {
366  // Distance mode.
367  const scalar distance = distances_[shellI][0];
368 
369  labelList candidateMap(pt.size());
370  scalarField candidateDistSqr(pt.size());
371  label candidateI = 0;
372 
373  forAll(ptLevel, pointI)
374  {
375  if (ptLevel[pointI] >= info[1] && ptLevel[pointI] < info[2])
376  {
377  candidateMap[candidateI] = pointI;
378  candidateDistSqr[candidateI] = sqr(distance);
379  candidateI++;
380  }
381  }
382  candidateMap.setSize(candidateI);
383  candidateDistSqr.setSize(candidateI);
384 
385  // Do the expensive nearest test only for the candidate points.
386  List<pointIndexHit> nearInfo;
387  allGeometry_[shells_[shellI]].findNearest
388  (
389  pointField(pt, candidateMap),
390  candidateDistSqr,
391  nearInfo
392  );
393 
394  // Update info
395  forAll(nearInfo, i)
396  {
397  if (nearInfo[i].hit())
398  {
399  const label pointI = candidateMap[i];
400  gapShell[pointI] = shellI;
401  gapInfo[pointI] = info;
402  gapMode[pointI] = mode;
403  }
404  }
405  }
406  else
407  {
408  // Collect all those points that have a current maxLevel less than the
409  // shell.
410 
411  labelList candidateMap(pt.size());
412  label candidateI = 0;
413 
414  forAll(ptLevel, pointI)
415  {
416  if (ptLevel[pointI] >= info[1] && ptLevel[pointI] < info[2])
417  {
418  candidateMap[candidateI++] = pointI;
419  }
420  }
421  candidateMap.setSize(candidateI);
422 
423  // Do the expensive nearest test only for the candidate points.
424  List<volumeType> volType;
425  allGeometry_[shells_[shellI]].getVolumeType
426  (
427  pointField(pt, candidateMap),
428  volType
429  );
430 
431  forAll(volType, i)
432  {
433  const label pointI = candidateMap[i];
434  const bool isInside = (volType[i] == volumeType::INSIDE);
435 
436  if
437  (
438  (
439  (modes_[shellI] == INSIDE && isInside)
440  || (modes_[shellI] == OUTSIDE && !isInside)
441  )
442  && info[2] > gapInfo[pointI][2]
443  )
444  {
445  gapShell[pointI] = shellI;
446  gapInfo[pointI] = info;
447  gapMode[pointI] = mode;
448  }
449  }
450  }
451 }
452 
453 
454 void Foam::shellSurfaces::findLevel
455 (
456  const pointField& pt,
457  const label shellI,
458  labelList& minLevel,
459  labelList& shell
460 ) const
461 {
462  const labelList& levels = levels_[shellI];
463 
464  if (modes_[shellI] == DISTANCE)
465  {
466  // Distance mode.
467 
468  const scalarField& distances = distances_[shellI];
469 
470  // Collect all those points that have a current level equal/greater
471  // (any of) the shell. Also collect the furthest distance allowable
472  // to any shell with a higher level.
473 
474  pointField candidates(pt.size());
475  labelList candidateMap(pt.size());
476  scalarField candidateDistSqr(pt.size());
477  label candidateI = 0;
478 
479  forAll(shell, pointI)
480  {
481  if (shell[pointI] == -1)
482  {
483  forAllReverse(levels, levelI)
484  {
485  if (levels[levelI] <= minLevel[pointI])
486  {
487  candidates[candidateI] = pt[pointI];
488  candidateMap[candidateI] = pointI;
489  candidateDistSqr[candidateI] = sqr(distances[levelI]);
490  candidateI++;
491  break;
492  }
493  }
494  }
495  }
496  candidates.setSize(candidateI);
497  candidateMap.setSize(candidateI);
498  candidateDistSqr.setSize(candidateI);
499 
500  // Do the expensive nearest test only for the candidate points.
501  List<pointIndexHit> nearInfo;
502  allGeometry_[shells_[shellI]].findNearest
503  (
504  candidates,
505  candidateDistSqr,
506  nearInfo
507  );
508 
509  // Update maxLevel
510  forAll(nearInfo, i)
511  {
512  if (nearInfo[i].hit())
513  {
514  // Check which level it actually is in.
515  label minDistI = findLower
516  (
517  distances,
518  mag(nearInfo[i].hitPoint()-candidates[i])
519  );
520 
521  label pointI = candidateMap[i];
522 
523  // pt is inbetween shell[minDistI] and shell[minDistI+1]
524  shell[pointI] = shellI;
525  minLevel[pointI] = levels[minDistI+1];
526  }
527  }
528  }
529  else
530  {
531  // Inside/outside mode
532 
533  // Collect all those points that have a current maxLevel less than the
534  // shell.
535 
536  pointField candidates(pt.size());
537  labelList candidateMap(pt.size());
538  label candidateI = 0;
539 
540  forAll(shell, pointI)
541  {
542  if (shell[pointI] == -1 && levels[0] <= minLevel[pointI])
543  {
544  candidates[candidateI] = pt[pointI];
545  candidateMap[candidateI] = pointI;
546  candidateI++;
547  }
548  }
549  candidates.setSize(candidateI);
550  candidateMap.setSize(candidateI);
551 
552  // Do the expensive nearest test only for the candidate points.
553  List<volumeType> volType;
554  allGeometry_[shells_[shellI]].getVolumeType(candidates, volType);
555 
556  forAll(volType, i)
557  {
558  if
559  (
560  (
561  modes_[shellI] == INSIDE
562  && volType[i] == volumeType::INSIDE
563  )
564  || (
565  modes_[shellI] == OUTSIDE
566  && volType[i] == volumeType::OUTSIDE
567  )
568  )
569  {
570  label pointI = candidateMap[i];
571  shell[pointI] = shellI;
572  minLevel[pointI] = levels[0];
573  }
574  }
575  }
576 }
577 
578 
579 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
580 
582 (
583  const searchableSurfaces& allGeometry,
584  const dictionary& shellsDict,
585  const bool dryRun
586 )
587 :
588  allGeometry_(allGeometry),
589  dryRun_(dryRun)
590 {
591  // Wildcard specification : loop over all surfaces and try to find a match.
592 
593  // Count number of shells.
594  label shellI = 0;
595  for (const word& geomName : allGeometry_.names())
596  {
597  if (shellsDict.found(geomName))
598  {
599  ++shellI;
600  }
601  }
602 
603 
604  // Size lists
605  shells_.setSize(shellI);
606  modes_.setSize(shellI);
607  distances_.setSize(shellI);
608  levels_.setSize(shellI);
609  dirLevels_.setSize(shellI);
610  smoothDirection_.setSize(shellI);
611  nSmoothExpansion_.setSize(shellI);
612  nSmoothPosition_.setSize(shellI);
613 
614  extendedGapLevel_.setSize(shellI);
615  extendedGapMode_.setSize(shellI);
616  selfProximity_.setSize(shellI);
617 
618  const FixedList<label, 3> nullGapLevel({0, 0, 0});
619 
620  wordHashSet unmatchedKeys(shellsDict.toc());
621  shellI = 0;
622 
623  forAll(allGeometry_.names(), geomI)
624  {
625  const word& geomName = allGeometry_.names()[geomI];
626 
627  const entry* eptr = shellsDict.findEntry(geomName, keyType::REGEX);
628 
629  if (eptr)
630  {
631  const dictionary& dict = eptr->dict();
632  unmatchedKeys.erase(eptr->keyword());
633 
634  shells_[shellI] = geomI;
635  modes_[shellI] = refineModeNames_.get("mode", dict);
636 
637  // Read pairs of distance+level
638  setAndCheckLevels(shellI, dict.lookup("levels"));
639 
640 
641  // Directional refinement
642  // ~~~~~~~~~~~~~~~~~~~~~~
643 
644  dirLevels_[shellI] = Tuple2<labelPair,labelVector>
645  (
648  );
649  const entry* levelPtr =
650  dict.findEntry("levelIncrement", keyType::REGEX);
651 
652  if (levelPtr)
653  {
654  // Do reading ourselves since using labelPair would require
655  // additional bracket pair
656  ITstream& is = levelPtr->stream();
657 
658  is.readBegin("levelIncrement");
659  is >> dirLevels_[shellI].first().first()
660  >> dirLevels_[shellI].first().second()
661  >> dirLevels_[shellI].second();
662  is.readEnd("levelIncrement");
663 
664  if (modes_[shellI] == INSIDE)
665  {
666  if (!dryRun_)
667  {
668  Info<< "Additional directional refinement level"
669  << " for all cells inside " << geomName << endl;
670  }
671  }
672  else if (modes_[shellI] == OUTSIDE)
673  {
674  if (!dryRun_)
675  {
676  Info<< "Additional directional refinement level"
677  << " for all cells outside " << geomName << endl;
678  }
679  }
680  else
681  {
682  FatalIOErrorInFunction(shellsDict)
683  << "Unsupported mode "
684  << refineModeNames_[modes_[shellI]]
685  << exit(FatalIOError);
686  }
687  }
688 
689  // Directional smoothing
690  // ~~~~~~~~~~~~~~~~~~~~~
691 
692  nSmoothExpansion_[shellI] = 0;
693  nSmoothPosition_[shellI] = 0;
694  smoothDirection_[shellI] =
695  dict.getOrDefault("smoothDirection", vector::zero);
696 
697  if (smoothDirection_[shellI] != vector::zero)
698  {
699  dict.readEntry("nSmoothExpansion", nSmoothExpansion_[shellI]);
700  dict.readEntry("nSmoothPosition", nSmoothPosition_[shellI]);
701  }
702 
703 
704  // Gap specification
705  // ~~~~~~~~~~~~~~~~~
706 
707 
708  // Shell-wide gap level specification
709  const searchableSurface& surface = allGeometry_[geomI];
710  const wordList& regionNames = surface.regions();
711 
712  FixedList<label, 3> gapSpec
713  (
715  (
716  "gapLevel",
717  nullGapLevel
718  )
719  );
720  extendedGapLevel_[shellI].setSize(regionNames.size());
721  extendedGapLevel_[shellI] = gapSpec;
722 
723  extendedGapMode_[shellI].setSize(regionNames.size());
724  extendedGapMode_[shellI] =
725  volumeType("gapMode", dict, volumeType::MIXED);
726 
727  // Detect self-intersections
728  selfProximity_[shellI].setSize
729  (
730  regionNames.size(),
731  dict.getOrDefault<bool>("gapSelf", true)
732  );
733 
734 
735  // Override on a per-region basis?
736 
737  if (dict.found("regions"))
738  {
739  const dictionary& regionsDict = dict.subDict("regions");
740  forAll(regionNames, regionI)
741  {
742  if (regionsDict.found(regionNames[regionI]))
743  {
744  // Get the dictionary for region
745  const dictionary& regionDict = regionsDict.subDict
746  (
747  regionNames[regionI]
748  );
749  FixedList<label, 3> gapSpec
750  (
751  regionDict.getOrDefault
752  (
753  "gapLevel",
754  nullGapLevel
755  )
756  );
757  extendedGapLevel_[shellI][regionI] = gapSpec;
758 
759  extendedGapMode_[shellI][regionI] =
760  volumeType
761  (
762  "gapMode",
763  regionDict,
765  );
766 
767  selfProximity_[shellI][regionI] =
768  regionDict.getOrDefault<bool>
769  (
770  "gapSelf",
771  true
772  );
773  }
774  }
775  }
776 
777  if (extendedGapLevel_[shellI][0][0] > 0)
778  {
779  Info<< "Refinement level up to "
780  << extendedGapLevel_[shellI][0][2]
781  << " for all cells in gaps for shell "
782  << geomName << endl;
783 
784  if (distances_[shellI].size() > 1)
785  {
786  WarningInFunction << "Using first distance only out of "
787  << distances_[shellI] << " to detect gaps for shell "
788  << geomName << endl;
789  }
790  }
791 
792  shellI++;
793  }
794  }
795 
796  if (unmatchedKeys.size() > 0)
797  {
798  IOWarningInFunction(shellsDict)
799  << "Not all entries in refinementRegions dictionary were used."
800  << " The following entries were not used : "
801  << unmatchedKeys.sortedToc()
802  << endl;
803  }
804 
805  // Orient shell surfaces before any searching is done. Note that this
806  // only needs to be done for inside or outside. Orienting surfaces
807  // constructs lots of addressing which we want to avoid.
808  orient();
809 }
810 
811 
812 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
813 
814 // Highest shell level
815 Foam::label Foam::shellSurfaces::maxLevel() const
816 {
817  label overallMax = 0;
818  forAll(levels_, shellI)
819  {
820  overallMax = max(overallMax, max(levels_[shellI]));
821  }
822  return overallMax;
823 }
824 
825 
827 {
828  labelList surfaceMax(extendedGapLevel_.size(), Zero);
829 
830  forAll(extendedGapLevel_, shelli)
831  {
832  const List<FixedList<label, 3>>& levels = extendedGapLevel_[shelli];
833  forAll(levels, i)
834  {
835  surfaceMax[shelli] = max(surfaceMax[shelli], levels[i][2]);
836  }
837  }
838  return surfaceMax;
839 }
840 
841 
843 {
844  labelPairList levels(dirLevels_.size());
845  forAll(dirLevels_, shelli)
846  {
847  levels[shelli] = dirLevels_[shelli].first();
848  }
849  return levels;
850 }
851 
852 
854 {
855  return nSmoothExpansion_;
856 }
857 
858 
860 {
861  return smoothDirection_;
862 }
863 
864 
866 {
867  return nSmoothPosition_;
868 }
869 
870 
871 void Foam::shellSurfaces::findHigherLevel
872 (
873  const pointField& pt,
874  const labelList& ptLevel,
875  labelList& maxLevel
876 ) const
877 {
878  // Maximum level of any shell. Start off with level of point.
879  maxLevel = ptLevel;
880 
881  forAll(shells_, shelli)
882  {
883  findHigherLevel(pt, shelli, maxLevel);
884  }
885 }
886 
887 
888 void Foam::shellSurfaces::findHigherGapLevel
889 (
890  const pointField& pt,
891  const labelList& ptLevel,
892  labelList& gapShell,
893  List<FixedList<label, 3>>& gapInfo,
894  List<volumeType>& gapMode
895 ) const
896 {
897  gapShell.setSize(pt.size());
898  gapShell = -1;
899 
900  gapInfo.setSize(pt.size());
901  gapInfo = FixedList<label, 3>({0, 0, 0});
902 
903  gapMode.setSize(pt.size());
904  gapMode = volumeType::MIXED;
905 
906  forAll(shells_, shelli)
907  {
908  findHigherGapLevel(pt, ptLevel, shelli, gapShell, gapInfo, gapMode);
909  }
910 }
911 
912 
913 void Foam::shellSurfaces::findHigherGapLevel
914 (
915  const pointField& pt,
916  const labelList& ptLevel,
917  List<FixedList<label, 3>>& gapInfo,
918  List<volumeType>& gapMode
919 ) const
920 {
921  labelList gapShell;
922  findHigherGapLevel(pt, ptLevel, gapShell, gapInfo, gapMode);
923 }
924 
925 
926 void Foam::shellSurfaces::findLevel
927 (
928  const pointField& pt,
929  const labelList& ptLevel,
930  labelList& shell
931 ) const
932 {
933  shell.setSize(pt.size());
934  shell = -1;
935 
936  labelList minLevel(ptLevel);
937 
938  forAll(shells_, shelli)
939  {
940  findLevel(pt, shelli, minLevel, shell);
941  }
942 }
943 
944 
946 (
947  const pointField& pt,
948  const labelList& ptLevel,
949  const labelList& dirLevel, // directional level
950  const direction dir,
951  labelList& shell
952 ) const
953 {
954  shell.setSize(pt.size());
955  shell = -1;
956 
957  List<volumeType> volType;
958 
959  // Current back to original
960  DynamicList<label> candidateMap(pt.size());
961 
962  forAll(shells_, shelli)
963  {
964  if (modes_[shelli] == INSIDE || modes_[shelli] == OUTSIDE)
965  {
966  const labelPair& selectLevels = dirLevels_[shelli].first();
967  const label addLevel = dirLevels_[shelli].second()[dir];
968 
969  // Collect the cells that are of the right original level
970  candidateMap.clear();
971  forAll(ptLevel, celli)
972  {
973  label level = ptLevel[celli];
974 
975  if
976  (
977  level >= selectLevels.first()
978  && level <= selectLevels.second()
979  && dirLevel[celli] < level+addLevel
980  )
981  {
982  candidateMap.append(celli);
983  }
984  }
985 
986  // Do geometric test
987  pointField candidatePt(pt, candidateMap);
988  allGeometry_[shells_[shelli]].getVolumeType(candidatePt, volType);
989 
990  // Extract selected cells
991  forAll(candidateMap, i)
992  {
993  if
994  (
995  (
996  modes_[shelli] == INSIDE
997  && volType[i] == volumeType::INSIDE
998  )
999  || (
1000  modes_[shelli] == OUTSIDE
1001  && volType[i] == volumeType::OUTSIDE
1002  )
1003  )
1004  {
1005  shell[candidateMap[i]] = shelli;
1006  }
1007  }
1008  }
1009  }
1010 }
1011 
1012 
1013 // ************************************************************************* //
shellSurfaces.H
Foam::Pair::second
const T & second() const noexcept
Return second element, which is also the last element.
Definition: PairI.H:122
Foam::entry
A keyword and a list of tokens is an 'entry'.
Definition: entry.H:67
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:67
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
Foam::scalarField
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Definition: primitiveFieldsFwd.H:52
Foam::shellSurfaces::refineMode
refineMode
Volume refinement controls.
Definition: shellSurfaces.H:64
Foam::Enum
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
Definition: IOstreamOption.H:57
pointIndexHit.H
Foam::shellSurfaces::smoothDirection
const vectorField & smoothDirection() const
Per shell the smoothing direction.
Definition: shellSurfaces.C:859
Foam::labelMax
constexpr label labelMax
Definition: label.H:61
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::entry::stream
virtual ITstream & stream() const =0
Return token stream, if entry is a primitive entry.
s
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))
Definition: gmvOutputSpray.H:25
searchableSurface.H
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::DynamicList< label >
Foam::dictionary::found
bool found(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Search for an entry (const access) with the given keyword.
Definition: dictionaryI.H:87
Foam::boundBox::invertedBox
static const boundBox invertedBox
A large inverted boundBox: min/max == +/- ROOTVGREAT.
Definition: boundBox.H:86
Foam::shellSurfaces::DISTANCE
Definition: shellSurfaces.H:68
Foam::shellSurfaces::maxGapLevel
labelList maxGapLevel() const
Highest shell gap level.
Definition: shellSurfaces.C:826
Foam::entry::keyword
const keyType & keyword() const noexcept
Return keyword.
Definition: entry.H:195
Foam::List::append
void append(const T &val)
Append an element at the end of the list.
Definition: ListI.H:175
Foam::FatalIOError
IOerror FatalIOError
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::Istream::readEnd
bool readEnd(const char *funcName)
End read of data chunk, ends with ')'.
Definition: Istream.C:129
Foam::HashSet< word, Hash< word > >
regionNames
wordList regionNames
Definition: getAllRegionOptions.H:37
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::Istream::readBegin
bool readBegin(const char *funcName)
Begin read of data chunk, starts with '('.
Definition: Istream.C:111
Foam::labelPair
Pair< label > labelPair
A pair of labels.
Definition: Pair.H:54
Foam::mode
mode_t mode(const fileName &name, const bool followLink=true)
Return the file mode, normally following symbolic links.
Definition: MSwindows.C:564
searchableSurfaces.H
volumeType.H
Foam::volumeType
An enumeration wrapper for classification of a location as being inside/outside of a volume.
Definition: volumeType.H:60
Foam::Field< vector >
Foam::findLower
label findLower(const ListType &input, const T &val, const label start, const ComparePredicate &comp)
Foam::ITstream
An input stream of tokens.
Definition: ITstream.H:52
Foam::searchableSurface::regions
virtual const wordList & regions() const =0
Names of regions.
Foam::Info
messageStream Info
Information stream (stdout output on master, null elsewhere)
refinementSurfaces.H
Foam::List::setSize
void setSize(const label n)
Alias for resize()
Definition: List.H:222
Foam::searchableSurface
Base class of (analytical or triangulated) surface. Encapsulates all the search routines....
Definition: searchableSurface.H:69
Foam::volumeType::MIXED
A location that is partly inside and outside.
Definition: volumeType.H:70
Foam::dictionary::subDict
const dictionary & subDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary.
Definition: dictionary.C:460
Foam::shellSurfaces::directionalSelectLevel
labelPairList directionalSelectLevel() const
Min and max cell level for directional refinement.
Definition: shellSurfaces.C:842
Foam::dictionary::readEntry
bool readEntry(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX, bool mandatory=true) const
Definition: dictionaryTemplates.C:302
Foam::shellSurfaces::shellSurfaces
shellSurfaces(const searchableSurfaces &allGeometry, const dictionary &shellsDict, const bool dryRun=false)
Construct from geometry and dictionary.
Definition: shellSurfaces.C:582
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
Foam::dictionary::lookup
ITstream & lookup(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionary.C:386
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:123
Foam::FixedList::setSize
void setSize(const label n)
Dummy function, to make FixedList consistent with List.
Definition: FixedList.H:304
Foam::entry::dict
virtual const dictionary & dict() const =0
Return dictionary, if entry is a dictionary.
Foam::distance
scalar distance(const vector &p1, const vector &p2)
Definition: curveTools.C:12
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
boundBox.H
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Foam::sqr
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Definition: dimensionedSymmTensor.C:51
Foam::Pair< label >
Foam::VectorSpace::max
static const Form max
Definition: VectorSpace.H:117
Foam::ILList::erase
bool erase(T *item)
Remove the specified element from the list and delete it.
Definition: ILList.C:97
Foam::shellSurfaces::findDirectionalLevel
void findDirectionalLevel(const pointField &pt, const labelList &ptLevel, const labelList &dirLevel, const direction dir, labelList &shell) const
Find any shell (or -1) with higher wanted directional level.
Definition: shellSurfaces.C:946
Foam::List< word >
Foam::searchableSurfaces
Container for searchableSurfaces. The collection is specified as a dictionary. For example,...
Definition: searchableSurfaces.H:92
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::FixedList< label, 3 >
Foam::dictionary::findEntry
entry * findEntry(const word &keyword, enum keyType::option matchOpt=keyType::REGEX)
Find for an entry (non-const access) with the given keyword.
Definition: dictionaryI.H:97
Foam::keyType::REGEX
Regular expression.
Definition: keyType.H:82
Foam::direction
uint8_t direction
Definition: direction.H:52
Foam::volumeType::INSIDE
A location inside the volume.
Definition: volumeType.H:68
Foam::labelMin
constexpr label labelMin
Definition: label.H:60
forAllReverse
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition: stdFoam.H:309
Foam::VectorSpace< Vector< Cmpt >, Cmpt, 3 >::zero
static const Vector< Cmpt > zero
Definition: VectorSpace.H:115
FatalIOErrorInFunction
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:473
Foam::shellSurfaces::nSmoothPosition
const labelList & nSmoothPosition() const
Per shell the positional smoothing iterations.
Definition: shellSurfaces.C:865
Foam::orientedSurface::orient
static bool orient(triSurface &, const point &, const bool orientOutside)
Flip faces such that normals are consistent with point:
Definition: orientedSurface.C:452
Foam::dictionary::toc
wordList toc() const
Return the table of contents.
Definition: dictionary.C:602
Foam::shellSurfaces::nSmoothExpansion
const labelList & nSmoothExpansion() const
Per shell the directional smoothing iterations.
Definition: shellSurfaces.C:853
IOWarningInFunction
#define IOWarningInFunction(ios)
Report an IO warning using Foam::Warning.
Definition: messageStream.H:340
Foam::Tuple2
A 2-tuple for storing two objects of dissimilar types. The container is similar in purpose to std::pa...
Definition: stringOps.H:60
Foam::point
vector point
Point is a vector.
Definition: point.H:43
Foam::shellSurfaces::INSIDE
Definition: shellSurfaces.H:66
Foam::shellSurfaces::maxLevel
label maxLevel() const
Highest shell level.
Definition: shellSurfaces.C:815
Foam::dictionary::getOrDefault
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:148
triSurfaceMesh.H
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:328
orientedSurface.H
Foam::volumeType::OUTSIDE
A location outside the volume.
Definition: volumeType.H:69