1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
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
13 the Free Software Foundation, either version 3 of the License, or
14 (at your 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, see <http://www.gnu.org/licenses/>.
25 Construct a cell shape from face information
27 \*---------------------------------------------------------------------------*/
29 #include "cellShapeRecognition.H"
30 #include "labelList.H"
32 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
37 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
39 cellShape create3DCellShape
41 const label cellIndex,
42 const labelList& faceLabels,
43 const faceList& faces,
44 const labelList& owner,
45 const labelList& neighbour,
46 const label fluentCellModelID
49 // List of pointers to shape models for 3-D shape recognition
50 static List<const cellModel*> fluentCellModelLookup
53 reinterpret_cast<const cellModel*>(0)
56 fluentCellModelLookup[2] = cellModeller::lookup("tet");
57 fluentCellModelLookup[4] = cellModeller::lookup("hex");
58 fluentCellModelLookup[5] = cellModeller::lookup("pyr");
59 fluentCellModelLookup[6] = cellModeller::lookup("prism");
61 static label faceMatchingOrder[7][6] =
63 {-1, -1, -1, -1, -1, -1},
64 {-1, -1, -1, -1, -1, -1},
65 { 0, 1, 2, 3, -1, -1}, // tet
66 {-1, -1, -1, -1, -1, -1},
67 { 0, 2, 4, 3, 5, 1}, // hex
68 { 0, 1, 2, 3, 4, -1}, // pyr
69 { 0, 2, 3, 4, 1, -1}, // prism
72 const cellModel& curModel = *fluentCellModelLookup[fluentCellModelID];
75 if (faceLabels.size() != curModel.nFaces())
79 "create3DCellShape(const label cellIndex, "
80 "const labelList& faceLabels, const labelListList& faces, "
81 "const labelList& owner, const labelList& neighbour, "
82 "const label fluentCellModelID)"
83 ) << "Number of face labels not equal to"
84 << "number of face in the model. "
85 << "Number of face labels: " << faceLabels.size()
86 << " number of faces in model: " << curModel.nFaces()
90 // make a list of outward-pointing faces
91 labelListList localFaces(faceLabels.size());
93 forAll(faceLabels, faceI)
95 const label curFaceLabel = faceLabels[faceI];
97 const labelList& curFace = faces[curFaceLabel];
99 if (owner[curFaceLabel] == cellIndex)
101 localFaces[faceI] = curFace;
103 else if (neighbour[curFaceLabel] == cellIndex)
106 localFaces[faceI].setSize(curFace.size());
108 forAllReverse(curFace, i)
110 localFaces[faceI][curFace.size() - i - 1] =
118 "create3DCellShape(const label cellIndex, "
119 "const labelList& faceLabels, const labelListList& faces, "
120 "const labelList& owner, const labelList& neighbour, "
121 "const label fluentCellModelID)"
122 ) << "face " << curFaceLabel
123 << " does not belong to cell " << cellIndex
124 << ". Face owner: " << owner[curFaceLabel] << " neighbour: "
125 << neighbour[curFaceLabel]
126 << abort(FatalError);
131 // Make an empty list of pointLabels and initialise it with -1. Pick the
132 // first face from modelFaces and look through the faces to find one with
133 // the same number of labels. Insert face by copying its labels into
134 // pointLabels. Mark the face as used. Loop through all model faces.
135 // For each model face loop through faces. If the face is unused and the
136 // numbers of labels fit, try to match the face onto the point labels. If
137 // at least one edge is matched, insert the face into pointLabels. If at
138 // any stage the matching algorithm reaches the end of faces, the matching
139 // algorithm has failed. Once all the faces are matched, the list of
140 // pointLabels defines the model.
142 // Make a list of empty pointLabels
143 labelList pointLabels(curModel.nPoints(), -1);
145 // Follow the used mesh faces
146 List<bool> meshFaceUsed(localFaces.size(), false);
148 // Get the raw model faces
149 const faceList& modelFaces = curModel.modelFaces();
151 // Insert the first face into the list
152 const labelList& firstModelFace =
153 modelFaces[faceMatchingOrder[fluentCellModelID][0]];
157 forAll(localFaces, meshFaceI)
159 if (localFaces[meshFaceI].size() == firstModelFace.size())
161 // Match. Insert points into the pointLabels
164 const labelList& curMeshFace = localFaces[meshFaceI];
166 meshFaceUsed[meshFaceI] = true;
168 forAll(curMeshFace, pointI)
170 pointLabels[firstModelFace[pointI]] = curMeshFace[pointI];
181 "create3DCellShape(const label cellIndex, "
182 "const labelList& faceLabels, const labelListList& faces, "
183 "const labelList& owner, const labelList& neighbour, "
184 "const label fluentCellModelID)"
185 ) << "Cannot find match for first face. "
186 << "cell model: " << curModel.name() << " first model face: "
187 << firstModelFace << " Mesh faces: " << localFaces
188 << abort(FatalError);
191 for (label modelFaceI = 1; modelFaceI < modelFaces.size(); modelFaceI++)
193 // get the next model face
194 const labelList& curModelFace =
196 [faceMatchingOrder[fluentCellModelID][modelFaceI]];
200 // Loop through mesh faces until a match is found
201 forAll(localFaces, meshFaceI)
205 !meshFaceUsed[meshFaceI]
206 && localFaces[meshFaceI].size() == curModelFace.size()
209 // A possible match. A mesh face will be rotated, so make a copy
210 labelList meshFaceLabels = localFaces[meshFaceI];
215 rotation < meshFaceLabels.size();
219 // try matching the face
220 label nMatchedLabels = 0;
222 forAll(meshFaceLabels, pointI)
226 pointLabels[curModelFace[pointI]]
227 == meshFaceLabels[pointI]
234 if (nMatchedLabels >= 2)
242 // match found. Insert mesh face
243 forAll(meshFaceLabels, pointI)
245 pointLabels[curModelFace[pointI]] =
246 meshFaceLabels[pointI];
249 meshFaceUsed[meshFaceI] = true;
255 // No match found. Rotate face
256 label firstLabel = meshFaceLabels[0];
258 for (label i = 1; i < meshFaceLabels.size(); i++)
260 meshFaceLabels[i - 1] = meshFaceLabels[i];
263 meshFaceLabels.last() = firstLabel;
273 // A model face is not matched. Shape detection failed
276 "create3DCellShape(const label cellIndex, "
277 "const labelList& faceLabels, const labelListList& faces, "
278 "const labelList& owner, const labelList& neighbour, "
279 "const label fluentCellModelID)"
280 ) << "Cannot find match for face "
282 << ".\nModel: " << curModel.name() << " model face: "
283 << curModelFace << " Mesh faces: " << localFaces
284 << "Matched points: " << pointLabels
285 << abort(FatalError);
289 return cellShape(curModel, pointLabels);
293 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
295 } // End namespace Foam
297 // ************************************************************************* //