Files
openfoam/src/OpenFOAM/meshes/primitiveMesh/PrimitivePatch/PrimitivePatchAddressing.C

319 lines
9.7 KiB
C

/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Description
This function calculates the list of patch edges, defined on the list of
points supporting the patch. The edges are ordered:
- 0..nInternalEdges-1 : upper triangular order
- nInternalEdges.. : boundary edges (no particular order)
Other patch addressing information is also calculated:
- faceFaces with neighbour faces in ascending order
- edgeFaces with ascending face order
- faceEdges sorted according to edges of a face
\*---------------------------------------------------------------------------*/
#include "PrimitivePatch.H"
#include "DynamicList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template
<
class Face,
template<class> class FaceList,
class PointField,
class PointType
>
void PrimitivePatch<Face, FaceList, PointField, PointType>::calcAddressing()
const
{
if (debug)
{
Info<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
<< "calcAddressing() : calculating patch addressing"
<< endl;
}
if (edgesPtr_ || faceFacesPtr_ || edgeFacesPtr_ || faceEdgesPtr_)
{
// it is considered an error to attempt to recalculate
// if already allocated
FatalErrorIn
(
"PrimitivePatch<Face, FaceList, PointField, PointType>::"
"calcAddressing()"
) << "addressing already calculated"
<< abort(FatalError);
}
// get reference to localFaces
const List<Face>& locFcs = localFaces();
// get reference to pointFaces
const labelListList& pf = pointFaces();
// Guess the max number of edges and neighbours for a face
label maxEdges = 0;
forAll (locFcs, faceI)
{
maxEdges += locFcs[faceI].size();
}
// create the lists for the various results. (resized on completion)
edgesPtr_ = new edgeList(maxEdges);
edgeList& edges = *edgesPtr_;
edgeFacesPtr_ = new labelListList(maxEdges);
labelListList& edgeFaces = *edgeFacesPtr_;
// faceFaces created using a dynamic list. Cannot guess size because
// of multiple connections
List<DynamicList<label> > ff(locFcs.size());
faceEdgesPtr_ = new labelListList(locFcs.size());
labelListList& faceEdges = *faceEdgesPtr_;
// count the number of face neighbours
labelList noFaceFaces(locFcs.size());
// initialise the lists of subshapes for each face to avoid duplication
edgeListList faceIntoEdges(locFcs.size());
forAll (locFcs, faceI)
{
faceIntoEdges[faceI] = locFcs[faceI].edges();
labelList& curFaceEdges = faceEdges[faceI];
curFaceEdges.setSize(faceIntoEdges[faceI].size());
forAll (curFaceEdges, faceEdgeI)
{
curFaceEdges[faceEdgeI] = -1;
}
}
// This algorithm will produce a separated list of edges, internal edges
// starting from 0 and boundary edges starting from the top and
// growing down.
label nEdges = 0;
bool found = false;
// Note that faceIntoEdges is sorted acc. to local vertex numbering
// in face (i.e. curEdges[0] is edge between f[0] and f[1])
// For all local faces ...
forAll (locFcs, faceI)
{
// Get reference to vertices of current face and corresponding edges.
const Face& curF = locFcs[faceI];
const edgeList& curEdges = faceIntoEdges[faceI];
// Record the neighbour face. Multiple connectivity allowed
List<DynamicList<label> > neiFaces(curF.size());
List<DynamicList<label> > edgeOfNeiFace(curF.size());
label nNeighbours = 0;
// For all edges ...
forAll (curEdges, edgeI)
{
// If the edge is already detected, skip
if (faceEdges[faceI][edgeI] >= 0) continue;
found = false;
// Set reference to the current edge
const edge& e = curEdges[edgeI];
// Collect neighbours for the current face vertex.
const labelList& nbrFaces = pf[e.start()];
forAll (nbrFaces, nbrFaceI)
{
// set reference to the current neighbour
label curNei = nbrFaces[nbrFaceI];
// Reject neighbours with the lower label
if (curNei > faceI)
{
// get the reference to subshapes of the neighbour
const edgeList& searchEdges = faceIntoEdges[curNei];
forAll (searchEdges, neiEdgeI)
{
if (searchEdges[neiEdgeI] == e)
{
// Match
found = true;
neiFaces[edgeI].append(curNei);
edgeOfNeiFace[edgeI].append(neiEdgeI);
// Record faceFaces both ways
ff[faceI].append(curNei);
ff[curNei].append(faceI);
// Keep searching due to multiple connectivity
}
}
}
} // End of neighbouring faces
if (found)
{
// Register another detected internal edge
nNeighbours++;
}
} // End of current edges
// Add the edges in increasing number of neighbours.
// Note: for multiply connected surfaces, the lower index neighbour for
// an edge will come first.
// Add the faces in the increasing order of neighbours
for (label neiSearch = 0; neiSearch < nNeighbours; neiSearch++)
{
// Find the lowest neighbour which is still valid
label nextNei = -1;
label minNei = locFcs.size();
forAll (neiFaces, nfI)
{
if (neiFaces[nfI].size() > 0 && neiFaces[nfI][0] < minNei)
{
nextNei = nfI;
minNei = neiFaces[nfI][0];
}
}
if (nextNei > -1)
{
// Add the face to the list of faces
edges[nEdges] = curEdges[nextNei];
// Set face-edge and face-neighbour-edge to current face label
faceEdges[faceI][nextNei] = nEdges;
DynamicList<label>& cnf = neiFaces[nextNei];
DynamicList<label>& eonf = edgeOfNeiFace[nextNei];
// Set edge-face addressing
labelList& curEf = edgeFaces[nEdges];
curEf.setSize(cnf.size() + 1);
curEf[0] = faceI;
forAll (cnf, cnfI)
{
faceEdges[cnf[cnfI]][eonf[cnfI]] = nEdges;
curEf[cnfI + 1] = cnf[cnfI];
}
// Stop the neighbour from being used again
cnf.clear();
eonf.clear();
// Increment number of faces counter
nEdges++;
}
else
{
FatalErrorIn
(
"PrimitivePatch<Face, FaceList, PointField, PointType>::"
"calcAddressing()"
) << "Error in internal edge insertion"
<< abort(FatalError);
}
}
}
nInternalEdges_ = nEdges;
// Do boundary faces
forAll (faceEdges, faceI)
{
labelList& curEdges = faceEdges[faceI];
forAll (curEdges, edgeI)
{
if (curEdges[edgeI] < 0)
{
// Grab edge and faceEdge
edges[nEdges] = faceIntoEdges[faceI][edgeI];
curEdges[edgeI] = nEdges;
// Add edgeFace
labelList& curEf = edgeFaces[nEdges];
curEf.setSize(1);
curEf[0] = faceI;
nEdges++;
}
}
}
// edges
edges.setSize(nEdges);
// edgeFaces list
edgeFaces.setSize(nEdges);
// faceFaces list
faceFacesPtr_ = new labelListList(locFcs.size());
labelListList& faceFaces = *faceFacesPtr_;
forAll (faceFaces, faceI)
{
faceFaces[faceI].transfer(ff[faceI]);
}
if (debug)
{
Info<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
<< "calcAddressing() : finished calculating patch addressing"
<< endl;
}
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //