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