1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 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 the
13 Free Software Foundation; either version 2 of the License, or (at your
14 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, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 \*---------------------------------------------------------------------------*/
29 #include "cellFeatures.H"
30 #include <OpenFOAM/primitiveMesh.H>
31 #include <OpenFOAM/HashSet.H>
32 #include <OpenFOAM/Map.H>
33 #include <OpenFOAM/demandDrivenData.H>
34 #include <OpenFOAM/ListOps.H>
35 #include <meshTools/meshTools.H>
37 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
40 // Return true if edge start and end are on increasing face vertices. (edge is
41 // guaranteed to be on face)
42 bool Foam::cellFeatures::faceAlignedEdge(const label faceI, const label edgeI)
45 const edge& e = mesh_.edges()[edgeI];
47 const face& f = mesh_.faces()[faceI];
51 if (f[fp] == e.start())
53 label fp1 = f.fcIndex(fp);
55 return f[fp1] == e.end();
61 "cellFeatures::faceAlignedEdge(const label, const label)"
62 ) << "Can not find edge " << mesh_.edges()[edgeI]
63 << " on face " << faceI << abort(FatalError);
69 // Return edge in featureEdge that uses vertI and is on same superface
71 Foam::label Foam::cellFeatures::nextEdge
73 const Map<label>& toSuperFace,
74 const label superFaceI,
75 const label thisEdgeI,
79 const labelList& pEdges = mesh_.pointEdges()[thisVertI];
81 forAll(pEdges, pEdgeI)
83 label edgeI = pEdges[pEdgeI];
85 if ((edgeI != thisEdgeI) && featureEdge_.found(edgeI))
87 // Check that edge is used by a face on same superFace
89 const labelList& eFaces = mesh_.edgeFaces()[edgeI];
91 forAll(eFaces, eFaceI)
93 label faceI = eFaces[eFaceI];
97 meshTools::faceOnCell(mesh_, cellI_, faceI)
98 && (toSuperFace[faceI] == superFaceI)
109 "cellFeatures::nextEdge(const label, const Map<label>"
110 ", const labelHashSet&, const label, const label, const label)"
111 ) << "Can not find edge in " << featureEdge_ << " connected to edge "
112 << thisEdgeI << " at vertex " << thisVertI << endl
113 << "This might mean that the externalEdges do not form a closed loop"
114 << abort(FatalError);
120 // Return true if angle between faces using it is larger than certain value.
121 bool Foam::cellFeatures::isCellFeatureEdge
127 // Get the two faces using this edge
131 meshTools::getEdgeFaces(mesh_, cellI_, edgeI, face0, face1);
133 // Check the angle between them by comparing the face normals.
135 vector n0 = mesh_.faceAreas()[face0];
138 vector n1 = mesh_.faceAreas()[face1];
141 scalar cosAngle = n0 & n1;
144 const edge& e = mesh_.edges()[edgeI];
146 const face& f0 = mesh_.faces()[face0];
148 label face0Start = findIndex(f0, e.start());
149 label face0End = f0.fcIndex(face0Start);
151 const face& f1 = mesh_.faces()[face1];
153 label face1Start = findIndex(f1, e.start());
154 label face1End = f1.fcIndex(face1Start);
159 (f0[face0End] == e.end())
160 && (f1[face1End] != e.end())
163 (f0[face0End] != e.end())
164 && (f1[face1End] == e.end())
171 cosAngle = -cosAngle;
174 if (cosAngle < minCos)
185 // Recursively mark (on toSuperFace) all face reachable across non-feature
187 void Foam::cellFeatures::walkSuperFace
190 const label superFaceI,
191 Map<label>& toSuperFace
194 if (!toSuperFace.found(faceI))
196 toSuperFace.insert(faceI, superFaceI);
198 const labelList& fEdges = mesh_.faceEdges()[faceI];
200 forAll(fEdges, fEdgeI)
202 label edgeI = fEdges[fEdgeI];
204 if (!featureEdge_.found(edgeI))
208 meshTools::getEdgeFaces(mesh_, cellI_, edgeI, face0, face1);
227 void Foam::cellFeatures::calcSuperFaces() const
229 // Determine superfaces by edge walking across non-feature edges
231 const labelList& cFaces = mesh_.cells()[cellI_];
233 // Mapping from old to super face:
234 // <not found> : not visited
236 Map<label> toSuperFace(10*cFaces.size());
238 label superFaceI = 0;
240 forAll(cFaces, cFaceI)
242 label faceI = cFaces[cFaceI];
244 if (!toSuperFace.found(faceI))
256 // Construct superFace-to-oldface mapping.
258 faceMap_.setSize(superFaceI);
260 forAll(cFaces, cFaceI)
262 label faceI = cFaces[cFaceI];
264 faceMap_[toSuperFace[faceI]].append(faceI);
267 forAll(faceMap_, superI)
269 faceMap_[superI].shrink();
273 // Construct superFaces
275 facesPtr_ = new faceList(superFaceI);
277 faceList& faces = *facesPtr_;
279 forAll(cFaces, cFaceI)
281 label faceI = cFaces[cFaceI];
283 label superFaceI = toSuperFace[faceI];
285 if (faces[superFaceI].empty())
287 // Superface not yet constructed.
289 // Find starting feature edge on face.
290 label startEdgeI = -1;
292 const labelList& fEdges = mesh_.faceEdges()[faceI];
294 forAll(fEdges, fEdgeI)
296 label edgeI = fEdges[fEdgeI];
298 if (featureEdge_.found(edgeI))
307 if (startEdgeI != -1)
309 // Walk point-edge-point along feature edges
311 DynamicList<label> superFace(10*mesh_.faces()[faceI].size());
313 const edge& e = mesh_.edges()[startEdgeI];
315 // Walk either start-end or end-start depending on orientation
316 // of face. SuperFace will have cellI as owner.
317 bool flipOrientation =
318 (mesh_.faceOwner()[faceI] == cellI_)
319 ^ (faceAlignedEdge(faceI, startEdgeI));
321 label startVertI = -1;
325 startVertI = e.end();
329 startVertI = e.start();
332 label edgeI = startEdgeI;
334 label vertI = e.otherVertex(startVertI);
338 label newEdgeI = nextEdge
346 // Determine angle between edges.
347 if (isFeaturePoint(edgeI, newEdgeI))
349 superFace.append(vertI);
354 if (vertI == startVertI)
359 vertI = mesh_.edges()[edgeI].otherVertex(vertI);
363 if (superFace.size() <= 2)
365 WarningIn("cellFeatures::calcSuperFaces")
366 << " Can not collapse faces " << faceMap_[superFaceI]
367 << " into one big face on cell " << cellI_ << endl
368 << "Try decreasing minCos:" << minCos_ << endl;
372 faces[superFaceI].transfer(superFace);
380 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
382 // Construct from components
383 Foam::cellFeatures::cellFeatures
385 const primitiveMesh& mesh,
393 featureEdge_(10*mesh.cellEdges()[cellI].size()),
397 const labelList& cEdges = mesh_.cellEdges()[cellI_];
399 forAll(cEdges, cEdgeI)
401 label edgeI = cEdges[cEdgeI];
403 if (isCellFeatureEdge(minCos_, edgeI))
405 featureEdge_.insert(edgeI);
412 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
414 Foam::cellFeatures::~cellFeatures()
416 deleteDemandDrivenData(facesPtr_);
420 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
422 bool Foam::cellFeatures::isFeaturePoint(const label edge0, const label edge1)
428 || (edge0 >= mesh_.nEdges())
430 || (edge1 >= mesh_.nEdges())
435 "cellFeatures::isFeatureVertex(const label, const label)"
436 ) << "Illegal edge labels : edge0:" << edge0 << " edge1:" << edge1
437 << abort(FatalError);
440 const edge& e0 = mesh_.edges()[edge0];
442 vector e0Vec = e0.vec(mesh_.points());
445 const edge& e1 = mesh_.edges()[edge1];
447 vector e1Vec = e1.vec(mesh_.points());
454 (e0.start() == e1.end())
455 || (e0.end() == e1.start())
459 cosAngle = e0Vec & e1Vec;
463 (e0.start() == e1.start())
464 || (e0.end() == e1.end())
468 cosAngle = - e0Vec & e1Vec;
472 cosAngle = GREAT; // satisfy compiler
476 "cellFeatures::isFeaturePoint(const label, const label"
478 ) << "Edges do not share common vertex. e0:" << e0
479 << " e1:" << e1 << abort(FatalError);
482 if (cosAngle < minCos_)
484 // Angle larger than criterium
494 bool Foam::cellFeatures::isFeatureVertex(const label faceI, const label vertI)
500 || (faceI >= mesh_.nFaces())
502 || (vertI >= mesh_.nPoints())
507 "cellFeatures::isFeatureVertex(const label, const label)"
508 ) << "Illegal face " << faceI << " or vertex " << vertI
509 << abort(FatalError);
512 const labelList& pEdges = mesh_.pointEdges()[vertI];
517 forAll(pEdges, pEdgeI)
519 label edgeI = pEdges[pEdgeI];
521 if (meshTools::edgeOnFace(mesh_, faceI, edgeI))
531 // Found the two edges.
541 "cellFeatures::isFeatureVertex(const label, const label)"
542 ) << "Did not find two edges sharing vertex " << vertI
543 << " on face " << faceI << " vertices:" << mesh_.faces()[faceI]
544 << abort(FatalError);
547 return isFeaturePoint(edge0, edge1);
551 // ************************ vim: set sw=4 sts=4 et: ************************ //