FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

create3DCellShape.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 Description
00025     Construct a cell shape from face information
00026 
00027 \*---------------------------------------------------------------------------*/
00028 
00029 #include "cellShapeRecognition.H"
00030 #include <OpenFOAM/labelList.H>
00031 
00032 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00033 
00034 namespace Foam
00035 {
00036 
00037 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00038 
00039 cellShape create3DCellShape
00040 (
00041     const label cellIndex,
00042     const labelList& faceLabels,
00043     const faceList& faces,
00044     const labelList& owner,
00045     const labelList& neighbour,
00046     const label fluentCellModelID
00047 )
00048 {
00049     // List of pointers to shape models for 3-D shape recognition
00050     static List<const cellModel*> fluentCellModelLookup
00051     (
00052         7,
00053         reinterpret_cast<const cellModel*>(0)
00054     );
00055 
00056     fluentCellModelLookup[2] = cellModeller::lookup("tet");
00057     fluentCellModelLookup[4] = cellModeller::lookup("hex");
00058     fluentCellModelLookup[5] = cellModeller::lookup("pyr");
00059     fluentCellModelLookup[6] = cellModeller::lookup("prism");
00060 
00061     static label faceMatchingOrder[7][6] =
00062     {
00063         {-1, -1, -1, -1, -1, -1},
00064         {-1, -1, -1, -1, -1, -1},
00065         { 0,  1,  2,  3, -1, -1},    // tet
00066         {-1, -1, -1, -1, -1, -1},
00067         { 0,  2,  4,  3,  5,  1},    // hex
00068         { 0,  1,  2,  3,  4, -1},    // pyr
00069         { 0,  2,  3,  4,  1, -1},    // prism
00070     };
00071 
00072     const cellModel& curModel = *fluentCellModelLookup[fluentCellModelID];
00073 
00074     // Checking
00075     if (faceLabels.size() != curModel.nFaces())
00076     {
00077         FatalErrorIn
00078         (
00079             "create3DCellShape(const label cellIndex, "
00080             "const labelList& faceLabels, const labelListList& faces, "
00081             "const labelList& owner, const labelList& neighbour, "
00082             "const label fluentCellModelID)"
00083         )   << "Number of face labels not equal to"
00084             << "number of face in the model. "
00085             << "Number of face labels: " << faceLabels.size()
00086             << " number of faces in model: " << curModel.nFaces()
00087             << abort(FatalError);
00088     }
00089 
00090     // make a list of outward-pointing faces
00091     labelListList localFaces(faceLabels.size());
00092 
00093     forAll  (faceLabels, faceI)
00094     {
00095         const label curFaceLabel = faceLabels[faceI];
00096 
00097         const labelList& curFace = faces[curFaceLabel];
00098 
00099         if (owner[curFaceLabel] == cellIndex)
00100         {
00101             localFaces[faceI] = curFace;
00102         }
00103         else if (neighbour[curFaceLabel] == cellIndex)
00104         {
00105             // Reverse the face
00106             localFaces[faceI].setSize(curFace.size());
00107 
00108             forAllReverse(curFace, i)
00109             {
00110                 localFaces[faceI][curFace.size() - i - 1] =
00111                     curFace[i];
00112             }
00113         }
00114         else
00115         {
00116             FatalErrorIn
00117             (
00118                 "create3DCellShape(const label cellIndex, "
00119                 "const labelList& faceLabels, const labelListList& faces, "
00120                 "const labelList& owner, const labelList& neighbour, "
00121                 "const label fluentCellModelID)"
00122             )   << "face " << curFaceLabel
00123                 << " does not belong to cell " << cellIndex
00124                 << ". Face owner: " << owner[curFaceLabel] << " neighbour: "
00125                 << neighbour[curFaceLabel]
00126                 << abort(FatalError);
00127         }
00128     }
00129 
00130     // Algorithm:
00131     // Make an empty list of pointLabels and initialise it with -1. Pick the
00132     // first face from modelFaces and look through the faces to find one with
00133     // the same number of labels. Insert face by copying its labels into
00134     // pointLabels. Mark the face as used. Loop through all model faces.
00135     // For each model face loop through faces. If the face is unused and the
00136     // numbers of labels fit, try to match the face onto the point labels. If
00137     // at least one edge is matched, insert the face into pointLabels. If at
00138     // any stage the matching algorithm reaches the end of faces, the matching
00139     // algorithm has failed. Once all the faces are matched, the list of
00140     // pointLabels defines the model.
00141 
00142     // Make a list of empty pointLabels
00143     labelList pointLabels(curModel.nPoints(), -1);
00144 
00145     // Follow the used mesh faces
00146     List<bool> meshFaceUsed(localFaces.size(), false);
00147 
00148     // Get the raw model faces
00149     const faceList& modelFaces = curModel.modelFaces();
00150 
00151     // Insert the first face into the list
00152     const labelList& firstModelFace =
00153         modelFaces[faceMatchingOrder[fluentCellModelID][0]];
00154 
00155     bool found = false;
00156 
00157     forAll (localFaces, meshFaceI)
00158     {
00159         if (localFaces[meshFaceI].size() == firstModelFace.size())
00160         {
00161             // Match. Insert points into the pointLabels
00162             found = true;
00163 
00164             const labelList& curMeshFace = localFaces[meshFaceI];
00165 
00166             meshFaceUsed[meshFaceI] = true;
00167 
00168             forAll (curMeshFace, pointI)
00169             {
00170                 pointLabels[firstModelFace[pointI]] = curMeshFace[pointI];
00171             }
00172 
00173             break;
00174         }
00175     }
00176 
00177     if (!found)
00178     {
00179         FatalErrorIn
00180         (
00181             "create3DCellShape(const label cellIndex, "
00182             "const labelList& faceLabels, const labelListList& faces, "
00183             "const labelList& owner, const labelList& neighbour, "
00184             "const label fluentCellModelID)"
00185         )   << "Cannot find match for first face. "
00186             << "cell model: " << curModel.name() << " first model face: "
00187             << firstModelFace << " Mesh faces: " << localFaces
00188             << abort(FatalError);
00189     }
00190 
00191     for (label modelFaceI = 1; modelFaceI < modelFaces.size(); modelFaceI++)
00192     {
00193         // get the next model face
00194         const labelList& curModelFace =
00195             modelFaces
00196             [faceMatchingOrder[fluentCellModelID][modelFaceI]];
00197 
00198         found = false;
00199 
00200         // Loop through mesh faces until a match is found
00201         forAll (localFaces, meshFaceI)
00202         {
00203             if
00204             (
00205                 !meshFaceUsed[meshFaceI]
00206              && localFaces[meshFaceI].size() == curModelFace.size()
00207             )
00208             {
00209                 // A possible match. A mesh face will be rotated, so make a copy
00210                 labelList meshFaceLabels = localFaces[meshFaceI];
00211 
00212                 for
00213                 (
00214                     label rotation = 0;
00215                     rotation < meshFaceLabels.size();
00216                     rotation++
00217                 )
00218                 {
00219                     // try matching the face
00220                     label nMatchedLabels = 0;
00221 
00222                     forAll (meshFaceLabels, pointI)
00223                     {
00224                         if
00225                         (
00226                             pointLabels[curModelFace[pointI]]
00227                          == meshFaceLabels[pointI]
00228                         )
00229                         {
00230                             nMatchedLabels++;
00231                         }
00232                     }
00233 
00234                     if (nMatchedLabels >= 2)
00235                     {
00236                         // match!
00237                         found = true;
00238                     }
00239 
00240                     if (found)
00241                     {
00242                         // match found. Insert mesh face
00243                         forAll (meshFaceLabels, pointI)
00244                         {
00245                             pointLabels[curModelFace[pointI]] =
00246                                 meshFaceLabels[pointI];
00247                         }
00248 
00249                         meshFaceUsed[meshFaceI] = true;
00250 
00251                         break;
00252                     }
00253                     else
00254                     {
00255                         // No match found. Rotate face
00256                         label firstLabel = meshFaceLabels[0];
00257 
00258                         for (label i = 1; i < meshFaceLabels.size(); i++)
00259                         {
00260                             meshFaceLabels[i - 1] = meshFaceLabels[i];
00261                         }
00262 
00263                         meshFaceLabels[meshFaceLabels.size() - 1] = firstLabel;
00264                     }
00265                 }
00266 
00267                 if (found) break;
00268             }
00269         }
00270 
00271         if (!found)
00272         {
00273             // A model face is not matched. Shape detection failed
00274             FatalErrorIn
00275             (
00276                 "create3DCellShape(const label cellIndex, "
00277                 "const labelList& faceLabels, const labelListList& faces, "
00278                 "const labelList& owner, const labelList& neighbour, "
00279                 "const label fluentCellModelID)"
00280             )   << "Cannot find match for face "
00281                 << modelFaceI
00282                 << ".\nModel: " << curModel.name() << " model face: "
00283                 << curModelFace << " Mesh faces: " << localFaces
00284                 << "Matched points: " << pointLabels
00285                 << abort(FatalError);
00286         }
00287     }
00288 
00289     return cellShape(curModel, pointLabels);
00290 }
00291 
00292 
00293 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00294 
00295 } // End namespace Foam
00296 
00297 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines