1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2004-2011 OpenCFD Ltd.
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/>.
24 \*---------------------------------------------------------------------------*/
26 #include "STARCDMeshReader.H"
27 #include "cyclicPolyPatch.H"
28 #include "emptyPolyPatch.H"
29 #include "wallPolyPatch.H"
30 #include "symmetryPolyPatch.H"
31 #include "cellModeller.H"
36 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
38 const char* const Foam::meshReaders::STARCD::defaultBoundaryName =
39 "Default_Boundary_Region";
41 const char* const Foam::meshReaders::STARCD::defaultSolidBoundaryName =
42 "Default_Boundary_Solid";
44 bool Foam::meshReaders::STARCD::keepSolids = false;
46 const int Foam::meshReaders::STARCD::starToFoamFaceAddr[4][6] =
48 { 4, 5, 2, 3, 0, 1 }, // 11 = pro-STAR hex
49 { 0, 1, 4, -1, 2, 3 }, // 12 = pro-STAR prism
50 { 3, -1, 2, -1, 1, 0 }, // 13 = pro-STAR tetra
51 { 0, -1, 4, 2, 1, 3 } // 14 = pro-STAR pyramid
55 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
57 void Foam::meshReaders::STARCD::readToNewline(IFstream& is)
64 while ((is) && ch != '\n');
68 bool Foam::meshReaders::STARCD::readHeader(IFstream& is, word fileSignature)
72 FatalErrorIn("meshReaders::STARCD::readHeader()")
73 << "cannot read " << fileSignature << " " << is.name()
83 // skip the rest of the line
86 // add other checks ...
87 if (header != fileSignature)
89 Info<< "header mismatch " << fileSignature << " " << is.name()
97 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
99 void Foam::meshReaders::STARCD::readAux(const objectRegistry& registry)
101 boundaryRegion_.readDict(registry);
102 cellTable_.readDict(registry);
106 // read in the points from the .vrt file
108 /*---------------------------------------------------------------------------*\
110 PROSTAR_VERTEX [newline]
113 <version> 0 0 0 0 0 0 0 [newline]
116 <vertexId> <x> <y> <z> [newline]
118 \*---------------------------------------------------------------------------*/
119 void Foam::meshReaders::STARCD::readPoints
121 const fileName& inputName,
122 const scalar scaleFactor
125 const word fileSignature = "PROSTAR_VERTEX";
126 label nPoints = 0, maxId = 0;
129 // get # points and maximum vertex label
131 IFstream is(inputName);
132 readHeader(is, fileSignature);
137 while ((is >> lineLabel).good())
140 maxId = max(maxId, lineLabel);
145 Info<< "Number of points = " << nPoints << endl;
147 // set sizes and reset to invalid values
149 points_.setSize(nPoints);
150 mapToFoamPointId_.setSize(maxId+1);
152 //- original Point number for a given vertex
153 // might need again in the future
154 //// labelList origPointId(nPoints);
155 //// origPointId = -1;
157 mapToFoamPointId_ = -1;
160 // construct pointList and conversion table
161 // from Star vertex numbers to Foam point labels
164 IFstream is(inputName);
165 readHeader(is, fileSignature);
170 while ((is >> lineLabel).good())
172 is >> points_[pointI].x()
173 >> points_[pointI].y()
174 >> points_[pointI].z();
176 // might need again in the future
177 //// origPointId[pointI] = lineLabel;
178 mapToFoamPointId_[lineLabel] = pointI;
182 if (nPoints > pointI)
185 points_.setSize(nPoints);
186 // might need again in the future
187 //// origPointId.setSize(nPoints);
190 if (scaleFactor > 1.0 + SMALL || scaleFactor < 1.0 - SMALL)
192 points_ *= scaleFactor;
197 FatalErrorIn("meshReaders::STARCD::readPoints()")
198 << "no points in file " << inputName
199 << abort(FatalError);
205 // read in the cells from the .cel file
207 /*---------------------------------------------------------------------------*\
209 PROSTAR_CELL [newline]
212 <version> 0 0 0 0 0 0 0 [newline]
215 <cellId> <shapeId> <nLabels> <cellTableId> <typeId> [newline]
216 <cellId> <int1> .. <int8>
217 <cellId> <int9> .. <int16>
237 For primitive cell shapes, the number of vertices will never exceed 8 (hexa)
238 and corresponds to <nLabels>.
239 For polyhedral, <nLabels> includes an index table comprising beg/end pairs
242 Strictly speaking, we only need the cellModeller for adding boundaries.
243 \*---------------------------------------------------------------------------*/
245 void Foam::meshReaders::STARCD::readCells(const fileName& inputName)
247 const word fileSignature = "PROSTAR_CELL";
248 label nFluids = 0, nSolids = 0, nBaffles = 0, nShells = 0;
251 bool unknownVertices = false;
255 // count nFluids, nSolids, nBaffle, nShell and maxId
256 // also see if polyhedral cells were used
258 IFstream is(inputName);
259 readHeader(is, fileSignature);
261 label lineLabel, shapeId, nLabels, cellTableId, typeId;
263 while ((is >> lineLabel).good())
265 label starCellId = lineLabel;
271 // skip the rest of the line
274 // max 8 indices per line
281 if (typeId == starcdFluidType)
284 maxId = max(maxId, starCellId);
286 if (!cellTable_.found(cellTableId))
288 cellTable_.setName(cellTableId);
289 cellTable_.setMaterial(cellTableId, "fluid");
292 else if (typeId == starcdSolidType)
297 maxId = max(maxId, starCellId);
300 if (!cellTable_.found(cellTableId))
302 cellTable_.setName(cellTableId);
303 cellTable_.setMaterial(cellTableId, "solid");
307 else if (typeId == starcdBaffleType)
309 // baffles have no cellTable entry
311 maxId = max(maxId, starCellId);
313 else if (typeId == starcdShellType)
316 if (!cellTable_.found(cellTableId))
318 cellTable_.setName(cellTableId);
319 cellTable_.setMaterial(cellTableId, "shell");
326 Info<< "Number of fluids = " << nFluids << nl
327 << "Number of baffles = " << nBaffles << nl;
330 Info<< "Number of solids = " << nSolids << nl;
334 Info<< "Ignored solids = " << nSolids << nl;
336 Info<< "Ignored shells = " << nShells << endl;
342 nCells = nFluids + nSolids;
349 cellFaces_.setSize(nCells);
350 cellShapes_.setSize(nCells);
351 cellTableId_.setSize(nCells);
353 // information for the interfaces
354 baffleFaces_.setSize(nBaffles);
356 // extra space for baffles
357 origCellId_.setSize(nCells + nBaffles);
358 mapToFoamCellId_.setSize(maxId+1);
359 mapToFoamCellId_ = -1;
362 // avoid undefined shapes for polyhedra
363 cellShape genericShape(*unknownModel, labelList(0));
366 // construct cellFaces_ and possibly cellShapes_
369 FatalErrorIn("meshReaders::STARCD::readCells()")
370 << "no cells in file " << inputName
371 << abort(FatalError);
375 IFstream is(inputName);
376 readHeader(is, fileSignature);
378 labelList starLabels(64);
379 label lineLabel, shapeId, nLabels, cellTableId, typeId;
384 while ((is >> lineLabel).good())
386 label starCellId = lineLabel;
392 if (nLabels > starLabels.size())
394 starLabels.setSize(nLabels);
398 // read indices - max 8 per line
399 for (label i = 0; i < nLabels; ++i)
409 if (typeId == starcdSolidType && !keepSolids)
414 // determine the foam cell shape
415 const cellModel* curModelPtr = NULL;
421 curModelPtr = hexModel;
424 curModelPtr = prismModel;
427 curModelPtr = tetModel;
430 curModelPtr = pyrModel;
436 // primitive cell - use shapes
438 // convert orig vertex Id to point label
440 for (label i=0; i < nLabels; ++i)
442 label pointId = mapToFoamPointId_[starLabels[i]];
445 Info<< "Cells inconsistent with vertex file. "
446 << "Star vertex " << starLabels[i]
447 << " does not exist" << endl;
449 unknownVertices = true;
451 starLabels[i] = pointId;
459 // record original cell number and lookup
460 origCellId_[cellI] = starCellId;
461 mapToFoamCellId_[starCellId] = cellI;
463 cellTableId_[cellI] = cellTableId;
464 cellShapes_[cellI] = cellShape
467 SubList<label>(starLabels, nLabels)
470 cellFaces_[cellI] = cellShapes_[cellI].faces();
473 else if (shapeId == starcdPoly)
476 label nFaces = starLabels[0] - 1;
478 // convert orig vertex id to point label
479 // start with offset (skip the index table)
481 for (label i=starLabels[0]; i < nLabels; ++i)
483 label pointId = mapToFoamPointId_[starLabels[i]];
486 Info<< "Cells inconsistent with vertex file. "
487 << "Star vertex " << starLabels[i]
488 << " does not exist" << endl;
490 unknownVertices = true;
492 starLabels[i] = pointId;
500 // traverse beg/end indices
501 faceList faces(nFaces);
503 for (label i=0; i < nFaces; ++i)
505 label beg = starLabels[i];
506 label n = starLabels[i+1] - beg;
510 SubList<label>(starLabels, n, beg)
524 Info<< "star cell " << starCellId << " has "
526 << " empty faces - could cause boundary "
527 << "addressing problems"
531 faces.setSize(nFaces);
536 FatalErrorIn("meshReaders::STARCD::readCells()")
537 << "star cell " << starCellId << " has " << nFaces
538 << abort(FatalError);
541 // record original cell number and lookup
542 origCellId_[cellI] = starCellId;
543 mapToFoamCellId_[starCellId] = cellI;
545 cellTableId_[cellI] = cellTableId;
546 cellShapes_[cellI] = genericShape;
547 cellFaces_[cellI] = faces;
550 else if (typeId == starcdBaffleType)
554 // convert orig vertex id to point label
556 for (label i=0; i < nLabels; ++i)
558 label pointId = mapToFoamPointId_[starLabels[i]];
561 Info<< "Baffles inconsistent with vertex file. "
562 << "Star vertex " << starLabels[i]
563 << " does not exist" << endl;
565 unknownVertices = true;
567 starLabels[i] = pointId;
578 SubList<label>(starLabels, nLabels)
586 baffleFaces_[baffleI] = f;
587 // insert lookup addressing in normal list
588 mapToFoamCellId_[starCellId] = nCells + baffleI;
589 origCellId_[nCells + baffleI] = starCellId;
595 baffleFaces_.setSize(baffleI);
600 FatalErrorIn("meshReaders::STARCD::readCells()")
601 << "cells with unknown vertices"
602 << abort(FatalError);
608 Info<< "CELLS READ" << endl;
612 mapToFoamPointId_.clear();
616 // read in the boundaries from the .bnd file
618 /*---------------------------------------------------------------------------*\
620 PROSTAR_BOUNDARY [newline]
623 <version> 0 0 0 0 0 0 0 [newline]
626 <boundId> <cellId> <cellFace> <regionId> 0 <boundaryType> [newline]
628 where boundaryType is truncated to 4 characters from one of the following:
634 \*---------------------------------------------------------------------------*/
636 void Foam::meshReaders::STARCD::readBoundary(const fileName& inputName)
638 const word fileSignature = "PROSTAR_BOUNDARY";
639 label nPatches = 0, nFaces = 0, nBafflePatches = 0, maxId = 0;
640 label lineLabel, starCellId, cellFaceId, starRegion, configNumber;
643 labelList mapToFoamPatchId(1000, -1);
644 labelList nPatchFaces(1000, 0);
645 labelList origRegion(1000, 0);
646 patchTypes_.setSize(1000);
648 // this is what we seem to need
649 // these MUST correspond to starToFoamFaceAddr
651 Map<label> faceLookupIndex;
653 faceLookupIndex.insert(hexModel->index(), 0);
654 faceLookupIndex.insert(prismModel->index(), 1);
655 faceLookupIndex.insert(tetModel->index(), 2);
656 faceLookupIndex.insert(pyrModel->index(), 3);
660 // no. of faces (nFaces), no. of patches (nPatches)
661 // and for each of these patches the number of faces
662 // (nPatchFaces[patchLabel])
664 // and a conversion table from Star regions to (Foam) patchLabels
666 // additionally note the no. of baffle patches (nBafflePatches)
667 // so that we sort these to the end of the patch list
668 // - this makes it easier to transfer them to an adjacent patch if reqd
670 IFstream is(inputName);
674 readHeader(is, fileSignature);
676 while ((is >> lineLabel).good())
685 // Build translation table to convert star patch to foam patch
686 label patchLabel = mapToFoamPatchId[starRegion];
687 if (patchLabel == -1)
689 patchLabel = nPatches;
690 mapToFoamPatchId[starRegion] = patchLabel;
691 origRegion[patchLabel] = starRegion;
692 patchTypes_[patchLabel] = patchType;
694 maxId = max(maxId, starRegion);
696 // should actually be case-insensitive
697 if (patchType == "BAFF")
704 nPatchFaces[patchLabel]++;
709 Info<< "No boundary faces in file " << inputName << endl;
714 Info<< "Could not read boundary file " << inputName << endl;
718 // keep empty patch region in reserve
720 Info<< "Number of patches = " << nPatches
721 << " (including extra for missing)" << endl;
724 origRegion.setSize(nPatches);
725 patchTypes_.setSize(nPatches);
726 patchNames_.setSize(nPatches);
727 nPatchFaces.setSize(nPatches);
729 // add our empty patch
730 origRegion[nPatches-1] = 0;
731 nPatchFaces[nPatches-1] = 0;
732 patchTypes_[nPatches-1] = "none";
735 // - use 'Label' entry from "constant/boundaryRegion" dictionary
736 forAll(patchTypes_, patchI)
738 bool foundName = false, foundType = false;
740 Map<dictionary>::const_iterator
741 iter = boundaryRegion_.find(origRegion[patchI]);
745 iter != boundaryRegion_.end()
748 foundType = iter().readIfPresent
754 foundName = iter().readIfPresent
761 // consistent names, in long form and in lowercase
765 forAllIter(string, patchTypes_[patchI], i)
770 if (patchTypes_[patchI] == "symp")
772 patchTypes_[patchI] = "symplane";
774 else if (patchTypes_[patchI] == "cycl")
776 patchTypes_[patchI] = "cyclic";
778 else if (patchTypes_[patchI] == "baff")
780 patchTypes_[patchI] = "baffle";
782 else if (patchTypes_[patchI] == "moni")
784 patchTypes_[patchI] = "monitoring";
788 // create a name if needed
791 patchNames_[patchI] =
792 patchTypes_[patchI] + "_" + name(origRegion[patchI]);
796 // enforce name "Default_Boundary_Region"
797 patchNames_[nPatches-1] = defaultBoundaryName;
799 // sort according to ascending region numbers, but leave
800 // Default_Boundary_Region as the final patch
802 labelList sortedIndices;
803 sortedOrder(SubList<label>(origRegion, nPatches-1), sortedIndices);
805 labelList oldToNew = identity(nPatches);
806 forAll(sortedIndices, i)
808 oldToNew[sortedIndices[i]] = i;
811 inplaceReorder(oldToNew, origRegion);
812 inplaceReorder(oldToNew, patchTypes_);
813 inplaceReorder(oldToNew, patchNames_);
814 inplaceReorder(oldToNew, nPatchFaces);
817 // re-sort to have baffles near the end
821 labelList oldToNew = identity(nPatches);
823 label baffleIndex = (nPatches-1 - nBafflePatches);
825 for (label i=0; i < oldToNew.size()-1; ++i)
827 if (patchTypes_[i] == "baffle")
829 oldToNew[i] = baffleIndex++;
833 oldToNew[i] = newIndex++;
837 inplaceReorder(oldToNew, origRegion);
838 inplaceReorder(oldToNew, patchTypes_);
839 inplaceReorder(oldToNew, patchNames_);
840 inplaceReorder(oldToNew, nPatchFaces);
843 mapToFoamPatchId.setSize(maxId+1, -1);
844 forAll(origRegion, patchI)
846 mapToFoamPatchId[origRegion[patchI]] = patchI;
849 boundaryIds_.setSize(nPatches);
850 forAll(boundaryIds_, patchI)
852 boundaryIds_[patchI].setSize(nPatchFaces[patchI]);
853 nPatchFaces[patchI] = 0;
859 if (nPatches > 1 && mapToFoamCellId_.size() > 1)
861 IFstream is(inputName);
862 readHeader(is, fileSignature);
864 while ((is >> lineLabel).good())
873 label patchI = mapToFoamPatchId[starRegion];
875 // zero-based indexing
880 // convert to FOAM cell number
881 if (starCellId < mapToFoamCellId_.size())
883 cellId = mapToFoamCellId_[starCellId];
889 << "Boundaries inconsistent with cell file. "
890 << "Star cell " << starCellId << " does not exist"
895 // restrict lookup to volume cells (no baffles)
896 if (cellId < cellShapes_.size())
898 label index = cellShapes_[cellId].model().index();
899 if (faceLookupIndex.found(index))
901 index = faceLookupIndex[index];
902 cellFaceId = starToFoamFaceAddr[index][cellFaceId];
907 // we currently use cellId >= nCells to tag baffles,
908 // we can also use a negative face number
912 boundaryIds_[patchI][nPatchFaces[patchI]] =
913 cellFaceIdentifier(cellId, cellFaceId);
915 #ifdef DEBUG_BOUNDARY
916 Info<< "bnd " << cellId << " " << cellFaceId << endl;
918 // increment counter of faces in current patch
919 nPatchFaces[patchI]++;
924 // retain original information in patchPhysicalTypes_ - overwrite latter
925 patchPhysicalTypes_.setSize(patchTypes_.size());
928 forAll(boundaryIds_, patchI)
930 // resize - avoid invalid boundaries
931 if (nPatchFaces[patchI] < boundaryIds_[patchI].size())
933 boundaryIds_[patchI].setSize(nPatchFaces[patchI]);
936 word origType = patchTypes_[patchI];
937 patchPhysicalTypes_[patchI] = origType;
939 if (origType == "symplane")
941 patchTypes_[patchI] = symmetryPolyPatch::typeName;
942 patchPhysicalTypes_[patchI] = patchTypes_[patchI];
944 else if (origType == "wall")
946 patchTypes_[patchI] = wallPolyPatch::typeName;
947 patchPhysicalTypes_[patchI] = patchTypes_[patchI];
949 else if (origType == "cyclic")
951 // incorrect. should be cyclicPatch but this
952 // requires info on connected faces.
953 patchTypes_[patchI] = cyclicPolyPatch::typeName;
954 patchPhysicalTypes_[patchI] = patchTypes_[patchI];
956 else if (origType == "baffle")
958 // incorrect. tag the patch until we get proper support.
959 // set physical type to a canonical "baffle"
960 patchTypes_[patchI] = emptyPolyPatch::typeName;
961 patchPhysicalTypes_[patchI] = "baffle";
965 patchTypes_[patchI] = polyPatch::typeName;
968 Info<< "patch " << patchI
969 << " (region " << origRegion[patchI]
970 << ": " << origType << ") type: '" << patchTypes_[patchI]
971 << "' name: " << patchNames_[patchI] << endl;
975 mapToFoamCellId_.clear();
981 // remove unused points
983 void Foam::meshReaders::STARCD::cullPoints()
985 label nPoints = points_.size();
986 labelList oldToNew(nPoints, -1);
988 // loop through cell faces and note which points are being used
989 forAll(cellFaces_, cellI)
991 const faceList& faces = cellFaces_[cellI];
994 const labelList& labels = faces[i];
997 oldToNew[labels[j]]++;
1002 // the new ordering and the count of unused points
1006 if (oldToNew[i] >= 0)
1008 oldToNew[i] = pointI++;
1012 // report unused points
1013 if (nPoints > pointI)
1015 Info<< "Unused points = " << (nPoints - pointI) << endl;
1018 // adjust points and truncate
1019 inplaceReorder(oldToNew, points_);
1020 points_.setSize(nPoints);
1022 // adjust cellFaces - with mesh shapes this might be faster
1023 forAll(cellFaces_, cellI)
1025 faceList& faces = cellFaces_[cellI];
1028 inplaceRenumber(oldToNew, faces[i]);
1033 forAll(baffleFaces_, faceI)
1035 inplaceRenumber(oldToNew, baffleFaces_[faceI]);
1041 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1043 bool Foam::meshReaders::STARCD::readGeometry(const scalar scaleFactor)
1045 // Info<< "called meshReaders::STARCD::readGeometry" << endl;
1047 readPoints(geometryFile_ + ".vrt", scaleFactor);
1048 readCells(geometryFile_ + ".cel");
1050 readBoundary(geometryFile_ + ".bnd");
1056 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1058 Foam::meshReaders::STARCD::STARCD
1060 const fileName& prefix,
1061 const objectRegistry& registry,
1062 const scalar scaleFactor
1065 meshReader(prefix, scaleFactor),
1067 mapToFoamPointId_(0),
1074 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
1076 Foam::meshReaders::STARCD::~STARCD()
1080 // ************************************************************************* //