1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright held by original author
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
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 the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
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
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
27 #include "searchableSurface.H"
28 #include "shellSurfaces.H"
30 #include "triSurfaceMesh.H"
31 #include "refinementSurfaces.H"
32 #include "searchableSurfaces.H"
33 #include "orientedSurface.H"
34 #include "pointIndexHit.H"
36 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
44 NamedEnum<shellSurfaces::refineMode, 3>::
52 const NamedEnum<shellSurfaces::refineMode, 3> shellSurfaces::refineModeNames_;
54 } // End namespace Foam
58 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
60 void Foam::shellSurfaces::setAndCheckLevels
63 const List<Tuple2<scalar, label> >& distLevels
66 if (modes_[shellI] != DISTANCE && distLevels.size() != 1)
70 "shellSurfaces::shellSurfaces"
71 "(const searchableSurfaces&, const dictionary&)"
72 ) << "For refinement mode "
73 << refineModeNames_[modes_[shellI]]
74 << " specify only one distance+level."
75 << " (its distance gets discarded)"
78 // Extract information into separate distance and level
79 distances_[shellI].setSize(distLevels.size());
80 levels_[shellI].setSize(distLevels.size());
84 distances_[shellI][j] = distLevels[j].first();
85 levels_[shellI][j] = distLevels[j].second();
87 // Check in incremental order
92 (distances_[shellI][j] <= distances_[shellI][j-1])
93 || (levels_[shellI][j] > levels_[shellI][j-1])
98 "shellSurfaces::shellSurfaces"
99 "(const searchableSurfaces&, const dictionary&)"
100 ) << "For refinement mode "
101 << refineModeNames_[modes_[shellI]]
102 << " : Refinement should be specified in order"
103 << " of increasing distance"
104 << " (and decreasing refinement level)." << endl
105 << "Distance:" << distances_[shellI][j]
106 << " refinementLevel:" << levels_[shellI][j]
112 const searchableSurface& shell = allGeometry_[shells_[shellI]];
114 if (modes_[shellI] == DISTANCE)
116 Info<< "Refinement level according to distance to "
117 << shell.name() << endl;
118 forAll(levels_[shellI], j)
120 Info<< " level " << levels_[shellI][j]
121 << " for all cells within " << distances_[shellI][j]
122 << " meter." << endl;
127 if (!allGeometry_[shells_[shellI]].hasVolumeType())
131 "shellSurfaces::shellSurfaces"
132 "(const searchableSurfaces&"
133 ", const PtrList<dictionary>&)"
134 ) << "Shell " << shell.name()
135 << " does not support testing for "
136 << refineModeNames_[modes_[shellI]] << endl
137 << "Probably it is not closed."
141 if (modes_[shellI] == INSIDE)
143 Info<< "Refinement level " << levels_[shellI][0]
144 << " for all cells inside " << shell.name() << endl;
148 Info<< "Refinement level " << levels_[shellI][0]
149 << " for all cells outside " << shell.name() << endl;
155 // Specifically orient triSurfaces using a calculated point outside.
156 // Done since quite often triSurfaces not of consistent orientation which
157 // is (currently) necessary for sideness calculation
158 void Foam::shellSurfaces::orient()
160 // Determine outside point.
161 boundBox overallBb = boundBox::invertedBox;
163 bool hasSurface = false;
165 forAll(shells_, shellI)
167 const searchableSurface& s = allGeometry_[shells_[shellI]];
169 if (modes_[shellI] != DISTANCE && isA<triSurfaceMesh>(s))
171 const triSurfaceMesh& shell = refCast<const triSurfaceMesh>(s);
173 if (shell.triSurface::size())
175 const pointField& points = shell.points();
179 boundBox shellBb(points[0], points[0]);
180 // Assume surface is compact!
181 for (label i = 0; i < points.size(); i++)
183 const point& pt = points[i];
184 shellBb.min() = min(shellBb.min(), pt);
185 shellBb.max() = max(shellBb.max(), pt);
188 overallBb.min() = min(overallBb.min(), shellBb.min());
189 overallBb.max() = max(overallBb.max(), shellBb.max());
196 const point outsidePt = overallBb.max() + overallBb.span();
198 //Info<< "Using point " << outsidePt << " to orient shells" << endl;
200 forAll(shells_, shellI)
202 const searchableSurface& s = allGeometry_[shells_[shellI]];
204 if (modes_[shellI] != DISTANCE && isA<triSurfaceMesh>(s))
206 triSurfaceMesh& shell = const_cast<triSurfaceMesh&>
208 refCast<const triSurfaceMesh>(s)
211 // Flip surface so outsidePt is outside.
212 bool anyFlipped = orientedSurface::orient
221 // orientedSurface will have done a clearOut of the surface.
222 // we could do a clearout of the triSurfaceMeshes::trees()
223 // but these aren't affected by orientation
224 // (except for cached
225 // sideness which should not be set at this point.
228 Info<< "shellSurfaces : Flipped orientation of surface "
230 << " so point " << outsidePt << " is outside." << endl;
238 // Find maximum level of a shell.
239 void Foam::shellSurfaces::findHigherLevel
241 const pointField& pt,
246 const labelList& levels = levels_[shellI];
248 if (modes_[shellI] == DISTANCE)
252 const scalarField& distances = distances_[shellI];
254 // Collect all those points that have a current maxLevel less than
255 // (any of) the shell. Also collect the furthest distance allowable
256 // to any shell with a higher level.
258 pointField candidates(pt.size());
259 labelList candidateMap(pt.size());
260 scalarField candidateDistSqr(pt.size());
261 label candidateI = 0;
263 forAll(maxLevel, pointI)
265 forAllReverse(levels, levelI)
267 if (levels[levelI] > maxLevel[pointI])
269 candidates[candidateI] = pt[pointI];
270 candidateMap[candidateI] = pointI;
271 candidateDistSqr[candidateI] = sqr(distances[levelI]);
277 candidates.setSize(candidateI);
278 candidateMap.setSize(candidateI);
279 candidateDistSqr.setSize(candidateI);
281 // Do the expensive nearest test only for the candidate points.
282 List<pointIndexHit> nearInfo;
283 allGeometry_[shells_[shellI]].findNearest
291 forAll(nearInfo, candidateI)
293 if (nearInfo[candidateI].hit())
295 // Check which level it actually is in.
296 label minDistI = findLower
299 mag(nearInfo[candidateI].hitPoint()-candidates[candidateI])
302 label pointI = candidateMap[candidateI];
304 // pt is inbetween shell[minDistI] and shell[minDistI+1]
305 maxLevel[pointI] = levels[minDistI+1];
311 // Inside/outside mode
313 // Collect all those points that have a current maxLevel less than the
316 pointField candidates(pt.size());
317 labelList candidateMap(pt.size());
318 label candidateI = 0;
320 forAll(maxLevel, pointI)
322 if (levels[0] > maxLevel[pointI])
324 candidates[candidateI] = pt[pointI];
325 candidateMap[candidateI] = pointI;
329 candidates.setSize(candidateI);
330 candidateMap.setSize(candidateI);
332 // Do the expensive nearest test only for the candidate points.
333 List<searchableSurface::volumeType> volType;
334 allGeometry_[shells_[shellI]].getVolumeType(candidates, volType);
338 label pointI = candidateMap[i];
343 modes_[shellI] == INSIDE
344 && volType[i] == searchableSurface::INSIDE
347 modes_[shellI] == OUTSIDE
348 && volType[i] == searchableSurface::OUTSIDE
352 maxLevel[pointI] = levels[0];
359 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
361 Foam::shellSurfaces::shellSurfaces
363 const searchableSurfaces& allGeometry,
364 const PtrList<dictionary>& shellDicts
367 allGeometry_(allGeometry)
369 shells_.setSize(shellDicts.size());
370 modes_.setSize(shellDicts.size());
371 distances_.setSize(shellDicts.size());
372 levels_.setSize(shellDicts.size());
374 forAll(shellDicts, shellI)
376 const dictionary& dict = shellDicts[shellI];
377 const word name = dict.lookup("name");
378 const word type = dict.lookup("type");
380 shells_[shellI] = allGeometry_.findSurfaceID(name);
382 if (shells_[shellI] == -1)
386 "shellSurfaces::shellSurfaces"
387 "(const searchableSurfaces&, const PtrList<dictionary>&)"
388 ) << "No surface called " << name << endl
389 << "Valid surfaces are " << allGeometry_.names()
393 modes_[shellI] = refineModeNames_.read(dict.lookup("refineMode"));
395 // Read pairs of distance+level
396 setAndCheckLevels(shellI, dict.lookup("levels"));
399 // Orient shell surfaces before any searching is done. Note that this
400 // only needs to be done for inside or outside. Orienting surfaces
401 // constructs lots of addressing which we want to avoid.
406 Foam::shellSurfaces::shellSurfaces
408 const searchableSurfaces& allGeometry,
409 const dictionary& shellsDict
412 allGeometry_(allGeometry)
414 shells_.setSize(shellsDict.size());
415 modes_.setSize(shellsDict.size());
416 distances_.setSize(shellsDict.size());
417 levels_.setSize(shellsDict.size());
420 forAllConstIter(dictionary, shellsDict, iter)
422 shells_[shellI] = allGeometry_.findSurfaceID(iter().keyword());
424 if (shells_[shellI] == -1)
428 "shellSurfaces::shellSurfaces"
429 "(const searchableSurfaces&, const dictionary>&"
430 ) << "No surface called " << iter().keyword() << endl
431 << "Valid surfaces are " << allGeometry_.names()
434 const dictionary& dict = shellsDict.subDict(iter().keyword());
436 modes_[shellI] = refineModeNames_.read(dict.lookup("mode"));
438 // Read pairs of distance+level
439 setAndCheckLevels(shellI, dict.lookup("levels"));
444 // Orient shell surfaces before any searching is done. Note that this
445 // only needs to be done for inside or outside. Orienting surfaces
446 // constructs lots of addressing which we want to avoid.
451 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
453 // Highest shell level
454 Foam::label Foam::shellSurfaces::maxLevel() const
456 label overallMax = 0;
457 forAll(levels_, shellI)
459 overallMax = max(overallMax, max(levels_[shellI]));
465 void Foam::shellSurfaces::findHigherLevel
467 const pointField& pt,
468 const labelList& ptLevel,
472 // Maximum level of any shell. Start off with level of point.
475 forAll(shells_, shellI)
477 findHigherLevel(pt, shellI, maxLevel);
482 // ************************************************************************* //