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