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