gmshToFoam.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) 2020-2023 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 Application
28  gmshToFoam
29 
30 group
31  grpMeshConversionUtilities
32 
33 Description
34  Reads .msh file as written by Gmsh.
35 
36  Needs surface elements on mesh to be present and aligned with outside faces
37  of the mesh. I.e. if the mesh is hexes, the outside faces need to be
38  quads.
39 
40  Note: There is something seriously wrong with the ordering written in the
41  .msh file. Normal operation is to check the ordering and invert prisms
42  and hexes if found to be wrong way round.
43  Use the -keepOrientation to keep the raw information.
44 
45  Note: The code now uses the element (cell,face) physical region id number
46  to create cell zones and faces zones (similar to
47  fluentMeshWithInternalFaces).
48 
49  A use of the cell zone information, is for field initialization with the
50  "setFields" utility. see the classes: topoSetSource, zoneToCell.
51 
52 \*---------------------------------------------------------------------------*/
53 
54 #include "argList.H"
55 #include "Time.H"
56 #include "polyMesh.H"
57 #include "IFstream.H"
58 #include "cellModel.H"
59 #include "repatchPolyTopoChanger.H"
60 #include "cellSet.H"
61 #include "faceSet.H"
62 #include "List.H"
63 
64 using namespace Foam;
65 
66 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
67 
68 // Element type numbers
69 
70 static label MSHLINE = 1;
71 
72 static label MSHTRI = 2;
73 static label MSHQUAD = 3;
74 static label MSHTET = 4;
75 
76 
77 static label MSHHEX = 5;
78 static label MSHPRISM = 6;
79 static label MSHPYR = 7;
80 
81 
82 // Skips till end of section. Returns false if end of file.
83 bool skipSection(IFstream& inFile)
84 {
85  string line;
86  do
87  {
88  inFile.getLine(line);
89 
90  if (!inFile.good())
91  {
92  return false;
93  }
94  }
95  while (line.size() < 4 || line.substr(0, 4) != "$End");
96 
97  return true;
98 }
99 
100 
101 void renumber
102 (
103  const Map<label>& mshToFoam,
104  labelList& labels
105 )
106 {
107  forAll(labels, labelI)
108  {
109  labels[labelI] = mshToFoam[labels[labelI]];
110  }
111 }
112 
113 
114 // Find face in pp which uses all vertices in meshF (in mesh point labels)
115 label findFace(const primitivePatch& pp, const labelList& meshF)
116 {
117  const Map<label>& meshPointMap = pp.meshPointMap();
118 
119  // meshF[0] in pp labels.
120  if (!meshPointMap.found(meshF[0]))
121  {
122  Warning<< "Not using gmsh face " << meshF
123  << " since zero vertex is not on boundary of polyMesh" << endl;
124  return -1;
125  }
126 
127  // Find faces using first point
128  const labelList& pFaces = pp.pointFaces()[meshPointMap[meshF[0]]];
129 
130  // Go through all these faces and check if there is one which uses all of
131  // meshF vertices (in any order ;-)
132  forAll(pFaces, i)
133  {
134  label facei = pFaces[i];
135 
136  const face& f = pp[facei];
137 
138  // Count uses of vertices of meshF for f
139  label nMatched = 0;
140 
141  forAll(f, fp)
142  {
143  if (meshF.found(f[fp]))
144  {
145  nMatched++;
146  }
147  }
148 
149  if (nMatched == meshF.size())
150  {
151  return facei;
152  }
153  }
154 
155  return -1;
156 }
157 
158 
159 // Same but find internal face. Expensive addressing.
160 label findInternalFace(const primitiveMesh& mesh, const labelList& meshF)
161 {
162  const labelList& pFaces = mesh.pointFaces()[meshF[0]];
163 
164  forAll(pFaces, i)
165  {
166  label facei = pFaces[i];
167 
168  const face& f = mesh.faces()[facei];
169 
170  // Count uses of vertices of meshF for f
171  label nMatched = 0;
172 
173  forAll(f, fp)
174  {
175  if (meshF.found(f[fp]))
176  {
177  nMatched++;
178  }
179  }
180 
181  if (nMatched == meshF.size())
182  {
183  return facei;
184  }
185  }
186  return -1;
187 }
188 
189 
190 // Determine whether cell is inside-out by checking for any wrong-oriented
191 // face.
192 bool correctOrientation(const pointField& points, const cellShape& shape)
193 {
194  // Get centre of shape.
195  const point cc(shape.centre(points));
196 
197  // Get outwards pointing faces.
198  faceList faces(shape.faces());
199 
200  for (const face& f : faces)
201  {
202  const vector areaNorm(f.areaNormal(points));
203 
204  // Check if vector from any point on face to cc points outwards
205  if (((points[f[0]] - cc) & areaNorm) < 0)
206  {
207  // Incorrectly oriented
208  return false;
209  }
210  }
211 
212  return true;
213 }
214 
215 
216 void storeCellInZone
217 (
218  const label regPhys,
219  const label celli,
220  Map<label>& physToZone,
221 
222  labelList& zoneToPhys,
223  List<DynamicList<label>>& zoneCells
224 )
225 {
226  const auto zoneFnd = physToZone.cfind(regPhys);
227 
228  if (zoneFnd.good())
229  {
230  // Existing zone for region
231  zoneCells[zoneFnd()].append(celli);
232  }
233  else
234  {
235  // New region. Allocate zone for it.
236  const label zonei = zoneCells.size();
237  zoneCells.setSize(zonei+1);
238  zoneToPhys.setSize(zonei+1);
239 
240  Info<< "Mapping region " << regPhys << " to Foam cellZone "
241  << zonei << endl;
242  physToZone.insert(regPhys, zonei);
243 
244  zoneToPhys[zonei] = regPhys;
245  zoneCells[zonei].append(celli);
246  }
247 }
248 
249 
250 // Reads mesh format
251 scalar readMeshFormat(IFstream& inFile)
252 {
253  Info<< "Starting to read mesh format at line "
254  << inFile.lineNumber()
255  << endl;
256 
257  string line;
258  inFile.getLine(line);
259  IStringStream lineStr(line);
260 
261  scalar version;
262  label asciiFlag, nBytes;
263  lineStr >> version >> asciiFlag >> nBytes;
264 
265  Info<< "Read format version " << version << " ascii " << asciiFlag << endl;
266 
267  if (asciiFlag != 0)
268  {
269  FatalIOErrorInFunction(inFile)
270  << "Can only read ascii msh files."
271  << exit(FatalIOError);
272  }
273 
274  inFile.getLine(line);
275  IStringStream tagStr(line);
276  word tag(tagStr);
277 
278  if (tag != "$EndMeshFormat")
279  {
280  FatalIOErrorInFunction(inFile)
281  << "Did not find $ENDNOD tag on line "
282  << inFile.lineNumber() << exit(FatalIOError);
283  }
284  Info<< endl;
285 
286  return version;
287 }
288 
289 
290 // Reads points and map for gmsh MSH file <4
291 void readPointsLegacy(IFstream& inFile, pointField& points, Map<label>& mshToFoam)
292 {
293  Info<< "Starting to read points at line " << inFile.lineNumber() << endl;
294 
295  string line;
296  inFile.getLine(line);
297  IStringStream lineStr(line);
298 
299  label nVerts;
300  lineStr >> nVerts;
301 
302  Info<< "Vertices to be read: " << nVerts << endl;
303 
304  points.resize(nVerts);
305 
306  for (label pointi = 0; pointi < nVerts; pointi++)
307  {
308  label mshLabel;
309  scalar xVal, yVal, zVal;
310 
311  string line;
312  inFile.getLine(line);
313  IStringStream lineStr(line);
314 
315  lineStr >> mshLabel >> xVal >> yVal >> zVal;
316 
317  point& pt = points[pointi];
318 
319  pt.x() = xVal;
320  pt.y() = yVal;
321  pt.z() = zVal;
322 
323  mshToFoam.insert(mshLabel, pointi);
324  }
325 
326  Info<< "Vertices read:" << mshToFoam.size() << endl;
327 
328  inFile.getLine(line);
329  IStringStream tagStr(line);
330  word tag(tagStr);
331 
332  if (tag != "$ENDNOD" && tag != "$EndNodes")
333  {
334  FatalIOErrorInFunction(inFile)
335  << "Did not find $ENDNOD tag on line "
336  << inFile.lineNumber() << exit(FatalIOError);
337  }
338  Info<< endl;
339 }
340 
341 // Reads points and map for gmsh MSH file >=4
342 void readPoints(IFstream& inFile, pointField& points, Map<label>& mshToFoam)
343 {
344  Info<< "Starting to read points at line " << inFile.lineNumber() << endl;
345 
346  string line;
347  inFile.getLine(line);
348  IStringStream lineStr(line);
349 
350  // Number of "entities": 0, 1, 2, and 3 dimensional geometric structures
351  label nEntities, nVerts;
352  lineStr >> nEntities >> nVerts;
353 
354  Info<< "Vertices to be read: " << nVerts << endl;
355 
356  points.resize(nVerts);
357 
358  // Index of points, in the order as they appeared, not what gmsh
359  // labelled them.
360  label pointi = 0;
361 
362  for (label entityi = 0; entityi < nEntities; entityi++)
363  {
364  label entityDim, entityLabel, isParametric, nNodes;
365  scalar xVal, yVal, zVal;
366  inFile.getLine(line);
367  IStringStream lineStr(line); // can IStringStream be removed?
368 
369  // Read entity entry, then set up a list for node IDs
370  lineStr >> entityDim >> entityLabel >> isParametric >> nNodes;
371  List<label> nodeIDs(nNodes);
372 
373  // Loop over entity node IDs
374  for (label eNode = 0; eNode < nNodes; ++eNode)
375  {
376  inFile.getLine(line);
377  IStringStream lineStr(line);
378  lineStr >> nodeIDs[eNode];
379  }
380 
381  // Loop over entity node values, saving to points[]
382  for (label eNode = 0; eNode < nNodes; ++eNode)
383  {
384  inFile.getLine(line);
385  IStringStream lineStr(line);
386  lineStr >> xVal >> yVal >> zVal;
387  point& pt = points[nodeIDs[eNode]-1];
388  pt.x() = xVal;
389  pt.y() = yVal;
390  pt.z() = zVal;
391  mshToFoam.insert(nodeIDs[eNode], pointi++);
392  }
393 
394  }
395 
396  Info<< "Vertices read: " << mshToFoam.size() << endl;
397 
398  inFile.getLine(line);
399  IStringStream tagStr(line);
400  word tag(tagStr);
401 
402  if (tag != "$ENDNOD" && tag != "$EndNodes")
403  {
404  FatalIOErrorInFunction(inFile)
405  << "Did not find $ENDNOD tag on line "
406  << inFile.lineNumber() << exit(FatalIOError);
407  }
408  Info<< endl;
409 }
410 
411 
412 // Reads physical names
413 void readPhysNames(IFstream& inFile, Map<word>& physicalNames)
414 {
415  Info<< "Starting to read physical names at line " << inFile.lineNumber()
416  << endl;
417 
418  string line;
419  inFile.getLine(line);
420  IStringStream lineStr(line);
421 
422  label nNames;
423  lineStr >> nNames;
424 
425  Info<< "Physical names:" << nNames << endl;
426 
427  for (label i = 0; i < nNames; i++)
428  {
429  label regionI;
430  string regionName;
431 
432  string line;
433  inFile.getLine(line);
434  IStringStream lineStr(line);
435  label nSpaces = lineStr.str().count(' ');
436 
437  if (nSpaces == 1)
438  {
439  lineStr >> regionI >> regionName;
440 
441  Info<< " " << regionI << '\t'
443  }
444  else if (nSpaces == 2)
445  {
446  // >= Gmsh2.4 physical types has tag in front.
447  label physType;
448  lineStr >> physType >> regionI >> regionName;
449  if (physType == 1)
450  {
451  Info<< " " << "Line " << regionI << '\t'
453  }
454  else if (physType == 2)
455  {
456  Info<< " " << "Surface " << regionI << '\t'
458  }
459  else if (physType == 3)
460  {
461  Info<< " " << "Volume " << regionI << '\t'
463  }
464  }
465  else
466  {
467  continue;
468  }
469 
470  physicalNames.insert(regionI, word::validate(regionName));
471  }
472 
473  inFile.getLine(line);
474  IStringStream tagStr(line);
475  word tag(tagStr);
476 
477  if (tag != "$EndPhysicalNames")
478  {
479  FatalIOErrorInFunction(inFile)
480  << "Did not find $EndPhysicalNames tag on line "
481  << inFile.lineNumber() << exit(FatalIOError);
482  }
483  Info<< endl;
484 }
485 
486 void readCellsLegacy
487 (
488  const scalar versionFormat,
489  const bool keepOrientation,
490  const pointField& points,
491  const Map<label>& mshToFoam,
492  IFstream& inFile,
494 
495  labelList& patchToPhys,
496  List<DynamicList<face>>& patchFaces,
497 
498  labelList& zoneToPhys,
499  List<DynamicList<label>>& zoneCells
500 )
501 {
502  //$Elements
503  //number-of-elements
504  //elm-number elm-type number-of-tags < tag > \u2026 node-number-list
505 
506 
507  Info<< "Starting to read cells at line " << inFile.lineNumber() << endl;
508 
510  const cellModel& prism = cellModel::ref(cellModel::PRISM);
513 
514  face triPoints(3);
515  face quadPoints(4);
516  labelList tetPoints(4);
517  labelList pyrPoints(5);
518  labelList prismPoints(6);
519  labelList hexPoints(8);
520 
521 
522  string line;
523  inFile.getLine(line);
524  IStringStream lineStr(line);
525 
526  label nElems;
527  lineStr >> nElems;
528 
529  Info<< "Cells to be read: " << nElems << endl << endl;
530 
531 
532  // Storage for all cells. Too big. Shrink later
533  cells.setSize(nElems);
534 
535  label celli = 0;
536  label nTet = 0;
537  label nPyr = 0;
538  label nPrism = 0;
539  label nHex = 0;
540 
541 
542  // From gmsh physical region to Foam patch
543  Map<label> physToPatch;
544 
545  // From gmsh physical region to Foam cellZone
546  Map<label> physToZone;
547 
548 
549  for (label elemI = 0; elemI < nElems; elemI++)
550  {
551  string line;
552  inFile.getLine(line);
553  IStringStream lineStr(line);
554 
555  label elmNumber, elmType, regPhys;
556  if (versionFormat >= 2)
557  {
558  lineStr >> elmNumber >> elmType;
559 
560  label nTags;
561  lineStr >> nTags;
562 
563  if (nTags > 0)
564  {
565  // Assume the first tag is the physical surface
566  lineStr >> regPhys;
567  for (label i = 1; i < nTags; i++)
568  {
569  label dummy;
570  lineStr >> dummy;
571  }
572  }
573  }
574  else
575  {
576  label regElem, nNodes;
577  lineStr >> elmNumber >> elmType >> regPhys >> regElem >> nNodes;
578  }
579 
580  // regPhys on surface elements is region number.
581  if (elmType == MSHLINE)
582  {
583  label meshPti;
584  lineStr >> meshPti >> meshPti;
585  }
586  else if (elmType == MSHTRI)
587  {
588  lineStr >> triPoints[0] >> triPoints[1] >> triPoints[2];
589 
590  renumber(mshToFoam, triPoints);
591 
592  const auto regFnd = physToPatch.cfind(regPhys);
593 
594  label patchi = -1;
595  if (regFnd.good())
596  {
597  // Existing patch for region
598  patchi = regFnd();
599  }
600  else
601  {
602  // New region. Allocate patch for it.
603  patchi = patchFaces.size();
604 
605  patchFaces.setSize(patchi + 1);
606  patchToPhys.setSize(patchi + 1);
607 
608  Info<< "Mapping region " << regPhys << " to Foam patch "
609  << patchi << endl;
610  physToPatch.insert(regPhys, patchi);
611  patchToPhys[patchi] = regPhys;
612  }
613 
614  // Add triangle to correct patchFaces.
615  patchFaces[patchi].append(triPoints);
616  }
617  else if (elmType == MSHQUAD)
618  {
619  lineStr
620  >> quadPoints[0] >> quadPoints[1] >> quadPoints[2]
621  >> quadPoints[3];
622 
623  renumber(mshToFoam, quadPoints);
624 
625  const auto regFnd = physToPatch.cfind(regPhys);
626 
627  label patchi = -1;
628  if (regFnd.good())
629  {
630  // Existing patch for region
631  patchi = regFnd();
632  }
633  else
634  {
635  // New region. Allocate patch for it.
636  patchi = patchFaces.size();
637 
638  patchFaces.setSize(patchi + 1);
639  patchToPhys.setSize(patchi + 1);
640 
641  Info<< "Mapping region " << regPhys << " to Foam patch "
642  << patchi << endl;
643  physToPatch.insert(regPhys, patchi);
644  patchToPhys[patchi] = regPhys;
645  }
646 
647  // Add quad to correct patchFaces.
648  patchFaces[patchi].append(quadPoints);
649  }
650  else if (elmType == MSHTET)
651  {
652  storeCellInZone
653  (
654  regPhys,
655  celli,
656  physToZone,
657  zoneToPhys,
658  zoneCells
659  );
660 
661  lineStr
662  >> tetPoints[0] >> tetPoints[1] >> tetPoints[2]
663  >> tetPoints[3];
664 
665  renumber(mshToFoam, tetPoints);
666 
667  cells[celli++].reset(tet, tetPoints);
668 
669  nTet++;
670  }
671  else if (elmType == MSHPYR)
672  {
673  storeCellInZone
674  (
675  regPhys,
676  celli,
677  physToZone,
678  zoneToPhys,
679  zoneCells
680  );
681 
682  lineStr
683  >> pyrPoints[0] >> pyrPoints[1] >> pyrPoints[2]
684  >> pyrPoints[3] >> pyrPoints[4];
685 
686  renumber(mshToFoam, pyrPoints);
687 
688  cells[celli++].reset(pyr, pyrPoints);
689 
690  nPyr++;
691  }
692  else if (elmType == MSHPRISM)
693  {
694  storeCellInZone
695  (
696  regPhys,
697  celli,
698  physToZone,
699  zoneToPhys,
700  zoneCells
701  );
702 
703  lineStr
704  >> prismPoints[0] >> prismPoints[1] >> prismPoints[2]
705  >> prismPoints[3] >> prismPoints[4] >> prismPoints[5];
706 
707  renumber(mshToFoam, prismPoints);
708 
709  cells[celli].reset(prism, prismPoints);
710 
711  const cellShape& cell = cells[celli];
712 
713  if (!keepOrientation && !correctOrientation(points, cell))
714  {
715  Info<< "Inverting prism " << celli << endl;
716  // Reorder prism.
717  prismPoints[0] = cell[0];
718  prismPoints[1] = cell[2];
719  prismPoints[2] = cell[1];
720  prismPoints[3] = cell[3];
721  prismPoints[4] = cell[4];
722  prismPoints[5] = cell[5];
723 
724  cells[celli].reset(prism, prismPoints);
725  }
726 
727  celli++;
728 
729  nPrism++;
730  }
731  else if (elmType == MSHHEX)
732  {
733  storeCellInZone
734  (
735  regPhys,
736  celli,
737  physToZone,
738  zoneToPhys,
739  zoneCells
740  );
741 
742  lineStr
743  >> hexPoints[0] >> hexPoints[1]
744  >> hexPoints[2] >> hexPoints[3]
745  >> hexPoints[4] >> hexPoints[5]
746  >> hexPoints[6] >> hexPoints[7];
747 
748  renumber(mshToFoam, hexPoints);
749 
750  cells[celli].reset(hex, hexPoints);
751 
752  const cellShape& cell = cells[celli];
753 
754  if (!keepOrientation && !correctOrientation(points, cell))
755  {
756  Info<< "Inverting hex " << celli << endl;
757  // Reorder hex.
758  hexPoints[0] = cell[4];
759  hexPoints[1] = cell[5];
760  hexPoints[2] = cell[6];
761  hexPoints[3] = cell[7];
762  hexPoints[4] = cell[0];
763  hexPoints[5] = cell[1];
764  hexPoints[6] = cell[2];
765  hexPoints[7] = cell[3];
766 
767  cells[celli].reset(hex, hexPoints);
768  }
769 
770  celli++;
771 
772  nHex++;
773  }
774  else
775  {
776  Info<< "Unhandled element " << elmType << " at line "
777  << inFile.lineNumber() << endl;
778  }
779  }
780 
781 
782  inFile.getLine(line);
783  IStringStream tagStr(line);
784  word tag(tagStr);
785 
786  if (tag != "$ENDELM" && tag != "$EndElements")
787  {
788  FatalIOErrorInFunction(inFile)
789  << "Did not find $ENDELM tag on line "
790  << inFile.lineNumber() << exit(FatalIOError);
791  }
792 
793 
794  cells.setSize(celli);
795 
796  forAll(patchFaces, patchi)
797  {
798  patchFaces[patchi].shrink();
799  }
800 
801 
802  Info<< "Cells:" << endl
803  << " total:" << cells.size() << endl
804  << " hex :" << nHex << endl
805  << " prism:" << nPrism << endl
806  << " pyr :" << nPyr << endl
807  << " tet :" << nTet << endl
808  << endl;
809 
810  if (cells.size() == 0)
811  {
812  FatalIOErrorInFunction(inFile)
813  << "No cells read from file " << inFile.name() << nl
814  << "Does your file specify any 3D elements (hex=" << MSHHEX
815  << ", prism=" << MSHPRISM << ", pyramid=" << MSHPYR
816  << ", tet=" << MSHTET << ")?" << nl
817  << "Perhaps you have not exported the 3D elements?"
818  << exit(FatalIOError);
819  }
820 
821  Info<< "CellZones:" << nl
822  << "Zone\tSize" << endl;
823 
824  forAll(zoneCells, zonei)
825  {
826  zoneCells[zonei].shrink();
827 
828  const labelList& zCells = zoneCells[zonei];
829 
830  if (zCells.size())
831  {
832  Info<< " " << zonei << '\t' << zCells.size() << endl;
833  }
834  }
835  Info<< endl;
836 }
837 
838 void readCells
839 (
840  const scalar versionFormat,
841  const bool keepOrientation,
842  const pointField& points,
843  const Map<label>& mshToFoam,
844  IFstream& inFile,
846 
847  labelList& patchToPhys,
848  List<DynamicList<face>>& patchFaces,
849 
850  labelList& zoneToPhys,
851  List<DynamicList<label>>& zoneCells,
852  Map<label> surfEntityToPhysSurface,
853  Map<label> volEntityToPhysVolume
854 )
855 {
856  Info<< "Starting to read cells at line " << inFile.lineNumber() << endl;
857 
859  const cellModel& prism = cellModel::ref(cellModel::PRISM);
862 
863  face triPoints(3);
864  face quadPoints(4);
865  labelList tetPoints(4);
866  labelList pyrPoints(5);
867  labelList prismPoints(6);
868  labelList hexPoints(8);
869 
870 
871  string line;
872  inFile.getLine(line);
873  IStringStream lineStr(line);
874 
875  label nEntities, nElems, minElemTag, maxElemTag;
876  lineStr >> nEntities >> nElems >> minElemTag >> maxElemTag;
877 
878  Info<< "Cells to be read:" << nElems << endl << endl;
879 
880  // Storage for all cells. Too big. Shrink later
881  cells.setSize(nElems);
882 
883  label celli = 0;
884  label nTet = 0;
885  label nPyr = 0;
886  label nPrism = 0;
887  label nHex = 0;
888 
889 
890  // From gmsh physical region to Foam patch
891  Map<label> physToPatch;
892 
893  // From gmsh physical region to Foam cellZone
894  Map<label> physToZone;
895 
896 
897  for (label entityi = 0; entityi < nEntities; entityi++)
898  {
899  string line;
900  inFile.getLine(line);
901  IStringStream lineStr(line);
902 
903  label entityDim, entityID, regPhys, elmType, nElemInBlock, elemID;
904  lineStr >> entityDim >> entityID >> elmType >> nElemInBlock;
905 
906  if (entityDim == 2)
907  regPhys = surfEntityToPhysSurface[entityID];
908  else if (entityDim == 3)
909  regPhys = volEntityToPhysVolume[entityID];
910  else
911  regPhys = 0; // Points and lines don't matter to openFOAM
912 
913  // regPhys on surface elements is region number.
914  if (elmType == MSHLINE)
915  {
916  for (label entityElm = 0; entityElm < nElemInBlock; entityElm++)
917  {
918  inFile.getLine(line);
919  IStringStream lineStr(line);
920  label meshPti;
921  lineStr >> elemID >> meshPti >> meshPti;
922  }
923  }
924  else if (elmType == MSHTRI)
925  {
926  for (label entityElm = 0; entityElm < nElemInBlock; entityElm++)
927  {
928  inFile.getLine(line);
929  IStringStream lineStr(line);
930  lineStr >> elemID >> triPoints[0] >> triPoints[1] >> triPoints[2];
931 
932  renumber(mshToFoam, triPoints);
933 
934  const auto regFnd = physToPatch.cfind(regPhys);
935 
936  label patchi = -1;
937  if (regFnd.good())
938  {
939  // Existing patch for region
940  patchi = regFnd();
941  }
942  else
943  {
944  // New region. Allocate patch for it.
945  patchi = patchFaces.size();
946 
947  patchFaces.setSize(patchi + 1);
948  patchToPhys.setSize(patchi + 1);
949 
950  Info<< "Mapping region " << regPhys << " to Foam patch "
951  << patchi << endl;
952  physToPatch.insert(regPhys, patchi);
953  patchToPhys[patchi] = regPhys;
954  }
955 
956  // Add triangle to correct patchFaces.
957  patchFaces[patchi].append(triPoints);
958  }
959  }
960  else if (elmType == MSHQUAD)
961  {
962  for (label entityElm = 0; entityElm < nElemInBlock; entityElm++)
963  {
964  inFile.getLine(line);
965  IStringStream lineStr(line);
966  lineStr >> elemID
967  >> quadPoints[0] >> quadPoints[1] >> quadPoints[2]
968  >> quadPoints[3];
969 
970  renumber(mshToFoam, quadPoints);
971 
972  const auto regFnd = physToPatch.cfind(regPhys);
973 
974  label patchi = -1;
975  if (regFnd.good())
976  {
977  // Existing patch for region
978  patchi = regFnd();
979  }
980  else
981  {
982  // New region. Allocate patch for it.
983  patchi = patchFaces.size();
984 
985  patchFaces.setSize(patchi + 1);
986  patchToPhys.setSize(patchi + 1);
987 
988  Info<< "Mapping region " << regPhys << " to Foam patch "
989  << patchi << endl;
990  physToPatch.insert(regPhys, patchi);
991  patchToPhys[patchi] = regPhys;
992  }
993 
994  // Add quad to correct patchFaces.
995  patchFaces[patchi].append(quadPoints);
996  }
997  }
998  else if (elmType == MSHTET)
999  {
1000  nTet += nElemInBlock;
1001 
1002  for (label entityElm = 0; entityElm < nElemInBlock; entityElm++)
1003  {
1004  inFile.getLine(line);
1005  IStringStream lineStr(line);
1006 
1007  storeCellInZone
1008  (
1009  regPhys,
1010  celli,
1011  physToZone,
1012  zoneToPhys,
1013  zoneCells
1014  );
1015 
1016  lineStr >> elemID
1017  >> tetPoints[0] >> tetPoints[1] >> tetPoints[2]
1018  >> tetPoints[3];
1019 
1020  renumber(mshToFoam, tetPoints);
1021 
1022  cells[celli++].reset(tet, tetPoints);
1023  }
1024  }
1025  else if (elmType == MSHPYR)
1026  {
1027  nPyr += nElemInBlock;
1028 
1029  for (label entityElm = 0; entityElm < nElemInBlock; entityElm++)
1030  {
1031  inFile.getLine(line);
1032  IStringStream lineStr(line);
1033 
1034  storeCellInZone
1035  (
1036  regPhys,
1037  celli,
1038  physToZone,
1039  zoneToPhys,
1040  zoneCells
1041  );
1042 
1043  lineStr >> elemID
1044  >> pyrPoints[0] >> pyrPoints[1] >> pyrPoints[2]
1045  >> pyrPoints[3] >> pyrPoints[4];
1046 
1047  renumber(mshToFoam, pyrPoints);
1048 
1049  cells[celli++].reset(pyr, pyrPoints);
1050  }
1051  }
1052  else if (elmType == MSHPRISM)
1053  {
1054  nPrism += nElemInBlock;
1055 
1056  for (label entityElm = 0; entityElm < nElemInBlock; entityElm++)
1057  {
1058  inFile.getLine(line);
1059  IStringStream lineStr(line);
1060 
1061  storeCellInZone
1062  (
1063  regPhys,
1064  celli,
1065  physToZone,
1066  zoneToPhys,
1067  zoneCells
1068  );
1069 
1070  lineStr >> elemID
1071  >> prismPoints[0] >> prismPoints[1] >> prismPoints[2]
1072  >> prismPoints[3] >> prismPoints[4] >> prismPoints[5];
1073 
1074  renumber(mshToFoam, prismPoints);
1075 
1076  cells[celli].reset(prism, prismPoints);
1077 
1078  const cellShape& cell = cells[celli];
1079 
1080  if (!keepOrientation && !correctOrientation(points, cell))
1081  {
1082  Info<< "Inverting prism " << celli << endl;
1083  // Reorder prism.
1084  prismPoints[0] = cell[0];
1085  prismPoints[1] = cell[2];
1086  prismPoints[2] = cell[1];
1087  prismPoints[3] = cell[3];
1088  prismPoints[4] = cell[4];
1089  prismPoints[5] = cell[5];
1090 
1091  cells[celli].reset(prism, prismPoints);
1092  }
1093 
1094  celli++;
1095  }
1096  }
1097  else if (elmType == MSHHEX)
1098  {
1099  nHex += nElemInBlock;
1100 
1101  for (label entityElm = 0; entityElm < nElemInBlock; entityElm++)
1102  {
1103  inFile.getLine(line);
1104  IStringStream lineStr(line);
1105 
1106  storeCellInZone
1107  (
1108  regPhys,
1109  celli,
1110  physToZone,
1111  zoneToPhys,
1112  zoneCells
1113  );
1114 
1115  lineStr >> elemID
1116  >> hexPoints[0] >> hexPoints[1]
1117  >> hexPoints[2] >> hexPoints[3]
1118  >> hexPoints[4] >> hexPoints[5]
1119  >> hexPoints[6] >> hexPoints[7];
1120 
1121  renumber(mshToFoam, hexPoints);
1122 
1123  cells[celli].reset(hex, hexPoints);
1124 
1125  const cellShape& cell = cells[celli];
1126 
1127  if (!keepOrientation && !correctOrientation(points, cell))
1128  {
1129  Info<< "Inverting hex " << celli << endl;
1130  // Reorder hex.
1131  hexPoints[0] = cell[4];
1132  hexPoints[1] = cell[5];
1133  hexPoints[2] = cell[6];
1134  hexPoints[3] = cell[7];
1135  hexPoints[4] = cell[0];
1136  hexPoints[5] = cell[1];
1137  hexPoints[6] = cell[2];
1138  hexPoints[7] = cell[3];
1139 
1140  cells[celli].reset(hex, hexPoints);
1141  }
1142 
1143  celli++;
1144  }
1145  }
1146  else
1147  {
1148  Info<< "Unhandled element " << elmType << " at line "
1149  << inFile.lineNumber() << "in/on physical region ID: "
1150  << regPhys << endl;
1151  Info << "Perhaps you created a higher order mesh?" << endl;
1152  }
1153  }
1154 
1155 
1156  inFile.getLine(line);
1157  IStringStream tagStr(line);
1158  word tag(tagStr);
1159 
1160  if (tag != "$ENDELM" && tag != "$EndElements")
1161  {
1162  FatalIOErrorInFunction(inFile)
1163  << "Did not find $ENDELM tag on line "
1164  << inFile.lineNumber() << exit(FatalIOError);
1165  }
1166 
1167 
1168  cells.setSize(celli);
1169 
1170  forAll(patchFaces, patchi)
1171  {
1172  patchFaces[patchi].shrink();
1173  }
1174 
1175 
1176  Info<< "Cells:" << endl
1177  << " total: " << cells.size() << endl
1178  << " hex : " << nHex << endl
1179  << " prism: " << nPrism << endl
1180  << " pyr : " << nPyr << endl
1181  << " tet : " << nTet << endl
1182  << endl;
1183 
1184  if (cells.size() == 0)
1185  {
1186  FatalIOErrorInFunction(inFile)
1187  << "No cells read from file " << inFile.name() << nl
1188  << "Does your file specify any 3D elements (hex=" << MSHHEX
1189  << ", prism=" << MSHPRISM << ", pyramid=" << MSHPYR
1190  << ", tet=" << MSHTET << ")?" << nl
1191  << "Perhaps you have not exported the 3D elements?"
1192  << exit(FatalIOError);
1193  }
1194 
1195  Info<< "CellZones:" << nl
1196  << "Zone\tSize" << endl;
1197 
1198  forAll(zoneCells, zonei)
1199  {
1200  zoneCells[zonei].shrink();
1201 
1202  const labelList& zCells = zoneCells[zonei];
1203 
1204  if (zCells.size())
1205  {
1206  Info<< " " << zonei << '\t' << zCells.size() << endl;
1207  }
1208  }
1209  Info<< endl;
1210 }
1211 
1212 void readEntities
1213 (
1214  IFstream& inFile,
1215  Map<label>& surfEntityToPhysSurface,
1216  Map<label>& volEntityToPhysVolume
1217 )
1218 {
1219  label nPoints, nCurves, nSurfaces, nVolumes;
1220  label entityID, physicalID, nPhysicalTags;
1221  scalar pt; // unused scalar, gives bounding boxes of entities
1222  string line;
1223  inFile.getLine(line);
1224  IStringStream lineStr(line);
1225 
1226  lineStr >> nPoints >> nCurves >> nSurfaces >> nVolumes;
1227 
1228  // Skip over the points, since only the full nodes list matters.
1229  for (label i = 0; i < nPoints; ++i)
1230  inFile.getLine(line);
1231 
1232  // Skip over the curves
1233  for (label i = 0; i < nCurves; ++i)
1234  inFile.getLine(line);
1235 
1236  // Read in physical surface entity groupings
1237  for (label i = 0; i < nSurfaces; ++i)
1238  {
1239  inFile.getLine(line);
1240  IStringStream lineStr(line);
1241  lineStr >> entityID;
1242 
1243  // Skip 6 useless (to us) numbers
1244  for (label j = 0; j < 6; ++j)
1245  lineStr >> pt;
1246 
1247  // Number of physical groups associated to this surface
1248  lineStr >> nPhysicalTags;
1249  if (nPhysicalTags > 1)
1250  {
1251  FatalIOErrorInFunction(inFile)
1252  << "Cannot interpret multiple physical surfaces associated"
1253  << " with one surface on line number " << inFile.lineNumber()
1254  << exit(FatalIOError);
1255  }
1256 
1257  lineStr >> physicalID;
1258  surfEntityToPhysSurface.insert(entityID, physicalID);
1259  }
1260 
1261  // Read in physical volume entity groupings
1262  for (label i = 0; i < nVolumes; ++i)
1263  {
1264  inFile.getLine(line);
1265  IStringStream lineStr(line);
1266  lineStr >> entityID;
1267 
1268  // Skip 6 useless (to us) numbers
1269  for (label j = 0; j < 6; ++j)
1270  lineStr >> pt;
1271 
1272  // Number of physical groups associated to this volume
1273  lineStr >> nPhysicalTags;
1274  if (nPhysicalTags > 1)
1275  {
1276  FatalIOErrorInFunction(inFile)
1277  << "Cannot interpret multiple physical volumes associated"
1278  << " with one volume on line number " << inFile.lineNumber()
1279  << exit(FatalIOError);
1280  }
1281 
1282  lineStr >> physicalID;
1283  volEntityToPhysVolume.insert(entityID, physicalID);
1284  }
1285 
1286  // Try to read end of section tag:
1287  inFile.getLine(line);
1288  IStringStream tagStr(line);
1289  word tag(tagStr);
1290 
1291  if (tag != "$EndEntities")
1292  {
1293  FatalIOErrorInFunction(inFile)
1294  << "Did not find $EndEntities tag on line "
1295  << inFile.lineNumber() << exit(FatalIOError);
1296  }
1297 }
1298 
1299 
1300 int main(int argc, char *argv[])
1301 {
1303  (
1304  "Convert a gmsh .msh file to OpenFOAM"
1305  );
1306 
1308  argList::addArgument(".msh file");
1310  (
1311  "keepOrientation",
1312  "Retain raw orientation for prisms/hexs"
1313  );
1314 
1315  #include "addRegionOption.H"
1316 
1317  #include "setRootCase.H"
1318  #include "createTime.H"
1319 
1320  // Specified region or default region
1321  #include "getRegionOption.H"
1322 
1323  if (!polyMesh::regionName(regionName).empty())
1324  {
1325  Info<< "Creating polyMesh for region " << regionName << nl;
1326  }
1327 
1328  const bool keepOrientation = args.found("keepOrientation");
1329  IFstream inFile(args.get<fileName>(1));
1330 
1331  // Storage for points
1333  Map<label> mshToFoam;
1334 
1335  // Storage for all cells.
1337 
1338  // Map from patch to gmsh physical region
1339  labelList patchToPhys;
1340  // Storage for patch faces.
1341  List<DynamicList<face>> patchFaces(0);
1342 
1343  // Map from cellZone to gmsh physical region
1344  labelList zoneToPhys;
1345  // Storage for cell zones.
1346  List<DynamicList<label>> zoneCells(0);
1347 
1348  // Name per physical region
1349  Map<word> physicalNames;
1350 
1351  // Maps from 2 and 3 dimensional entity IDs to physical region ID
1352  Map<label> surfEntityToPhysSurface;
1353  Map<label> volEntityToPhysVolume;
1354 
1355  // Version 1 or 2 format
1356  scalar versionFormat = 1;
1357 
1358  do
1359  {
1360  string line;
1361  inFile.getLine(line);
1362  IStringStream lineStr(line);
1363 
1364  // This implies the end of while has been reached
1365  if (line == "")
1366  break;
1367 
1368  word tag(lineStr);
1369 
1370  if (tag == "$MeshFormat")
1371  {
1372  versionFormat = readMeshFormat(inFile);
1373  }
1374  else if (tag == "$PhysicalNames")
1375  {
1376  readPhysNames(inFile, physicalNames);
1377  }
1378  else if (tag == "$Entities")
1379  {
1380  // This will only happen to .msh files over version 4.
1381  readEntities(inFile,
1382  surfEntityToPhysSurface,
1383  volEntityToPhysVolume);
1384  }
1385  else if (tag == "$NOD" || tag == "$Nodes")
1386  {
1387  if (versionFormat < 4.0)
1388  readPointsLegacy(inFile, points, mshToFoam);
1389  else
1390  readPoints(inFile, points, mshToFoam);
1391  }
1392  else if (tag == "$ELM" || tag == "$Elements")
1393  {
1394  if (versionFormat < 4.0)
1395  readCellsLegacy
1396  (
1397  versionFormat,
1398  keepOrientation,
1399  points,
1400  mshToFoam,
1401  inFile,
1402  cells,
1403  patchToPhys,
1404  patchFaces,
1405  zoneToPhys,
1406  zoneCells
1407  );
1408  else
1409  readCells
1410  (
1411  versionFormat,
1412  keepOrientation,
1413  points,
1414  mshToFoam,
1415  inFile,
1416  cells,
1417  patchToPhys,
1418  patchFaces,
1419  zoneToPhys,
1420  zoneCells,
1421  surfEntityToPhysSurface,
1422  volEntityToPhysVolume
1423  );
1424  }
1425  else
1426  {
1427  Info<< "Skipping tag " << tag << " at line "
1428  << inFile.lineNumber()
1429  << endl;
1430 
1431  if (!skipSection(inFile))
1432  {
1433  break;
1434  }
1435  }
1436  } while (inFile.good());
1437 
1438 
1439  label nValidCellZones = 0;
1440 
1441  forAll(zoneCells, zonei)
1442  {
1443  if (zoneCells[zonei].size())
1444  {
1445  ++nValidCellZones;
1446  }
1447  }
1448 
1449 
1450  // Problem is that the orientation of the patchFaces does not have to
1451  // be consistent with the outwards orientation of the mesh faces. So
1452  // we have to construct the mesh in two stages:
1453  // 1. define mesh with all boundary faces in one patch
1454  // 2. use the read patchFaces to find the corresponding boundary face
1455  // and repatch it.
1456 
1457 
1458  // Create correct number of patches
1459  // (but without any faces in it)
1460  faceListList boundaryFaces(patchFaces.size());
1461 
1462  wordList boundaryPatchNames(boundaryFaces.size());
1463 
1464  forAll(boundaryPatchNames, patchi)
1465  {
1466  boundaryPatchNames[patchi] =
1467  physicalNames.lookup
1468  (
1469  patchToPhys[patchi],
1470  polyPatch::defaultName(patchi)
1471  );
1472 
1473  Info<< "Patch " << patchi << " gets name "
1474  << boundaryPatchNames[patchi] << endl;
1475  }
1476  Info<< endl;
1477 
1478  wordList boundaryPatchTypes(boundaryFaces.size(), polyPatch::typeName);
1479  word defaultFacesName = "defaultFaces";
1480  word defaultFacesType = polyPatch::typeName;
1481  wordList boundaryPatchPhysicalTypes
1482  (
1483  boundaryFaces.size(),
1484  polyPatch::typeName
1485  );
1486 
1487  polyMesh mesh
1488  (
1489  IOobject
1490  (
1491  regionName,
1492  runTime.constant(),
1493  runTime
1494  ),
1495  std::move(points),
1496  cells,
1497  boundaryFaces,
1498  boundaryPatchNames,
1499  boundaryPatchTypes,
1502  boundaryPatchPhysicalTypes
1503  );
1504 
1505  // Remove files now, to ensure all mesh files written are consistent.
1506  mesh.removeFiles();
1507 
1508  repatchPolyTopoChanger repatcher(mesh);
1509 
1510  // Now use the patchFaces to patch up the outside faces of the mesh.
1511 
1512  // Get the patch for all the outside faces (= default patch added as last)
1513  const polyPatch& pp = mesh.boundaryMesh().last();
1514 
1515  // Storage for faceZones.
1516  List<DynamicList<label>> zoneFaces(patchFaces.size());
1517 
1518 
1519  // Go through all the patchFaces and find corresponding face in pp.
1520  forAll(patchFaces, patchi)
1521  {
1522  const DynamicList<face>& pFaces = patchFaces[patchi];
1523 
1524  Info<< "Finding faces of patch " << patchi << endl;
1525 
1526  forAll(pFaces, i)
1527  {
1528  const face& f = pFaces[i];
1529 
1530  // Find face in pp using all vertices of f.
1531  label patchFacei = findFace(pp, f);
1532 
1533  if (patchFacei != -1)
1534  {
1535  label meshFacei = pp.start() + patchFacei;
1536 
1537  repatcher.changePatchID(meshFacei, patchi);
1538  }
1539  else
1540  {
1541  // Maybe internal face? If so add to faceZone with same index
1542  // - might be useful.
1543  label meshFacei = findInternalFace(mesh, f);
1544 
1545  if (meshFacei != -1)
1546  {
1547  zoneFaces[patchi].append(meshFacei);
1548  }
1549  else
1550  {
1552  << "Could not match gmsh face " << f
1553  << " to any of the interior or exterior faces"
1554  << " that share the same 0th point" << endl;
1555  }
1556  }
1557  }
1558  }
1559  Info<< nl;
1560 
1561  // Face zones
1562  label nValidFaceZones = 0;
1563 
1564  Info<< "FaceZones:" << nl
1565  << "Zone\tSize" << endl;
1566 
1567  forAll(zoneFaces, zonei)
1568  {
1569  zoneFaces[zonei].shrink();
1570 
1571  const labelList& zFaces = zoneFaces[zonei];
1572 
1573  if (zFaces.size())
1574  {
1575  ++nValidFaceZones;
1576 
1577  Info<< " " << zonei << '\t' << zFaces.size() << endl;
1578  }
1579  }
1580  Info<< endl;
1581 
1582 
1583  //Get polyMesh to write to constant
1584 
1586 
1587  repatcher.repatch();
1588 
1589  List<cellZone*> cz;
1590  List<faceZone*> fz;
1591 
1592  // Construct and add the zones. Note that cell ordering does not change
1593  // because of repatch() and neither does internal faces so we can
1594  // use the zoneCells/zoneFaces as is.
1595 
1596  if (nValidCellZones > 0)
1597  {
1598  cz.setSize(nValidCellZones);
1599 
1600  nValidCellZones = 0;
1601 
1602  forAll(zoneCells, zonei)
1603  {
1604  if (zoneCells[zonei].size())
1605  {
1606  const word zoneName
1607  (
1608  physicalNames.lookup
1609  (
1610  zoneToPhys[zonei],
1611  "cellZone_" + Foam::name(zonei) // default name
1612  )
1613  );
1614 
1615  Info<< "Writing zone " << zonei << " to cellZone "
1616  << zoneName << " and cellSet"
1617  << endl;
1618 
1619  cellSet cset(mesh, zoneName, zoneCells[zonei]);
1620  cset.write();
1621 
1622  cz[nValidCellZones] = new cellZone
1623  (
1624  zoneName,
1625  zoneCells[zonei],
1626  nValidCellZones,
1627  mesh.cellZones()
1628  );
1629  nValidCellZones++;
1630  }
1631  }
1632  }
1633 
1634  if (nValidFaceZones > 0)
1635  {
1636  fz.setSize(nValidFaceZones);
1637 
1638  nValidFaceZones = 0;
1639 
1640  forAll(zoneFaces, zonei)
1641  {
1642  if (zoneFaces[zonei].size())
1643  {
1644  const word zoneName
1645  (
1646  physicalNames.lookup
1647  (
1648  patchToPhys[zonei],
1649  "faceZone_" + Foam::name(zonei) // default name
1650  )
1651  );
1652 
1653  Info<< "Writing zone " << zonei << " to faceZone "
1654  << zoneName << " and faceSet"
1655  << endl;
1656 
1657  faceSet fset(mesh, zoneName, zoneFaces[zonei]);
1658  fset.write();
1659 
1660  fz[nValidFaceZones] = new faceZone
1661  (
1662  zoneName,
1663  zoneFaces[zonei],
1664  true, // all are flipped
1665  nValidFaceZones,
1666  mesh.faceZones()
1667  );
1668  nValidFaceZones++;
1669  }
1670  }
1671  }
1672 
1673  if (cz.size() || fz.size())
1674  {
1675  mesh.addZones(List<pointZone*>(0), fz, cz);
1676  }
1677 
1678  // Remove empty defaultFaces
1679  label defaultPatchID = mesh.boundaryMesh().findPatchID(defaultFacesName);
1680  if (mesh.boundaryMesh()[defaultPatchID].size() == 0)
1681  {
1682  polyPatchList newPatches((mesh.boundaryMesh().size() - 1));
1683  label newPatchi = 0;
1684  forAll(mesh.boundaryMesh(), patchi)
1685  {
1686  if (patchi != defaultPatchID)
1687  {
1688  const polyPatch& patch = mesh.boundaryMesh()[patchi];
1689 
1690  newPatches.set
1691  (
1692  newPatchi,
1693  patch.clone
1694  (
1695  mesh.boundaryMesh(),
1696  newPatchi,
1697  patch.size(),
1698  patch.start()
1699  )
1700  );
1701  ++newPatchi;
1702  }
1703  }
1704  repatcher.changePatches(newPatches);
1705  }
1706 
1707  // Set the precision of the points data to 10
1709 
1710  mesh.write();
1711 
1712  Info<< "End\n" << endl;
1713 
1714  return 0;
1715 }
1716 
1717 
1718 // ************************************************************************* //
label findPatchID(const word &patchName, const bool allowNotFound=true) const
Find patch index given a name, return -1 if not found.
static word validate(const std::string &s, const bool prefix=false)
Construct validated word (no invalid characters).
Definition: word.C:39
word defaultFacesType
Definition: readKivaGrid.H:456
static word defaultName(const label n=-1)
Default patch name: "patch" or "patchN".
static void addNote(const string &note)
Add extra notes for the usage information.
Definition: argList.C:462
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
A line primitive.
Definition: line.H:52
T & last()
Return reference to the last element of the list.
Definition: UPtrList.H:861
A class for handling file names.
Definition: fileName.H:72
A list of face labels.
Definition: faceSet.H:47
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:68
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:160
IOstream & hex(IOstream &io)
Definition: IOstream.H:545
void append(const T &val)
Append an element at the end of the list.
Definition: List.H:517
bool found(const Key &key) const
Same as contains()
Definition: HashTable.H:1354
const word & regionName() const
The mesh region name or word::null if polyMesh::defaultRegion.
Definition: polyMesh.C:847
Cell-face mesh analysis engine.
Definition: primitiveMesh.H:75
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
IntListType renumber(const labelUList &oldToNew, const IntListType &input)
Renumber the values (not the indices) of a list.
An analytical geometric cellShape.
Definition: cellShape.H:68
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
engineTime & runTime
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
bool found(const T &val, label pos=0) const
Same as contains()
Definition: UList.H:879
static unsigned int defaultPrecision() noexcept
Return the default precision.
Definition: IOstream.H:423
static void addBoolOption(const word &optName, const string &usage="", bool advanced=false)
Add a bool option to validOptions with usage information.
Definition: argList.C:374
static void noParallel()
Remove the parallel options.
Definition: argList.C:584
Required Classes.
#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
bool insert(const Key &key, const T &obj)
Copy insert a new entry, not overwriting existing entries.
Definition: HashTableI.H:152
label size() const noexcept
The number of elements in table.
Definition: HashTable.H:342
A list of faces which address into the list of points.
Required Classes.
virtual const fileName & name() const override
Read/write access to the name of the stream.
Definition: ISstream.H:141
const Map< label > & meshPointMap() const
Mesh point map.
faceList faces() const
Faces of this cell.
Definition: cellShapeI.H:254
void setSize(const label n)
Alias for resize()
Definition: List.H:316
dynamicFvMesh & mesh
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
const cellShapeList & cells
A mesh which allows changes in the patch distribution of the boundary faces. The change in patching i...
const pointField & points
void removeFiles(const fileName &instanceDir) const
Remove all files from mesh instance.
Definition: polyMesh.C:1329
const_iterator cfind(const Key &key) const
Find and return an const_iterator set at the hashed entry.
Definition: HashTableI.H:113
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundary mesh.
Definition: polyMesh.H:608
A class for handling words, derived from Foam::string.
Definition: word.H:63
label nPoints
Triangle point storage. Default constructable (triangle is not)
Definition: triangle.H:74
label size() const noexcept
The number of entries in the list.
Definition: UPtrListI.H:106
void addZones(PtrList< pointZone > &&pz, PtrList< faceZone > &&fz, PtrList< cellZone > &&cz)
Add mesh zones.
Definition: polyMesh.C:1009
virtual void setTime(const Time &t)
Reset the time and time-index to those of the given time.
Definition: Time.C:935
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1103
const T * set(const label i) const
Return const pointer to element (can be nullptr), or nullptr for out-of-range access (ie...
Definition: PtrList.H:159
virtual bool write(const bool writeOnProc=true) const
Write mesh using IO settings from time.
Definition: fvMesh.C:1102
const labelListList & pointFaces() const
Return point-face addressing.
ISstream & getLine(std::string &str, char delim='\n')
Raw, low-level getline (until delimiter) into a string.
Definition: ISstreamI.H:69
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
const word & constant() const noexcept
Return constant name.
Definition: TimePathsI.H:112
const faceZoneMesh & faceZones() const noexcept
Return face zone mesh.
Definition: polyMesh.H:670
Input from file stream, using an ISstream.
Definition: IFstream.H:49
labelList f(nPoints)
Info<< "Finished reading KIVA file"<< endl;cellShapeList cellShapes(nPoints);labelList cellZoning(nPoints, -1);const cellModel &hex=cellModel::ref(cellModel::HEX);labelList hexLabels(8);label activeCells=0;labelList pointMap(nPoints);forAll(pointMap, i){ pointMap[i]=i;}for(label i=0;i< nPoints;i++){ if(f[i] > 0.0) { hexLabels[0]=i;hexLabels[1]=i1tab[i];hexLabels[2]=i3tab[i1tab[i]];hexLabels[3]=i3tab[i];hexLabels[4]=i8tab[i];hexLabels[5]=i1tab[i8tab[i]];hexLabels[6]=i3tab[i1tab[i8tab[i]]];hexLabels[7]=i3tab[i8tab[i]];cellShapes[activeCells].reset(hex, hexLabels);edgeList edges=cellShapes[activeCells].edges();forAll(edges, ei) { if(edges[ei].mag(points)< SMALL) { label start=pointMap[edges[ei].start()];while(start !=pointMap[start]) { start=pointMap[start];} label end=pointMap[edges[ei].end()];while(end !=pointMap[end]) { end=pointMap[end];} label minLabel=min(start, end);pointMap[start]=pointMap[end]=minLabel;} } cellZoning[activeCells]=idreg[i];activeCells++;}}cellShapes.setSize(activeCells);cellZoning.setSize(activeCells);forAll(cellShapes, celli){ cellShape &cs=cellShapes[celli];forAll(cs, i) { cs[i]=pointMap[cs[i]];} cs.collapse();}label bcIDs[11]={-1, 0, 2, 4, -1, 5, -1, 6, 7, 8, 9};const label nBCs=12;const word *kivaPatchTypes[nBCs]={ &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &symmetryPolyPatch::typeName, &wedgePolyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &symmetryPolyPatch::typeName, &oldCyclicPolyPatch::typeName};enum patchTypeNames{ PISTON, VALVE, LINER, CYLINDERHEAD, AXIS, WEDGE, INFLOW, OUTFLOW, PRESIN, PRESOUT, SYMMETRYPLANE, CYCLIC};const char *kivaPatchNames[nBCs]={ "piston", "valve", "liner", "cylinderHead", "axis", "wedge", "inflow", "outflow", "presin", "presout", "symmetryPlane", "cyclic"};List< SLList< face > > pFaces[nBCs]
Definition: readKivaGrid.H:235
A subset of mesh cells.
Definition: cellZone.H:58
word defaultFacesName
Definition: readKivaGrid.H:455
messageStream Warning
Warning stream (stdout output on master, null elsewhere), with additional &#39;FOAM Warning&#39; header text...
label lineNumber() const noexcept
Const access to the current stream line number.
Definition: IOstream.H:390
An instant of time. Contains the time value and name. Uses Foam::Time when formatting the name...
Definition: instant.H:53
const std::string version
OpenFOAM version (name or stringified number) as a std::string.
const T & lookup(const label &key, const T &deflt) const
Return hashed entry if it exists, or return the given default.
Definition: HashTableI.H:222
T get(const label index) const
Get a value from the argument at index.
Definition: argListI.H:271
#define WarningInFunction
Report a warning using Foam::Warning.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:627
Foam::word regionName(args.getOrDefault< word >("region", Foam::polyMesh::defaultRegion))
Tet point storage. Default constructable (tetrahedron is not)
Definition: tetrahedron.H:82
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers...
Definition: List.H:55
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:53
Input from string buffer, using a ISstream. Always UNCOMPRESSED.
Definition: StringStream.H:120
A collection of cell labels.
Definition: cellSet.H:47
bool good() const noexcept
True if next operation might succeed.
Definition: IOstream.H:281
Maps a geometry to a set of cell primitives.
Definition: cellModel.H:72
const std::string patch
OpenFOAM patch number as a std::string.
static void addArgument(const string &argName, const string &usage="")
Append a (mandatory) argument to validArgs.
Definition: argList.C:351
const cellZoneMesh & cellZones() const noexcept
Return cell zone mesh.
Definition: polyMesh.H:678
messageStream Info
Information stream (stdout output on master, null elsewhere)
const labelListList & pointFaces() const
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:60
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:69
Foam::argList args(argc, argv)
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:172
bool found(const word &optName) const
Return true if the named option is found.
Definition: argListI.H:171
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
Namespace for OpenFOAM.
point centre(const UList< point > &points) const
Centroid of the cell.
Definition: cellShapeI.H:314
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...