00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <meshTools/searchableSurface.H>
00027 #include "shellSurfaces.H"
00028 #include <OpenFOAM/boundBox.H>
00029 #include <meshTools/triSurfaceMesh.H>
00030 #include <autoMesh/refinementSurfaces.H>
00031 #include <meshTools/searchableSurfaces.H>
00032 #include <meshTools/orientedSurface.H>
00033 #include <meshTools/pointIndexHit.H>
00034
00035
00036
00037
00038 namespace Foam
00039 {
00040
00041 template<>
00042 const char*
00043 NamedEnum<shellSurfaces::refineMode, 3>::
00044 names[] =
00045 {
00046 "inside",
00047 "outside",
00048 "distance"
00049 };
00050
00051 const NamedEnum<shellSurfaces::refineMode, 3> shellSurfaces::refineModeNames_;
00052
00053 }
00054
00055
00056
00057
00058
00059 void Foam::shellSurfaces::setAndCheckLevels
00060 (
00061 const label shellI,
00062 const List<Tuple2<scalar, label> >& distLevels
00063 )
00064 {
00065 if (modes_[shellI] != DISTANCE && distLevels.size() != 1)
00066 {
00067 FatalErrorIn
00068 (
00069 "shellSurfaces::shellSurfaces"
00070 "(const searchableSurfaces&, const dictionary&)"
00071 ) << "For refinement mode "
00072 << refineModeNames_[modes_[shellI]]
00073 << " specify only one distance+level."
00074 << " (its distance gets discarded)"
00075 << exit(FatalError);
00076 }
00077
00078 distances_[shellI].setSize(distLevels.size());
00079 levels_[shellI].setSize(distLevels.size());
00080
00081 forAll(distLevels, j)
00082 {
00083 distances_[shellI][j] = distLevels[j].first();
00084 levels_[shellI][j] = distLevels[j].second();
00085
00086
00087 if (j > 0)
00088 {
00089 if
00090 (
00091 (distances_[shellI][j] <= distances_[shellI][j-1])
00092 || (levels_[shellI][j] > levels_[shellI][j-1])
00093 )
00094 {
00095 FatalErrorIn
00096 (
00097 "shellSurfaces::shellSurfaces"
00098 "(const searchableSurfaces&, const dictionary&)"
00099 ) << "For refinement mode "
00100 << refineModeNames_[modes_[shellI]]
00101 << " : Refinement should be specified in order"
00102 << " of increasing distance"
00103 << " (and decreasing refinement level)." << endl
00104 << "Distance:" << distances_[shellI][j]
00105 << " refinementLevel:" << levels_[shellI][j]
00106 << exit(FatalError);
00107 }
00108 }
00109 }
00110
00111 const searchableSurface& shell = allGeometry_[shells_[shellI]];
00112
00113 if (modes_[shellI] == DISTANCE)
00114 {
00115 Info<< "Refinement level according to distance to "
00116 << shell.name() << endl;
00117 forAll(levels_[shellI], j)
00118 {
00119 Info<< " level " << levels_[shellI][j]
00120 << " for all cells within " << distances_[shellI][j]
00121 << " meter." << endl;
00122 }
00123 }
00124 else
00125 {
00126 if (!allGeometry_[shells_[shellI]].hasVolumeType())
00127 {
00128 FatalErrorIn
00129 (
00130 "shellSurfaces::shellSurfaces"
00131 "(const searchableSurfaces&"
00132 ", const PtrList<dictionary>&)"
00133 ) << "Shell " << shell.name()
00134 << " does not support testing for "
00135 << refineModeNames_[modes_[shellI]] << endl
00136 << "Probably it is not closed."
00137 << exit(FatalError);
00138 }
00139
00140 if (modes_[shellI] == INSIDE)
00141 {
00142 Info<< "Refinement level " << levels_[shellI][0]
00143 << " for all cells inside " << shell.name() << endl;
00144 }
00145 else
00146 {
00147 Info<< "Refinement level " << levels_[shellI][0]
00148 << " for all cells outside " << shell.name() << endl;
00149 }
00150 }
00151 }
00152
00153
00154
00155
00156
00157 void Foam::shellSurfaces::orient()
00158 {
00159
00160 boundBox overallBb = boundBox::invertedBox;
00161
00162 bool hasSurface = false;
00163
00164 forAll(shells_, shellI)
00165 {
00166 const searchableSurface& s = allGeometry_[shells_[shellI]];
00167
00168 if (modes_[shellI] != DISTANCE && isA<triSurfaceMesh>(s))
00169 {
00170 const triSurfaceMesh& shell = refCast<const triSurfaceMesh>(s);
00171
00172 if (shell.triSurface::size())
00173 {
00174 const pointField& points = shell.points();
00175
00176 hasSurface = true;
00177
00178 boundBox shellBb(points[0], points[0]);
00179
00180 for (label i = 0; i < points.size(); i++)
00181 {
00182 const point& pt = points[i];
00183 shellBb.min() = min(shellBb.min(), pt);
00184 shellBb.max() = max(shellBb.max(), pt);
00185 }
00186
00187 overallBb.min() = min(overallBb.min(), shellBb.min());
00188 overallBb.max() = max(overallBb.max(), shellBb.max());
00189 }
00190 }
00191 }
00192
00193 if (hasSurface)
00194 {
00195 const point outsidePt = overallBb.max() + overallBb.span();
00196
00197
00198
00199 forAll(shells_, shellI)
00200 {
00201 const searchableSurface& s = allGeometry_[shells_[shellI]];
00202
00203 if (modes_[shellI] != DISTANCE && isA<triSurfaceMesh>(s))
00204 {
00205 triSurfaceMesh& shell = const_cast<triSurfaceMesh&>
00206 (
00207 refCast<const triSurfaceMesh>(s)
00208 );
00209
00210
00211 bool anyFlipped = orientedSurface::orient
00212 (
00213 shell,
00214 outsidePt,
00215 true
00216 );
00217
00218 if (anyFlipped)
00219 {
00220
00221
00222
00223
00224
00225
00226
00227 Info<< "shellSurfaces : Flipped orientation of surface "
00228 << s.name()
00229 << " so point " << outsidePt << " is outside." << endl;
00230 }
00231 }
00232 }
00233 }
00234 }
00235
00236
00237
00238 void Foam::shellSurfaces::findHigherLevel
00239 (
00240 const pointField& pt,
00241 const label shellI,
00242 labelList& maxLevel
00243 ) const
00244 {
00245 const labelList& levels = levels_[shellI];
00246
00247 if (modes_[shellI] == DISTANCE)
00248 {
00249
00250
00251 const scalarField& distances = distances_[shellI];
00252
00253
00254
00255
00256
00257 pointField candidates(pt.size());
00258 labelList candidateMap(pt.size());
00259 scalarField candidateDistSqr(pt.size());
00260 label candidateI = 0;
00261
00262 forAll(maxLevel, pointI)
00263 {
00264 forAllReverse(levels, levelI)
00265 {
00266 if (levels[levelI] > maxLevel[pointI])
00267 {
00268 candidates[candidateI] = pt[pointI];
00269 candidateMap[candidateI] = pointI;
00270 candidateDistSqr[candidateI] = sqr(distances[levelI]);
00271 candidateI++;
00272 break;
00273 }
00274 }
00275 }
00276 candidates.setSize(candidateI);
00277 candidateMap.setSize(candidateI);
00278 candidateDistSqr.setSize(candidateI);
00279
00280
00281 List<pointIndexHit> nearInfo;
00282 allGeometry_[shells_[shellI]].findNearest
00283 (
00284 candidates,
00285 candidateDistSqr,
00286 nearInfo
00287 );
00288
00289
00290 forAll(nearInfo, candidateI)
00291 {
00292 if (nearInfo[candidateI].hit())
00293 {
00294
00295 label minDistI = findLower
00296 (
00297 distances,
00298 mag(nearInfo[candidateI].hitPoint()-candidates[candidateI])
00299 );
00300
00301 label pointI = candidateMap[candidateI];
00302
00303
00304 maxLevel[pointI] = levels[minDistI+1];
00305 }
00306 }
00307 }
00308 else
00309 {
00310
00311
00312
00313
00314
00315 pointField candidates(pt.size());
00316 labelList candidateMap(pt.size());
00317 label candidateI = 0;
00318
00319 forAll(maxLevel, pointI)
00320 {
00321 if (levels[0] > maxLevel[pointI])
00322 {
00323 candidates[candidateI] = pt[pointI];
00324 candidateMap[candidateI] = pointI;
00325 candidateI++;
00326 }
00327 }
00328 candidates.setSize(candidateI);
00329 candidateMap.setSize(candidateI);
00330
00331
00332 List<searchableSurface::volumeType> volType;
00333 allGeometry_[shells_[shellI]].getVolumeType(candidates, volType);
00334
00335 forAll(volType, i)
00336 {
00337 label pointI = candidateMap[i];
00338
00339 if
00340 (
00341 (
00342 modes_[shellI] == INSIDE
00343 && volType[i] == searchableSurface::INSIDE
00344 )
00345 || (
00346 modes_[shellI] == OUTSIDE
00347 && volType[i] == searchableSurface::OUTSIDE
00348 )
00349 )
00350 {
00351 maxLevel[pointI] = levels[0];
00352 }
00353 }
00354 }
00355 }
00356
00357
00358
00359
00360 Foam::shellSurfaces::shellSurfaces
00361 (
00362 const searchableSurfaces& allGeometry,
00363 const PtrList<dictionary>& shellDicts
00364 )
00365 :
00366 allGeometry_(allGeometry)
00367 {
00368 shells_.setSize(shellDicts.size());
00369 modes_.setSize(shellDicts.size());
00370 distances_.setSize(shellDicts.size());
00371 levels_.setSize(shellDicts.size());
00372
00373 forAll(shellDicts, shellI)
00374 {
00375 const dictionary& dict = shellDicts[shellI];
00376 const word name = dict.lookup("name");
00377 const word type = dict.lookup("type");
00378
00379 shells_[shellI] = allGeometry_.findSurfaceID(name);
00380
00381 if (shells_[shellI] == -1)
00382 {
00383 FatalErrorIn
00384 (
00385 "shellSurfaces::shellSurfaces"
00386 "(const searchableSurfaces&, const PtrList<dictionary>&)"
00387 ) << "No surface called " << name << endl
00388 << "Valid surfaces are " << allGeometry_.names()
00389 << exit(FatalError);
00390 }
00391
00392 modes_[shellI] = refineModeNames_.read(dict.lookup("refineMode"));
00393
00394
00395 setAndCheckLevels(shellI, dict.lookup("levels"));
00396 }
00397
00398
00399
00400
00401 orient();
00402 }
00403
00404
00405 Foam::shellSurfaces::shellSurfaces
00406 (
00407 const searchableSurfaces& allGeometry,
00408 const dictionary& shellsDict
00409 )
00410 :
00411 allGeometry_(allGeometry)
00412 {
00413 shells_.setSize(shellsDict.size());
00414 modes_.setSize(shellsDict.size());
00415 distances_.setSize(shellsDict.size());
00416 levels_.setSize(shellsDict.size());
00417
00418 label shellI = 0;
00419 forAllConstIter(dictionary, shellsDict, iter)
00420 {
00421 shells_[shellI] = allGeometry_.findSurfaceID(iter().keyword());
00422
00423 if (shells_[shellI] == -1)
00424 {
00425 FatalErrorIn
00426 (
00427 "shellSurfaces::shellSurfaces"
00428 "(const searchableSurfaces&, const dictionary>&"
00429 ) << "No surface called " << iter().keyword() << endl
00430 << "Valid surfaces are " << allGeometry_.names()
00431 << exit(FatalError);
00432 }
00433 const dictionary& dict = shellsDict.subDict(iter().keyword());
00434
00435 modes_[shellI] = refineModeNames_.read(dict.lookup("mode"));
00436
00437
00438 setAndCheckLevels(shellI, dict.lookup("levels"));
00439
00440 shellI++;
00441 }
00442
00443
00444
00445
00446 orient();
00447 }
00448
00449
00450
00451
00452
00453 Foam::label Foam::shellSurfaces::maxLevel() const
00454 {
00455 label overallMax = 0;
00456 forAll(levels_, shellI)
00457 {
00458 overallMax = max(overallMax, max(levels_[shellI]));
00459 }
00460 return overallMax;
00461 }
00462
00463
00464 void Foam::shellSurfaces::findHigherLevel
00465 (
00466 const pointField& pt,
00467 const labelList& ptLevel,
00468 labelList& maxLevel
00469 ) const
00470 {
00471
00472 maxLevel = ptLevel;
00473
00474 forAll(shells_, shellI)
00475 {
00476 findHigherLevel(pt, shellI, maxLevel);
00477 }
00478 }
00479
00480
00481