STARCDMeshReader.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2020 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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.
15 
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
19  for more details.
20 
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/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "STARCDMeshReader.H"
27 #include "mergedCyclicPolyPatch.H"
28 #include "emptyPolyPatch.H"
29 #include "wallPolyPatch.H"
30 #include "symmetryPolyPatch.H"
31 #include "cellModeller.H"
32 #include "ListOps.H"
33 #include "IFstream.H"
34 #include "IOMap.H"
35 
36 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
37 
39  "Default_Boundary_Region";
40 
42  "Default_Boundary_Solid";
43 
45 
47 {
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
52 };
53 
54 
55 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
56 
58 {
59  char ch = '\n';
60  do
61  {
62  (is).get(ch);
63  }
64  while ((is) && ch != '\n');
65 }
66 
67 
69 {
70  if (!is.good())
71  {
73  << abort(FatalError);
74  }
75 
76  word header;
77  label majorVersion;
78 
79  is >> header;
80  is >> majorVersion;
81 
82  // skip the rest of the line
83  readToNewline(is);
84 
85  // add other checks ...
86  if (header != fileSignature)
87  {
88  Info<< "header mismatch " << fileSignature << " " << is.name()
89  << endl;
90  }
91 
92  return true;
93 }
94 
95 
97 {
98  boundaryRegion_.readDict(registry);
99  cellTable_.readDict(registry);
100 }
101 
102 
103 // read in the points from the .vrt file
104 //
105 /*---------------------------------------------------------------------------*\
106 Line 1:
107  PROSTAR_VERTEX [newline]
108 
109 Line 2:
110  <version> 0 0 0 0 0 0 0 [newline]
111 
112 Body:
113  <vertexId> <x> <y> <z> [newline]
114 
115 \*---------------------------------------------------------------------------*/
117 (
118  const fileName& inputName,
119  const scalar scaleFactor
120 )
121 {
122  const word fileSignature = "PROSTAR_VERTEX";
123  label nPoints = 0, maxId = 0;
124 
125  // Pass 1:
126  // get # points and maximum vertex label
127  {
128  IFstream is(inputName);
129  readHeader(is, fileSignature);
130 
131  label lineLabel;
132  scalar x, y, z;
133 
134  while ((is >> lineLabel).good())
135  {
136  nPoints++;
137  maxId = max(maxId, lineLabel);
138  is >> x >> y >> z;
139  }
140  }
141 
142  Info<< "Number of points = " << nPoints << endl;
143 
144  // set sizes and reset to invalid values
145 
146  points_.setSize(nPoints);
147  mapToFoamPointId_.setSize(maxId+1);
148 
149  //- Original Point number for a given vertex
150  // might need again in the future
153 
154  mapToFoamPointId_ = -1;
155 
156  // Pass 2:
157  // construct pointList and conversion table
158  // from Star vertex numbers to Foam point labels
159  if (nPoints > 0)
160  {
161  IFstream is(inputName);
162  readHeader(is, fileSignature);
163 
164  label lineLabel;
165 
166  label pointi = 0;
167  while ((is >> lineLabel).good())
168  {
169  is >> points_[pointi].x()
170  >> points_[pointi].y()
171  >> points_[pointi].z();
172 
173  // might need again in the future
175  mapToFoamPointId_[lineLabel] = pointi;
176  pointi++;
177  }
178 
179  if (nPoints > pointi)
180  {
181  nPoints = pointi;
182  points_.setSize(nPoints);
183  // might need again in the future
185  }
186 
187  if (scaleFactor > 1.0 + small || scaleFactor < 1.0 - small)
188  {
189  points_ *= scaleFactor;
190  }
191  }
192  else
193  {
195  << "no points in file " << inputName
196  << abort(FatalError);
197  }
198 
199 }
200 
201 
202 // read in the cells from the .cel file
203 //
204 /*---------------------------------------------------------------------------*\
205 Line 1:
206  PROSTAR_CELL [newline]
207 
208 Line 2:
209  <version> 0 0 0 0 0 0 0 [newline]
210 
211 Body:
212  <cellId> <shapeId> <nLabels> <cellTableId> <typeId> [newline]
213  <cellId> <int1> .. <int8>
214  <cellId> <int9> .. <int16>
215 
216  with shapeId:
217  * 1 = point
218  * 2 = line
219  * 3 = shell
220  * 11 = hexa
221  * 12 = prism
222  * 13 = tetra
223  * 14 = pyramid
224  * 255 = polyhedron
225 
226  with typeId
227  * 1 = fluid
228  * 2 = solid
229  * 3 = baffle
230  * 4 = shell
231  * 5 = line
232  * 6 = point
233 
234 For primitive cell shapes, the number of vertices will never exceed 8 (hexa)
235 and corresponds to <nLabels>.
236 For polyhedral, <nLabels> includes an index table comprising beg/end pairs
237 for each cell face.
238 
239 Strictly speaking, we only need the cellModeller for adding boundaries.
240 \*---------------------------------------------------------------------------*/
241 
243 {
244  const word fileSignature = "PROSTAR_CELL";
245  label nFluids = 0, nSolids = 0, nBaffles = 0, nShells = 0;
246  label maxId = 0;
247 
248  bool unknownVertices = false;
249 
250 
251  // Pass 1:
252  // count nFluids, nSolids, nBaffle, nShell and maxId
253  // also see if polyhedral cells were used
254  {
255  IFstream is(inputName);
256  readHeader(is, fileSignature);
257 
258  label lineLabel, shapeId, nLabels, cellTableId, typeId;
259 
260  while ((is >> lineLabel).good())
261  {
262  label starCellId = lineLabel;
263  is >> shapeId
264  >> nLabels
265  >> cellTableId
266  >> typeId;
267 
268  // skip the rest of the line
269  readToNewline(is);
270 
271  // max 8 indices per line
272  while (nLabels > 0)
273  {
274  readToNewline(is);
275  nLabels -= 8;
276  }
277 
278  if (typeId == starcdFluidType)
279  {
280  nFluids++;
281  maxId = max(maxId, starCellId);
282 
283  if (!cellTable_.found(cellTableId))
284  {
285  cellTable_.setName(cellTableId);
286  cellTable_.setMaterial(cellTableId, "fluid");
287  }
288  }
289  else if (typeId == starcdSolidType)
290  {
291  nSolids++;
292  if (keepSolids)
293  {
294  maxId = max(maxId, starCellId);
295  }
296 
297  if (!cellTable_.found(cellTableId))
298  {
299  cellTable_.setName(cellTableId);
300  cellTable_.setMaterial(cellTableId, "solid");
301  }
302 
303  }
304  else if (typeId == starcdBaffleType)
305  {
306  // baffles have no cellTable entry
307  nBaffles++;
308  maxId = max(maxId, starCellId);
309  }
310  else if (typeId == starcdShellType)
311  {
312  nShells++;
313  if (!cellTable_.found(cellTableId))
314  {
315  cellTable_.setName(cellTableId);
316  cellTable_.setMaterial(cellTableId, "shell");
317  }
318  }
319 
320  }
321  }
322 
323  Info<< "Number of fluids = " << nFluids << nl
324  << "Number of baffles = " << nBaffles << nl;
325  if (keepSolids)
326  {
327  Info<< "Number of solids = " << nSolids << nl;
328  }
329  else
330  {
331  Info<< "Ignored solids = " << nSolids << nl;
332  }
333  Info<< "Ignored shells = " << nShells << endl;
334 
335 
336  label nCells;
337  if (keepSolids)
338  {
339  nCells = nFluids + nSolids;
340  }
341  else
342  {
343  nCells = nFluids;
344  }
345 
346  cellFaces_.setSize(nCells);
347  cellShapes_.setSize(nCells);
348  cellTableId_.setSize(nCells);
349 
350  // information for the interfaces
351  baffleFaces_.setSize(nBaffles);
352 
353  // extra space for baffles
354  origCellId_.setSize(nCells + nBaffles);
355  mapToFoamCellId_.setSize(maxId+1);
356  mapToFoamCellId_ = -1;
357 
358 
359  // avoid undefined shapes for polyhedra
360  cellShape genericShape(*unknownModel, labelList(0));
361 
362  // Pass 2:
363  // construct cellFaces_ and possibly cellShapes_
364  if (nCells <= 0)
365  {
367  << "no cells in file " << inputName
368  << abort(FatalError);
369  }
370  else
371  {
372  IFstream is(inputName);
373  readHeader(is, fileSignature);
374 
375  labelList starLabels(64);
376  label lineLabel, shapeId, nLabels, cellTableId, typeId;
377 
378  label celli = 0;
379  label baffleI = 0;
380 
381  while ((is >> lineLabel).good())
382  {
383  label starCellId = lineLabel;
384  is >> shapeId
385  >> nLabels
386  >> cellTableId
387  >> typeId;
388 
389  if (nLabels > starLabels.size())
390  {
391  starLabels.setSize(nLabels);
392  }
393  starLabels = -1;
394 
395  // read indices - max 8 per line
396  for (label i = 0; i < nLabels; ++i)
397  {
398  if ((i % 8) == 0)
399  {
400  is >> lineLabel;
401  }
402  is >> starLabels[i];
403  }
404 
405  // skip solid cells
406  if (typeId == starcdSolidType && !keepSolids)
407  {
408  continue;
409  }
410 
411  // determine the foam cell shape
412  const cellModel* curModelPtr = nullptr;
413 
414  // fluid/solid cells
415  switch (shapeId)
416  {
417  case starcdHex:
418  curModelPtr = hexModel;
419  break;
420  case starcdPrism:
421  curModelPtr = prismModel;
422  break;
423  case starcdTet:
424  curModelPtr = tetModel;
425  break;
426  case starcdPyr:
427  curModelPtr = pyrModel;
428  break;
429  }
430 
431  if (curModelPtr)
432  {
433  // primitive cell - use shapes
434 
435  // convert orig vertex Id to point label
436  bool isBad = false;
437  for (label i=0; i < nLabels; ++i)
438  {
439  label pointId = mapToFoamPointId_[starLabels[i]];
440  if (pointId < 0)
441  {
442  Info<< "Cells inconsistent with vertex file. "
443  << "Star vertex " << starLabels[i]
444  << " does not exist" << endl;
445  isBad = true;
446  unknownVertices = true;
447  }
448  starLabels[i] = pointId;
449  }
450 
451  if (isBad)
452  {
453  continue;
454  }
455 
456  // record original cell number and lookup
457  origCellId_[celli] = starCellId;
458  mapToFoamCellId_[starCellId] = celli;
459 
460  cellTableId_[celli] = cellTableId;
461  cellShapes_[celli] = cellShape
462  (
463  *curModelPtr,
464  SubList<label>(starLabels, nLabels)
465  );
466 
467  cellFaces_[celli] = cellShapes_[celli].faces();
468  celli++;
469  }
470  else if (shapeId == starcdPoly)
471  {
472  // polyhedral cell
473  label nFaces = starLabels[0] - 1;
474 
475  // convert orig vertex id to point label
476  // start with offset (skip the index table)
477  bool isBad = false;
478  for (label i=starLabels[0]; i < nLabels; ++i)
479  {
480  label pointId = mapToFoamPointId_[starLabels[i]];
481  if (pointId < 0)
482  {
483  Info<< "Cells inconsistent with vertex file. "
484  << "Star vertex " << starLabels[i]
485  << " does not exist" << endl;
486  isBad = true;
487  unknownVertices = true;
488  }
489  starLabels[i] = pointId;
490  }
491 
492  if (isBad)
493  {
494  continue;
495  }
496 
497  // traverse beg/end indices
498  faceList faces(nFaces);
499  label facei = 0;
500  for (label i=0; i < nFaces; ++i)
501  {
502  label beg = starLabels[i];
503  label n = starLabels[i+1] - beg;
504 
505  face f
506  (
507  SubList<label>(starLabels, n, beg)
508  );
509 
510  f.collapse();
511 
512  // valid faces only
513  if (f.size() >= 3)
514  {
515  faces[facei++] = f;
516  }
517  }
518 
519  if (nFaces > facei)
520  {
521  Info<< "star cell " << starCellId << " has "
522  << (nFaces - facei)
523  << " empty faces - could cause boundary "
524  << "addressing problems"
525  << endl;
526 
527  nFaces = facei;
528  faces.setSize(nFaces);
529  }
530 
531  if (nFaces < 4)
532  {
534  << "star cell " << starCellId << " has " << nFaces
535  << abort(FatalError);
536  }
537 
538  // record original cell number and lookup
539  origCellId_[celli] = starCellId;
540  mapToFoamCellId_[starCellId] = celli;
541 
542  cellTableId_[celli] = cellTableId;
543  cellShapes_[celli] = genericShape;
544  cellFaces_[celli] = faces;
545  celli++;
546  }
547  else if (typeId == starcdBaffleType)
548  {
549  // baffles
550 
551  // convert orig vertex id to point label
552  bool isBad = false;
553  for (label i=0; i < nLabels; ++i)
554  {
555  label pointId = mapToFoamPointId_[starLabels[i]];
556  if (pointId < 0)
557  {
558  Info<< "Baffles inconsistent with vertex file. "
559  << "Star vertex " << starLabels[i]
560  << " does not exist" << endl;
561  isBad = true;
562  unknownVertices = true;
563  }
564  starLabels[i] = pointId;
565  }
566 
567  if (isBad)
568  {
569  continue;
570  }
571 
572 
573  face f
574  (
575  SubList<label>(starLabels, nLabels)
576  );
577 
578  f.collapse();
579 
580  // valid faces only
581  if (f.size() >= 3)
582  {
583  baffleFaces_[baffleI] = f;
584  // insert lookup addressing in normal list
585  mapToFoamCellId_[starCellId] = nCells + baffleI;
586  origCellId_[nCells + baffleI] = starCellId;
587  baffleI++;
588  }
589  }
590  }
591 
592  baffleFaces_.setSize(baffleI);
593  }
594 
595  if (unknownVertices)
596  {
598  << "cells with unknown vertices"
599  << abort(FatalError);
600  }
601 
602  // truncate lists
603 
604 #ifdef DEBUG_READING
605  Info<< "CELLS READ" << endl;
606 #endif
607 
608  // cleanup
610 }
611 
612 
613 // read in the boundaries from the .bnd file
614 //
615 /*---------------------------------------------------------------------------*\
616 Line 1:
617  PROSTAR_BOUNDARY [newline]
618 
619 Line 2:
620  <version> 0 0 0 0 0 0 0 [newline]
621 
622 Body:
623  <boundId> <cellId> <cellFace> <regionId> 0 <boundaryType> [newline]
624 
625 where boundaryType is truncated to 4 characters from one of the following:
626 INLET
627 PRESSURE
628 OUTLET
629 BAFFLE
630 etc,
631 \*---------------------------------------------------------------------------*/
632 
634 {
635  const word fileSignature = "PROSTAR_BOUNDARY";
636  label nPatches = 0, nFaces = 0, nBafflePatches = 0, maxId = 0;
637  label lineLabel, starCellId, cellFaceId, starRegion, configNumber;
638  word patchType;
639 
640  labelList mapToFoamPatchId(1000, label(-1));
641  labelList nPatchFaces(1000, label(0));
642  labelList origRegion(1000, label(0));
643  patchTypes_.setSize(1000);
644 
645  // this is what we seem to need
646  // these MUST correspond to starToFoamFaceAddr
647  //
648  Map<label> faceLookupIndex;
649 
650  faceLookupIndex.insert(hexModel->index(), 0);
651  faceLookupIndex.insert(prismModel->index(), 1);
652  faceLookupIndex.insert(tetModel->index(), 2);
653  faceLookupIndex.insert(pyrModel->index(), 3);
654 
655  // Pass 1:
656  // collect
657  // no. of faces (nFaces), no. of patches (nPatches)
658  // and for each of these patches the number of faces
659  // (nPatchFaces[patchLabel])
660  //
661  // and a conversion table from Star regions to (Foam) patchLabels
662  //
663  // additionally note the no. of baffle patches (nBafflePatches)
664  // so that we sort these to the end of the patch list
665  // - this makes it easier to transfer them to an adjacent patch if reqd
666  {
667  IFstream is(inputName);
668 
669  if (is.good())
670  {
671  readHeader(is, fileSignature);
672 
673  while ((is >> lineLabel).good())
674  {
675  nFaces++;
676  is >> starCellId
677  >> cellFaceId
678  >> starRegion
679  >> configNumber
680  >> patchType;
681 
682  // Build translation table to convert star patch to foam patch
683  label patchLabel = mapToFoamPatchId[starRegion];
684  if (patchLabel == -1)
685  {
686  patchLabel = nPatches;
687  mapToFoamPatchId[starRegion] = patchLabel;
688  origRegion[patchLabel] = starRegion;
689  patchTypes_[patchLabel] = patchType;
690 
691  maxId = max(maxId, starRegion);
692 
693  // should actually be case-insensitive
694  if (patchType == "BAFF")
695  {
696  nBafflePatches++;
697  }
698  nPatches++;
699  }
700 
701  nPatchFaces[patchLabel]++;
702  }
703 
704  if (nPatches == 0)
705  {
706  Info<< "No boundary faces in file " << inputName << endl;
707  }
708  }
709  else
710  {
711  Info<< "Could not read boundary file " << inputName << endl;
712  }
713  }
714 
715  // keep empty patch region in reserve
716  nPatches++;
717  Info<< "Number of patches = " << nPatches
718  << " (including extra for missing)" << endl;
719 
720  // resize
721  origRegion.setSize(nPatches);
722  patchTypes_.setSize(nPatches);
723  patchNames_.setSize(nPatches);
724  nPatchFaces.setSize(nPatches);
725 
726  // add our empty patch
727  origRegion[nPatches-1] = 0;
728  nPatchFaces[nPatches-1] = 0;
729  patchTypes_[nPatches-1] = "none";
730 
731  // create names
732  // - use 'Label' entry from "constant/boundaryRegion" dictionary
734  {
735  bool foundName = false, foundType = false;
736 
738  iter = boundaryRegion_.find(origRegion[patchi]);
739 
740  if
741  (
742  iter != boundaryRegion_.end()
743  )
744  {
745  foundType = iter().readIfPresent
746  (
747  "BoundaryType",
748  patchTypes_[patchi]
749  );
750 
751  foundName = iter().readIfPresent
752  (
753  "Label",
754  patchNames_[patchi]
755  );
756  }
757 
758  // consistent names, in long form and in lowercase
759  if (!foundType)
760  {
761  // transform
762  forAllIter(string, patchTypes_[patchi], i)
763  {
764  *i = tolower(*i);
765  }
766 
767  if (patchTypes_[patchi] == "symp")
768  {
769  patchTypes_[patchi] = "symplane";
770  }
771  else if (patchTypes_[patchi] == "cycl")
772  {
773  patchTypes_[patchi] = "cyclic";
774  }
775  else if (patchTypes_[patchi] == "baff")
776  {
777  patchTypes_[patchi] = "baffle";
778  }
779  else if (patchTypes_[patchi] == "moni")
780  {
781  patchTypes_[patchi] = "monitoring";
782  }
783  }
784 
785  // create a name if needed
786  if (!foundName)
787  {
789  patchTypes_[patchi] + "_" + name(origRegion[patchi]);
790  }
791  }
792 
793  // enforce name "Default_Boundary_Region"
794  patchNames_[nPatches-1] = defaultBoundaryName;
795 
796  // sort according to ascending region numbers, but leave
797  // Default_Boundary_Region as the final patch
798  {
799  labelList sortedIndices;
800  sortedOrder(SubList<label>(origRegion, nPatches-1), sortedIndices);
801 
802  labelList oldToNew = identity(nPatches);
803  forAll(sortedIndices, i)
804  {
805  oldToNew[sortedIndices[i]] = i;
806  }
807 
808  inplaceReorder(oldToNew, origRegion);
809  inplaceReorder(oldToNew, patchTypes_);
810  inplaceReorder(oldToNew, patchNames_);
811  inplaceReorder(oldToNew, nPatchFaces);
812  }
813 
814  // re-sort to have baffles near the end
815  nBafflePatches = 1;
816  if (nBafflePatches)
817  {
818  labelList oldToNew = identity(nPatches);
819  label newIndex = 0;
820  label baffleIndex = (nPatches-1 - nBafflePatches);
821 
822  for (label i=0; i < oldToNew.size()-1; ++i)
823  {
824  if (patchTypes_[i] == "baffle")
825  {
826  oldToNew[i] = baffleIndex++;
827  }
828  else
829  {
830  oldToNew[i] = newIndex++;
831  }
832  }
833 
834  inplaceReorder(oldToNew, origRegion);
835  inplaceReorder(oldToNew, patchTypes_);
836  inplaceReorder(oldToNew, patchNames_);
837  inplaceReorder(oldToNew, nPatchFaces);
838  }
839 
840  mapToFoamPatchId.setSize(maxId+1, -1);
841  forAll(origRegion, patchi)
842  {
843  mapToFoamPatchId[origRegion[patchi]] = patchi;
844  }
845 
846  boundaryIds_.setSize(nPatches);
848  {
849  boundaryIds_[patchi].setSize(nPatchFaces[patchi]);
850  nPatchFaces[patchi] = 0;
851  }
852 
853 
854  // Pass 2:
855  //
856  if (nPatches > 1 && mapToFoamCellId_.size() > 1)
857  {
858  IFstream is(inputName);
859  readHeader(is, fileSignature);
860 
861  while ((is >> lineLabel).good())
862  {
863  is
864  >> starCellId
865  >> cellFaceId
866  >> starRegion
867  >> configNumber
868  >> patchType;
869 
870  label patchi = mapToFoamPatchId[starRegion];
871 
872  // zero-based indexing
873  cellFaceId--;
874 
875  label cellId = -1;
876 
877  // convert to FOAM cell number
878  if (starCellId < mapToFoamCellId_.size())
879  {
880  cellId = mapToFoamCellId_[starCellId];
881  }
882 
883  if (cellId < 0)
884  {
885  Info
886  << "Boundaries inconsistent with cell file. "
887  << "Star cell " << starCellId << " does not exist"
888  << endl;
889  }
890  else
891  {
892  // restrict lookup to volume cells (no baffles)
893  if (cellId < cellShapes_.size())
894  {
895  label index = cellShapes_[cellId].model().index();
896  if (faceLookupIndex.found(index))
897  {
898  index = faceLookupIndex[index];
899  cellFaceId = starToFoamFaceAddr[index][cellFaceId];
900  }
901  }
902  else
903  {
904  // we currently use cellId >= nCells to tag baffles,
905  // we can also use a negative face number
906  cellFaceId = -1;
907  }
908 
909  boundaryIds_[patchi][nPatchFaces[patchi]] =
910  cellFaceIdentifier(cellId, cellFaceId);
911 
912 #ifdef DEBUG_BOUNDARY
913  Info<< "bnd " << cellId << " " << cellFaceId << endl;
914 #endif
915  // increment counter of faces in current patch
916  nPatchFaces[patchi]++;
917  }
918  }
919  }
920 
921  // retain original information in patchPhysicalTypes_ - overwrite latter
923 
924 
926  {
927  // resize - avoid invalid boundaries
928  if (nPatchFaces[patchi] < boundaryIds_[patchi].size())
929  {
930  boundaryIds_[patchi].setSize(nPatchFaces[patchi]);
931  }
932 
933  word origType = patchTypes_[patchi];
934  patchPhysicalTypes_[patchi] = origType;
935 
936  if (origType == "symplane")
937  {
938  patchTypes_[patchi] = symmetryPolyPatch::typeName;
940  }
941  else if (origType == "wall")
942  {
943  patchTypes_[patchi] = wallPolyPatch::typeName;
945  }
946  else if (origType == "cyclic")
947  {
948  patchTypes_[patchi] = mergedCyclicPolyPatch::typeName;
950  }
951  else if (origType == "baffle")
952  {
953  patchTypes_[patchi] = mergedCyclicPolyPatch::typeName;
954  patchPhysicalTypes_[patchi] = "baffle";
955  }
956  else
957  {
958  patchTypes_[patchi] = polyPatch::typeName;
959  }
960 
961  Info<< "patch " << patchi
962  << " (region " << origRegion[patchi]
963  << ": " << origType << ") type: '" << patchTypes_[patchi]
964  << "' name: " << patchNames_[patchi] << endl;
965  }
966 
967  // cleanup
969  cellShapes_.clear();
970 }
971 
972 
973 //
974 // remove unused points
975 //
977 {
979  labelList oldToNew(nPoints, -1);
980 
981  // loop through cell faces and note which points are being used
982  forAll(cellFaces_, celli)
983  {
984  const faceList& faces = cellFaces_[celli];
985  forAll(faces, i)
986  {
987  const labelList& labels = faces[i];
988  forAll(labels, j)
989  {
990  oldToNew[labels[j]]++;
991  }
992  }
993  }
994 
995  // the new ordering and the count of unused points
996  label pointi = 0;
997  forAll(oldToNew, i)
998  {
999  if (oldToNew[i] >= 0)
1000  {
1001  oldToNew[i] = pointi++;
1002  }
1003  }
1004 
1005  // report unused points
1006  if (nPoints > pointi)
1007  {
1008  Info<< "Unused points = " << (nPoints - pointi) << endl;
1009  nPoints = pointi;
1010 
1011  // adjust points and truncate
1012  inplaceReorder(oldToNew, points_);
1013  points_.setSize(nPoints);
1014 
1015  // adjust cellFaces - with mesh shapes this might be faster
1016  forAll(cellFaces_, celli)
1017  {
1018  faceList& faces = cellFaces_[celli];
1019  forAll(faces, i)
1020  {
1021  inplaceRenumber(oldToNew, faces[i]);
1022  }
1023  }
1024 
1025  // adjust baffles
1026  forAll(baffleFaces_, facei)
1027  {
1028  inplaceRenumber(oldToNew, baffleFaces_[facei]);
1029  }
1030  }
1031 }
1032 
1033 
1034 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1035 
1036 bool Foam::meshReaders::STARCD::readGeometry(const scalar scaleFactor)
1037 {
1038  readPoints(geometryFile_ + ".vrt", scaleFactor);
1039  readCells(geometryFile_ + ".cel");
1040  cullPoints();
1041  readBoundary(geometryFile_ + ".bnd");
1042 
1043  return true;
1044 }
1045 
1046 
1047 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1048 
1051  const fileName& prefix,
1052  const objectRegistry& registry,
1053  const scalar scaleFactor
1054 )
1055 :
1056  meshReader(prefix, scaleFactor),
1057  cellShapes_(0),
1058  mapToFoamPointId_(0),
1059  mapToFoamCellId_(0)
1060 {
1061  readAux(registry);
1062 }
1063 
1064 
1065 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
1066 
1068 {}
1069 
1070 
1071 // ************************************************************************* //
label nPatches
Definition: readKivaGrid.H:402
static const char *const defaultSolidBoundaryName
static const cellModel * tetModel
Definition: meshReader.H:237
static const char *const defaultBoundaryName
void inplaceReorder(const labelUList &oldToNew, ListType &)
Inplace reorder the elements of a list.
List< List< cellFaceIdentifier > > boundaryIds_
Identify boundary faces by cells and their faces.
Definition: meshReader.H:256
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
FvWallInfoData< WallInfo, label > label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
wordList patchPhysicalTypes_
Boundary patch physical types.
Definition: meshReader.H:265
void sortedOrder(const UList< T > &, labelList &order)
Generate the (stable) sort order for the list.
A class for handling file names.
Definition: fileName.H:79
void readAux(const objectRegistry &)
Read auxiliary data from constant/{boundaryRegion,cellTable}.
void inplaceRenumber(const labelUList &oldToNew, ListType &)
Inplace renumber the values of a list.
static iteratorEnd end()
iteratorEnd set to beyond the end of any HashTable
Definition: HashTable.H:112
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
virtual ~STARCD()
Destructor.
error FatalError
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:306
#define forAllIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:459
labelList mapToFoamCellId_
Cell labels (imported Cell numbering not necessarily contiguous)
An analytical geometric cellShape.
Definition: cellShape.H:69
void setName(const label, const word &)
Assign name.
Definition: cellTable.C:295
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
wordList patchTypes_
Boundary patch types.
Definition: meshReader.H:259
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
Identify cell faces in terms of cell Id and face Id.
Definition: meshReader.H:77
static const int starToFoamFaceAddr[4][6]
Face addressing from pro-STAR faces -> OpenFOAM faces.
labelList identity(const label len)
Create identity map (map[i] == i) of given length.
Definition: ListOps.C:104
virtual bool readGeometry(const scalar scaleFactor=1.0)
Read the mesh from the file(s)
static const cellModel * prismModel
Definition: meshReader.H:239
static void readToNewline(IFstream &)
Read and discard to newline.
void setMaterial(const label, const word &)
Assign material Type.
Definition: cellTable.C:289
pointField points_
Points supporting the mesh.
Definition: meshReader.H:249
bool good() const
Return true if next operation might succeed.
Definition: IOstream.H:330
static const cellModel * unknownModel
Pointers to cell shape models.
Definition: meshReader.H:236
virtual void readCells(const fileName &)
Read cell connectivities from file.
Various functions to operate on Lists.
bool insert(const Key &, const T &newElmt)
Insert a new hashedEntry.
Definition: HashTableI.H:80
iterator find(const Key &)
Find and return an iterator set at the hashedEntry.
Definition: HashTable.C:142
label collapse()
Collapse face by removing duplicate point labels.
Definition: face.C:199
scalar y
A List obtained as a section of another List.
Definition: SubList.H:53
labelList origCellId_
Lookup original Cell number for a given cell.
Definition: meshReader.H:252
wordList patchNames_
Boundary patch names.
Definition: meshReader.H:262
void readDict(const objectRegistry &, const word &name="cellTable", const fileName &instance="constant")
Read constant/cellTable.
Definition: cellTable.C:313
bool found(const Key &) const
Return true if hashedEntry is found in table.
Definition: HashTable.C:113
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:125
A class for handling words, derived from string.
Definition: word.H:59
label nPoints
const fileName & name() const
Return the name of the stream.
Definition: IFstream.H:116
meshReader(const fileName &, const scalar scaleFactor=1.0)
Construct from fileName.
Definition: meshReader.C:200
boundaryRegion boundaryRegion_
Boundary region data.
List< label > labelList
A List of labels.
Definition: labelList.H:56
static bool readHeader(IFstream &, word fileSignature)
Read header.
static const cellModel * pyrModel
Definition: meshReader.H:238
errorManip< error > abort(error &err)
Definition: errorManip.H:131
static const char nl
Definition: Ostream.H:260
Input from file stream.
Definition: IFstream.H:81
labelList f(nPoints)
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
cellTable cellTable_
Cell table persistent data saved as a dictionary.
Definition: meshReader.H:277
fileName geometryFile_
Referenced filename.
Definition: meshReader.H:243
label index() const
Return index of model in the model list.
Definition: cellModelI.H:44
void readDict(const objectRegistry &, const word &name="boundaryRegion", const fileName &instance="constant")
Read constant/boundaryRegion.
void setSize(const label)
Reset size of List.
Definition: List.C:281
static const cellModel * hexModel
Definition: meshReader.H:240
faceList baffleFaces_
List of each baffle face.
Definition: meshReader.H:271
labelList cellTableId_
Cell table id for each cell.
Definition: meshReader.H:274
label patchi
void readPoints(const fileName &, const scalar scaleFactor)
Read points from file.
label cellId
Maps a geometry to a set of cell primitives, which enables geometric cell data to be calculated witho...
Definition: cellModel.H:64
labelList mapToFoamPointId_
Point labels (imported Point numbering not necessarily contiguous)
messageStream Info
cellShapeList cellShapes_
Cell shapes.
label n
Registry of regIOobjects.
void readBoundary(const fileName &)
Read boundary (cell/face) definitions.
STARCD(const fileName &prefix, const objectRegistry &, const scalar scaleFactor=1.0)
Construct from case name.
faceListList cellFaces_
List of faces for every cell.
Definition: meshReader.H:268
static bool keepSolids
Keep solids (default false)
void cullPoints()
Remove unused points.