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