refinementSurfaces.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-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 "refinementSurfaces.H"
30 #include "Time.H"
31 #include "searchableSurfaces.H"
32 #include "shellSurfaces.H"
33 #include "triSurfaceMesh.H"
34 #include "labelPair.H"
36 #include "UPtrList.H"
37 #include "volumeType.H"
38 // For dictionary::get wrapper
39 #include "meshRefinement.H"
40 
41 #include "OBJstream.H"
42 
43 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
44 
45 Foam::labelList Foam::refinementSurfaces::findHigherLevel
46 (
47  const searchableSurface& geom,
48  const shellSurfaces& shells,
49  const List<pointIndexHit>& intersectionInfo,
50  const labelList& surfaceLevel // current level
51 ) const
52 {
53  // See if a cached level field available
54  labelList minLevelField;
55  geom.getField(intersectionInfo, minLevelField);
56 
57 
58  // Detect any uncached values and do proper search
59  labelList localLevel(surfaceLevel);
60  {
61  // Check hits:
62  // 1. cached value == -1 : store for re-testing
63  // 2. cached value != -1 : use
64  // 3. uncached : use region 0 value
65 
66  DynamicList<label> retestSet;
67  label nHits = 0;
68 
69  forAll(intersectionInfo, i)
70  {
71  if (intersectionInfo[i].hit())
72  {
73  nHits++;
74 
75  // Check if minLevelField for this surface.
76  if (minLevelField.size())
77  {
78  if (minLevelField[i] == -1)
79  {
80  retestSet.append(i);
81  }
82  else
83  {
84  localLevel[i] = max(localLevel[i], minLevelField[i]);
85  }
86  }
87  else
88  {
89  retestSet.append(i);
90  }
91  }
92  }
93 
94  if (returnReduceOr(retestSet.size()))
95  {
96  //Info<< "Retesting "
97  // << returnReduce(retestSet.size(), sumOp<label>())
98  // << " out of " << returnReduce(nHits, sumOp<label>())
99  // << " intersections on uncached elements on geometry "
100  // << geom.name() << endl;
101 
102  pointField samples(retestSet.size());
103  forAll(retestSet, i)
104  {
105  samples[i] = intersectionInfo[retestSet[i]].hitPoint();
106  }
107  labelList shellLevel;
108  shells.findHigherLevel
109  (
110  samples,
111  labelUIndList(surfaceLevel, retestSet)(),
112  shellLevel
113  );
114  forAll(retestSet, i)
115  {
116  label sampleI = retestSet[i];
117  localLevel[sampleI] = max(localLevel[sampleI], shellLevel[i]);
118  }
119  }
120  }
121 
122  return localLevel;
123 }
124 
125 
126 Foam::labelList Foam::refinementSurfaces::calcSurfaceIndex
127 (
128  const searchableSurfaces& allGeometry,
129  const labelList& surfaces
130 )
131 {
132  // Determine overall number of global regions
133  label globalI = 0;
134  forAll(surfaces, surfI)
135  {
136  globalI += allGeometry[surfaces[surfI]].regions().size();
137  }
138 
139  labelList regionToSurface(globalI);
140  globalI = 0;
141  forAll(surfaces, surfI)
142  {
143  const label nLocal = allGeometry[surfaces[surfI]].regions().size();
144  for (label i = 0; i < nLocal; i++)
145  {
146  regionToSurface[globalI++] = surfI;
147  }
148  }
149 
150  return regionToSurface;
151 }
152 
153 
154 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
155 
156 Foam::refinementSurfaces::refinementSurfaces
157 (
158  const searchableSurfaces& allGeometry,
159  const dictionary& surfacesDict,
160  const label gapLevelIncrement,
161  const bool dryRun
162 )
163 :
164  allGeometry_(allGeometry),
165  surfaces_(surfacesDict.size()),
166  names_(surfacesDict.size()),
167  surfZones_(surfacesDict.size()),
168  regionOffset_(surfacesDict.size()),
169  dryRun_(dryRun)
170 {
171  // Wildcard specification : loop over all surface, all regions
172  // and try to find a match.
173 
174  // Count number of surfaces.
175  label surfI = 0;
176  forAll(allGeometry_.names(), geomI)
177  {
178  const word& geomName = allGeometry_.names()[geomI];
179 
180  if (surfacesDict.found(geomName))
181  {
182  surfI++;
183  }
184  }
185 
186  // Size lists
187  surfaces_.setSize(surfI);
188  names_.setSize(surfI);
189  surfZones_.setSize(surfI);
190  regionOffset_.setSize(surfI);
191 
192  // Per surface data
193  labelList globalMinLevel(surfI, Zero);
194  labelList globalMaxLevel(surfI, Zero);
195  labelList globalLevelIncr(surfI, Zero);
196 
197  const FixedList<label, 3> nullGapLevel({0, 0, 0});
198  List<FixedList<label, 3>> globalGapLevel(surfI);
199  List<volumeType> globalGapMode(surfI);
200  boolList globalGapSelf(surfI);
201 
202  const FixedList<label, 4> nullCurvLevel({0, 0, 0, -1});
203  List<FixedList<label, 4>> globalCurvLevel(surfI);
204 
205  scalarField globalAngle(surfI, -GREAT);
206  PtrList<dictionary> globalPatchInfo(surfI);
207 
208  labelList globalBlockLevel(surfI, labelMax);
209  labelList globalLeakLevel(surfI, labelMax);
210 
211  // Per surface, per region data
212  List<Map<label>> regionMinLevel(surfI);
213  List<Map<label>> regionMaxLevel(surfI);
214  List<Map<label>> regionLevelIncr(surfI);
215  List<Map<FixedList<label, 3>>> regionGapLevel(surfI);
216  List<Map<volumeType>> regionGapMode(surfI);
217  List<Map<bool>> regionGapSelf(surfI);
218  List<Map<FixedList<label, 4>>> regionCurvLevel(surfI);
219  List<Map<scalar>> regionAngle(surfI);
220  List<Map<autoPtr<dictionary>>> regionPatchInfo(surfI);
221  List<Map<label>> regionBlockLevel(surfI);
222  List<Map<label>> regionLeakLevel(surfI);
223 
224  wordHashSet unmatchedKeys(surfacesDict.toc());
225 
226  surfI = 0;
227  forAll(allGeometry_.names(), geomI)
228  {
229  const word& geomName = allGeometry_.names()[geomI];
230 
231  const entry* ePtr =
232  surfacesDict.findEntry(geomName, keyType::REGEX);
233 
234  if (ePtr)
235  {
236  const dictionary& dict = ePtr->dict();
237  unmatchedKeys.erase(ePtr->keyword());
238 
239  names_[surfI] = geomName;
240  surfaces_[surfI] = geomI;
241 
242  const labelPair refLevel
243  (
244  meshRefinement::get<labelPair>
245  (
246  dict,
247  "level",
248  dryRun_,
250  labelPair(0, 0)
251  )
252  );
253 
254  globalMinLevel[surfI] = refLevel[0];
255  globalMaxLevel[surfI] = refLevel[1];
256  globalLevelIncr[surfI] = dict.getOrDefault
257  (
258  "gapLevelIncrement",
259  gapLevelIncrement
260  );
261 
262  if
263  (
264  globalMinLevel[surfI] < 0
265  || globalMaxLevel[surfI] < globalMinLevel[surfI]
266  || globalMaxLevel[surfI] < 0
267  || globalLevelIncr[surfI] < 0
268  )
269  {
271  << "Illegal level specification for surface "
272  << names_[surfI]
273  << " : minLevel:" << globalMinLevel[surfI]
274  << " maxLevel:" << globalMaxLevel[surfI]
275  << " levelIncrement:" << globalLevelIncr[surfI]
276  << exit(FatalIOError);
277  }
278 
279 
280  // Optional gapLevel specification
281 
282  globalGapLevel[surfI] = dict.getOrDefault
283  (
284  "gapLevel",
285  nullGapLevel
286  );
287  globalGapMode[surfI] =
288  volumeType("gapMode", dict, volumeType::MIXED);
289 
290  if
291  (
292  globalGapMode[surfI] == volumeType::UNKNOWN
293  || globalGapLevel[surfI][0] < 0
294  || globalGapLevel[surfI][1] < 0
295  || globalGapLevel[surfI][2] < 0
296  || globalGapLevel[surfI][1] > globalGapLevel[surfI][2]
297  )
298  {
300  << "Illegal gapLevel specification for surface "
301  << names_[surfI]
302  << " : gapLevel:" << globalGapLevel[surfI]
303  << " gapMode:" << globalGapMode[surfI].str()
304  << exit(FatalIOError);
305  }
306 
307  globalGapSelf[surfI] =
308  dict.getOrDefault<bool>("gapSelf", true);
309 
310  globalCurvLevel[surfI] = nullCurvLevel;
311  if (dict.readIfPresent("curvatureLevel", globalCurvLevel[surfI]))
312  {
313  if (globalCurvLevel[surfI][0] <= 0)
314  {
316  << "Illegal curvatureLevel specification for surface "
317  << names_[surfI]
318  << " : curvatureLevel:" << globalCurvLevel[surfI]
319  << exit(FatalIOError);
320  }
321  }
322 
323  const searchableSurface& surface = allGeometry_[surfaces_[surfI]];
324 
325  // Surface zones
326  surfZones_.set
327  (
328  surfI,
329  new surfaceZonesInfo
330  (
331  surface,
332  dict,
333  allGeometry_.regionNames()[surfaces_[surfI]]
334  )
335  );
336 
337  // Global perpendicular angle
338  if (dict.found("patchInfo"))
339  {
340  globalPatchInfo.set
341  (
342  surfI,
343  dict.subDict("patchInfo").clone()
344  );
345  }
346  dict.readIfPresent("perpendicularAngle", globalAngle[surfI]);
347  dict.readIfPresent("blockLevel", globalBlockLevel[surfI]);
348  dict.readIfPresent("leakLevel", globalLeakLevel[surfI]);
349 
350 
351  if (dict.found("regions"))
352  {
353  const dictionary& regionsDict = dict.subDict("regions");
354  const wordList& regionNames = surface.regions();
355 
356  forAll(regionNames, regionI)
357  {
358  if (regionsDict.found(regionNames[regionI]))
359  {
360  // Get the dictionary for region
361  const dictionary& regionDict = regionsDict.subDict
362  (
363  regionNames[regionI]
364  );
365 
366  const labelPair refLevel
367  (
368  meshRefinement::get<labelPair>
369  (
370  regionDict,
371  "level",
372  dryRun_,
374  //labelPair(0, 0)
375  labelPair
376  (
377  globalMinLevel[surfI],
378  globalMaxLevel[surfI]
379  )
380  )
381  );
382 
383 
384  regionMinLevel[surfI].insert(regionI, refLevel[0]);
385  regionMaxLevel[surfI].insert(regionI, refLevel[1]);
386  label levelIncr = regionDict.getOrDefault
387  (
388  "gapLevelIncrement",
389  gapLevelIncrement
390  );
391  regionLevelIncr[surfI].insert(regionI, levelIncr);
392 
393  if
394  (
395  refLevel[0] < 0
396  || refLevel[1] < refLevel[0]
397  || levelIncr < 0
398  )
399  {
401  << "Illegal level specification for surface "
402  << names_[surfI] << " region "
403  << regionNames[regionI]
404  << " : minLevel:" << refLevel[0]
405  << " maxLevel:" << refLevel[1]
406  << " levelIncrement:" << levelIncr
407  << exit(FatalIOError);
408  }
409 
410 
411 
412  // Optional gapLevel specification
413 
414  FixedList<label, 3> gapSpec
415  (
416  regionDict.getOrDefault
417  (
418  "gapLevel",
419  globalGapLevel[surfI] //nullGapLevel
420  )
421  );
422  regionGapLevel[surfI].insert(regionI, gapSpec);
423  volumeType gapModeSpec
424  (
425  "gapMode",
426  regionDict,
427  globalGapMode[surfI] //volumeType::MIXED
428  );
429  regionGapMode[surfI].insert(regionI, gapModeSpec);
430  if
431  (
432  gapModeSpec == volumeType::UNKNOWN
433  || gapSpec[0] < 0
434  || gapSpec[1] < 0
435  || gapSpec[2] < 0
436  || gapSpec[1] > gapSpec[2]
437  )
438  {
440  << "Illegal gapLevel specification for surface "
441  << names_[surfI]
442  << " : gapLevel:" << gapSpec
443  << " gapMode:" << gapModeSpec.str()
444  << exit(FatalIOError);
445  }
446  regionGapSelf[surfI].insert
447  (
448  regionI,
449  regionDict.getOrDefault<bool>
450  (
451  "gapSelf",
452  globalGapSelf[surfI] //true
453  )
454  );
455 
456  // Start off with the per-surface level
457  FixedList<label, 4> curvSpec(nullCurvLevel);
458  if
459  (
460  regionDict.readIfPresent("curvatureLevel", curvSpec)
461  )
462  {
463  if (curvSpec[0] <= 0)
464  {
466  << "Illegal curvatureLevel"
467  << " specification for surface "
468  << names_[surfI]
469  << " : curvatureLevel:" << curvSpec
470  << exit(FatalIOError);
471  }
472  regionCurvLevel[surfI].insert(regionI, curvSpec);
473  }
474 
475  if (regionDict.found("perpendicularAngle"))
476  {
477  regionAngle[surfI].insert
478  (
479  regionI,
480  regionDict.get<scalar>("perpendicularAngle")
481  );
482  }
483 
484  if (regionDict.found("patchInfo"))
485  {
486  regionPatchInfo[surfI].insert
487  (
488  regionI,
489  regionDict.subDict("patchInfo").clone()
490  );
491  }
492 
493  label l;
494  if (regionDict.readIfPresent<label>("blockLevel", l))
495  {
496  regionBlockLevel[surfI].insert(regionI, l);
497  }
498  if (regionDict.readIfPresent<label>("leakLevel", l))
499  {
500  regionLeakLevel[surfI].insert(regionI, l);
501  }
502  }
503  }
504  }
505  surfI++;
506  }
507  }
508 
509  if (unmatchedKeys.size() > 0)
510  {
511  IOWarningInFunction(surfacesDict)
512  << "Not all entries in refinementSurfaces dictionary were used."
513  << " The following entries were not used : "
514  << unmatchedKeys.sortedToc()
515  << endl;
516  }
517 
518 
519  // Calculate local to global region offset
520  label nRegions = 0;
521 
522  forAll(surfaces_, surfI)
523  {
524  regionOffset_[surfI] = nRegions;
525  nRegions += allGeometry_[surfaces_[surfI]].regions().size();
526  }
527 
528  // Rework surface specific information into information per global region
529 
530  regionToSurface_ = calcSurfaceIndex(allGeometry_, surfaces_);
531 
532 
533  minLevel_.setSize(nRegions);
534  minLevel_ = 0;
535  maxLevel_.setSize(nRegions);
536  maxLevel_ = 0;
537  gapLevel_.setSize(nRegions);
538  gapLevel_ = -1;
539  extendedGapLevel_.setSize(nRegions);
540  extendedGapLevel_ = nullGapLevel;
541  extendedGapMode_.setSize(nRegions);
542  extendedGapMode_ = volumeType::UNKNOWN;
543  selfProximity_.setSize(nRegions);
544  selfProximity_ = true;
545  extendedCurvatureLevel_.setSize(nRegions);
546  extendedCurvatureLevel_ = nullCurvLevel;
547  perpendicularAngle_.setSize(nRegions);
548  perpendicularAngle_ = -GREAT;
549  patchInfo_.setSize(nRegions);
550  blockLevel_.setSize(nRegions);
551  blockLevel_ = labelMax;
552  leakLevel_.setSize(nRegions);
553  leakLevel_ = labelMax;
554 
555 
556  forAll(globalMinLevel, surfI)
557  {
558  label nRegions = allGeometry_[surfaces_[surfI]].regions().size();
559 
560  // Initialise to global (i.e. per surface)
561  for (label i = 0; i < nRegions; i++)
562  {
563  const label globalRegionI = regionOffset_[surfI] + i;
564 
565  minLevel_[globalRegionI] = globalMinLevel[surfI];
566  maxLevel_[globalRegionI] = globalMaxLevel[surfI];
567  gapLevel_[globalRegionI] =
568  maxLevel_[globalRegionI]
569  + globalLevelIncr[surfI];
570  extendedGapLevel_[globalRegionI] = globalGapLevel[surfI];
571  extendedGapMode_[globalRegionI] = globalGapMode[surfI];
572  selfProximity_[globalRegionI] = globalGapSelf[surfI];
573  extendedCurvatureLevel_[globalRegionI] = globalCurvLevel[surfI];
574  perpendicularAngle_[globalRegionI] = globalAngle[surfI];
575  if (globalPatchInfo.set(surfI))
576  {
577  patchInfo_.set
578  (
579  globalRegionI,
580  globalPatchInfo[surfI].clone()
581  );
582  }
583  blockLevel_[globalRegionI] = globalBlockLevel[surfI];
584  leakLevel_[globalRegionI] = globalLeakLevel[surfI];
585  }
586 
587  // Overwrite with region specific information
588  forAllConstIters(regionMinLevel[surfI], iter)
589  {
590  const label globalRegionI = regionOffset_[surfI] + iter.key();
591 
592  minLevel_[globalRegionI] = iter.val();
593  maxLevel_[globalRegionI] = regionMaxLevel[surfI][iter.key()];
594  gapLevel_[globalRegionI] =
595  maxLevel_[globalRegionI]
596  + regionLevelIncr[surfI][iter.key()];
597  }
598 
599  forAllConstIters(regionGapLevel[surfI], iter)
600  {
601  const label globalRegionI = regionOffset_[surfI] + iter.key();
602 
603  extendedGapLevel_[globalRegionI] =
604  regionGapLevel[surfI][iter.key()];
605  extendedGapMode_[globalRegionI] =
606  regionGapMode[surfI][iter.key()];
607  selfProximity_[globalRegionI] =
608  regionGapSelf[surfI][iter.key()];
609  }
610 
611  forAllConstIters(regionCurvLevel[surfI], iter)
612  {
613  const label globalRegionI = regionOffset_[surfI] + iter.key();
614  extendedCurvatureLevel_[globalRegionI] = iter.val();
615  }
616 
617  forAllConstIters(regionAngle[surfI], iter)
618  {
619  const label globalRegionI = regionOffset_[surfI] + iter.key();
620  perpendicularAngle_[globalRegionI] = iter.val();
621  }
622 
623  const Map<autoPtr<dictionary>>& localInfo = regionPatchInfo[surfI];
624  forAllConstIters(localInfo, iter)
625  {
626  const label globalRegionI = regionOffset_[surfI] + iter.key();
627  const dictionary& dict = *(iter.val());
628 
629  patchInfo_.set(globalRegionI, dict.clone());
630  }
631 
632  forAllConstIters(regionBlockLevel[surfI], iter)
633  {
634  const label globalRegionI = regionOffset_[surfI] + iter.key();
635 
636  blockLevel_[globalRegionI] = iter.val();
637  leakLevel_[globalRegionI] = iter.val();
638  }
639  }
640 }
641 
642 
643 Foam::refinementSurfaces::refinementSurfaces
644 (
645  const searchableSurfaces& allGeometry,
646  const labelList& surfaces,
647  const wordList& names,
648  const PtrList<surfaceZonesInfo>& surfZones,
649  const labelList& regionOffset,
650  const labelList& minLevel,
651  const labelList& maxLevel,
652  const labelList& gapLevel,
653  const scalarField& perpendicularAngle,
654  PtrList<dictionary>& patchInfo,
655  const bool dryRun
656 )
657 :
658  allGeometry_(allGeometry),
659  surfaces_(surfaces),
660  names_(names),
661  surfZones_(surfZones),
662  regionOffset_(regionOffset),
663  regionToSurface_(calcSurfaceIndex(allGeometry, surfaces)),
664  minLevel_(minLevel),
665  maxLevel_(maxLevel),
666  gapLevel_(gapLevel),
667  perpendicularAngle_(perpendicularAngle),
668  patchInfo_(patchInfo.size()),
669  dryRun_(dryRun)
670 {
671  forAll(patchInfo_, pI)
672  {
673  if (patchInfo.set(pI))
674  {
675  patchInfo_.set(pI, patchInfo.set(pI, nullptr));
676  }
677  }
678 }
679 
680 
681 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
682 
684 (
685  const label globalRegionI
686 ) const
687 {
688  const label surfI = regionToSurface_[globalRegionI];
689  const label localI = globalRegionI-regionOffset_[surfI];
690  return labelPair(surfI, localI);
691 }
692 
693 
694 // // Count number of triangles per surface region
695 // Foam::labelList Foam::refinementSurfaces::countRegions(const triSurface& s)
696 // {
697 // const geometricSurfacePatchList& regions = s.patches();
698 //
699 // labelList nTris(regions.size(), Zero);
700 //
701 // forAll(s, triI)
702 // {
703 // nTris[s[triI].region()]++;
704 // }
705 // return nTris;
706 // }
707 
708 
709 // // Pre-calculate the refinement level for every element
710 // void Foam::refinementSurfaces::wantedRefinementLevel
711 // (
712 // const shellSurfaces& shells,
713 // const label surfI,
714 // const List<pointIndexHit>& info, // Indices
715 // const pointField& ctrs, // Representative coordinate
716 // labelList& minLevelField
717 // ) const
718 // {
719 // const searchableSurface& geom = allGeometry_[surfaces_[surfI]];
720 //
721 // // Get per element the region
722 // labelList region;
723 // geom.getRegion(info, region);
724 //
725 // // Initialise fields to region wise minLevel
726 // minLevelField.setSize(ctrs.size());
727 // minLevelField = -1;
728 //
729 // forAll(minLevelField, i)
730 // {
731 // if (info[i].hit())
732 // {
733 // minLevelField[i] = minLevel(surfI, region[i]);
734 // }
735 // }
736 //
737 // // Find out if triangle inside shell with higher level
738 // // What level does shell want to refine fc to?
739 // labelList shellLevel;
740 // shells.findHigherLevel(ctrs, minLevelField, shellLevel);
741 //
742 // forAll(minLevelField, i)
743 // {
744 // minLevelField[i] = max(minLevelField[i], shellLevel[i]);
745 // }
746 // }
747 
748 
750 {
751  labelList surfaceMax(surfaces_.size(), Zero);
752 
753  forAll(surfaces_, surfI)
754  {
755  const wordList& regionNames = allGeometry_[surfaces_[surfI]].regions();
756 
757  forAll(regionNames, regionI)
758  {
759  label globalI = globalRegion(surfI, regionI);
760  const FixedList<label, 3>& gapInfo = extendedGapLevel_[globalI];
761  surfaceMax[surfI] = max(surfaceMax[surfI], gapInfo[2]);
762  }
763  }
764  return surfaceMax;
765 }
766 
767 
769 {
770  labelList surfaceMax(surfaces_.size(), Zero);
771 
772  forAll(surfaces_, surfI)
773  {
774  const wordList& regionNames = allGeometry_[surfaces_[surfI]].regions();
775 
776  forAll(regionNames, regionI)
777  {
778  label globalI = globalRegion(surfI, regionI);
779  const FixedList<label, 4>& gapInfo =
780  extendedCurvatureLevel_[globalI];
781  surfaceMax[surfI] = max(surfaceMax[surfI], gapInfo[2]);
782  }
783  }
784  return surfaceMax;
785 }
786 
787 
788 // Precalculate the refinement level for every element of the searchable
789 // surface.
790 void Foam::refinementSurfaces::setMinLevelFields(const shellSurfaces& shells)
791 {
792  forAll(surfaces_, surfI)
793  {
794  const searchableSurface& geom = allGeometry_[surfaces_[surfI]];
795 
796  // Cache the refinement level (max of surface level and shell level)
797  // on a per-element basis. Only makes sense if there are lots of
798  // elements. Possibly should have 'enough' elements to have fine
799  // enough resolution but for now just make sure we don't catch e.g.
800  // searchableBox (size=6)
801  if (geom.globalSize() > 10)
802  {
803  // Representative local coordinates and bounding sphere
804  pointField ctrs;
805  scalarField radiusSqr;
806  geom.boundingSpheres(ctrs, radiusSqr);
807 
808  labelList minLevelField(ctrs.size(), Zero);
809  {
810  // Get the element index in a roundabout way. Problem is e.g.
811  // distributed surface where local indices differ from global
812  // ones (needed for getRegion call)
813  List<pointIndexHit> info;
814  geom.findNearest(ctrs, radiusSqr, info);
815 
816  // Get per element the region
817  labelList region;
818  geom.getRegion(info, region);
819 
820  // From the region get the surface-wise refinement level
821  forAll(minLevelField, i)
822  {
823  if (info[i].hit()) //Note: should not be necessary
824  {
825  minLevelField[i] = minLevel(surfI, region[i]);
826  }
827  }
828  }
829 
830  // Find out if triangle inside shell with higher level
831  // What level does shell want to refine fc to?
832  labelList shellLevel;
833  shells.findHigherLevel(ctrs, minLevelField, shellLevel);
834 
835 
836  // In case of triangulated surfaces only cache value if triangle
837  // centre and vertices are in same shell
838  const auto* tsPtr = isA<const triSurface>(geom);
839 
840  if (tsPtr)
841  {
842  label nUncached = 0;
843 
844  // Check if points differing from ctr level
845 
846  const triSurface& ts = *tsPtr;
847  const pointField& points = ts.points();
848 
849  // Determine minimum expected level to avoid having to
850  // test lots of points
851  labelList minPointLevel(points.size(), labelMax);
852  forAll(shellLevel, triI)
853  {
854  const labelledTri& t = ts[triI];
855  label level = shellLevel[triI];
856  forAll(t, tI)
857  {
858  minPointLevel[t[tI]] = min(minPointLevel[t[tI]], level);
859  }
860  }
861 
862 
863  // See if inside any shells with higher refinement level
864  labelList pointLevel;
865  shells.findHigherLevel(points, minPointLevel, pointLevel);
866 
867 
868  // See if triangle centre values differ from triangle points
869  forAll(shellLevel, triI)
870  {
871  const labelledTri& t = ts[triI];
872  label fLevel = shellLevel[triI];
873  if
874  (
875  (pointLevel[t[0]] != fLevel)
876  || (pointLevel[t[1]] != fLevel)
877  || (pointLevel[t[2]] != fLevel)
878  )
879  {
880  //Pout<< "Detected triangle " << t.tri(ts.points())
881  // << " partially inside/partially outside" << endl;
882 
883  // Mark as uncached
884  shellLevel[triI] = -1;
885  nUncached++;
886  }
887  }
888 
889  if (!dryRun_)
890  {
891  Info<< "For geometry " << geom.name()
892  << " detected "
893  << returnReduce(nUncached, sumOp<label>())
894  << " uncached triangles out of " << geom.globalSize()
895  << endl;
896  }
897  }
898 
899 
900  // Combine overall level field with current shell level. Make sure
901  // to preserve -1 (from triSurfaceMeshes with triangles partly
902  // inside/outside
903  forAll(minLevelField, i)
904  {
905  if (min(minLevelField[i], shellLevel[i]) < 0)
906  {
907  minLevelField[i] = -1;
908  }
909  else
910  {
911  minLevelField[i] = max(minLevelField[i], shellLevel[i]);
912  }
913  }
914 
915  // Store minLevelField on surface
916  const_cast<searchableSurface&>(geom).setField(minLevelField);
917  }
918  }
919 }
920 
921 
922 // Precalculate the refinement level for every element of the searchable
923 // surface.
925 (
926  const scalar cosAngle,
927  const scalar level0EdgeLength
928 )
929 {
930  const labelList maxCurvLevel(maxCurvatureLevel());
931 
932 
933  forAll(surfaces_, surfI)
934  {
935  // Check if there is a specification of the extended curvature
936  if (maxCurvLevel[surfI] <= 0)
937  {
938  continue;
939  }
940 
941  const searchableSurface& geom = allGeometry_[surfaces_[surfI]];
942 
943  const auto* tsPtr = isA<const triSurface>(geom);
944 
945  // Cache the refinement level (max of surface level and shell level)
946  // on a per-element basis. Only makes sense if there are lots of
947  // elements. Possibly should have 'enough' elements to have fine
948  // enough resolution but for now just make sure we don't catch e.g.
949  // searchableBox (size=6)
950  if (tsPtr)
951  {
952  // Representative local coordinates and bounding sphere
953  pointField ctrs;
954  scalarField radiusSqr;
955  geom.boundingSpheres(ctrs, radiusSqr);
956 
957  labelList minLevelField(ctrs.size(), Zero);
958  //labelList surfMin(ctrs.size(), Zero);
959  labelList surfMax(ctrs.size(), Zero);
960  labelList nCurvCells(ctrs.size(), Zero);
961  labelList curvIgnore(ctrs.size(), -1);
962  {
963  // Get the element index in a roundabout way. Problem is e.g.
964  // distributed surface where local indices differ from global
965  // ones (needed for getRegion call)
966  List<pointIndexHit> info;
967  geom.findNearest(ctrs, radiusSqr, info);
968 
969  // Get per element the region
970  labelList region;
971  geom.getRegion(info, region);
972 
973  // See if a cached level field available (from e.g. shells)
974  labelList cachedField;
975  geom.getField(info, cachedField);
976 
977  // From the region get the surface-wise refinement level
978  forAll(minLevelField, i)
979  {
980  if (info[i].hit()) //Note: should not be necessary
981  {
982  const label globali = globalRegion(surfI, region[i]);
983  curvIgnore[i] = extendedCurvatureLevel_[globali][3];
984  nCurvCells[i] = extendedCurvatureLevel_[globali][0];
985  //surfMin[i] = extendedCurvatureLevel_[globali][1];
986  surfMax[i] = extendedCurvatureLevel_[globali][2];
987 
988  minLevelField[i] = minLevel(surfI, region[i]);
989  if (cachedField.size() > i)
990  {
991  minLevelField[i] =
992  max(minLevelField[i], cachedField[i]);
993  }
994  }
995  }
996  }
997 
998  // Calculate per-triangle curvature. This is the max of the
999  // measured point-based curvature + some constraints.
1000  scalarField cellCurv(ctrs.size(), Zero);
1001  {
1002  // Walk surface and detect sharp features. Returns maximum
1003  // curvature (per surface point. Note: returns per point, not
1004  // per localpoint)
1005  const auto& ts = *tsPtr;
1006  auto tcurv(triSurfaceTools::curvatures(ts));
1007  auto& curv = tcurv.ref();
1008 
1009  // Reset curvature on sharp edges (and neighbours since
1010  // curvature uses extended stencil)
1011  {
1012  const auto& edgeFaces = ts.edgeFaces();
1013  const auto& edges = ts.edges();
1014  const auto& points = ts.points();
1015  const auto& mp = ts.meshPoints();
1016 
1017  bitSet isOnSharpEdge(points.size());
1018  forAll(edgeFaces, edgei)
1019  {
1020  const auto& eFaces = edgeFaces[edgei];
1021  const edge meshE(mp, edges[edgei]);
1022 
1023  if (eFaces.size() == 2)
1024  {
1025  const auto& f0 = ts[eFaces[0]];
1026  const auto& f1 = ts[eFaces[1]];
1027 
1028  const vector n0 = f0.unitNormal(points);
1029 
1030  const int dir0 = f0.edgeDirection(meshE);
1031  const int dir1 = f1.edgeDirection(meshE);
1032  vector n1 = f1.unitNormal(points);
1033  if (dir0 == dir1)
1034  {
1035  // Flip since use edge in same direction
1036  // (should not be the case for 'proper'
1037  // surfaces)
1038  n1 = -n1;
1039  }
1040 
1041  if ((n0&n1) < cosAngle)
1042  {
1043  isOnSharpEdge.set(meshE[0]);
1044  isOnSharpEdge.set(meshE[1]);
1045  }
1046  }
1047  }
1048 
1049  // Extend by one layer
1050  {
1051  bitSet oldOnSharpEdge(isOnSharpEdge);
1052  isOnSharpEdge = false;
1053  for (const auto& f : ts)
1054  {
1055  for (const label pointi : f)
1056  {
1057  if (oldOnSharpEdge[pointi])
1058  {
1059  // Mark all points on triangle
1060  isOnSharpEdge.set(f);
1061  break;
1062  }
1063  }
1064  }
1065  }
1066 
1067 
1068  // Unmark curvature
1069  autoPtr<OBJstream> str;
1070  //if (debug)
1071  //{
1072  // str.reset
1073  // (
1074  // new OBJstream
1075  // (
1076  // "sharpEdgePoints_"
1077  // + geom.name()
1078  // + ".obj"
1079  // )
1080  // );
1081  // Info<< "Writing sharp edge points to "
1082  // << str().name() << endl;
1083  //}
1084 
1085  for (const label pointi : isOnSharpEdge)
1086  {
1087  // Reset measured point-based curvature
1088  curv[pointi] = 0.0;
1089  if (str)
1090  {
1091  str().write(points[pointi]);
1092  }
1093  }
1094  }
1095 
1096  // Reset curvature on -almost- sharp edges.
1097  // This resets the point-based curvature if the edge
1098  // is considered to be a sharp edge based on its actual
1099  // curvature. This is only used if the 'ignore' level is
1100  // given.
1101  {
1102  // Pass 1: accumulate constraints on the points - get
1103  // the minimum of curvature constraints on the
1104  // connected triangles. Looks at user-specified
1105  // min curvature - does not use actual measured
1106  // curvature
1107  scalarField pointMinCurv(ts.nPoints(), VGREAT);
1108 
1109  forAll(ts, i)
1110  {
1111  // Is ignore level given for surface
1112  const label level = curvIgnore[i];
1113  if (level >= 0)
1114  {
1115  // Convert to (inv) size
1116  const scalar length = level0EdgeLength/(2<<level);
1117  const scalar invLength = 1.0/length;
1118  for (const label pointi : ts[i])
1119  {
1120  if
1121  (
1122  invLength < pointMinCurv[pointi]
1123  && curv[pointi] > SMALL
1124  )
1125  {
1126  //Pout<< "** at location:"
1127  // << ts.points()[pointi]
1128  // << " measured curv:" << curv[pointi]
1129  // << " radius:" << 1.0/curv[pointi]
1130  // << " ignore level:" << level
1131  // << " ignore radius:" << length
1132  // << " resetting minCurv to "
1133  // << invLength
1134  // << endl;
1135  }
1136 
1137  pointMinCurv[pointi] =
1138  min(pointMinCurv[pointi], invLength);
1139  }
1140  }
1141  }
1142 
1143  // Clip curvature (should do nothing for most points unless
1144  // ignore-level is triggered)
1145  forAll(pointMinCurv, pointi)
1146  {
1147  if (pointMinCurv[pointi] < curv[pointi])
1148  {
1149  //Pout<< "** at location:" << ts.points()[pointi]
1150  // << " measured curv:" << curv[pointi]
1151  // << " radius:" << 1.0/curv[pointi]
1152  // << " cellLimit:" << pointMinCurv[pointi]
1153  // << endl;
1154 
1155  // Set up to ignore point
1156  //curv[pointi] = pointMinCurv[pointi];
1157  curv[pointi] = 0.0;
1158  }
1159  }
1160  }
1161 
1162 
1163  forAll(ts, i)
1164  {
1165  const auto& f = ts[i];
1166  // Take max curvature (= min radius of curvature)
1167  cellCurv[i] = max(curv[f[0]], max(curv[f[1]], curv[f[2]]));
1168  }
1169  }
1170 
1171 
1172  //if(debug)
1173  //{
1174  // const scalar maxCurv = gMax(cellCurv);
1175  // if (maxCurv > SMALL)
1176  // {
1177  // const scalar r = scalar(1.0)/maxCurv;
1178  //
1179  // Pout<< "For geometry " << geom.name()
1180  // << " have curvature max " << maxCurv
1181  // << " which equates to radius:" << r
1182  // << " which equates to refinement level "
1183  // << log2(level0EdgeLength/r)
1184  // << endl;
1185  // }
1186  //}
1187 
1188  forAll(cellCurv, i)
1189  {
1190  if (cellCurv[i] > SMALL && nCurvCells[i] > 0)
1191  {
1192  //- ?If locally have a cached field override the
1193  // surface-based level ignore any curvature?
1194  //if (minLevelField[i] > surfMin[i])
1195  //{
1196  // // Ignore curvature
1197  //}
1198  //else
1199  //if (surfMin[i] == surfMax[i])
1200  //{
1201  // // Ignore curvature. Bypass calculation below.
1202  //}
1203  //else
1204  {
1205  // Re-work the curvature into a radius and into a
1206  // number of cells
1207  const scalar r = scalar(1.0)/cellCurv[i];
1208  const scalar level =
1209  log2(nCurvCells[i]*level0EdgeLength/r);
1210  const label l = round(level);
1211 
1212  if (l > minLevelField[i] && l <= surfMax[i])
1213  {
1214  minLevelField[i] = l;
1215  }
1216  }
1217  }
1218  }
1219 
1220 
1221  // Store minLevelField on surface
1222  const_cast<searchableSurface&>(geom).setField(minLevelField);
1223  }
1224  }
1225 }
1226 
1228 // Find intersections of edge. Return -1 or first surface with higher minLevel
1229 // number.
1231 (
1232  const shellSurfaces& shells,
1233 
1234  const pointField& start,
1235  const pointField& end,
1236  const labelList& currentLevel, // current cell refinement level
1237 
1238  labelList& surfaces,
1239  labelList& surfaceLevel
1240 ) const
1241 {
1242  surfaces.setSize(start.size());
1243  surfaces = -1;
1244  surfaceLevel.setSize(start.size());
1245  surfaceLevel = -1;
1246 
1247  if (surfaces_.empty())
1248  {
1249  return;
1250  }
1251 
1252  if (surfaces_.size() == 1)
1253  {
1254  // Optimisation: single segmented surface. No need to duplicate
1255  // point storage.
1256 
1257  label surfI = 0;
1258 
1259  const searchableSurface& geom = allGeometry_[surfaces_[surfI]];
1260 
1261  // Do intersection test
1262  List<pointIndexHit> intersectionInfo(start.size());
1263  geom.findLineAny(start, end, intersectionInfo);
1264 
1265 
1266  // Surface-based refinement level
1267  labelList surfaceOnlyLevel(start.size(), -1);
1268  {
1269  // Get per intersection the region
1270  labelList region;
1271  geom.getRegion(intersectionInfo, region);
1272 
1273  forAll(intersectionInfo, i)
1274  {
1275  if (intersectionInfo[i].hit())
1276  {
1277  surfaceOnlyLevel[i] = minLevel(surfI, region[i]);
1278  }
1279  }
1280  }
1281 
1282 
1283  // Get shell refinement level if higher
1284  const labelList localLevel
1285  (
1286  findHigherLevel
1287  (
1288  geom,
1289  shells,
1290  intersectionInfo,
1291  surfaceOnlyLevel // starting level
1292  )
1293  );
1294 
1295 
1296  // Combine localLevel with current level
1297  forAll(localLevel, i)
1298  {
1299  if (localLevel[i] > currentLevel[i])
1300  {
1301  surfaces[i] = surfI; // index of surface
1302  surfaceLevel[i] = localLevel[i];
1303  }
1304  }
1305 
1306  return;
1307  }
1308 
1309 
1310 
1311  // Work arrays
1312  pointField p0(start);
1313  pointField p1(end);
1314  labelList intersectionToPoint(identity(start.size()));
1315  List<pointIndexHit> intersectionInfo(start.size());
1316 
1317  forAll(surfaces_, surfI)
1318  {
1319  const searchableSurface& geom = allGeometry_[surfaces_[surfI]];
1320 
1321  // Do intersection test
1322  geom.findLineAny(p0, p1, intersectionInfo);
1323 
1324 
1325  // Surface-based refinement level
1326  labelList surfaceOnlyLevel(intersectionInfo.size(), -1);
1327  {
1328  // Get per intersection the region
1329  labelList region;
1330  geom.getRegion(intersectionInfo, region);
1331 
1332  forAll(intersectionInfo, i)
1333  {
1334  if (intersectionInfo[i].hit())
1335  {
1336  surfaceOnlyLevel[i] = minLevel(surfI, region[i]);
1337  }
1338  }
1339  }
1340 
1341 
1342  // Get shell refinement level if higher
1343  const labelList localLevel
1344  (
1345  findHigherLevel
1346  (
1347  geom,
1348  shells,
1349  intersectionInfo,
1350  surfaceOnlyLevel
1351  )
1352  );
1353 
1354 
1355  // Combine localLevel with current level
1356  label missI = 0;
1357  forAll(localLevel, i)
1358  {
1359  label pointI = intersectionToPoint[i];
1360 
1361  if (localLevel[i] > currentLevel[pointI])
1362  {
1363  // Mark point for refinement
1364  surfaces[pointI] = surfI;
1365  surfaceLevel[pointI] = localLevel[i];
1366  }
1367  else
1368  {
1369  p0[missI] = start[pointI];
1370  p1[missI] = end[pointI];
1371  intersectionToPoint[missI] = pointI;
1372  missI++;
1373  }
1374  }
1375 
1376 
1377  // All done? Note that this decision should be synchronised
1378  if (returnReduceAnd(missI == 0))
1379  {
1380  break;
1381  }
1382 
1383  // Trim misses
1384  p0.setSize(missI);
1385  p1.setSize(missI);
1386  intersectionToPoint.setSize(missI);
1387  intersectionInfo.setSize(missI);
1388  }
1390 
1391 
1393 (
1394  const pointField& start,
1395  const pointField& end,
1396  const labelList& currentLevel, // current cell refinement level
1397 
1398  const labelList& globalMinLevel,
1399  const labelList& globalMaxLevel,
1400 
1401  List<vectorList>& surfaceNormal,
1402  labelListList& surfaceLevel
1403 ) const
1404 {
1405  surfaceLevel.setSize(start.size());
1406  surfaceNormal.setSize(start.size());
1407 
1408  if (surfaces_.empty())
1409  {
1410  return;
1411  }
1412 
1413  // Work arrays
1414  List<List<pointIndexHit>> hitInfo;
1415 
1416  forAll(surfaces_, surfI)
1417  {
1418  const searchableSurface& surface = allGeometry_[surfaces_[surfI]];
1419 
1420  surface.findLineAll(start, end, hitInfo);
1421 
1422  // Repack hits for surface into flat list
1423  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1424  // To avoid overhead of calling getRegion for every point
1425 
1426  label n = 0;
1427  forAll(hitInfo, pointI)
1428  {
1429  n += hitInfo[pointI].size();
1430  }
1431 
1432  List<pointIndexHit> surfInfo(n);
1433  labelList pointMap(n);
1434  n = 0;
1435 
1436  forAll(hitInfo, pointI)
1437  {
1438  const List<pointIndexHit>& pHits = hitInfo[pointI];
1439 
1440  forAll(pHits, i)
1441  {
1442  surfInfo[n] = pHits[i];
1443  pointMap[n] = pointI;
1444  n++;
1445  }
1446  }
1447 
1448  labelList surfRegion(n);
1449  vectorField surfNormal(n);
1450  surface.getRegion(surfInfo, surfRegion);
1451  surface.getNormal(surfInfo, surfNormal);
1452 
1453  surfInfo.clear();
1454 
1455 
1456  // Extract back into pointwise
1457  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
1458 
1459  forAll(surfRegion, i)
1460  {
1461  label region = globalRegion(surfI, surfRegion[i]);
1462  label pointI = pointMap[i];
1463 
1464  if
1465  (
1466  currentLevel[pointI] >= globalMinLevel[region]
1467  && currentLevel[pointI] < globalMaxLevel[region]
1468  )
1469  {
1470  // Append to pointI info
1471  label sz = surfaceNormal[pointI].size();
1472  surfaceNormal[pointI].setSize(sz+1);
1473  surfaceNormal[pointI][sz] = surfNormal[i];
1474 
1475  surfaceLevel[pointI].setSize(sz+1);
1476  surfaceLevel[pointI][sz] = globalMaxLevel[region];
1477  }
1478  }
1479  }
1481 
1482 
1484 (
1485  const pointField& start,
1486  const pointField& end,
1487  const labelList& currentLevel, // current cell refinement level
1488 
1489  const labelList& globalMinLevel,
1490  const labelList& globalMaxLevel,
1491 
1493  List<vectorList>& surfaceNormal,
1494  labelListList& surfaceLevel
1495 ) const
1496 {
1497  surfaceLevel.setSize(start.size());
1498  surfaceNormal.setSize(start.size());
1499  surfaceLocation.setSize(start.size());
1500 
1501  if (surfaces_.empty())
1502  {
1503  return;
1504  }
1505 
1506  // Work arrays
1507  List<List<pointIndexHit>> hitInfo;
1508 
1509  forAll(surfaces_, surfI)
1510  {
1511  const searchableSurface& surface = allGeometry_[surfaces_[surfI]];
1512 
1513  surface.findLineAll(start, end, hitInfo);
1514 
1515  // Repack hits for surface into flat list
1516  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1517  // To avoid overhead of calling getRegion for every point
1518 
1519  label n = 0;
1520  forAll(hitInfo, pointI)
1521  {
1522  n += hitInfo[pointI].size();
1523  }
1524 
1525  List<pointIndexHit> surfInfo(n);
1526  labelList pointMap(n);
1527  n = 0;
1528 
1529  forAll(hitInfo, pointI)
1530  {
1531  const List<pointIndexHit>& pHits = hitInfo[pointI];
1532 
1533  forAll(pHits, i)
1534  {
1535  surfInfo[n] = pHits[i];
1536  pointMap[n] = pointI;
1537  n++;
1538  }
1539  }
1540 
1541  labelList surfRegion(n);
1542  vectorField surfNormal(n);
1543  surface.getRegion(surfInfo, surfRegion);
1544  surface.getNormal(surfInfo, surfNormal);
1545 
1546  // Extract back into pointwise
1547  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
1548 
1549  forAll(surfRegion, i)
1550  {
1551  label region = globalRegion(surfI, surfRegion[i]);
1552  label pointI = pointMap[i];
1553 
1554  if
1555  (
1556  currentLevel[pointI] >= globalMinLevel[region]
1557  && currentLevel[pointI] < globalMaxLevel[region]
1558  )
1559  {
1560  // Append to pointI info
1561  label sz = surfaceNormal[pointI].size();
1562  surfaceLocation[pointI].setSize(sz+1);
1563  surfaceLocation[pointI][sz] = surfInfo[i].hitPoint();
1564 
1565  surfaceNormal[pointI].setSize(sz+1);
1566  surfaceNormal[pointI][sz] = surfNormal[i];
1567 
1568  surfaceLevel[pointI].setSize(sz+1);
1569  // Level should just be higher than provided point level.
1570  // Actual value is not important.
1571  surfaceLevel[pointI][sz] = globalMaxLevel[region];
1572  }
1573  }
1574  }
1575 }
1576 
1577 
1578 //void Foam::refinementSurfaces::findAllIntersections
1579 //(
1580 // const labelList& surfacesToTest,
1581 // const pointField& start,
1582 // const pointField& end,
1583 //
1584 // List<labelList>& hitSurface, // surface index
1585 // List<pointList>& hitLocation, // surface location
1586 // List<labelList>& hitRegion,
1587 // List<vectorField>& hitNormal
1588 //) const
1589 //{
1590 // hitSurface.setSize(start.size());
1591 // hitLocation.setSize(start.size());
1592 // hitRegion.setSize(start.size());
1593 // hitNormal.setSize(start.size());
1594 //
1595 // if (surfaces_.empty())
1596 // {
1597 // return;
1598 // }
1599 //
1600 // // Work arrays
1601 // List<List<pointIndexHit>> hitInfo;
1602 //
1603 // for (const label surfI : surfacesToTest)
1604 // {
1605 // const searchableSurface& surface = allGeometry_[surfaces_[surfI]];
1606 //
1607 // surface.findLineAll(start, end, hitInfo);
1608 //
1609 // // Repack hits for surface into flat list
1610 // // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1611 // // To avoid overhead of calling getRegion for every point
1612 //
1613 // label n = 0;
1614 // forAll(hitInfo, pointI)
1615 // {
1616 // n += hitInfo[pointI].size();
1617 // }
1618 //
1619 // List<pointIndexHit> surfInfo(n);
1620 // labelList pointMap(n);
1621 // n = 0;
1622 //
1623 // forAll(hitInfo, pointI)
1624 // {
1625 // const List<pointIndexHit>& pHits = hitInfo[pointI];
1626 //
1627 // forAll(pHits, i)
1628 // {
1629 // surfInfo[n] = pHits[i];
1630 // pointMap[n] = pointI;
1631 // n++;
1632 // }
1633 // }
1634 //
1635 // labelList surfRegion(n);
1636 // vectorField surfNormal(n);
1637 // surface.getRegion(surfInfo, surfRegion);
1638 // surface.getNormal(surfInfo, surfNormal);
1639 //
1640 // surfInfo.clear();
1641 //
1642 //
1643 // // Extract back into pointwise
1644 // // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
1645 //
1646 // forAll(surfRegion, i)
1647 // {
1648 // const label pointI = pointMap[i];
1649 //
1650 // // Append to pointI info
1651 // hitSurface[pointI].append(surfI);
1652 // hitRegion[pointI].append(globalRegion(surfI, surfRegion[i]));
1653 // hitLocation[pointI].append(surfInfo[i].hitPoint());
1654 // hitNormal[pointI].append(surfNormal[i]);
1655 // }
1656 // }
1657 //}
1658 
1659 
1661 (
1662  const labelList& surfacesToTest,
1663  const pointField& start,
1664  const pointField& end,
1665 
1666  labelList& surface1,
1667  List<pointIndexHit>& hit1,
1668  labelList& region1,
1669  labelList& surface2,
1670  List<pointIndexHit>& hit2,
1671  labelList& region2
1672 ) const
1673 {
1674  // 1. intersection from start to end
1675  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1676 
1677  // Initialize arguments
1678  surface1.setSize(start.size());
1679  surface1 = -1;
1680  hit1.setSize(start.size());
1681  region1.setSize(start.size());
1682 
1683  // Current end of segment to test.
1684  pointField nearest(end);
1685  // Work array
1686  List<pointIndexHit> nearestInfo(start.size());
1687  labelList region;
1688 
1689  forAll(surfacesToTest, testI)
1690  {
1691  label surfI = surfacesToTest[testI];
1692 
1693  const searchableSurface& surface = allGeometry_[surfaces_[surfI]];
1694 
1695  // See if any intersection between start and current nearest
1696  surface.findLine
1697  (
1698  start,
1699  nearest,
1700  nearestInfo
1701  );
1702  surface.getRegion
1703  (
1704  nearestInfo,
1705  region
1706  );
1707 
1708  forAll(nearestInfo, pointI)
1709  {
1710  if (nearestInfo[pointI].hit())
1711  {
1712  hit1[pointI] = nearestInfo[pointI];
1713  surface1[pointI] = surfI;
1714  region1[pointI] = region[pointI];
1715  nearest[pointI] = hit1[pointI].hitPoint();
1716  }
1717  }
1718  }
1719 
1720 
1721  // 2. intersection from end to last intersection
1722  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1723 
1724  // Find the nearest intersection from end to start. Note that we initialize
1725  // to the first intersection (if any).
1726  surface2 = surface1;
1727  hit2 = hit1;
1728  region2 = region1;
1729 
1730  // Set current end of segment to test.
1731  forAll(nearest, pointI)
1732  {
1733  if (hit1[pointI].hit())
1734  {
1735  nearest[pointI] = hit1[pointI].point();
1736  }
1737  else
1738  {
1739  // Disable testing by setting to end.
1740  nearest[pointI] = end[pointI];
1741  }
1742  }
1743 
1744  forAll(surfacesToTest, testI)
1745  {
1746  label surfI = surfacesToTest[testI];
1747 
1748  const searchableSurface& surface = allGeometry_[surfaces_[surfI]];
1749 
1750  // See if any intersection between end and current nearest
1751  surface.findLine
1752  (
1753  end,
1754  nearest,
1755  nearestInfo
1756  );
1757  surface.getRegion
1758  (
1759  nearestInfo,
1760  region
1761  );
1762 
1763  forAll(nearestInfo, pointI)
1764  {
1765  if (nearestInfo[pointI].hit())
1766  {
1767  hit2[pointI] = nearestInfo[pointI];
1768  surface2[pointI] = surfI;
1769  region2[pointI] = region[pointI];
1770  nearest[pointI] = hit2[pointI].hitPoint();
1771  }
1772  }
1773  }
1774 
1775 
1776  // Make sure that if hit1 has hit something, hit2 will have at least the
1777  // same point (due to tolerances it might miss its end point)
1778  forAll(hit1, pointI)
1779  {
1780  if (hit1[pointI].hit() && !hit2[pointI].hit())
1781  {
1782  hit2[pointI] = hit1[pointI];
1783  surface2[pointI] = surface1[pointI];
1784  region2[pointI] = region1[pointI];
1785  }
1786  }
1788 
1789 
1791 (
1792  const labelList& surfacesToTest,
1793  const pointField& start,
1794  const pointField& end,
1795 
1796  labelList& surface1,
1797  List<pointIndexHit>& hit1,
1798  labelList& region1,
1799  vectorField& normal1,
1800 
1801  labelList& surface2,
1802  List<pointIndexHit>& hit2,
1803  labelList& region2,
1804  vectorField& normal2
1805 ) const
1806 {
1807  // 1. intersection from start to end
1808  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1809 
1810  // Initialize arguments
1811  surface1.setSize(start.size());
1812  surface1 = -1;
1813  hit1.setSize(start.size());
1814  region1.setSize(start.size());
1815  region1 = -1;
1816  normal1.setSize(start.size());
1817  normal1 = Zero;
1818 
1819  // Current end of segment to test.
1820  pointField nearest(end);
1821  // Work array
1822  List<pointIndexHit> nearestInfo(start.size());
1823  labelList region;
1824  vectorField normal;
1825 
1826  forAll(surfacesToTest, testI)
1827  {
1828  label surfI = surfacesToTest[testI];
1829  const searchableSurface& geom = allGeometry_[surfaces_[surfI]];
1830 
1831  // See if any intersection between start and current nearest
1832  geom.findLine(start, nearest, nearestInfo);
1833  geom.getRegion(nearestInfo, region);
1834  geom.getNormal(nearestInfo, normal);
1835 
1836  forAll(nearestInfo, pointI)
1837  {
1838  if (nearestInfo[pointI].hit())
1839  {
1840  hit1[pointI] = nearestInfo[pointI];
1841  surface1[pointI] = surfI;
1842  region1[pointI] = region[pointI];
1843  normal1[pointI] = normal[pointI];
1844  nearest[pointI] = hit1[pointI].hitPoint();
1845  }
1846  }
1847  }
1848 
1849 
1850  // 2. intersection from end to last intersection
1851  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1852 
1853  // Find the nearest intersection from end to start. Note that we initialize
1854  // to the first intersection (if any).
1855  surface2 = surface1;
1856  hit2 = hit1;
1857  region2 = region1;
1858  normal2 = normal1;
1859 
1860  // Set current end of segment to test.
1861  forAll(nearest, pointI)
1862  {
1863  if (hit1[pointI].hit())
1864  {
1865  nearest[pointI] = hit1[pointI].point();
1866  }
1867  else
1868  {
1869  // Disable testing by setting to end.
1870  nearest[pointI] = end[pointI];
1871  }
1872  }
1873 
1874  forAll(surfacesToTest, testI)
1875  {
1876  label surfI = surfacesToTest[testI];
1877  const searchableSurface& geom = allGeometry_[surfaces_[surfI]];
1878 
1879  // See if any intersection between end and current nearest
1880  geom.findLine(end, nearest, nearestInfo);
1881  geom.getRegion(nearestInfo, region);
1882  geom.getNormal(nearestInfo, normal);
1883 
1884  forAll(nearestInfo, pointI)
1885  {
1886  if (nearestInfo[pointI].hit())
1887  {
1888  hit2[pointI] = nearestInfo[pointI];
1889  surface2[pointI] = surfI;
1890  region2[pointI] = region[pointI];
1891  normal2[pointI] = normal[pointI];
1892  nearest[pointI] = hit2[pointI].hitPoint();
1893  }
1894  }
1895  }
1896 
1897 
1898  // Make sure that if hit1 has hit something, hit2 will have at least the
1899  // same point (due to tolerances it might miss its end point)
1900  forAll(hit1, pointI)
1901  {
1902  if (hit1[pointI].hit() && !hit2[pointI].hit())
1903  {
1904  hit2[pointI] = hit1[pointI];
1905  surface2[pointI] = surface1[pointI];
1906  region2[pointI] = region1[pointI];
1907  normal2[pointI] = normal1[pointI];
1908  }
1909  }
1911 
1912 
1914 (
1915  const pointField& start,
1916  const pointField& end,
1917 
1918  labelList& surface1,
1919  vectorField& normal1
1920 ) const
1921 {
1922  // Initialize arguments
1923  surface1.setSize(start.size());
1924  surface1 = -1;
1925  normal1.setSize(start.size());
1926  normal1 = Zero;
1927 
1928  // Current end of segment to test.
1929  pointField nearest(end);
1930  // Work array
1931  List<pointIndexHit> nearestInfo(start.size());
1932  labelList region;
1933  vectorField normal;
1934 
1935  forAll(surfaces_, surfI)
1936  {
1937  const searchableSurface& geom = allGeometry_[surfaces_[surfI]];
1938 
1939  // See if any intersection between start and current nearest
1940  geom.findLine(start, nearest, nearestInfo);
1941  geom.getNormal(nearestInfo, normal);
1942 
1943  forAll(nearestInfo, pointI)
1944  {
1945  if (nearestInfo[pointI].hit())
1946  {
1947  surface1[pointI] = surfI;
1948  normal1[pointI] = normal[pointI];
1949  nearest[pointI] = nearestInfo[pointI].point();
1950  }
1951  }
1952  }
1954 
1955 
1957 (
1958  const pointField& start,
1959  const pointField& end,
1960 
1961  labelList& surface1,
1962  List<pointIndexHit>& hitInfo1,
1963  vectorField& normal1
1964 ) const
1965 {
1966  // 1. intersection from start to end
1967  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1968 
1969  // Initialize arguments
1970  surface1.setSize(start.size());
1971  surface1 = -1;
1972  hitInfo1.setSize(start.size());
1973  hitInfo1 = pointIndexHit();
1974  normal1.setSize(start.size());
1975  normal1 = Zero;
1976 
1977  // Current end of segment to test.
1978  pointField nearest(end);
1979  // Work array
1980  List<pointIndexHit> nearestInfo(start.size());
1981  labelList region;
1982  vectorField normal;
1983 
1984  forAll(surfaces_, surfI)
1985  {
1986  const searchableSurface& geom = allGeometry_[surfaces_[surfI]];
1987 
1988  // See if any intersection between start and current nearest
1989  geom.findLine(start, nearest, nearestInfo);
1990  geom.getNormal(nearestInfo, normal);
1991 
1992  forAll(nearestInfo, pointI)
1993  {
1994  if (nearestInfo[pointI].hit())
1995  {
1996  surface1[pointI] = surfI;
1997  hitInfo1[pointI] = nearestInfo[pointI];
1998  normal1[pointI] = normal[pointI];
1999  nearest[pointI] = nearestInfo[pointI].point();
2000  }
2001  }
2002  }
2004 
2005 
2007 (
2008  const pointField& start,
2009  const pointField& end,
2010 
2011  labelList& hitSurface,
2012  List<pointIndexHit>& hitInfo
2013 ) const
2014 {
2016  (
2017  allGeometry_,
2018  surfaces_,
2019  start,
2020  end,
2021  hitSurface,
2022  hitInfo
2023  );
2025 
2026 
2028 (
2029  const labelList& surfacesToTest,
2030  const pointField& samples,
2031  const scalarField& nearestDistSqr,
2032  labelList& hitSurface,
2033  List<pointIndexHit>& hitInfo
2034 ) const
2035 {
2036  labelList geometries(labelUIndList(surfaces_, surfacesToTest));
2037 
2038  // Do the tests. Note that findNearest returns index in geometries.
2040  (
2041  allGeometry_,
2042  geometries,
2043  samples,
2044  nearestDistSqr,
2045  hitSurface,
2046  hitInfo
2047  );
2048 
2049  // Rework the hitSurface to be surface (i.e. index into surfaces_)
2050  forAll(hitSurface, pointI)
2051  {
2052  if (hitSurface[pointI] != -1)
2053  {
2054  hitSurface[pointI] = surfacesToTest[hitSurface[pointI]];
2055  }
2056  }
2058 
2059 
2061 (
2062  const labelList& surfacesToTest,
2063  const pointField& samples,
2064  const scalarField& nearestDistSqr,
2065  labelList& hitSurface,
2066  labelList& hitRegion
2067 ) const
2068 {
2069  labelList geometries(labelUIndList(surfaces_, surfacesToTest));
2070 
2071  // Do the tests. Note that findNearest returns index in geometries.
2072  List<pointIndexHit> hitInfo;
2074  (
2075  allGeometry_,
2076  geometries,
2077  samples,
2078  nearestDistSqr,
2079  hitSurface,
2080  hitInfo
2081  );
2082 
2083  // Rework the hitSurface to be surface (i.e. index into surfaces_)
2084  forAll(hitSurface, pointI)
2085  {
2086  if (hitSurface[pointI] != -1)
2087  {
2088  hitSurface[pointI] = surfacesToTest[hitSurface[pointI]];
2089  }
2090  }
2091 
2092  // Collect the region
2093  hitRegion.setSize(hitSurface.size());
2094  hitRegion = -1;
2095 
2096  forAll(surfacesToTest, i)
2097  {
2098  label surfI = surfacesToTest[i];
2099 
2100  // Collect hits for surfI
2101  const labelList localIndices(findIndices(hitSurface, surfI));
2102 
2103  List<pointIndexHit> localHits
2104  (
2105  UIndirectList<pointIndexHit>
2106  (
2107  hitInfo,
2108  localIndices
2109  )
2110  );
2111 
2112  labelList localRegion;
2113  allGeometry_[surfaces_[surfI]].getRegion(localHits, localRegion);
2114 
2115  forAll(localIndices, i)
2116  {
2117  hitRegion[localIndices[i]] = localRegion[i];
2118  }
2119  }
2121 
2122 
2124 (
2125  const labelList& surfacesToTest,
2126  const pointField& samples,
2127  const scalarField& nearestDistSqr,
2128  labelList& hitSurface,
2129  List<pointIndexHit>& hitInfo,
2130  labelList& hitRegion,
2131  vectorField& hitNormal
2132 ) const
2133 {
2134  labelList geometries(labelUIndList(surfaces_, surfacesToTest));
2135 
2136  // Do the tests. Note that findNearest returns index in geometries.
2138  (
2139  allGeometry_,
2140  geometries,
2141  samples,
2142  nearestDistSqr,
2143  hitSurface,
2144  hitInfo
2145  );
2146 
2147  // Rework the hitSurface to be surface (i.e. index into surfaces_)
2148  forAll(hitSurface, pointI)
2149  {
2150  if (hitSurface[pointI] != -1)
2151  {
2152  hitSurface[pointI] = surfacesToTest[hitSurface[pointI]];
2153  }
2154  }
2155 
2156  // Collect the region
2157  hitRegion.setSize(hitSurface.size());
2158  hitRegion = -1;
2159  hitNormal.setSize(hitSurface.size());
2160  hitNormal = Zero;
2161 
2162  forAll(surfacesToTest, i)
2163  {
2164  label surfI = surfacesToTest[i];
2165 
2166  // Collect hits for surfI
2167  const labelList localIndices(findIndices(hitSurface, surfI));
2168 
2169  List<pointIndexHit> localHits
2170  (
2171  UIndirectList<pointIndexHit>
2172  (
2173  hitInfo,
2174  localIndices
2175  )
2176  );
2177 
2178  // Region
2179  labelList localRegion;
2180  allGeometry_[surfaces_[surfI]].getRegion(localHits, localRegion);
2181 
2182  forAll(localIndices, i)
2183  {
2184  hitRegion[localIndices[i]] = localRegion[i];
2185  }
2186 
2187  // Normal
2188  vectorField localNormal;
2189  allGeometry_[surfaces_[surfI]].getNormal(localHits, localNormal);
2190 
2191  forAll(localIndices, i)
2192  {
2193  hitNormal[localIndices[i]] = localNormal[i];
2194  }
2195  }
2196 }
2197 
2198 
2201 //Foam::label Foam::refinementSurfaces::findHighestIntersection
2202 //(
2203 // const point& start,
2204 // const point& end,
2205 // const label currentLevel, // current cell refinement level
2206 //
2207 // pointIndexHit& maxHit
2208 //) const
2209 //{
2210 // // surface with highest maxlevel
2211 // label maxSurface = -1;
2212 // // maxLevel of maxSurface
2213 // label maxLevel = currentLevel;
2214 //
2215 // forAll(*this, surfI)
2216 // {
2217 // pointIndexHit hit = operator[](surfI).findLineAny(start, end);
2218 //
2219 // if (hit.hit())
2220 // {
2221 // const triSurface& s = operator[](surfI);
2222 //
2223 // label region = globalRegion(surfI, s[hit.index()].region());
2224 //
2225 // if (maxLevel_[region] > maxLevel)
2226 // {
2227 // maxSurface = surfI;
2228 // maxLevel = maxLevel_[region];
2229 // maxHit = hit;
2230 // }
2231 // }
2232 // }
2233 //
2234 // if (maxSurface == -1)
2235 // {
2236 // // maxLevel unchanged. No interesting surface hit.
2237 // maxHit.setMiss();
2238 // }
2239 //
2240 // return maxSurface;
2241 //}
2242 
2243 
2245 (
2246  const labelList& testSurfaces,
2247  const pointField& pt,
2248  labelList& insideSurfaces
2249 ) const
2250 {
2251  insideSurfaces.setSize(pt.size());
2252  insideSurfaces = -1;
2253 
2254  forAll(testSurfaces, i)
2255  {
2256  label surfI = testSurfaces[i];
2257 
2258  const searchableSurface& surface = allGeometry_[surfaces_[surfI]];
2259 
2260  const surfaceZonesInfo::areaSelectionAlgo selectionMethod =
2261  surfZones_[surfI].zoneInside();
2262 
2263  if
2264  (
2265  selectionMethod != surfaceZonesInfo::INSIDE
2266  && selectionMethod != surfaceZonesInfo::OUTSIDE
2267  )
2268  {
2270  << "Trying to use surface "
2271  << surface.name()
2272  << " which has non-geometric inside selection method "
2273  << surfaceZonesInfo::areaSelectionAlgoNames[selectionMethod]
2274  << exit(FatalError);
2275  }
2276 
2277  if (surface.hasVolumeType())
2278  {
2279  List<volumeType> volType;
2280  surface.getVolumeType(pt, volType);
2281 
2282  forAll(volType, pointI)
2283  {
2284  if (insideSurfaces[pointI] == -1)
2285  {
2286  if
2287  (
2288  (
2289  volType[pointI] == volumeType::INSIDE
2290  && selectionMethod == surfaceZonesInfo::INSIDE
2291  )
2292  || (
2293  volType[pointI] == volumeType::OUTSIDE
2294  && selectionMethod == surfaceZonesInfo::OUTSIDE
2295  )
2296  )
2297  {
2298  insideSurfaces[pointI] = surfI;
2299  }
2300  }
2301  }
2302  }
2303  }
2305 
2306 
2308 (
2309  const labelList& surfacesToTest,
2310  const labelListList& regions,
2311 
2312  const pointField& samples,
2313  const scalarField& nearestDistSqr,
2314 
2315  labelList& hitSurface,
2316  List<pointIndexHit>& hitInfo
2317 ) const
2318 {
2319  labelList geometries(labelUIndList(surfaces_, surfacesToTest));
2320 
2321  // Do the tests. Note that findNearest returns index in geometries.
2323  (
2324  allGeometry_,
2325  geometries,
2326  regions,
2327  samples,
2328  nearestDistSqr,
2329  hitSurface,
2330  hitInfo
2331  );
2332 
2333  // Rework the hitSurface to be surface (i.e. index into surfaces_)
2334  forAll(hitSurface, pointI)
2335  {
2336  if (hitSurface[pointI] != -1)
2337  {
2338  hitSurface[pointI] = surfacesToTest[hitSurface[pointI]];
2339  }
2340  }
2342 
2343 
2345 (
2346  const labelList& surfacesToTest,
2347  const labelListList& regions,
2348 
2349  const pointField& samples,
2350  const scalarField& nearestDistSqr,
2351 
2352  labelList& hitSurface,
2353  List<pointIndexHit>& hitInfo,
2354  labelList& hitRegion,
2355  vectorField& hitNormal
2356 ) const
2357 {
2358  labelList geometries(labelUIndList(surfaces_, surfacesToTest));
2359 
2360  // Do the tests. Note that findNearest returns index in geometries.
2362  (
2363  allGeometry_,
2364  geometries,
2365  regions,
2366  samples,
2367  nearestDistSqr,
2368  hitSurface,
2369  hitInfo
2370  );
2371 
2372  // Rework the hitSurface to be surface (i.e. index into surfaces_)
2373  forAll(hitSurface, pointI)
2374  {
2375  if (hitSurface[pointI] != -1)
2376  {
2377  hitSurface[pointI] = surfacesToTest[hitSurface[pointI]];
2378  }
2379  }
2380 
2381  // Collect the region
2382  hitRegion.setSize(hitSurface.size());
2383  hitRegion = -1;
2384  hitNormal.setSize(hitSurface.size());
2385  hitNormal = Zero;
2386 
2387  forAll(surfacesToTest, i)
2388  {
2389  label surfI = surfacesToTest[i];
2390 
2391  // Collect hits for surfI
2392  const labelList localIndices(findIndices(hitSurface, surfI));
2393 
2394  List<pointIndexHit> localHits
2395  (
2396  UIndirectList<pointIndexHit>
2397  (
2398  hitInfo,
2399  localIndices
2400  )
2401  );
2402 
2403  // Region
2404  labelList localRegion;
2405  allGeometry_[surfaces_[surfI]].getRegion(localHits, localRegion);
2406 
2407  forAll(localIndices, i)
2408  {
2409  hitRegion[localIndices[i]] = localRegion[i];
2410  }
2411 
2412  // Normal
2413  vectorField localNormal;
2414  allGeometry_[surfaces_[surfI]].getNormal(localHits, localNormal);
2415 
2416  forAll(localIndices, i)
2417  {
2418  hitNormal[localIndices[i]] = localNormal[i];
2419  }
2420  }
2421 }
2422 
2423 
2424 // ************************************************************************* //
static const Enum< areaSelectionAlgo > areaSelectionAlgoNames
dictionary dict
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:118
labelList maxCurvatureLevel() const
Per surface the maximum curvatureLevel over all its regions.
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.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
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:120
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:578
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.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
scalarField samples(nIntervals, Zero)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:487
PointIndexHit< point > pointIndexHit
A PointIndexHit with a 3D point.
Definition: pointIndexHit.H:58
void findAnyIntersection(const pointField &start, const pointField &end, labelList &surfaces, List< pointIndexHit > &) const
Used for debugging only: find intersection of edge.
labelList findIndices(const ListType &input, typename ListType::const_reference val, label start=0)
Linear search to find all occurrences of given element.
Base class of (analytical or triangulated) surface. Encapsulates all the search routines. WIP.
wordList regionNames
virtual void findLineAny(const pointField &start, const pointField &end, List< pointIndexHit > &) const =0
Return any intersection on segment from start to end.
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
void findNearest(const labelList &surfacesToTest, const pointField &samples, const scalarField &nearestDistSqr, labelList &surfaces, List< pointIndexHit > &) const
Find nearest point on surfaces.
wordList toc() const
Return the table of contents.
Definition: dictionary.C:599
Unknown state.
Definition: volumeType.H:64
bool found(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry (const access) with the given keyword.
Definition: dictionaryI.H:100
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:413
void findHigherIntersection(const shellSurfaces &shells, const pointField &start, const pointField &end, const labelList &currentLevel, labelList &surfaces, labelList &surfaceLevel) const
Find intersection of edge. Return -1 or first surface.
bool returnReduceAnd(const bool value, const label comm=UPstream::worldComm)
Perform logical (and) MPI Allreduce on a copy. Uses UPstream::reduceAnd.
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
void setSize(const label n)
Alias for resize()
Definition: List.H:289
const pointField & points
surfacesMesh setField(triSurfaceToAgglom)
void findNearestRegion(const labelList &surfacesToTest, const pointField &samples, const scalarField &nearestDistSqr, labelList &hitSurface, labelList &hitRegion) const
Find nearest point on surfaces. Return surface and region on.
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i)
Definition: labelList.C:31
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:109
A class for handling words, derived from Foam::string.
Definition: word.H:63
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
const List< wordList > & regionNames() const
Region names per surface.
label size() const noexcept
The number of elements in the list.
Definition: UPtrListI.H:99
labelPair whichSurface(const label globalRegionI) const
From global region to surface + region.
void findAllIntersections(const pointField &start, const pointField &end, const labelList &currentLevel, const labelList &globalMinLevel, const labelList &globalMaxLevel, List< vectorList > &surfaceNormal, labelListList &surfaceLevel) const
Find all intersections of edge with any surface with applicable.
Container for searchableSurfaces. The collection is specified as a dictionary. For example...
Encapsulates queries for volume refinement (&#39;refine all cells within shell&#39;).
Definition: shellSurfaces.H:53
Vector< scalar > vector
Definition: vector.H:57
HashSet< word, Hash< word > > wordHashSet
A HashSet of words, uses string hasher.
Definition: HashSet.H:73
A location inside the volume.
Definition: volumeType.H:65
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.
A location outside the volume.
Definition: volumeType.H:66
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:26
const wordList surface
Standard surface field types (scalar, vector, tensor, etc)
A location that is partly inside and outside.
Definition: volumeType.H:67
Pair< label > labelPair
A pair of labels.
Definition: Pair.H:50
constexpr auto end(C &c) -> decltype(c.end())
Return iterator to the end of the container c.
Definition: stdFoam.H:193
labelList f(nPoints)
void setCurvatureMinLevelFields(const scalar cosAngle, const scalar level0EdgeLength)
Update minLevelFields according to (triSurface-only) curvature.
List< word > wordList
A List of words.
Definition: fileName.H:58
UIndirectList< label > labelUIndList
UIndirectList of labels.
Definition: IndirectList.H:65
static tmp< scalarField > curvatures(const triSurface &surf, const vectorField &pointNormals, const triadField &pointTriads)
Surface curvatures at the vertex points.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:607
const wordList & names() const
Surface names, not region names.
labelList maxGapLevel() const
Per surface the maximum extendedGapLevel over all its regions.
const entry * findEntry(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry (const access) with the given keyword.
Definition: dictionaryI.H:80
virtual void getRegion(const List< pointIndexHit > &, labelList &region) const =0
From a set of points and indices get the region.
messageStream Info
Information stream (stdout output on master, null elsewhere)
constexpr label labelMax
Definition: label.H:55
const PtrList< dictionary > & patchInfo() const
From global region number to patch type.
label n
Field< vector > vectorField
Specialisation of Field<T> for vector.
#define IOWarningInFunction(ios)
Report an IO warning using Foam::Warning.
Contains information about location on a triSurface.
List< label > labelList
A List of labels.
Definition: List.H:62
void findNearestIntersection(const labelList &surfacesToTest, const pointField &start, const pointField &end, labelList &surface1, List< pointIndexHit > &hit1, labelList &region1, labelList &surface2, List< pointIndexHit > &hit2, labelList &region2) const
Find intersection nearest to the endpoints. surface1,2 are.
void setMinLevelFields(const shellSurfaces &shells)
Calculate minLevelFields according to both surface- and.
bool returnReduceOr(const bool value, const label comm=UPstream::worldComm)
Perform logical (or) MPI Allreduce on a copy. Uses UPstream::reduceOr.
List< bool > boolList
A List of bools.
Definition: List.H:60
virtual void getNormal(const List< pointIndexHit > &, vectorField &normal) const =0
From a set of points and indices get the normal.
areaSelectionAlgo
Types of selection of area.
Regular expression.
Definition: keyType.H:83
virtual void findLine(const pointField &start, const pointField &end, List< pointIndexHit > &) const =0
Find first intersection on segment from start to end.
const volScalarField & p0
Definition: EEqn.H:36
const dimensionedScalar mp
Proton mass.
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
void findInside(const labelList &surfacesToTest, const pointField &pt, labelList &insideSurfaces) const
Detect if a point is &#39;inside&#39; (closed) surfaces.
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:157