refinementSurfaces.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "refinementSurfaces.H"
27 #include "Time.H"
28 #include "searchableSurfaces.H"
29 #include "shellSurfaces.H"
30 #include "triSurfaceMesh.H"
31 #include "labelPair.H"
33 #include "UPtrList.H"
34 #include "volumeType.H"
35 
36 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
37 
38 Foam::refinementSurfaces::refinementSurfaces
39 (
40  const searchableSurfaces& allGeometry,
41  const dictionary& surfacesDict,
42  const label gapLevelIncrement
43 )
44 :
45  allGeometry_(allGeometry),
46  surfaces_(surfacesDict.size()),
47  names_(surfacesDict.size()),
48  surfZones_(surfacesDict.size()),
49  regionOffset_(surfacesDict.size())
50 {
51  // Wildcard specification : loop over all surface, all regions
52  // and try to find a match.
53 
54  // Count number of surfaces.
55  label surfI = 0;
56  forAll(allGeometry_.names(), geomI)
57  {
58  const word& geomName = allGeometry_.names()[geomI];
59 
60  if (surfacesDict.found(geomName))
61  {
62  surfI++;
63  }
64  }
65 
66  // Size lists
67  surfaces_.setSize(surfI);
68  names_.setSize(surfI);
69  surfZones_.setSize(surfI);
70  regionOffset_.setSize(surfI);
71 
72  labelList globalMinLevel(surfI, 0);
73  labelList globalMaxLevel(surfI, 0);
74  labelList globalLevelIncr(surfI, 0);
75  scalarField globalAngle(surfI, -great);
76  PtrList<dictionary> globalPatchInfo(surfI);
77  List<Map<label>> regionMinLevel(surfI);
78  List<Map<label>> regionMaxLevel(surfI);
79  List<Map<label>> regionLevelIncr(surfI);
80  List<Map<scalar>> regionAngle(surfI);
81  List<Map<autoPtr<dictionary>>> regionPatchInfo(surfI);
82 
83 
84  HashSet<word> unmatchedKeys(surfacesDict.toc());
85 
86  surfI = 0;
87  forAll(allGeometry_.names(), geomI)
88  {
89  const word& geomName = allGeometry_.names()[geomI];
90 
91  const entry* ePtr = surfacesDict.lookupEntryPtr(geomName, false, true);
92 
93  if (ePtr)
94  {
95  const dictionary& dict = ePtr->dict();
96  unmatchedKeys.erase(ePtr->keyword());
97 
98  names_[surfI] = geomName;
99  surfaces_[surfI] = geomI;
100 
101  const labelPair refLevel(dict.lookup("level"));
102  globalMinLevel[surfI] = refLevel[0];
103  globalMaxLevel[surfI] = refLevel[1];
104  globalLevelIncr[surfI] = dict.lookupOrDefault
105  (
106  "gapLevelIncrement",
107  gapLevelIncrement
108  );
109 
110  if
111  (
112  globalMinLevel[surfI] < 0
113  || globalMaxLevel[surfI] < globalMinLevel[surfI]
114  || globalLevelIncr[surfI] < 0
115  )
116  {
118  (
119  dict
120  ) << "Illegal level specification for surface "
121  << names_[surfI]
122  << " : minLevel:" << globalMinLevel[surfI]
123  << " maxLevel:" << globalMaxLevel[surfI]
124  << " levelIncrement:" << globalLevelIncr[surfI]
125  << exit(FatalIOError);
126  }
127 
128  const searchableSurface& surface = allGeometry_[surfaces_[surfI]];
129 
130  // Surface zones
131  surfZones_.set(surfI, new surfaceZonesInfo(surface, dict));
132 
133  // Global perpendicular angle
134  if (dict.found("patchInfo"))
135  {
136  globalPatchInfo.set
137  (
138  surfI,
139  dict.subDict("patchInfo").clone()
140  );
141  }
142  dict.readIfPresent("perpendicularAngle", globalAngle[surfI]);
143 
144  if (dict.found("regions"))
145  {
146  const dictionary& regionsDict = dict.subDict("regions");
147  const wordList& regionNames = surface.regions();
148 
149  forAll(regionNames, regionI)
150  {
151  if (regionsDict.found(regionNames[regionI]))
152  {
153  // Get the dictionary for region
154  const dictionary& regionDict = regionsDict.subDict
155  (
156  regionNames[regionI]
157  );
158 
159  const labelPair refLevel(regionDict.lookup("level"));
160 
161  regionMinLevel[surfI].insert(regionI, refLevel[0]);
162  regionMaxLevel[surfI].insert(regionI, refLevel[1]);
163  label levelIncr = regionDict.lookupOrDefault
164  (
165  "gapLevelIncrement",
166  gapLevelIncrement
167  );
168  regionLevelIncr[surfI].insert(regionI, levelIncr);
169 
170  if
171  (
172  refLevel[0] < 0
173  || refLevel[1] < refLevel[0]
174  || levelIncr < 0
175  )
176  {
178  (
179  dict
180  ) << "Illegal level specification for surface "
181  << names_[surfI] << " region "
182  << regionNames[regionI]
183  << " : minLevel:" << refLevel[0]
184  << " maxLevel:" << refLevel[1]
185  << " levelIncrement:" << levelIncr
186  << exit(FatalIOError);
187  }
188 
189  if (regionDict.found("perpendicularAngle"))
190  {
191  regionAngle[surfI].insert
192  (
193  regionI,
194  readScalar
195  (
196  regionDict.lookup("perpendicularAngle")
197  )
198  );
199  }
200 
201  if (regionDict.found("patchInfo"))
202  {
203  regionPatchInfo[surfI].insert
204  (
205  regionI,
206  regionDict.subDict("patchInfo").clone()
207  );
208  }
209  }
210  }
211  }
212  surfI++;
213  }
214  }
215 
216  if (unmatchedKeys.size() > 0)
217  {
219  (
220  surfacesDict
221  ) << "Not all entries in refinementSurfaces dictionary were used."
222  << " The following entries were not used : "
223  << unmatchedKeys.sortedToc()
224  << endl;
225  }
226 
227 
228  // Calculate local to global region offset
229  label nRegions = 0;
230 
231  forAll(surfaces_, surfI)
232  {
233  regionOffset_[surfI] = nRegions;
234  nRegions += allGeometry_[surfaces_[surfI]].regions().size();
235  }
236 
237  // Rework surface specific information into information per global region
238  minLevel_.setSize(nRegions);
239  minLevel_ = 0;
240  maxLevel_.setSize(nRegions);
241  maxLevel_ = 0;
242  gapLevel_.setSize(nRegions);
243  gapLevel_ = -1;
244  perpendicularAngle_.setSize(nRegions);
245  perpendicularAngle_ = -great;
246  patchInfo_.setSize(nRegions);
247 
248 
249  forAll(globalMinLevel, surfI)
250  {
251  label nRegions = allGeometry_[surfaces_[surfI]].regions().size();
252 
253  // Initialise to global (i.e. per surface)
254  for (label i = 0; i < nRegions; i++)
255  {
256  label globalRegionI = regionOffset_[surfI] + i;
257  minLevel_[globalRegionI] = globalMinLevel[surfI];
258  maxLevel_[globalRegionI] = globalMaxLevel[surfI];
259  gapLevel_[globalRegionI] =
260  maxLevel_[globalRegionI]
261  + globalLevelIncr[surfI];
262 
263  perpendicularAngle_[globalRegionI] = globalAngle[surfI];
264  if (globalPatchInfo.set(surfI))
265  {
266  patchInfo_.set
267  (
268  globalRegionI,
269  globalPatchInfo[surfI].clone()
270  );
271  }
272  }
273 
274  // Overwrite with region specific information
275  forAllConstIter(Map<label>, regionMinLevel[surfI], iter)
276  {
277  label globalRegionI = regionOffset_[surfI] + iter.key();
278 
279  minLevel_[globalRegionI] = iter();
280  maxLevel_[globalRegionI] = regionMaxLevel[surfI][iter.key()];
281  gapLevel_[globalRegionI] =
282  maxLevel_[globalRegionI]
283  + regionLevelIncr[surfI][iter.key()];
284  }
285  forAllConstIter(Map<scalar>, regionAngle[surfI], iter)
286  {
287  label globalRegionI = regionOffset_[surfI] + iter.key();
288 
289  perpendicularAngle_[globalRegionI] = regionAngle[surfI][iter.key()];
290  }
291 
292  const Map<autoPtr<dictionary>>& localInfo = regionPatchInfo[surfI];
293  forAllConstIter(Map<autoPtr<dictionary>>, localInfo, iter)
294  {
295  label globalRegionI = regionOffset_[surfI] + iter.key();
296 
297  patchInfo_.set(globalRegionI, iter()().clone());
298  }
299  }
300 }
301 
302 
303 Foam::refinementSurfaces::refinementSurfaces
304 (
305  const searchableSurfaces& allGeometry,
306  const labelList& surfaces,
307  const wordList& names,
308  const PtrList<surfaceZonesInfo>& surfZones,
309  const labelList& regionOffset,
310  const labelList& minLevel,
311  const labelList& maxLevel,
312  const labelList& gapLevel,
313  const scalarField& perpendicularAngle,
314  PtrList<dictionary>& patchInfo
315 )
316 :
317  allGeometry_(allGeometry),
318  surfaces_(surfaces),
319  names_(names),
320  surfZones_(surfZones),
321  regionOffset_(regionOffset),
322  minLevel_(minLevel),
323  maxLevel_(maxLevel),
324  gapLevel_(gapLevel),
325  perpendicularAngle_(perpendicularAngle),
326  patchInfo_(patchInfo.size())
327 {
328  forAll(patchInfo_, pI)
329  {
330  if (patchInfo.set(pI))
331  {
332  patchInfo_.set(pI, patchInfo.set(pI, nullptr));
333  }
334  }
335 }
336 
337 
338 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
339 
340 // // Count number of triangles per surface region
341 // Foam::labelList Foam::refinementSurfaces::countRegions(const triSurface& s)
342 // {
343 // const geometricSurfacePatchList& regions = s.patches();
344 //
345 // labelList nTris(regions.size(), 0);
346 //
347 // forAll(s, triI)
348 // {
349 // nTris[s[triI].region()]++;
350 // }
351 // return nTris;
352 // }
353 
354 
355 // // Pre-calculate the refinement level for every element
356 // void Foam::refinementSurfaces::wantedRefinementLevel
357 // (
358 // const shellSurfaces& shells,
359 // const label surfI,
360 // const List<pointIndexHit>& info, // Indices
361 // const pointField& ctrs, // Representative coordinate
362 // labelList& minLevelField
363 // ) const
364 // {
365 // const searchableSurface& geom = allGeometry_[surfaces_[surfI]];
366 //
367 // // Get per element the region
368 // labelList region;
369 // geom.getRegion(info, region);
370 //
371 // // Initialise fields to region wise minLevel
372 // minLevelField.setSize(ctrs.size());
373 // minLevelField = -1;
374 //
375 // forAll(minLevelField, i)
376 // {
377 // if (info[i].hit())
378 // {
379 // minLevelField[i] = minLevel(surfI, region[i]);
380 // }
381 // }
382 //
383 // // Find out if triangle inside shell with higher level
384 // // What level does shell want to refine fc to?
385 // labelList shellLevel;
386 // shells.findHigherLevel(ctrs, minLevelField, shellLevel);
387 //
388 // forAll(minLevelField, i)
389 // {
390 // minLevelField[i] = max(minLevelField[i], shellLevel[i]);
391 // }
392 // }
393 
394 
395 // Precalculate the refinement level for every element of the searchable
396 // surface.
398 (
399  const shellSurfaces& shells
400 )
401 {
402  forAll(surfaces_, surfI)
403  {
404  const searchableSurface& geom = allGeometry_[surfaces_[surfI]];
405 
406  // Precalculation only makes sense if there are different regions
407  // (so different refinement levels possible) and there are some
408  // elements. Possibly should have 'enough' elements to have fine
409  // enough resolution but for now just make sure we don't catch e.g.
410  // searchableBox (size=6)
411  if (geom.regions().size() > 1 && geom.globalSize() > 10)
412  {
413  // Representative local coordinates and bounding sphere
414  pointField ctrs;
415  scalarField radiusSqr;
416  geom.boundingSpheres(ctrs, radiusSqr);
417 
418  labelList minLevelField(ctrs.size(), -1);
419  {
420  // Get the element index in a roundabout way. Problem is e.g.
421  // distributed surface where local indices differ from global
422  // ones (needed for getRegion call)
423  List<pointIndexHit> info;
424  geom.findNearest(ctrs, radiusSqr, info);
425 
426  // Get per element the region
427  labelList region;
428  geom.getRegion(info, region);
429 
430  // From the region get the surface-wise refinement level
431  forAll(minLevelField, i)
432  {
433  if (info[i].hit()) // Note: should not be necessary
434  {
435  minLevelField[i] = minLevel(surfI, region[i]);
436  }
437  }
438  }
439 
440  // Find out if triangle inside shell with higher level
441  // What level does shell want to refine fc to?
442  labelList shellLevel;
443  shells.findHigherLevel(ctrs, minLevelField, shellLevel);
444 
445  forAll(minLevelField, i)
446  {
447  minLevelField[i] = max(minLevelField[i], shellLevel[i]);
448  }
449 
450  // Store minLevelField on surface
451  const_cast<searchableSurface&>(geom).setField(minLevelField);
452  }
453  }
454 }
455 
456 
457 // Find intersections of edge. Return -1 or first surface with higher minLevel
458 // number.
460 (
461  const pointField& start,
462  const pointField& end,
463  const labelList& currentLevel, // current cell refinement level
464 
465  labelList& surfaces,
466  labelList& surfaceLevel
467 ) const
468 {
469  surfaces.setSize(start.size());
470  surfaces = -1;
471  surfaceLevel.setSize(start.size());
472  surfaceLevel = -1;
473 
474  if (surfaces_.empty())
475  {
476  return;
477  }
478 
479  if (surfaces_.size() == 1)
480  {
481  // Optimisation: single segmented surface. No need to duplicate
482  // point storage.
483 
484  label surfI = 0;
485 
486  const searchableSurface& geom = allGeometry_[surfaces_[surfI]];
487 
488  // Do intersection test
489  List<pointIndexHit> intersectionInfo(start.size());
490  geom.findLineAny(start, end, intersectionInfo);
491 
492  // See if a cached level field available
493  labelList minLevelField;
494  geom.getField(intersectionInfo, minLevelField);
495  bool haveLevelField =
496  (
497  returnReduce(minLevelField.size(), sumOp<label>())
498  > 0
499  );
500 
501  if (!haveLevelField && geom.regions().size() == 1)
502  {
503  minLevelField = labelList
504  (
505  intersectionInfo.size(),
506  minLevel(surfI, 0)
507  );
508  haveLevelField = true;
509  }
510 
511  if (haveLevelField)
512  {
513  forAll(intersectionInfo, i)
514  {
515  if
516  (
517  intersectionInfo[i].hit()
518  && minLevelField[i] > currentLevel[i]
519  )
520  {
521  surfaces[i] = surfI; // index of surface
522  surfaceLevel[i] = minLevelField[i];
523  }
524  }
525  return;
526  }
527  }
528 
529 
530 
531  // Work arrays
532  pointField p0(start);
533  pointField p1(end);
534  labelList intersectionToPoint(identity(start.size()));
535  List<pointIndexHit> intersectionInfo(start.size());
536 
537  forAll(surfaces_, surfI)
538  {
539  const searchableSurface& geom = allGeometry_[surfaces_[surfI]];
540 
541  // Do intersection test
542  geom.findLineAny(p0, p1, intersectionInfo);
543 
544  // See if a cached level field available
545  labelList minLevelField;
546  geom.getField(intersectionInfo, minLevelField);
547 
548  // Copy all hits into arguments, In-place compact misses.
549  label missI = 0;
550  forAll(intersectionInfo, i)
551  {
552  // Get the minLevel for the point
553  label minLocalLevel = -1;
554 
555  if (intersectionInfo[i].hit())
556  {
557  // Check if minLevelField for this surface.
558  if (minLevelField.size())
559  {
560  minLocalLevel = minLevelField[i];
561  }
562  else
563  {
564  // Use the min level for the surface instead. Assume
565  // single region 0.
566  minLocalLevel = minLevel(surfI, 0);
567  }
568  }
569 
570 
571  label pointi = intersectionToPoint[i];
572 
573  if (minLocalLevel > currentLevel[pointi])
574  {
575  // Mark point for refinement
576  surfaces[pointi] = surfI;
577  surfaceLevel[pointi] = minLocalLevel;
578  }
579  else
580  {
581  p0[missI] = start[pointi];
582  p1[missI] = end[pointi];
583  intersectionToPoint[missI] = pointi;
584  missI++;
585  }
586  }
587 
588  // All done? Note that this decision should be synchronised
589  if (returnReduce(missI, sumOp<label>()) == 0)
590  {
591  break;
592  }
593 
594  // Trim misses
595  p0.setSize(missI);
596  p1.setSize(missI);
597  intersectionToPoint.setSize(missI);
598  intersectionInfo.setSize(missI);
599  }
600 }
601 
602 
604 (
605  const pointField& start,
606  const pointField& end,
607  const labelList& currentLevel, // current cell refinement level
608 
609  const labelList& globalRegionLevel,
610 
611  List<vectorList>& surfaceNormal,
612  labelListList& surfaceLevel
613 ) const
614 {
615  surfaceLevel.setSize(start.size());
616  surfaceNormal.setSize(start.size());
617 
618  if (surfaces_.empty())
619  {
620  return;
621  }
622 
623  // Work arrays
624  List<List<pointIndexHit>> hitInfo;
625  labelList pRegions;
626  vectorField pNormals;
627 
628  forAll(surfaces_, surfI)
629  {
630  const searchableSurface& surface = allGeometry_[surfaces_[surfI]];
631 
632  surface.findLineAll(start, end, hitInfo);
633 
634  // Repack hits for surface into flat list
635  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
636  // To avoid overhead of calling getRegion for every point
637 
638  label n = 0;
639  forAll(hitInfo, pointi)
640  {
641  n += hitInfo[pointi].size();
642  }
643 
644  List<pointIndexHit> surfInfo(n);
645  labelList pointMap(n);
646  n = 0;
647 
648  forAll(hitInfo, pointi)
649  {
650  const List<pointIndexHit>& pHits = hitInfo[pointi];
651 
652  forAll(pHits, i)
653  {
654  surfInfo[n] = pHits[i];
655  pointMap[n] = pointi;
656  n++;
657  }
658  }
659 
660  labelList surfRegion(n);
661  vectorField surfNormal(n);
662  surface.getRegion(surfInfo, surfRegion);
663  surface.getNormal(surfInfo, surfNormal);
664 
665  surfInfo.clear();
666 
667 
668  // Extract back into pointwise
669  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
670 
671  forAll(surfRegion, i)
672  {
673  label region = globalRegion(surfI, surfRegion[i]);
674  label pointi = pointMap[i];
675 
676  if (globalRegionLevel[region] > currentLevel[pointi])
677  {
678  // Append to pointi info
679  label sz = surfaceNormal[pointi].size();
680  surfaceNormal[pointi].setSize(sz+1);
681  surfaceNormal[pointi][sz] = surfNormal[i];
682 
683  surfaceLevel[pointi].setSize(sz+1);
684  surfaceLevel[pointi][sz] = globalRegionLevel[region];
685  }
686  }
687  }
688 }
689 
690 
692 (
693  const pointField& start,
694  const pointField& end,
695  const labelList& currentLevel, // current cell refinement level
696 
697  const labelList& globalRegionLevel,
698 
699  List<pointList>& surfaceLocation,
700  List<vectorList>& surfaceNormal,
701  labelListList& surfaceLevel
702 ) const
703 {
704  surfaceLevel.setSize(start.size());
705  surfaceNormal.setSize(start.size());
706  surfaceLocation.setSize(start.size());
707 
708  if (surfaces_.empty())
709  {
710  return;
711  }
712 
713  // Work arrays
714  List<List<pointIndexHit>> hitInfo;
715  labelList pRegions;
716  vectorField pNormals;
717 
718  forAll(surfaces_, surfI)
719  {
720  const searchableSurface& surface = allGeometry_[surfaces_[surfI]];
721 
722  surface.findLineAll(start, end, hitInfo);
723 
724  // Repack hits for surface into flat list
725  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
726  // To avoid overhead of calling getRegion for every point
727 
728  label n = 0;
729  forAll(hitInfo, pointi)
730  {
731  n += hitInfo[pointi].size();
732  }
733 
734  List<pointIndexHit> surfInfo(n);
735  labelList pointMap(n);
736  n = 0;
737 
738  forAll(hitInfo, pointi)
739  {
740  const List<pointIndexHit>& pHits = hitInfo[pointi];
741 
742  forAll(pHits, i)
743  {
744  surfInfo[n] = pHits[i];
745  pointMap[n] = pointi;
746  n++;
747  }
748  }
749 
750  labelList surfRegion(n);
751  vectorField surfNormal(n);
752  surface.getRegion(surfInfo, surfRegion);
753  surface.getNormal(surfInfo, surfNormal);
754 
755  // Extract back into pointwise
756  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
757 
758  forAll(surfRegion, i)
759  {
760  label region = globalRegion(surfI, surfRegion[i]);
761  label pointi = pointMap[i];
762 
763  if (globalRegionLevel[region] > currentLevel[pointi])
764  {
765  // Append to pointi info
766  label sz = surfaceNormal[pointi].size();
767  surfaceLocation[pointi].setSize(sz+1);
768  surfaceLocation[pointi][sz] = surfInfo[i].hitPoint();
769 
770  surfaceNormal[pointi].setSize(sz+1);
771  surfaceNormal[pointi][sz] = surfNormal[i];
772 
773  surfaceLevel[pointi].setSize(sz+1);
774  surfaceLevel[pointi][sz] = globalRegionLevel[region];
775  }
776  }
777  }
778 }
779 
780 
782 (
783  const labelList& surfacesToTest,
784  const pointField& start,
785  const pointField& end,
786 
787  labelList& surface1,
788  List<pointIndexHit>& hit1,
789  labelList& region1,
790  labelList& surface2,
791  List<pointIndexHit>& hit2,
792  labelList& region2
793 ) const
794 {
795  // 1. intersection from start to end
796  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
797 
798  // Initialize arguments
799  surface1.setSize(start.size());
800  surface1 = -1;
801  hit1.setSize(start.size());
802  region1.setSize(start.size());
803 
804  // Current end of segment to test.
805  pointField nearest(end);
806  // Work array
807  List<pointIndexHit> nearestInfo(start.size());
808  labelList region;
809 
810  forAll(surfacesToTest, testI)
811  {
812  label surfI = surfacesToTest[testI];
813 
814  const searchableSurface& surface = allGeometry_[surfaces_[surfI]];
815 
816  // See if any intersection between start and current nearest
817  surface.findLine
818  (
819  start,
820  nearest,
821  nearestInfo
822  );
823  surface.getRegion
824  (
825  nearestInfo,
826  region
827  );
828 
829  forAll(nearestInfo, pointi)
830  {
831  if (nearestInfo[pointi].hit())
832  {
833  hit1[pointi] = nearestInfo[pointi];
834  surface1[pointi] = surfI;
835  region1[pointi] = region[pointi];
836  nearest[pointi] = hit1[pointi].hitPoint();
837  }
838  }
839  }
840 
841 
842  // 2. intersection from end to last intersection
843  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
844 
845  // Find the nearest intersection from end to start. Note that we initialize
846  // to the first intersection (if any).
847  surface2 = surface1;
848  hit2 = hit1;
849  region2 = region1;
850 
851  // Set current end of segment to test.
852  forAll(nearest, pointi)
853  {
854  if (hit1[pointi].hit())
855  {
856  nearest[pointi] = hit1[pointi].hitPoint();
857  }
858  else
859  {
860  // Disable testing by setting to end.
861  nearest[pointi] = end[pointi];
862  }
863  }
864 
865  forAll(surfacesToTest, testI)
866  {
867  label surfI = surfacesToTest[testI];
868 
869  const searchableSurface& surface = allGeometry_[surfaces_[surfI]];
870 
871  // See if any intersection between end and current nearest
872  surface.findLine
873  (
874  end,
875  nearest,
876  nearestInfo
877  );
878  surface.getRegion
879  (
880  nearestInfo,
881  region
882  );
883 
884  forAll(nearestInfo, pointi)
885  {
886  if (nearestInfo[pointi].hit())
887  {
888  hit2[pointi] = nearestInfo[pointi];
889  surface2[pointi] = surfI;
890  region2[pointi] = region[pointi];
891  nearest[pointi] = hit2[pointi].hitPoint();
892  }
893  }
894  }
895 
896 
897  // Make sure that if hit1 has hit something, hit2 will have at least the
898  // same point (due to tolerances it might miss its end point)
899  forAll(hit1, pointi)
900  {
901  if (hit1[pointi].hit() && !hit2[pointi].hit())
902  {
903  hit2[pointi] = hit1[pointi];
904  surface2[pointi] = surface1[pointi];
905  region2[pointi] = region1[pointi];
906  }
907  }
908 }
909 
910 
912 (
913  const labelList& surfacesToTest,
914  const pointField& start,
915  const pointField& end,
916 
917  labelList& surface1,
918  List<pointIndexHit>& hit1,
919  labelList& region1,
920  vectorField& normal1,
921 
922  labelList& surface2,
923  List<pointIndexHit>& hit2,
924  labelList& region2,
925  vectorField& normal2
926 ) const
927 {
928  // 1. intersection from start to end
929  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
930 
931  // Initialize arguments
932  surface1.setSize(start.size());
933  surface1 = -1;
934  hit1.setSize(start.size());
935  region1.setSize(start.size());
936  region1 = -1;
937  normal1.setSize(start.size());
938  normal1 = Zero;
939 
940  // Current end of segment to test.
941  pointField nearest(end);
942  // Work array
943  List<pointIndexHit> nearestInfo(start.size());
944  labelList region;
945  vectorField normal;
946 
947  forAll(surfacesToTest, testI)
948  {
949  label surfI = surfacesToTest[testI];
950  const searchableSurface& geom = allGeometry_[surfaces_[surfI]];
951 
952  // See if any intersection between start and current nearest
953  geom.findLine(start, nearest, nearestInfo);
954  geom.getRegion(nearestInfo, region);
955  geom.getNormal(nearestInfo, normal);
956 
957  forAll(nearestInfo, pointi)
958  {
959  if (nearestInfo[pointi].hit())
960  {
961  hit1[pointi] = nearestInfo[pointi];
962  surface1[pointi] = surfI;
963  region1[pointi] = region[pointi];
964  normal1[pointi] = normal[pointi];
965  nearest[pointi] = hit1[pointi].hitPoint();
966  }
967  }
968  }
969 
970 
971  // 2. intersection from end to last intersection
972  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
973 
974  // Find the nearest intersection from end to start. Note that we initialize
975  // to the first intersection (if any).
976  surface2 = surface1;
977  hit2 = hit1;
978  region2 = region1;
979  normal2 = normal1;
980 
981  // Set current end of segment to test.
982  forAll(nearest, pointi)
983  {
984  if (hit1[pointi].hit())
985  {
986  nearest[pointi] = hit1[pointi].hitPoint();
987  }
988  else
989  {
990  // Disable testing by setting to end.
991  nearest[pointi] = end[pointi];
992  }
993  }
994 
995  forAll(surfacesToTest, testI)
996  {
997  label surfI = surfacesToTest[testI];
998  const searchableSurface& geom = allGeometry_[surfaces_[surfI]];
999 
1000  // See if any intersection between end and current nearest
1001  geom.findLine(end, nearest, nearestInfo);
1002  geom.getRegion(nearestInfo, region);
1003  geom.getNormal(nearestInfo, normal);
1004 
1005  forAll(nearestInfo, pointi)
1006  {
1007  if (nearestInfo[pointi].hit())
1008  {
1009  hit2[pointi] = nearestInfo[pointi];
1010  surface2[pointi] = surfI;
1011  region2[pointi] = region[pointi];
1012  normal2[pointi] = normal[pointi];
1013  nearest[pointi] = hit2[pointi].hitPoint();
1014  }
1015  }
1016  }
1017 
1018 
1019  // Make sure that if hit1 has hit something, hit2 will have at least the
1020  // same point (due to tolerances it might miss its end point)
1021  forAll(hit1, pointi)
1022  {
1023  if (hit1[pointi].hit() && !hit2[pointi].hit())
1024  {
1025  hit2[pointi] = hit1[pointi];
1026  surface2[pointi] = surface1[pointi];
1027  region2[pointi] = region1[pointi];
1028  normal2[pointi] = normal1[pointi];
1029  }
1030  }
1031 }
1032 
1033 
1036  const pointField& start,
1037  const pointField& end,
1038 
1039  labelList& hitSurface,
1040  List<pointIndexHit>& hitInfo
1041 ) const
1042 {
1043  searchableSurfacesQueries::findAnyIntersection
1044  (
1045  allGeometry_,
1046  surfaces_,
1047  start,
1048  end,
1049  hitSurface,
1050  hitInfo
1051  );
1052 }
1053 
1054 
1057  const labelList& surfacesToTest,
1058  const pointField& samples,
1059  const scalarField& nearestDistSqr,
1060  labelList& hitSurface,
1061  List<pointIndexHit>& hitInfo
1062 ) const
1063 {
1064  labelList geometries(UIndirectList<label>(surfaces_, surfacesToTest));
1065 
1066  // Do the tests. Note that findNearest returns index in geometries.
1067  searchableSurfacesQueries::findNearest
1068  (
1069  allGeometry_,
1070  geometries,
1071  samples,
1072  nearestDistSqr,
1073  hitSurface,
1074  hitInfo
1075  );
1076 
1077  // Rework the hitSurface to be surface (i.e. index into surfaces_)
1078  forAll(hitSurface, pointi)
1079  {
1080  if (hitSurface[pointi] != -1)
1081  {
1082  hitSurface[pointi] = surfacesToTest[hitSurface[pointi]];
1083  }
1084  }
1085 }
1086 
1087 
1090  const labelList& surfacesToTest,
1091  const pointField& samples,
1092  const scalarField& nearestDistSqr,
1093  labelList& hitSurface,
1094  labelList& hitRegion
1095 ) const
1096 {
1097  labelList geometries(UIndirectList<label>(surfaces_, surfacesToTest));
1098 
1099  // Do the tests. Note that findNearest returns index in geometries.
1100  List<pointIndexHit> hitInfo;
1101  searchableSurfacesQueries::findNearest
1102  (
1103  allGeometry_,
1104  geometries,
1105  samples,
1106  nearestDistSqr,
1107  hitSurface,
1108  hitInfo
1109  );
1110 
1111  // Rework the hitSurface to be surface (i.e. index into surfaces_)
1112  forAll(hitSurface, pointi)
1113  {
1114  if (hitSurface[pointi] != -1)
1115  {
1116  hitSurface[pointi] = surfacesToTest[hitSurface[pointi]];
1117  }
1118  }
1119 
1120  // Collect the region
1121  hitRegion.setSize(hitSurface.size());
1122  hitRegion = -1;
1123 
1124  forAll(surfacesToTest, i)
1125  {
1126  label surfI = surfacesToTest[i];
1127 
1128  // Collect hits for surfI
1129  const labelList localIndices(findIndices(hitSurface, surfI));
1130 
1131  List<pointIndexHit> localHits
1132  (
1134  (
1135  hitInfo,
1136  localIndices
1137  )
1138  );
1139 
1140  labelList localRegion;
1141  allGeometry_[surfaces_[surfI]].getRegion(localHits, localRegion);
1142 
1143  forAll(localIndices, i)
1144  {
1145  hitRegion[localIndices[i]] = localRegion[i];
1146  }
1147  }
1148 }
1149 
1150 
1153  const labelList& surfacesToTest,
1154  const pointField& samples,
1155  const scalarField& nearestDistSqr,
1156  labelList& hitSurface,
1157  List<pointIndexHit>& hitInfo,
1158  labelList& hitRegion,
1159  vectorField& hitNormal
1160 ) const
1161 {
1162  labelList geometries(UIndirectList<label>(surfaces_, surfacesToTest));
1163 
1164  // Do the tests. Note that findNearest returns index in geometries.
1165  searchableSurfacesQueries::findNearest
1166  (
1167  allGeometry_,
1168  geometries,
1169  samples,
1170  nearestDistSqr,
1171  hitSurface,
1172  hitInfo
1173  );
1174 
1175  // Rework the hitSurface to be surface (i.e. index into surfaces_)
1176  forAll(hitSurface, pointi)
1177  {
1178  if (hitSurface[pointi] != -1)
1179  {
1180  hitSurface[pointi] = surfacesToTest[hitSurface[pointi]];
1181  }
1182  }
1183 
1184  // Collect the region
1185  hitRegion.setSize(hitSurface.size());
1186  hitRegion = -1;
1187  hitNormal.setSize(hitSurface.size());
1188  hitNormal = Zero;
1189 
1190  forAll(surfacesToTest, i)
1191  {
1192  label surfI = surfacesToTest[i];
1193 
1194  // Collect hits for surfI
1195  const labelList localIndices(findIndices(hitSurface, surfI));
1196 
1197  List<pointIndexHit> localHits
1198  (
1200  (
1201  hitInfo,
1202  localIndices
1203  )
1204  );
1205 
1206  // Region
1207  labelList localRegion;
1208  allGeometry_[surfaces_[surfI]].getRegion(localHits, localRegion);
1209 
1210  forAll(localIndices, i)
1211  {
1212  hitRegion[localIndices[i]] = localRegion[i];
1213  }
1214 
1215  // Normal
1216  vectorField localNormal;
1217  allGeometry_[surfaces_[surfI]].getNormal(localHits, localNormal);
1218 
1219  forAll(localIndices, i)
1220  {
1221  hitNormal[localIndices[i]] = localNormal[i];
1222  }
1223  }
1224 }
1225 
1226 
1229 //Foam::label Foam::refinementSurfaces::findHighestIntersection
1230 //(
1231 // const point& start,
1232 // const point& end,
1233 // const label currentLevel, // current cell refinement level
1234 //
1235 // pointIndexHit& maxHit
1236 //) const
1237 //{
1238 // // surface with highest maxlevel
1239 // label maxSurface = -1;
1240 // // maxLevel of maxSurface
1241 // label maxLevel = currentLevel;
1242 //
1243 // forAll(*this, surfI)
1244 // {
1245 // pointIndexHit hit = operator[](surfI).findLineAny(start, end);
1246 //
1247 // if (hit.hit())
1248 // {
1249 // const triSurface& s = operator[](surfI);
1250 //
1251 // label region = globalRegion(surfI, s[hit.index()].region());
1252 //
1253 // if (maxLevel_[region] > maxLevel)
1254 // {
1255 // maxSurface = surfI;
1256 // maxLevel = maxLevel_[region];
1257 // maxHit = hit;
1258 // }
1259 // }
1260 // }
1261 //
1262 // if (maxSurface == -1)
1263 // {
1264 // // maxLevel unchanged. No interesting surface hit.
1265 // maxHit.setMiss();
1266 // }
1267 //
1268 // return maxSurface;
1269 //}
1270 
1271 
1274  const labelList& testSurfaces,
1275  const pointField& pt,
1276  labelList& insideSurfaces
1277 ) const
1278 {
1279  insideSurfaces.setSize(pt.size());
1280  insideSurfaces = -1;
1281 
1282  forAll(testSurfaces, i)
1283  {
1284  label surfI = testSurfaces[i];
1285 
1286  const searchableSurface& surface = allGeometry_[surfaces_[surfI]];
1287 
1288  const surfaceZonesInfo::areaSelectionAlgo selectionMethod =
1289  surfZones_[surfI].zoneInside();
1290 
1291  if
1292  (
1293  selectionMethod != surfaceZonesInfo::INSIDE
1294  && selectionMethod != surfaceZonesInfo::OUTSIDE
1295  )
1296  {
1298  << "Trying to use surface "
1299  << surface.name()
1300  << " which has non-geometric inside selection method "
1301  << surfaceZonesInfo::areaSelectionAlgoNames[selectionMethod]
1302  << exit(FatalError);
1303  }
1304 
1305  if (surface.hasVolumeType())
1306  {
1307  List<volumeType> volType;
1308  surface.getVolumeType(pt, volType);
1309 
1310  forAll(volType, pointi)
1311  {
1312  if (insideSurfaces[pointi] == -1)
1313  {
1314  if
1315  (
1316  (
1317  volType[pointi] == volumeType::INSIDE
1318  && selectionMethod == surfaceZonesInfo::INSIDE
1319  )
1320  || (
1321  volType[pointi] == volumeType::OUTSIDE
1322  && selectionMethod == surfaceZonesInfo::OUTSIDE
1323  )
1324  )
1325  {
1326  insideSurfaces[pointi] = surfI;
1327  }
1328  }
1329  }
1330  }
1331  }
1332 }
1333 
1334 
1335 // ************************************************************************* //
#define readScalar
Definition: doubleScalar.C:38
A HashTable with keys but without contents.
Definition: HashSet.H:59
dictionary dict
bool found(const word &, bool recursive=false, bool patternMatch=true) const
Search dictionary for given keyword.
Definition: dictionary.C:431
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:428
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
const word & name() const
Return name.
Definition: IOobject.H:297
const entry * lookupEntryPtr(const word &, bool recursive, bool patternMatch) const
Find and return an entry data stream pointer if present.
Definition: dictionary.C:470
virtual const wordList & regions() const =0
Names of regions.
bool set(const label) const
Is element set.
Definition: PtrListI.H:65
const keyType & keyword() const
Return keyword.
Definition: entry.H:123
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
error FatalError
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:137
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
void findAllHigherIntersections(const pointField &start, const pointField &end, const labelList &currentLevel, const labelList &globalRegionLevel, List< vectorList > &surfaceNormal, labelListList &surfaceLevel) const
Find all intersections of edge. Unsorted order.
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:163
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:256
virtual const dictionary & dict() const =0
Return dictionary if this entry is a dictionary.
void findAnyIntersection(const pointField &start, const pointField &end, labelList &surfaces, List< pointIndexHit > &) const
Used for debugging only: find intersection of edge.
labelList identity(const label len)
Create identity map (map[i] == i) of given length.
Definition: ListOps.C:104
Base class of (analytical or triangulated) surface. Encapsulates all the search routines. WIP.
virtual void findLineAny(const pointField &start, const pointField &end, List< pointIndexHit > &) const =0
Return any intersection on segment from start to end.
labelList findIndices(const ListType &, typename ListType::const_reference, const label start=0)
Find all occurrences of given element. Linear search.
virtual void getField(const List< pointIndexHit > &, labelList &values) const
WIP. From a set of hits (points and.
void findNearest(const labelList &surfacesToTest, const pointField &samples, const scalarField &nearestDistSqr, labelList &surfaces, List< pointIndexHit > &) const
Find nearest point on surfaces.
bool erase(T *p)
Remove the specified element from the list and delete it.
Definition: ILList.C:96
autoPtr< dictionary > clone() const
Construct and return clone.
Definition: dictionary.C:340
wordList toc() const
Return the table of contents.
Definition: dictionary.C:776
const dictionary & subDict(const word &) const
Find and return a sub-dictionary.
Definition: dictionary.C:692
An ordered pair of two objects of type <T> with first() and second() elements.
Definition: contiguous.H:49
virtual void findNearest(const pointField &sample, const scalarField &nearestDistSqr, List< pointIndexHit > &) const =0
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.
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:124
virtual void findLineAll(const pointField &start, const pointField &end, List< List< pointIndexHit >> &) const =0
Get all intersections in order from start to end.
A class for handling words, derived from string.
Definition: word.H:59
bool readIfPresent(const word &, T &, bool recursive=false, bool patternMatch=true) const
Find an entry if present, and assign to T.
Container for searchableSurfaces.
List< label > labelList
A List of labels.
Definition: labelList.H:56
static const zero Zero
Definition: zero.H:97
Encapsulates queries for volume refinement (&#39;refine all cells within shell&#39;).
Definition: shellSurfaces.H:52
virtual label globalSize() const
Range of global indices that can be returned.
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:29
label size() const
Return the number of elements in the UPtrList.
Definition: UPtrListI.H:29
void setSize(const label)
Reset size of List.
Definition: List.C:281
T lookupOrDefault(const word &, const T &, bool recursive=false, bool patternMatch=true) const
Find and return a T,.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:331
A templated 1D list of pointers to objects of type <T>, where the size of the array is known and used...
Definition: List.H:63
A List with indirect addressing.
Definition: fvMatrix.H:106
virtual void getVolumeType(const pointField &, List< volumeType > &) const =0
Determine type (inside/outside) for point. unknown if.
virtual void getRegion(const List< pointIndexHit > &, labelList &region) const =0
From a set of points and indices get the region.
label n
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
#define IOWarningInFunction(ios)
Report an IO warning using Foam::Warning.
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: PtrList.H:52
void findHigherIntersection(const pointField &start, const pointField &end, const labelList &currentLevel, labelList &surfaces, labelList &surfaceLevel) const
Find intersection of edge. Return -1 or first surface.
void findNearestIntersection(const labelList &surfacesToTest, const pointField &start, const pointField &end, labelList &surface1, List< pointIndexHit > &hit1, labelList &region1, labelList &surface2, List< pointIndexHit > &hit2, labelList &region2) const
Find intersection nearest to the endpoints. surface1,2 are.
void setMinLevelFields(const shellSurfaces &shells)
Calculate minLevelFields.
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.
virtual void findLine(const pointField &start, const pointField &end, List< pointIndexHit > &) const =0
Find first intersection on segment from start to end.
virtual bool hasVolumeType() const =0
Whether supports volume type below.
A keyword and a list of tokens is an &#39;entry&#39;.
Definition: entry.H:65
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:576
void findInside(const labelList &surfacesToTest, const pointField &pt, labelList &insideSurfaces) const
Detect if a point is &#39;inside&#39; (closed) surfaces.
virtual void boundingSpheres(pointField &centres, scalarField &radiusSqr) const =0
Get bounding spheres (centre and radius squared), one per element.
IOerror FatalIOError