1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2004-2010 OpenCFD Ltd.
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
13 the Free Software Foundation, either version 3 of the License, or
14 (at your 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, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "cellFeatures.H"
27 #include "primitiveMesh.H"
30 #include "demandDrivenData.H"
32 #include "meshTools.H"
34 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
37 // Return true if edge start and end are on increasing face vertices. (edge is
38 // guaranteed to be on face)
39 bool Foam::cellFeatures::faceAlignedEdge(const label faceI, const label edgeI)
42 const edge& e = mesh_.edges()[edgeI];
44 const face& f = mesh_.faces()[faceI];
48 if (f[fp] == e.start())
50 label fp1 = f.fcIndex(fp);
52 return f[fp1] == e.end();
58 "cellFeatures::faceAlignedEdge(const label, const label)"
59 ) << "Can not find edge " << mesh_.edges()[edgeI]
60 << " on face " << faceI << abort(FatalError);
66 // Return edge in featureEdge that uses vertI and is on same superface
68 Foam::label Foam::cellFeatures::nextEdge
70 const Map<label>& toSuperFace,
71 const label superFaceI,
72 const label thisEdgeI,
76 const labelList& pEdges = mesh_.pointEdges()[thisVertI];
78 forAll(pEdges, pEdgeI)
80 label edgeI = pEdges[pEdgeI];
82 if ((edgeI != thisEdgeI) && featureEdge_.found(edgeI))
84 // Check that edge is used by a face on same superFace
86 const labelList& eFaces = mesh_.edgeFaces()[edgeI];
88 forAll(eFaces, eFaceI)
90 label faceI = eFaces[eFaceI];
94 meshTools::faceOnCell(mesh_, cellI_, faceI)
95 && (toSuperFace[faceI] == superFaceI)
106 "cellFeatures::nextEdge(const label, const Map<label>"
107 ", const labelHashSet&, const label, const label, const label)"
108 ) << "Can not find edge in " << featureEdge_ << " connected to edge "
109 << thisEdgeI << " at vertex " << thisVertI << endl
110 << "This might mean that the externalEdges do not form a closed loop"
111 << abort(FatalError);
117 // Return true if angle between faces using it is larger than certain value.
118 bool Foam::cellFeatures::isCellFeatureEdge
124 // Get the two faces using this edge
128 meshTools::getEdgeFaces(mesh_, cellI_, edgeI, face0, face1);
130 // Check the angle between them by comparing the face normals.
132 vector n0 = mesh_.faceAreas()[face0];
135 vector n1 = mesh_.faceAreas()[face1];
138 scalar cosAngle = n0 & n1;
141 const edge& e = mesh_.edges()[edgeI];
143 const face& f0 = mesh_.faces()[face0];
145 label face0Start = findIndex(f0, e.start());
146 label face0End = f0.fcIndex(face0Start);
148 const face& f1 = mesh_.faces()[face1];
150 label face1Start = findIndex(f1, e.start());
151 label face1End = f1.fcIndex(face1Start);
156 (f0[face0End] == e.end())
157 && (f1[face1End] != e.end())
160 (f0[face0End] != e.end())
161 && (f1[face1End] == e.end())
168 cosAngle = -cosAngle;
171 if (cosAngle < minCos)
182 // Recursively mark (on toSuperFace) all face reachable across non-feature
184 void Foam::cellFeatures::walkSuperFace
187 const label superFaceI,
188 Map<label>& toSuperFace
191 if (!toSuperFace.found(faceI))
193 toSuperFace.insert(faceI, superFaceI);
195 const labelList& fEdges = mesh_.faceEdges()[faceI];
197 forAll(fEdges, fEdgeI)
199 label edgeI = fEdges[fEdgeI];
201 if (!featureEdge_.found(edgeI))
205 meshTools::getEdgeFaces(mesh_, cellI_, edgeI, face0, face1);
224 void Foam::cellFeatures::calcSuperFaces() const
226 // Determine superfaces by edge walking across non-feature edges
228 const labelList& cFaces = mesh_.cells()[cellI_];
230 // Mapping from old to super face:
231 // <not found> : not visited
233 Map<label> toSuperFace(10*cFaces.size());
235 label superFaceI = 0;
237 forAll(cFaces, cFaceI)
239 label faceI = cFaces[cFaceI];
241 if (!toSuperFace.found(faceI))
253 // Construct superFace-to-oldface mapping.
255 faceMap_.setSize(superFaceI);
257 forAll(cFaces, cFaceI)
259 label faceI = cFaces[cFaceI];
261 faceMap_[toSuperFace[faceI]].append(faceI);
264 forAll(faceMap_, superI)
266 faceMap_[superI].shrink();
270 // Construct superFaces
272 facesPtr_ = new faceList(superFaceI);
274 faceList& faces = *facesPtr_;
276 forAll(cFaces, cFaceI)
278 label faceI = cFaces[cFaceI];
280 label superFaceI = toSuperFace[faceI];
282 if (faces[superFaceI].empty())
284 // Superface not yet constructed.
286 // Find starting feature edge on face.
287 label startEdgeI = -1;
289 const labelList& fEdges = mesh_.faceEdges()[faceI];
291 forAll(fEdges, fEdgeI)
293 label edgeI = fEdges[fEdgeI];
295 if (featureEdge_.found(edgeI))
304 if (startEdgeI != -1)
306 // Walk point-edge-point along feature edges
308 DynamicList<label> superFace(10*mesh_.faces()[faceI].size());
310 const edge& e = mesh_.edges()[startEdgeI];
312 // Walk either start-end or end-start depending on orientation
313 // of face. SuperFace will have cellI as owner.
314 bool flipOrientation =
315 (mesh_.faceOwner()[faceI] == cellI_)
316 ^ (faceAlignedEdge(faceI, startEdgeI));
318 label startVertI = -1;
322 startVertI = e.end();
326 startVertI = e.start();
329 label edgeI = startEdgeI;
331 label vertI = e.otherVertex(startVertI);
335 label newEdgeI = nextEdge
343 // Determine angle between edges.
344 if (isFeaturePoint(edgeI, newEdgeI))
346 superFace.append(vertI);
351 if (vertI == startVertI)
356 vertI = mesh_.edges()[edgeI].otherVertex(vertI);
360 if (superFace.size() <= 2)
362 WarningIn("cellFeatures::calcSuperFaces")
363 << " Can not collapse faces " << faceMap_[superFaceI]
364 << " into one big face on cell " << cellI_ << endl
365 << "Try decreasing minCos:" << minCos_ << endl;
369 faces[superFaceI].transfer(superFace);
377 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
379 // Construct from components
380 Foam::cellFeatures::cellFeatures
382 const primitiveMesh& mesh,
390 featureEdge_(10*mesh.cellEdges()[cellI].size()),
394 const labelList& cEdges = mesh_.cellEdges()[cellI_];
396 forAll(cEdges, cEdgeI)
398 label edgeI = cEdges[cEdgeI];
400 if (isCellFeatureEdge(minCos_, edgeI))
402 featureEdge_.insert(edgeI);
409 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
411 Foam::cellFeatures::~cellFeatures()
413 deleteDemandDrivenData(facesPtr_);
417 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
419 bool Foam::cellFeatures::isFeaturePoint(const label edge0, const label edge1)
425 || (edge0 >= mesh_.nEdges())
427 || (edge1 >= mesh_.nEdges())
432 "cellFeatures::isFeatureVertex(const label, const label)"
433 ) << "Illegal edge labels : edge0:" << edge0 << " edge1:" << edge1
434 << abort(FatalError);
437 const edge& e0 = mesh_.edges()[edge0];
439 vector e0Vec = e0.vec(mesh_.points());
442 const edge& e1 = mesh_.edges()[edge1];
444 vector e1Vec = e1.vec(mesh_.points());
451 (e0.start() == e1.end())
452 || (e0.end() == e1.start())
456 cosAngle = e0Vec & e1Vec;
460 (e0.start() == e1.start())
461 || (e0.end() == e1.end())
465 cosAngle = - e0Vec & e1Vec;
469 cosAngle = GREAT; // satisfy compiler
473 "cellFeatures::isFeaturePoint(const label, const label"
475 ) << "Edges do not share common vertex. e0:" << e0
476 << " e1:" << e1 << abort(FatalError);
479 if (cosAngle < minCos_)
481 // Angle larger than criterium
491 bool Foam::cellFeatures::isFeatureVertex(const label faceI, const label vertI)
497 || (faceI >= mesh_.nFaces())
499 || (vertI >= mesh_.nPoints())
504 "cellFeatures::isFeatureVertex(const label, const label)"
505 ) << "Illegal face " << faceI << " or vertex " << vertI
506 << abort(FatalError);
509 const labelList& pEdges = mesh_.pointEdges()[vertI];
514 forAll(pEdges, pEdgeI)
516 label edgeI = pEdges[pEdgeI];
518 if (meshTools::edgeOnFace(mesh_, faceI, edgeI))
528 // Found the two edges.
538 "cellFeatures::isFeatureVertex(const label, const label)"
539 ) << "Did not find two edges sharing vertex " << vertI
540 << " on face " << faceI << " vertices:" << mesh_.faces()[faceI]
541 << abort(FatalError);
544 return isFeaturePoint(edge0, edge1);
548 // ************************************************************************* //