1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend 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 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
26 \*---------------------------------------------------------------------------*/
28 #include "cellFeatures.H"
29 #include "primitiveMesh.H"
32 #include "demandDrivenData.H"
34 #include "meshTools.H"
36 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
39 // Return true if edge start and end are on increasing face vertices. (edge is
40 // guaranteed to be on face)
41 bool Foam::cellFeatures::faceAlignedEdge(const label faceI, const label edgeI)
44 const edge& e = mesh_.edges()[edgeI];
46 const face& f = mesh_.faces()[faceI];
50 if (f[fp] == e.start())
52 label fp1 = f.fcIndex(fp);
54 return f[fp1] == e.end();
60 "cellFeatures::faceAlignedEdge(const label, const label)"
61 ) << "Can not find edge " << mesh_.edges()[edgeI]
62 << " on face " << faceI << abort(FatalError);
68 // Return edge in featureEdge that uses vertI and is on same superface
70 Foam::label Foam::cellFeatures::nextEdge
72 const Map<label>& toSuperFace,
73 const label superFaceI,
74 const label thisEdgeI,
78 const labelList& pEdges = mesh_.pointEdges()[thisVertI];
80 forAll(pEdges, pEdgeI)
82 label edgeI = pEdges[pEdgeI];
84 if ((edgeI != thisEdgeI) && featureEdge_.found(edgeI))
86 // Check that edge is used by a face on same superFace
88 const labelList& eFaces = mesh_.edgeFaces()[edgeI];
90 forAll(eFaces, eFaceI)
92 label faceI = eFaces[eFaceI];
96 meshTools::faceOnCell(mesh_, cellI_, faceI)
97 && (toSuperFace[faceI] == superFaceI)
108 "cellFeatures::nextEdge(const label, const Map<label>"
109 ", const labelHashSet&, const label, const label, const label)"
110 ) << "Can not find edge in " << featureEdge_ << " connected to edge "
111 << thisEdgeI << " at vertex " << thisVertI << endl
112 << "This might mean that the externalEdges do not form a closed loop"
113 << abort(FatalError);
119 // Return true if angle between faces using it is larger than certain value.
120 bool Foam::cellFeatures::isCellFeatureEdge
126 // Get the two faces using this edge
130 meshTools::getEdgeFaces(mesh_, cellI_, edgeI, face0, face1);
132 // Check the angle between them by comparing the face normals.
134 vector n0 = mesh_.faceAreas()[face0];
137 vector n1 = mesh_.faceAreas()[face1];
140 scalar cosAngle = n0 & n1;
143 const edge& e = mesh_.edges()[edgeI];
145 const face& f0 = mesh_.faces()[face0];
147 label face0Start = findIndex(f0, e.start());
148 label face0End = f0.fcIndex(face0Start);
150 const face& f1 = mesh_.faces()[face1];
152 label face1Start = findIndex(f1, e.start());
153 label face1End = f1.fcIndex(face1Start);
158 (f0[face0End] == e.end())
159 && (f1[face1End] != e.end())
162 (f0[face0End] != e.end())
163 && (f1[face1End] == e.end())
170 cosAngle = -cosAngle;
173 if (cosAngle < minCos)
184 // Recursively mark (on toSuperFace) all face reachable across non-feature
186 void Foam::cellFeatures::walkSuperFace
189 const label superFaceI,
190 Map<label>& toSuperFace
193 if (!toSuperFace.found(faceI))
195 toSuperFace.insert(faceI, superFaceI);
197 const labelList& fEdges = mesh_.faceEdges()[faceI];
199 forAll(fEdges, fEdgeI)
201 label edgeI = fEdges[fEdgeI];
203 if (!featureEdge_.found(edgeI))
207 meshTools::getEdgeFaces(mesh_, cellI_, edgeI, face0, face1);
226 void Foam::cellFeatures::calcSuperFaces() const
228 // Determine superfaces by edge walking across non-feature edges
230 const labelList& cFaces = mesh_.cells()[cellI_];
232 // Mapping from old to super face:
233 // <not found> : not visited
235 Map<label> toSuperFace(10*cFaces.size());
237 label superFaceI = 0;
239 forAll(cFaces, cFaceI)
241 label faceI = cFaces[cFaceI];
243 if (!toSuperFace.found(faceI))
255 // Construct superFace-to-oldface mapping.
257 faceMap_.setSize(superFaceI);
259 forAll(cFaces, cFaceI)
261 label faceI = cFaces[cFaceI];
263 faceMap_[toSuperFace[faceI]].append(faceI);
266 forAll(faceMap_, superI)
268 faceMap_[superI].shrink();
272 // Construct superFaces
274 facesPtr_ = new faceList(superFaceI);
276 faceList& faces = *facesPtr_;
278 forAll(cFaces, cFaceI)
280 label faceI = cFaces[cFaceI];
282 label superFaceI = toSuperFace[faceI];
284 if (faces[superFaceI].empty())
286 // Superface not yet constructed.
288 // Find starting feature edge on face.
289 label startEdgeI = -1;
291 const labelList& fEdges = mesh_.faceEdges()[faceI];
293 forAll(fEdges, fEdgeI)
295 label edgeI = fEdges[fEdgeI];
297 if (featureEdge_.found(edgeI))
306 if (startEdgeI != -1)
308 // Walk point-edge-point along feature edges
310 dynamicLabelList superFace(10*mesh_.faces()[faceI].size());
312 const edge& e = mesh_.edges()[startEdgeI];
314 // Walk either start-end or end-start depending on orientation
315 // of face. SuperFace will have cellI as owner.
316 bool flipOrientation =
317 (mesh_.faceOwner()[faceI] == cellI_)
318 ^ (faceAlignedEdge(faceI, startEdgeI));
320 label startVertI = -1;
324 startVertI = e.end();
328 startVertI = e.start();
331 label edgeI = startEdgeI;
333 label vertI = e.otherVertex(startVertI);
337 label newEdgeI = nextEdge
345 // Determine angle between edges.
346 if (isFeaturePoint(edgeI, newEdgeI))
348 superFace.append(vertI);
353 if (vertI == startVertI)
358 vertI = mesh_.edges()[edgeI].otherVertex(vertI);
362 if (superFace.size() <= 2)
364 WarningIn("cellFeatures::calcSuperFaces")
365 << " Can not collapse faces " << faceMap_[superFaceI]
366 << " into one big face on cell " << cellI_ << endl
367 << "Try decreasing minCos:" << minCos_ << endl;
371 faces[superFaceI].transfer(superFace);
379 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
381 // Construct from components
382 Foam::cellFeatures::cellFeatures
384 const primitiveMesh& mesh,
392 featureEdge_(10*mesh.cellEdges()[cellI].size()),
396 const labelList& cEdges = mesh_.cellEdges()[cellI_];
398 forAll(cEdges, cEdgeI)
400 label edgeI = cEdges[cEdgeI];
402 if (isCellFeatureEdge(minCos_, edgeI))
404 featureEdge_.insert(edgeI);
411 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
413 Foam::cellFeatures::~cellFeatures()
415 deleteDemandDrivenData(facesPtr_);
419 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
421 bool Foam::cellFeatures::isFeaturePoint(const label edge0, const label edge1)
427 || (edge0 >= mesh_.nEdges())
429 || (edge1 >= mesh_.nEdges())
434 "cellFeatures::isFeatureVertex(const label, const label)"
435 ) << "Illegal edge labels : edge0:" << edge0 << " edge1:" << edge1
436 << abort(FatalError);
439 const edge& e0 = mesh_.edges()[edge0];
441 vector e0Vec = e0.vec(mesh_.points());
444 const edge& e1 = mesh_.edges()[edge1];
446 vector e1Vec = e1.vec(mesh_.points());
453 (e0.start() == e1.end())
454 || (e0.end() == e1.start())
458 cosAngle = e0Vec & e1Vec;
462 (e0.start() == e1.start())
463 || (e0.end() == e1.end())
467 cosAngle = - e0Vec & e1Vec;
471 cosAngle = GREAT; // satisfy compiler
475 "cellFeatures::isFeaturePoint(const label, const label"
477 ) << "Edges do not share common vertex. e0:" << e0
478 << " e1:" << e1 << abort(FatalError);
481 if (cosAngle < minCos_)
483 // Angle larger than criterium
493 bool Foam::cellFeatures::isFeatureVertex(const label faceI, const label vertI)
499 || (faceI >= mesh_.nFaces())
501 || (vertI >= mesh_.nPoints())
506 "cellFeatures::isFeatureVertex(const label, const label)"
507 ) << "Illegal face " << faceI << " or vertex " << vertI
508 << abort(FatalError);
511 const labelList& pEdges = mesh_.pointEdges()[vertI];
516 forAll(pEdges, pEdgeI)
518 label edgeI = pEdges[pEdgeI];
520 if (meshTools::edgeOnFace(mesh_, faceI, edgeI))
530 // Found the two edges.
540 "cellFeatures::isFeatureVertex(const label, const label)"
541 ) << "Did not find two edges sharing vertex " << vertI
542 << " on face " << faceI << " vertices:" << mesh_.faces()[faceI]
543 << abort(FatalError);
546 return isFeaturePoint(edge0, edge1);
550 // ************************************************************************* //