openfoam/applications/utilities/mesh/conversion/fluentMeshToFoam/create3DCellShape.C
2019-10-31 14:48:44 +00:00

280 lines
8.9 KiB
C

/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
-------------------------------------------------------------------------------
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,
nullptr
);
fluentCellModelLookup[2] = cellModel::ptr(cellModel::TET);
fluentCellModelLookup[4] = cellModel::ptr(cellModel::HEX);
fluentCellModelLookup[5] = cellModel::ptr(cellModel::PYR);
fluentCellModelLookup[6] = cellModel::ptr(cellModel::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
// ************************************************************************* //