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-2021 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.found())
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.found())
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.found())
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.found())
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.found())
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 
1321 
1322  if (args.readIfPresent("region", regionName))
1323  {
1324  Info<< "Creating polyMesh for region " << regionName << endl;
1325  }
1326 
1327  const bool keepOrientation = args.found("keepOrientation");
1328  IFstream inFile(args.get<fileName>(1));
1329 
1330  // Storage for points
1332  Map<label> mshToFoam;
1333 
1334  // Storage for all cells.
1336 
1337  // Map from patch to gmsh physical region
1338  labelList patchToPhys;
1339  // Storage for patch faces.
1340  List<DynamicList<face>> patchFaces(0);
1341 
1342  // Map from cellZone to gmsh physical region
1343  labelList zoneToPhys;
1344  // Storage for cell zones.
1345  List<DynamicList<label>> zoneCells(0);
1346 
1347  // Name per physical region
1348  Map<word> physicalNames;
1349 
1350  // Maps from 2 and 3 dimensional entity IDs to physical region ID
1351  Map<label> surfEntityToPhysSurface;
1352  Map<label> volEntityToPhysVolume;
1353 
1354  // Version 1 or 2 format
1355  scalar versionFormat = 1;
1356 
1357  do
1358  {
1359  string line;
1360  inFile.getLine(line);
1361  IStringStream lineStr(line);
1362 
1363  // This implies the end of while has been reached
1364  if (line == "")
1365  break;
1366 
1367  word tag(lineStr);
1368 
1369  if (tag == "$MeshFormat")
1370  {
1371  versionFormat = readMeshFormat(inFile);
1372  }
1373  else if (tag == "$PhysicalNames")
1374  {
1375  readPhysNames(inFile, physicalNames);
1376  }
1377  else if (tag == "$Entities")
1378  {
1379  // This will only happen to .msh files over version 4.
1380  readEntities(inFile,
1381  surfEntityToPhysSurface,
1382  volEntityToPhysVolume);
1383  }
1384  else if (tag == "$NOD" || tag == "$Nodes")
1385  {
1386  if (versionFormat < 4.0)
1387  readPointsLegacy(inFile, points, mshToFoam);
1388  else
1389  readPoints(inFile, points, mshToFoam);
1390  }
1391  else if (tag == "$ELM" || tag == "$Elements")
1392  {
1393  if (versionFormat < 4.0)
1394  readCellsLegacy
1395  (
1396  versionFormat,
1397  keepOrientation,
1398  points,
1399  mshToFoam,
1400  inFile,
1401  cells,
1402  patchToPhys,
1403  patchFaces,
1404  zoneToPhys,
1405  zoneCells
1406  );
1407  else
1408  readCells
1409  (
1410  versionFormat,
1411  keepOrientation,
1412  points,
1413  mshToFoam,
1414  inFile,
1415  cells,
1416  patchToPhys,
1417  patchFaces,
1418  zoneToPhys,
1419  zoneCells,
1420  surfEntityToPhysSurface,
1421  volEntityToPhysVolume
1422  );
1423  }
1424  else
1425  {
1426  Info<< "Skipping tag " << tag << " at line "
1427  << inFile.lineNumber()
1428  << endl;
1429 
1430  if (!skipSection(inFile))
1431  {
1432  break;
1433  }
1434  }
1435  } while (inFile.good());
1436 
1437 
1438  label nValidCellZones = 0;
1439 
1440  forAll(zoneCells, zonei)
1441  {
1442  if (zoneCells[zonei].size())
1443  {
1444  ++nValidCellZones;
1445  }
1446  }
1447 
1448 
1449  // Problem is that the orientation of the patchFaces does not have to
1450  // be consistent with the outwards orientation of the mesh faces. So
1451  // we have to construct the mesh in two stages:
1452  // 1. define mesh with all boundary faces in one patch
1453  // 2. use the read patchFaces to find the corresponding boundary face
1454  // and repatch it.
1455 
1456 
1457  // Create correct number of patches
1458  // (but without any faces in it)
1459  faceListList boundaryFaces(patchFaces.size());
1460 
1461  wordList boundaryPatchNames(boundaryFaces.size());
1462 
1463  forAll(boundaryPatchNames, patchi)
1464  {
1465  boundaryPatchNames[patchi] =
1466  physicalNames.lookup
1467  (
1468  patchToPhys[patchi],
1469  polyPatch::defaultName(patchi)
1470  );
1471 
1472  Info<< "Patch " << patchi << " gets name "
1473  << boundaryPatchNames[patchi] << endl;
1474  }
1475  Info<< endl;
1476 
1477  wordList boundaryPatchTypes(boundaryFaces.size(), polyPatch::typeName);
1478  word defaultFacesName = "defaultFaces";
1479  word defaultFacesType = polyPatch::typeName;
1480  wordList boundaryPatchPhysicalTypes
1481  (
1482  boundaryFaces.size(),
1483  polyPatch::typeName
1484  );
1485 
1486  polyMesh mesh
1487  (
1488  IOobject
1489  (
1490  regionName,
1491  runTime.constant(),
1492  runTime
1493  ),
1494  std::move(points),
1495  cells,
1496  boundaryFaces,
1497  boundaryPatchNames,
1498  boundaryPatchTypes,
1501  boundaryPatchPhysicalTypes
1502  );
1503 
1504  // Remove files now, to ensure all mesh files written are consistent.
1505  mesh.removeFiles();
1506 
1507  repatchPolyTopoChanger repatcher(mesh);
1508 
1509  // Now use the patchFaces to patch up the outside faces of the mesh.
1510 
1511  // Get the patch for all the outside faces (= default patch added as last)
1512  const polyPatch& pp = mesh.boundaryMesh().last();
1513 
1514  // Storage for faceZones.
1515  List<DynamicList<label>> zoneFaces(patchFaces.size());
1516 
1517 
1518  // Go through all the patchFaces and find corresponding face in pp.
1519  forAll(patchFaces, patchi)
1520  {
1521  const DynamicList<face>& pFaces = patchFaces[patchi];
1522 
1523  Info<< "Finding faces of patch " << patchi << endl;
1524 
1525  forAll(pFaces, i)
1526  {
1527  const face& f = pFaces[i];
1528 
1529  // Find face in pp using all vertices of f.
1530  label patchFacei = findFace(pp, f);
1531 
1532  if (patchFacei != -1)
1533  {
1534  label meshFacei = pp.start() + patchFacei;
1535 
1536  repatcher.changePatchID(meshFacei, patchi);
1537  }
1538  else
1539  {
1540  // Maybe internal face? If so add to faceZone with same index
1541  // - might be useful.
1542  label meshFacei = findInternalFace(mesh, f);
1543 
1544  if (meshFacei != -1)
1545  {
1546  zoneFaces[patchi].append(meshFacei);
1547  }
1548  else
1549  {
1551  << "Could not match gmsh face " << f
1552  << " to any of the interior or exterior faces"
1553  << " that share the same 0th point" << endl;
1554  }
1555  }
1556  }
1557  }
1558  Info<< nl;
1559 
1560  // Face zones
1561  label nValidFaceZones = 0;
1562 
1563  Info<< "FaceZones:" << nl
1564  << "Zone\tSize" << endl;
1565 
1566  forAll(zoneFaces, zonei)
1567  {
1568  zoneFaces[zonei].shrink();
1569 
1570  const labelList& zFaces = zoneFaces[zonei];
1571 
1572  if (zFaces.size())
1573  {
1574  ++nValidFaceZones;
1575 
1576  Info<< " " << zonei << '\t' << zFaces.size() << endl;
1577  }
1578  }
1579  Info<< endl;
1580 
1581 
1582  //Get polyMesh to write to constant
1583 
1585 
1586  repatcher.repatch();
1587 
1588  List<cellZone*> cz;
1589  List<faceZone*> fz;
1590 
1591  // Construct and add the zones. Note that cell ordering does not change
1592  // because of repatch() and neither does internal faces so we can
1593  // use the zoneCells/zoneFaces as is.
1594 
1595  if (nValidCellZones > 0)
1596  {
1597  cz.setSize(nValidCellZones);
1598 
1599  nValidCellZones = 0;
1600 
1601  forAll(zoneCells, zonei)
1602  {
1603  if (zoneCells[zonei].size())
1604  {
1605  const word zoneName
1606  (
1607  physicalNames.lookup
1608  (
1609  zoneToPhys[zonei],
1610  "cellZone_" + Foam::name(zonei) // default name
1611  )
1612  );
1613 
1614  Info<< "Writing zone " << zonei << " to cellZone "
1615  << zoneName << " and cellSet"
1616  << endl;
1617 
1618  cellSet cset(mesh, zoneName, zoneCells[zonei]);
1619  cset.write();
1620 
1621  cz[nValidCellZones] = new cellZone
1622  (
1623  zoneName,
1624  zoneCells[zonei],
1625  nValidCellZones,
1626  mesh.cellZones()
1627  );
1628  nValidCellZones++;
1629  }
1630  }
1631  }
1632 
1633  if (nValidFaceZones > 0)
1634  {
1635  fz.setSize(nValidFaceZones);
1636 
1637  nValidFaceZones = 0;
1638 
1639  forAll(zoneFaces, zonei)
1640  {
1641  if (zoneFaces[zonei].size())
1642  {
1643  const word zoneName
1644  (
1645  physicalNames.lookup
1646  (
1647  patchToPhys[zonei],
1648  "faceZone_" + Foam::name(zonei) // default name
1649  )
1650  );
1651 
1652  Info<< "Writing zone " << zonei << " to faceZone "
1653  << zoneName << " and faceSet"
1654  << endl;
1655 
1656  faceSet fset(mesh, zoneName, zoneFaces[zonei]);
1657  fset.write();
1658 
1659  fz[nValidFaceZones] = new faceZone
1660  (
1661  zoneName,
1662  zoneFaces[zonei],
1663  true, // all are flipped
1664  nValidFaceZones,
1665  mesh.faceZones()
1666  );
1667  nValidFaceZones++;
1668  }
1669  }
1670  }
1671 
1672  if (cz.size() || fz.size())
1673  {
1674  mesh.addZones(List<pointZone*>(0), fz, cz);
1675  }
1676 
1677  // Remove empty defaultFaces
1678  label defaultPatchID = mesh.boundaryMesh().findPatchID(defaultFacesName);
1679  if (mesh.boundaryMesh()[defaultPatchID].size() == 0)
1680  {
1681  List<polyPatch*> newPatchPtrList((mesh.boundaryMesh().size() - 1));
1682  label newPatchi = 0;
1683  forAll(mesh.boundaryMesh(), patchi)
1684  {
1685  if (patchi != defaultPatchID)
1686  {
1687  const polyPatch& patch = mesh.boundaryMesh()[patchi];
1688 
1689  newPatchPtrList[newPatchi] = patch.clone
1690  (
1691  mesh.boundaryMesh(),
1692  newPatchi,
1693  patch.size(),
1694  patch.start()
1695  ).ptr();
1696 
1697  newPatchi++;
1698  }
1699  }
1700  repatcher.changePatches(newPatchPtrList);
1701  }
1702 
1703  // Set the precision of the points data to 10
1705 
1706  mesh.write();
1707 
1708  Info<< "End\n" << endl;
1709 
1710  return 0;
1711 }
1712 
1713 
1714 // ************************************************************************* //
runTime
engineTime & runTime
Definition: createEngineTime.H:13
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:169
Foam::Vector::x
const Cmpt & x() const
Access to the vector x component.
Definition: VectorI.H:73
Foam::PrimitivePatch::pointFaces
const labelListList & pointFaces() const
Return point-face addressing.
Definition: PrimitivePatch.C:301
List.H
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::ISstream::getLine
ISstream & getLine(std::string &str, char delim='\n')
Raw, low-level getline (until delimiter) into a string.
Definition: ISstreamI.H:76
Foam::fileName
A class for handling file names.
Definition: fileName.H:73
Foam::fvMesh::write
virtual bool write(const bool valid=true) const
Write mesh using IO settings from time.
Definition: fvMesh.C:1041
Foam::polyMesh::defaultRegion
static word defaultRegion
Return the default region name.
Definition: polyMesh.H:318
Foam::cellShape::centre
point centre(const UList< point > &points) const
Centroid of the cell.
Definition: cellShapeI.H:287
Foam::IFstream
Input from file stream, using an ISstream.
Definition: IFstream.H:53
Foam::DynamicList< label >
Foam::IFstream::name
virtual const fileName & name() const
Read/write access to the name of the stream.
Definition: ISstream.H:113
Foam::cellModel::HEX
hex
Definition: cellModel.H:81
Foam::Warning
messageStream Warning
Foam::primitiveMesh::pointFaces
const labelListList & pointFaces() const
Definition: primitiveMeshPointFaces.C:34
Foam::argList::addNote
static void addNote(const string &note)
Add extra notes for the usage information.
Definition: argList.C:412
Foam::Map< label >
Foam::word::validate
static word validate(const std::string &s, const bool prefix=false)
Construct validated word (no invalid characters).
Definition: word.C:45
Foam::faceSet
A list of face labels.
Definition: faceSet.H:51
Foam::IOstream::lineNumber
label lineNumber() const noexcept
Const access to the current stream line number.
Definition: IOstream.H:318
Foam::List::append
void append(const T &val)
Append an element at the end of the list.
Definition: ListI.H:175
Foam::FatalIOError
IOerror FatalIOError
Foam::polyMesh::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:444
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::cellShape::faces
faceList faces() const
Faces of this cell.
Definition: cellShapeI.H:227
polyMesh.H
defaultFacesType
word defaultFacesType
Definition: readKivaGrid.H:456
Foam::argList::get
T get(const label index) const
Get a value from the argument at index.
Definition: argListI.H:278
Foam::argList::readIfPresent
bool readIfPresent(const word &optName, T &val) const
Read a value from the named option if present.
Definition: argListI.H:323
Foam::Vector::z
const Cmpt & z() const
Access to the vector z component.
Definition: VectorI.H:85
Foam::cellModel::TET
tet
Definition: cellModel.H:85
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:77
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::IOstream::good
bool good() const noexcept
True if next operation might succeed.
Definition: IOstream.H:233
Foam::cellZone
A subset of mesh cells.
Definition: cellZone.H:62
nPoints
label nPoints
Definition: gmvOutputHeader.H:2
Foam::argList::addArgument
static void addArgument(const string &argName, const string &usage="")
Append a (mandatory) argument to validArgs.
Definition: argList.C:301
regionName
Foam::word regionName
Definition: createNamedDynamicFvMesh.H:1
Foam::triPoints
Triangle storage. Null constructable (unfortunately triangle<point, point> is not)
Definition: triPoints.H:52
Foam::repatchPolyTopoChanger
A mesh which allows changes in the patch distribution of the boundary faces. The change in patching i...
Definition: repatchPolyTopoChanger.H:54
Foam::Field< vector >
cellModel.H
Foam::faceZone
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:64
Foam::Info
messageStream Info
Information stream (stdout output on master, null elsewhere)
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:68
Foam::polyMesh::cellZones
const cellZoneMesh & cellZones() const noexcept
Return cell zone mesh.
Definition: polyMesh.H:492
Foam::List::setSize
void setSize(const label n)
Alias for resize()
Definition: List.H:222
Foam::polyMesh::removeFiles
void removeFiles(const fileName &instanceDir) const
Remove all files from mesh instance.
Definition: polyMesh.C:1325
argList.H
faceSet.H
addRegionOption.H
Foam::cellModel::PRISM
prism
Definition: cellModel.H:83
Foam::polyMesh::faceZones
const faceZoneMesh & faceZones() const noexcept
Return face zone mesh.
Definition: polyMesh.H:486
Foam::cellModel::ref
static const cellModel & ref(const modelType model)
Look up reference to cellModel by enumeration. Fatal on failure.
Definition: cellModels.C:157
Foam::polyBoundaryMesh::findPatchID
label findPatchID(const word &patchName, const bool allowNotFound=true) const
Find patch index given a name, return -1 if not found.
Definition: polyBoundaryMesh.C:765
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
IFstream.H
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
Foam::cellShape
An analytical geometric cellShape.
Definition: cellShape.H:69
Foam::IStringStream
Input from string buffer, using a ISstream. Always UNCOMPRESSED.
Definition: StringStream.H:108
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::cellSet
A collection of cell labels.
Definition: cellSet.H:51
Foam::polyPatch::start
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:361
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::foamVersion::version
const std::string version
OpenFOAM version (name or stringified number) as a std::string.
Foam::hex
IOstream & hex(IOstream &io)
Definition: IOstream.H:446
Foam::tetPoints
Tet storage. Null constructable (unfortunately tetrahedron<point, point> is not)
Definition: tetPoints.H:53
Foam::argList::addBoolOption
static void addBoolOption(const word &optName, const string &usage="", bool advanced=false)
Add a bool option to validOptions with usage information.
Definition: argList.C:324
Foam::IOstream::defaultPrecision
static unsigned int defaultPrecision() noexcept
Return the default precision.
Definition: IOstream.H:342
Time.H
setRootCase.H
Foam::Vector::y
const Cmpt & y() const
Access to the vector y component.
Definition: VectorI.H:79
Foam::renumber
IntListType renumber(const labelUList &oldToNew, const IntListType &input)
Renumber the values (not the indices) of a list.
Definition: ListOpsTemplates.C:37
Foam::polyMesh::faces
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1094
Foam::cellModel::PYR
pyr
Definition: cellModel.H:84
Foam::nl
constexpr char nl
Definition: Ostream.H:404
defaultFacesName
word defaultFacesName
Definition: readKivaGrid.H:455
f
labelList f(nPoints)
Foam::foamVersion::patch
const std::string patch
OpenFOAM patch number as a std::string.
Foam::Vector< scalar >
Foam::List< label >
Foam::Time::setTime
virtual void setTime(const Time &t)
Reset the time and time-index to those of the given time.
Definition: Time.C:1003
points
const pointField & points
Definition: gmvOutputHeader.H:1
createTime.H
Foam::line
A line primitive.
Definition: line.H:53
Foam::name
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:72
FatalIOErrorInFunction
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:473
cells
const cellShapeList & cells
Definition: gmvOutputHeader.H:3
Foam::instant
An instant of time. Contains the time value and name.
Definition: instant.H:52
Foam::cellModel
Maps a geometry to a set of cell primitives.
Definition: cellModel.H:72
cellSet.H
Foam::PrimitivePatch::meshPointMap
const Map< label > & meshPointMap() const
Mesh point map.
Definition: PrimitivePatch.C:343
Foam::argList::noParallel
static void noParallel()
Remove the parallel options.
Definition: argList.C:510
Foam::patchIdentifier::defaultName
static word defaultName(const label n=-1)
Default patch name: "patch" or "patchN".
Definition: patchIdentifier.H:76
Foam::TimePaths::constant
const word & constant() const
Return constant name.
Definition: TimePathsI.H:96
args
Foam::argList args(argc, argv)
repatchPolyTopoChanger.H
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:328
Foam::cell
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:54
Foam::polyMesh::addZones
void addZones(const List< pointZone * > &pz, const List< faceZone * > &fz, const List< cellZone * > &cz)
Add mesh zones.
Definition: polyMesh.C:999
pFaces
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
Foam::argList::found
bool found(const word &optName) const
Return true if the named option is found.
Definition: argListI.H:178
Foam::PrimitivePatch
A list of faces which address into the list of points.
Definition: PrimitivePatch.H:79
Foam::labelI
static const labelSphericalTensor labelI(1)
Identity labelTensor.
Foam::primitiveMesh
Cell-face mesh analysis engine.
Definition: primitiveMesh.H:78