1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2008 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 "primitiveMesh.H"
31 #include "labelHashSet.H"
33 #include "demandDrivenData.H"
35 #include "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 = (fp + 1) % f.size();
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 = (face0Start + 1) % f0.size();
151 const face& f1 = mesh_.faces()[face1];
153 label face1Start = findIndex(f1, e.start());
154 label face1End = (face1Start + 1) % f1.size();
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].size() == 0)
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;
374 faces[superFaceI] = face(superFace);
382 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
384 // Construct from components
385 Foam::cellFeatures::cellFeatures
387 const primitiveMesh& mesh,
395 featureEdge_(10*mesh.cellEdges()[cellI].size()),
399 const labelList& cEdges = mesh_.cellEdges()[cellI_];
401 forAll(cEdges, cEdgeI)
403 label edgeI = cEdges[cEdgeI];
405 if (isCellFeatureEdge(minCos_, edgeI))
407 featureEdge_.insert(edgeI);
414 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
416 Foam::cellFeatures::~cellFeatures()
418 deleteDemandDrivenData(facesPtr_);
422 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
424 bool Foam::cellFeatures::isFeaturePoint(const label edge0, const label edge1)
430 || (edge0 >= mesh_.nEdges())
432 || (edge1 >= mesh_.nEdges())
437 "cellFeatures::isFeatureVertex(const label, const label)"
438 ) << "Illegal edge labels : edge0:" << edge0 << " edge1:" << edge1
439 << abort(FatalError);
442 const edge& e0 = mesh_.edges()[edge0];
444 vector e0Vec = e0.vec(mesh_.points());
447 const edge& e1 = mesh_.edges()[edge1];
449 vector e1Vec = e1.vec(mesh_.points());
456 (e0.start() == e1.end())
457 || (e0.end() == e1.start())
461 cosAngle = e0Vec & e1Vec;
465 (e0.start() == e1.start())
466 || (e0.end() == e1.end())
470 cosAngle = - e0Vec & e1Vec;
474 cosAngle = GREAT; // satisfy compiler
478 "cellFeatures::isFeaturePoint(const label, const label"
480 ) << "Edges do not share common vertex. e0:" << e0
481 << " e1:" << e1 << abort(FatalError);
484 if (cosAngle < minCos_)
486 // Angle larger than criterium
496 bool Foam::cellFeatures::isFeatureVertex(const label faceI, const label vertI)
502 || (faceI >= mesh_.nFaces())
504 || (vertI >= mesh_.nPoints())
509 "cellFeatures::isFeatureVertex(const label, const label)"
510 ) << "Illegal face " << faceI << " or vertex " << vertI
511 << abort(FatalError);
514 const labelList& pEdges = mesh_.pointEdges()[vertI];
519 forAll(pEdges, pEdgeI)
521 label edgeI = pEdges[pEdgeI];
523 if (meshTools::edgeOnFace(mesh_, faceI, edgeI))
533 // Found the two edges.
543 "cellFeatures::isFeatureVertex(const label, const label)"
544 ) << "Did not find two edges sharing vertex " << vertI
545 << " on face " << faceI << " vertices:" << mesh_.faces()[faceI]
546 << abort(FatalError);
549 return isFeaturePoint(edge0, edge1);
553 // ************************************************************************* //