PageRenderTime 25ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/src/mesh/autoMesh/autoHexMesh/shellSurfaces/shellSurfaces.C

https://gitlab.com/johnvarv/OpenFOAM-3.0.x
C | 464 lines | 325 code | 73 blank | 66 comment | 35 complexity | b8d8bc866720d709b911b112ef8b6ea4 MD5 | raw file
  1. /*---------------------------------------------------------------------------*\
  2. ========= |
  3. \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
  4. \\ / O peration |
  5. \\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
  6. \\/ M anipulation |
  7. -------------------------------------------------------------------------------
  8. License
  9. This file is part of OpenFOAM.
  10. OpenFOAM is free software: you can redistribute it and/or modify it
  11. under the terms of the GNU General Public License as published by
  12. the Free Software Foundation, either version 3 of the License, or
  13. (at your option) any later version.
  14. OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
  15. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  16. FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  17. for more details.
  18. You should have received a copy of the GNU General Public License
  19. along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
  20. \*---------------------------------------------------------------------------*/
  21. #include "shellSurfaces.H"
  22. #include "searchableSurface.H"
  23. #include "boundBox.H"
  24. #include "triSurfaceMesh.H"
  25. #include "refinementSurfaces.H"
  26. #include "searchableSurfaces.H"
  27. #include "orientedSurface.H"
  28. #include "pointIndexHit.H"
  29. #include "volumeType.H"
  30. // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
  31. namespace Foam
  32. {
  33. template<>
  34. const char*
  35. NamedEnum<shellSurfaces::refineMode, 3>::
  36. names[] =
  37. {
  38. "inside",
  39. "outside",
  40. "distance"
  41. };
  42. const NamedEnum<shellSurfaces::refineMode, 3> shellSurfaces::refineModeNames_;
  43. } // End namespace Foam
  44. // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
  45. void Foam::shellSurfaces::setAndCheckLevels
  46. (
  47. const label shellI,
  48. const List<Tuple2<scalar, label> >& distLevels
  49. )
  50. {
  51. if (modes_[shellI] != DISTANCE && distLevels.size() != 1)
  52. {
  53. FatalErrorIn
  54. (
  55. "shellSurfaces::shellSurfaces"
  56. "(const searchableSurfaces&, const dictionary&)"
  57. ) << "For refinement mode "
  58. << refineModeNames_[modes_[shellI]]
  59. << " specify only one distance+level."
  60. << " (its distance gets discarded)"
  61. << exit(FatalError);
  62. }
  63. // Extract information into separate distance and level
  64. distances_[shellI].setSize(distLevels.size());
  65. levels_[shellI].setSize(distLevels.size());
  66. forAll(distLevels, j)
  67. {
  68. distances_[shellI][j] = distLevels[j].first();
  69. levels_[shellI][j] = distLevels[j].second();
  70. // Check in incremental order
  71. if (j > 0)
  72. {
  73. if
  74. (
  75. (distances_[shellI][j] <= distances_[shellI][j-1])
  76. || (levels_[shellI][j] > levels_[shellI][j-1])
  77. )
  78. {
  79. FatalErrorIn
  80. (
  81. "shellSurfaces::shellSurfaces"
  82. "(const searchableSurfaces&, const dictionary&)"
  83. ) << "For refinement mode "
  84. << refineModeNames_[modes_[shellI]]
  85. << " : Refinement should be specified in order"
  86. << " of increasing distance"
  87. << " (and decreasing refinement level)." << endl
  88. << "Distance:" << distances_[shellI][j]
  89. << " refinementLevel:" << levels_[shellI][j]
  90. << exit(FatalError);
  91. }
  92. }
  93. }
  94. const searchableSurface& shell = allGeometry_[shells_[shellI]];
  95. if (modes_[shellI] == DISTANCE)
  96. {
  97. Info<< "Refinement level according to distance to "
  98. << shell.name() << endl;
  99. forAll(levels_[shellI], j)
  100. {
  101. Info<< " level " << levels_[shellI][j]
  102. << " for all cells within " << distances_[shellI][j]
  103. << " metre." << endl;
  104. }
  105. }
  106. else
  107. {
  108. if (!allGeometry_[shells_[shellI]].hasVolumeType())
  109. {
  110. FatalErrorIn
  111. (
  112. "shellSurfaces::shellSurfaces"
  113. "(const searchableSurfaces&"
  114. ", const PtrList<dictionary>&)"
  115. ) << "Shell " << shell.name()
  116. << " does not support testing for "
  117. << refineModeNames_[modes_[shellI]] << endl
  118. << "Probably it is not closed."
  119. << exit(FatalError);
  120. }
  121. if (modes_[shellI] == INSIDE)
  122. {
  123. Info<< "Refinement level " << levels_[shellI][0]
  124. << " for all cells inside " << shell.name() << endl;
  125. }
  126. else
  127. {
  128. Info<< "Refinement level " << levels_[shellI][0]
  129. << " for all cells outside " << shell.name() << endl;
  130. }
  131. }
  132. }
  133. // Specifically orient triSurfaces using a calculated point outside.
  134. // Done since quite often triSurfaces not of consistent orientation which
  135. // is (currently) necessary for sideness calculation
  136. void Foam::shellSurfaces::orient()
  137. {
  138. // Determine outside point.
  139. boundBox overallBb = boundBox::invertedBox;
  140. bool hasSurface = false;
  141. forAll(shells_, shellI)
  142. {
  143. const searchableSurface& s = allGeometry_[shells_[shellI]];
  144. if (modes_[shellI] != DISTANCE && isA<triSurfaceMesh>(s))
  145. {
  146. const triSurfaceMesh& shell = refCast<const triSurfaceMesh>(s);
  147. if (shell.triSurface::size())
  148. {
  149. const pointField& points = shell.points();
  150. hasSurface = true;
  151. boundBox shellBb(points[0], points[0]);
  152. // Assume surface is compact!
  153. forAll(points, i)
  154. {
  155. const point& pt = points[i];
  156. shellBb.min() = min(shellBb.min(), pt);
  157. shellBb.max() = max(shellBb.max(), pt);
  158. }
  159. overallBb.min() = min(overallBb.min(), shellBb.min());
  160. overallBb.max() = max(overallBb.max(), shellBb.max());
  161. }
  162. }
  163. }
  164. if (hasSurface)
  165. {
  166. const point outsidePt = overallBb.max() + overallBb.span();
  167. //Info<< "Using point " << outsidePt << " to orient shells" << endl;
  168. forAll(shells_, shellI)
  169. {
  170. const searchableSurface& s = allGeometry_[shells_[shellI]];
  171. if (modes_[shellI] != DISTANCE && isA<triSurfaceMesh>(s))
  172. {
  173. triSurfaceMesh& shell = const_cast<triSurfaceMesh&>
  174. (
  175. refCast<const triSurfaceMesh>(s)
  176. );
  177. // Flip surface so outsidePt is outside.
  178. bool anyFlipped = orientedSurface::orient
  179. (
  180. shell,
  181. outsidePt,
  182. true
  183. );
  184. if (anyFlipped)
  185. {
  186. // orientedSurface will have done a clearOut of the surface.
  187. // we could do a clearout of the triSurfaceMeshes::trees()
  188. // but these aren't affected by orientation
  189. // (except for cached
  190. // sideness which should not be set at this point.
  191. // !!Should check!)
  192. Info<< "shellSurfaces : Flipped orientation of surface "
  193. << s.name()
  194. << " so point " << outsidePt << " is outside." << endl;
  195. }
  196. }
  197. }
  198. }
  199. }
  200. // Find maximum level of a shell.
  201. void Foam::shellSurfaces::findHigherLevel
  202. (
  203. const pointField& pt,
  204. const label shellI,
  205. labelList& maxLevel
  206. ) const
  207. {
  208. const labelList& levels = levels_[shellI];
  209. if (modes_[shellI] == DISTANCE)
  210. {
  211. // Distance mode.
  212. const scalarField& distances = distances_[shellI];
  213. // Collect all those points that have a current maxLevel less than
  214. // (any of) the shell. Also collect the furthest distance allowable
  215. // to any shell with a higher level.
  216. pointField candidates(pt.size());
  217. labelList candidateMap(pt.size());
  218. scalarField candidateDistSqr(pt.size());
  219. label candidateI = 0;
  220. forAll(maxLevel, pointI)
  221. {
  222. forAllReverse(levels, levelI)
  223. {
  224. if (levels[levelI] > maxLevel[pointI])
  225. {
  226. candidates[candidateI] = pt[pointI];
  227. candidateMap[candidateI] = pointI;
  228. candidateDistSqr[candidateI] = sqr(distances[levelI]);
  229. candidateI++;
  230. break;
  231. }
  232. }
  233. }
  234. candidates.setSize(candidateI);
  235. candidateMap.setSize(candidateI);
  236. candidateDistSqr.setSize(candidateI);
  237. // Do the expensive nearest test only for the candidate points.
  238. List<pointIndexHit> nearInfo;
  239. allGeometry_[shells_[shellI]].findNearest
  240. (
  241. candidates,
  242. candidateDistSqr,
  243. nearInfo
  244. );
  245. // Update maxLevel
  246. forAll(nearInfo, candidateI)
  247. {
  248. if (nearInfo[candidateI].hit())
  249. {
  250. // Check which level it actually is in.
  251. label minDistI = findLower
  252. (
  253. distances,
  254. mag(nearInfo[candidateI].hitPoint()-candidates[candidateI])
  255. );
  256. label pointI = candidateMap[candidateI];
  257. // pt is inbetween shell[minDistI] and shell[minDistI+1]
  258. maxLevel[pointI] = levels[minDistI+1];
  259. }
  260. }
  261. }
  262. else
  263. {
  264. // Inside/outside mode
  265. // Collect all those points that have a current maxLevel less than the
  266. // shell.
  267. pointField candidates(pt.size());
  268. labelList candidateMap(pt.size());
  269. label candidateI = 0;
  270. forAll(maxLevel, pointI)
  271. {
  272. if (levels[0] > maxLevel[pointI])
  273. {
  274. candidates[candidateI] = pt[pointI];
  275. candidateMap[candidateI] = pointI;
  276. candidateI++;
  277. }
  278. }
  279. candidates.setSize(candidateI);
  280. candidateMap.setSize(candidateI);
  281. // Do the expensive nearest test only for the candidate points.
  282. List<volumeType> volType;
  283. allGeometry_[shells_[shellI]].getVolumeType(candidates, volType);
  284. forAll(volType, i)
  285. {
  286. label pointI = candidateMap[i];
  287. if
  288. (
  289. (
  290. modes_[shellI] == INSIDE
  291. && volType[i] == volumeType::INSIDE
  292. )
  293. || (
  294. modes_[shellI] == OUTSIDE
  295. && volType[i] == volumeType::OUTSIDE
  296. )
  297. )
  298. {
  299. maxLevel[pointI] = levels[0];
  300. }
  301. }
  302. }
  303. }
  304. // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
  305. Foam::shellSurfaces::shellSurfaces
  306. (
  307. const searchableSurfaces& allGeometry,
  308. const dictionary& shellsDict
  309. )
  310. :
  311. allGeometry_(allGeometry)
  312. {
  313. // Wilcard specification : loop over all surfaces and try to find a match.
  314. // Count number of shells.
  315. label shellI = 0;
  316. forAll(allGeometry.names(), geomI)
  317. {
  318. const word& geomName = allGeometry_.names()[geomI];
  319. if (shellsDict.found(geomName))
  320. {
  321. shellI++;
  322. }
  323. }
  324. // Size lists
  325. shells_.setSize(shellI);
  326. modes_.setSize(shellI);
  327. distances_.setSize(shellI);
  328. levels_.setSize(shellI);
  329. HashSet<word> unmatchedKeys(shellsDict.toc());
  330. shellI = 0;
  331. forAll(allGeometry_.names(), geomI)
  332. {
  333. const word& geomName = allGeometry_.names()[geomI];
  334. const entry* ePtr = shellsDict.lookupEntryPtr(geomName, false, true);
  335. if (ePtr)
  336. {
  337. const dictionary& dict = ePtr->dict();
  338. unmatchedKeys.erase(ePtr->keyword());
  339. shells_[shellI] = geomI;
  340. modes_[shellI] = refineModeNames_.read(dict.lookup("mode"));
  341. // Read pairs of distance+level
  342. setAndCheckLevels(shellI, dict.lookup("levels"));
  343. shellI++;
  344. }
  345. }
  346. if (unmatchedKeys.size() > 0)
  347. {
  348. IOWarningIn
  349. (
  350. "shellSurfaces::shellSurfaces(..)",
  351. shellsDict
  352. ) << "Not all entries in refinementRegions dictionary were used."
  353. << " The following entries were not used : "
  354. << unmatchedKeys.sortedToc()
  355. << endl;
  356. }
  357. // Orient shell surfaces before any searching is done. Note that this
  358. // only needs to be done for inside or outside. Orienting surfaces
  359. // constructs lots of addressing which we want to avoid.
  360. orient();
  361. }
  362. // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
  363. // Highest shell level
  364. Foam::label Foam::shellSurfaces::maxLevel() const
  365. {
  366. label overallMax = 0;
  367. forAll(levels_, shellI)
  368. {
  369. overallMax = max(overallMax, max(levels_[shellI]));
  370. }
  371. return overallMax;
  372. }
  373. void Foam::shellSurfaces::findHigherLevel
  374. (
  375. const pointField& pt,
  376. const labelList& ptLevel,
  377. labelList& maxLevel
  378. ) const
  379. {
  380. // Maximum level of any shell. Start off with level of point.
  381. maxLevel = ptLevel;
  382. forAll(shells_, shellI)
  383. {
  384. findHigherLevel(pt, shellI, maxLevel);
  385. }
  386. }
  387. // ************************************************************************* //