Added faceCentres member function.
[OpenFOAM-1.6.x.git] / src / OpenFOAM / meshes / primitiveMesh / PrimitivePatch / PrimitivePatchAddressing.C
blob5deecba26c4f20dcf301270cbf1ec012d675fa71
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 1991-2009 OpenCFD Ltd.
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
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
19     for more details.
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
25 Description
26     This function calculates the list of patch edges, defined on the list of
27     points supporting the patch. The edges are ordered:
28     - 0..nInternalEdges-1 : upper triangular order
29     - nInternalEdges..    : boundary edges (no particular order)
31     Other patch addressing information is also calculated:
32     - faceFaces with neighbour faces in ascending order
33     - edgeFaces with ascending face order
34     - faceEdges sorted according to edges of a face
36 \*---------------------------------------------------------------------------*/
38 #include "PrimitivePatch.H"
39 #include "DynamicList.H"
42 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
44 template
46     class Face,
47     template<class> class FaceList,
48     class PointField,
49     class PointType
51 void
52 Foam::PrimitivePatch<Face, FaceList, PointField, PointType>::
53 calcAddressing() const
55     if (debug)
56     {
57         Info<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
58             << "calcAddressing() : calculating patch addressing"
59             << endl;
60     }
62     if (edgesPtr_ || faceFacesPtr_ || edgeFacesPtr_ || faceEdgesPtr_)
63     {
64         // it is considered an error to attempt to recalculate
65         // if already allocated
66         FatalErrorIn
67         (
68             "PrimitivePatch<Face, FaceList, PointField, PointType>::"
69             "calcAddressing()"
70         )   << "addressing already calculated"
71             << abort(FatalError);
72     }
74     // get reference to localFaces
75     const List<Face>& locFcs = localFaces();
77     // get reference to pointFaces
78     const labelListList& pf = pointFaces();
80     // Guess the max number of edges and neighbours for a face
81     label maxEdges = 0;
82     forAll (locFcs, faceI)
83     {
84         maxEdges += locFcs[faceI].size();
85     }
87     // create the lists for the various results. (resized on completion)
88     edgesPtr_ = new edgeList(maxEdges);
89     edgeList& edges = *edgesPtr_;
91     edgeFacesPtr_ = new labelListList(maxEdges);
92     labelListList& edgeFaces = *edgeFacesPtr_;
94     // faceFaces created using a dynamic list.  Cannot guess size because
95     // of multiple connections
96     List<DynamicList<label> > ff(locFcs.size());
98     faceEdgesPtr_ = new labelListList(locFcs.size());
99     labelListList& faceEdges = *faceEdgesPtr_;
101     // count the number of face neighbours
102     labelList noFaceFaces(locFcs.size());
104     // initialise the lists of subshapes for each face to avoid duplication
105     edgeListList faceIntoEdges(locFcs.size());
107     forAll (locFcs, faceI)
108     {
109         faceIntoEdges[faceI] = locFcs[faceI].edges();
111         labelList& curFaceEdges = faceEdges[faceI];
112         curFaceEdges.setSize(faceIntoEdges[faceI].size());
114         forAll (curFaceEdges, faceEdgeI)
115         {
116             curFaceEdges[faceEdgeI] = -1;
117         }
118     }
120     // This algorithm will produce a separated list of edges, internal edges
121     // starting from 0 and boundary edges starting from the top and
122     // growing down.
124     label nEdges = 0;
126     bool found = false;
128     // Note that faceIntoEdges is sorted acc. to local vertex numbering
129     // in face (i.e. curEdges[0] is edge between f[0] and f[1])
131     // For all local faces ...
132     forAll (locFcs, faceI)
133     {
134         // Get reference to vertices of current face and corresponding edges.
135         const Face& curF = locFcs[faceI];
136         const edgeList& curEdges = faceIntoEdges[faceI];
138         // Record the neighbour face.  Multiple connectivity allowed
139         List<DynamicList<label> > neiFaces(curF.size());
140         List<DynamicList<label> > edgeOfNeiFace(curF.size());
142         label nNeighbours = 0;
144         // For all edges ...
145         forAll (curEdges, edgeI)
146         {
147             // If the edge is already detected, skip
148             if (faceEdges[faceI][edgeI] >= 0) continue;
150             found = false;
152             // Set reference to the current edge
153             const edge& e = curEdges[edgeI];
155             // Collect neighbours for the current face vertex.
157             const labelList& nbrFaces = pf[e.start()];
159             forAll (nbrFaces, nbrFaceI)
160             {
161                 // set reference to the current neighbour
162                 label curNei = nbrFaces[nbrFaceI];
164                 // Reject neighbours with the lower label
165                 if (curNei > faceI)
166                 {
167                     // get the reference to subshapes of the neighbour
168                     const edgeList& searchEdges = faceIntoEdges[curNei];
170                     forAll (searchEdges, neiEdgeI)
171                     {
172                         if (searchEdges[neiEdgeI] == e)
173                         {
174                             // Match
175                             found = true;
177                             neiFaces[edgeI].append(curNei);
178                             edgeOfNeiFace[edgeI].append(neiEdgeI);
180                             // Record faceFaces both ways
181                             ff[faceI].append(curNei);
182                             ff[curNei].append(faceI);
184                             // Keep searching due to multiple connectivity
185                         }
186                     }
187                 }
188             } // End of neighbouring faces
190             if (found)
191             {
192                 // Register another detected internal edge
193                 nNeighbours++;
194             }
195         } // End of current edges
197         // Add the edges in increasing number of neighbours.
198         // Note: for multiply connected surfaces, the lower index neighbour for
199         // an edge will come first.
201         // Add the faces in the increasing order of neighbours
202         for (label neiSearch = 0; neiSearch < nNeighbours; neiSearch++)
203         {
204             // Find the lowest neighbour which is still valid
205             label nextNei = -1;
206             label minNei = locFcs.size();
208             forAll (neiFaces, nfI)
209             {
210                 if (neiFaces[nfI].size() && neiFaces[nfI][0] < minNei)
211                 {
212                     nextNei = nfI;
213                     minNei = neiFaces[nfI][0];
214                 }
215             }
217             if (nextNei > -1)
218             {
219                 // Add the face to the list of faces
220                 edges[nEdges] = curEdges[nextNei];
222                 // Set face-edge and face-neighbour-edge to current face label
223                 faceEdges[faceI][nextNei] = nEdges;
225                 DynamicList<label>& cnf = neiFaces[nextNei];
226                 DynamicList<label>& eonf = edgeOfNeiFace[nextNei];
228                 // Set edge-face addressing
229                 labelList& curEf = edgeFaces[nEdges];
230                 curEf.setSize(cnf.size() + 1);
231                 curEf[0] = faceI;
233                 forAll (cnf, cnfI)
234                 {
235                     faceEdges[cnf[cnfI]][eonf[cnfI]] = nEdges;
237                     curEf[cnfI + 1] = cnf[cnfI];
238                 }
240                 // Stop the neighbour from being used again
241                 cnf.clear();
242                 eonf.clear();
244                 // Increment number of faces counter
245                 nEdges++;
246             }
247             else
248             {
249                 FatalErrorIn
250                 (
251                     "PrimitivePatch<Face, FaceList, PointField, PointType>::"
252                     "calcAddressing()"
253                 )   << "Error in internal edge insertion"
254                     << abort(FatalError);
255             }
256         }
257     }
259     nInternalEdges_ = nEdges;
261     // Do boundary faces
263     forAll (faceEdges, faceI)
264     {
265         labelList& curEdges = faceEdges[faceI];
267         forAll (curEdges, edgeI)
268         {
269             if (curEdges[edgeI] < 0)
270             {
271                 // Grab edge and faceEdge
272                 edges[nEdges] = faceIntoEdges[faceI][edgeI];
273                 curEdges[edgeI] = nEdges;
275                 // Add edgeFace
276                 labelList& curEf = edgeFaces[nEdges];
277                 curEf.setSize(1);
278                 curEf[0] = faceI;
280                 nEdges++;
281             }
282         }
283     }
285     // edges
286     edges.setSize(nEdges);
288     // edgeFaces list
289     edgeFaces.setSize(nEdges);
291     // faceFaces list
292     faceFacesPtr_ = new labelListList(locFcs.size());
293     labelListList& faceFaces = *faceFacesPtr_;
295     forAll (faceFaces, faceI)
296     {
297         faceFaces[faceI].transfer(ff[faceI]);
298     }
301     if (debug)
302     {
303         Info<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
304             << "calcAddressing() : finished calculating patch addressing"
305             << endl;
306     }
310 // ************************************************************************* //