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<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<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  vector n1 = f1.unitNormal(points);
1030 
1031  const auto dir0 = f0.edgeDirection(meshE);
1032  const auto dir1 = f1.edgeDirection(meshE);
1033 
1034  if (dir0 && ((dir0 > 0) == (dir1 > 0)))
1035  {
1036  // Flip since use edge in same direction
1037  // (should not be the case for 'proper'
1038  // surfaces)
1039  n1 = -n1;
1040  }
1041 
1042  if ((n0&n1) < cosAngle)
1043  {
1044  isOnSharpEdge.set(meshE[0]);
1045  isOnSharpEdge.set(meshE[1]);
1046  }
1047  }
1048  }
1049 
1050  // Extend by one layer
1051  {
1052  bitSet oldOnSharpEdge(isOnSharpEdge);
1053  isOnSharpEdge = false;
1054  for (const auto& f : ts)
1055  {
1056  for (const label pointi : f)
1057  {
1058  if (oldOnSharpEdge[pointi])
1059  {
1060  // Mark all points on triangle
1061  isOnSharpEdge.set(f);
1062  break;
1063  }
1064  }
1065  }
1066  }
1067 
1068 
1069  // Unmark curvature
1070  autoPtr<OBJstream> str;
1071  //if (debug)
1072  //{
1073  // str.reset
1074  // (
1075  // new OBJstream
1076  // (
1077  // "sharpEdgePoints_"
1078  // + geom.name()
1079  // + ".obj"
1080  // )
1081  // );
1082  // Info<< "Writing sharp edge points to "
1083  // << str().name() << endl;
1084  //}
1085 
1086  for (const label pointi : isOnSharpEdge)
1087  {
1088  // Reset measured point-based curvature
1089  curv[pointi] = 0.0;
1090  if (str)
1091  {
1092  str().write(points[pointi]);
1093  }
1094  }
1095  }
1096 
1097  // Reset curvature on -almost- sharp edges.
1098  // This resets the point-based curvature if the edge
1099  // is considered to be a sharp edge based on its actual
1100  // curvature. This is only used if the 'ignore' level is
1101  // given.
1102  {
1103  // Pass 1: accumulate constraints on the points - get
1104  // the minimum of curvature constraints on the
1105  // connected triangles. Looks at user-specified
1106  // min curvature - does not use actual measured
1107  // curvature
1108  scalarField pointMinCurv(ts.nPoints(), VGREAT);
1109 
1110  forAll(ts, i)
1111  {
1112  // Is ignore level given for surface
1113  const label level = curvIgnore[i];
1114  if (level >= 0)
1115  {
1116  // Convert to (inv) size
1117  const scalar length = level0EdgeLength/(2<<level);
1118  const scalar invLength = 1.0/length;
1119  for (const label pointi : ts[i])
1120  {
1121  if
1122  (
1123  invLength < pointMinCurv[pointi]
1124  && curv[pointi] > SMALL
1125  )
1126  {
1127  //Pout<< "** at location:"
1128  // << ts.points()[pointi]
1129  // << " measured curv:" << curv[pointi]
1130  // << " radius:" << 1.0/curv[pointi]
1131  // << " ignore level:" << level
1132  // << " ignore radius:" << length
1133  // << " resetting minCurv to "
1134  // << invLength
1135  // << endl;
1136  }
1137 
1138  pointMinCurv[pointi] =
1139  min(pointMinCurv[pointi], invLength);
1140  }
1141  }
1142  }
1143 
1144  // Clip curvature (should do nothing for most points unless
1145  // ignore-level is triggered)
1146  forAll(pointMinCurv, pointi)
1147  {
1148  if (pointMinCurv[pointi] < curv[pointi])
1149  {
1150  //Pout<< "** at location:" << ts.points()[pointi]
1151  // << " measured curv:" << curv[pointi]
1152  // << " radius:" << 1.0/curv[pointi]
1153  // << " cellLimit:" << pointMinCurv[pointi]
1154  // << endl;
1155 
1156  // Set up to ignore point
1157  //curv[pointi] = pointMinCurv[pointi];
1158  curv[pointi] = 0.0;
1159  }
1160  }
1161  }
1162 
1163 
1164  forAll(ts, i)
1165  {
1166  const auto& f = ts[i];
1167  // Take max curvature (= min radius of curvature)
1168  cellCurv[i] = max(curv[f[0]], max(curv[f[1]], curv[f[2]]));
1169  }
1170  }
1171 
1172 
1173  //if(debug)
1174  //{
1175  // const scalar maxCurv = gMax(cellCurv);
1176  // if (maxCurv > SMALL)
1177  // {
1178  // const scalar r = scalar(1.0)/maxCurv;
1179  //
1180  // Pout<< "For geometry " << geom.name()
1181  // << " have curvature max " << maxCurv
1182  // << " which equates to radius:" << r
1183  // << " which equates to refinement level "
1184  // << log2(level0EdgeLength/r)
1185  // << endl;
1186  // }
1187  //}
1188 
1189  forAll(cellCurv, i)
1190  {
1191  if (cellCurv[i] > SMALL && nCurvCells[i] > 0)
1192  {
1193  //- ?If locally have a cached field override the
1194  // surface-based level ignore any curvature?
1195  //if (minLevelField[i] > surfMin[i])
1196  //{
1197  // // Ignore curvature
1198  //}
1199  //else
1200  //if (surfMin[i] == surfMax[i])
1201  //{
1202  // // Ignore curvature. Bypass calculation below.
1203  //}
1204  //else
1205  {
1206  // Re-work the curvature into a radius and into a
1207  // number of cells
1208  const scalar r = scalar(1.0)/cellCurv[i];
1209  const scalar level =
1210  log2(nCurvCells[i]*level0EdgeLength/r);
1211  const label l = round(level);
1212 
1213  if (l > minLevelField[i] && l <= surfMax[i])
1214  {
1215  minLevelField[i] = l;
1216  }
1217  }
1218  }
1219  }
1220 
1221 
1222  // Store minLevelField on surface
1223  const_cast<searchableSurface&>(geom).setField(minLevelField);
1224  }
1225  }
1226 }
1227 
1229 // Find intersections of edge. Return -1 or first surface with higher minLevel
1230 // number.
1232 (
1233  const shellSurfaces& shells,
1234 
1235  const pointField& start,
1236  const pointField& end,
1237  const labelList& currentLevel, // current cell refinement level
1238 
1239  labelList& surfaces,
1240  labelList& surfaceLevel
1241 ) const
1242 {
1243  surfaces.setSize(start.size());
1244  surfaces = -1;
1245  surfaceLevel.setSize(start.size());
1246  surfaceLevel = -1;
1247 
1248  if (surfaces_.empty())
1249  {
1250  return;
1251  }
1252 
1253  if (surfaces_.size() == 1)
1254  {
1255  // Optimisation: single segmented surface. No need to duplicate
1256  // point storage.
1257 
1258  label surfI = 0;
1259 
1260  const searchableSurface& geom = allGeometry_[surfaces_[surfI]];
1261 
1262  // Do intersection test
1263  List<pointIndexHit> intersectionInfo(start.size());
1264  geom.findLineAny(start, end, intersectionInfo);
1265 
1266 
1267  // Surface-based refinement level
1268  labelList surfaceOnlyLevel(start.size(), -1);
1269  {
1270  // Get per intersection the region
1271  labelList region;
1272  geom.getRegion(intersectionInfo, region);
1273 
1274  forAll(intersectionInfo, i)
1275  {
1276  if (intersectionInfo[i].hit())
1277  {
1278  surfaceOnlyLevel[i] = minLevel(surfI, region[i]);
1279  }
1280  }
1281  }
1282 
1283 
1284  // Get shell refinement level if higher
1285  const labelList localLevel
1286  (
1287  findHigherLevel
1288  (
1289  geom,
1290  shells,
1291  intersectionInfo,
1292  surfaceOnlyLevel // starting level
1293  )
1294  );
1295 
1296 
1297  // Combine localLevel with current level
1298  forAll(localLevel, i)
1299  {
1300  if (localLevel[i] > currentLevel[i])
1301  {
1302  surfaces[i] = surfI; // index of surface
1303  surfaceLevel[i] = localLevel[i];
1304  }
1305  }
1306 
1307  return;
1308  }
1309 
1310 
1311 
1312  // Work arrays
1313  pointField p0(start);
1314  pointField p1(end);
1315  labelList intersectionToPoint(identity(start.size()));
1316  List<pointIndexHit> intersectionInfo(start.size());
1317 
1318  forAll(surfaces_, surfI)
1319  {
1320  const searchableSurface& geom = allGeometry_[surfaces_[surfI]];
1321 
1322  // Do intersection test
1323  geom.findLineAny(p0, p1, intersectionInfo);
1324 
1325 
1326  // Surface-based refinement level
1327  labelList surfaceOnlyLevel(intersectionInfo.size(), -1);
1328  {
1329  // Get per intersection the region
1330  labelList region;
1331  geom.getRegion(intersectionInfo, region);
1332 
1333  forAll(intersectionInfo, i)
1334  {
1335  if (intersectionInfo[i].hit())
1336  {
1337  surfaceOnlyLevel[i] = minLevel(surfI, region[i]);
1338  }
1339  }
1340  }
1341 
1342 
1343  // Get shell refinement level if higher
1344  const labelList localLevel
1345  (
1346  findHigherLevel
1347  (
1348  geom,
1349  shells,
1350  intersectionInfo,
1351  surfaceOnlyLevel
1352  )
1353  );
1354 
1355 
1356  // Combine localLevel with current level
1357  label missI = 0;
1358  forAll(localLevel, i)
1359  {
1360  label pointI = intersectionToPoint[i];
1361 
1362  if (localLevel[i] > currentLevel[pointI])
1363  {
1364  // Mark point for refinement
1365  surfaces[pointI] = surfI;
1366  surfaceLevel[pointI] = localLevel[i];
1367  }
1368  else
1369  {
1370  p0[missI] = start[pointI];
1371  p1[missI] = end[pointI];
1372  intersectionToPoint[missI] = pointI;
1373  missI++;
1374  }
1375  }
1376 
1377 
1378  // All done? Note that this decision should be synchronised
1379  if (returnReduceAnd(missI == 0))
1380  {
1381  break;
1382  }
1383 
1384  // Trim misses
1385  p0.setSize(missI);
1386  p1.setSize(missI);
1387  intersectionToPoint.setSize(missI);
1388  intersectionInfo.setSize(missI);
1389  }
1391 
1392 
1394 (
1395  const pointField& start,
1396  const pointField& end,
1397  const labelList& currentLevel, // current cell refinement level
1398 
1399  const labelList& globalMinLevel,
1400  const labelList& globalMaxLevel,
1401 
1402  List<vectorList>& surfaceNormal,
1403  labelListList& surfaceLevel
1404 ) const
1405 {
1406  surfaceLevel.setSize(start.size());
1407  surfaceNormal.setSize(start.size());
1408 
1409  if (surfaces_.empty())
1410  {
1411  return;
1412  }
1413 
1414  // Work arrays
1415  List<List<pointIndexHit>> hitInfo;
1416 
1417  forAll(surfaces_, surfI)
1418  {
1419  const searchableSurface& surface = allGeometry_[surfaces_[surfI]];
1420 
1421  surface.findLineAll(start, end, hitInfo);
1422 
1423  // Repack hits for surface into flat list
1424  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1425  // To avoid overhead of calling getRegion for every point
1426 
1427  label n = 0;
1428  forAll(hitInfo, pointI)
1429  {
1430  n += hitInfo[pointI].size();
1431  }
1432 
1433  List<pointIndexHit> surfInfo(n);
1434  labelList pointMap(n);
1435  n = 0;
1436 
1437  forAll(hitInfo, pointI)
1438  {
1439  const List<pointIndexHit>& pHits = hitInfo[pointI];
1440 
1441  forAll(pHits, i)
1442  {
1443  surfInfo[n] = pHits[i];
1444  pointMap[n] = pointI;
1445  n++;
1446  }
1447  }
1448 
1449  labelList surfRegion(n);
1450  vectorField surfNormal(n);
1451  surface.getRegion(surfInfo, surfRegion);
1452  surface.getNormal(surfInfo, surfNormal);
1453 
1454  surfInfo.clear();
1455 
1456 
1457  // Extract back into pointwise
1458  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
1459 
1460  forAll(surfRegion, i)
1461  {
1462  label region = globalRegion(surfI, surfRegion[i]);
1463  label pointI = pointMap[i];
1464 
1465  if
1466  (
1467  currentLevel[pointI] >= globalMinLevel[region]
1468  && currentLevel[pointI] < globalMaxLevel[region]
1469  )
1470  {
1471  // Append to pointI info
1472  label sz = surfaceNormal[pointI].size();
1473  surfaceNormal[pointI].setSize(sz+1);
1474  surfaceNormal[pointI][sz] = surfNormal[i];
1475 
1476  surfaceLevel[pointI].setSize(sz+1);
1477  surfaceLevel[pointI][sz] = globalMaxLevel[region];
1478  }
1479  }
1480  }
1482 
1483 
1485 (
1486  const pointField& start,
1487  const pointField& end,
1488  const labelList& currentLevel, // current cell refinement level
1489 
1490  const labelList& globalMinLevel,
1491  const labelList& globalMaxLevel,
1492 
1494  List<vectorList>& surfaceNormal,
1495  labelListList& surfaceLevel
1496 ) const
1497 {
1498  surfaceLevel.setSize(start.size());
1499  surfaceNormal.setSize(start.size());
1500  surfaceLocation.setSize(start.size());
1501 
1502  if (surfaces_.empty())
1503  {
1504  return;
1505  }
1506 
1507  // Work arrays
1508  List<List<pointIndexHit>> hitInfo;
1509 
1510  forAll(surfaces_, surfI)
1511  {
1512  const searchableSurface& surface = allGeometry_[surfaces_[surfI]];
1513 
1514  surface.findLineAll(start, end, hitInfo);
1515 
1516  // Repack hits for surface into flat list
1517  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1518  // To avoid overhead of calling getRegion for every point
1519 
1520  label n = 0;
1521  forAll(hitInfo, pointI)
1522  {
1523  n += hitInfo[pointI].size();
1524  }
1525 
1526  List<pointIndexHit> surfInfo(n);
1527  labelList pointMap(n);
1528  n = 0;
1529 
1530  forAll(hitInfo, pointI)
1531  {
1532  const List<pointIndexHit>& pHits = hitInfo[pointI];
1533 
1534  forAll(pHits, i)
1535  {
1536  surfInfo[n] = pHits[i];
1537  pointMap[n] = pointI;
1538  n++;
1539  }
1540  }
1541 
1542  labelList surfRegion(n);
1543  vectorField surfNormal(n);
1544  surface.getRegion(surfInfo, surfRegion);
1545  surface.getNormal(surfInfo, surfNormal);
1546 
1547  // Extract back into pointwise
1548  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
1549 
1550  forAll(surfRegion, i)
1551  {
1552  label region = globalRegion(surfI, surfRegion[i]);
1553  label pointI = pointMap[i];
1554 
1555  if
1556  (
1557  currentLevel[pointI] >= globalMinLevel[region]
1558  && currentLevel[pointI] < globalMaxLevel[region]
1559  )
1560  {
1561  // Append to pointI info
1562  label sz = surfaceNormal[pointI].size();
1563  surfaceLocation[pointI].setSize(sz+1);
1564  surfaceLocation[pointI][sz] = surfInfo[i].hitPoint();
1565 
1566  surfaceNormal[pointI].setSize(sz+1);
1567  surfaceNormal[pointI][sz] = surfNormal[i];
1568 
1569  surfaceLevel[pointI].setSize(sz+1);
1570  // Level should just be higher than provided point level.
1571  // Actual value is not important.
1572  surfaceLevel[pointI][sz] = globalMaxLevel[region];
1573  }
1574  }
1575  }
1576 }
1577 
1578 
1579 //void Foam::refinementSurfaces::findAllIntersections
1580 //(
1581 // const labelList& surfacesToTest,
1582 // const pointField& start,
1583 // const pointField& end,
1584 //
1585 // List<labelList>& hitSurface, // surface index
1586 // List<pointList>& hitLocation, // surface location
1587 // List<labelList>& hitRegion,
1588 // List<vectorField>& hitNormal
1589 //) const
1590 //{
1591 // hitSurface.setSize(start.size());
1592 // hitLocation.setSize(start.size());
1593 // hitRegion.setSize(start.size());
1594 // hitNormal.setSize(start.size());
1595 //
1596 // if (surfaces_.empty())
1597 // {
1598 // return;
1599 // }
1600 //
1601 // // Work arrays
1602 // List<List<pointIndexHit>> hitInfo;
1603 //
1604 // for (const label surfI : surfacesToTest)
1605 // {
1606 // const searchableSurface& surface = allGeometry_[surfaces_[surfI]];
1607 //
1608 // surface.findLineAll(start, end, hitInfo);
1609 //
1610 // // Repack hits for surface into flat list
1611 // // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1612 // // To avoid overhead of calling getRegion for every point
1613 //
1614 // label n = 0;
1615 // forAll(hitInfo, pointI)
1616 // {
1617 // n += hitInfo[pointI].size();
1618 // }
1619 //
1620 // List<pointIndexHit> surfInfo(n);
1621 // labelList pointMap(n);
1622 // n = 0;
1623 //
1624 // forAll(hitInfo, pointI)
1625 // {
1626 // const List<pointIndexHit>& pHits = hitInfo[pointI];
1627 //
1628 // forAll(pHits, i)
1629 // {
1630 // surfInfo[n] = pHits[i];
1631 // pointMap[n] = pointI;
1632 // n++;
1633 // }
1634 // }
1635 //
1636 // labelList surfRegion(n);
1637 // vectorField surfNormal(n);
1638 // surface.getRegion(surfInfo, surfRegion);
1639 // surface.getNormal(surfInfo, surfNormal);
1640 //
1641 // surfInfo.clear();
1642 //
1643 //
1644 // // Extract back into pointwise
1645 // // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
1646 //
1647 // forAll(surfRegion, i)
1648 // {
1649 // const label pointI = pointMap[i];
1650 //
1651 // // Append to pointI info
1652 // hitSurface[pointI].append(surfI);
1653 // hitRegion[pointI].append(globalRegion(surfI, surfRegion[i]));
1654 // hitLocation[pointI].append(surfInfo[i].hitPoint());
1655 // hitNormal[pointI].append(surfNormal[i]);
1656 // }
1657 // }
1658 //}
1659 
1660 
1662 (
1663  const labelList& surfacesToTest,
1664  const pointField& start,
1665  const pointField& end,
1666 
1667  labelList& surface1,
1668  List<pointIndexHit>& hit1,
1669  labelList& region1,
1670  labelList& surface2,
1671  List<pointIndexHit>& hit2,
1672  labelList& region2
1673 ) const
1674 {
1675  // 1. intersection from start to end
1676  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1677 
1678  // Initialize arguments
1679  surface1.setSize(start.size());
1680  surface1 = -1;
1681  hit1.setSize(start.size());
1682  region1.setSize(start.size());
1683 
1684  // Current end of segment to test.
1685  pointField nearest(end);
1686  // Work array
1687  List<pointIndexHit> nearestInfo(start.size());
1688  labelList region;
1689 
1690  forAll(surfacesToTest, testI)
1691  {
1692  label surfI = surfacesToTest[testI];
1693 
1694  const searchableSurface& surface = allGeometry_[surfaces_[surfI]];
1695 
1696  // See if any intersection between start and current nearest
1697  surface.findLine
1698  (
1699  start,
1700  nearest,
1701  nearestInfo
1702  );
1703  surface.getRegion
1704  (
1705  nearestInfo,
1706  region
1707  );
1708 
1709  forAll(nearestInfo, pointI)
1710  {
1711  if (nearestInfo[pointI].hit())
1712  {
1713  hit1[pointI] = nearestInfo[pointI];
1714  surface1[pointI] = surfI;
1715  region1[pointI] = region[pointI];
1716  nearest[pointI] = hit1[pointI].hitPoint();
1717  }
1718  }
1719  }
1720 
1721 
1722  // 2. intersection from end to last intersection
1723  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1724 
1725  // Find the nearest intersection from end to start. Note that we initialize
1726  // to the first intersection (if any).
1727  surface2 = surface1;
1728  hit2 = hit1;
1729  region2 = region1;
1730 
1731  // Set current end of segment to test.
1732  forAll(nearest, pointI)
1733  {
1734  if (hit1[pointI].hit())
1735  {
1736  nearest[pointI] = hit1[pointI].point();
1737  }
1738  else
1739  {
1740  // Disable testing by setting to end.
1741  nearest[pointI] = end[pointI];
1742  }
1743  }
1744 
1745  forAll(surfacesToTest, testI)
1746  {
1747  label surfI = surfacesToTest[testI];
1748 
1749  const searchableSurface& surface = allGeometry_[surfaces_[surfI]];
1750 
1751  // See if any intersection between end and current nearest
1752  surface.findLine
1753  (
1754  end,
1755  nearest,
1756  nearestInfo
1757  );
1758  surface.getRegion
1759  (
1760  nearestInfo,
1761  region
1762  );
1763 
1764  forAll(nearestInfo, pointI)
1765  {
1766  if (nearestInfo[pointI].hit())
1767  {
1768  hit2[pointI] = nearestInfo[pointI];
1769  surface2[pointI] = surfI;
1770  region2[pointI] = region[pointI];
1771  nearest[pointI] = hit2[pointI].hitPoint();
1772  }
1773  }
1774  }
1775 
1776 
1777  // Make sure that if hit1 has hit something, hit2 will have at least the
1778  // same point (due to tolerances it might miss its end point)
1779  forAll(hit1, pointI)
1780  {
1781  if (hit1[pointI].hit() && !hit2[pointI].hit())
1782  {
1783  hit2[pointI] = hit1[pointI];
1784  surface2[pointI] = surface1[pointI];
1785  region2[pointI] = region1[pointI];
1786  }
1787  }
1789 
1790 
1792 (
1793  const labelList& surfacesToTest,
1794  const pointField& start,
1795  const pointField& end,
1796 
1797  labelList& surface1,
1798  List<pointIndexHit>& hit1,
1799  labelList& region1,
1800  vectorField& normal1,
1801 
1802  labelList& surface2,
1803  List<pointIndexHit>& hit2,
1804  labelList& region2,
1805  vectorField& normal2
1806 ) const
1807 {
1808  // 1. intersection from start to end
1809  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1810 
1811  // Initialize arguments
1812  surface1.setSize(start.size());
1813  surface1 = -1;
1814  hit1.setSize(start.size());
1815  region1.setSize(start.size());
1816  region1 = -1;
1817  normal1.setSize(start.size());
1818  normal1 = Zero;
1819 
1820  // Current end of segment to test.
1821  pointField nearest(end);
1822  // Work array
1823  List<pointIndexHit> nearestInfo(start.size());
1824  labelList region;
1825  vectorField normal;
1826 
1827  forAll(surfacesToTest, testI)
1828  {
1829  label surfI = surfacesToTest[testI];
1830  const searchableSurface& geom = allGeometry_[surfaces_[surfI]];
1831 
1832  // See if any intersection between start and current nearest
1833  geom.findLine(start, nearest, nearestInfo);
1834  geom.getRegion(nearestInfo, region);
1835  geom.getNormal(nearestInfo, normal);
1836 
1837  forAll(nearestInfo, pointI)
1838  {
1839  if (nearestInfo[pointI].hit())
1840  {
1841  hit1[pointI] = nearestInfo[pointI];
1842  surface1[pointI] = surfI;
1843  region1[pointI] = region[pointI];
1844  normal1[pointI] = normal[pointI];
1845  nearest[pointI] = hit1[pointI].hitPoint();
1846  }
1847  }
1848  }
1849 
1850 
1851  // 2. intersection from end to last intersection
1852  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1853 
1854  // Find the nearest intersection from end to start. Note that we initialize
1855  // to the first intersection (if any).
1856  surface2 = surface1;
1857  hit2 = hit1;
1858  region2 = region1;
1859  normal2 = normal1;
1860 
1861  // Set current end of segment to test.
1862  forAll(nearest, pointI)
1863  {
1864  if (hit1[pointI].hit())
1865  {
1866  nearest[pointI] = hit1[pointI].point();
1867  }
1868  else
1869  {
1870  // Disable testing by setting to end.
1871  nearest[pointI] = end[pointI];
1872  }
1873  }
1874 
1875  forAll(surfacesToTest, testI)
1876  {
1877  label surfI = surfacesToTest[testI];
1878  const searchableSurface& geom = allGeometry_[surfaces_[surfI]];
1879 
1880  // See if any intersection between end and current nearest
1881  geom.findLine(end, nearest, nearestInfo);
1882  geom.getRegion(nearestInfo, region);
1883  geom.getNormal(nearestInfo, normal);
1884 
1885  forAll(nearestInfo, pointI)
1886  {
1887  if (nearestInfo[pointI].hit())
1888  {
1889  hit2[pointI] = nearestInfo[pointI];
1890  surface2[pointI] = surfI;
1891  region2[pointI] = region[pointI];
1892  normal2[pointI] = normal[pointI];
1893  nearest[pointI] = hit2[pointI].hitPoint();
1894  }
1895  }
1896  }
1897 
1898 
1899  // Make sure that if hit1 has hit something, hit2 will have at least the
1900  // same point (due to tolerances it might miss its end point)
1901  forAll(hit1, pointI)
1902  {
1903  if (hit1[pointI].hit() && !hit2[pointI].hit())
1904  {
1905  hit2[pointI] = hit1[pointI];
1906  surface2[pointI] = surface1[pointI];
1907  region2[pointI] = region1[pointI];
1908  normal2[pointI] = normal1[pointI];
1909  }
1910  }
1912 
1913 
1915 (
1916  const pointField& start,
1917  const pointField& end,
1918 
1919  labelList& surface1,
1920  vectorField& normal1
1921 ) const
1922 {
1923  // Initialize arguments
1924  surface1.setSize(start.size());
1925  surface1 = -1;
1926  normal1.setSize(start.size());
1927  normal1 = Zero;
1928 
1929  // Current end of segment to test.
1930  pointField nearest(end);
1931  // Work array
1932  List<pointIndexHit> nearestInfo(start.size());
1933  labelList region;
1934  vectorField normal;
1935 
1936  forAll(surfaces_, surfI)
1937  {
1938  const searchableSurface& geom = allGeometry_[surfaces_[surfI]];
1939 
1940  // See if any intersection between start and current nearest
1941  geom.findLine(start, nearest, nearestInfo);
1942  geom.getNormal(nearestInfo, normal);
1943 
1944  forAll(nearestInfo, pointI)
1945  {
1946  if (nearestInfo[pointI].hit())
1947  {
1948  surface1[pointI] = surfI;
1949  normal1[pointI] = normal[pointI];
1950  nearest[pointI] = nearestInfo[pointI].point();
1951  }
1952  }
1953  }
1955 
1956 
1958 (
1959  const pointField& start,
1960  const pointField& end,
1961 
1962  labelList& surface1,
1963  List<pointIndexHit>& hitInfo1,
1964  vectorField& normal1
1965 ) const
1966 {
1967  // 1. intersection from start to end
1968  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1969 
1970  // Initialize arguments
1971  surface1.setSize(start.size());
1972  surface1 = -1;
1973  hitInfo1.setSize(start.size());
1974  hitInfo1 = pointIndexHit();
1975  normal1.setSize(start.size());
1976  normal1 = Zero;
1977 
1978  // Current end of segment to test.
1979  pointField nearest(end);
1980  // Work array
1981  List<pointIndexHit> nearestInfo(start.size());
1982  labelList region;
1983  vectorField normal;
1984 
1985  forAll(surfaces_, surfI)
1986  {
1987  const searchableSurface& geom = allGeometry_[surfaces_[surfI]];
1988 
1989  // See if any intersection between start and current nearest
1990  geom.findLine(start, nearest, nearestInfo);
1991  geom.getNormal(nearestInfo, normal);
1992 
1993  forAll(nearestInfo, pointI)
1994  {
1995  if (nearestInfo[pointI].hit())
1996  {
1997  surface1[pointI] = surfI;
1998  hitInfo1[pointI] = nearestInfo[pointI];
1999  normal1[pointI] = normal[pointI];
2000  nearest[pointI] = nearestInfo[pointI].point();
2001  }
2002  }
2003  }
2005 
2006 
2008 (
2009  const pointField& start,
2010  const pointField& end,
2011 
2012  labelList& hitSurface,
2013  List<pointIndexHit>& hitInfo
2014 ) const
2015 {
2017  (
2018  allGeometry_,
2019  surfaces_,
2020  start,
2021  end,
2022  hitSurface,
2023  hitInfo
2024  );
2026 
2027 
2029 (
2030  const labelList& surfacesToTest,
2031  const pointField& samples,
2032  const scalarField& nearestDistSqr,
2033  labelList& hitSurface,
2034  List<pointIndexHit>& hitInfo
2035 ) const
2036 {
2037  labelList geometries(labelUIndList(surfaces_, surfacesToTest));
2038 
2039  // Do the tests. Note that findNearest returns index in geometries.
2041  (
2042  allGeometry_,
2043  geometries,
2044  samples,
2045  nearestDistSqr,
2046  hitSurface,
2047  hitInfo
2048  );
2049 
2050  // Rework the hitSurface to be surface (i.e. index into surfaces_)
2051  forAll(hitSurface, pointI)
2052  {
2053  if (hitSurface[pointI] != -1)
2054  {
2055  hitSurface[pointI] = surfacesToTest[hitSurface[pointI]];
2056  }
2057  }
2059 
2060 
2062 (
2063  const labelList& surfacesToTest,
2064  const pointField& samples,
2065  const scalarField& nearestDistSqr,
2066  labelList& hitSurface,
2067  labelList& hitRegion
2068 ) const
2069 {
2070  labelList geometries(labelUIndList(surfaces_, surfacesToTest));
2071 
2072  // Do the tests. Note that findNearest returns index in geometries.
2073  List<pointIndexHit> hitInfo;
2075  (
2076  allGeometry_,
2077  geometries,
2078  samples,
2079  nearestDistSqr,
2080  hitSurface,
2081  hitInfo
2082  );
2083 
2084  // Rework the hitSurface to be surface (i.e. index into surfaces_)
2085  forAll(hitSurface, pointI)
2086  {
2087  if (hitSurface[pointI] != -1)
2088  {
2089  hitSurface[pointI] = surfacesToTest[hitSurface[pointI]];
2090  }
2091  }
2092 
2093  // Collect the region
2094  hitRegion.setSize(hitSurface.size());
2095  hitRegion = -1;
2096 
2097  forAll(surfacesToTest, i)
2098  {
2099  label surfI = surfacesToTest[i];
2100 
2101  // Collect hits for surfI
2102  const labelList localIndices(findIndices(hitSurface, surfI));
2103 
2104  List<pointIndexHit> localHits
2105  (
2106  UIndirectList<pointIndexHit>
2107  (
2108  hitInfo,
2109  localIndices
2110  )
2111  );
2112 
2113  labelList localRegion;
2114  allGeometry_[surfaces_[surfI]].getRegion(localHits, localRegion);
2115 
2116  forAll(localIndices, i)
2117  {
2118  hitRegion[localIndices[i]] = localRegion[i];
2119  }
2120  }
2122 
2123 
2125 (
2126  const labelList& surfacesToTest,
2127  const pointField& samples,
2128  const scalarField& nearestDistSqr,
2129  labelList& hitSurface,
2130  List<pointIndexHit>& hitInfo,
2131  labelList& hitRegion,
2132  vectorField& hitNormal
2133 ) const
2134 {
2135  labelList geometries(labelUIndList(surfaces_, surfacesToTest));
2136 
2137  // Do the tests. Note that findNearest returns index in geometries.
2139  (
2140  allGeometry_,
2141  geometries,
2142  samples,
2143  nearestDistSqr,
2144  hitSurface,
2145  hitInfo
2146  );
2147 
2148  // Rework the hitSurface to be surface (i.e. index into surfaces_)
2149  forAll(hitSurface, pointI)
2150  {
2151  if (hitSurface[pointI] != -1)
2152  {
2153  hitSurface[pointI] = surfacesToTest[hitSurface[pointI]];
2154  }
2155  }
2156 
2157  // Collect the region
2158  hitRegion.setSize(hitSurface.size());
2159  hitRegion = -1;
2160  hitNormal.setSize(hitSurface.size());
2161  hitNormal = Zero;
2162 
2163  forAll(surfacesToTest, i)
2164  {
2165  label surfI = surfacesToTest[i];
2166 
2167  // Collect hits for surfI
2168  const labelList localIndices(findIndices(hitSurface, surfI));
2169 
2170  List<pointIndexHit> localHits
2171  (
2172  UIndirectList<pointIndexHit>
2173  (
2174  hitInfo,
2175  localIndices
2176  )
2177  );
2178 
2179  // Region
2180  labelList localRegion;
2181  allGeometry_[surfaces_[surfI]].getRegion(localHits, localRegion);
2182 
2183  forAll(localIndices, i)
2184  {
2185  hitRegion[localIndices[i]] = localRegion[i];
2186  }
2187 
2188  // Normal
2189  vectorField localNormal;
2190  allGeometry_[surfaces_[surfI]].getNormal(localHits, localNormal);
2191 
2192  forAll(localIndices, i)
2193  {
2194  hitNormal[localIndices[i]] = localNormal[i];
2195  }
2196  }
2197 }
2198 
2199 
2202 //Foam::label Foam::refinementSurfaces::findHighestIntersection
2203 //(
2204 // const point& start,
2205 // const point& end,
2206 // const label currentLevel, // current cell refinement level
2207 //
2208 // pointIndexHit& maxHit
2209 //) const
2210 //{
2211 // // surface with highest maxlevel
2212 // label maxSurface = -1;
2213 // // maxLevel of maxSurface
2214 // label maxLevel = currentLevel;
2215 //
2216 // forAll(*this, surfI)
2217 // {
2218 // pointIndexHit hit = operator[](surfI).findLineAny(start, end);
2219 //
2220 // if (hit.hit())
2221 // {
2222 // const triSurface& s = operator[](surfI);
2223 //
2224 // label region = globalRegion(surfI, s[hit.index()].region());
2225 //
2226 // if (maxLevel_[region] > maxLevel)
2227 // {
2228 // maxSurface = surfI;
2229 // maxLevel = maxLevel_[region];
2230 // maxHit = hit;
2231 // }
2232 // }
2233 // }
2234 //
2235 // if (maxSurface == -1)
2236 // {
2237 // // maxLevel unchanged. No interesting surface hit.
2238 // maxHit.setMiss();
2239 // }
2240 //
2241 // return maxSurface;
2242 //}
2243 
2244 
2246 (
2247  const labelList& testSurfaces,
2248  const pointField& pt,
2249  labelList& insideSurfaces
2250 ) const
2251 {
2252  insideSurfaces.setSize(pt.size());
2253  insideSurfaces = -1;
2254 
2255  forAll(testSurfaces, i)
2256  {
2257  label surfI = testSurfaces[i];
2258 
2259  const searchableSurface& surface = allGeometry_[surfaces_[surfI]];
2260 
2261  const surfaceZonesInfo::areaSelectionAlgo selectionMethod =
2262  surfZones_[surfI].zoneInside();
2263 
2264  if
2265  (
2266  selectionMethod != surfaceZonesInfo::INSIDE
2267  && selectionMethod != surfaceZonesInfo::OUTSIDE
2268  )
2269  {
2271  << "Trying to use surface "
2272  << surface.name()
2273  << " which has non-geometric inside selection method "
2274  << surfaceZonesInfo::areaSelectionAlgoNames[selectionMethod]
2275  << exit(FatalError);
2276  }
2277 
2278  if (surface.hasVolumeType())
2279  {
2280  List<volumeType> volType;
2281  surface.getVolumeType(pt, volType);
2282 
2283  forAll(volType, pointI)
2284  {
2285  if (insideSurfaces[pointI] == -1)
2286  {
2287  if
2288  (
2289  (
2290  volType[pointI] == volumeType::INSIDE
2291  && selectionMethod == surfaceZonesInfo::INSIDE
2292  )
2293  || (
2294  volType[pointI] == volumeType::OUTSIDE
2295  && selectionMethod == surfaceZonesInfo::OUTSIDE
2296  )
2297  )
2298  {
2299  insideSurfaces[pointI] = surfI;
2300  }
2301  }
2302  }
2303  }
2304  }
2306 
2307 
2309 (
2310  const labelList& surfacesToTest,
2311  const labelListList& regions,
2312 
2313  const pointField& samples,
2314  const scalarField& nearestDistSqr,
2315 
2316  labelList& hitSurface,
2317  List<pointIndexHit>& hitInfo
2318 ) const
2319 {
2320  labelList geometries(labelUIndList(surfaces_, surfacesToTest));
2321 
2322  // Do the tests. Note that findNearest returns index in geometries.
2324  (
2325  allGeometry_,
2326  geometries,
2327  regions,
2328  samples,
2329  nearestDistSqr,
2330  hitSurface,
2331  hitInfo
2332  );
2333 
2334  // Rework the hitSurface to be surface (i.e. index into surfaces_)
2335  forAll(hitSurface, pointI)
2336  {
2337  if (hitSurface[pointI] != -1)
2338  {
2339  hitSurface[pointI] = surfacesToTest[hitSurface[pointI]];
2340  }
2341  }
2343 
2344 
2346 (
2347  const labelList& surfacesToTest,
2348  const labelListList& regions,
2349 
2350  const pointField& samples,
2351  const scalarField& nearestDistSqr,
2352 
2353  labelList& hitSurface,
2354  List<pointIndexHit>& hitInfo,
2355  labelList& hitRegion,
2356  vectorField& hitNormal
2357 ) const
2358 {
2359  labelList geometries(labelUIndList(surfaces_, surfacesToTest));
2360 
2361  // Do the tests. Note that findNearest returns index in geometries.
2363  (
2364  allGeometry_,
2365  geometries,
2366  regions,
2367  samples,
2368  nearestDistSqr,
2369  hitSurface,
2370  hitInfo
2371  );
2372 
2373  // Rework the hitSurface to be surface (i.e. index into surfaces_)
2374  forAll(hitSurface, pointI)
2375  {
2376  if (hitSurface[pointI] != -1)
2377  {
2378  hitSurface[pointI] = surfacesToTest[hitSurface[pointI]];
2379  }
2380  }
2381 
2382  // Collect the region
2383  hitRegion.setSize(hitSurface.size());
2384  hitRegion = -1;
2385  hitNormal.setSize(hitSurface.size());
2386  hitNormal = Zero;
2387 
2388  forAll(surfacesToTest, i)
2389  {
2390  label surfI = surfacesToTest[i];
2391 
2392  // Collect hits for surfI
2393  const labelList localIndices(findIndices(hitSurface, surfI));
2394 
2395  List<pointIndexHit> localHits
2396  (
2397  UIndirectList<pointIndexHit>
2398  (
2399  hitInfo,
2400  localIndices
2401  )
2402  );
2403 
2404  // Region
2405  labelList localRegion;
2406  allGeometry_[surfaces_[surfI]].getRegion(localHits, localRegion);
2407 
2408  forAll(localIndices, i)
2409  {
2410  hitRegion[localIndices[i]] = localRegion[i];
2411  }
2412 
2413  // Normal
2414  vectorField localNormal;
2415  allGeometry_[surfaces_[surfI]].getNormal(localHits, localNormal);
2416 
2417  forAll(localIndices, i)
2418  {
2419  hitNormal[localIndices[i]] = localNormal[i];
2420  }
2421  }
2422 }
2423 
2424 
2425 // ************************************************************************* //
static const Enum< areaSelectionAlgo > areaSelectionAlgoNames
dictionary dict
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
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:129
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
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
UIndirectList< label > labelUIndList
UIndirectList of labels.
Definition: IndirectList.H:65
scalarField samples(nIntervals, Zero)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
PointIndexHit< point > pointIndexHit
A PointIndexHit with a 3D point.
Definition: pointIndexHit.H:58
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:587
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:104
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
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:316
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), works like std::iota() but returning a...
Definition: labelLists.C:44
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:137
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 entries in the list.
Definition: UPtrListI.H:106
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:51
constexpr auto end(C &c) -> decltype(c.end())
Return iterator to the end of the container c.
Definition: stdFoam.H:201
labelList f(nPoints)
void setCurvatureMinLevelFields(const scalar cosAngle, const scalar level0EdgeLength)
Update minLevelFields according to (triSurface-only) curvature.
List< word > wordList
List of word.
Definition: fileName.H:59
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:627
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:84
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:127