openfoam/applications/utilities/mesh/conversion/ensightToFoam/ensightMeshReader.C
Mark Olesen 1339c3357b ENH: general boundBox/treeBoundBox improvements
- null() static method
  * as const reference to the invertedBox with the appropriate casting.

- boundBox inflate(random)
  * refactored from treeBoundBox::extend, but allows in-place modification

- boundBox::hexFaces() instead of boundBox::faces
  * rarely used, but avoids confusion with treeBoundBox::faces
    and reuses hexCell face definitions without code duplication

- boundBox::hexCorners() for corner points corresponding to a hexCell.
  Can also be accessed from a treeBoundBox without ambiguity with
  points(), which could be hex corners (boundBox) or octant corners
  (treeBoundBox)

- boundBox::add with pairs of points
  * convenient (for example) when adding edges or a 'box' that has
    been extracted from a primitive mesh shape.

- declare boundBox nPoints(), nFaces(), nEdges() as per hexCell

ENH: return invertedBox instead of FatalError for empty trees

- similar to #2612

ENH: cellShape(HEX, ...) + boundBox hexCorners for block meshes

STYLE: cellModel::ref(...) instead of de-reference cellModel::ptr(...)
2022-11-24 12:21:01 +00:00

1109 lines
31 KiB
C

/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
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/>.
\*---------------------------------------------------------------------------*/
#include "ensightMeshReader.H"
#include "cellModel.H"
#include "ensightReadFile.H"
#include "matchPoints.H"
#include "mergePoints.H"
#include "ListListOps.H"
#include "stringOps.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace fileFormats
{
defineTypeNameAndDebug(ensightMeshReader, 0);
}
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
const Foam::face& Foam::fileFormats::ensightMeshReader::rotateFace
(
const face& f,
face& rotatedFace
) const
{
label fp = findMin(f);
rotatedFace.setSize(f.size());
forAll(rotatedFace, i)
{
rotatedFace[i] = f[fp];
fp = f.fcIndex(fp);
}
return rotatedFace;
}
void Foam::fileFormats::ensightMeshReader::readVerts
(
ensightReadFile& is,
const label nVerts,
const Map<label>& nodeIdToPoints,
DynamicList<label>& verts
) const
{
verts.clear();
for (label i = 0; i < nVerts; i++)
{
label verti;
is.read(verti);
//if (nodeIdToPoints.size())
//{
// verts.append(nodeIdToPoints[verti]);
//}
//else
{
verts.append(verti-1);
}
}
}
void Foam::fileFormats::ensightMeshReader::readIDs
(
ensightReadFile& is,
const bool doRead,
const label nShapes,
labelList& foamToElem,
Map<label>& elemToFoam
) const
{
const label sz = foamToElem.size();
foamToElem.resize(sz+nShapes);
if (doRead)
{
elemToFoam.resize(sz+nShapes);
for (label shapei = 0; shapei < nShapes; shapei++)
{
label elemi;
is.read(elemi);
foamToElem[sz+shapei] = elemi;
elemToFoam.insert(elemi, sz+shapei);
}
}
else
{
for (label shapei = 0; shapei < nShapes; shapei++)
{
foamToElem[sz+shapei] = sz+shapei;
}
}
}
void Foam::fileFormats::ensightMeshReader::setHandedness
(
const cellModel& model,
DynamicList<label>& verts,
const pointField& points
) const
{
// // From plot3dToFoam/hexBlock.C
// const vector x(points[verts[1]]-points[verts[0]]);
// const scalar xMag(mag(x));
//
// const vector y(points[verts[3]]-points[verts[0]]);
// const scalar yMag(mag(y));
//
// const vector z(points[verts[4]]-points[verts[0]]);
// const scalar zMag(mag(z));
//
// if (xMag > SMALL && yMag > SMALL && zMag > SMALL)
// {
// if (((x ^ y) & z) < 0)
// {
// // Flipped hex
// Swap(verts[0], verts[4]);
// Swap(verts[1], verts[5]);
// Swap(verts[2], verts[6]);
// Swap(verts[3], verts[7]);
// }
// }
if (model.mag(verts, points) < 0)
{
if (verts.size() == 8)
{
// Flipped hex
Swap(verts[0], verts[4]);
Swap(verts[1], verts[5]);
Swap(verts[2], verts[6]);
Swap(verts[3], verts[7]);
}
else if (verts.size() == 4)
{
// Flipped tet. Change orientation of base
Swap(verts[0], verts[1]);
}
else if (verts.size() == 5)
{
// Flipped pyr. Change orientation of base
Swap(verts[1], verts[3]);
}
else if (verts.size() == 6)
{
// Flipped prism.
Swap(verts[0], verts[3]);
Swap(verts[1], verts[4]);
Swap(verts[2], verts[5]);
}
}
}
bool Foam::fileFormats::ensightMeshReader::readGoldPart
(
ensightReadFile& is,
const bool read_node_ids,
const bool read_elem_ids,
pointField& points,
labelList& pointToNodeIds,
Map<label>& nodeIdToPoints,
// 3D-elems : cells (cell-to-faces)
faceListList& cells,
labelList& cellToElemIds,
Map<label>& elemIdToCells,
// 2D-elems : faces
faceList& faces,
labelList& faceToElemIDs,
Map<label>& elemIdToFaces
) const
{
//- Read a single part. Return true if end-of-file reached. Return false
// if reaching next 'part'.
// Work
DynamicList<label> verts;
string line;
while (is.good())
{
do
{
is.readKeyword(line);
}
while (line.empty() && is.good());
const auto split = stringOps::splitSpace(line);
if (split.size() == 0)
{
continue;
}
if (split[0] == "part")
{
return false;
}
else if (split[0] == "node_ids")
{
const label nPoints = points.size();
// Ignore for now
for (label i = 0; i < nPoints; i++)
{
label index;
is.read(index);
}
}
else if (split[0] == "coordinates")
{
label nPoints;
is.read(nPoints);
Pout<< indent << "coordinates " << nPoints
<< " starting at line " << is.lineNumber()
<< " position " << is.stdStream().tellg() << endl;
readIDs
(
is,
read_node_ids,
nPoints,
pointToNodeIds,
nodeIdToPoints
);
points.setSize(nPoints);
for (label pointi = 0; pointi < nPoints; pointi++)
{
is.read(points[pointi].x());
}
for (label pointi = 0; pointi < nPoints; pointi++)
{
is.read(points[pointi].y());
}
for (label pointi = 0; pointi < nPoints; pointi++)
{
is.read(points[pointi].z());
}
}
else if (split[0] == "tetra4")
{
label nShapes;
is.read(nShapes);
Pout<< indent<< "tetra4 " << nShapes
<< " starting at line " << is.lineNumber()
<< " position " << is.stdStream().tellg() << endl;
const label celli = cells.size();
cells.resize(celli+nShapes);
readIDs
(
is,
read_elem_ids,
nShapes,
cellToElemIds,
elemIdToCells
);
const auto& model = cellModel::ref(cellModel::TET);
for (label shapei = 0; shapei < nShapes; shapei++)
{
readVerts(is, 4, nodeIdToPoints, verts);
if (setHandedness_)
{
setHandedness(model, verts, points);
}
const cellShape cellVerts(model, verts);
cells[celli+shapei] = cellVerts.faces();
}
}
else if (split[0] == "pyramid5")
{
label nShapes;
is.read(nShapes);
Pout<< indent<< "pyramid5 " << nShapes
<< " starting at line " << is.lineNumber()
<< " position " << is.stdStream().tellg() << endl;
const label celli = cells.size();
cells.resize(celli+nShapes);
readIDs
(
is,
read_elem_ids,
nShapes,
cellToElemIds,
elemIdToCells
);
const auto& model = cellModel::ref(cellModel::PYR);
for (label shapei = 0; shapei < nShapes; shapei++)
{
readVerts(is, 5, nodeIdToPoints, verts);
if (setHandedness_)
{
setHandedness(model, verts, points);
}
const cellShape cellVerts(model, verts);
cells[celli+shapei] = cellVerts.faces();
}
}
else if (split[0] == "penta6")
{
label nShapes;
is.read(nShapes);
Pout<< indent<< "penta6 " << nShapes
<< " starting at line " << is.lineNumber()
<< " position " << is.stdStream().tellg() << endl;
const label celli = cells.size();
cells.resize(celli+nShapes);
readIDs
(
is,
read_elem_ids,
nShapes,
cellToElemIds,
elemIdToCells
);
const auto& model = cellModel::ref(cellModel::PRISM);
for (label shapei = 0; shapei < nShapes; shapei++)
{
readVerts(is, 6, nodeIdToPoints, verts);
if (setHandedness_)
{
setHandedness(model, verts, points);
}
const cellShape cellVerts(model, verts);
cells[celli+shapei] = cellVerts.faces();
}
}
else if (split[0] == "hexa8")
{
label nShapes;
is.read(nShapes);
Pout<< indent<< "hexa8 " << nShapes
<< " starting at line " << is.lineNumber()
<< " position " << is.stdStream().tellg() << endl;
const label celli = cells.size();
cells.resize(celli+nShapes);
readIDs
(
is,
read_elem_ids,
nShapes,
cellToElemIds,
elemIdToCells
);
const auto& model = cellModel::ref(cellModel::HEX);
for (label shapei = 0; shapei < nShapes; shapei++)
{
readVerts(is, 8, nodeIdToPoints, verts);
if (setHandedness_)
{
setHandedness(model, verts, points);
}
const cellShape cellVerts(model, verts);
cells[celli+shapei] = cellVerts.faces();
}
}
else if (split[0] == "nfaced")
{
label nShapes;
is.read(nShapes);
Pout<< indent<< "nfaced " << nShapes
<< " starting at line " << is.lineNumber()
<< " position " << is.stdStream().tellg() << endl;
const label celli = cells.size();
cells.resize(celli+nShapes);
readIDs
(
is,
read_elem_ids,
nShapes,
cellToElemIds,
elemIdToCells
);
for (label shapei = 0; shapei < nShapes; shapei++)
{
label nFaces;
is.read(nFaces);
faceList& cellFaces = cells[celli+shapei];
cellFaces.setSize(nFaces);
}
for (label shapei = 0; shapei < nShapes; shapei++)
{
faceList& cellFaces = cells[celli+shapei];
forAll(cellFaces, cellFacei)
{
label nVerts;
is.read(nVerts);
cellFaces[cellFacei].setSize(nVerts);
}
}
for (label shapei = 0; shapei < nShapes; shapei++)
{
faceList& cellFaces = cells[celli+shapei];
forAll(cellFaces, cellFacei)
{
face& f = cellFaces[cellFacei];
readVerts(is, f.size(), nodeIdToPoints, verts);
f.labelList::operator=(verts);
forAll(f, fp)
{
if (f[fp] < 0 || f[fp] >= points.size())
{
FatalErrorInFunction<< "Face:" << shapei
<< " verts:" << f
<< " indexes outside points:" << points.size()
<< exit(FatalError);
}
}
}
}
}
else if (split[0] == "tria3")
{
label nShapes;
is.read(nShapes);
Pout<< indent << "tria3 " << nShapes
<< " starting at line " << is.lineNumber()
<< " position " << is.stdStream().tellg() << endl;
const label facei = faces.size();
readIDs
(
is,
read_elem_ids,
nShapes,
faceToElemIDs,
elemIdToFaces
);
faces.setSize(facei+nShapes);
for (label shapei = 0; shapei < nShapes; shapei++)
{
auto& f = faces[facei+shapei];
f.setSize(3);
readVerts(is, f.size(), nodeIdToPoints, verts);
f.labelList::operator=(verts);
}
}
else if (split[0] == "quad4")
{
label nShapes;
is.read(nShapes);
Pout<< indent << "quad4 " << nShapes
<< " starting at line " << is.lineNumber()
<< " position " << is.stdStream().tellg() << endl;
const label facei = faces.size();
readIDs
(
is,
read_elem_ids,
nShapes,
faceToElemIDs,
elemIdToFaces
);
faces.setSize(facei+nShapes);
for (label shapei = 0; shapei < nShapes; shapei++)
{
auto& f = faces[facei+shapei];
f.setSize(4);
readVerts(is, f.size(), nodeIdToPoints, verts);
f.labelList::operator=(verts);
}
}
else if (split[0] == "nsided")
{
label nShapes;
is.read(nShapes);
Pout<< indent << "nsided " << nShapes
<< " starting at line " << is.lineNumber()
<< " position " << is.stdStream().tellg() << endl;
const label facei = faces.size();
readIDs
(
is,
read_elem_ids,
nShapes,
faceToElemIDs,
elemIdToFaces
);
faces.setSize(facei+nShapes);
for (label shapei = 0; shapei < nShapes; shapei++)
{
auto& f = faces[facei+shapei];
label nVerts;
is.read(nVerts);
f.setSize(nVerts);
}
for (label shapei = 0; shapei < nShapes; shapei++)
{
auto& f = faces[facei+shapei];
readVerts(is, f.size(), nodeIdToPoints, verts);
f.labelList::operator=(verts);
}
}
else
{
WarningInFunction << "Unhandled key " << string(split[0])
<< " from line " << line
<< " starting at line " << is.lineNumber()
<< " position " << is.stdStream().tellg() << endl;
}
}
// EOF
return true;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
bool Foam::fileFormats::ensightMeshReader::readGeometry
(
const scalar scaleFactor
)
{
ensightReadFile is(geometryFile_);
// Skip 'binary' tag
is.readBinaryHeader();
string header;
is.read(header);
Info<< "Ensight : " << header << endl;
is.read(header);
Info<< "Ensight : " << header << endl;
bool read_node_ids = false;
bool read_elem_ids = false;
// Storage for all the parts
// ~~~~~~~~~~~~~~~~~~~~~~~~~
List<string> partNames;
DynamicList<label> partIDs; // per part the original Ensight part no
PtrList<pointField> partPoints;
PtrList<labelList> partNodeIDs;
PtrList<Map<label>> partPointIDs;
// Cells (cell-to-faces)
// Note: only one internal mesh supported.
PtrList<faceListList> partCells;
// Element ID for cells
PtrList<labelList> partCellIDs;
PtrList<Map<label>> partCellElemIDs;
// Boundary faces
PtrList<faceList> partFaces;
// Element IDs for faces
PtrList<labelList> partFaceIDs;
PtrList<Map<label>> partFaceElemIDs;
// Parse all
string line;
while (is.good())
{
do
{
is.readKeyword(line);
}
while (line.empty() && is.good());
const auto split = stringOps::splitSpace(line);
if (split[0] == "extents")
{
point min;
point max;
is.read(min.x());
is.read(max.x());
is.read(min.y());
is.read(max.y());
is.read(min.z());
is.read(max.z());
Pout<< indent
<< "Read extents " << boundBox(min, max)
<< endl;
}
else if (split[0] == "node")
{
word id(split[1]);
word op(split[2]);
if (op == "given" || op == "ignore")
{
Pout<< indent << "Reading node ids" << endl;
read_node_ids = true;
}
}
else if (split[0] == "element")
{
word id(split[1]);
word op(split[2]);
if (op == "given" || op == "ignore")
{
Pout<< indent << "Reading element ids" << endl;
read_elem_ids = true;
}
}
else if (split[0] == "part")
{
bool finished = false;
do
{
label partIndex;
is.read(partIndex);
partIDs.append(partIndex);
// Make space
partNames.setSize(partIDs.size());
partPoints.append(new pointField(0));
partNodeIDs.append(new labelList(0));
partPointIDs.append(new Map<label>());
partCells.append(new faceListList(0));
partCellIDs.append(new labelList(0));
partCellElemIDs.append(new Map<label>());
partFaces.append(new faceList(0));
partFaceIDs.append(new labelList(0));
partFaceElemIDs.append(new Map<label>());
is.read(partNames.last());
Pout<< indent
<< "Reading part " << partIndex
<< " name " << partNames.last()
<< " starting at line " << is.lineNumber()
<< " position " << is.stdStream().tellg() << endl;
Pout<< incrIndent;
finished = readGoldPart
(
is,
read_node_ids,
read_elem_ids,
partPoints.last(),
partNodeIDs.last(),
partPointIDs.last(),
// Cells (cell-to-faces)
partCells.last(),
partCellIDs.last(),
partCellElemIDs.last(),
// Faces
partFaces.last(),
partFaceIDs.last(),
partFaceElemIDs.last()
);
partPoints.last() *= scaleFactor;
Pout<< indent
<< "For part " << partIndex
<< " read cells " << partCells.last().size()
<< " faces " << partFaces.last().size()
<< endl;
Pout<< decrIndent;
}
while (!finished);
break;
}
}
// Merge all coordinates
labelListList pointToMerged(partPoints.size());
//- Use point merging - also merges points inside a part which might upset
//- e.g. ami
//{
// label nPoints = 0;
// forAll(partPoints, parti)
// {
// nPoints += partPoints[parti].size();
// }
//
// points_.setSize(nPoints);
// nodeIds_.setSize(nPoints, -1);
// nPoints = 0;
// forAll(partPoints, parti)
// {
// const auto& pts = partPoints[parti];
//
// SubList<point>(points_, pts.size(), nPoints) = pts;
// SubList<label>(nodeIds_, pts.size(), nPoints) =
// partNodeIDs[parti];
//
// auto& map = pointToMerged[parti];
// map = nPoints + identity(pts.size());
//
// nPoints += pts.size();
// }
//
// if (mergeTol_ > 0)
// {
// const scalar mergeDist = mergeTol_*boundBox(points_, true).mag();
//
// labelList sharedToMerged;
// const label nMerged = inplaceMergePoints
// (
// points_,
// mergeDist,
// false,
// sharedToMerged
// );
// Pout<< "Merged " << nMerged << " points out of " << nPoints
// << " using merge tolerance " << mergeTol_
// << ", distance " << mergeDist
// << endl;
//
// forAll(partNodeIDs, parti)
// {
// inplaceRenumber(sharedToMerged, pointToMerged[parti]);
//
// // Now pointToMerged contains the numbering from original,
// // partwise to global points
// UIndirectList<label>(nodeIds_, pointToMerged[parti]) =
// partNodeIDs[parti];
// }
// }
//}
// Merge all coordinates
{
boundBox extents;
label nPoints = 0;
forAll(partPoints, parti)
{
extents.add(partPoints[parti]);
nPoints += partPoints[parti].size();
}
const scalar mergeDist = mergeTol_*extents.mag();
Pout<< "Merging points closer than " << mergeDist
<< " calculated from bounding box " << extents
<< " and mergeTol " << mergeTol_
<< endl;
forAll(partPoints, parti)
{
const auto& pPoints = partPoints[parti];
auto& pPointMap = pointToMerged[parti];
pPointMap.setSize(pPoints.size(), -1);
Pout<< "Matching part " << parti
<< " name " << partNames[parti]
<< " points " << pPoints.size()
<< " to current merged points " << points_.size()
<< endl;
if (points_.empty())
{
points_ = pPoints;
pPointMap = identity(pPoints.size());
}
else
{
// Match to existing
labelList from0To1;
matchPoints
(
pPoints,
points_,
scalarField(pPoints.size(), mergeDist),
false,
from0To1
);
label nAdded = 0;
forAll(from0To1, partPointi)
{
const label pointi = from0To1[partPointi];
if (pointi != -1)
{
pPointMap[partPointi] = pointi;
}
else
{
nAdded++;
}
}
const label nOldPoints = points_.size();
points_.setSize(nOldPoints+nAdded);
nAdded = 0;
forAll(from0To1, partPointi)
{
if (from0To1[partPointi] == -1)
{
const label newPointi = nOldPoints+nAdded++;
points_[newPointi] = pPoints[partPointi];
pPointMap[partPointi] = newPointi;
}
}
}
}
// Now we have complete points. Take over element IDs.
nodeIds_.setSize(points_.size());
forAll(partNodeIDs, parti)
{
const auto& pPointMap = pointToMerged[parti];
UIndirectList<label>(nodeIds_, pPointMap) = partNodeIDs[parti];
}
Pout<< "Merged from " << nPoints << " down to " << points_.size()
<< " points" << endl;
}
// Merge all cells
labelList cellOffsets(partCells.size()+1);
cellOffsets[0] = 0;
{
label nCells = 0;
forAll(partCells, parti)
{
nCells += partCells[parti].size();
cellOffsets[parti+1] = nCells;
}
cellFaces_.setSize(nCells);
cellTableId_.setSize(nCells);
elementIds_.setSize(nCells, -1);
forAll(partCells, parti)
{
// Copy cells into position
const auto& cells = partCells[parti];
SubList<faceList> cellSlice
(
cellFaces_,
cells.size(),
cellOffsets[parti]
);
cellSlice = cells;
SubList<label>
(
cellTableId_,
cells.size(),
cellOffsets[parti]
) = parti;
SubList<label>
(
elementIds_,
cells.size(),
cellOffsets[parti]
) = partCellIDs[parti];
// Renumber faces
const auto& pointMap = pointToMerged[parti];
for (auto& cellFaces : cellSlice)
{
for (auto& f : cellFaces)
{
inplaceRenumber(pointMap, f);
}
}
}
}
// Add cells to separate zones
forAll(partCells, parti)
{
cellTable_.setMaterial(parti, "fluid");
cellTable_.setName(parti, "part" + Foam::name(partIDs[parti]));
}
// Build map from face to cell and index. Note: use exact match
// - no circular equivalence
// - but instead pass in ordered faces (lowest numbered vertex first)
HashTable<cellFaceIdentifier, face, face::symmHasher> vertsToCell
(
2*cellOffsets.last()
);
// Insert cell's faces into hashtable
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
face rotatedFace;
forAll(cellFaces_, celli)
{
const auto& cFaces = cellFaces_[celli];
forAll(cFaces, cFacei)
{
const face& f = rotateFace(cFaces[cFacei], rotatedFace);
const auto fFnd = vertsToCell.find(f);
if (fFnd)
{
// Already inserted. Internal face.
vertsToCell.erase(fFnd);
}
else
{
vertsToCell.insert(f, cellFaceIdentifier(celli, cFacei));
}
}
}
labelList patchToPart(partNames.size());
label nPatches = 0;
forAll(partFaces, parti)
{
if (partFaces[parti].size())
{
Pout<< "Using part " << parti
<< " name " << partNames[parti]
<< " as patch " << nPatches
<< endl;
patchToPart[nPatches++] = parti;
}
}
patchToPart.setSize(nPatches);
boundaryIds_.setSize(nPatches);
patchTypes_.setSize(nPatches, "wall");
patchNames_.setSize(nPatches);
forAll(patchNames_, patchi)
{
const label parti = patchToPart[patchi];
Pout<< "Matching part " << parti
<< " name " << partNames[parti]
<< " faces " << partFaces[parti].size()
//<< " points " << partPoints[parti].size()
<< " to merged faces " << vertsToCell.size()
<< ", merged points " << points_.size()
<< endl;
patchNames_[patchi] = word::validate(partNames[parti]);
const auto& pointMap = pointToMerged[parti];
const auto& faces = partFaces[parti];
auto& partCellAndFace = boundaryIds_[patchi];
partCellAndFace.setSize(faces.size());
label patchFacei = 0;
forAll(faces, facei)
{
if (faces[facei].empty())
{
Pout<< "Ignoring empty face:" << facei << endl;
continue;
}
// Rewrite into mesh-point ordering
const face newF(pointMap, faces[facei]);
// Lookup cell and face on cell using the vertices
const auto cAndF = vertsToCell.find
(
rotateFace
(
newF,
rotatedFace
)
);
if (!cAndF)
{
//WarningInFunction
// << "Did not find face " << facei
// << " verts:" << faces[facei]
// << " renumbered:" << newF
// << " rotated:" << rotatedFace
// << " in part " << parti
// << endl;
}
else
{
partCellAndFace[patchFacei++] = cAndF();
vertsToCell.erase(cAndF);
}
}
partCellAndFace.setSize(patchFacei);
}
patchPhysicalTypes_.setSize(nPatches, "wall");
patchStarts_.setSize(nPatches, 0);
patchSizes_.setSize(nPatches, 0);
if (vertsToCell.size())
{
// Unused internal or boundary faces
boundaryIds_.append(List<cellFaceIdentifier>(0));
{
auto& cellAndFaces = boundaryIds_.last();
cellAndFaces.setSize(vertsToCell.size());
label i = 0;
for (const auto& e : vertsToCell)
{
cellAndFaces[i++] = e;
}
}
patchTypes_.append("empty");
patchNames_.append("defaultFaces");
patchPhysicalTypes_.append("empty");
patchStarts_.append(0);
patchSizes_.append(0);
Pout<< "Introducing default patch " << patchNames_.size()-1
<< " name " << patchNames_.last() << endl;
}
return true;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::fileFormats::ensightMeshReader::ensightMeshReader
(
const fileName& geomFile,
const objectRegistry& registry,
const scalar mergeTol,
const scalar scaleFactor,
const bool setHandedness
)
:
meshReader(geomFile, scaleFactor),
mergeTol_(mergeTol),
setHandedness_(setHandedness)
{}
// ************************************************************************* //