46 Foam::shellSurfaces::refineModeNames_
48 { refineMode::INSIDE,
"inside" },
49 { refineMode::OUTSIDE,
"outside" },
50 { refineMode::DISTANCE,
"distance" },
56 void Foam::shellSurfaces::setAndCheckLevels
59 const List<Tuple2<scalar, label>>& distLevels
62 const searchableSurface& shell = allGeometry_[shells_[shellI]];
64 if (modes_[shellI] !=
DISTANCE && distLevels.size() != 1)
67 <<
"For refinement mode " 68 << refineModeNames_[modes_[shellI]]
69 <<
" specify only one distance+level." 70 <<
" (its distance gets discarded)" 74 distances_[shellI].
setSize(distLevels.size());
75 levels_[shellI].
setSize(distLevels.size());
79 distances_[shellI][j] = distLevels[j].
first();
80 levels_[shellI][j] = distLevels[j].second();
82 if (levels_[shellI][j] < -1)
85 <<
"Shell " << shell.name()
86 <<
" has illegal refinement level " 97 (distances_[shellI][j] <= distances_[shellI][j-1])
98 || (levels_[shellI][j] > levels_[shellI][j-1])
102 <<
"For refinement mode " 103 << refineModeNames_[modes_[shellI]]
104 <<
" : Refinement should be specified in order" 105 <<
" of increasing distance" 106 <<
" (and decreasing refinement level)." <<
endl 107 <<
"Distance:" << distances_[shellI][j]
108 <<
" refinementLevel:" << levels_[shellI][j]
118 Info<<
"Refinement level according to distance to " 119 << shell.name() <<
endl;
120 forAll(levels_[shellI], j)
122 Info<<
" level " << levels_[shellI][j]
123 <<
" for all cells within " << distances_[shellI][j]
124 <<
" metre." <<
endl;
130 if (!shell.hasVolumeType())
133 <<
"Shell " << shell.name()
134 <<
" does not support testing for " 135 << refineModeNames_[modes_[shellI]] <<
endl 136 <<
"Probably it is not closed." 142 if (modes_[shellI] ==
INSIDE)
144 Info<<
"Refinement level " << levels_[shellI][0]
145 <<
" for all cells inside " << shell.name() <<
endl;
149 Info<<
"Refinement level " << levels_[shellI][0]
150 <<
" for all cells outside " << shell.name() <<
endl;
160 void Foam::shellSurfaces::orient()
165 bool hasSurface =
false;
169 const searchableSurface&
s = allGeometry_[shells_[shellI]];
171 if (modes_[shellI] != DISTANCE && isA<triSurfaceMesh>(
s))
175 const triSurfaceMesh& shell = refCast<const triSurfaceMesh>(
s);
176 if (shell.triSurface::size())
179 overallBb.add(
s.bounds());
186 const point outsidePt = overallBb.max() + overallBb.span();
192 const searchableSurface&
s = allGeometry_[shells_[shellI]];
194 if (modes_[shellI] != DISTANCE && isA<triSurfaceMesh>(
s))
196 triSurfaceMesh& shell =
const_cast<triSurfaceMesh&
> 198 refCast<const triSurfaceMesh>(
s)
200 bool anyFlipped =
false;
201 if (!isA<distributedTriSurfaceMesh>(
s))
219 List<pointIndexHit> info;
231 if ((normal[0] & (info[0].
point()-outsidePt)) > 0)
238 if (anyFlipped && !dryRun_)
240 Info<<
"shellSurfaces : Flipped orientation of surface " 242 <<
" so point " << outsidePt <<
" is outside." <<
endl;
251 void Foam::shellSurfaces::findHigherLevel
258 const labelList& levels = levels_[shellI];
260 if (modes_[shellI] == DISTANCE)
272 label candidateI = 0;
278 if (levels[levelI] > maxLevel[pointi])
280 candidateMap[candidateI] = pointi;
281 candidateDistSqr[candidateI] =
sqr(distances[levelI]);
287 candidateMap.setSize(candidateI);
288 candidateDistSqr.setSize(candidateI);
291 List<pointIndexHit> nearInfo;
292 allGeometry_[shells_[shellI]].findNearest
302 if (nearInfo[i].hit())
304 const label pointi = candidateMap[i];
310 nearInfo[i].
point().dist(pt[pointi])
314 maxLevel[pointi] = levels[minDistI+1];
327 label candidateI = 0;
331 if (levels[0] > maxLevel[pointi])
333 candidates[candidateI] = pt[pointi];
334 candidateMap[candidateI] = pointi;
338 candidates.setSize(candidateI);
339 candidateMap.setSize(candidateI);
342 List<volumeType> volType;
343 allGeometry_[shells_[shellI]].getVolumeType(candidates, volType);
347 label pointi = candidateMap[i];
352 modes_[shellI] == INSIDE
356 modes_[shellI] == OUTSIDE
361 maxLevel[pointi] = levels[0];
368 void Foam::shellSurfaces::findHigherGapLevel
374 List<FixedList<label, 3>>& gapInfo,
375 List<volumeType>& gapMode
379 const FixedList<label, 3>& info = extendedGapLevel_[shellI][0];
380 const volumeType
mode = extendedGapMode_[shellI][0];
387 if (modes_[shellI] == DISTANCE)
390 const scalar
distance = distances_[shellI][0];
394 label candidateI = 0;
398 if (ptLevel[pointI] >= info[1] && ptLevel[pointI] < info[2])
400 candidateMap[candidateI] = pointI;
405 candidateMap.setSize(candidateI);
406 candidateDistSqr.setSize(candidateI);
409 List<pointIndexHit> nearInfo;
410 allGeometry_[shells_[shellI]].findNearest
420 if (nearInfo[i].hit())
422 const label pointI = candidateMap[i];
423 gapShell[pointI] = shellI;
424 gapInfo[pointI] = info;
425 gapMode[pointI] =
mode;
435 label candidateI = 0;
439 if (ptLevel[pointI] >= info[1] && ptLevel[pointI] < info[2])
441 candidateMap[candidateI++] = pointI;
444 candidateMap.setSize(candidateI);
447 List<volumeType> volType;
448 allGeometry_[shells_[shellI]].getVolumeType
456 const label pointI = candidateMap[i];
462 (modes_[shellI] == INSIDE && isInside)
463 || (modes_[shellI] == OUTSIDE && !isInside)
465 && info[2] > gapInfo[pointI][2]
468 gapShell[pointI] = shellI;
469 gapInfo[pointI] = info;
470 gapMode[pointI] =
mode;
477 void Foam::shellSurfaces::findLevel
485 const labelList& levels = levels_[shellI];
487 if (modes_[shellI] == DISTANCE)
500 label candidateI = 0;
504 if (shell[pointI] == -1)
508 if (levels[levelI] <= minLevel[pointI])
510 candidates[candidateI] = pt[pointI];
511 candidateMap[candidateI] = pointI;
512 candidateDistSqr[candidateI] =
sqr(distances[levelI]);
519 candidates.setSize(candidateI);
520 candidateMap.setSize(candidateI);
521 candidateDistSqr.setSize(candidateI);
524 List<pointIndexHit> nearInfo;
525 allGeometry_[shells_[shellI]].findNearest
535 if (nearInfo[i].hit())
541 nearInfo[i].
point().dist(candidates[i])
544 label pointI = candidateMap[i];
547 shell[pointI] = shellI;
548 minLevel[pointI] = levels[minDistI+1];
561 label candidateI = 0;
565 if (shell[pointI] == -1 && levels[0] <= minLevel[pointI])
567 candidates[candidateI] = pt[pointI];
568 candidateMap[candidateI] = pointI;
572 candidates.setSize(candidateI);
573 candidateMap.setSize(candidateI);
576 List<volumeType> volType;
577 allGeometry_[shells_[shellI]].getVolumeType(candidates, volType);
584 modes_[shellI] == INSIDE
588 modes_[shellI] == OUTSIDE
593 label pointI = candidateMap[i];
594 shell[pointI] = shellI;
595 minLevel[pointI] = levels[0];
606 const searchableSurfaces& allGeometry,
607 const dictionary& shellsDict,
611 allGeometry_(allGeometry),
618 for (
const word& geomName : allGeometry_.
names())
620 if (shellsDict.found(geomName))
628 shells_.setSize(shellI);
632 dirLevels_.setSize(shellI);
633 smoothDirection_.
setSize(shellI);
634 nSmoothExpansion_.
setSize(shellI);
635 nSmoothPosition_.
setSize(shellI);
637 extendedGapLevel_.setSize(shellI);
638 extendedGapMode_.setSize(shellI);
639 selfProximity_.
setSize(shellI);
641 const FixedList<label, 3> nullGapLevel({0, 0, 0});
648 const word& geomName = allGeometry_.
names()[geomI];
650 const entry* eptr = shellsDict.findEntry(geomName,
keyType::REGEX);
655 unmatchedKeys.erase(eptr->keyword());
657 shells_[shellI] = geomI;
658 modes_[shellI] = refineModeNames_.
get(
"mode",
dict);
661 setAndCheckLevels(shellI,
dict.lookup(
"levels"));
667 dirLevels_[shellI] = Tuple2<labelPair,labelVector>
672 const entry* levelPtr =
679 ITstream& is = levelPtr->stream();
681 is.readBegin(
"levelIncrement");
682 is >> dirLevels_[shellI].first().first()
683 >> dirLevels_[shellI].first().second()
684 >> dirLevels_[shellI].second();
685 is.readEnd(
"levelIncrement");
687 if (modes_[shellI] ==
INSIDE)
691 Info<<
"Additional directional refinement level" 692 <<
" for all cells inside " << geomName <<
endl;
695 else if (modes_[shellI] ==
OUTSIDE)
699 Info<<
"Additional directional refinement level" 700 <<
" for all cells outside " << geomName <<
endl;
706 <<
"Unsupported mode " 707 << refineModeNames_[modes_[shellI]]
715 nSmoothExpansion_[shellI] = 0;
716 nSmoothPosition_[shellI] = 0;
717 smoothDirection_[shellI] =
718 dict.getOrDefault(
"smoothDirection", vector::zero);
720 if (smoothDirection_[shellI] != vector::zero)
722 dict.readEntry(
"nSmoothExpansion", nSmoothExpansion_[shellI]);
723 dict.readEntry(
"nSmoothPosition", nSmoothPosition_[shellI]);
732 const searchableSurface&
surface = allGeometry_[geomI];
735 FixedList<label, 3> gapSpec
743 extendedGapLevel_[shellI].setSize(
regionNames.size());
744 extendedGapLevel_[shellI] = gapSpec;
746 extendedGapMode_[shellI].setSize(
regionNames.size());
747 extendedGapMode_[shellI] =
754 dict.getOrDefault<
bool>(
"gapSelf",
true)
760 if (
dict.found(
"regions"))
768 const dictionary& regionDict = regionsDict.subDict
772 FixedList<label, 3> gapSpec
774 regionDict.getOrDefault
780 extendedGapLevel_[shellI][regionI] = gapSpec;
782 extendedGapMode_[shellI][regionI] =
790 selfProximity_[shellI][regionI] =
791 regionDict.getOrDefault<
bool>
800 if (extendedGapLevel_[shellI][0][0] > 0)
802 Info<<
"Refinement level up to " 803 << extendedGapLevel_[shellI][0][2]
804 <<
" for all cells in gaps for shell " 807 if (distances_[shellI].size() > 1)
810 << distances_[shellI] <<
" to detect gaps for shell " 819 if (unmatchedKeys.size() > 0)
822 <<
"Not all entries in refinementRegions dictionary were used." 823 <<
" The following entries were not used : " 824 << unmatchedKeys.sortedToc()
840 label overallMax = 0;
843 overallMax =
max(overallMax,
max(levels_[shellI]));
853 forAll(extendedGapLevel_, shelli)
855 const List<FixedList<label, 3>>& levels = extendedGapLevel_[shelli];
858 surfaceMax[shelli] =
max(surfaceMax[shelli], levels[i][2]);
868 forAll(dirLevels_, shelli)
870 levels[shelli] = dirLevels_[shelli].first();
878 return nSmoothExpansion_;
884 return smoothDirection_;
890 return nSmoothPosition_;
894 void Foam::shellSurfaces::findHigherLevel
906 findHigherLevel(pt, shelli, maxLevel);
911 void Foam::shellSurfaces::findHigherGapLevel
916 List<FixedList<label, 3>>& gapInfo,
917 List<volumeType>& gapMode
920 gapShell.setSize(pt.size());
923 gapInfo.setSize(pt.size());
924 gapInfo = FixedList<label, 3>({0, 0, 0});
926 gapMode.setSize(pt.size());
931 findHigherGapLevel(pt, ptLevel, shelli, gapShell, gapInfo, gapMode);
936 void Foam::shellSurfaces::findHigherGapLevel
940 List<FixedList<label, 3>>& gapInfo,
941 List<volumeType>& gapMode
945 findHigherGapLevel(pt, ptLevel, gapShell, gapInfo, gapMode);
949 void Foam::shellSurfaces::findLevel
963 findLevel(pt, shelli, minLevel, shell);
977 shell.setSize(pt.size());
980 List<volumeType> volType;
983 DynamicList<label> candidateMap(pt.size());
987 if (modes_[shelli] == INSIDE || modes_[shelli] == OUTSIDE)
990 const label addLevel = dirLevels_[shelli].second()[dir];
993 candidateMap.clear();
996 label level = ptLevel[celli];
1000 level >= selectLevels.first()
1001 && level <= selectLevels.second()
1002 && dirLevel[celli] < level+addLevel
1005 candidateMap.append(celli);
1011 allGeometry_[shells_[shelli]].getVolumeType(candidatePt, volType);
1019 modes_[shelli] == INSIDE
1023 modes_[shelli] == OUTSIDE
1028 shell[candidateMap[i]] = shelli;
EnumType get(const word &enumName) const
The enumeration corresponding to the given name.
const T & first() const noexcept
Access the first element.
void size(const label n)
Older name for setAddressableSize.
labelPairList directionalSelectLevel() const
Min and max cell level for directional refinement.
label findLower(const ListType &input, const T &val, const label start, const ComparePredicate &comp)
Binary search to find the index of the last element in a sorted list that is less than value...
errorManipArg< error, int > exit(error &err, const int errNo=1)
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
dimensionedSymmTensor sqr(const dimensionedVector &dv)
refineMode
Volume refinement controls.
T & first()
Access first element of the list, position [0].
Ostream & endl(Ostream &os)
Add newline and flush stream.
static bool orient(triSurface &, const point &, const bool orientOutside)
Flip faces such that normals are consistent with point:
const labelList & nSmoothExpansion() const
Per shell the directional smoothing iterations.
scalar distance(const vector &p1, const vector &p2)
label maxLevel() const
Highest shell level.
List< labelPair > labelPairList
List of labelPair.
#define forAll(list, i)
Loop across all elements in list.
vectorField pointField
pointField is a vectorField.
void setSize(const label n)
Alias for resize()
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
HashSet< word, Hash< word > > wordHashSet
A HashSet of words, uses string hasher.
A location inside the volume.
A location outside the volume.
bool returnReduceOr(const bool value, const int communicator=UPstream::worldComm)
Perform logical (or) MPI Allreduce on a copy. Uses UPstream::reduceOr.
labelList maxGapLevel() const
Highest shell gap level.
const wordList surface
Standard surface field types (scalar, vector, tensor, etc)
A location that is partly inside and outside.
void findDirectionalLevel(const pointField &pt, const labelList &ptLevel, const labelList &dirLevel, const direction dir, labelList &shell) const
Find any shell (or -1) with higher wanted directional level.
Pair< label > labelPair
A pair of labels.
static bool orientConsistent(triSurface &s)
Make sure surface has consistent orientation across connected.
shellSurfaces(const searchableSurfaces &allGeometry, const dictionary &shellsDict, const bool dryRun=false)
Construct from geometry and dictionary.
const vectorField & smoothDirection() const
Per shell the smoothing direction.
const labelList & nSmoothPosition() const
Per shell the positional smoothing iterations.
List< word > wordList
List of word.
vector point
Point is a vector.
#define WarningInFunction
Report a warning using Foam::Warning.
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
const wordList & names() const
Surface names, not region names.
messageStream Info
Information stream (stdout output on master, null elsewhere)
Field< vector > vectorField
Specialisation of Field<T> for vector.
#define IOWarningInFunction(ios)
Report an IO warning using Foam::Warning.
#define forAllReverse(list, i)
Reverse loop across all elements in list.
List< label > labelList
A List of labels.
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))
mode_t mode(const fileName &name, const bool followLink=true)
Return the file mode, normally following symbolic links.
static const Vector< label > zero
IOerror FatalIOError
Error stream (stdout output on all processes), with additional 'FOAM FATAL IO ERROR' header text and ...
static constexpr const zero Zero
Global zero (0)