STARCDMeshReader.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2016-2019 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "STARCDMeshReader.H"
30 #include "oldCyclicPolyPatch.H"
31 #include "emptyPolyPatch.H"
32 #include "wallPolyPatch.H"
33 #include "symmetryPolyPatch.H"
34 #include "cellModel.H"
35 #include "ListOps.H"
36 #include "stringOps.H"
37 #include "IFstream.H"
38 #include "IOMap.H"
39 
40 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
41 
42 namespace Foam
43 {
44 
45  // Read and discard to newline
46  static inline void readToNewline(ISstream& is)
47  {
48  char ch = '\n';
49  do
50  {
51  is.get(ch);
52  }
53  while ((is) && ch != '\n');
54  }
55 
56 } // End namespace Foam
57 
58 
59 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
60 
62 (
63  const objectRegistry& registry
64 )
65 {
66  boundaryRegion_.readDict(registry);
67  cellTable_.readDict(registry);
68 }
69 
70 
71 // Read points from <.vrt> file
72 //
73 /*---------------------------------------------------------------------------*\
74 Line 1:
75  PROSTAR_VERTEX [newline]
76 
77 Line 2:
78  <version> 0 0 0 0 0 0 0 [newline]
79 
80 Body:
81  <vertexId> <x> <y> <z> [newline]
82 
83 \*---------------------------------------------------------------------------*/
85 (
86  const fileName& inputName,
87  const scalar scaleFactor
88 )
89 {
90  label nPoints = 0, maxId = 0;
91  token tok;
92 
93  // Pass 1:
94  // get # points and maximum vertex label
95  {
96  IFstream is(inputName);
97  readHeader(is, STARCDCore::HEADER_VRT);
98 
99  scalar x, y, z;
100 
101  while (is.read(tok).good() && tok.isLabel())
102  {
103  const label starVertexId = tok.labelToken();
104 
105  is >> x >> y >> z;
106 
107  maxId = max(maxId, starVertexId);
108  ++nPoints;
109  }
110  }
111 
112  if (!nPoints)
113  {
115  << "No points in file " << inputName << nl
116  << abort(FatalError);
117  }
118 
119  Info<< "Number of points = " << nPoints << endl;
120 
121  // Set sizes and reset to invalid values
122 
123  points_.setSize(nPoints);
124  mapToFoamPointId_.setSize(maxId+1);
125 
126  //- Original Point number for a given vertex
127  // might need again in the future
130 
131  mapToFoamPointId_ = -1;
132 
133  // Pass 2:
134  // construct pointList and conversion table
135  // from Star vertex numbers to Foam point labels
136  {
137  IFstream is(inputName);
138  readHeader(is, STARCDCore::HEADER_VRT);
139 
140  label pointi = 0;
141  while (is.read(tok).good() && tok.isLabel())
142  {
143  const label starVertexId = tok.labelToken();
144 
145  is >> points_[pointi].x()
146  >> points_[pointi].y()
147  >> points_[pointi].z();
148 
149  // might need again in the future
151  mapToFoamPointId_[starVertexId] = pointi;
152  ++pointi;
153  }
154 
155  if (nPoints > pointi)
156  {
157  nPoints = pointi;
158  points_.setSize(nPoints);
159  // might need again in the future
161  }
162 
163  if
164  (
165  scaleFactor > 0
166  && (scaleFactor > 1.0 + SMALL || scaleFactor < 1.0 - SMALL)
167  )
168  {
169  points_ *= scaleFactor;
170  }
171  }
172 
173  return maxId;
174 }
175 
176 
177 // Read cells from <.cel> file
178 //
179 /*---------------------------------------------------------------------------*\
180 Line 1:
181  PROSTAR_CELL [newline]
182 
183 Line 2:
184  <version> 0 0 0 0 0 0 0 [newline]
185 
186 Body:
187  <cellId> <shapeId> <nLabels> <cellTableId> <typeId> [newline]
188  <cellId> <int1> .. <int8>
189  <cellId> <int9> .. <int16>
190 
191  with shapeId:
192  * 1 = point
193  * 2 = line
194  * 3 = shell
195  * 11 = hexa
196  * 12 = prism
197  * 13 = tetra
198  * 14 = pyramid
199  * 255 = polyhedron
200 
201  with typeId
202  * 1 = fluid
203  * 2 = solid
204  * 3 = baffle
205  * 4 = shell
206  * 5 = line
207  * 6 = point
208 
209 For primitive cell shapes, the number of vertices will never exceed 8 (hexa)
210 and corresponds to <nLabels>.
211 For polyhedral, <nLabels> includes an index table comprising beg/end pairs
212 for each cell face.
214 Strictly speaking, we only need the cellModeller for adding boundaries.
215 \*---------------------------------------------------------------------------*/
216 
218 {
219  label nFluids = 0, nSolids = 0, nBaffles = 0, nShells = 0;
220  label maxId = 0;
221  token tok;
222 
223  bool unknownVertices = false;
224 
225 
226  // Pass 1:
227  // count nFluids, nSolids, nBaffle, nShell and maxId
228  // also see if polyhedral cells were used
229  {
230  IFstream is(inputName);
231  readHeader(is, STARCDCore::HEADER_CEL);
232 
233  label shapeId, nLabels, cellTableId, typeId;
234 
235  while (is.read(tok).good() && tok.isLabel())
236  {
237  const label starCellId = tok.labelToken();
238 
239  is >> shapeId
240  >> nLabels
241  >> cellTableId
242  >> typeId;
243 
244  // Skip the rest of the line
245  readToNewline(is);
246 
247  // Max 8 indices per line
248  while (nLabels > 0)
249  {
250  readToNewline(is);
251  nLabels -= 8;
252  }
253 
254  if (typeId == STARCDCore::starcdFluidType)
255  {
256  ++nFluids;
257  maxId = max(maxId, starCellId);
258 
259  if (!cellTable_.found(cellTableId))
260  {
261  cellTable_.setName(cellTableId);
262  cellTable_.setMaterial(cellTableId, "fluid");
263  }
264  }
265  else if (typeId == STARCDCore::starcdSolidType)
266  {
267  ++nSolids;
268  if (keepSolids_)
269  {
270  maxId = max(maxId, starCellId);
271  }
272 
273  if (!cellTable_.found(cellTableId))
274  {
275  cellTable_.setName(cellTableId);
276  cellTable_.setMaterial(cellTableId, "solid");
277  }
278  }
279  else if (typeId == STARCDCore::starcdBaffleType)
280  {
281  // baffles have no cellTable entry
282  ++nBaffles;
283  maxId = max(maxId, starCellId);
284  }
285  else if (typeId == STARCDCore::starcdShellType)
286  {
287  ++nShells;
288  if (!cellTable_.found(cellTableId))
289  {
290  cellTable_.setName(cellTableId);
291  cellTable_.setMaterial(cellTableId, "shell");
292  }
293  }
294  }
295  }
296 
297  const label nCells = nFluids + (keepSolids_ ? nSolids : 0);
298 
299  Info<< "Number of fluids = " << nFluids << nl
300  << "Number of baffles = " << nBaffles << nl
301  << "Number of solids = " << nSolids
302  << (keepSolids_ ? " (treat as fluid)" : " (ignored)") << nl
303  << "Number of shells = " << nShells << " (ignored)" << nl;
304 
305  if (!nCells)
306  {
308 
309  err << "No cells in file " << inputName << nl;
310 
311  if (nShells)
312  {
313  err << "Consists of shells only (typeId=4)." << nl;
314  }
315 
316  err << nl
317  << abort(FatalError);
318  }
319 
320  cellFaces_.setSize(nCells);
321  cellShapes_.setSize(nCells);
322  cellTableId_.setSize(nCells);
323 
324  // information for the interfaces
325  baffleFaces_.setSize(nBaffles);
326 
327  // extra space for baffles
328  origCellId_.setSize(nCells + nBaffles);
329  mapToFoamCellId_.setSize(maxId+1);
330  mapToFoamCellId_ = -1;
331 
332 
333  // avoid undefined shapes for polyhedra
334  cellShape genericShape
335  (
337  );
338 
339  // Pass 2:
340  // construct cellFaces_ and possibly cellShapes_
341  {
342  IFstream is(inputName);
343  readHeader(is, STARCDCore::HEADER_CEL);
344 
345  labelList starLabels(64);
346  label ignoredLabel, shapeId, nLabels, cellTableId, typeId;
347 
348  label celli = 0, bafflei = 0;
349 
350  while (is.read(tok).good() && tok.isLabel())
351  {
352  const label starCellId = tok.labelToken();
353 
354  is >> shapeId
355  >> nLabels
356  >> cellTableId
357  >> typeId;
358 
359  if (nLabels > starLabels.size())
360  {
361  starLabels.setSize(nLabels);
362  }
363  starLabels = -1;
364 
365  // Read indices - max 8 per line
366  for (label i = 0; i < nLabels; ++i)
367  {
368  if ((i % 8) == 0)
369  {
370  is >> ignoredLabel; // Skip cellId for continuation lines
371  }
372  is >> starLabels[i];
373  }
374 
375  // Skip solid cells
376  if
377  (
379  && !keepSolids_
380  )
381  {
382  continue;
383  }
384 
385  // Determine the OpenFOAM cell shape
386  const cellModel* curModelPtr = nullptr;
387 
388  // fluid/solid cells
389  switch (shapeId)
390  {
392  curModelPtr = cellModel::ptr(cellModel::HEX);
393  break;
395  curModelPtr = cellModel::ptr(cellModel::PRISM);
396  break;
398  curModelPtr = cellModel::ptr(cellModel::TET);
399  break;
401  curModelPtr = cellModel::ptr(cellModel::PYR);
402  break;
403  }
404 
405  if (curModelPtr)
406  {
407  // primitive cell - use shapes
408 
409  // convert orig vertex Id to point label
410  bool isBad = false;
411  for (label i=0; i < nLabels; ++i)
412  {
413  label pointId = mapToFoamPointId_[starLabels[i]];
414  if (pointId < 0)
415  {
416  Info<< "Cells inconsistent with vertex file. "
417  << "Star vertex " << starLabels[i]
418  << " does not exist" << endl;
419  isBad = true;
420  unknownVertices = true;
421  }
422  starLabels[i] = pointId;
423  }
424 
425  if (isBad)
426  {
427  continue;
428  }
429 
430  // record original cell number and lookup
431  origCellId_[celli] = starCellId;
432  mapToFoamCellId_[starCellId] = celli;
433 
434  cellTableId_[celli] = cellTableId;
435  cellShapes_[celli] = cellShape
436  (
437  *curModelPtr,
438  SubList<label>(starLabels, nLabels)
439  );
440 
441  cellFaces_[celli] = cellShapes_[celli].faces();
442  ++celli;
443  }
444  else if (shapeId == STARCDCore::starcdPoly)
445  {
446  // polyhedral cell
447  label nFaces = starLabels[0] - 1;
448 
449  // convert orig vertex id to point label
450  // start with offset (skip the index table)
451  bool isBad = false;
452  for (label i=starLabels[0]; i < nLabels; ++i)
453  {
454  label pointId = mapToFoamPointId_[starLabels[i]];
455  if (pointId < 0)
456  {
457  Info<< "Cells inconsistent with vertex file. "
458  << "Star vertex " << starLabels[i]
459  << " does not exist" << endl;
460  isBad = true;
461  unknownVertices = true;
462  }
463  starLabels[i] = pointId;
464  }
465 
466  if (isBad)
467  {
468  continue;
469  }
470 
471  // traverse beg/end indices
472  faceList faces(nFaces);
473  label facei = 0;
474  for (label i=0; i < nFaces; ++i)
475  {
476  label beg = starLabels[i];
477  label n = starLabels[i+1] - beg;
478 
479  face f
480  (
481  SubList<label>(starLabels, n, beg)
482  );
483 
484  f.collapse();
485 
486  // valid faces only
487  if (f.size() >= 3)
488  {
489  faces[facei++] = f;
490  }
491  }
492 
493  if (nFaces > facei)
494  {
495  Info<< "star cell " << starCellId << " has "
496  << (nFaces - facei)
497  << " empty faces - could cause boundary "
498  << "addressing problems"
499  << endl;
500 
501  nFaces = facei;
502  faces.setSize(nFaces);
503  }
504 
505  if (nFaces < 4)
506  {
508  << "star cell " << starCellId << " has " << nFaces
509  << abort(FatalError);
510  }
511 
512  // record original cell number and lookup
513  origCellId_[celli] = starCellId;
514  mapToFoamCellId_[starCellId] = celli;
515 
516  cellTableId_[celli] = cellTableId;
517  cellShapes_[celli] = genericShape;
518  cellFaces_[celli] = faces;
519  ++celli;
520  }
521  else if (typeId == STARCDCore::starcdBaffleType)
522  {
523  // baffles
524 
525  // convert orig vertex id to point label
526  bool isBad = false;
527  for (label i=0; i < nLabels; ++i)
528  {
529  label pointId = mapToFoamPointId_[starLabels[i]];
530  if (pointId < 0)
531  {
532  Info<< "Baffles inconsistent with vertex file. "
533  << "Star vertex " << starLabels[i]
534  << " does not exist" << endl;
535  isBad = true;
536  unknownVertices = true;
537  }
538  starLabels[i] = pointId;
539  }
540 
541  if (isBad)
542  {
543  continue;
544  }
545 
546 
547  face f
548  (
549  SubList<label>(starLabels, nLabels)
550  );
551 
552  f.collapse();
553 
554  // valid faces only
555  if (f.size() >= 3)
556  {
557  baffleFaces_[bafflei] = f;
558  // insert lookup addressing in normal list
559  mapToFoamCellId_[starCellId] = nCells + bafflei;
560  origCellId_[nCells + bafflei] = starCellId;
561  ++bafflei;
562  }
563  }
564  }
565 
566  baffleFaces_.setSize(bafflei);
567  }
568 
569  if (unknownVertices)
570  {
572  << "cells with unknown vertices"
573  << abort(FatalError);
574  }
575 
576  // truncate lists
577 
578 #ifdef DEBUG_READING
579  Info<< "CELLS READ" << endl;
580 #endif
581 
582  // cleanup
583  mapToFoamPointId_.clear();
584 }
585 
586 
587 // Read boundaries from <.bnd> file
588 //
589 /*---------------------------------------------------------------------------*\
590 Line 1:
591  PROSTAR_BOUNDARY [newline]
592 
593 Line 2:
594  <version> 0 0 0 0 0 0 0 [newline]
595 
596 Body:
597  <boundId> <cellId> <cellFace> <regionId> 0 <boundaryType> [newline]
598 
599 where boundaryType is truncated to 4 characters from one of the following:
600 INLET
601 PRESSSURE
602 OUTLET
603 BAFFLE
604 etc,
605 \*---------------------------------------------------------------------------*/
606 
608 (
609  const fileName& inputName
610 )
611 {
612  label nPatches = 0, nFaces = 0, nBafflePatches = 0, maxId = 0;
613  label starCellId, cellFaceId, starRegion, configNumber;
614  token tok;
615  word patchType;
616 
617  labelList mapToFoamPatchId(1000, label(-1));
618  labelList nPatchFaces(1000, Zero);
619  labelList origRegion(1000, Zero);
620  patchTypes_.setSize(1000);
621 
622  //
623  // Mapping between OpenFOAM and PROSTAR primitives
624  // - needed for face mapping
625  //
626  const Map<label> shapeLookup =
627  {
632  };
633 
634  // Pass 1:
635  // collect
636  // no. of faces (nFaces), no. of patches (nPatches)
637  // and for each of these patches the number of faces
638  // (nPatchFaces[patchLabel])
639  //
640  // and a conversion table from Star regions to (Foam) patchLabels
641  //
642  // additionally note the no. of baffle patches (nBafflePatches)
643  // so that we sort these to the end of the patch list
644  // - this makes it easier to transfer them to an adjacent patch if reqd
645  {
646  IFstream is(inputName);
647 
648  if (is.good())
649  {
650  readHeader(is, STARCDCore::HEADER_BND);
651 
652  while (is.read(tok).good() && tok.isLabel())
653  {
654  // Ignore boundary id (not needed)
655 
656  ++nFaces;
657 
658  is >> starCellId
659  >> cellFaceId
660  >> starRegion
661  >> configNumber
662  >> patchType;
663 
664  // Build translation table to convert star patch to foam patch
665  label patchLabel = mapToFoamPatchId[starRegion];
666  if (patchLabel == -1)
667  {
668  patchLabel = nPatches;
669  mapToFoamPatchId[starRegion] = patchLabel;
670  origRegion[patchLabel] = starRegion;
671  patchTypes_[patchLabel] = patchType;
672 
673  maxId = max(maxId, starRegion);
674 
675  // should actually be case-insensitive
676  if (patchType == "BAFF")
677  {
678  ++nBafflePatches;
679  }
680  ++nPatches;
681  }
682 
683  ++nPatchFaces[patchLabel];
684  }
685 
686  if (nPatches == 0)
687  {
688  Info<< "No boundary faces in file " << inputName << endl;
689  }
690  }
691  else
692  {
693  Info<< "Could not read boundary file " << inputName << endl;
694  }
695  }
696 
697  // keep empty patch region in reserve
698  ++nPatches;
699  Info<< "Number of patches = " << nPatches
700  << " (including extra for missing) with "
701  << nFaces << " faces" << endl;
702 
703  // resize
704  origRegion.setSize(nPatches);
705  patchTypes_.setSize(nPatches);
706  patchNames_.setSize(nPatches);
707  nPatchFaces.setSize(nPatches);
708 
709  // add our empty patch
710  origRegion[nPatches-1] = 0;
711  nPatchFaces[nPatches-1] = 0;
712  patchTypes_[nPatches-1] = "none";
713 
714  // create names
715  // - use 'Label' entry from "constant/boundaryRegion" dictionary
716  forAll(patchTypes_, patchi)
717  {
718  bool fndName = false, fndType = false;
719 
720  auto iter = boundaryRegion_.cfind(origRegion[patchi]);
721 
722  if (iter.good())
723  {
724  const dictionary& dict = *iter;
725 
726  fndType = dict.readIfPresent("BoundaryType", patchTypes_[patchi]);
727  fndName = dict.readIfPresent("Label", patchNames_[patchi]);
728  }
729 
730  // Consistent names. Long form and in lowercase
731  if (!fndType)
732  {
733  stringOps::inplaceLower(patchTypes_[patchi]);
734 
735  if (patchTypes_[patchi] == "symp")
736  {
737  patchTypes_[patchi] = "symplane";
738  }
739  else if (patchTypes_[patchi] == "cycl")
740  {
741  patchTypes_[patchi] = "cyclic";
742  }
743  else if (patchTypes_[patchi] == "baff")
744  {
745  patchTypes_[patchi] = "baffle";
746  }
747  else if (patchTypes_[patchi] == "moni")
748  {
749  patchTypes_[patchi] = "monitoring";
750  }
751  }
752 
753  // Create a name if needed
754  if (!fndName)
755  {
756  patchNames_[patchi] =
757  patchTypes_[patchi] + "_" + name(origRegion[patchi]);
758  }
759  }
760 
761  // Enforce name "Default_Boundary_Region"
762  patchNames_[nPatches-1] = defaultBoundaryName;
763 
764  // Sort according to ascending region numbers, but leave
765  // "Default_Boundary_Region" as the final patch
766  {
767  labelList sortedIndices
768  (
769  sortedOrder(SubList<label>(origRegion, nPatches-1))
770  );
771 
772  labelList oldToNew = identity(nPatches);
773  forAll(sortedIndices, i)
774  {
775  oldToNew[sortedIndices[i]] = i;
776  }
777 
778  inplaceReorder(oldToNew, origRegion);
779  inplaceReorder(oldToNew, patchTypes_);
780  inplaceReorder(oldToNew, patchNames_);
781  inplaceReorder(oldToNew, nPatchFaces);
782  }
783 
784  // re-sort to have baffles near the end
785  nBafflePatches = 1;
786  if (nBafflePatches)
787  {
788  labelList oldToNew = identity(nPatches);
789  label newIndex = 0;
790  label baffleIndex = (nPatches-1 - nBafflePatches);
791 
792  for (label i=0; i < oldToNew.size()-1; ++i)
793  {
794  if (patchTypes_[i] == "baffle")
795  {
796  oldToNew[i] = baffleIndex++;
797  }
798  else
799  {
800  oldToNew[i] = newIndex++;
801  }
802  }
803 
804  inplaceReorder(oldToNew, origRegion);
805  inplaceReorder(oldToNew, patchTypes_);
806  inplaceReorder(oldToNew, patchNames_);
807  inplaceReorder(oldToNew, nPatchFaces);
808  }
809 
810  mapToFoamPatchId.setSize(maxId+1, -1);
811  forAll(origRegion, patchi)
812  {
813  mapToFoamPatchId[origRegion[patchi]] = patchi;
814  }
815 
816  boundaryIds_.setSize(nPatches);
817  forAll(boundaryIds_, patchi)
818  {
819  boundaryIds_[patchi].setSize(nPatchFaces[patchi]);
820  nPatchFaces[patchi] = 0;
821  }
822 
823 
824  // Pass 2:
825  //
826  if (nPatches > 1 && mapToFoamCellId_.size() > 1)
827  {
828  IFstream is(inputName);
829  readHeader(is, STARCDCore::HEADER_BND);
830 
831  while (is.read(tok).good() && tok.isLabel())
832  {
833  // Ignore boundary id (not needed)
834 
835  is
836  >> starCellId
837  >> cellFaceId
838  >> starRegion
839  >> configNumber
840  >> patchType;
841 
842  label patchi = mapToFoamPatchId[starRegion];
843 
844  // zero-based indexing
845  cellFaceId--;
846 
847  label cellId = -1;
848 
849  // convert to FOAM cell number
850  if (starCellId < mapToFoamCellId_.size())
851  {
852  cellId = mapToFoamCellId_[starCellId];
853  }
854 
855  if (cellId < 0)
856  {
857  Info
858  << "Boundaries inconsistent with cell file. "
859  << "Star cell " << starCellId << " does not exist"
860  << endl;
861  }
862  else
863  {
864  // restrict lookup to volume cells (no baffles)
865  if (cellId < cellShapes_.size())
866  {
867  label mapIndex = cellShapes_[cellId].model().index();
868  if (shapeLookup.found(mapIndex))
869  {
870  mapIndex = shapeLookup[mapIndex];
871  cellFaceId =
873  [mapIndex][cellFaceId];
874  }
875  }
876  else
877  {
878  // we currently use cellId >= nCells to tag baffles,
879  // we can also use a negative face number
880  cellFaceId = -1;
881  }
882 
883  boundaryIds_[patchi][nPatchFaces[patchi]] =
884  cellFaceIdentifier(cellId, cellFaceId);
885 
886 #ifdef DEBUG_BOUNDARY
887  Info<< "bnd " << cellId << " " << cellFaceId << endl;
888 #endif
889  // Increment counter of faces in current patch
890  ++nPatchFaces[patchi];
891  }
892  }
893  }
894 
895  // retain original information in patchPhysicalTypes_ - overwrite latter
896  patchPhysicalTypes_.setSize(patchTypes_.size());
897 
898 
899  forAll(boundaryIds_, patchi)
900  {
901  // resize - avoid invalid boundaries
902  if (nPatchFaces[patchi] < boundaryIds_[patchi].size())
903  {
904  boundaryIds_[patchi].setSize(nPatchFaces[patchi]);
905  }
906 
907  word origType = patchTypes_[patchi];
908  patchPhysicalTypes_[patchi] = origType;
909 
910  if (origType == "symplane")
911  {
912  patchTypes_[patchi] = symmetryPolyPatch::typeName;
913  patchPhysicalTypes_[patchi] = patchTypes_[patchi];
914  }
915  else if (origType == "wall")
916  {
917  patchTypes_[patchi] = wallPolyPatch::typeName;
918  patchPhysicalTypes_[patchi] = patchTypes_[patchi];
919  }
920  else if (origType == "cyclic")
921  {
922  // incorrect. should be cyclicPatch but this
923  // requires info on connected faces.
924  patchTypes_[patchi] = oldCyclicPolyPatch::typeName;
925  patchPhysicalTypes_[patchi] = patchTypes_[patchi];
926  }
927  else if (origType == "baffle")
928  {
929  // incorrect. tag the patch until we get proper support.
930  // set physical type to a canonical "baffle"
931  patchTypes_[patchi] = emptyPolyPatch::typeName;
932  patchPhysicalTypes_[patchi] = "baffle";
933  }
934  else
935  {
936  patchTypes_[patchi] = polyPatch::typeName;
937  }
938 
939  Info<< "patch " << patchi
940  << " (region " << origRegion[patchi]
941  << ": " << origType << ") type: '" << patchTypes_[patchi]
942  << "' name: " << patchNames_[patchi] << endl;
943  }
944 
945  // cleanup
946  mapToFoamCellId_.clear();
947  cellShapes_.clear();
948 }
949 
951 //
952 // remove unused points
953 //
955 {
956  label nPoints = points_.size();
957  labelList oldToNew(nPoints, -1);
958 
959  // loop through cell faces and note which points are being used
960  forAll(cellFaces_, celli)
961  {
962  const faceList& faces = cellFaces_[celli];
963  forAll(faces, i)
964  {
965  const labelList& labels = faces[i];
966  forAll(labels, j)
967  {
968  oldToNew[labels[j]]++;
969  }
970  }
971  }
972 
973  // The new ordering and the count of unused points
974  label pointi = 0;
975  forAll(oldToNew, i)
976  {
977  if (oldToNew[i] >= 0)
978  {
979  oldToNew[i] = pointi++;
980  }
981  }
982 
983  // Report unused points
984  if (nPoints > pointi)
985  {
986  Info<< "Unused points = " << (nPoints - pointi) << endl;
987  nPoints = pointi;
988 
989  // Adjust points and truncate
990  inplaceReorder(oldToNew, points_);
991  points_.setSize(nPoints);
992 
993  // Adjust cellFaces - with mesh shapes this might be faster
994  for (faceList& faces : cellFaces_)
995  {
996  for (face& f : faces)
997  {
998  inplaceRenumber(oldToNew, f);
999  }
1000  }
1001 
1002  // Adjust baffles
1003  for (face& f : baffleFaces_)
1004  {
1005  inplaceRenumber(oldToNew, f);
1006  }
1007  }
1008 }
1010 
1011 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1012 
1013 bool Foam::fileFormats::STARCDMeshReader::readGeometry(const scalar scaleFactor)
1014 {
1015  readPoints
1016  (
1017  starFileName(geometryFile_, STARCDCore::VRT_FILE),
1018  scaleFactor
1019  );
1020  readCells
1021  (
1022  starFileName(geometryFile_, STARCDCore::CEL_FILE)
1023  );
1024  cullPoints();
1025  readBoundary
1026  (
1027  starFileName(geometryFile_, STARCDCore::BND_FILE)
1028  );
1029 
1030  return true;
1031 }
1032 
1034 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1035 
1037 (
1038  const fileName& prefix,
1039  const objectRegistry& registry,
1040  const scalar scaleFactor,
1041  const bool keepSolids
1042 )
1043 :
1044  meshReader(prefix, scaleFactor),
1045  keepSolids_(keepSolids),
1046  cellShapes_(0),
1047  mapToFoamPointId_(0),
1048  mapToFoamCellId_(0)
1049 {
1050  readAux(registry);
1051 }
1052 
1053 
1054 // ************************************************************************* //
label nPatches
Definition: readKivaGrid.H:396
Generic output stream using a standard (STL) stream.
Definition: OSstream.H:50
dictionary dict
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
A class for handling file names.
Definition: fileName.H:72
void readBoundary(const fileName &)
Read boundary (cell/face) definitions.
STARCDMeshReader(const fileName &prefix, const objectRegistry &registry, const scalar scaleFactor=1.0, const bool keepSolids=false)
Construct from case name.
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:68
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
static const Map< FixedList< int, 6 > > starToFoamFaceAddr
Face addressing from PROSTAR faces to OpenFOAM faces.
Definition: STARCDCore.H:141
void readAux(const objectRegistry &)
Read auxiliary data from constant/{boundaryRegion,cellTable}.
bool found(const Key &key) const
Same as contains()
Definition: HashTable.H:1354
labelList sortedOrder(const UList< T > &input)
Return the (stable) sort order for the list.
static void readToNewline(ISstream &is)
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
An analytical geometric cellShape.
Definition: cellShape.H:68
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
void inplaceReorder(const labelUList &oldToNew, ListType &input, const bool prune=false)
Inplace reorder the elements of a list.
label readPoints(const fileName &, const scalar scaleFactor)
Read points from file, return the max prostar id used.
A token holds an item read from Istream.
Definition: token.H:65
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
Identify cell faces in terms of cell Id and face Id.
Definition: meshReader.H:71
Various functions to operate on Lists.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
static const cellModel & ref(const modelType model)
Look up reference to cellModel by enumeration. Fatal on failure.
Definition: cellModels.C:150
scalar y
A List obtained as a section of another List.
Definition: SubList.H:50
void readDict(const objectRegistry &, const word &name="cellTable", const fileName &instance="constant")
Read constant/cellTable.
Definition: cellTable.C:305
void setSize(const label n)
Alias for resize()
Definition: List.H:316
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
boundaryRegion boundaryRegion_
Boundary region data.
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i), works like std::iota() but returning a...
Definition: labelLists.C:44
A class for handling words, derived from Foam::string.
Definition: word.H:63
label nPoints
static const cellModel * ptr(const modelType model)
Look up pointer to cellModel by enumeration, or nullptr on failure.
Definition: cellModels.C:113
void cullPoints()
Remove unused points.
errorManip< error > abort(error &err)
Definition: errorManip.H:139
Input from file stream, using an ISstream.
Definition: IFstream.H:49
labelList f(nPoints)
virtual Istream & read(token &t) override
Return next token from stream.
Definition: ISstream.C:535
cellTable cellTable_
Cell table persistent data saved as a dictionary.
Definition: meshReader.H:334
void readDict(const objectRegistry &, const word &name="boundaryRegion", const fileName &instance="constant")
Read constant/boundaryRegion.
virtual void readCells(const fileName &)
Read cell connectivities from file.
void inplaceRenumber(const labelUList &oldToNew, IntListType &input)
Inplace renumber the values (not the indices) of a list.
Generic input stream using a standard (STL) stream.
Definition: ISstream.H:51
label index() const noexcept
Return index of model in the model list.
Definition: cellModelI.H:30
void inplaceLower(std::string &s)
Inplace transform string with std::tolower on each character.
Definition: stringOps.C:1181
bool good() const noexcept
True if next operation might succeed.
Definition: IOstream.H:281
label cellId
label labelToken() const
Return label value.
Definition: tokenI.H:615
Maps a geometry to a set of cell primitives.
Definition: cellModel.H:72
bool isLabel() const noexcept
Token is LABEL.
Definition: tokenI.H:599
messageStream Info
Information stream (stdout output on master, null elsewhere)
label n
virtual bool readGeometry(const scalar scaleFactor=1.0)
Read the mesh from the file(s)
List< label > labelList
A List of labels.
Definition: List.H:62
Registry of regIOobjects.
ISstream & get(char &c)
Raw, low-level get character function.
Definition: ISstreamI.H:49
This class supports creating polyMeshes with baffles.
Definition: meshReader.H:64
Namespace for OpenFOAM.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127