Added linuxIA64 compilation options
[OpenFOAM-1.6.x.git] / src / meshTools / cellDist / cellDistFuncs.C
blobbca2841273c45d8782658aa9ef4526ac95dffbd8
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 \*---------------------------------------------------------------------------*/
27 #include "cellDistFuncs.H"
28 #include "polyMesh.H"
29 #include "wallPolyPatch.H"
30 #include "polyBoundaryMesh.H"
32 namespace Foam
35 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
37 defineTypeNameAndDebug(cellDistFuncs, 0);
42 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
44 // Find val in first nElems elements of elems.
45 Foam::label Foam::cellDistFuncs::findIndex
47     const label nElems,
48     const labelList& elems,
49     const label val
52     for (label i = 0; i < nElems; i++)
53     {
54         if (elems[i] == val)
55         {
56             return i;
57         }
58     }
59     return -1;
63 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
65 // Construct from mesh
66 Foam::cellDistFuncs::cellDistFuncs(const polyMesh& mesh)
68     mesh_(mesh)
72 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
74 // Get patch ids of named patches
75 Foam::labelHashSet Foam::cellDistFuncs::getPatchIDs
77     const wordList& patchNames
78 ) const
80     const polyBoundaryMesh& bMesh = mesh().boundaryMesh();
82     // Construct Set of patchNames for easy checking if included
83     HashSet<word> patchNamesHash(patchNames.size());
85     forAll(patchNames, patchI)
86     {
87         patchNamesHash.insert(patchNames[patchI]);
88     }
90     // Loop over all patches and check if patch name in hashset
92     labelHashSet patchIDs(bMesh.size());
94     forAll(bMesh, patchI)
95     {
96         const polyPatch& patch = bMesh[patchI];
98         if (patchNamesHash.found(patch.name()))
99         {
100             patchIDs.insert(patchI);
101         }
102     }
103     return patchIDs;
107 // Return smallest true distance from p to any of wallFaces.
108 // Note that even if normal hits face we still check other faces.
109 // Note that wallFaces is untruncated and we explicitly pass in size.
110 Foam::scalar Foam::cellDistFuncs::smallestDist
112     const point& p,
113     const polyPatch& patch,
114     const label nWallFaces,
115     const labelList& wallFaces,
116     label& minFaceI
117 ) const
119     const pointField& points = patch.points();
121     scalar minDist = GREAT;
122     minFaceI = -1;
124     for(label wallFaceI = 0; wallFaceI < nWallFaces; wallFaceI++)
125     {
126         label patchFaceI = wallFaces[wallFaceI];
128         pointHit curHit = patch[patchFaceI].nearestPoint(p, points);
130         if (curHit.distance() < minDist)
131         {
132             minDist = curHit.distance();
133             minFaceI = patch.start() + patchFaceI;
134         }
135     }
137     return minDist;
141 // Get point neighbours of faceI (including faceI). Returns number of faces.
142 // Note: does not allocate storage but does use linear search to determine
143 // uniqueness. For polygonal faces this might be quite inefficient.
144 Foam::label Foam::cellDistFuncs::getPointNeighbours
146     const primitivePatch& patch,
147     const label patchFaceI,
148     labelList& neighbours
149 ) const
151     label nNeighbours = 0;
153     // Add myself
154     neighbours[nNeighbours++] = patchFaceI;
156     // Add all face neighbours
157     const labelList& faceNeighbours = patch.faceFaces()[patchFaceI];
159     forAll(faceNeighbours, faceNeighbourI)
160     {
161         neighbours[nNeighbours++] = faceNeighbours[faceNeighbourI];
162     }
164     // Remember part of neighbours that contains edge-connected faces.
165     label nEdgeNbs = nNeighbours;
168     // Add all point-only neighbours by linear searching in edge neighbours.
169     // Assumes that point-only neighbours are not using multiple points on
170     // face.
172     const face& f = patch.localFaces()[patchFaceI];
174     forAll(f, fp)
175     {
176         label pointI = f[fp];
178         const labelList& pointNbs = patch.pointFaces()[pointI];
180         forAll(pointNbs, nbI)
181         {
182             label faceI = pointNbs[nbI];
184             // Check for faceI in edge-neighbours part of neighbours
185             if (findIndex(nEdgeNbs, neighbours, faceI) == -1)
186             {
187                 neighbours[nNeighbours++] = faceI;
188             }
189         }
190     }
193     if (debug)
194     {
195         // Check for duplicates
197         // Use hashSet to determine nbs.
198         labelHashSet nbs(4*f.size());
200         forAll(f, fp)
201         {
202             const labelList& pointNbs = patch.pointFaces()[f[fp]];
204             forAll(pointNbs, i)
205             {
206                 nbs.insert(pointNbs[i]);
207             }
208         }
210         // Subtract ours.
211         for (label i = 0; i < nNeighbours; i++)
212         {
213             label nb = neighbours[i];
215             if (!nbs.found(nb))
216             {
217                 SeriousErrorIn("Foam::cellDistFuncs::getPointNeighbours")
218                     << "getPointNeighbours : patchFaceI:" << patchFaceI
219                     << " verts:" << f << endl;
221                 forAll(f, fp)
222                 {
223                     SeriousErrorIn("Foam::cellDistFuncs::getPointNeighbours")
224                         << "point:" << f[fp] << " pointFaces:"
225                         << patch.pointFaces()[f[fp]] << endl;
226                 }
228                 for (label i = 0; i < nNeighbours; i++)
229                 {
230                     SeriousErrorIn("Foam::cellDistFuncs::getPointNeighbours")
231                         << "fast nbr:" << neighbours[i]
232                         << endl;
233                 }
235                 FatalErrorIn("getPointNeighbours")
236                     << "Problem: fast pointNeighbours routine included " << nb
237                     << " which is not in proper neigbour list " << nbs.toc()
238                     << abort(FatalError);
239             }
240             nbs.erase(nb);
241         }
243         if (nbs.size())
244         {
245             FatalErrorIn("getPointNeighbours")
246                 << "Problem: fast pointNeighbours routine did not find "
247                 << nbs.toc() << abort(FatalError);
248         }
249     }
251     return nNeighbours;
255 // size of largest patch (out of supplied subset of patches)
256 Foam::label Foam::cellDistFuncs::maxPatchSize(const labelHashSet& patchIDs)
257  const
259     label maxSize = 0;
261     forAll(mesh().boundaryMesh(), patchI)
262     {
263         if (patchIDs.found(patchI))
264         {
265             const polyPatch& patch = mesh().boundaryMesh()[patchI];
267             maxSize = Foam::max(maxSize, patch.size());
268         }
269     }
270     return maxSize;
274 // sum of patch sizes (out of supplied subset of patches)
275 Foam::label Foam::cellDistFuncs::sumPatchSize(const labelHashSet& patchIDs)
276  const
278     label sum = 0;
280     forAll(mesh().boundaryMesh(), patchI)
281     {
282         if (patchIDs.found(patchI))
283         {
284             const polyPatch& patch = mesh().boundaryMesh()[patchI];
286             sum += patch.size();
287         }
288     }
289     return sum;
293 // Gets nearest wall for cells next to wall
294 void Foam::cellDistFuncs::correctBoundaryFaceCells
296     const labelHashSet& patchIDs,
297     scalarField& wallDistCorrected,
298     Map<label>& nearestFace
299 ) const
301     // Size neighbours array for maximum possible (= size of largest patch)
302     label maxPointNeighbours = maxPatchSize(patchIDs);
304     labelList neighbours(maxPointNeighbours);
307     // Correct all cells with face on wall
308     const vectorField& cellCentres = mesh().cellCentres();
309     const labelList& faceOwner = mesh().faceOwner();
311     forAll(mesh().boundaryMesh(), patchI)
312     {
313         if (patchIDs.found(patchI))
314         {
315             const polyPatch& patch = mesh().boundaryMesh()[patchI];
317             // Check cells with face on wall
318             forAll(patch, patchFaceI)
319             {
320                 label nNeighbours = getPointNeighbours
321                 (
322                     patch,
323                     patchFaceI,
324                     neighbours
325                 );
327                 label cellI = faceOwner[patch.start() + patchFaceI];
329                 label minFaceI = -1;
331                 wallDistCorrected[cellI] = smallestDist
332                 (
333                     cellCentres[cellI],
334                     patch,
335                     nNeighbours,
336                     neighbours,
337                     minFaceI
338                 );
340                 // Store wallCell and its nearest neighbour
341                 nearestFace.insert(cellI, minFaceI);
342             }
343         }
344     }
349 // Correct all cells connected to wall (via point) and not in nearestFace
350 void Foam::cellDistFuncs::correctBoundaryPointCells
352     const labelHashSet& patchIDs,
353     scalarField& wallDistCorrected,
354     Map<label>& nearestFace
355 ) const
357     // Correct all (non-visited) cells with point on wall
359     const labelListList& pointCells = mesh().pointCells();
360     const vectorField& cellCentres = mesh().cellCentres();
362     forAll(mesh().boundaryMesh(), patchI)
363     {
364         if (patchIDs.found(patchI))
365         {
366             const polyPatch& patch = mesh().boundaryMesh()[patchI];
368             const labelList& meshPoints = patch.meshPoints();
369             const labelListList& pointFaces = patch.pointFaces();
371             forAll(meshPoints, meshPointI)
372             {
373                 label vertI = meshPoints[meshPointI];
375                 const labelList& neighbours = pointCells[vertI];
377                 forAll(neighbours, neighbourI)
378                 {
379                     label cellI = neighbours[neighbourI];
381                     if (!nearestFace.found(cellI))
382                     {
383                         const labelList& wallFaces = pointFaces[meshPointI];
385                         label minFaceI = -1;
387                         wallDistCorrected[cellI] = smallestDist
388                         (
389                             cellCentres[cellI],
390                             patch,
391                             wallFaces.size(),
392                             wallFaces,
393                             minFaceI
394                         );
396                         // Store wallCell and its nearest neighbour
397                         nearestFace.insert(cellI, minFaceI);
398                     }
399                 }
400             }
401         }
402     }
406 // ************************************************************************* //