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