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
00027
00028 #include "cellFeatures.H"
00029 #include <OpenFOAM/primitiveMesh.H>
00030 #include <OpenFOAM/HashSet.H>
00031 #include <OpenFOAM/Map.H>
00032 #include <OpenFOAM/demandDrivenData.H>
00033 #include <OpenFOAM/ListOps.H>
00034 #include <meshTools/meshTools.H>
00035
00036
00037
00038
00039
00040
00041 bool Foam::cellFeatures::faceAlignedEdge(const label faceI, const label edgeI)
00042 const
00043 {
00044 const edge& e = mesh_.edges()[edgeI];
00045
00046 const face& f = mesh_.faces()[faceI];
00047
00048 forAll(f, fp)
00049 {
00050 if (f[fp] == e.start())
00051 {
00052 label fp1 = f.fcIndex(fp);
00053
00054 return f[fp1] == e.end();
00055 }
00056 }
00057
00058 FatalErrorIn
00059 (
00060 "cellFeatures::faceAlignedEdge(const label, const label)"
00061 ) << "Can not find edge " << mesh_.edges()[edgeI]
00062 << " on face " << faceI << abort(FatalError);
00063
00064 return false;
00065 }
00066
00067
00068
00069
00070 Foam::label Foam::cellFeatures::nextEdge
00071 (
00072 const Map<label>& toSuperFace,
00073 const label superFaceI,
00074 const label thisEdgeI,
00075 const label thisVertI
00076 ) const
00077 {
00078 const labelList& pEdges = mesh_.pointEdges()[thisVertI];
00079
00080 forAll(pEdges, pEdgeI)
00081 {
00082 label edgeI = pEdges[pEdgeI];
00083
00084 if ((edgeI != thisEdgeI) && featureEdge_.found(edgeI))
00085 {
00086
00087
00088 const labelList& eFaces = mesh_.edgeFaces()[edgeI];
00089
00090 forAll(eFaces, eFaceI)
00091 {
00092 label faceI = eFaces[eFaceI];
00093
00094 if
00095 (
00096 meshTools::faceOnCell(mesh_, cellI_, faceI)
00097 && (toSuperFace[faceI] == superFaceI)
00098 )
00099 {
00100 return edgeI;
00101 }
00102 }
00103 }
00104 }
00105
00106 FatalErrorIn
00107 (
00108 "cellFeatures::nextEdge(const label, const Map<label>"
00109 ", const labelHashSet&, const label, const label, const label)"
00110 ) << "Can not find edge in " << featureEdge_ << " connected to edge "
00111 << thisEdgeI << " at vertex " << thisVertI << endl
00112 << "This might mean that the externalEdges do not form a closed loop"
00113 << abort(FatalError);
00114
00115 return -1;
00116 }
00117
00118
00119
00120 bool Foam::cellFeatures::isCellFeatureEdge
00121 (
00122 const scalar minCos,
00123 const label edgeI
00124 ) const
00125 {
00126
00127
00128 label face0;
00129 label face1;
00130 meshTools::getEdgeFaces(mesh_, cellI_, edgeI, face0, face1);
00131
00132
00133
00134 vector n0 = mesh_.faceAreas()[face0];
00135 n0 /= mag(n0);
00136
00137 vector n1 = mesh_.faceAreas()[face1];
00138 n1 /= mag(n1);
00139
00140 scalar cosAngle = n0 & n1;
00141
00142
00143 const edge& e = mesh_.edges()[edgeI];
00144
00145 const face& f0 = mesh_.faces()[face0];
00146
00147 label face0Start = findIndex(f0, e.start());
00148 label face0End = f0.fcIndex(face0Start);
00149
00150 const face& f1 = mesh_.faces()[face1];
00151
00152 label face1Start = findIndex(f1, e.start());
00153 label face1End = f1.fcIndex(face1Start);
00154
00155 if
00156 (
00157 (
00158 (f0[face0End] == e.end())
00159 && (f1[face1End] != e.end())
00160 )
00161 || (
00162 (f0[face0End] != e.end())
00163 && (f1[face1End] == e.end())
00164 )
00165 )
00166 {
00167 }
00168 else
00169 {
00170 cosAngle = -cosAngle;
00171 }
00172
00173 if (cosAngle < minCos)
00174 {
00175 return true;
00176 }
00177 else
00178 {
00179 return false;
00180 }
00181 }
00182
00183
00184
00185
00186 void Foam::cellFeatures::walkSuperFace
00187 (
00188 const label faceI,
00189 const label superFaceI,
00190 Map<label>& toSuperFace
00191 ) const
00192 {
00193 if (!toSuperFace.found(faceI))
00194 {
00195 toSuperFace.insert(faceI, superFaceI);
00196
00197 const labelList& fEdges = mesh_.faceEdges()[faceI];
00198
00199 forAll(fEdges, fEdgeI)
00200 {
00201 label edgeI = fEdges[fEdgeI];
00202
00203 if (!featureEdge_.found(edgeI))
00204 {
00205 label face0;
00206 label face1;
00207 meshTools::getEdgeFaces(mesh_, cellI_, edgeI, face0, face1);
00208
00209 if (face0 == faceI)
00210 {
00211 face0 = face1;
00212 }
00213
00214 walkSuperFace
00215 (
00216 face0,
00217 superFaceI,
00218 toSuperFace
00219 );
00220 }
00221 }
00222 }
00223 }
00224
00225
00226 void Foam::cellFeatures::calcSuperFaces() const
00227 {
00228
00229
00230 const labelList& cFaces = mesh_.cells()[cellI_];
00231
00232
00233
00234
00235 Map<label> toSuperFace(10*cFaces.size());
00236
00237 label superFaceI = 0;
00238
00239 forAll(cFaces, cFaceI)
00240 {
00241 label faceI = cFaces[cFaceI];
00242
00243 if (!toSuperFace.found(faceI))
00244 {
00245 walkSuperFace
00246 (
00247 faceI,
00248 superFaceI,
00249 toSuperFace
00250 );
00251 superFaceI++;
00252 }
00253 }
00254
00255
00256
00257 faceMap_.setSize(superFaceI);
00258
00259 forAll(cFaces, cFaceI)
00260 {
00261 label faceI = cFaces[cFaceI];
00262
00263 faceMap_[toSuperFace[faceI]].append(faceI);
00264 }
00265
00266 forAll(faceMap_, superI)
00267 {
00268 faceMap_[superI].shrink();
00269 }
00270
00271
00272
00273
00274 facesPtr_ = new faceList(superFaceI);
00275
00276 faceList& faces = *facesPtr_;
00277
00278 forAll(cFaces, cFaceI)
00279 {
00280 label faceI = cFaces[cFaceI];
00281
00282 label superFaceI = toSuperFace[faceI];
00283
00284 if (faces[superFaceI].empty())
00285 {
00286
00287
00288
00289 label startEdgeI = -1;
00290
00291 const labelList& fEdges = mesh_.faceEdges()[faceI];
00292
00293 forAll(fEdges, fEdgeI)
00294 {
00295 label edgeI = fEdges[fEdgeI];
00296
00297 if (featureEdge_.found(edgeI))
00298 {
00299 startEdgeI = edgeI;
00300
00301 break;
00302 }
00303 }
00304
00305
00306 if (startEdgeI != -1)
00307 {
00308
00309
00310 DynamicList<label> superFace(10*mesh_.faces()[faceI].size());
00311
00312 const edge& e = mesh_.edges()[startEdgeI];
00313
00314
00315
00316 bool flipOrientation =
00317 (mesh_.faceOwner()[faceI] == cellI_)
00318 ^ (faceAlignedEdge(faceI, startEdgeI));
00319
00320 label startVertI = -1;
00321
00322 if (flipOrientation)
00323 {
00324 startVertI = e.end();
00325 }
00326 else
00327 {
00328 startVertI = e.start();
00329 }
00330
00331 label edgeI = startEdgeI;
00332
00333 label vertI = e.otherVertex(startVertI);
00334
00335 do
00336 {
00337 label newEdgeI = nextEdge
00338 (
00339 toSuperFace,
00340 superFaceI,
00341 edgeI,
00342 vertI
00343 );
00344
00345
00346 if (isFeaturePoint(edgeI, newEdgeI))
00347 {
00348 superFace.append(vertI);
00349 }
00350
00351 edgeI = newEdgeI;
00352
00353 if (vertI == startVertI)
00354 {
00355 break;
00356 }
00357
00358 vertI = mesh_.edges()[edgeI].otherVertex(vertI);
00359 }
00360 while (true);
00361
00362 if (superFace.size() <= 2)
00363 {
00364 WarningIn("cellFeatures::calcSuperFaces")
00365 << " Can not collapse faces " << faceMap_[superFaceI]
00366 << " into one big face on cell " << cellI_ << endl
00367 << "Try decreasing minCos:" << minCos_ << endl;
00368 }
00369 else
00370 {
00371 faces[superFaceI].transfer(superFace);
00372 }
00373 }
00374 }
00375 }
00376 }
00377
00378
00379
00380
00381
00382 Foam::cellFeatures::cellFeatures
00383 (
00384 const primitiveMesh& mesh,
00385 const scalar minCos,
00386 const label cellI
00387 )
00388 :
00389 mesh_(mesh),
00390 minCos_(minCos),
00391 cellI_(cellI),
00392 featureEdge_(10*mesh.cellEdges()[cellI].size()),
00393 facesPtr_(NULL),
00394 faceMap_(0)
00395 {
00396 const labelList& cEdges = mesh_.cellEdges()[cellI_];
00397
00398 forAll(cEdges, cEdgeI)
00399 {
00400 label edgeI = cEdges[cEdgeI];
00401
00402 if (isCellFeatureEdge(minCos_, edgeI))
00403 {
00404 featureEdge_.insert(edgeI);
00405 }
00406 }
00407
00408 }
00409
00410
00411
00412
00413 Foam::cellFeatures::~cellFeatures()
00414 {
00415 deleteDemandDrivenData(facesPtr_);
00416 }
00417
00418
00419
00420
00421 bool Foam::cellFeatures::isFeaturePoint(const label edge0, const label edge1)
00422 const
00423 {
00424 if
00425 (
00426 (edge0 < 0)
00427 || (edge0 >= mesh_.nEdges())
00428 || (edge1 < 0)
00429 || (edge1 >= mesh_.nEdges())
00430 )
00431 {
00432 FatalErrorIn
00433 (
00434 "cellFeatures::isFeatureVertex(const label, const label)"
00435 ) << "Illegal edge labels : edge0:" << edge0 << " edge1:" << edge1
00436 << abort(FatalError);
00437 }
00438
00439 const edge& e0 = mesh_.edges()[edge0];
00440
00441 vector e0Vec = e0.vec(mesh_.points());
00442 e0Vec /= mag(e0Vec);
00443
00444 const edge& e1 = mesh_.edges()[edge1];
00445
00446 vector e1Vec = e1.vec(mesh_.points());
00447 e1Vec /= mag(e1Vec);
00448
00449 scalar cosAngle;
00450
00451 if
00452 (
00453 (e0.start() == e1.end())
00454 || (e0.end() == e1.start())
00455 )
00456 {
00457
00458 cosAngle = e0Vec & e1Vec;
00459 }
00460 else if
00461 (
00462 (e0.start() == e1.start())
00463 || (e0.end() == e1.end())
00464 )
00465 {
00466
00467 cosAngle = - e0Vec & e1Vec;
00468 }
00469 else
00470 {
00471 cosAngle = GREAT;
00472
00473 FatalErrorIn
00474 (
00475 "cellFeatures::isFeaturePoint(const label, const label"
00476 ", const label)"
00477 ) << "Edges do not share common vertex. e0:" << e0
00478 << " e1:" << e1 << abort(FatalError);
00479 }
00480
00481 if (cosAngle < minCos_)
00482 {
00483
00484 return true;
00485 }
00486 else
00487 {
00488 return false;
00489 }
00490 }
00491
00492
00493 bool Foam::cellFeatures::isFeatureVertex(const label faceI, const label vertI)
00494 const
00495 {
00496 if
00497 (
00498 (faceI < 0)
00499 || (faceI >= mesh_.nFaces())
00500 || (vertI < 0)
00501 || (vertI >= mesh_.nPoints())
00502 )
00503 {
00504 FatalErrorIn
00505 (
00506 "cellFeatures::isFeatureVertex(const label, const label)"
00507 ) << "Illegal face " << faceI << " or vertex " << vertI
00508 << abort(FatalError);
00509 }
00510
00511 const labelList& pEdges = mesh_.pointEdges()[vertI];
00512
00513 label edge0 = -1;
00514 label edge1 = -1;
00515
00516 forAll(pEdges, pEdgeI)
00517 {
00518 label edgeI = pEdges[pEdgeI];
00519
00520 if (meshTools::edgeOnFace(mesh_, faceI, edgeI))
00521 {
00522 if (edge0 == -1)
00523 {
00524 edge0 = edgeI;
00525 }
00526 else
00527 {
00528 edge1 = edgeI;
00529
00530
00531 break;
00532 }
00533 }
00534 }
00535
00536 if (edge1 == -1)
00537 {
00538 FatalErrorIn
00539 (
00540 "cellFeatures::isFeatureVertex(const label, const label)"
00541 ) << "Did not find two edges sharing vertex " << vertI
00542 << " on face " << faceI << " vertices:" << mesh_.faces()[faceI]
00543 << abort(FatalError);
00544 }
00545
00546 return isFeaturePoint(edge0, edge1);
00547 }
00548
00549
00550