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-2023 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
609  mapToFoamPointId_.clear();
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, 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  is >> starCellId
676  >> cellFaceId
677  >> starRegion
678  >> configNumber
679  >> patchType;
680 
681  // Build translation table to convert star patch to foam patch
682  label patchLabel = mapToFoamPatchId[starRegion];
683  if (patchLabel == -1)
684  {
685  patchLabel = nPatches;
686  mapToFoamPatchId[starRegion] = patchLabel;
687  origRegion[patchLabel] = starRegion;
688  patchTypes_[patchLabel] = patchType;
689 
690  maxId = max(maxId, starRegion);
691 
692  // should actually be case-insensitive
693  if (patchType == "BAFF")
694  {
695  nBafflePatches++;
696  }
697  nPatches++;
698  }
699 
700  nPatchFaces[patchLabel]++;
701  }
702 
703  if (nPatches == 0)
704  {
705  Info<< "No boundary faces in file " << inputName << endl;
706  }
707  }
708  else
709  {
710  Info<< "Could not read boundary file " << inputName << endl;
711  }
712  }
713 
714  // keep empty patch region in reserve
715  nPatches++;
716  Info<< "Number of patches = " << nPatches
717  << " (including extra for missing)" << endl;
718 
719  // resize
720  origRegion.setSize(nPatches);
721  patchTypes_.setSize(nPatches);
722  patchNames_.setSize(nPatches);
723  nPatchFaces.setSize(nPatches);
724 
725  // add our empty patch
726  origRegion[nPatches-1] = 0;
727  nPatchFaces[nPatches-1] = 0;
728  patchTypes_[nPatches-1] = "none";
729 
730  // create names
731  // - use 'Label' entry from "constant/boundaryRegion" dictionary
732  forAll(patchTypes_, patchi)
733  {
734  bool foundName = false, foundType = false;
735 
737  iter = boundaryRegion_.find(origRegion[patchi]);
738 
739  if
740  (
741  iter != boundaryRegion_.end()
742  )
743  {
744  foundType = iter().readIfPresent
745  (
746  "BoundaryType",
747  patchTypes_[patchi]
748  );
749 
750  foundName = iter().readIfPresent
751  (
752  "Label",
753  patchNames_[patchi]
754  );
755  }
756 
757  // consistent names, in long form and in lowercase
758  if (!foundType)
759  {
760  // transform
761  forAllIter(string, patchTypes_[patchi], i)
762  {
763  *i = tolower(*i);
764  }
765 
766  if (patchTypes_[patchi] == "symp")
767  {
768  patchTypes_[patchi] = "symplane";
769  }
770  else if (patchTypes_[patchi] == "cycl")
771  {
772  patchTypes_[patchi] = "cyclic";
773  }
774  else if (patchTypes_[patchi] == "baff")
775  {
776  patchTypes_[patchi] = "baffle";
777  }
778  else if (patchTypes_[patchi] == "moni")
779  {
780  patchTypes_[patchi] = "monitoring";
781  }
782  }
783 
784  // create a name if needed
785  if (!foundName)
786  {
787  patchNames_[patchi] =
788  patchTypes_[patchi] + "_" + name(origRegion[patchi]);
789  }
790  }
791 
792  // enforce name "Default_Boundary_Region"
793  patchNames_[nPatches-1] = defaultBoundaryName;
794 
795  // sort according to ascending region numbers, but leave
796  // Default_Boundary_Region as the final patch
797  {
798  labelList sortedIndices;
799  sortedOrder(SubList<label>(origRegion, nPatches-1), sortedIndices);
800 
801  labelList oldToNew = identityMap(nPatches);
802  forAll(sortedIndices, i)
803  {
804  oldToNew[sortedIndices[i]] = i;
805  }
806 
807  inplaceReorder(oldToNew, origRegion);
808  inplaceReorder(oldToNew, patchTypes_);
809  inplaceReorder(oldToNew, patchNames_);
810  inplaceReorder(oldToNew, nPatchFaces);
811  }
812 
813  // re-sort to have baffles near the end
814  nBafflePatches = 1;
815  if (nBafflePatches)
816  {
817  labelList oldToNew = identityMap(nPatches);
818  label newIndex = 0;
819  label baffleIndex = (nPatches-1 - nBafflePatches);
820 
821  for (label i=0; i < oldToNew.size()-1; ++i)
822  {
823  if (patchTypes_[i] == "baffle")
824  {
825  oldToNew[i] = baffleIndex++;
826  }
827  else
828  {
829  oldToNew[i] = newIndex++;
830  }
831  }
832 
833  inplaceReorder(oldToNew, origRegion);
834  inplaceReorder(oldToNew, patchTypes_);
835  inplaceReorder(oldToNew, patchNames_);
836  inplaceReorder(oldToNew, nPatchFaces);
837  }
838 
839  mapToFoamPatchId.setSize(maxId+1, -1);
840  forAll(origRegion, patchi)
841  {
842  mapToFoamPatchId[origRegion[patchi]] = patchi;
843  }
844 
845  boundaryIds_.setSize(nPatches);
846  forAll(boundaryIds_, patchi)
847  {
848  boundaryIds_[patchi].setSize(nPatchFaces[patchi]);
849  nPatchFaces[patchi] = 0;
850  }
851 
852 
853  // Pass 2:
854  //
855  if (nPatches > 1 && mapToFoamCellId_.size() > 1)
856  {
857  IFstream is(inputName);
858  readHeader(is, fileSignature);
859 
860  while ((is >> lineLabel).good())
861  {
862  is
863  >> starCellId
864  >> cellFaceId
865  >> starRegion
866  >> configNumber
867  >> patchType;
868 
869  label patchi = mapToFoamPatchId[starRegion];
870 
871  // zero-based indexing
872  cellFaceId--;
873 
874  label cellId = -1;
875 
876  // convert to FOAM cell number
877  if (starCellId < mapToFoamCellId_.size())
878  {
879  cellId = mapToFoamCellId_[starCellId];
880  }
881 
882  if (cellId < 0)
883  {
884  Info
885  << "Boundaries inconsistent with cell file. "
886  << "Star cell " << starCellId << " does not exist"
887  << endl;
888  }
889  else
890  {
891  // restrict lookup to volume cells (no baffles)
892  if (cellId < cellShapes_.size())
893  {
894  label index = cellShapes_[cellId].model().index();
895  if (faceLookupIndex.found(index))
896  {
897  index = faceLookupIndex[index];
898  cellFaceId = starToFoamFaceAddr[index][cellFaceId];
899  }
900  }
901  else
902  {
903  // we currently use cellId >= nCells to tag baffles,
904  // we can also use a negative face number
905  cellFaceId = -1;
906  }
907 
908  boundaryIds_[patchi][nPatchFaces[patchi]] =
909  cellFaceIdentifier(cellId, cellFaceId);
910 
911 #ifdef DEBUG_BOUNDARY
912  Info<< "bnd " << cellId << " " << cellFaceId << endl;
913 #endif
914  // increment counter of faces in current patch
915  nPatchFaces[patchi]++;
916  }
917  }
918  }
919 
920  // retain original information in patchPhysicalTypes_ - overwrite latter
921  patchPhysicalTypes_.setSize(patchTypes_.size());
922 
923 
924  forAll(boundaryIds_, patchi)
925  {
926  // resize - avoid invalid boundaries
927  if (nPatchFaces[patchi] < boundaryIds_[patchi].size())
928  {
929  boundaryIds_[patchi].setSize(nPatchFaces[patchi]);
930  }
931 
932  word origType = patchTypes_[patchi];
933  patchPhysicalTypes_[patchi] = origType;
934 
935  if (origType == "symplane")
936  {
937  patchTypes_[patchi] = symmetryPolyPatch::typeName;
938  patchPhysicalTypes_[patchi] = patchTypes_[patchi];
939  }
940  else if (origType == "wall")
941  {
942  patchTypes_[patchi] = wallPolyPatch::typeName;
943  patchPhysicalTypes_[patchi] = patchTypes_[patchi];
944  }
945  else if (origType == "cyclic")
946  {
947  patchTypes_[patchi] = mergedCyclicPolyPatch::typeName;
948  patchPhysicalTypes_[patchi] = patchTypes_[patchi];
949  }
950  else if (origType == "baffle")
951  {
952  patchTypes_[patchi] = mergedCyclicPolyPatch::typeName;
953  patchPhysicalTypes_[patchi] = "baffle";
954  }
955  else
956  {
957  patchTypes_[patchi] = polyPatch::typeName;
958  }
959 
960  Info<< "patch " << patchi
961  << " (region " << origRegion[patchi]
962  << ": " << origType << ") type: '" << patchTypes_[patchi]
963  << "' name: " << patchNames_[patchi] << endl;
964  }
965 
966  // cleanup
967  mapToFoamCellId_.clear();
968  cellShapes_.clear();
969 }
970 
971 
972 //
973 // remove unused points
974 //
976 {
977  label nPoints = points_.size();
978  labelList oldToNew(nPoints, -1);
979 
980  // loop through cell faces and note which points are being used
981  forAll(cellFaces_, celli)
982  {
983  const faceList& faces = cellFaces_[celli];
984  forAll(faces, i)
985  {
986  const labelList& labels = faces[i];
987  forAll(labels, j)
988  {
989  oldToNew[labels[j]]++;
990  }
991  }
992  }
993 
994  // the new ordering and the count of unused points
995  label pointi = 0;
996  forAll(oldToNew, i)
997  {
998  if (oldToNew[i] >= 0)
999  {
1000  oldToNew[i] = pointi++;
1001  }
1002  }
1003 
1004  // report unused points
1005  if (nPoints > pointi)
1006  {
1007  Info<< "Unused points = " << (nPoints - pointi) << endl;
1008  nPoints = pointi;
1009 
1010  // adjust points and truncate
1011  inplaceReorder(oldToNew, points_);
1012  points_.setSize(nPoints);
1013 
1014  // adjust cellFaces - with mesh shapes this might be faster
1015  forAll(cellFaces_, celli)
1016  {
1017  faceList& faces = cellFaces_[celli];
1018  forAll(faces, i)
1019  {
1020  inplaceRenumber(oldToNew, faces[i]);
1021  }
1022  }
1023 
1024  // adjust baffles
1025  forAll(baffleFaces_, facei)
1026  {
1027  inplaceRenumber(oldToNew, baffleFaces_[facei]);
1028  }
1029  }
1030 }
1031 
1032 
1033 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1034 
1035 bool Foam::meshReaders::STARCD::readGeometry(const scalar scaleFactor)
1036 {
1037  readPoints(geometryFile_ + ".vrt", scaleFactor);
1038  readCells(geometryFile_ + ".cel");
1039  cullPoints();
1040  readBoundary(geometryFile_ + ".bnd");
1041 
1042  return true;
1043 }
1044 
1045 
1046 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1047 
1049 (
1050  const fileName& prefix,
1051  const objectRegistry& registry,
1052  const scalar scaleFactor
1053 )
1054 :
1055  meshReader(prefix, scaleFactor),
1056  cellShapes_(0),
1057  mapToFoamPointId_(0),
1058  mapToFoamCellId_(0)
1059 {
1060  readAux(registry);
1061 }
1062 
1063 
1064 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
1065 
1067 {}
1068 
1069 
1070 // ************************************************************************* //
scalar y
Various functions to operate on Lists.
label n
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
#define forAllIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:459
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
bool found(const Key &) const
Return true if hashedEntry is found in table.
Definition: HashTable.C:113
Input from file stream.
Definition: IFstream.H:85
const fileName & name() const
Return the name of the stream.
Definition: IFstream.H:116
bool good() const
Return true if next operation might succeed.
Definition: IOstream.H:330
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
void setSize(const label)
Reset size of List.
Definition: List.C:281
A List obtained as a section of another List.
Definition: SubList.H:56
Maps a geometry to a set of cell primitives, which enables geometric cell data to be calculated witho...
Definition: cellModel.H:65
An analytical geometric cellShape.
Definition: cellShape.H:72
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:76
A class for handling file names.
Definition: fileName.H:82
Identify cell faces in terms of cell Id and face Id.
Definition: meshReader.H:78
This class supports creating polyMeshes with baffles.
Definition: meshReader.H:73
static const int starToFoamFaceAddr[4][6]
Face addressing from pro-STAR faces -> OpenFOAM faces.
STARCD(const fileName &prefix, const objectRegistry &, const scalar scaleFactor=1.0)
Construct from case name.
virtual ~STARCD()
Destructor.
static bool readHeader(IFstream &, word fileSignature)
Read header.
static bool keepSolids
Keep solids (default false)
virtual bool readGeometry(const scalar scaleFactor=1.0)
Read the mesh from the file(s)
void cullPoints()
Remove unused points.
static const char *const defaultBoundaryName
void readBoundary(const fileName &)
Read boundary (cell/face) definitions.
void readPoints(const fileName &, const scalar scaleFactor)
Read points from file.
virtual void readCells(const fileName &)
Read cell connectivities from file.
static const char *const defaultSolidBoundaryName
static void readToNewline(IFstream &)
Read and discard to newline.
void readAux(const objectRegistry &)
Read auxiliary data from constant/{boundaryRegion,cellTable}.
Registry of regIOobjects.
A class for handling words, derived from string.
Definition: word.H:62
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:306
label patchi
label nPoints
const label cellId
List< label > labelList
A List of labels.
Definition: labelList.H:56
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
errorManip< error > abort(error &err)
Definition: errorManip.H:131
messageStream Info
void inplaceRenumber(const labelUList &oldToNew, ListType &)
Inplace renumber the values of a list.
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
error FatalError
labelList identityMap(const label len)
Create identity map (map[i] == i) of given length.
Definition: ListOps.C:104
void sortedOrder(const UList< T > &, labelList &order)
Generate the (stable) sort order for the list.
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
static const char nl
Definition: Ostream.H:260
void inplaceReorder(const labelUList &oldToNew, ListType &)
Inplace reorder the elements of a list.
labelList f(nPoints)
label nPatches
Definition: readKivaGrid.H:396
static iteratorEnd end()
iteratorEnd set to beyond the end of any HashTable
Definition: HashTable.H:112