1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
|
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
Description
Construct a cell shape from face information
\*---------------------------------------------------------------------------*/
#include "cellShapeRecognition.H"
#include "labelList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
cellShape create3DCellShape
(
const label cellIndex,
const labelList& faceLabels,
const faceList& faces,
const labelList& owner,
const labelList& neighbour,
const label fluentCellModelID
)
{
// List of pointers to shape models for 3-D shape recognition
static List<const cellModel*> fluentCellModelLookup
(
7,
reinterpret_cast<const cellModel*>(0)
);
fluentCellModelLookup[2] = cellModeller::lookup("tet");
fluentCellModelLookup[4] = cellModeller::lookup("hex");
fluentCellModelLookup[5] = cellModeller::lookup("pyr");
fluentCellModelLookup[6] = cellModeller::lookup("prism");
static label faceMatchingOrder[7][6] =
{
{-1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1},
{ 0, 1, 2, 3, -1, -1}, // tet
{-1, -1, -1, -1, -1, -1},
{ 0, 2, 4, 3, 5, 1}, // hex
{ 0, 1, 2, 3, 4, -1}, // pyr
{ 0, 2, 3, 4, 1, -1}, // prism
};
const cellModel& curModel = *fluentCellModelLookup[fluentCellModelID];
// Checking
if (faceLabels.size() != curModel.nFaces())
{
FatalErrorInFunction
<< "Number of face labels not equal to"
<< "number of face in the model. "
<< "Number of face labels: " << faceLabels.size()
<< " number of faces in model: " << curModel.nFaces()
<< abort(FatalError);
}
// make a list of outward-pointing faces
labelListList localFaces(faceLabels.size());
forAll(faceLabels, facei)
{
const label curFaceLabel = faceLabels[facei];
const labelList& curFace = faces[curFaceLabel];
if (owner[curFaceLabel] == cellIndex)
{
localFaces[facei] = curFace;
}
else if (neighbour[curFaceLabel] == cellIndex)
{
// Reverse the face
localFaces[facei].setSize(curFace.size());
forAllReverse(curFace, i)
{
localFaces[facei][curFace.size() - i - 1] =
curFace[i];
}
}
else
{
FatalErrorInFunction
<< "face " << curFaceLabel
<< " does not belong to cell " << cellIndex
<< ". Face owner: " << owner[curFaceLabel] << " neighbour: "
<< neighbour[curFaceLabel]
<< abort(FatalError);
}
}
// Algorithm:
// Make an empty list of pointLabels and initialise it with -1. Pick the
// first face from modelFaces and look through the faces to find one with
// the same number of labels. Insert face by copying its labels into
// pointLabels. Mark the face as used. Loop through all model faces.
// For each model face loop through faces. If the face is unused and the
// numbers of labels fit, try to match the face onto the point labels. If
// at least one edge is matched, insert the face into pointLabels. If at
// any stage the matching algorithm reaches the end of faces, the matching
// algorithm has failed. Once all the faces are matched, the list of
// pointLabels defines the model.
// Make a list of empty pointLabels
labelList pointLabels(curModel.nPoints(), -1);
// Follow the used mesh faces
List<bool> meshFaceUsed(localFaces.size(), false);
// Get the raw model faces
const faceList& modelFaces = curModel.modelFaces();
// Insert the first face into the list
const labelList& firstModelFace =
modelFaces[faceMatchingOrder[fluentCellModelID][0]];
bool found = false;
forAll(localFaces, meshFacei)
{
if (localFaces[meshFacei].size() == firstModelFace.size())
{
// Match. Insert points into the pointLabels
found = true;
const labelList& curMeshFace = localFaces[meshFacei];
meshFaceUsed[meshFacei] = true;
forAll(curMeshFace, pointi)
{
pointLabels[firstModelFace[pointi]] = curMeshFace[pointi];
}
break;
}
}
if (!found)
{
FatalErrorInFunction
<< "Cannot find match for first face. "
<< "cell model: " << curModel.name() << " first model face: "
<< firstModelFace << " Mesh faces: " << localFaces
<< abort(FatalError);
}
for (label modelFacei = 1; modelFacei < modelFaces.size(); modelFacei++)
{
// get the next model face
const labelList& curModelFace =
modelFaces
[faceMatchingOrder[fluentCellModelID][modelFacei]];
found = false;
// Loop through mesh faces until a match is found
forAll(localFaces, meshFacei)
{
if
(
!meshFaceUsed[meshFacei]
&& localFaces[meshFacei].size() == curModelFace.size()
)
{
// A possible match. A mesh face will be rotated, so make a copy
labelList meshFaceLabels = localFaces[meshFacei];
for
(
label rotation = 0;
rotation < meshFaceLabels.size();
rotation++
)
{
// try matching the face
label nMatchedLabels = 0;
forAll(meshFaceLabels, pointi)
{
if
(
pointLabels[curModelFace[pointi]]
== meshFaceLabels[pointi]
)
{
nMatchedLabels++;
}
}
if (nMatchedLabels >= 2)
{
// match!
found = true;
}
if (found)
{
// match found. Insert mesh face
forAll(meshFaceLabels, pointi)
{
pointLabels[curModelFace[pointi]] =
meshFaceLabels[pointi];
}
meshFaceUsed[meshFacei] = true;
break;
}
else
{
// No match found. Rotate face
label firstLabel = meshFaceLabels[0];
for (label i = 1; i < meshFaceLabels.size(); i++)
{
meshFaceLabels[i - 1] = meshFaceLabels[i];
}
meshFaceLabels.last() = firstLabel;
}
}
if (found) break;
}
}
if (!found)
{
// A model face is not matched. Shape detection failed
FatalErrorInFunction
<< "Cannot find match for face "
<< modelFacei
<< ".\nModel: " << curModel.name() << " model face: "
<< curModelFace << " Mesh faces: " << localFaces
<< "Matched points: " << pointLabels
<< abort(FatalError);
}
}
return cellShape(curModel, pointLabels);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //
|